Skip to content

iq-dev-lab/javascript-deep-dive

Repository files navigation

🟨 JavaScript Deep Dive

"클로저가 무엇을 캡처하고 this가 무엇으로 결정되는지, 명세 수준에서 안다는 것"


"JS를 작성하는 것과, 실행 컨텍스트·스코프·프로토타입이 명세 수준에서 어떻게 동작하는지 아는 것은 다르다"

실행 컨텍스트·환경 레코드부터 클로저·프로토타입 체인·this 결정 규칙·강제 변환 알고리즘까지 왜 이렇게 동작하는가 라는 질문으로 ECMAScript 명세 수준에서 JavaScript 언어 의미론을 끝까지 파헤칩니다


GitHub JavaScript Node ECMAScript Docs License


🎯 이 레포에 대하여

JavaScript 문법을 다루는 자료는 넘쳐납니다. 하지만 대부분은 "어떻게 쓰나" 에서 멈춥니다.

일반 자료 이 레포
"var는 호이스팅됩니다" 실행 컨텍스트의 생성 단계에서 환경 레코드가 var 바인딩을 undefined로 사전 초기화하는 추상 연산
"let/const는 TDZ에 빠집니다" TDZ는 "선언 전 접근 금지"가 아니라 LexicalEnvironment에서 바인딩이 uninitialized인 시간 구간이라는 명세 정의
"클로저는 함수가 외부 변수를 기억하는 것" 함수 객체의 [[Environment]] 내부 슬롯이 정의 시점의 LexicalEnvironment를 캡처하는 메커니즘
"this는 호출자에 따라 달라집니다" EvaluateCallReference Record의 base를 통해 this를 결정하는 4가지 분기
"[] == ![]true입니다" ToPrimitiveToNumberAbstract Equality Comparison의 단계별 추상 연산으로 분해
"class는 새로운 객체 시스템" class[[Prototype]] 체인의 설탕, extends__proto__prototype을 동시에 연결하는 원리
문법 나열 콘솔로 즉시 검증 가능한 스니펫 + 명세 추상 연산 단계 추적

선행 학습 없음 — 언어 기초 레포입니다. 단, Compiler Deep Dive의 스코프/심볼 개념을 알면 1장이 더 빠르게 이해됩니다.


🚀 빠른 시작

각 챕터의 첫 문서부터 바로 학습을 시작하세요!

Execution Model Closures Prototypes This Coercion Modules Metaprogramming


📚 전체 학습 지도

💡 각 섹션을 클릭하면 상세 문서 목록이 펼쳐집니다


🔹 Chapter 1: 실행 모델

핵심 질문: 변수가 어떻게 해석되며, 호이스팅과 TDZ는 명세에서 어떻게 정의되는가?

실행 컨텍스트, 환경 레코드, 호이스팅, TDZ, 스코프 체인 (6개 문서)
문서 다루는 내용
01. 실행 컨텍스트 생성/실행 2단계, 실행 컨텍스트 스택, 전역/함수/eval 컨텍스트의 차이, LexicalEnvironmentVariableEnvironment의 분리
02. 환경 레코드와 스코프 DeclarativeEnvironmentRecord / ObjectEnvironmentRecord / FunctionEnvironmentRecord / GlobalEnvironmentRecord, 식별자 해석이 ResolveBinding 추상 연산으로 정의되는 방식
03. 호이스팅의 실체 varfunction 호이스팅이 "환경 레코드 사전 생성" 단계인 이유, 함수 선언문이 표현식과 다르게 처리되는 코드
04. TDZ — Temporal Dead Zone let/const가 "선언 전 접근 시 ReferenceError"가 아니라 바인딩이 uninitialized 상태인 시간 구간이라는 명세 정의, typeof도 TDZ에서 에러가 나는 이유
05. 스코프 체인 OuterEnv 링크를 따라 식별자를 탐색하는 알고리즘, 렉시컬 스코핑(정의 위치 기준)이 동적 스코핑과 다른 점, 다이어그램으로 보는 중첩 스코프
06. 블록 스코프와 루프 변수 let/const가 블록마다 새 환경 레코드를 생성하는 동작, for(let)이 반복마다 새 바인딩을 만드는 명세 단계, var vs let 루프 클로저 캡처 차이

🔹 Chapter 2: 클로저

핵심 질문: 함수가 정의 환경을 "붙잡는다"는 것은 명세 수준에서 무엇을 의미하는가?

