Language/Javascript

[Javascript] 실행 컨텍스트

Jinn 2024. 9. 25. 23:39
목차

1. 소스코드
    1.1 소스코드의 종류
    1.2 소스코드의 평가와 실행
2. 실행 컨텍스트
    2.1 실행 컨텍스트 스택
    2.2 변수 호이스팅

 

1. 소스코드

1.1 소스코드의 종류

ECMAScript 사양은 4가지 소스코드가 있다.

  • 전역 코드: 전역에 존재하는 소스코드
  • 함수 코드: 함수 내부에 존재하는 소스코드
  • eval 코드: 빌트인 전역 함수인 eval 함수에 인수로 전달되어 실행되는 소스코드
  • 모듈 코드: 모듈 내부에 존재하는 소스코드

소스코드의 종류에 따라 생성하는 실행 컨텍스트가 다르다.
 

1.2 소스코드의 평가와 실행

자바스크립트 엔진은 소스코드를 소스코드 평가소스코드 실행 두 과정으로 나누어 처리한다.
 
소스코드 평가 과정에서는 실행 컨텍스트를 생성하고 변수, 함수 등의 선언문만 먼저 실행하여 생성된 변수나 함수를 키로 실행 컨텍스트가 관리하는 스코프에 등록한다.
 
소스코드 실행 과정은 선언문을 제외한 소스코드가 순차적으로 실행되는 것이다. 이때 실행에 필요한 변수나 함수 정보를 실행 컨텍스트에서 얻는다. 소스코드의 실행 결과(변수 값 변경 등)는 다시 실행 컨텍스트의 스코프에 등록된다.
 

var x;
x = 1;

위 소스코드를 자바스크립트 엔진은 설명한 대로 평가와 실행 두 과정으로 나누어 처리한다.
평가 과정에서 변수 선언문인 var x;가 먼저 실행되고 실행 컨텍스트가 관리하는 스코프에 등록된다. 이때 초기값은 undefined이다.

평가 과정이 끝나면 실행 과정이 시작된다. 선언문을 제외한 x = 1;이 실행된다.
이때 변수 x가 선언된 변수인지 확인한다. 즉 실행 컨텍스트의 스코프에 변수 x가 등록되어 있는지 확인한다.
변수 x가 선언된 변수라면 값을 할당하고 그 결과를 실행 컨텍스트의 스코프에 등록한다.


2. 실행 컨텍스트

2.1 실행 컨텍스트 스택

앞에서 계속 등장한 실행 컨텍스트는 소스코드를 실행하는 데 필요한 환경을 제공하고 코드의 실행 결과를 관리하는 영역이다. 여기서 소스코드를 실행하는 데 필요한 환경이란 식별자(변수, 함수, 클래스 등)를 의미한다.
 
소스 코드의 실행 순서는 실행 컨텍스트 스택으로 관리한다.
자바스크립트 엔진은 전역 코드를 먼저 평가하여 전역 실행 컨텍스트를 생성한다. 이후 함수가 호출되면 함수 내부를 평가하여 함수 실행 컨텍스트를 생성한다. 이렇게 생성된 실행 컨텍스트들은 스택 구조로 관리된다.

const x = 1;

function func1 () {
    const y = 2;
    
    function func2 () {
        const z = 3;
        console.log(x + y + z);
    }
    func2();
}
func1();

위 코드가 실행되면 실행 컨텍스트 스택은 아래와 같은 과정을 거친다.

  1. 전역 코드를 평가하여 전역 실행 컨텍스트가 스택에 추가된다. 전역 변수 x와 전역 함수 func1은 전역 실행 컨텍스트에 등록된다. 평가가 끝나고 실행 과정이 시작되면 전역 변수 x에 1이 할당되고 전역 함수 func1이 호출된다.
  2. 함수 func1이 호출되면 코드 실행이 중지되고 func1 함수 내부로 이동한다. func1 내부 코드를 평가하여 func1 함수 실행 컨텍스트를 생성하여 스택에 추가한다. func1 함수의 지역 변수 y와 중첩 함수 func2가 func1 함수 실행 컨텍스트에 등록되고, 평가가 끝나면 실행 과정에서 변수 값이 할당되고 함수 func2가 호출된다.
  3. 함수 func2가 호출되면 2번 단계와 동일하게 func2 함수의 내부를 평가하고 실행한다. 이 과정에서 func2 함수 실행 컨텍스트가 생성되어 스택에 추가된다. 이후 console.log 메서드를 호출하고 func2 함수는 종료된다.
  4. 함수 func2가 종료되면 코드 흐름은 다시 함수 func1로 돌아온다. 이때 func2 함수 실행 컨텍스트가 스택에서 제거된다. 함수 func2 호출 이후에 실행될 코드가 없으므로 함수 func1도 종료된다.
  5. 함수 func1이 종료되면 코드 흐름은 다시 전역 코드로 돌아온다. 이때 func1 함수 실행 컨텍스트가 스택에서 제거된다.  함수 func1 호출 이후에 실행될 코드가 없으므로 전역 실행 컨텍스트도 스택에서 제거된다.

이렇게 실행 컨텍스트 스택을 통해 코드의 실행 순서를 관리한다. 가장 위에 있는 컨텍스트를 실행 중인 실행 컨텍스트라고 한다.
 

2.2 변수 호이스팅

console.log(x);
var x = 1;

위 코드의 실행 결과는 undefined가 출력된다.
console.log(x);가 실행되는 시점에는 아직 변수 x가 선언되지 않았으므로 참조 에러가 발생할 것처럼 보이지만 undefined가 출력된 것이다. 그 이유는 처음에 설명한 대로 자바스크립트 엔진은 소스코드를 평가와 실행 두 단계로 나누어 처리하기 때문이다. 평가 단계에서 이미 변수 x는 실행 컨텍스트에 undefined로 초기화되었기 때문에 undefined로 출력된 것이다. 이후에 실행 단계에서 변수 x가 1로 초기화되면서 실행 컨텍스트에도 1로 등록된다.
 
이처럼 자바스크립트는 변수 선언의 위치에 상관없이 어디서든 변수를 참조할 수 있다. 이렇게 변수 선언이 코드의 상단으로 끌어올려진 것처럼 동작하는 특징을 변수 호이스팅이라고 한다. 호이스팅은 변수뿐만 아니라 선언하는 모든 식별자(변수, 함수, 클래스 등)에 해당되는 개념이다. 모든 선언문은 런타임 이전에 실행된다.