실행 컨텍스트

설영환·2020년 11월 18일
0

들어가기전

여기서는 2020년 현재 기준 실행컨텍스트를 설명하고 있습니다. es5 중간에 실행컨텍스트가 한번 크게 변했고 나중에도 언제 변할지 모릅니다. 이글은 최신의 실행컨텍스트 설명뿐만 아니라 es5 이전의 실행컨텍스트도 설명에 들어있습니다. es5 이전과 이후 실행컨텍스트 모두의 이해는 어렵지만 이전의 실행컨텍스트의 이해가 조금더 쉽다고 생각되어 먼저 설명을 해놓았으니 이전의 실행컨텍스트의 글을 같이 읽고 es5이후의 실행컨텍스트를 읽으시면 이해가 더 쉬우실거 같습니다. 넘어가고 싶으시다면 es5이후의 실행컨텍스트를 찾아서 읽으시면됩니다. 다만 이 글은 하나의 쭉 이어진 글로 작성되어 흐름이 끊어질수는 있습니다.

실행 컨텍스트란?

context는 한글로 문맥 입니다. 문맥이란 사전에서 정의되길 글월에 표현된 의미의 앞뒤 연결 이라는 뜻입니다.

Execution Context(실행 컨텍스트)는 자바스크립트에서 실행되는동안의 문맥, 즉 순서와 내용 이것들을 담고있는 객체를 의미합니다.

프로그래밍은 어떤것이 실행되게 하는 순서와 행동을 미리 정해놓고 그것을 상황이 되면 실행시키게 하는 것을 말합니다. 자바스크립트에도 실행시에 실행되는 순서와 행동이 있다고 생각하시면 될거같습니다. 이 순서와 행동이 있고 이러한 정보들을 저장해 놓는 곳들을 모아둔곳이 실행 컨텍스트입니다.

아직은 글로만 되어있어서 이해가 어렵지만 지금은 넘어가셔도 됩니다.

실행컨텍스트의 종류

실행컨텍스트에는 크게 두종류가 있습니다. 전역컨텍스트함수컨텍스트!

이 둘은 거의 비슷한 모양을 지니고있습니다. 이후 설명할 내용에서 다루겠지만 크게

생성 시점,arguments object의 유무, this의 값(같을수도 다를수도 있습니다.),인자의 유무 정도로 보면 될거 같습니다.

차이 관련해서는 이후 내용에서 자연스럽게 나올것이기 때문에 실행컨텍스트는 두가지가 있고 차이는 저렇게 두개구나 하고 넘어가셔도 될거같습니다.

(여기서 실행컨텍스트중에 eval 실행컨텍스트는 다루지 않습니다. eval도 비슷하게 실행컨텍스트가 생성되지만 eval함수 자체는 안티패턴으로 인식되기때문에 이후에는 언급되지 않습니다.)

실행컨텍스트의 순환주기(Life Cycle)

  • 라이프사이클이라는 용어는 명세에 없지만 순환주기에 어울리기에 제목으로 삼았습니다.
function foo(){
	function bar(){
		console.log("bar");
	}
}

위 함수에 대한 실행 컨텍스트 순환주기

실행컨텍스트는 웹이 실행되면 전역 실행컨텍스트(Global Execution Context)가 먼저 생성됩니다. 이후에 함수가 생성될때마다 함수 실행컨텍스트(Function Execution Context)가 생성이 되어 FILO(first in last out / stack)으로 쌓이게 됩니다. 그래서 제어권은 가장 나중에 들어온 함수의 실행 컨텍스트로 이동합니다. (함수 실행컨텍스트와 전역실행 컨텍스트의 차이점 첫번째입니다.)

여기서 실행 컨텍스트는 두가지 단계를 거쳐서 생성됩니다.

  1. Creation Phase(생성단계)
  2. Execution Phase(실행단계)

1번단계는 생성은 했지만 컴파일 단계라서 스캔하는 단계입니다.

