⚡ 자바스크립트 핵심 개념 완전 정리
"자바스크립트는 10분 만에 배울 수 있지만, 제대로 이해하는 데는 10년이 걸린다."
프론트엔드 기술 면접에서 가장 자주 등장하는 것이 바로 자바스크립트 핵심 동작 원리입니다. 이 글에서는 면접에서 반드시 나오는 개념들을 원리 중심으로 정리합니다.
📌 목차
- 클로저 (Closure)
- 이벤트 루프 (Event Loop)
- 프로토타입 (Prototype)
- this 바인딩
- 호이스팅 (Hoisting)
- 비동기 처리: Promise와 async/await
1️⃣ 클로저 (Closure)
클로저는 함수가 자신이 선언될 당시의 렉시컬 스코프(Lexical Scope)를 기억해, 함수 실행이 끝난 후에도 그 스코프에 접근할 수 있는 현상입니다.
function makeCounter() {
let count = 0;
return function () {
count += 1;
return count;
};
}
const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
makeCounter() 실행이 끝나도 반환된 함수는 count 변수를 계속 기억합니다. 이것이 클로저입니다.
실무 활용 예시
- 프라이빗 변수 구현 (모듈 패턴)
- 디바운스/쓰로틀 함수 구현
- 리액트의 useState도 내부적으로 클로저 원리를 활용
// 디바운스 함수 - 클로저로 timer를 유지
function debounce(fn, delay) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
}
💡 면접 포인트: "클로저가 무엇인가"보다 "왜 메모리 누수를 조심해야 하는가"까지 답할 수 있으면 좋습니다. 클로저에 계속 참조되는 변수는 가비지 컬렉션 대상에서 제외되기 때문입니다.
2️⃣ 이벤트 루프 (Event Loop)
자바스크립트는 싱글 스레드로 동작하지만, setTimeout, fetch 같은 비동기 작업을 어떻게 논블로킹으로 처리할까요? 그 답이 이벤트 루프입니다.
┌───────────────┐
│ Call Stack │ ← 동기 코드가 실행되는 곳
└───────┬───────┘
│ 비어있으면
▼
┌───────────────┐ ┌──────────────────┐
│ Event Loop │◀────│ Microtask Queue │ ← Promise 콜백
└───────┬───────┘ └──────────────────┘
│ ▲
▼ │
┌───────────────┐ ┌──────────────────┐
│ Task Queue │─────▶│ Web APIs │ ← setTimeout, fetch 등
└───────────────┘ └──────────────────┘
실행 순서 예시
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');
// 출력 순서: 1 → 4 → 3 → 2
핵심 원리
- 동기 코드(Call Stack)가 먼저 모두 실행된다 (1, 4)
- Call Stack이 비면, Microtask Queue(Promise)를 먼저 모두 비운다 (3)
- 그 다음 Task Queue(setTimeout 등)를 하나씩 처리한다 (2)
💡 면접 포인트: "Microtask가 Task보다 우선순위가 높다"는 점을 코드 실행 순서 예제로 설명할 수 있어야 합니다.
3️⃣ 프로토타입 (Prototype)
자바스크립트는 클래스 기반이 아닌 프로토타입 기반 상속 언어입니다. 모든 객체는 자신의 프로토타입을 가지며, 프로퍼티를 찾을 때 프로토타입 체인을 따라 올라갑니다.
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function () {
return `${this.name} makes a sound.`;
};
const dog = new Animal('Dog');
console.log(dog.speak()); // "Dog makes a sound."
dog ──[[Prototype]]──▶ Animal.prototype ──[[Prototype]]──▶ Object.prototype ──▶ null
dog 객체에 speak가 없으면, 프로토타입 체인을 따라 Animal.prototype에서 찾습니다.
ES6 class 문법은 이 프로토타입 방식을 감싸는 **문법적 설탕(Syntactic Sugar)**일 뿐, 내부 동작 원리는 동일합니다.
class Animal {
constructor(name) { this.name = name; }
speak() { return `${this.name} makes a sound.`; }
}
4️⃣ this 바인딩
this는 함수가 호출되는 방식에 따라 값이 결정됩니다 (선언 위치가 아님, 단 화살표 함수는 예외).
호출 방식this 값
| 일반 함수 호출 | undefined (strict mode) 또는 전역 객체 |
| 메서드 호출 (obj.method()) | obj |
| call/apply/bind | 명시적으로 지정한 객체 |
| 화살표 함수 | 선언 시점의 상위 스코프의 this를 그대로 사용 |
| 생성자 함수 (new) | 새로 생성된 인스턴스 |
const obj = {
name: 'Kim',
regular: function () { console.log(this.name); },
arrow: () => { console.log(this.name); },
};
obj.regular(); // "Kim" (obj가 this)
obj.arrow(); // undefined (선언 시점 상위 스코프의 this)
💡 면접 포인트: 콜백 함수 안에서 this가 예상과 다르게 동작하는 문제를 화살표 함수나 bind로 어떻게 해결하는지 설명할 수 있어야 합니다.
5️⃣ 호이스팅 (Hoisting)
변수와 함수 선언이 스코프의 최상단으로 끌어올려지는 것처럼 동작하는 현상입니다.
console.log(a); // undefined (에러 아님!)
var a = 10;
console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 20;
핵심 차이
- var: 선언과 초기화(undefined)가 함께 호이스팅됨 → 접근 시 에러 없이 undefined
- let/const: 선언만 호이스팅되고 초기화는 실제 코드 위치에서 이루어짐 → 그 사이 구간을 **TDZ(Temporal Dead Zone)**라 부르며, 접근 시 에러 발생
TDZ 시작 실제 선언문 TDZ 끝
│ │
▼ ▼
{ let b; ... 접근 불가 구간 ... let b = 20; }
6️⃣ 비동기 처리: Promise와 async/await
콜백 지옥 문제
getUser(id, (user) => {
getPosts(user.id, (posts) => {
getComments(posts[0].id, (comments) => {
console.log(comments); // 들여쓰기 지옥
});
});
});
Promise로 개선
getUser(id)
.then((user) => getPosts(user.id))
.then((posts) => getComments(posts[0].id))
.then((comments) => console.log(comments))
.catch((err) => console.error(err));
async/await로 더 개선
async function loadComments(id) {
try {
const user = await getUser(id);
const posts = await getPosts(user.id);
const comments = await getComments(posts[0].id);
console.log(comments);
} catch (err) {
console.error(err);
}
}
async/await는 Promise를 동기 코드처럼 읽히게 해주는 문법적 설탕입니다. 내부적으로는 여전히 Promise 기반으로 동작합니다.
💡 면접 포인트: Promise.all과 Promise.allSettled의 차이(하나라도 실패하면 전체 실패 vs 모든 결과를 받음)를 설명할 수 있으면 좋은 인상을 줍니다.
🔚 마무리
자바스크립트 면접 질문들은 대부분 "왜 이렇게 동작하는가"를 묻습니다. 단순 암기보다 직접 코드를 실행해보며 결과를 예측하고 검증하는 연습이 가장 효과적인 준비 방법입니다.
'Frontend' 카테고리의 다른 글
| [Frontend] 3D 지형 종/횡단면 분석 기능 구현 (feat. MSA) (0) | 2026.07.05 |
|---|---|
| [Frontend] 3D 시뮬레이션 기능 구현 (feat. MSA) (1) | 2026.07.05 |
| [Frontend] 디지털트윈 방역공조 모니터링 시스템(feat. R&D 과제) (0) | 2026.07.04 |
| [Frontend] 3D 재난 모니터링 플랫폼(feat. R&D 과제) (0) | 2026.07.04 |
| [Frontend] Web Fundamentals 정리 (1) | 2026.07.03 |