0%

오늘 한 것

공부한 javaScript 코딩 문제

1.수박수박수박수박수박수?

문제 설명
길이가 n이고, 수박수박수박수….와 같은 패턴을 유지하는 문자열을 리턴하는 함수, solution을 완성하세요. 예를들어 n이 4이면 수박수박을 리턴하고 3이라면 수박수를 리턴하면 됩니다.

제한 조건
n은 길이 10,000이하인 자연수입니다.

입출력 예
n return
3 수박수
4 수박수박

나의 답

1
2
3
4
5
6
7
8
9
function solution(n) {
var arr = "";
var answer = "";
for (var i = 0; i < n; i++) {
i % 2 == 0 ? (arr += "수") : (arr += "박");
}
answer = arr;
return answer;
}

타인의 답안

  1. 이 답안을 보고 엄청 웃었다.

    1
    2
    3
    4
    5
    6
    7
    function waterMelon(n) {
    var result =
    "수박수박수박수박수박수박수박수박수박수박수박수박수박수박수박수박수박수박수박수박수박수박수박수박수박수박수박수박수박수박수박수박";
    //함수를 완성하세요

    return result.substring(0, n);
    }
  2. 고차함수를 이용하는 것이 확실히 깔끔하다.

    1
    2
    3
    const waterMelon = (n) => {
    return "수박".repeat(n / 2) + (n % 2 === 1 ? "수" : "");
    };

2. 평균 구하기

문제 설명
정수를 담고 있는 배열 arr의 평균값을 return하는 함수, solution을 완성해보세요.

제한사항
arr은 길이 1 이상, 100 이하인 배열입니다.
arr의 원소는 -10,000 이상 10,000 이하인 정수입니다.

입출력 예
arr return
[1,2,3,4] 2.5
[5,5] 5

나의 답

1
2
3
4
5
6
7
8
9
10
11
function solution(arr) {
var result = 0;
var answer = 0.0;

for (var i = 0; i < arr.length; i++) {
result += arr[i];
}

answer = result / arr.length;
return answer;
}

감탄한 타인의 답안

1
2
3
function average(array) {
return array.reduce((a, b) => a + b) / array.length;
}
  • 이렇게 짧게되는 걸.. 함수에 대한 이해가 더 필요하다.

출처: programmers

Nyong’s GitHub

제어문 연습

1. 변수 x가 10보다 크고 20보다 작을 때 변수 x를 출력하는 조건식을 완성하라

1
2
3
4
5
6
var x = 15;

// 변수 x가 10보다 크고 20보다 작을 때 변수 x를 출력하는 조건식을 완성하라.
if (10 < x < 20) {
console.log(x);
}

결과

1
15

2. for문을 사용하여 0부터 10미만의 정수 중에서 짝수만을 작은 수부터 출력하시오.

1
2
3
for (var i = 0; i < 10; i += 2) {
console.log(i);
}

결과

1
2
3
4
5
0
2
4
6
8

3. for문을 사용하여 0부터 10미만의 정수 중에서 짝수만을 작은 수부터 문자열로 출력하시오.

1
2
3
4
5
var result = "";
for (var i = 0; i < 10; i += 2) {
result += i;
}
console.log(result);

결과

1
02468

4. for문을 사용하여 0부터 10미만의 정수 중에서 홀수만을 큰수부터 출력하시오.

1
2
3
for (var i = 9; i > 0; i -= 2) {
console.log(i);
}

결과

1
2
3
4
5
9
7
5
3
1

5. while문을 사용하여 0 부터 10 미만의 정수 중에서 짝수만을 작은 수부터 출력하시오.

1
2
3
4
5
6
var i = 0;

while (i < 10) {
console.log(i);
i += 2;
}

결과

1
2
3
4
5
0
2
4
6
8

6. while문을 사용하여 0 부터 10 미만의 정수 중에서 홀수만을 큰수부터 출력하시오.

1
2
3
4
5
6
var i = 9;

while (i > 0) {
console.log(i);
i -= 2;
}

결과

1
2
3
4
5
9
7
5
3
1

7. for 문을 사용하여 0부터 10미만의 정수의 합을 출력하시오.

1
2
3
4
5
var result = 0;
for (var i = 0; i < 10; i++) {
result += i;
}
console.log(result);

결과

1
45

8. 1부터 20 미만의 정수 중에서 2 또는 3의 배수가 아닌 수의 총합을 구하시오.

1
2
3
4
5
6
7
var result = 0;
for (var i = 0; i < 20; i++) {
if (i % 2 && i % 3) {
result += i;
}
}
console.log(result);

결과

1
73

9. 1부터 20 미만의 정수 중에서 2 또는 3의 배수인 수의 총합을 구하시오.

1
2
3
4
5
6
7
var result = 0;
for (var i = 0; i < 20; i++) {
if (i % 2 === 0 || i % 3 === 0) {
result += i;
}
}
console.log(result);

결과

1
117

10. 두 개의 주사위를 던졌을 때, 눈의 합이 6이 되는 모든 경우의 수를 출력하시오.

1
2
3
4
5
6
7
8
var dice1 = [1, 2, 3, 4, 5, 6];
var dice2 = [1, 2, 3, 4, 5, 6];

for (var i = 0; i < dice1.length; i++) {
for (var j = 0; j < dice2.length; j++) {
if (dice1[i] + dice2[j] === 6) console.log(`[${dice1[i]},${dice2[j]}]`);
}
}

결과

1
2
3
4
5
[1,5]
[2,4]
[3,3]
[4,2]
[5,1]

11. 삼각형 출력하기 - pattern 1

다음을 참고하여 *(별)로 높이가 5인(var line = 5) 삼각형을 문자열로 완성하라.
개행문자(‘\n’)를 사용하여 개행한다. 완성된 문자열의 마지막은 개행문자(‘\n’)로 끝나도 관계없다.

1
2
3
4
5
6
7
8
9
10
11
12
13
var result = "";
var line = 5; // line 변수 값으로 높이 조절
var i;
var j;

for (i = 0; i < line; i++) {
for (j = 0; j <= i; j++) {
result = result.concat("*");
}
result = result.concat("\n");
}

console.log(result);

결과

1
2
3
4
5
*
**
***
****
*****

12. 삼각형 출력하기 - pattern 2

다음을 참고하여 *(별)로 트리를 문자열로 완성하라. 개행문자(‘\n’)를 사용하여 개행한다.
완성된 문자열의 마지막은 개행문자(‘\n’)로 끝나도 관계없다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var star = "";
var line = 5;
var i = 0;
var j = 0;
var k;

for (i = 0; i < line; i++) {
for (j = 0; j <= i; j++) {
star = star.concat(" ");
}

for (k = line - i; k > 0; k--) {
star = star.concat("*");
}

star = star.concat("\n");
}

console.log(star);

결과

1
2
3
4
5
*****
****
***
**
*

13. 삼각형 출력하기 - pattern 3

다음을 참고하여 *(별)로 트리를 문자열로 완성하라. 개행문자(‘\n’)를 사용하여 개행한다. 완성된 문자열의 마지막은 개행문자(‘\n’)로 끝나도 관계없다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var star = "";
var line = 5;
var i = 0;
var j;
var k = 0;

for (i; i < line; i++) {
for (j = line - i; j > 0; j--) {
star = star.concat("*");
}
for (k; k <= i; k++) {
star = star.concat(" ");
}
star = star.concat("\n");
}

console.log(star);

결과

1
2
3
4
5
*****
****
***
**
*

14. 삼각형 출력하기 - pattern 4

다음을 참고하여 *(별)로 트리를 문자열로 완성하라. 개행문자(‘\n’)를 사용하여 개행한다. 완성된 문자열의 마지막은 개행문자(‘\n’)로 끝나도 관계없다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var star = "";
var line = 5;
var i = 1;
var j;
var k = 0;

for (i; i <= line; i++) {
for (j = line - i; j > 0; j--) {
star = star.concat(" ");
}

k = 0;
for (k; k < i; k++) {
star = star.concat("*");
}

star = star.concat("\n");
}

console.log(star);

결과

1
2
3
4
5
    *
**
***
****
*****

15. 정삼각형 출력하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var star = "";
var line = 5;
var i = 1;
var j;
var k = 0;

for (i; i <= line; i++) {
for (j = line - i; j > 0; j--) {
star = star.concat(" ");
}

for (k; k < i; k++) {
star = star.concat("*");
}
k = 0;

for (var l = 0; l < i - 1; l++) star = star.concat("*");

star = star.concat("\n");
}

console.log(star);

결과

1
2
3
4
5
    *
***
*****
*******
*********

16. 역정삼각형 출력하기

1
2
3
4
5
*********
*******
*****
***
*
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var star = "";
var line = 5;
var i = 0;
var j = 0;
var k = 0;
var l = 0;

for (i; i < line; i++) {
for (j = 0; j <= i; j++) {
star = star.concat(" ");
}

for (k = line; k > i; k--) {
star = star.concat("*");
}

for (l = line; l > i + 1; l--) {
star = star.concat("*");
}

star = star.concat("\n");
}

console.log(star);

결과

1
2
3
4
5
*********
*******
*****
***
*

오늘 느낀 것

  • 4년만에 별찍기를 해본다. 생각보다 쉽지는 않았다.
  • 아직 초반이라 그런지 참 재밌다. 더 열심히 공부해야지!
  • 초심을 잃지말자!

Nyong’s GitHub