클로저 정의부터 메모리 함의, 함정 디버깅까지 (5개 문서)
문서 다루는 내용
01. 클로저의 정의 함수 객체의 [[Environment]] 내부 슬롯, OrdinaryFunctionCreate가 호출 시점이 아닌 정의 시점의 LexicalEnvironment를 캡처하는 이유
02. 클로저 동작 — 변수 캡처 클로저는 "값"이 아닌 "변수 자체(바인딩)"를 캡처한다는 사실, 같은 외부 변수를 공유하는 클로저들 vs 격리된 클로저
03. 클로저와 메모리 무엇이 GC되지 않고 살아남나, V8의 Context 객체 구조, 클로저가 큰 외부 객체를 의도치 않게 잡고 있는 패턴
04. 클로저 활용 패턴 모듈 패턴, 비공개 상태(IIFE 기반 캡슐화), 커링, 메모이제이션, 부분 적용
05. 함정 — 루프 클로저와 누수 for(var) + setTimeout 클로저 캡처 문제, 이벤트 리스너 누적, Chrome DevTools Memory 탭으로 클로저 기반 누수 디버깅하는 방법

🔹 Chapter 3: 프로토타입과 객체

핵심 질문: class는 새로운 객체 시스템이 아니라 프로토타입 체인의 설탕이다 — 그 메커니즘은?

[[Prototype]] 체인부터 class·디스크립터·불변 객체까지 (6개 문서)
문서 다루는 내용
01. 프로토타입 체인 [[Prototype]] 내부 슬롯, 속성 탐색이 [[Get]]OrdinaryGet을 통해 체인을 따라가는 알고리즘, 체인의 끝(null)
02. prototype vs proto 함수 객체의 prototype 프로퍼티(자식의 __proto__가 될 객체)와 인스턴스의 __proto__(실제 체인 링크) 구분, Object.getPrototypeOf 권장
03. 생성자와 new new 연산자가 수행하는 4단계 (OrdinaryCreateFromConstructor[[Construct]] → 본문 실행 → 반환), 생성자가 객체를 명시 반환할 때의 동작
04. class 문법의 실체 classfunction + prototype 설정의 설탕, extends__proto__prototype 양쪽을 연결하는 이유, super 호출 메커니즘, #private 필드의 명세 구현
05. 객체 생성 패턴 Object.create로 직접 위임 체인 만들기, 팩토리 함수, 믹스인(Object.assign), 위임 기반 설계 vs 클래스 상속
06. 프로퍼티 디스크립터 writable/enumerable/configurable의 의미, getter/setter 정의, Object.freeze / Object.seal / Object.preventExtensions의 차이와 얕은 동결 한계

🔹 Chapter 4: this와 함수

핵심 질문: this는 함수가 어디서 정의됐는지가 아니라 어떻게 호출됐는지로 결정된다 — 그 4가지 규칙은?

this 결정 규칙부터 화살표 함수, 함수 일급 객체까지 (5개 문서)
문서 다루는 내용
01. this 결정 규칙 4가지 일반 호출(fn()) / 메서드 호출(obj.fn()) / new 호출 / 명시적 바인딩의 4분기, EvaluateCallReference Record의 base를 통해 this를 결정하는 명세 단계
02. 명시적 바인딩 — call/apply/bind Function.prototype.call/apply가 임시로 this를 지정하는 방식, bindBoundFunctionExoticObject를 생성하는 원리, 부분 적용 패턴
03. 화살표 함수와 렉시컬 this 화살표 함수는 자신의 this/arguments/super를 갖지 않음, 정의된 스코프의 this를 그대로 사용하는 명세 정의, 콜백에서의 이점과 메서드 정의 시의 함정
04. 함수의 일급 객체성 함수가 객체로서 갖는 속성(length, name, prototype), arguments 객체의 특이성, 나머지/기본/구조분해 매개변수
05. 함정 — this 손실 패턴 메서드 추출 시 this 분리, 콜백 전달 시 컨텍스트 손실, 이벤트 핸들러의 this, setTimeout에서의 this, 화살표 함수와 bind로 해결

🔹 Chapter 5: 타입과 강제 변환

핵심 질문: [] == ![]true인 결과를 추상 연산 단계로 도출할 수 있는가?