(실행컨텍스트에서는 중요하진 않으니 넘어가셔도 됩니다. )

위의 단계는 ES5이후에 실행컨텍스트의 구조를 설명하기 위해 간단히 언급했습니다.

이후 함수의 실행이 끝나면 실행컨텍스트는 사라지게 되고 이전에 생성되었던 실행컨텍스트로 제어권이 넘어가게 됩니다. (실행컨텍스트는 사라지지만 함수들의 객체및 정보들은 남아있어서 closure가 가능하게 됩니다. 이는 다음에 설명하겠습니다.)

실행 컨텍스트의 내부

es5이전의 실행 컨텍스트에는 물리적으로 크게 세가지의 값을 포함한 객체로 이루어져 있었습니다. 각 값에는

  1. 변수 객체(Variable Object)
  2. Scope Chain(스코프 체인)
  3. this의 값(thisValue)

세가지로 구성이 되어있습니다. 아래에서 더 자세하게 설명하겠습니다.

es5 이후의 실행컨텍스트는 위 세가지 설명후에 바뀐부분의 설명과 함께 설명하겠습니다.

1. 변수객체(Variable Object)

변수객체에는 총 세가지의 값이 호이스팅으로 먼저 선언이 됩니다. (Hoisting에 관련해서는 나중에 변수관련 블로깅에서 다루겠습니다.)

  1. 변수
  2. 함수
  3. 매개변수 및 인수정보

변수는 변수객체가 생성될 때 선언만되어 저장이 됩니다. 그리고 함수는 선언식으로 선언이 되었다면 Hoisting이 되어 선언이 됩니다. 표현식일때는

var boo = function(){ ... } 

위의 부분중에 var boo부분인 앞부분만 선언이되어 저장이 됩니다.(Hoisting부분에서 더 자세히)

  • 전역컨텍스트에서의 변수객체

전역컨텍스트의 변수객체는 전역객체(Global Object / GO)를 가르키고 있습니다. 이 전역객체 안에는 전역변수와 전역 함수를 프로퍼티로 가지고 있습니다. 그리고 함수가 아니기 때문에 인수와 매개변수는 존재하지 않습니다.

브라우저 환경에서는 window 객체가 전역객체이고, nodejs에서는 global 객체입니다.

  • 함수 컨텍스트에서의 변수객체

함수 컨텍스트에서의 변수객체는 활성객체(Activation Object / AO)를 가르키며 변수, 함수 뿐만아니라 전역객체와는 다르게 인수및 매개변수들의 정보를 배열로 담고있는 argument object도 추가됩니다.

3. 스코프 체인(Scope Chain / SC)

스코프체인은 리스트(배열)의 형태로 함수의 scope를 차례로 저장하고 있습니다.

0번에는 자기자신의 활성객체(AO)를 넣고 1번엔 다음 활성객체를 넣고 계속되다가 배열의 마지막에는 전역객체를 넣게 됩니다.

스코프 체인을 이용해서 변수를 참조해야될때는 자신의 활성화 객체를 먼저 참조하고 그다음 1번 활성화 객체 다음순서로 하여 전역객체까지 참조합니다.

이때, 중간에 변수를 찾았다면 더 이상 찾지 않고 그 참조값을 이용합니다.

위의 그림처럼 0번에 있는것을 먼저 참조하고 1번을 참조하여 상위 컨텍스트를 참조합니다.

3. this의 값(thisValue)

this의 값은 각 실행컨텍스트의 this의 값이 할당이됩니다. 전역 실행컨텍스트의 경우에는 global/window 객체를 가르키고 나머지는 할당되는 값을 가르킵니다.

this의 경우에는 따로 블로깅을 하도록 하겠습니다.

4. ES5 이후의 실행 컨텍스트의 내부