오늘 한 것

데이터 타입

1
2
3
4
5
//이스케이프시퀀스도 좋지만 가독성이 안 좋다.
var string = "안녕'하세요' ";

//`(백틱)을 사용하는게 낫다.
var string = `안녕'하세요'`;

변수가 아닌 값이 데이터 타입을 갖는다.

변수는 남발하면 안 되고 신중하게 써야함. 많이 쓸 수록 에러 발생률도 비례해서 높아짐.

연산자

1
2
3
4
// 지수 연산자
2 ** 2; // -> 4
// 제곱하는 메서드
Math.pow(2, 2); // -> 4

부수 효과가 있는 연산자는 할당(= , += …) 연산자, 증가/감소(++/ -- ) 연산자, delete 연산자이다.

제어문

제어문은 논리적 흐름에서 벗어날 때가 많음 (가독성이 떨어짐)

→ 가독성을 위해 제어문은 효율적이지만 대체 가능하다면 대체하는게 좋을 수 있음. (forEach, map, filter() …)

블록문

1
2
3
{
// 블록문
}
  • 관련 문들을 하나로 묶기 위함으로 사용한다.
  • 다른 언어는 블록문이 하나의 스코프이다.
  • Javascript는 블록문이 독립된 스코프가 아니다.
  • Javascript는 블록문을 함수가 아니면 하나의 스코프로 취급하지 않는다. (var 일 경우 블록문 외부에서도 사용 가능)
  • let 은 블록문 내에서 선언하면 해당 블록 안에서만 유효하다.
1
2
3
4
5
6
7
8
9
10
11
for (var i = 0; i < 5; i++) {
var result = "";
result += "*";
}
console.log(result); // *

for (var k = 0; k < 5; k++) {
let star = "";
star += "*";
}
console.log(star); // ReferenceError: star is not defined

공부한 javaScript 코딩 문제

1.직사각형 별찍기

문제 설명
이 문제에는 표준 입력으로 두 개의 정수 n과 m이 주어집니다.
별(*) 문자를 이용해 가로의 길이가 n, 세로의 길이가 m인 직사각형 형태를 출력해보세요.

제한 조건
n과 m은 각각 1000 이하인 자연수입니다.

나의 답

1
2
3
4
5
6
7
8
9
10
11
12
13
14
process.stdin.setEncoding("utf8");
process.stdin.on("data", (data) => {
const n = data.split(" ");
const a = Number(n[0]),
b = Number(n[1]);

for (var i = 0; i < b; i++) {
for (var j = 0; j < a; j++) {
var result = "";
result = result + "*";
}
console.log(result);
}
});

감탄한 타인의 답안

1
2
3
4
5
6
7
8
9
10
process.stdin.setEncoding("utf8");
process.stdin.on("data", (data) => {
const n = data.split(" ");
const a = Number(n[0]),
b = Number(n[1]);
const row = "*".repeat(a);
for (let i = 0; i < b; i++) {
console.log(row);
}
});

오늘 느낀 것

  • javascript에서 왜 계속 반복문 내부 변수가 밖에서도 사용 가능한가 이상했는데 역시 javascript 블록문은 독립된 스코프가 아니었다.
  • javascript는 예상도 못한 점에서 달라서 생각보다 시행착오가 많이 생긴다.

Nyong’s GitHub

오늘 한 것

타입 변환

타입 변환은 크게 두가지 상황이 있다.

  1. 의도와는 상관없이 표현식을 평가하는 도중에 자바스크립트 엔진에 의해 타입이 자동 변환되는 암묵적 타입 변환(implicit coercion) 또는 타입 강제 변환(type coercion)

    1
    2
    3
    4
    5
    6
    7
    8
    var x = 10;

    // 문자열 연결 연산자는 숫자 타입 x의 값을 바탕으로 새로운 문자열을 생성한다.
    var str = x + "";
    console.log(typeof str, str); // string 10

    // x 변수의 값이 변경된 것은 아니다.
    console.log(typeof x, x); // number 10
  2. 의도적으로 값의 타입을 변환하는 명시적 타입 변환(explicit coercion) 또는 타입 캐스팅(type casting)

    1
    2
    3
    4
    5
    6
    7
    8
    var x = 10;

    // 숫자를 문자열로 타입 캐스팅한다.
    var str = x.toString();
    console.log(typeof str, str); // string 10

    // x 변수의 값이 변경된 것은 아니다.
    console.log(typeof x, x); // number 10
  • 타입 변환이란 기존 원시값을 사용해 다른 타입의 새로운 원시값을 생성하는 것이다.
  • 때로는 명시적 타입 변환보다 암묵적 타입 변환이 가독성 측면에서 더 좋을 수도 있다. (10).toString()보다 10 + ‘’이 더욱 간결하고 이해하기 쉽다.

암묵적 타입 변환

문자열 타입 변환

1
1 + "2"; // -> "12"
  • 숫자 타입과 문자열 타입이 +연산되면 문자열로 자동 형 변환이 일어난다.
  • + 연산은 문자열끼리 합칠 때도 사용하기 때문이다.
1
`1 + 1 = ${1 + 1}` // -> "1 + 1 = 2"
  • 위와 같은 템플릿 리터럴을 사용하면 결과 값을 계산한 후 형 변환이 일어난다.

그 외에 다양한 문자열로의 자동 형 변환이 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 숫자 타입
0 + '' // -> "0"
-0 + '' // -> "0"
1 + '' // -> "1"
-1 + '' // -> "-1"
NaN + '' // -> "NaN"
Infinity + '' // -> "Infinity"
-Infinity + '' // -> "-Infinity"

// 불리언 타입
true + '' // -> "true"
false + '' // -> "false"

// null 타입
null + '' // -> "null"

// undefined 타입
undefined + '' // -> "undefined"

// 심벌 타입
(Symbol()) + '' // -> TypeError: Cannot convert a Symbol value to a string

// 객체 타입
({}) + '' // -> "[object Object]"
Math + '' // -> "[object Math]"
[] + '' // -> ""
[10, 20] + '' // -> "10,20"
(function(){}) + '' // -> "function(){}"
Array + '' // -> "function Array() { [native code] }"

숫자 타입 변환

1
2
3
1 - "1"; // -> 0
1 * "10"; // -> 10
1 / "one"; // -> NaN

숫자끼리의 연산을 위한 연산자를 사용할 경우 number타입으로 자동 형 변환된다.

1
"1" > 0; // -> true

위와 같이 숫자끼리의 크기를 비교하는 연산이기 때문에 숫자 타입으로 형 변환된다.

+ 단항 연산자 또한 숫자 타입으로 암묵적 타입 변환을 수행한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 문자열 타입
+"" + // -> 0
"0" + // -> 0
"1" + // -> 1
"string" + // -> NaN
// 불리언 타입
true + // -> 1
false + // -> 0
// null 타입
null + // -> 0
// undefined 타입
undefined + // -> NaN
// 심벌 타입
Symbol() + // -> ypeError: Cannot convert a Symbol value to a number
// 객체 타입
// 빈 문자열(‘’), 빈 배열([]), null, false는 0으로, true는 1로 변환된다.
// 객체와 빈 배열이 아닌 배열, undefined는 변환되지 않아 NaN이 된다는 것에 주의하자.
{} + // -> NaN
[] + // -> 0
[10, 20] + // -> NaN
function () {}; // -> NaN

불리언 타입 변환

1
2
3
4
5
6
7
8
9
//if문의 조건식일 경우 true, false 값으로 암묵적 타입 변환이 이뤄짐.

if ("") console.log("1");
if (true) console.log("2");
if (0) console.log("3");
if ("str") console.log("4");
if (null) console.log("5");

// 2 4
  • 위의 결과에서 boolean 타입 값으로 타입 변환돼서 그 중 true 값으로 평가되는 값인 2번 4번만 출력된다.

  • 아래 값들은 false 값으로 평가된다.

    • false
    • undefined
    • null
    • 0, -0
    • NaN
    • ’’ (빈 문자열)
    1
    2
    3
    4
    5
    6
    7
    8
    // 아래의 조건문은 모두 코드 블록을 실행한다.
    // ! 부정 논리 연산자로 인해 원래 false인 것이 true로 바뀌어 조건문이 실행된다.
    if (!false) console.log(false + " is falsy value");
    if (!undefined) console.log(undefined + " is falsy value");
    if (!null) console.log(null + " is falsy value");
    if (!0) console.log(0 + " is falsy value");
    if (!NaN) console.log(NaN + " is falsy value");
    if (!"") console.log("" + " is falsy value");

명시적 타입 변환

명시적 타입 변환에는 여러가지 방법이 있다.

  1. 표준 빌트인 생성자 함수(String, Number, Boolean)를 new 연산자 없이 호출하는 방법
  2. 빌트인 메서드를 사용하는 방법
  3. 암묵적 타입 변환을 의도적으로 이용하는 방법

문자열 타입 변환

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 1. String 생성자 함수를 new 연산자 없이 호출하는 방법
String(1); // -> "1"
String(NaN); // -> "NaN"
String(Infinity); // -> "Infinity"
String(true); // -> "true"
String(false); // -> "false"

// 2. Object.prototype.toString 메서드를 사용하는 방법
(1).toString(); // -> "1"
NaN.toString(); // -> "NaN"
Infinity.toString(); // -> "Infinity"
true.toString(); // -> "true"
false.toString(); // -> "false"

