지난주에는 CSS의 마무리로 CSS Grid와 미디어 쿼리를 다뤘습니다. 핵심만 빠르게 짚어보겠습니다.
1fr: 남은 공간을 비율로 나눔repeat(auto-fill, minmax(280px, 1fr)): 미디어 쿼리 없이
자동 반응형min-width로 큰 화면
대응prefers-color-scheme: 다크 모드 감지prefers-reduced-motion: 접근성, 애니메이션 줄이기이번 주 범위인 JS 타입, 변수, 호이스팅에서 자주 헷갈리는 포인트를 코드와 함께 정리합니다.
undefined는 JS 엔진이 "아직 값을 안 넣었네"라고 자동으로 넣어주는 것입니다. null은 개발자가 "여기는 일부러 비워놨어"라고 직접 넣는 것입니다. 비유하면 undefined는 택배가 아직 안 온 상태, null은 "빈 상자를 보낸" 상태입니다.
let a; // 선언만 하고 값을 안 넣음
console.log(a); // undefined — JS 엔진이 넣어줌
let b = null; // 개발자가 의도적으로 "비어있음"을 표시
console.log(b); // null
var는 블록(if, for)을 스코프 경계로 인식하지 않습니다. 이게 실질적으로
어떤 문제를 만드는지 코드로 보겠습니다.
// var — if 블록을 무시하고 밖에서도 살아있음
if (true) {
var secret = "비밀번호123";
}
console.log(secret); // "비밀번호123" — if 밖에서 접근 가능
// let — 블록 안에서만 존재
if (true) {
let safe = "안전한값";
}
console.log(safe); // ReferenceError — 블록 밖에서 접근 불가
호이스팅은 "선언이 위로 끌어올려진다"라고 배우지만, 실제로 코드가 이동하는 것은 아닙니다. JS 엔진이 실행 전에 선언을 미리 읽어두는 것입니다.
// 우리가 작성한 코드
console.log(x); // undefined — 에러 아님!
var x = 5;
console.log(x); // 5
// JS 엔진이 이해하는 순서 (개념적)
// var x; ← 선언만 끌어올림, 값은 undefined
// console.log(x); ← undefined
// x = 5; ← 여기서 값 할당
// console.log(x); ← 5
// let/const는 다르게 동작
console.log(y); // ReferenceError! — TDZ(일시적 사각지대)
let y = 5;
// 선언은 인식하지만, 초기화 전까지 접근을 막음
NaN(Not a Number)은 "계산 실패"를 뜻합니다. 실패한 계산 두
개가 같은 실패인지 비교하는 건 의미가 없으므로, JS 표준에서 NaN은 자기
자신과도 같지 않다고 정의했습니다. NaN 여부 확인에는 반드시 Number.isNaN()을
사용합니다.
NaN === NaN; // false — 유일하게 자기 자신과 같지 않은 값
Number.isNaN(NaN); // true — 올바른 확인 방법
Number.isNaN("hello"); // false — 문자열은 NaN이 아님
isNaN("hello"); // true — 전역 isNaN은 타입 변환을 하므로 위험!
Q1. typeof NaN의 결과는 무엇인가요? 왜 그런 결과가 나오는지 JS 스펙(IEEE
754) 관점에서 설명하고, NaN인지 확인하는 올바른 방법은 무엇인지 설명하세요.
"number"NaN은 IEEE 754 부동소수점 표준에서 정의한
"숫자가 아님을 나타내는 숫자 값"입니다. 0/0, Infinity - Infinity 같이 수학적으로 정의할 수 없는 연산의 결과로 나옵니다. 이름은 "Not a
Number"지만 타입은 number입니다.
NaN을 확인하려면 Number.isNaN()을 사용해야 합니다. 전역
isNaN()은 인자를 숫자로 변환한 뒤 판단하므로 isNaN('hello')가 true를
반환하는 등 부정확합니다.
NaN === NaN이 false라는 점을 이용해 value !== value로 NaN을 체크하는
방법도 있지만, 의도가 명확하지 않습니다.
Number.isNaN()을 쓰는 것이 가장 명확합니다.
Q2. 아래 코드의 실행 결과를 예측하고, 왜 그런 결과가 나오는지 TDZ(Temporal Dead Zone) 개념을 사용해 설명하세요.
console.log(a);
let a = 1;
let으로 선언한 변수는 호이스팅은 되지만,
선언문에 도달하기 전까지 TDZ(Temporal Dead Zone)에 놓여 접근할 수 없습니다.
var는 호이스팅 시 undefined로 초기화되지만, let/const는 선언문에서
초기화가 이루어집니다. 선언문 이전 구간이 TDZ이며, 이 구간에서 접근하면
ReferenceError가 발생합니다.
"let도 호이스팅이 되므로 undefined가 출력된다"고 답하는 경우가 많습니다.
호이스팅은 되지만 초기화가 되지 않은 상태가 TDZ이며,
TDZ 구간에서 접근하면 에러가 납니다.
Q3. null == undefined는 true인데, null === undefined는 false입니다.
왜 이런 차이가 나는지 == 연산자의 타입 변환 규칙을 설명하세요.
== 연산자의 Abstract Equality Comparison 알고리즘에서
null과 undefined는 서로에 대해서만 동등하다고 특별 규칙으로 정의
되어 있습니다. 반면 ===는 타입 변환 없이 비교하므로 null(object 타입)과
undefined(undefined 타입)는 타입이 달라 false를 반환합니다.
이 특수 규칙 덕분에 value == null로 null과 undefined를 동시에 체크하는
패턴이 실무에서 예외적으로 허용됩니다.
Q4. JavaScript의 falsy 값 6가지를 나열하세요. 그리고 빈 배열 []이 falsy가
아닌 이유를 설명하세요.
'', null, undefined, NaN빈 배열 []은 객체(object)이고,
JS에서 모든 객체는 truthy입니다. 배열의 길이가 0이더라도 객체
자체가 존재하므로 truthy로 평가됩니다. 빈 객체 {}도 마찬가지입니다.
falsy 값에 0n(BigInt 0)을 추가해 7가지라고 답하는 경우도 있습니다. ES2020에
추가된 0n도 falsy이므로 문맥에 따라 맞는 답일 수 있습니다. 배열이 비어있는지
확인하려면 arr.length === 0으로 명시적으로 검사해야 합니다.
JavaScript부터는 학습 방식이 바뀝니다. 지금까지 HTML/CSS는 강의 영상으로 진행했는데, JS는 텍스트 자료 위주로 학습합니다. 이미 다른 언어 경험이 있기 때문에, 영상으로 기초를 쌓는 단계보다 JS 특유의 동작 방식을 이해하는 것이 더 중요합니다.
학습 자료를 읽으면서 브라우저 콘솔(F12 → Console 탭)을 열고 코드를 직접 실행해보는 것을 강하게 권장합니다. 특히 JS는 눈으로 읽을 때와 실제로 실행해볼 때 결과가 다르게 느껴지는 경우가 많습니다.
이번 주 범위와 관련된 실제 면접 질문들입니다. 정답을 외우기보다는 자신만의 말로 설명하는 연습을 해보세요.
Q1. null, undefined, undeclared(선언되지 않은 변수)의 차이는 무엇인가요?
undefined: 변수가 선언됐지만 값이 할당되지 않은 상태. JS
엔진이 자동 부여.null: 개발자가 의도적으로 "값 없음"을 명시한 상태. typeof null은 버그로 인해 'object'를 반환.typeof로 접근하면
'undefined'를 반환하지만, 직접 참조하면 ReferenceError 발생.let a;
console.log(a); // undefined
console.log(typeof a); // 'undefined'
let b = null;
console.log(b); // null
console.log(typeof b); // 'object' ← 버그
console.log(typeof c); // 'undefined' (선언 안 했지만 typeof는 안전)
console.log(c); // ReferenceError: c is not defined
var, let, const의 차이를 설명해주세요.세 가지 모두 변수 선언 키워드지만 스코프, 재선언, 재할당, 호이스팅 동작이 다릅니다.
var: 함수 스코프, 재선언 가능, 호이스팅 시 undefined로
초기화. 예측하기 어려워 현재는 사용하지 않습니다.let: 블록 스코프, 재선언 불가, 재할당 가능. TDZ로 인해 선언
전 접근 시 ReferenceError.const: 블록 스코프, 재선언·재할당 모두 불가. 단,
객체·배열의 내부 값은 변경 가능.면접 팁: "기본적으로 const를 쓰고, 재할당이 필요한 경우에만 let을 쓴다. var는 쓰지 않는다"고 정리하면 좋습니다.
==와 ===의 차이는 무엇인가요?==(동등 연산자)는 비교 전에 두 값의 타입을 맞추는 암묵적
타입 변환을 수행합니다. 그래서 0 == false, '' == false, null == undefined가 모두 true가 됩니다.
===(일치 연산자)는 타입 변환 없이 값과 타입이 모두 같아야
true를 반환합니다. 예측 불가능한 버그를 방지하기 위해 실무에서는 항상
===를 사용합니다.
다음 주에는 JS의 핵심인 객체(Object)와 함수(Function), 그리고 스코프(Scope)를 배웁니다. 특히 함수는 JS에서 일급 객체로 취급된다는 점, 스코프는 var와 let/const가 다르게 동작한다는 점이 핵심입니다.
다음 주 학습 자료(week6)의 얄코 강의를 시청하거나, 스킵 진단 문제 10개를 풀어보세요. 코드 예제를 콘솔에서 직접 실행해보면서 학습하는 것을 권장합니다.