관리 메뉴

bright jazz music

자바스크립트의 실행 컨텍스트 1 (실행 컨텍스트의 기본 개념) 본문

Language/Javascript

자바스크립트의 실행 컨텍스트 1 (실행 컨텍스트의 기본 개념)

bright jazz music 2024. 11. 13. 18:45

 

1. 실행 컨텍스트(excution context)

: 실행할 코드에 제공할 환경 정보들을 모아놓은 '객체'.

 

- 동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성한다.

- 이를 콜 스택에 쌓아 올렸다가 가장 위에 쌓여 있는 컨텍스트와 관련 있는 코드들을 실행하는 식으로 전체 코드의 환경과 순서를 보장한다.

 

'동일한 환경'이란 하나의 실행 컨텍스트를 구성할 수 있는 방법을 의미하며, 전역공간, eval(), 함수 등이 있다. 자동으로 생성되는 전역공간과 eval을 제외한다면, 실제적으로 컨텍스트를 구성하는 방법은 함수를 실행하는 것밖에 없다.

//------------------------------------(1)
var a = 1;
function outer() {
    function inner() {
    	console.log(a);	// undefined
        var a = 3;
    }
    
    inner(); //-----------------------(2)
    console.log(a);	// 1	
}

outer();	//------------------------(3)
console.log(a);		// 1

 

위 코드를 실행하면,

 

1) 전역 컨텍스트가 콜스택에 담긴다.

: 코드를 실행하면 (1)번 구간의 상황이 되며, 전역 컨텍스트가 콜스택에 담긴다. 전역 컨텍스트는 일반적인 실행 컨텍스트(코드 실행을 위한 환경 정보 객체)와 특별히 다를 것이 없다. 최상단의 공간은 코드 내부에 별도 실행 멸령이 없어도 브라우저에서 자동 실행한다. 따라서 자바스크립트 파일이 열리는 순간 전역 컨텍스트가 활성화 된다고 이해하면 된다.

 

2) outer함수 호출 -> outer 실행 컨텍스트 생성 후 콜스택 담기 -> outer함수 내부 코드 실행

: 콜스택에는 전역 컨텍스트 외에 다른 덩어리가 없다. 따라서 전역 컨텍스트와 관련된 코드들을 순차로 진행한다. 그러다가 (3)번 구간에서 outer()함수를 만나면 자바스크립트 엔진이  outer 환경정보를 수집해서 outer실행 컨텍스트를 생성한 후 콜 스택에 담는다. 이제 콜 스택의 맨 위에 outer 실행 컨텍스트가 놓인 상태(outer컨텍스트 아래에 전역 컨텍스트)가 됐으므로 전역 컨텍스트와 관련된 코드의 실행을 일시 중지하고 대신 outer함수 내부의 코드들을 순차로 실행한다.

 

3) inner 함수 호출 -> inner 컨텍스트 생성 후 콜스택 담기 -> inner 함수 내부 코드 실행

: outer함수의 내부 코드를 실행하다가 (2)번 지점에서 inner() 함수를 만나게 된다.  자바스크립트 엔진이 inner함수와 관련된 환경 정보를 수집해서 실행 컨텍스트를 생성한 후 콜스택에 담는다. 이와 동시에 outer 컨텍스트와 관련된 코드의 실행(즉, outer 함수의 내부 코드 진행)을 중지하고 inner함수의 컨텍스트와 관련된 코드(inner함수 내부 코드)를 실행한다.

 

 

4) inner함수 종료 -> 콜스택에서 inner 실행 컨텍스트 제거

: inner함수의 마지막 줄은 a 변수에 3을 할당하는 것이다. 이를 완료하고 나면 함수의 실행이 종료되고, 그와 함께 inner 실행 컨텍스트가 콜스택에서 제거된다.

 

5) outer 함수 코드 실행 재개

: inner의 실행 컨텍스트가 콜스택에서 제거됨에 따라 실행이 중지된 채 inner컨텍스트에서 대기하던 outer컨텍스트가 콜스택의 맨 위에 존재하게 된다. 따라서 (2) 지점에서부터 코드 실행을 재개한다. 이 때 a를 출력(출력값은 1이다. 3이 아니다)

 

6) outer함수 종료 -> 콜스택에서 outer실행 컨텍스트 제거

: 마지막 코드가 실행됨에 따라 콜스택에서 outer 컨텍스트가 제거된다.

 

7) 전역 컨택스트 코드 실행 재개

: outer 실행 컨텍스트가 콜스택에서 제거됨에 따라 전역 컨텍스트만이 콜스택에 남아있게 된다. 따라서 (3) 지점에서 멈춰 있던 코드 실행이 재개되며, a의 값을 출력함으로써 코드 실행을 종료한다 ( 이때의 출력값은 1이다)

 

8) 전역 컨텍스트 관련 코드 실행 종료 -> 콜스택에서 전역 컨텍스트 제거

: a 값을 출력함으로써 전역 컨텍스트와 관련된 코드 수행이 끝나고 전역 공간에 더는 실행할 코드가 남아있지 않게 된다. 따라서 콜스택에서 전역 컨텍스트도 제거된다.

 

 

 

 

* 참고

- inner()함수에서 a를 출력했을 때 undefined가 출력된 것은 호이스팅 때문이다.

자바스크립트에서 변수 선언(var, let, const)과 함수 선언은 코드가 실행되기 전에 해당 스코프의 최상단으로 "끌어올려진다"고 표현한다. 이것이 호이스팅이다.

var 키워드를 사용한 변수 선언의 경우,

  1. 선언과 초기화가 분리됨
    • 선언부(var a)는 해당 스코프의 최상단으로 끌어올려진다.
    • 이때 변수는 undefined로 초기화 된다.
    • 할당부(= 3)는 원래 코드에 있던 위치에서 실행됩니다.
function inner() {
    console.log(a);  // undefined
    var a = 3;
}

자바스크립트 엔진은 실제로는 이 코드를 아래와 같이 해석한다

function inner() {
    var a;           // 선언이 최상단으로 호이스팅되고 undefined로 초기화
    console.log(a);  // undefined 출력
    a = 3;           // 이 시점에서 값이 할당됨
}

 

이것은 자바스크립트의 독특한 특성 중 하나이며 직관적으로 예상하지 못한 동작을 일으킬 수 있어 주의해야 한다. 이러한 이유로 최신 자바스크립트에서는 변수 선언에 let과 const를 사용하는 것이 권장된다. 이들은 호이스팅은 되지만 초기화 전에 접근하면 참조 에러(TDZ, Temporal Dead Zone)가 발생한다. 즉, var를 사용하면 undefined를 반환지만 그것이 에러는 아니기 때문에 간과할 수 있는 반면, let이나 const를 사용하는 경우, 초기화 되지 않은 변수에 접근했을 때 에러(ReferenceError: Cannot access '변수명' before initialization)을 반환하기 때문에 해당 시점에 문제를 해결할 수 있다는 것이다.

 

- outer함수에서 출력한 a의 값이 1인 이유는 스코프 때문이다.

inner 함수의 지역 변수 a는 outer 함수의 스코프에 영향을 주지 않고, outer 함수는 자신의 스코프에서 a를 찾지 못해 전역 스코프의 a(값은 1)를 참조한다.

Comments