// 3. 문자열 연결 연산자를 이용하는 방법
1 + ""; // -> "1"
NaN + ""; // -> "NaN"
Infinity + ""; // -> "Infinity"
true + ""; // -> "true"
false + ""; // -> "false"

숫자 타입 변환

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 1. Number 생성자 함수를 new 연산자 없이 호출하는 방법
Number("0"); // -> 0
Number("-1"); // -> -1
Number("10.53"); // -> 10.53
Number(true); // -> 1
Number(false); // -> 0

// 2. parseInt, parseFloat 함수를 사용하는 방법(문자열만 변환 가능)
parseInt("0"); // -> 0
parseInt("-1"); // -> -1
parseFloat("10.53"); // -> 10.53

// 3. + 단항 산술 연산자를 이용하는 방법
+"0"; // -> 0
+"-1"; // -> -1
+"10.53"; // -> 10.53
+true; // -> 1
+false; // -> 0

// 4. * 산술 연산자를 이용하는 방법
"0" * 1; // -> 0
"-1" * 1; // -> -1
"10.53" * 1; // -> 10.53
true * 1; // -> 1
false * 1; // -> 0

불리언 타입 변환

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 1. Boolean 생성자 함수를 new 연산자 없이 호출하는 방법
// 문자열 타입 => 불리언 타입
Boolean("x"); // -> true
Boolean(""); // -> false
Boolean("false"); // -> true
// 숫자 타입 => 불리언 타입
// 참고로 0이 아닌 모든 숫자 타입은 `true`다.
Boolean(0); // -> false
Boolean(1); // -> true
Boolean(NaN); // -> false
Boolean(Infinity); // -> true
// null 타입 => 불리언 타입
Boolean(null); // -> false
// undefined 타입 => 불리언 타입
Boolean(undefined); // -> false
// 객체 타입 => 불리언 타입
Boolean({}); // -> true
Boolean([]); // -> true

// 2. ! 부정 논리 연산자를 두번 사용하는 방법
// 문자열 타입 => 불리언 타입
!!"x"; // -> true
!!""; // -> false
!!"false"; // -> true
// 숫자 타입 => 불리언 타입
!!0; // -> false
!!1; // -> true
!!NaN; // -> false
!!Infinity; // -> true
// null 타입 => 불리언 타입
!!null; // -> false
// undefined 타입 => 불리언 타입
!!undefined; // -> false
// 객체 타입 => 불리언 타입
!!{}; // -> true
!![]; // -> true

단축 평가

논리연산자를 이용한 단축평가

논리합||, 논리곱&&연산자의 계산 방향은 좌에서 우로 진행된다.

1
"Cat" || "Dog"; // -> "Cat"

|| 연산자는 좌항 우항에 존재한 피연산자 중 하나만 true라면 반환값이 true이다.
좌측에서 계산하다 좌항이 true니 뒤는 확인하지 않고 좌항의 값을 반환한다.

1
'Cat' && 'Dog' // -> "Dog"

&& 연산자는 좌항 우항에 존재한 피연산자 모두 true면 반환값이 true이다.
좌측부터 계산해서 우항도 true라면 우항의 값을 반환한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 정리하면 다음과 같은 규칙을 따른다.
true || "anything"; // -> true
false || "anything"; // -> anything
true && "anything"; // -> anything
false && "anything"; // -> false

// 논리합(||) 연산자
"Cat" || "Dog"; // -> "Cat"
false || "Dog"; // -> "Dog"
"Cat" || false; // -> "Cat"

// 논리곱(&&) 연산자
"Cat" && "Dog"; // -> "Dog"
false && "Dog"; // -> false
"Cat" && false; // -> false

if문은 단축평가로 대체가 가능하다.

1
2
3
4
5
6
7
8
9
10
var done = true;
var message = "";

//if문 사용
if (done) message = "완료";

//단축평가로 if문 대체
message = done && "완료";

console.log(message); // 완료
1
2
3
4
5
6
7
8
9
10
var done = false;
var message = "";

// if문 사용
if (!done) message = "미완료";

//단축평가로 if문 대체
message = done || "미완료";

console.log(message); // 미완료

다음은 단축평가 응용 방법이다.

  • 객체를 가리키기를 기대하는 변수의 값이 객체가 아니라 null 또는 undefined인 경우 객체의 프로퍼티를 참조하면 타입 에러TypeError가 발생한다.
    이때 단축 평가를 사용하면 에러를 발생시키지 않는다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    //객체 프로퍼티 참조
    var elem = null;
    var value = elem.value; // TypeError: Cannot read property 'value' of null

    //단축평가 사용
    var elem = null;
    // elem이 null이나 undefined와 같은 Falsy 값이면 elem으로 평가되고
    // elem이 Truthy 값이면 elem.value로 평가된다.
    var value = elem && elem.value; // -> null
  • 함수를 호출할 때 인수를 전달하지 않으면 매개변수는 undefined를 갖는다.
    이때 단축 평가를 사용하여 매개변수의 기본값을 설정하면 undefined로 인해 발생할 수 있는 에러를 방지할 수 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // ES6의 매개변수의 기본값 설정
    function getStringLength(str = "") {
    return str.length;
    }

    getStringLength(); // -> 0
    getStringLength("hi"); // -> 2

    // 단축 평가를 사용한 매개변수의 기본값 설정
    // 위 처럼 = '' 같은 걸 넣어줄 필요가 없다.
    function getStringLength(str) {
    str = str || "";
    return str.length;
    }

    getStringLength(); // -> 0
    getStringLength("hi"); // -> 2

옵셔널 체이닝 연산자

옵셔널 체이닝(optional chaining) 연산자 ?.는 좌항의 피연산자가 null 또는 undefined인 경우 undefined를 반환하고,
그렇지 않으면 우항의 프로퍼티 참조를 이어간다.

1
2
3
4
5
var elem = null;

// elem이 null 또는 undefined이면 undefined를 반환하고, 그렇지 않으면 우항의 프로퍼티 참조를 이어간다.
var value = elem?.value;
console.log(value); // undefined

&&를 이용한 단축 평가가 있음에도 나온 이유는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var str = "";

// 문자열의 길이(length)를 참조한다.
var length = str && str.length;

// 문자열의 길이(length)를 참조하지 못한다.
console.log(length); // ''

/************************************************
*************************************************/

var str = "";

// 문자열의 길이(length)를 참조한다. 이때 좌항 피연산자가 false로 평가되는 Falsy 값이라도
// null 또는 undefined가 아니면 우항의 프로퍼티 참조를 이어간다.
var length = str?.length;
console.log(length); // 0
  • 논리 연산자 &&는 좌항 피연산자가 false로 평가되는 Falsy 값(false, undefined, null, 0, -0, NaN, ‘‘)이면 좌항 피연산자를 그대로 반환한다.

  • 좌항 피연산자가 Falsy 값인 0이나 ‘‘인 경우도 마찬가지다. 하지만 0이나 ‘‘은 객체로 평가될 때도 있다.

  • 하지만 옵셔널 체이닝 연산자 ?.는 좌항 피연산자가 false로 평가되는 Falsy 값(false, undefined, null, 0, -0, NaN, ‘‘)이라도 null 또는 undefined가 아니면 우항의 프로퍼티 참조를 이어간다.

null 병합 연산자

null 병합(nullish coalescing) 연산자 ??는 좌항의 피연산자가 null 또는 undefined인 경우 우항의 피연산자를 반환하고, 그렇지 않으면 좌항의 피연산자를 반환한다.

1
2
3
// 좌항의 피연산자가 null 또는 undefined이면 우항의 피연산자를 반환하고, 그렇지 않으면 좌항의 피연산자를 반환한다.
var foo = null ?? "default string";
console.log(foo); // "default string"

||를 이용한 단축 평가가 있음에도 나온 이유는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
// Falsy 값인 0이나 ''도 기본값으로서 유효하다면 예기치 않은 동작이 발생할 수 있다.
var foo = "" || "default string";
console.log(foo); // "default string"

/************************************************
*************************************************/

// 좌항의 피연산자가 Falsy 값이라도 null 또는 undefined이 아니면 좌항의 피연산자를 반환한다.
var foo = "" ?? "default string";
console.log(foo); // ""
  • 논리 연산자 ||를 사용한 단축 평가의 경우 좌항의 피연산자가 false로 평가되는 Falsy 값(false, undefined, null, 0, -0, NaN, ‘‘)이면 우항의 피연산자를 반환한다.

  • 만약 Falsy 값인 0이나 ‘‘도 기본값으로서 유효하다면 예기치 않은 동작이 발생할 수 있다.

  • null 병합 연산자 ??는 좌항의 피연산자가 false로 평가되는 Falsy 값(false, undefined, null, 0, -0, NaN, ‘‘)이라도 null 또는 undefined가 아니면 좌항의 피연산자를 그대로 반환한다.

참고 도서: 모던 자바스크립트 Deep Dive

오늘 느낀 것

  • 새로 배우는게 정말 많다. 단축 평가 등은 이번에 처음 알았다.
  • 기본를 정리하는게 생각보다 더 도움이 많이 된다. 기본에 집중하자.

Nyong’s GitHub

오늘 한 것

제어문

제어문(control flow statement)은 주어진 조건에 따라 코드 블록을 실행(조건문)하거나 반복 실행(반복문)할 때 사용한다.

조건문

