JS 실행컨텍스트 (Execution Context)

Philip Yoon·2021년 3월 29일
4
post-thumbnail

컨텍스트?

실행 컨텍스트 찾아보기에 앞서 실행 컨텍스트를 한국말로 번역을 해보자면 실행문맥이라는 말이된다.
그럼 실행할 수 있는 단락? 문맥이란 말일까?
컴퓨터에서 컨텍스트를 찾아보았다. (Wiki)

컴퓨터 과학에서 작업 컨텍스트 는 작업이 중단 되고 나중에 동일한 지점에서 계속 될 수 있도록 저장해야하는 작업 ( 프로세스 , 스레드 일 수 있음)에 사용되는 최소한의 데이터 집합입니다 . 컨텍스트의 개념은 인터럽트 가능한 작업의 경우 중요하다고 가정하며, 인터럽트되면 프로세서는 컨텍스트를 저장하고 인터럽트 서비스 루틴을 제공합니다 . 따라서 컨텍스트가 작을수록 지연 시간이 줄어 듭니다.
컨텍스트 데이터는 프로세서 레지스터 , 작업에서 사용하는 메모리 또는 일부 운영 체제 에서 작업을 관리하는 데 사용하는 제어 레지스터에 있을 수 있습니다 .

즉 컴퓨터에서의 컨텍스트란 하나의 작업이라고 정의할 수 있겠다.

실행 컨텍스트?

그렇다면 js에서 말하는 실행 컨텍스트란 무엇일까?
코어 자바스크립트 책에서 실행컨텍스트란 다음과 같이 이야기하고있다.

실행 컨텍스트란 실행할 코드에 제공할 환경 정보들을 모아놓은 객체로서, 동일한 스코프에 있는 코드들을 실행할 때 필요한 환경 정보를 모아 컨텍스트를 구성하고, 이를 호출 스택(콜 스택)에 쌓아서 실행 순서를 보장합니다.

실행 컨텍스트가 구성되는 요소는 다음과 같이 구성됩니다.

  • 변수 객체(arguments, variable)
  • scope chain
  • this

그렇다면 실행 컨텍스트의 종류는 무엇이 있을까요?
실행 컨텍스트는 다음과 같이 3가지 종류로 나뉘어집니다.
-전역 컨텍스트: 특정 함수가 실행되지 않는 한 전역 컨텍스트에서 실행됩니다.
여기서 변수 객체를 생성하는 대신 this를 전역 객체(global object)를 활용한다.

-함수 컨텍스트: 함수가 실행될 때마다 실행 컨텍스트가 생성되고, 함수가 동작을 다하면 콜스택에서 삭제된다.

-eval 함수 실행 컨텍스트: eval함수도 자신만의 실행 컨텍스트를 가진다.

전역 공간과 악마로 취급받는 Eval을 제외하면 실제로 실행 컨텍스트를 구성하는 방법은 함수 컨텍스트 뿐입니다. 이번 포스팅에서는 실행 컨텍스트가 어떻게 콜스택에 쌓이고 해결되는지, 전역컨텍스트와 함수 컨텍스트는 무엇인지 알아보도록 하겠습니다. Eval의 경우 사용하지 말라는 의견이 있기에 Eval은 제외하겠습니다. (Eval을 사용하지 말아야하는 이유)
Eval에 대한 반대 의견도 있습니다.(Eval isn't evil)

전역 컨텍스트 & 함수 컨텍스트 구성요소

코드를 통해 전역 컨텍스트,함수 컨텍스트가 어떻게 구성되는지 알아보도록 합시다.

var name = '그루트'
function callName (text) {
  console.log(text + name)
}
function hey () {
  var name = '아이언맨'
  callName('I am')
}
hey() 
// result: I am 그루트

위의 코드에서의 전역 컨텍스트와 함수 컨텍스트는 다음과 같이 분리 될 수 있습니다.

{ // 전역 컨텍스트
  '변수 객체': {
    arguments: null,
    variable: [ 'name', 'callName', 'hey' ]
  },
  scopeChain: [ '전역 변수 객체' ],
  this: window
}
{ // hey 함수 컨텍스트
  '변수 객체': {
    arguments: null,
    variable: [ 'name' ]
  },
  scopeChain: [ 'hey 변수 객체', '전역 변수 객체'],
  this: window
}
{ // callName 함수 컨텍스트
  '변수 객체': {
    arguments: [{ text: 'I am' }],
    variable: null
  },
  scopeChain: [ 'callName 변수 객체', '전역 변수 객체'],
  this: window
}

결과값이 I am 아이언맨이 아닌 I am 그루트가 나오는것은 스코프체인에 의해 callName에서 name을 찾을 수 없기 때문에 전역으로 설정된 그루트가 나오게 되는것입니다.

실행 컨텍스트 & 콜스텍

이번에는 아래 코드를 보며 실행 컨텍스트가 콜 스택에 어떤 순서로 쌓이고 사라지는지 살펴보겠습니다.

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

가장 먼저 자바스크립트 파일이 열리는 순간 전역 컨텍스트가 활성화됩니다. 따라서 전역 컨텍스트가 콜 스택에 쌓입니다. 그리고 outer 함수가 호출되면 자바스크립트 엔진은 outer에 대한 환경 정보를 수집해서 outer 실행 컨텍스트를 생성한 후 콜스택에 담습니다. 전역 컨텍스트와 관련된 코드의 실행을 중단하고 outer 실행 컨텍스트와 관련된 코드를 순차적으로 실행합니다. 다시 inner 함수의 실행 컨텍스트가 콜 스택의 가장 위에 담기면 outer 컨텍스트는 중단하고 inner 함수 내부 코드를 진행합니다. 실행이 종료되면 콜 스택에서 제거되고 그 다음 순서에 있는 코드를 이어서 진행합니다.

위의 설명으로 실행 컨텍스트가 어떻게 콜스택에 쌓이게 알 수 있었습니다. 해당 내용들은 Variable Environment와 Lexical Environment에 저장되고 참조되는데 이것은 다른 포스팅에서 알아보도록 하겠습니다.
위의 코드를 run js 에서 실행 해보면 inner function :: undefined가 나오는것을 확인할 수 있습니다.
undefined가 나오는 이유는 inner 컨텍스트에서 a를 탐색했지만 이미 inner 컨텍스트 안에 var a = 3 이라는 식별자가 존재하므로 스코프 체인 검색을 더 진행하지 않고 inner 컨텍스트 상의 a를 반환하게 됩니다. 즉 inner 함수 내부에서 a 변수를 선언했기 때문에 전역 컨텍스트에서 선언한 a변수에 접근할 수 없는것입니다. 이것을 변수 은닉화 라고 하는데 이것은 다음 포스팅에서 알아보도록 하겠습니다. ( inner function에서 a를 출력하고 싶다면 var a = 3 을 삭제하면 정상적으로 출력되는것을 확인 할 수 있습니다. )

참고

MNIII의 Execution Context 실행 컨텍스트
Execution context, Scope chain and JavaScript internals
휴먼스케이프 기술 블로그
코어 자바스크립트 책

profile
FE 개발자 윤현준입니다.

0개의 댓글