기본적으로 Front-End 개발자라면 Javascript를 통해 각종 기능을 개발하고 그 안에는 UI 제어, 사용자 데이터 처리 또는 연산 그리고 서버와의 데이터 통신 등이 있을것이다. 그렇다면 이러한 기능들은 Javascript 엔진에서는 어떤 환경에서 어떻게 실행되는것일까?
그 중심에는 이번에 다룰 Javascript의 핵심원리인 실행 컨텍스트(Execution Context)가 있으며 Scope, Hoisting, this, function, closure 등의 동작원리를 담고 있는 총체적 개념이라고 할 수 있다.
그렇다면 실행 컨텍스트란 무엇이며, 어떠한 구조로 이루어져 있고, 어떻게 작동하는지 알아보자.
실행 컨텍스트 (Execution Context)
서두에서 말했듯이 실행 컨텍스트 란 Javascript의 핵심원리로서, 실행 가능한 코드를 형상화 하고 구분하는 추상적인 개념으로 코드가 실행되고 있는 구역 또는 범위 라고 정의할 수 있다.
Javascript 엔진은 코드를 실행하기 위해 여러가지 정보를 알고 있어야 하며 다음에 얘기할 실행 컨텍스트의 유형에 따라서 달라질 수 있음을 기억하고 있어야 한다.
- Variable: 전역 변수, 지역 변수, 매개 변수, 객체의 프로퍼티
- Argument: 인자 객체
- Scope: 변수의 유효범위
- This
위와 같이 실행에 필요한 정보를 형상화하고 구분하기 위해서 JS 엔진은 실행 컨텍스트를 물리적 객체의 형태로 관리한다.
실행 컨텍스트의 유형
실행 구역 또는 범위에 따라 실행 컨텍스트의 유형을 구분할 수 있음
- 전역 컨텍스트 (Global Execution Context)
- 함수 컨텍스트 (Functional Execution Context)
- Eval 함수 컨텍스트 (Eval Function Execution Context)
전역 실행 컨텍스트 (Global Execution Context)
실행 컨텍스트의 가장 기초가 되는 구간 또는 범위로, 함수
구간 안에서 실행되는 코드가 아니라면 대부분 전역 컨텍스트 안에서 실행된다. 전역 컨텍스트에서는 두 가지 작업이 발생된다.
window
객체인 전역 컨텍스트 생성this
를 전역 객체로 할당
함수 실행 컨텍스트 (Functional Execution Context)
함수가 실행될때마다 해당 함수의 실행 컨텍스트가 생성된다. 즉, 호출
이 발생될때마다 각 함수의 함수 컨텍스트가 생성되는 것이다.
Eval 함수 실행 컨텍스트 (Eval Function Execution Context)
eval
함수 또한 함수 컨텍스트와 동일하게 실행 컨텍스트를 갖지만 많이 사용하지 않는 함수이며 지양해야할 기능이므로 생략하겠다.
실행 컨텍스트의 생성과 실행 관리
실행 컨텍스트의 생성 및 실행을 이해하기 위해서는 실행 스택(Execution Stack) 과 제어권(Control) 에 대한 개념을 숙지해야한다.
먼저 호출 스택(Execution Stack) 이란 다른 언어 또는 파트에서도 나오는 호출 스택(Call Stack) 과 같은 LIFO (Last In, First Out) 의 자료구조로 코드 또는 함수가 실행되면서 생성되는 각각의 실행 컨텍스트를 저장하는 구조적 집합체 이다.
Javascript 엔진이 script
태그를 만나면,
- 실행 가능한 코드로 제어권(control) 이 이동하면 논리적 스택 구조를 가지는 빈 실행 컨텍스트 스택이 생성
- 제어권 이 전역 코드로 이동하면 전역 실행 컨텍스트 가 생성되며 비어있는 컨텍스트 스택에 push
- 그리고 전역환경에서 함수를 호출하면 제어권 이 함수 코드로 이동하면서 호출된 함수의 함수 컨텍스트 가 생성 및 실행 스택에 push. 즉, 스택의 가장 마지막 순서로 삽입됨
- Javascript 엔진은 실행 스택 에서 가장 상단에 있는 실행 컨텍스트 부터 실행
- 각 실행 컨텍스트 가 종료되고 나면 실행 스택 에서 제거 (pop) 되고, LIFO의 순서에 맞춰서 제어권이 이동한다.
아래의 예제를 보자
우리는 main.js
라는 javascript file을 갖고 있으며 script
태그를 통해 첨부했다고 가정하자.
1 | // 전역 context |
main.js
가 로드되면서 Javascript 엔진은 실행 스택 을 아래와 같이 분석 및 구분할 것이며 이는 그림 [실행 스택 예시] 와 같을 것이다. (초기 컨텍스트 스택 순서는 생략)
- 전역 컨텍스트가 호출되면서 전역 실행 컨텍스트가 실행 스택에 push 되고
- sum 함수가 호출 및 실행되면서 sum 함수의 함수 실행 컨텍스트가 실행 스택에 push
- print 함수가 호출 및 실행되면서 print 함수의 함수 실행 컨텍스트를 실행 스택에 push. 그리고 실행이 끝나면 print 함수의 함수 실행 컨텍스트는 pop (제거)
- sum 함수의 실행 또한 완료되며 함수 실행 컨텍스트가 pop (제거)
- 전역 실행 컨텍스트 만 남게된다.
여기까지 실행 컨텍스트는 무엇이며 그 유형과 Javascript 엔진이 실행 컨텍스트를 어떻게 생성하고 관리하는지 알아보았습니다. 다음 포스팅에서는 실행 컨텍스트에 대한 구조와 예시에 대해 다뤄보도록 하겠습니다.
참조
- Understanding Execution Context and Execution Stack in Javascript
- Executable Code and Execution Contexts - ecma-262 from ECMAScript
- [Javascript] Execution Context와 Lexical Environment - https://iamsjy17.github.io
- [JS] 자바스크립트의 The Execution Context (실행 컨텍스트) 와 Hoisting (호이스팅) - https://velog.io/@imacoolgirlyo
- 자바스크립트 함수 (3) - Lexical Environment - meetup.toast.com
- 자바스크립트의 스코프와 클로저 - meetup.toast.com