조건문은 조건식(Boolean)을 판단하여 참 거짓에 따라 실행할 코드 블록을 정한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 대표적인 if else 문이다.
if (조건식) {
// 조건식이 참이면 이 코드 블록이 실행된다.
} else {
// 조건식이 거짓이면 이 코드 블록이 실행된다.
}

// else if 문이 새로 등장한다. '아님 말고' 느낌으로 써준다.
if (조건식1) {
// 조건식1이 참이면 이 코드 블록이 실행된다.
} else if (조건식2) {
// 조건식2가 참이면 이 코드 블록이 실행된다.
} else {
// 조건식1과 조건식2가 모두 거짓이면 이 코드 블록이 실행된다.
}

if… else… else if…를 배웠다면 아래의 switch 문도 알아보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
switch (표현식) {
case 표현식1:
switch 문의 표현식과 표현식1이 일치하면 실행될 문;
// break를 사용하지 않으면 표현식이 참이더라도 맨밑으로 내려간다. 의도한게 아니라면 까먹지 말자.
break;

case 표현식2:
switch 문의 표현식과 표현식2가 일치하면 실행될 문;
break;

//default는 필수가 아닌 선택, 어차피 마지막이라 break가 필요 없다.
default:
switch 문의 표현식과 일치하는 표현식을 갖는 case 문이 없을 때 실행될 문;
}

반복문

반복문(loop statement)은 조건식의 평가 결과가 참인 동안 코드 블록을 계속 반복 실행한다. 반복 과정에서 매번 조건식을 다시 평가히여 참인 경우 코드 블록을 반복, 거짓일 경우 끝이 난다.

for

아래 예시는 i가 0 부터 시작하여 2 보다 작은 동안 i를 매번 1씩 증가시키면서 코드블록을 반복하는 반복문이다.

1
2
3
for (var i = 0; i < 2; i++) {
console.log(i);
}

결과는 아래와 같다. i가 0일 때, 1일 때 두번 실행됐다.

1
2
0
1

for 문을 무한루프로 활용하는 법이다.

1
2
// 무한루프
for (;;) { ... }

while

1
2
3
4
5
6
7
var count = 0;

// count가 3보다 작을 때까지 코드 블록을 계속 반복 실행한다.
while (count < 3) {
console.log(count); // 0 1 2
count++;
}

탈출하는 경우 break를 사용한다!

1
2
3
4
5
6
7
8
9
var count = 0;

// while의 무한루프
while (true) {
console.log(count);
count++;
// count가 3이면 코드 블록을 탈출한다.
if (count === 3) break;
} // 0 1 2

do…while

do를 먼저 실행한 후 반복문으로 들어간다. 그냥 while문과 실행 순서가 다른 것을 이용할 수 있다.

1
2
3
4
5
6
7
var count = 0;

// while과 다른 점은 조건식 비교 이전에 do를 실행한 후 조건식과 비교한다.
do {
console.log(count);
count++;
} while (count < 3); // 0 1 2

break와 continue

break

  • break문은 엄밀하게 말하면 코드 블록 탈출이 아닌, 레이블 문, 반복문(for, for…in, for…of, while, do…while) 또는 switch 문의 코드 블록을 탈출하는 것이다.
  • 레이블 문, 반복문, switch 문의 코드 블록 외에 break 문을 사용하면 SyntaxError(문법 에러)가 발생한다.
1
2
3
if (true) {
break; // Uncaught SyntaxError: Illegal break statement
}
  • break문은 레이블 문에서도 쓰인다.
  • 레이블 문은 프로그램의 실행 순서를 제어하는 데 사용한다. 사실 switch 문의 case 문과 default 문도 레이블 문이다. 레이블 문을 탈출하려면 break 문에 레이블 식별자를 지정한다.
1
2
// foo라는 레이블 식별자가 붙은 레이블 문
foo: console.log("foo");
1
2
3
4
5
6
7
8
9
10
// outer라는 식별자가 붙은 레이블 for 문
outer: for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
// i + j === 3이면 outer라는 식별자가 붙은 레이블 for 문을 탈출한다.
if (i + j === 3) break outer;
console.log(`inner [${i}, ${j}]`);
}
}

console.log("Done!");
  • break outer를 만나면 outer 레이블이 달린 for 문을 탈출한다.
  • 레이블 문은 중첩된 for 문 외부로 탈출할 때 유용하지만 그 밖의 경우에는권장하지 않는다.
  • 레이블 문을 사용하면 프로그램의 흐름이 복잡해져서 가독성이 나빠지고 오류를 발생시킬 가능성이 높아지기 때문이다.

continue

  • continue 문은 반복문의 코드 블록 실행을 현 지점에서 중단하고 반복문의 증감식으로 실행 흐름을 이동시킨다.
  • 반복문을 아예 탈출하는 break문과는 다르다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 문자열에서 특정 문자의 개수를 세는 예

var string = "Hello World.";
var search = "l";
var count = 0;

// 문자열은 유사배열이므로 for 문으로 순회할 수 있다.
for (var i = 0; i < string.length; i++) {
// 'l'이 아니면 현 지점에서 실행을 중단하고 반복문의 증감식으로 이동한다.
if (string[i] !== search) continue;
count++; // continue 문이 실행되면 이 문은 실행되지 않는다.
}

console.log(count); // 3

// 참고로 String.prototype.match 메서드를 사용해도 같은 동작을 한다.
const regexp = new RegExp(search, "g");
console.log(string.match(regexp).length); // 3

오늘 느낀 것

  • 제어문은 C나 JAVA 때도 했지만 오래전이라 다시 복기하는 심정으로 정리했다.
  • 다시 공부해보니 새롭게 알게 된 사실도 있고 애매하게 알고있던 부분도 명쾌해졌다.

Nyong’s GitHub

오늘 한 것

연산자

표현식인 피연산자와 연산자의 조합으로 값으로 평가될 수 있는 표현식인 연산자 표현식을 이룬다.

1
2
3
4
5
6
7
8
9
10
11
12
// 산술 연산자
5 * 4; // -> 20
// 문자열 연결 연산자
"My name is " + "Lee"; // -> 'My name is Lee'
// 할당 연산자
color = "red"; // -> 'red'
// 비교 연산자
3 > 5; // -> false
// 논리 연산자
true && false; // -> false
// 타입 연산자
typeof "Hi"; // -> 'string'

산술 연산자

1
5 / 2; // -> 2.5

JavaScript는 number 타입이 모두 실수기 때문에 정수를 나눠 실수값을 얻을 수도 있다.

단항 산술 연산자

단항 산술 연산자인 증가/감소(++/–) 연산자는 위치에 의미가 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var x = 5,
result;

// 선할당 후증가(postfix increment operator)
result = x++;
console.log(result, x); // 5 6

// 선증가 후할당(prefix increment operator)
result = ++x;
console.log(result, x); // 7 7

// 선할당 후감소(postfix decrement operator)
result = x--;
console.log(result, x); // 7 6

// 선감소 후할당 (prefix decrement operator)
result = --x;
console.log(result, x); // 5 5

단항 산술 연산자에는 +, - 도 있다.

1
2
3
// + 연산자는 아무런 효과가 없다.
+10; // -> 10
+-10; // -> -10

+ 연산자는 언제 사용할까?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var x = "1";

// 문자열을 숫자로 타입 변환한다.
console.log(+x); // 1
// 부수 효과는 없다.
console.log(x); // "1"

// 불리언 값을 숫자로 타입 변환한다.
x = true;
console.log(+x); // 1
// 부수 효과는 없다.
console.log(x); // true

// 불리언 값을 숫자로 타입 변환한다.
x = false;
console.log(+x); // 0
// 부수 효과는 없다.
console.log(x); // false

// 문자열을 숫자로 타입 변환할 수 없으므로 NaN을 반환한다.
x = "Hello";
console.log(+x); // NaN
// 부수 효과는 없다.
console.log(x); // "Hello"

숫자 타입으로 변환한 값을 생성해서 반환한다. 하지만 변수 값 자체를 바꾸지는 않는다.

- 연산자는 부호를 반전하거나 숫자 타입으로 변환한다. 하지만 변수 값 자체를 바꾸지는 않는다.

1
2
3
4
5
6
7
8
9
10
11
// 부호를 반전한다.
-(-10); // -> 10

// 문자열을 숫자로 타입 변환한다.
-"10"; // -> -10

// 불리언 값을 숫자로 타입 변환한다.
-true; // -> -1

// 문자열은 숫자로 타입 변환할 수 없으므로 NaN을 반환한다.
-"Hello"; // -> NaN

문자열 연결 연산자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 문자열 연결 연산자
1 + "2"; // -> '12'

// true는 1로 타입 변환된다.
1 + true; // -> 2

// false는 0으로 타입 변환된다.
1 + false; // -> 1

// null은 0으로 타입 변환된다.
1 + null; // -> 1

// undefined는 숫자로 타입 변환되지 않는다.
+undefined; // -> NaN
1 + undefined; // -> NaN

위와 같이 서로 연산할 수 없는 타입끼리 만나면 JS 엔진에 의해 암묵적 타입 변환(implicit coercion) 또는 타입 강제 변환(type coercion)이 일어난다.

비교 연산자

비교 연산자(comparison operator)는 좌항과 우항의 피연산자를 비교한 다음 그 결과를 불리언 값으로 반환한다.

동등비교(==) 연산자는 타입이 달라도 암묵적 타입 변환을 통해 비교된 값만 같으면 동등하다.

