[JavaScript] 실행 컨텍스트

eonisal·2023년 9월 10일
0

JavaScript

목록 보기
2/3
post-thumbnail

🎠 실행 컨텍스트(Execution Context)

실행 컨텍스트(Execution Context)는 자바스크립트 코드가 실행되는 환경으로, 실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다.

실행 컨텍스트는 함수가 실행될 때 생성되어 자바스크립트 엔진의 콜스택에 push 되고 함수 실행이 완료되면 pop 되는 LIFO 구조로, 우리가 흔히 알고있는 스택 구조와 같다.

이 스택 구조의 흐름으로, 실행되는 코드에 해당하는 실행 컨텍스트가 적재되어 우리가 실행하는 코드의 scope 별로 실행 순서가 보장된다.

🎫 실행 컨텍스트의 정보

실행 컨텍스트의 정보는 this 포인터, 해당 스코프의 변수들(Variable Object), Scope chain 이 있다.

This

this 포인터에 대해서는 뒤에서 자세히 알아보겠지만 우선 요약하자면 this는 코드가 실행되는 시점의 환경이 가리키는 객체를 의미한다.

어떤 환경(컨텍스트)인지에 따라 this가 의미하는 값이 바뀐다.

Variable Object

Variable Object는 실행되는 코드의 스코프에 있는 변수나 함수, 객체 등의 자원들을 프로퍼티로 하는 객체이다.

function myFunc() {
  let a = 10;
  let b = 20;
  function add(first, second) {
    return first + second;
  }
  return add(a, b);
}

myFunc();

이러한 함수가 있을 때, 이 함수가 호출되어 실행될 때 이 함수의 실행 컨텍스트가 콜스텍에 쌓이고 이때의 variable object는

{
  a: 10,
  b: 20,
  add: function { ... }
}

이러한 객체와 같다. myFunc 함수 내에서 선언된 변수와 함수를 프로퍼티로 갖는 객체이다.

myFunc 함수 내의 add 함수의 경우는 myFunc 함수처럼 let 키워드 등을 이용해 직접적으로 선언된 변수는 없지만 함수가 실행될 때 생성되어 사용하는 변수가 있다. 바로 함수의 인자로 선언된 first와 second이다. 따라서 add 함수의 variable object는

{
  first: 10,
  second: 20,
}

이 된다.

만약 스코프에 선언된 변수나 함수, 객체 등의 자원이 없는 경우 컨텍스트의 Variable Object는 빈 객체가 된다.

Scope chain

Scope chain은 실행되는 코드의 스코프의 상위 스코프들을 순서대로 나타내는 배열이다.

function myFunc() {
  let a = 10;
  let b = 20;
  function add(first, second) {
    return first + second;
  }
  return add(a, b);
}

myFunc();

앞서 살펴본 이 예시의 경우 myFunc 함수의 실행 컨텍스트의 scope chain은 [ global ] 이 된다. 바로 상위의 스코프가 전역 스코프이므로 scope chain 배열의 첫번째 요소로 global이 되고, 이보다 상위 스코프는 없기 때문에 요소는 global 뿐인 배열이 된다.

myFunc 함수 내부의 add 함수의 경우는 바로 상위의 스코프는 myFunc 이고 그 상위 스코프가 global 이므로 scope chain은 [ myFunc, global ] 이 된다.

특정 스코프에서 변수나 함수 등을 사용할 때 해당 컨텍스트의 variable object 에서 필요한 변수를 찾는데, variable object에 찾는 변수가 없는 경우 scope chain의 요소 순서를 참고하여 상위 스코프를 탐색한다.

scope chain의 첫번째 요소에 해당하는 스코프의 컨텍스트의 variable object를 탐색하여 필요한 변수를 찾고, 없으면 scope chain의 다음 요소의 variable object에서 찾고... 이러한 과정을 반복한다.

따라서 찾는 변수가 계속 없어서 상위 스코프로 점점 올라가다보면 최종적으로 global scope에 도달한다. 이 전역 스코프에도 변수가 없으면 해당 변수를 찾을 수 없는 것이기 때문에 에러가 발생하게 될것이다.

🎢 자바스크립트 코드가 실행되는 과정

실행 컨텍스트는 전역에서 시작해 함수가 실행될 때 스택에 쌓이게 된다.