es5때 실행 컨텍스트의 내부가 변경되었습니다. 이후에도 변경될수도 있습니다. 하지만 블로그를 쓴 시점을 기준으로 작성해보겠습니다. 이전까지의 실행 컨텍스트는 이해를 위하여 작성하였습니다. 간단하게 알고 넘어가고 싶다면 여기서 정지 하셔도 좋습니다. 이 이후는 이해하기 어려운 개념들이 많아서.. 이전까지의 개념은 제가 쉽게 설명하기위해 정리해보았지만 이후는 제가 쉽게 하기위해 정리하는게 쉽지않을거같습니다.

일단 실행컨텍스트의 내부에는 총 두가지의 값을 가진 객체로 이루어져 있습니다.

{
	LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative",
      // let, const, function etc.
    }
    outer: <Global or outer function environment reference>,
    this: <depends on how function is called>
  }
	VariableEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative",
      // var 
    }
    outer: <Global or outer function environment reference>,
    this: <depends on how function is called>
  }
}

위의 코드처럼

  • LexicalEnvironment
  • VariableEnvironment

두개의 객체로 이루어져 있습니다.

각 객체는 모양은 같게 생겼지만 하는 일이 다릅니다.

공통점을 먼저 살펴보고 차이점을 살펴보겠습니다.

공통점

생성 단계(Creation phase)에서 EC가 생성되면, 엔진은 해당 컨텍스트에서 실행에 필요한 여러 가지 정보를 담을 객체를 생성합니다. 위에 객체를 적어놓은 것처럼 실행컨텍스트에 저장되고 이를 활성 객체(변수 객체)라고 합니다.

그 안에는 여러가지 정보들이 들어있습니다.

  1. 스코프 체인
  2. arguments 객체 생성
  3. 변수의 생성 (할당 말고)
  4. this 의 바인딩

Environment Record 안쪽에 타입과 변수, 함수 등의 참조값이 저장되어있습니다. 그리고 global, window객체가 아니면 argument도 같이 저장되어 있습니다.

(변수의 생성-호이스팅 관련)

outer에는 글로벌 객체 또는 바깥쪽의 함수 들의 참조값을 저장하고 있습니다. 이를 이용하여 es5이전 실행컨텍스트의 Scope chain을 대체합니다.

this는 각각 존재합니다. 그리고 this의 설정 기준에 따라 this가 객체로 저장되어 있습니다.(이는 나중 this를 블로깅해서 더 자세히 설명하겠습니다.)

차이점

차이점으로는 모양자체는 크게 다르지 않지만 사용되는 곳은 다릅니다

  • LexicalEnvironment

이 객체에서는 let, const의 변수,객체 및 함수의 참조값을 실행컨텍스트가 생성되는순간 hoisting합니다.

snapshot으로 저장되는 것이 아니라서 변동이 가능합니다. 변수의 저장과 저장 과정등은 hoisting에서 따로 bloging하도록 하겠습니다.

  • VariableEnvironment

이 객체에는 var 의 변수 및 객체 를 실행컨텍스트가 생성되는 순간 hoisting합니다.

이 객체는 snapshot으로 저장되어 변동이 불가능합니다. 변수의 저장등은 lexical과 마찬가지로 따로 글을 쓰겠습니다.

마무리

실행 컨텍스트는 자바스크립트의 기본이면서 제일 어려운 대상입니다. 자바스크립트가 실행되고 자바스크립트에서 함수의 실행이 어떻게 진행되는지 설명하기 위한 제일 첫번째 대상이라 일주일 넘게 자료찾기 및 초고를 작성했습니다. 중간에 빠진 부분도 많지만 빠진부분은 나중에 다른 글로써 다시 올라갈 예정입니다.

참조(Reference)

ECMAscript SPEC - 실행 가능한 코드 및 실행 컨텍스트

PoiemWeb - 실행 컨텍스트와 자바스크립트의 동작 원리

miffy님의 벨로그 - 실행 컨텍스트

profile
Frontend 를 목표로합니다.

0개의 댓글