1
2
3
4
5
6
7
"0" == ""; // -> false
0 == ""; // -> true
0 == "0"; // -> true
false == "false"; // -> false
false == "0"; // -> true
false == null; // -> false
false == undefined; // -> false

일치 비교(===) 연산자는 좌항과 우항의 피연산자가 타입과 값이 모두 같은 경우에 true를 반환한다.

1
5 === "5"; // -> false

주의할 점!

1
2
3
4
5
6
7
8
9
10
11
//NaN은 자신과 일치하지 않는 유일한 값이다.
NaN === NaN; // -> false

//isNaN 함수를 사용하자
isNaN(NaN); // -> true
isNaN(10); // -> false
isNaN(1 + undefined); // -> true

//0도 주의하자 JS는 음의 0, 양의 0 둘 다 있지만 타입과 같은 같다.
0 === -0; // -> true
0 == -0; // -> true

위 처럼 +0, -0은 같게 판단하고 NaN끼리는 다르다 그래서 Object.is()가 생겼다.

1
2
3
4
5
-0 === +0; // -> true
Object.is(-0, +0); // -> false

NaN === NaN; // -> false
Object.is(NaN, NaN); // -> true

부동등 비교 연산자(!=)와 불일치 비교 연산자(!==)는 다른지를 판단하는 개념이다.

1
2
3
4
5
6
7
8
9
// 부동등 비교(타입은 논외)
5 != 8; // -> true
5 != 5; // -> false
5 != "5"; // -> false

// 불일치 비교(타입도 판단)
5 !== 8; // -> true
5 !== 5; // -> false
5 !== "5"; // -> true

논리 연산자

논리 연산자(logical operator)는 우항과 좌항의 논리관계를 연산한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 논리합(||) 연산자, 하나만 true면 true
true || true; // -> true
true || false; // -> true
false || true; // -> true
false || false; // -> false

// 논리곱(&&) 연산자, 모두 true여야 true
true && true; // -> true
true && false; // -> false
false && true; // -> false
false && false; // -> false

// 논리 부정(!) 연산자, 반대값을 출력
!true; // -> false
!false; // -> true

// boolean값이 아닐 경우 암묵적 타입 변환
!0; // -> true
!"Hello"; // -> false

지수 연산자

좌항의 피연산자를 밑으로, 우항의 피연산자를 지수로 거듭 제곱하여 숫자 값을 반환한다.

1
2
3
4
5
6
7
8
9
10
2 ** 2; // -> 4
2 ** 2.5; // -> 5.65685424949238
2 ** 0; // -> 1
2 ** -2; // -> 0.25

//음수는 괄호로 묶어야한다.
(-5) ** 2; // -> 25

//지수 연산자는 이항 연산자 중에서 우선순위가 가장 높다.
2 * 5 ** 2; // -> 50

참고 도서: 모던 자바스크립트 Deep Dive

오늘 느낀 것

  • C랑 Java랑 비슷하지만 새로 배우는 것도 있었다. 배움 앞에 겸손하자.

Nyong’s GitHub

오늘 한 것

변수

원시 값 자체와, 원시값을 할당한 변수를 혼동하면 안 된다. 변수는 재할당할이 가능하지만, 원시 값은 객체타입과 다르게 변형할 수 없다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 문자열 메서드는 문자열을 변형하지 않음
var bar = "baz";
console.log(bar); // baz
bar.toUpperCase();
console.log(bar); // baz

// 할당은 원시 값에 새로운 값을 부여 (변형이 아님)
bar = bar.toUpperCase(); // BAZ

//원시타입 String도 같음
var x = "Hello";
console.log(x); // Hi

// 참조 타입인 배열은 변형함
var foo = [];
console.log(foo); // []
foo.push("plugh");
console.log(foo); // ["plugh"]

원시값 MDN

  • 원시 값을 교체할 수는 있지만, 직접 변형할 수는 없다.

아래의 경우 x와 y의 값을 바꾸는 과정이다.

1
2
3
4
5
6
7
8
9
10
11
12
//기본적인 방법
var x = 1;
var y = 2;
var z = y;

y = x;
x = z;
console.log(x, y); // 2 1

// 배열 이용
[y, x] = [x, y];
console.log(x, y); // 2 1
  • 원시값을 변형할 수는 없지만 변수의 값은 재할당이 가능하다.

표현식과 문

  • 표현식인 문과 표현식이 아닌 문은 변수에 할당해보면 안다. 표현식인 문은 변수에 할당되지만, 표현식이 아닌 문은 변수에 할당되지 않는다.

  • 문 > 값 > 표현식 > 리터럴 과 같이 포함 관계를 갖는다. 당연히 역은 성립되지 않는다.

  • 토큰에는 문을 구성하는 모든 기본 요소가 토큰의 지위를 갖을 수 있지만 토큰의 조건은 문의 구성 요소만을 토큰이라 말한다.

  • 콘솔에서 표현식인 문을 실행하면 평가되어 생성된 결과인 값을 출력한다.

1
2
> 10 + 10
< 20
  • 위와 같은 표현식과는 다르게 표현식이 아닌 문을 실행하면 언제나 undefined를 출력한다.
1
2
3
//console
> var x;
< undefined
  • 이를 완료값이라 한다. 완료값은 표현식의 평가 결과가 아니다. 따라서 표현식처럼 변수에 할당, 참조가 불가능하다.

데이터 타입

  • JavaScript에서 데이터 타입은 변수가 아닌 값에 있다.
  • JS에서 모든 숫자는 실수이다. 배정밀도 64비트 부동소수점 형식을 따른다.(8바이트)
1
2
3
4
5
6
7
8
9
10
11
var x = 1;
console.log(x, typeof x);

var y = "1";
console.log(y, typeof y);

// ==은 값만 비교한다.
console.log(x == y); //true

// === 은 데이터타입과 값을 둘 다 비교한다.
console.log(x === y); //false
  • 같은 값 1이 아닌 숫자와 문자에 차이가 있는 1이다.
1
console.log(0.1 + 0.2); // 0.30000000000000004
  • 위 결과가 0.3이 아닌 이유는 컴퓨터의 한계다. 10진법을 2진법으로 변환해서 계산하면 높은 확률로 무한 소수가 발생하기 때문에 오차가 있다.

왜 8bit는 1byte일까?

  • 최근에는 8bit가 1byte지만, 역사적으로 6bit, 7bit, 9bit 등의 1byte가 존재했다.
  • 하여튼 8bit가 1byte인 이유는 컴퓨터의 발전이 영문권에서 발전한 것과 큰 연관이 있다.
  • ASCII(아스키 코드: 영문 알파벳을 사용하는 대표적인 문자 인코딩)에서의 영문자와 숫자 1자가 7bit이다.
  • 여기에 통신 오류검출을 위한 parity bit를 1bit 추가해서 8bit가 됐다는 설이 가장 유력하다.

오늘 느낀 것

  • 기초를 파면서 C나 JAVA와는 다른 점이 생각보다 많으며 새로운 것도 많이 배우고 있다.
  • JavaScript를 공부하다가 C, JAVA가 차라리 더 편하겠다는 생각이 들 때면 개발을 포기하고 싶었던 그때를 떠올리며 마음을 잡자…
  • 재밌다! 내일도 ‘즐코’

Nyong’s GitHub

오늘 한 것

개념 및 용어 정리

변수

  • 만약 숫자 ‘10’을 메모리에 저장한다면 숫자 ‘10’에 접근할 때마다 복잡한 메모리 주소를 찾아 직접 접근해야한다. 하지만 메모리 주소에 직접 접근하는 것은 매우 위험하다. 잘 못 접근하게 되면 미지의 메모리를 변경할 수도 있기 때문이다.
  • 위와 같은 이유로 프로그래밍 언어는 값을 메모리에 저장하고, 저장된 값을 읽어 들여 재사용하기 위해 변수라는 메커니즘을 제공한다.
  • 변수는 값의 위치를 나타내는 상징적인 이름이며 식별자라고도 부른다.
1
2
3
4
5
// 변수는 하나의 값을 저장하기 위한 수단이다.
var nyong = 10;

// 연산을 통해 생성된 값을 변수를 통해 메모리 공간에 저장할 수도 있다.
var result = 10 + 20;
  • 변수에 값을 저장하는 것을 할당(assignment), 변수에 저장된 값을 읽어 들이는 것을 참조(reference)라 한다.
  • 안에 담긴 값의 의미를 반영하여 지은 변수 이름은 저장된 값의 의미를 명확히 할 수 있어 가독성을 높여준다.
  • 코드는 컴퓨터에게 내리는 명령이면서 동시에 개발자를 위한 문서이기도 하다. 명확한 네이밍은 코드를 이해하기 쉽게 만들며 타인이 내 코드를 쉽게 해석할 수 있게 돕는다.

변수 선언

  • 변수를 사용하려면 반드시 선언이 필요하다. 변수를 선언할 때는 var, let, const 키워드를 사용한다.
1
2
var score; // 변수 선언
console.log(score); //undefined
  • 위와 같이 변수를 선언한 후 출력하면 undefined 값이 출력된다. 이는 현재 변수 안에 메모리 공간은 확보됐지만 어떤 값도 할당하지 않은 것이다.
  • 자바스크립트에서 변수를 선언하면 다음의 절차를 거친다
    1. 선언 단계 : 변수 이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알린다.
    2. 초기화 단계 : 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화한다.
  • 자바스크립트에서는 초기화 값으로 정의되지 않았다는 뜻인 undefined를 할당한다. 이것도 할당이라면 할당이지만 의도하지 않았다면 제대로된 값을 할당한 행위는 아니다.

