
2023-03-03
실행 컨텍스트
자바스크립트는 어떻게 실행되는가
소스코드 타입
- 전역 코드
- 전역에 존재하는 소스 코드, 전역에 정의된 함수, 클래스 등의 내부 코드는 포함되지 않는다.
- 함수 코드
- 함수 내부에 존재하는 소스코드, 함수 내부에 중첩된 함수, 클래스 등의 내부 코드는 포함되지 않는다.
- eval 코드
- 빌트인 전역 함수인 eval 함수에 인수로 전달되어 실행되는 소스코드
- 모듈 코드
- 모듈 내부에 존재하는 소스코드, 모듈 내부의 함수, 클래스 등의 내부코드는 포함되지 않는다.
소스코드의 평가와 실행
- 자바스크립트 엔진은 소스코드 평가와 소스코드의 실행 두 가지 과정으로 나누어 처리한다.
소스코드 평가
- 실행 컨텍스트를 생성하고 변수, 함수 등의 선언문만 먼저 실행하여 생성된 변수나 함수 식별자를 키로 실행 컨텍스트가 관리하는 스코프(렉시컬 환경의 환경레코드)에 등록한다.
소스코드의 실행
- 평가가 끝나면 코드가 실행된다. (런타임)
실행 컨텍스트
→ 소스코드를 실행하는데 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역( 스코프 = 식별자 등록&관리 / 코드 실행순서 관리 / 모든 코드는 실행 컨텍스트를 통해 실행 및 관리)
- 전역 코드 평가
- 전역 코드 실행
- 함수 코드 평가
- 함수 코드 실행
// 전역변수 선언 const x = 1; const y = 2; // 함수 정의 function foo (a) { // 지역변수 선언 const x = 10; const y = 20; // 메서드 호출 console.log(a + x + y); // 130 } // 함수 호출 foo(100); // 메서드 호출 console.log(x + y); // 3
- 코드가 실행되려면 스코프, 식별자, 코드 실행순서 등의 관리가 필요하다.
- 선언에 의해 생성된 모든 식별자(변수, 함수, 클래스 등)를 스코프를 구분하여 등록하고 상태변화 (식별자에 바인딩된 값의 변화)를 지속적으로 관리할 수 있어야 한다.
- 스코프는 중첩 관계에 의해 스코프 체인을 형성해야 한다. 즉, 스코프 체인을 통해 상위 스코프로 이동하며 식별자를 검색할 수 있어야 한다.
- 현재 실행 중인 코드의 실행 순서를 변경(함수 호출에 의한 실행 순서 변경)할 수 있어야 하며 다시 되돌아갈 수 있어야 한다.
스택
- 스코프와 식별자는 렉시컬 환경으로 관리하고 스택으로 순서를 관리한다.
- 실행 컨텍스트 스택의 최상 위에 존재하는 실행 컨텍스트는 언제나 현재 실행 중인 코드의 실행 컨텍스트이다.
const x = 1; function foo () { const y = 2; function bar () { const z = 3; console.log(x + y + z); } bar(); } foo(); // 6
- 전역 코드의 평가와 실행 ( 전역변수 x, 함수 foo() )
- foo 함수 코드의 평가와 실행 ( 전역 코드 실행 일시 중단, foo 내부 코드)
- bar 함수 코드(중첩 함수)의 평가와 실행 (foo 함수 코드 실행 일시 중단, bar 내부 코드)
- foo 함수 코드로 복귀
- 전역 코드로 복귀
렉시컬 환경
- 식별자와 실별자에 바인딩된 값, 그리고 상위 스코프에 대한 참조를 기록하는 자료구조 (실행 컨텍스트 구성 컴포넌트)
- 실행 컨텍스트 스택 (코드 실행 순서 관리) ↔ 렉시컬 환경 (스코프와 식별자 관리)
- 키와 값을 갖는 (객체 형태)스코프를 생성하여 식별자를 키로 등록하고 식별자에 바인딩 된 값을 관리
구성
- 환경 레코드
- 스코프에 포함된 식별자 등록, 등록된 식별자에 바인딩 된 값 관리 저장소
- 외부 렉시컬 환경 참조
- 상위 스코프를 참조 (해당 실행 컨텍스트를 생성한 소스코드를 포함하는 상위 코드의 렉시컬 환경) / 스코프 체인 형성 (단방향 링크드 리스트)
실행 컨텍스트 생성과 식별자 검색 과정
- 전역 객체 생성
- 전역 코드 평가
- 전역 코드 실행
- foo 함수 코드 평가
- foo 함수 코드 실행
- bar 함수 코드 평가
- bar 함수 코드 실행
- bar 함수 코드 종료
- foo 함수 코드 종료
- 전역 코드 실행 종료
var x = 1; const y = 2; function foo (a) { var x = 3; const y = 4; function bar (b) { const z = 5; console.log(a + b + x + y + z); } bar (10); } foo(20); // 42
- 비어있는 전역 실행 컨텍스트를 생성하고 스택에 푸쉬
- 전역 렉시컬 환경 생성, 전역 실행 컨텍스트에 바인딩
- 전역 환경 레코드 → 객체 환경 레코드, 선언적 환경 레코드 / this 바인딩
- 외부 렉시컬 환경 참조 결정
💡 함수를 어디서 호출했는지가 아니라 어디서 정의했는지에 따라 상위 스코프를 결정!
식별자 결정
- 동일한 이름의 식별자가 다른 스코프에 존재 할 수도 있다. 어느 스코프의 식별자를 참조하면 되는지 결정해야 한다.
- 식별자 결정을 위한 탐색은 실행 중인 실행 컨텍스트에서 시작한다.
console.log
- console 식별자 검색
- 외부 참조 → 전역 참조 → 전역 객체 환경 레코드(binding object)
- log 메서드 검색
- console 식별자에 바인딩 된 객체 (console 객체에서 log 메서드 검색)
댓글을 불러오는 중입니다.

CSR vs SSR
CSR? SSR? 뭐가 더 좋을까

클로저
클로저 제대로 알아보기