원시 타입부터 강제 변환 알고리즘, IEEE754 부동소수점까지 (5개 문서)
문서 다루는 내용
01. 원시 타입과 래퍼 객체 7가지 원시 타입(string/number/boolean/null/undefined/symbol/bigint) + object, String/Number/Boolean 래퍼와 오토박싱, typeof null === 'object'의 역사적 이유
02. 강제 변환 알고리즘 ToPrimitive 추상 연산의 hint('default'/'string'/'number') 분기, ToNumber/ToString/ToBoolean의 단계별 정의, Symbol.toPrimitive 커스터마이징
03. == vs === — 추상 동등 비교 Abstract Equality Comparison의 9단계 알고리즘, null == undefined만 true인 이유, [] == ![]/'' == 0/'0' == false 결과를 단계별로 분해
04. 진리값과 단축 평가 falsy 8종(false/0/-0/0n/''/null/undefined/NaN), &&/||/??의 차이, 옵셔널 체이닝과 결합한 안전한 접근 패턴
05. 숫자의 함정 — IEEE754 모든 number가 64-bit 부동소수점인 결과, 0.1 + 0.2 !== 0.3의 비트 수준 원인, Number.EPSILON을 활용한 비교, BigInt 도입 배경과 호환성

🔹 Chapter 6: 모듈과 런타임

핵심 질문: ESM의 라이브 바인딩과 CommonJS의 값 복사는 무엇이 다르며, 순환 의존에서 어떻게 갈리는가?

모듈 시스템 역사부터 ESM 의미론, 엄격 모드, 런타임 차이까지 (5개 문서)
문서 다루는 내용
01. 모듈의 역사 전역 오염 → IIFE → CommonJS(Node) → AMD/UMD(브라우저) → ESM 표준화로 이어진 흐름, 각 단계가 푸는 문제
02. ESM 의미론 정적 구조(파싱 시점 의존성 분석), 라이브 바인딩(import는 참조), import 호이스팅, 순환 의존 시 ESM의 동작
03. CJS vs ESM 상호운용 동기 require vs 비동기 모듈 그래프, default export 호환성 함정, Node의 dual package 패턴, import() 동적 로드
04. 엄격 모드 'use strict'가 바꾸는 동작들(silent fail → 에러, this 기본값 undefined, with 금지), ESM은 항상 strict
05. 런타임 차이 — 브라우저 vs Node 전역 객체(window vs global/globalThis), 모듈 해석(URL 기반 vs CommonJS 알고리즘), 이벤트 루프 구현 차이의 큰 그림

🔹 Chapter 7: 메타프로그래밍과 최신 기능

핵심 질문: Symbol, Proxy, Generator는 어떻게 언어 동작 자체를 확장 가능하게 만드는가?

Symbol·이터레이터·Proxy부터 반응성 미니 구현까지 (6개 문서)
문서 다루는 내용
01. Symbol과 well-known symbols 고유한 프로퍼티 키로서의 Symbol, Symbol.iterator/Symbol.toPrimitive/Symbol.asyncIterator 등 well-known symbol이 언어 동작을 후킹하는 방식
02. 이터레이터와 제너레이터 이터러블 프로토콜([Symbol.iterator](){value, done}), function*yield의 일시 정지 메커니즘, 지연 평가 시퀀스 패턴
03. Proxy와 Reflect 13가지 트랩(get/set/has/deleteProperty 등)으로 객체 기본 동작 가로채기, Reflect API와의 짝, Vue 3 / MobX 같은 반응성 라이브러리의 기반
04. 디스트럭처링과 스프레드 패턴 매칭으로서의 디스트럭처링, 기본값/이름변경/중첩, 얕은 복사로서의 스프레드, 불변 업데이트 패턴({...state, count: state.count+1})
05. 최신 문법의 의미 옵셔널 체이닝(?.)이 푸는 nested null 체크 문제, 널 병합(??)이 ||와 다른 이유, top-level await, 클래스 필드 등
06. 종합 — Proxy로 반응성 구현 Proxy의 get(track) / set(trigger)으로 자동 의존성 추적 구현, 100줄 미만 미니 Vue Reactivity, 상태관리 레포로 이어지는 다리

🗺️ 목적별 학습 경로

🟢 "클로저랑 this를 정확히 설명하고 싶다" — 면접 준비 / 실무 의문 해소 (2주)

Week 1 — 실행 모델과 클로저

Ch1-01  실행 컨텍스트
Ch1-03  호이스팅의 실체
Ch1-04  TDZ
Ch2-01  클로저의 정의
Ch2-02  클로저 동작 — 변수 캡처
Ch2-05  함정 — 루프 클로저

Week 2 — this와 강제 변환