호이스팅

1
2
3
console.log(score); // undefined

var score; // 변수 선언문
  • 자바스크립트는 인터프리터 언어인 것을 저번에 설명하였다. 그렇다면 console.log(score)구문을 실행하면 var score가 실행되기 전이기 때문에 변수 참조 에러(ReferenceError)가 발생해야하지만 undefined값이 출력됐다.
  • 그 이유는 변수 선언이 소스코드가 한 줄씩 순차적으로 실행되는 런타임(runtime)이 아니라 이전 단계에서 먼저 실행되기 때문이다.
  • 자바스크립트 엔진은 런 타임에 진입하기 전 준비과정으로 모든 선언문(변수,함수 선언문 등)을 찾아 먼저 실행한다. 그렇기 때문에 var로 선언된 변수인 score가 먼저 실행되어 위의 현상이 나타나는 것이다.
  • 이처럼 변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 변수 호이스팅(variable hoisting)이라 한다.
  • var, let, const, function, function*, class 키워드를 사용해서 선언하는 모든 식별자(변수, 함수, 클래스 등)는 호이스팅된다.

값 할당

1
var score = 80; // 변수 선언과 값의 할당
  • 변수 선언은 소스코드가 순차적으로 실행되는 시점인 런타임 이전에 먼저 실행되지만 값의 할당은 소스코드가 순차적으로 실행되는 시점인 런타임에 실행된다. 아래 코드를 보자.
1
2
3
4
5
6
console.log(score); // undefined

var score; // ① 변수 선언
score = 80; // ② 값의 할당

console.log(score); // 80
  • 참고로 변수에 값을 할당할 때는 이전 값 undefined가 저장되어 있던 메모리 공간을 지우고 그 메모리 공간에 할당 값 80을 새롭게 저장하는 것이 아니라 새로운 메모리 공간을 확보하고 그 곳에 할당 값을 저장한다.(즉, 메모리 주소가 동일하지 않다.)
  • 그 이유는 undefined값도 할당이라면 할당이라고 위에서 말했는데 변수에 값을 제대로 할당할 경우(사실은 처음이 아닌 ‘재할당’이다.) 새로운 메모리 공간을 확보하고 그 메모리 공간에 새로운 값을 저장하기 때문이다.
  • 그렇다면 전에 값이 저장된 메모리 공간이 불필요하게 존재한다고 걱정할 수 있는데 이는 가비지 콜렉터라는 기능에 의해 자동 삭제된다. 단, 언제 삭제될지는 모른다.

변수 네이밍 규칙

  1. 식별자는 특수문자를 제외한 문자, 숫자, 언더스코어(_), 달러 기호($)를 포함할 수 있다.
  2. 단, 식별자는 특수문자를 제외한 문자, 언더스코어(_), 달러 기호($)로 시작해야 한다. 숫자로 시작하는 것은 허용하지 않는다.
  3. 예약어는 식별자로 사용할 수 없다.(예약어는 프로그래밍 언어에서 사용되고 있거나 사용될 예정인 단어를 말한다.)
  4. 영어 이외의 문자로도 명명할 수 있지만 권장하지 않는다.
  5. 자바스크립트는 대소문자를 구별한다.
  6. 주석이 필요없어도 의미를 알 수 있는 이름으로 짓자.
  7. 네이밍 컨벤션을 활용하자.
1
2
3
4
5
6
7
8
9
10
11
12
13
// 카멜 케이스 (camelCase)
var firstName;

// 스네이크 케이스 (snake_case)
var first_name;

// 파스칼 케이스 (PascalCase)
var FirstName;

// 헝가리언 케이스 (typeHungarianCase)
var strFirstName; // type + identifier
var $elem = document.getElementById("myId"); // DOM 노드
var observable$ = fromEvent(document, "click"); // RxJS 옵저버블

리터럴

  • 리터럴(literal)은 약속된 ‘기호를 사용해 값을 생성’하는 표기 방식(notaion)을 말한다.
  • 이해할 수 있는 문자(아라비아 숫자, 알파벳, 한글 등) 또는 미리 약속된 기호(‘’, “”, ., [], {}, // 등)로 표기한 코드다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 정수 리터럴
100
// 부동소수점 리터럴
10.5
// 2진수 리터럴(0b로 시작)
0b01000001
// 8진수 리터럴(ES6에서 도입. 0o로 시작)
0o101
// 16진수 리터럴(ES6에서 도입. 0x로 시작)
0x41

// 문자열 리터럴
'Hello'
"World"

// 불리언 리터럴
true
false

// null 리터럴
null

// undefined 리터럴
undefined

// 객체 리터럴
{ name: 'Lee', address: 'Seoul' }

// 배열 리터럴
[ 1, 2, 3 ]

// 함수 리터럴
function() {}

// 정규표현식 리터럴
/[A-Z]+/g

표현식

  • 표현식(expression)은 값으로 평가될 수 있는 문(statement)이다. 즉, 표현식이 평가되면 새로운 값을 생성하거나 기존 값을 참조한다.
  • 때문에 리터럴도 표현식이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 50 + 50은 리터럴과 연산자로 이뤄져 있다. 하지만 50 + 50도 평가되어 숫자 값 100을 생성하므로 표현식이다.
var score = 50 + 50;

// 변수 식별자를 참조하면 변수 값으로 평가된다.
score; // -> 100

// 다음과 같이 다양한 표현식이 있지만 값으로 평가된다는 점에서 모두 동일하다. 즉, 값으로 평가되는 문은 모두 표현식이다.
// 문법적으로 값이 위치할 수 있는 자리에는 표현식도 위치할 수 있다는 것을 의미한다. 표현식은 다른 표현식의 일부가 되어 새로운 값을 만들어낼 수 있다.
// 리터럴 표현식
10;
("Hello");

// 식별자 표현식(선언이 이미 존재한다고 가정)
sum;
person.name;
arr[1];

// 연산자 표현식
10 + 20;
sum = 10;
sum !== 10;

// 함수/메서드 호출 표현식(선언이 이미 존재한다고 가정)
square();
person.getName();

  • 문(statement)은 프로그램을 구성하는 기본 단위이자 최소 실행 단위이다. 문의 집합으로 이뤄진 것이 프로그램이며, 문을 작성하고 순서에 맞게 나열하는 것이 프로그래밍이다.

  • 문은 여러 토큰으로 구성된다. 토큰(token)이란 문법적인 의미를 가지며, 더 이상 나눌 수 없는 코드의 기본 요소다. 예를 들어, 키워드, 식별자, 연산자, 리터럴, 세미콜론(;)이나 마침표(.) 등의 특수 기호는 문법적인 의미를 가지며, 문법적으로 더 이상 나눌 수 없는 코드의 기본 요소이므로 모두 토큰이다.

  • 표현식은 문의 일부일 수도 있고 그 자체로 문이 될 수도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
// 변수 선언문은 값으로 평가될 수 없으므로 표현식이 아니다.
var x;

// 1, 2, 1 + 2, x = 1 + 2는 모두 표현식이다.
// x = 1 + 2는 표현식이면서 완전한 문이기도 하다.
x = 1 + 2;

// 표현식이 아닌 문은 값처럼 사용할 수 없다.
var foo = var x; // SyntaxError: Unexpected token var

// 표현식인 문은 값처럼 사용할 수 있다
var foo = x = 100;
  • 표현식인 문과 표현식이 아닌 문을 구별하는 가장 간단하고 명료한 방법은 변수에 할당해 보는 것이다. 표현식인 문은 값으로 평가되므로 변수에 할당할 수 있다.

데이터 타입

자바스크립트(ES6)는 7개의 데이터 타입을 제공한다.

  • 원시 타입(primitive type)

    • 숫자(number) 타입: 숫자. 정수와 실수 구분 없이 하나의 숫자 타입만 존재
    • 문자열(string) 타입: 문자열
    • 불리언(boolean) 타입: 논리적 참(true)과 거짓(false)
    • undefined 타입: var 키워드로 선언된 변수에 암묵적으로 할당되는 값
    • null 타입: 값이 없다는 것을 의도적으로 명시할 때 사용하는 값
  • 심벌(symbol) 타입: ES6에서 추가된 7번째 타입

    • 객체 타입 (object/reference type): 객체, 함수, 배열 등

숫자 타입

  • 자바스크립트는 하나의 숫자 타입만 존재한다.
  • ECMAScript 사양에 따르면 숫자 타입의 값은 모든 수를 실수로 처리하며, 정수만 표현하기 위한 데이터 타입(integer type)이 별도로 존재하지 않는다.
1
2
3
4
// 숫자 타입은 모두 실수로 처리된다.
console.log(1 === 1.0); // true
console.log(4 / 2); // 2
console.log(3 / 2); // 1.5
  • 2진수, 8진수, 16진수는 아래와 같이 표기한다.
1
2
3
4
5
6
7
var binary = 0b01000001; // 2진수
var octal = 0o101; // 8진수
var hex = 0x41; // 16진수

console.log(binary); // 65
console.log(octal); // 65
console.log(hex); // 65
  • 숫자 타입은 추가적으로 특별한 값들도 표현할 수 있다.
1
2
3
4
// 숫자 타입의 세 가지 특별한 값
console.log(10 / 0); // Infinity
console.log(10 / -0); // -Infinity
console.log(1 * "String"); // NaN <- 대소문자 구별 주의

문자열

  • 자바스크립트의 문자열은 원시 타입이며, 변경 불가능한 값(immutable value)이다. 때문에 문자열이 생성되면 그 문자열을 변경할 수 없다. C나 Java와는 문자열 타입이 다르다.
  • 자바스크립트에서 일반적인 표기법은 작은따옴표를 사용한다. 하지만 작은따옴표(‘’), 큰따옴표(“”), 백틱(``)으로도 가능하다.
  • 따옴표로 감싸지 않으면 키워드나 식별자로 인식한다.
1
2
3
4
5
6
7
8
9
10
11
// 문자열 타입
var string;
string = "문자열"; // 작은따옴표
string = "문자열"; // 큰따옴표
string = `문자열`; // 백틱 (ES6)

string = '작은따옴표로 감싼 문자열 내의 "큰따옴표"는 문자열로 인식된다.';
string = "큰따옴표로 감싼 문자열 내의 '작은따옴표'는 문자열로 인식된다.";

// 따옴표로 감싸지 않은 hello를 식별자로 인식한다.
var string = hello; // ReferenceError: hello is not defined

템플릿 리터럴

  • 템플릿 리터럴은 아래와 같이 문자열 처리 기능을 제공한다.

    • 멀티라인 문자열(multi-line string)
    • 표현식 삽입(expression interpolation)
    • 태그드 템플릿(tagged template)
  • 템플릿 리터럴은 백틱(``)으로 표현한다.

  1. 멀티라인 문자열

    • 템플릿 리터럴 내에서는 이스케이프 시퀀스를 사용하지 않고도 줄바꿈이 허용되며, 모든 공백도 있는 그대로 적용된다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var template = `<ul>
    <li><a href="#">Home</a></li>
    </ul>`;

    console.log(template);
    /*
    <ul>
    <li><a href="#">Home</a></li>
    </ul>
    */
  2. 표현식 삽입

    • 간단히 문자열을 삽입할 수 있다. 이를 통해 문자열 연산자보다 가독성 좋고 간편하게 문자열을 조합할 수 있다.
    1
    2
    3
    4
    5
    6
    7
    8
    var first = "Ung-mo";
    var last = "Lee";

    // ES6: 표현식 삽입
    console.log(`My name is ${first} ${last}.`); // My name is Ung-mo Lee.

    // 템플릿 리터럴이 아닌 일반 문자열에서의 표현식 삽입은 문자열로 취급된다.
    console.log("1 + 2 = ${1 + 2}"); // 1 + 2 = ${1 + 2}

undefined

  • undefined 타입의 값은 undefined가 유일하다.
  • var 키워드로 선언한 변수는 undefined로 초기화된다.
1
2
var foo;
console.log(foo); // undefined
  • 자바스크립트 엔진이 변수를 초기화할 때 쓰는 undefined를 개발자가 의도적으로 변수에 할당하는 것은 취지와 어긋나기 때문에 권장하지 않는다.
  • 변수에 값이 없다는 것을 명시하고 싶은 때는 undefined를 할당하는 것이 아니라 null을 할당한다.

null

  • null 타입의 값은 null이 유일하다. (대소문자 구별)
  • null은 변수에 값이 없다는 것을 의도적으로 명시할 때 사용하며 변수 값에 대한 참조를 제거한다.

symbol

  • 변경 불가능한 원시 타입의 값이다. 심벌 값은 절대 다른 값과 중복되지 않다.
  • 주로 이름이 충돌할 위험이 없는 객체의 유일한 프로퍼티 키를 만들기 위해 사용한다.
1
2
3
4
5
6
7
8
9
10
// 심벌 값 생성
var key = Symbol("key");
console.log(typeof key); // symbol

// 객체 생성
var obj = {};

// 이름이 충돌할 위험이 없는 유일무이한 값인 심벌을 프로퍼티 키로 사용한다.
obj[key] = "value";
console.log(obj[key]); // value

동적 타입 언어 / 정적 타입 언어

  • C나 Java의 경우 정적 타입(static/strong type) 언어이다. 변수를 선언할 때 데이터 타입을 명확하게 선언해야 한다.

  • 정적 타입 언어는 변수의 타입을 변경할 수 없고 선언한 타입에 맞는 값만 할당할 수 있다. 정적 타입 언어는 컴파일 시점에 타입 체크를 수행한다.

  • 자바스크립트는 동적 타입 언어로서 변수 타입을 선언하지 않고 var, let, const 키워드를 사용한다.

  • 자바스크립트의 변수는 데이터 타입의 값이라도 자유롭게 할당할 수 있다.

  • 자바스크립트 변수는 할당에 의해 타입이 결정된다. 또한 다른 타입 값을 재할당해 동적으로 타입을 바꿀 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var foo;
console.log(typeof foo); // undefined

foo = 3;
console.log(typeof foo); // number

foo = "Hello";
console.log(typeof foo); // string

foo = true;
console.log(typeof foo); // boolean

foo = null;
console.log(typeof foo); // object

foo = Symbol(); // 심벌
console.log(typeof foo); // symbol

foo = {}; // 객체
console.log(typeof foo); // object

foo = []; // 배열
console.log(typeof foo); // object

foo = function () {}; // 함수
console.log(typeof foo); // function
  • 변수의 타입이 동적으로 변하기 때문에 동적 타입 언어의 변수는 값의 변경에 의해 타입도 언제든지 변경될 수 있다. 따라서 변수 값을 확인하기 전에는 타입을 확신할 수 없다.

  • 자바스크립트 엔진에 의해 암묵적으로 타입이 자동으로 변환되는 경우도 있기 때문에 동적 타입 언어는 유연성(flexibility)은 높지만 신뢰성(reliability)은 떨어진다.

  • 이러한 동적 언어의 특징으로 아래와 같이 변수를 사용하길 권장한다.

    • 변수는 꼭 필요한 경우에 한해 제한적으로 사용한다. 필요한 만큼 최소한으로 유지해야한다.
    • 변수의 유효 범위(스코프)는 가능한 좁게 만들어 변수의 부작용을 억제해야 한다.
    • 전역 변수는 최대한 사용하지 않도록 한다.
    • 변수보다는 상수를 사용해 값의 변경을 억제한다.
    • 변수 이름은 변수의 목적이나 의미를 파악할 수 있도록 네이밍한다.

오늘 느낀 것

  • 용어 정리를 하면서 새롭게 배우는 것이 생각보다 많다. 사상누각되지 말자. 복습부터 새로 배우는 모든 것이 내 기본기가 된다.

Nyong’s GitHub

오늘 한 것

JavaScript

JavaScript의 역사

  • 1995년 웹페이지의 보조적인 기능을 수행(웹서버 실행, HTML/CSS 랜더링 등)하기 위한 브라우저에서 동작하는 경량 프로그래밍 언어로 탄생하였다.

  • 처음 이름은 ‘모카’에서 ‘라이브스크립트’로 변경했다가 1996년 12월 최종적으로 ‘JavaScript’로 명명되었다.

  • 1996년 8월 마이크로소프트의 JScript가 IE 3.0에 탑재되면서 JavaScript와의 표준화에 실패하고 자사 브라우저 사장 점유율 높이려고 치킨게임을 시작했고 이로 인해 크로스 브라우징 이슈가 끝없이 발생했다.

  • 1996년 11월 모든 브라우저 정상 작동을 위한 ECMA 인터내셔널에 JavaScript의 표준화를 요청하며 1997년 7월 ECMA-262라는 JavaScript 초판(ECMAScript 1)사양이 완성되었고, 1999년 ECMAScript3, 2009년 ECMAScript5가 HTML5와 함께 출현하며 표준 사양이 되었다.

  • 2015년 출시한 ECMAScript 6에는 화살표 함수, 클래스, 모듈 같은 범용 프로그래밍 언어에 적합한 기능들이 추가되며 큰 변화가 생겼다.

  • 현재 JavaScript는 모든 브라우저의 표준 프로그래밍 언어가 되었다.

  • ECMAScript 2020가 현재 표준 사양이다. javaScript에 대한 표준이다. 브라우저에서 지원하는 alert() 같은 함수는 포함되지 않는 브라우저 node.js에서 모두 동작하는 순수한 엔진에 대한 표준이다.

ECMAScript 2020 사양

Ajax 등장

  • 1999년, 자바스크립트를 이용해 서버와 브라우저가 비동기(asynchronous) 방식으로 데이터를 교환할 수 있는 통신 기능인 Ajax(Asynchronous Javascript And XML)가 등장했다.

  • 비동기통신 발명 이전에는 완전한 HTML 코드 자체를 서버로부터 받아 웹페이지 전체를 랜더링하고 이후 화면 전환이 필요하면 다시 완전한 HTML 코드 자체를 받아 웹페이지 전체를 새로 랜더링했다.

  • 위와 같은 방식으로 랜더링을 하게 되면 변경할 필요가 없는 부분까지 전송 받아 다시 랜더링했기 때문에 불필요한 데이터 통신이 발생하였고 이로 인해 화면 전환 시 화면이 깜빡거리는 현상이 발생한다. 하지만 이는 어쩔 수 없는 웹페이지의 한계로 받아들여졌었다.

  • Ajax는 웹페이지에서 화면전환이 필요한 부분만 서버로부터 받아 부분만 랜더링하는 방식이다. 이로서 빠른 성능과 부드러운 화면 전환이 가능해졌다.

V8 JavaScript 엔진

  • 2008년 웹 애플리케이션을 구축하려는 요구에 부합하는 빠른 성능을 가진 구글의 V8 JavaScript 엔진이 등장했다.
  • V8 엔진은 JavaScript로 데스크톱 애플리케이션과 유사한 UX를 제공할 수 있는 가능성을 보여주며 웹 애플리케이션 프로그래밍 언어로 정착하였다.

Node.js

  • node.js는 2009년 브라우저의 JavaScript 엔진에서만 동작하던 JavaScript 이외의 환경에서도 동작할 수 있도록 독립시킨 JavaScript 실행 환경이다.
  • JavaScript는 Node.js를 통해 서버 사이드 애플리케이션 개발에서도 사용할 수 있는 범용 프로그래밍 언어가 되었다. JavaScript는 프런트엔드 영역은 물론 백엔드 영역까지 아우르는 웹 프로그래밍 언어의 표준으로 자리 잡고 있다.

SPA (Single Page Application)

  • SPA는 한번의 전체 페이지 로드 이후에는 데이터 요청만으로 부분을 변경하여 사용하는 Application을 뜻한다.
  • 언뜻보면 Ajax 같은 비동기 방식과의 다른점을 찾아 볼 수 없지만 ‘라우팅’이란 개념으로 다르게 된다. 기존 Ajax의 경우 화면을 구성해도 동일한 페이지에서 구성했기 때문에 히스토리가 남지 않고 뒤로가기나 해당 페이지 즐겨찾기가 불가능하다. 하지만 ‘라우팅’을 이용하는 SPA는 index#menu1#submenu1 같이 해쉬태그와 해쉬값에 맞는 페이지를 실행하기 때문에 한페이지 내에서 여러 페이지 구성이 가능하다.
  • SPA가 대중화되면서 Angular, React, Vue.js, Svelte 등 다양한 SPA 프레임워크/라이브러리가 많이 사용되고 있다.
  • 하지만 초기 구동 속도가 상대적으로 느리며 SEO(검색최적화)에 취약한 것이 단점이다.

기타

interpreter vs compile

  • 프로그래밍 언어에는 interpreter 언어와 compile 언어가 있다.
  • 참고로 자바스크립트 엔진은 원래 interpreter 언어지만 일부 소스 코드는 컴파일하고 실행한다. 두 언어의 장점을 결합해 비교적 처리 속도가 느린 인터프리터의 단점을 해결했다.
  • 현재는 컴파일러와 인터프리터의 기술적 구분이 점차 모호해져 가는 추세다.

interpreter

  • interpreter 언어는 코드가 실행되는 단계인 런타임에 문 단위로 바이트코드(가상 머신에서 실행하도록 만드는 바이너리 코드)로 변환 후 실행한다.
  • 위와 같은 이유로 실행 파일이 생성되지 않는다. 때문에 코드가 실행될 때마다 인터프리트 과정이 반복 수행된다.
  • 언어 특징 때문에 실행 중 에러 발생 시 더 이상 실행이 이뤄지지 않는다.
  • 구문에 대한 해석과 실행이 동시에 이뤄지기 때문에 별도의 실행파일이 존재하지 않는다.
  • 컴파일이 없기 때문에 신속하게 동작한다.
  • 대표적으로 HTML, CSS, JavaScript, Python 등이 있다.

compile

  • compile 언어는 interpreter 언어와 다르게 소스코드를 전부 해석하고 수집한 후 머신 코드(CPU가 바로 실행할 수 있는 기계어)로 재구성하여 실행한다.
  • 실행 파일이 생성된다. 때문에 컴파일은 실행에 앞서 단 한번만 수행된다.
  • 전체 코드를 변환 후 에러를 보고한다. 이렇기 때문에 보안측에서는 interpreter 언어보다 취약하다.
  • 컴파일 언어는 한번 컴파일하게 되면 실행 파일이 생성되며 실행파일은 interpreter 언어보다 빠르다.
  • 대표적으로 C, C++, JAVA 등이 있다.

픽셀 절대 단위일까, 상대 단위일까?

  • 픽셀은 viewport에서 표현 가능한 최소 단위이다. 픽셀은 그렇다면 절대 단위인가?
  • 하지만 같은 최대 해상도(픽셀 수가 척도인 출력 정도)를 가진 다른 크기의 디바이스 1px의 값의 절대적인 수치는 다르다. 다르게 말하면 픽셀은 디바이스 해상도에 따라 상대적인 크기를 갖는다.
  • 1픽셀은 모든 디바이스에서 1픽셀이지만 디바이스마다 갖는 1픽셀의 크기는 다르다.
  • 모니터의 1px과 빔프로젝트로 보는 1px을 생각하면 감이 잡힐지 모른다. 모니터에서 10px 크기의 상자와 모니터와 연결된 빔프로젝트로 보는 10px 크기의 상자는 분명 다를 것이다.
  • 위처럼 디바이스 별로 픽셀의 크기는 제각각이기 때문에 픽셀을 기준으로 하는 단위는 명확하지 않다. 따라서 대부분의 브라우저는 1px을 1/96 인치의 절대단위로 인식한다.

오늘 느낀 것

  • 사상누각 되지 말자. 모든 것은 기본기가 탄탄해야한다. 결과만 보고 달리다가 기본기를 잃으면 무너지는 것은 시간 문제다.
  • 그런 의미로 오늘은 개론을 공부했다.

Nyong’s GitHub

카페 W 프로젝트 개발

카페 W는 고정형 웹 개발을 위한 프로젝트로서 HTML/CSS를 최대한으로 활용하여 개발하였다.

카페 W의 디자인

  • 완성된 UI 디자인을 Figma 도구를 통해 배포 받고 레이아웃 구성에 활용하였다.

  • cafe W figma 링크: cafeW figma

  • 데스크탑 UI는 1440px+ 급으로 설계하였다.

  • Desktop UI

UI

  • Design System

Design

UI 개발

  • Developer — 제작된 UI 디자인을 토대로 모바일/데스크탑 UI를 개발합니다.
  1. 효율적인 코딩에 적합한 Visual Studio Code 도구를 활용하였다.
  2. 모두를 위한 디자인을 지향하며 개발하였다. (Universal Design, A11Y)
  3. 시멘틱 마크업을 통해 웹 접근성을 최대한 끌어내도록 노력하였다. (HTML5 + WAI-ARIA)
  4. 소스 버전을 Git을 통해 관리하여 효율적인 개발 작업, 분배, 병합 환경을 구축하였다. (Git)
  5. issue 등록을 통한 작업 분배화 실시간으로 현황을 파악할 수 있는 환경을 구축하고 개발하였다. (GitHub)

Semantic Markup (HTML5 + WAI-ARIA)
image

Version Control System (Git + GitHub)
image
image

참여인원

  • @yhun940731 최용훈
  • @ahnanne 안예인
  • @moripark32 박세리

프로젝트_GitHub
발표자료

느낀 것

  • 팀장으로 참여하여 참 많은 우여곡절을 겪었다. 그래도 팀장이어서 더 책임감을 느끼고 보람찼다. 결과적으로 시간분배부터 팀장으로서의 git 사용, 더 많은 분량 등 최대의 노력을 쏟아낼 수 있었던 좋은 기회였다.

  • merge하다가 꼬여서 고생했다. 앞으로 진짜 신중하게 검토해야하는 습관을 들여야한다.

  • git bash에서 명령어 입력할 때 생각을 하고 하자. 잘 못 입력해서 이미지 파일을 다 날렸다.

  • 방금 말한 것과 같이 git 과 git hub를 처음 사용해보면서 위와 같은 시행착오를 겪으며 어렵고 불편했지만 갈 수록 널리 쓰이는 이유를 알게됐다.

  • 시멘틱 마크업을 알게되니 div와 span을 쓰면 불안해진다. 하지만 시멘틱 마크업도 중요하지만 쓸 때는 쓰는 결단력이 필요하다.

  • 절대값으로 레이아웃을 구성하면 너무 찝찝해서 최대한 안 쓰려고 했는데 능력의 한계로
    쓸 수 밖에 없을 때 좀 더 깊은 레이아웃 구성 방법에 대해 간절함을 느꼈다.

  • 이번 프로젝트에서 css를 적용할 때 스타일 적용하면서도 더 효율적인 방법이 있을 텐데를 고민할때가
    괴롭지만 참 재밌었다.

  • 시간이 더 있었다면 퀄리티가 더 높았겠지만 그건 변명이다. 결국 정해진 기한 내에 하는 것도 실력이다.

  • 크로스 브라우징은 너무 어려워서 거의 진행하지 못하였다. 좀 더 섬세한 부분도 완성하고 싶었지만 시간관계상 못 하지 못해 많이 아쉬웠다. 별개로 앞으로 IE를 사용하는 사람이 있으면 도시락 싸들고 말려야겠다는 결심을 했다.

  • 결과는 과정의 노력을 확인하는 수단일 뿐, 집착하고 얽매일 필요가 없다. 때때로 힘들었지만 점점 결과를 보여갈 때 느꼈던 기분과, 과정을 통해 얻은 새로운 지식과 경험이 중요하다고 생각한다. 잘하는 것도 중요하지만 과정을 통해 전보다 나아졌다는 것이 중점이라고 생각하며 프로젝트를 마친다.

Nyong’s GitHub