자바스크립트 엔진이 코드를 읽고 실행하면 우선 global scope에 해당하는 환경인 전역 실행 컨텍스트(Global Execution Context)가 콜스택에 쌓이게 된다. 그래서 전역 실행 컨텍스트 환경이 되고 전역 실행 컨텍스트에서 this는 window 객체를 가리킨다(node 환경에서는 global 객체).

그렇기 때문에 우리가 브라우저 환경에서는 window, node.js 환경에서는 global 객체의 프로퍼티들을 바로 사용할 수 있는 것이다.

이렇게 전역 환경이 된 후, 함수가 호출되어 실행될 때마다 그 함수의 함수 실행 컨텍스트(Function Execution Context)가 생성되어 콜스택에 쌓이게 된다. 해당 함수의 this, variable object, scope chain 정보가 있는 컨텍스트 환경이 되어 함수의 내용이 실행되고 함수가 종료되면 이 함수의 컨텍스트는 콜스택에서 pop 되어 사라진다.

이러한 과정을 예시 코드를 들어 그림으로 살펴보자.

// 어떤 코드도 없는 경우

자바스크립트 엔진은 코드가 없어도 실행 환경(실행 컨텍스트)을 초기화한다. 이런 빈 코드를 실행하면 전역 실행 컨텍스트는 다음과 같은 모습으로 생성된다.

이때의 this는 window 객체이고 선언된 변수, 함수, 객체 등은 아무것도 없으니 variable object는 빈 객체이다. 그리고 전역 실행 컨텍스트인 경우 전역 스코프보다 상위 스코프는 존재하지 않으므로 scope chain은 빈 배열이 된다.


const obj = {
  name: '김바보',
  method: function(num) {
    return this.name.repeat(n);
  }
}

function myFunc() {
  let n = 10;
  return obj.method(n);
}

myFunc();

이 코드를 실행했을 때의 과정은 어떻게 될까?

먼저 전역 실행 컨텍스트가 생긴다. 전역 스코프에서는 obj 라는 객체와 myFunc 라는 함수가 하나 선언되어 있으므로 variable object는 obj와 myFunc를 프로퍼티로 갖는다.

그 후 전역에서 myFunc 함수를 실행하였으므로 콜스택에 myFunc의 실행 컨텍스트가 push 된다.
myFunc 함수 실행 컨텍스트는 variable object는 변수 n 뿐이고 scope chain은 global 이다.

여기서 this가 undefined 인 것에 주목하자.


함수 실행 컨텍스트에서의 this

함수 실행 컨텍스트에서의 this는 함수가 일반 함수냐, 객체의 메서드로서의 함수냐에 따라 달라진다.

위의 코드에서 myFunc 함수는 전역에서 함수로 선언된 일반적인 함수이다. 이런 경우엔 함수 실행 컨텍스트의 this는 기본적으로 window 객체로 지정되는데, strict mode 에서는 undefined로 지정된다.

하지만 obj 객체의 method 프로퍼티로 지정된 익명함수와 같이 객체 내의 메서드로서 정의된 함수는 해당 객체를 가리키는 this 포인터를 갖게 된다.

따라서 위의 콜스택 이미지의 세번째 콜스택에서 가장 위에 있는 컨텍스트의 this는 obj를 가리킨다. myFunc 함수의 return 문에 의해 obj 객체의 method 가 실행되어 생성된 obj.method 함수의 함수 실행 컨텍스트이기 때문이다.


이렇게 obj.method 의 함수 실행 컨텍스트까지 push 되고, obj.method의 실행이 끝나면 이 컨텍스트는 pop되어 콜스택에서 사라진다. 그리고 obj.method의 실행이 끝난 후 myFunc 함수의 실행도 종료되기에 myFunc의 컨텍스트도 pop되고, myFunc 함수의 실행이 끝나면 전역에서의 모든 로직이 수행된 것이기 때문에 전역 실행 컨텍스트도 pop 되어 콜스택이 비워진다.

이렇게 전역 실행 컨텍스트가 생성되어 push 된 후, 함수의 실행 시에 함수 실행 컨텍스트가 생성 및 push 되고 역순으로 pop 되어 콜스택이 비워지는 흐름으로 자바스크립트의 코드가 실행된다 🙂




참고자료

https://gamguma.dev/post/2022/04/js_execution_context
https://www.zerocho.com/category/JavaScript/post/5741d96d094da4986bc950a0
https://frontj.com/entry/7-Javascript%EC%9D%98-this%EC%99%80-execution-context

profile
언제까지_이렇게_살아야돼_

0개의 댓글