Ch4-01  this 결정 규칙 4가지
Ch4-03  화살표 함수와 렉시컬 this
Ch4-05  this 손실 패턴
Ch5-03  == vs === — 추상 동등 비교 (면접 단골)
Ch5-04  진리값과 단축 평가
🔵 JS 언어 의미론을 명세 수준에서 이해하고 싶은 개발자 (7주)
Week 1  Chapter 1 전체 — 실행 모델과 환경 레코드
Week 2  Chapter 2 전체 — 클로저
Week 3  Chapter 3 전체 — 프로토타입과 객체
Week 4  Chapter 4 전체 — this와 함수
Week 5  Chapter 5 전체 — 타입과 강제 변환
Week 6  Chapter 6 전체 — 모듈과 런타임
Week 7  Chapter 7 전체 — 메타프로그래밍과 최신 기능
🔴 React/상태관리 전에 기초를 단단히 하고 싶은 개발자 (집중 코스)
핵심 경로 (React의 클로저·불변성·this 이슈를 원리로 이해)

Step 1  Ch2-01~02  클로저 정의와 변수 캡처 → useState 동작 이해의 바닥
Step 2  Ch2-05     루프 클로저 함정 → stale closure 문제 정복
Step 3  Ch4-01,03  this 결정 규칙 + 화살표 함수 → 이벤트 핸들러 바인딩
Step 4  Ch7-04     디스트럭처링/스프레드 → 불변 업데이트 패턴
Step 5  Ch3-01,04  프로토타입 체인 + class → 클래스 컴포넌트 잔재 이해
Step 6  Ch6-02     ESM 의미론 → 번들러가 무엇을 분석하는지
Step 7  Ch7-03,06  Proxy와 Reflect + 반응성 구현 → Vue/MobX/Recoil 기반

🔬 검증 환경

Docker 불필요. Node 또는 브라우저 콘솔이면 충분합니다.

node script.js          # 또는 브라우저 DevTools 콘솔
node --use-strict       # 엄격 모드 동작 비교

모든 문서의 💻 실험으로 확인하기 섹션은 콘솔에 그대로 붙여넣어 검증할 수 있습니다.

// this 결정 — 호출 방식이 결정
const o = { x: 1, get() { return this.x; } };
o.get();              // 1  (메서드 호출 → this = o)
const g = o.get; g(); // undefined (일반 호출 → this = undefined / 전역)

// 루프 클로저 — var vs let
for (var i = 0; i < 3; i++) setTimeout(() => console.log(i)); // 3, 3, 3
for (let i = 0; i < 3; i++) setTimeout(() => console.log(i)); // 0, 1, 2

// 강제 변환 — 명세로 분해 가능
[] == ![]            // true  (Ch5-03에서 단계별로 도출)
'' == 0              // true
null == undefined    // true,   null == 0 // false

📖 각 문서 구성 방식

모든 문서는 동일한 구조로 작성됩니다.

섹션 설명
🎯 핵심 질문 이 문서를 읽고 나면 답할 수 있는 질문
🔍 왜 이게 존재하는가 문제 상황과 언어 설계 배경
😱 흔한 오해 또는 잘못된 사용 Before — 많은 개발자가 틀리는 방식
올바른 이해와 사용 After — 명세 수준에서 안 다음의 접근
🔬 내부 동작 원리 ECMAScript 추상 연산 단계 추적 + 다이어그램
💻 실험으로 확인하기 콘솔에 붙여넣을 수 있는 스니펫 + 실행 결과
엔진과 성능 V8 형태(Hidden Class) 안정성, 인라인 캐시 등 언어 의미가 엔진 최적화에 주는 영향
🤔 트레이드오프 이 설계의 장단점, 언제 다른 방법을 택할 것인가
📌 핵심 정리 한 화면 요약
🤔 생각해볼 문제 개념을 더 깊이 이해하기 위한 질문 + 해설

🔗 레포 연결

관계 레포 연결 지점
🤝 시너지 V8 Engine Deep Dive 언어 의미가 엔진 최적화(Hidden Class, Inline Cache)를 좌우
🤝 시너지 Event Loop & Async Deep Dive 비동기 의미론(Promise, microtask)이 언어 위에 얹힘
🤝 시너지 TypeScript Type System Deep Dive 타입 시스템이 JS 런타임 의미 위에서 동작
🧬 수렴 React Deep Dive useState 클로저, 불변성 패턴의 언어적 기반
🧬 수렴 State Management Deep Dive Proxy 기반 반응성(Vue/MobX/Recoil)의 메커니즘

🙏 Reference


⭐️ 도움이 되셨다면 Star를 눌러주세요!

Made with ❤️ by Dev Book Lab


"JS를 쓰는 것과, 명세 수준에서 안다는 것은 다르다"

About

클로저가 무엇을 캡처하고 this가 무엇으로 결정되는지, 명세 수준에서 안다는 것

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors