프로그래밍/JavaScript

[JS] 실행 컨텍스트

mhko411 2021. 7. 7. 07:58
728x90

자바스크립트 엔진은 소스코드를 어떻게 실행할까? 소스코드가 정상적으로 실행되기 위해서는 신경써줘야 할 것들이 많다. 선언한 변수를 찾을 수 있어야하고 함수가 실행되고 종료되었을 때 함수가 호출된 시점으로 돌아갈 수도 있어야한다. 자바스크립트 엔진은 실행 컨텍스트를 통해 소스코드가 실행하는 데 필요한 환경을 만들어주고 관리한다.


자바스크립트 엔진은 소스코드를 평가하고 실행한다.

자바스크립트 엔진은 소스코드를 평가하고 실행하는 2개의 과정을 거치게된다. 평가 과정에서는 선언문으로 작성한 변수와 함수에 대한 식별자를 실행 컨텍스트가 관리하는 스코프에 등록한다. 이어서 소스코드를 순차적으로 실행하게 된다. 실행 과정에서는 평가 과정에서 변수와 함수의 식별자를 등록한 스코프에서 필요한 것을 검색한다.

 

또한 자바스크립트는 소스코드를 전역 코드, 함수 코드, eval 코드, 모듈 코드로 크게 4가지로 구분한다. 왜냐하면 각각 소스코드의 타입마다 실행 컨텍스트를 생성하고 관리하는 것이 다르기 때문이다.

 

실행 컨텍스트의 역할

실행 컨텍스트는 소스코드가 실행되는 환경을 구성하고 결과를 관리하는 역할을 한다. 

- 모든 식별자에 대한 상태변화를 지속적으로 관리한다.

- 스코프 체인을 통해 식별자를 검색할 수 있도록 한다.

- 함수가 종료되었을 때 함수가 호출된 시점으로 돌아갈 수 있도록 한다.

 

이렇게 소스코드가 정상적으로 실행되기 위한 실행 컨텍스트의 역할을 콜 스택렉시컬 환경으로 나눌 수 있다.

 

콜 스택

자바스크립트에서 소스코드의 흐름을 스택 자료구조를 활요하는 콜 스택(실행컨텍스트 스택)을 활용한다. 스택은 가장 늦게 저장한 데이터가 가장 먼저 나오는 FIFO의 특징을 갖고있다. 그렇다면 콜 스택이 소스코드를 어떻게 활용하는지 다음 코드를 보자.

 

먼저 전역 코드가 평가되고 실행될 것이다. 전역 코드가 실행되는 과정에서 apple 함수가 호출이되고 apple 함수 실행 컨텍스트가 평가되고 실행된다. 또한 apple 함수 내에서 banana 함수가 호출되기 때문에 banana 함수 실행 컨텍스트가 실행된다.

 

banana 함수는 'banana'라는 문자열을 출력한 후에 종료되어 apple 함수로 돌아가고 'apple'이라는 문자열을 출력한 후에 종료된다. 마지막으로 전역 코드의 실행 컨텍스트가 종료된다. 이에 대한 과정을 그림을 통해 콜 스택에서 어떻게 동작하는지 보자.

var a = 1;

function apple() {
    
    function banana() {
        console.log('banana');
    }

    banana();
    console.log('apple');
}

apple();

 

위의 소스코드가 콜 스택에서 실행되는 과정을 그림을 나타낸 것이다.

 

가장 먼저 비어있는 콜 스택에서 전역 코드가 평가되면서 전역 실행 컨텍스트가 생성되고 전역 실행 컨텍스트를 스택에 push한다. 전역 코드가 실행되면서 apple 함수를 호출하게되고 이에따라 apple 함수를 평가하면서 apple 함수 실행 컨텍스트가 생성되고 콜 스택에 push한다. 또한 apple 함수에서 banana 함수를 호출하여 banana 함수를 평가하면서 실행 컨텍스트 생성 후 스택에 push 한다.

 

이제 banana함수가 종료되면서 콜 스택에서 pop이 되며 순서대로 apple 함수도 pop이된다. 이때 콜 스택에서만 제거된 것이고 함수 실행 컨텍스트 자체는 제거되지 않았다. 왜냐하면 다른 곳에서 참조할 수 있기 때문이다.

 

렉시컬 환경

콜 스택이 소스코드의 실행 순서를 관리한다면 렉시컬 환경에서는 식별자를 관리하고 스코프를 구분하는 역할을 한다. 렉시컬 환경은 환경 레코드외부 렉시컬 환경 참조라는 컴포넌트로 구성되어 있다.

환경 레코드는 스코프에 포함된 식별자를 등록하고 식별자에 바인딩된 값을 관리한다. 외부 렉시컬 환경 참조는 해당 렉시컬 환경의 상위 렉시컬 환경을 단방향 링크드리스트로 연결하여 스코프 체인을 구현한다.

 

위에서 구현한 코드를 통해 렉시컬 환경을 이해해보자.

먼저 전역 실행컨텍스트가 생성되어 콜 스택에 push되었다. 이어서 전역 렉시컬 환경을 생성하고 전역 실행 컨텍스트가 이를 가리키게된다. 이어서 전역 환경 레코드를 생성하여 식별자를 관리하게 되는데 전역 환경 레코드는 객체 환경 레코드와 선언적 환경 레코드로 구성되어있다.

객체 환경 레코드는 var 키워드로 선언한 변수 또는 변수 선언문 등을 선언과 초기화가 진행되고 선언적 환경 레코드는 let, const 키워드를 가리키게 된다.

 

지금까지의 상황을 그림으로 보면 다음과 같다.

이어서 전역 코드가 실행되면 전역 렉시컬 환경에서 식별자 검색을 하여 값을 할당하거나 읽게된다. 여기서 apple 함수를 호출하여 apple 함수 평가가 진행된다. 이제 다음과 같이 apple 함수의 렉시컬 환경 중 외부 렉시컬 환경참조가 전역 렉시컬 환경을 가리키게 된다. 

만약 apple 함수에서 어떠한 변수를 참조할 때 apple 함수 내에 정의되어있지 않다면 외부렉시컬 환경참조에서 전역 렉시컬 환경을 검사한다. 이렇게 식별자를 검색해나가는 것을 스코프 체인이라고 한다.

마지막으로 위와 비슷한 과정으로 apple 함수에서 banana 함수를 호출하여 banana함수에 대한 렉시컬 환경이 생성될 것이다.


자바스크립트의 실행 컨텍스트를 알아보며 소스코드가 어떻게 평가되고 실행되는지 알 수 있었다. 이를 이해하는 것이 다른 사람의 코드를 이해하고 좀 더 효율적으로 코드를 작성하는데 많은 도움이 될 것이다. 또한 React, Vue 등의 프레임워크를 더 잘 다룰 수 있을 것이고 이러한 사용도구가 바뀌더라도 쉽게 적응할 수 있을 것이다.

'프로그래밍 > JavaScript' 카테고리의 다른 글

[JS] 함수  (0) 2021.07.19
[JS] Closure  (0) 2021.07.10
[JS] 호이스팅이 발생하는 이유  (0) 2021.07.06
[Vue] 싱글 파일 컴포넌트(SFC)  (0) 2021.05.11
[Vue] computed와 watch  (0) 2021.05.10