프론트엔드 개발자로서, 자바스크립트의 중요성은 누구나 다 안다.
하지만, 자바스크립트의 동작원리의 핵심은 무엇일까? 오늘은 이에 대해 한 번 간단하게 찍먹(?) 정도만 해보겠다. ㅎㅎ
흔희 우리가 알고있는 문맥. 일종의 글로 치면 글의 흐름, 대화에서는 대화의 흐름처럼. 프로그래밍에서도 이런 문맥이 중요하다.
이 흐름을 잘 알아야만, 어떤 구조로 흘러가고 있는 지, 재빠르게 캐치를 할 수 있고, 모든 것들의 핵심파악이 빨라진다. 이런 의미에서 문맥은 중요하다. 이 문맥을 프로그래밍 용어로는 보통 context 또는 실행 컨텍스트라고 한다.
그래서 이번 시간에는 이 실행 컨텍스트를 왜 프로그래밍을 이해하는 것에 있어서 중요한 지와 더불어 간단하게 구조와 관련 내용들을 얘기해 보겠다.
보통 실행 컨텍스트는 다음과 같이 정의한다.
ECMAScript 스펙에 따르면 실행 컨텍스트를 실행 가능한 코드를 형상화하고 구분하는 추상적인 개념이라고 정의한다. 좀 더 쉽게 말하자면 실행 컨텍스트는 실행 가능한 코드가 실행되기 위해 필요한 환경 이라고 말할 수 있겠다.
이게 뭔 소리여?
할 수 있다. 자~ 이제 하나씩 살펴보겠다.
실행 컨텍스트는 결국 함수가 실행되는 환경을 의미한다.
여기서 함수는 변수, 매개변수, 내장함수, this. 이 4가지로 이뤄져 있는 것이 함수다. 따라서 이런 것들을 실행하는 어떤 환경을 의미한다.
그러면, 본격적으로 실행 컨텍스트에 대해 알아보기 전, 실행 구조에 대해 좀 더 알고 넘어가자.
자바스크립트는 싱글스레드 언어다. 즉, 싱글스레드라고 하면, 하나씩 처리하는 언어라고 생각하면 쉽다. 그래서 하나의 콜스택. 단일 호출 스택으로 코드를 실행한다.
위의 그림은 foo라는 함수가 하나씩 콜 스택에 쌓이면서, 오버 플로우가 되는 사례다.
그런데, 사실 아래 그림처럼 되어야 정상이다.
처음에는 글로벌 컨텍스트가 쌓이고, 그 이후에는 함수에 해당하는 각각의 컨텍스트가 콜 스택에 쌓인다. 즉, 실행 컨텍스트 단위로 함수가 콜스택에 쌓여서 코드가 실행된다.
그런데 여기서 용어를 하나 짚어 두고 가자. 바로 다음과 같다.
즉, 스코프 체인 = 실행 컨텍스트 체인, 지역 환경 = 지역 스코프.
또, 이 렉시컬 스코프는 environment record와 Outer environment record를 의미한다.
이 렉시컬 스코프는 함수가 호출 될 때를 기반으로 해서, 코드의 스코프를 파악하는 것이 아니라, 쓰여진 것을 기반으로 해서 스코프를 파악한다.
예를 들어서, 지금 second는 first 밑에 있다. second가 봤을 때, first는 outer scope. 다. 즉, 바깥에 있는 스코프라는 것이다. 이런 것이 바로 렉시컬 스코프다.
실행컨텍스트는 다음과 같이 3가지로 이뤄져 있다.
여기서 Eval 실행 컨텍스트도 있지만, 이는 중요성 면에서 추후 다시 다루도록 하겠다. 그래서 크게 우리가 주목해서 봐야할 컨텍스트는 글로벌과 함수형 두 가지다.
먼저, 글로벌 컨텍스트는 다른 말로 전역 객체라고 불리며, this object와 window object로 이뤄졌다. 함수형은 활성 객체라고 불린다.
대표적으로 전역객체와 활성 객체는 다음과 같은 것들을 의미한다.
실행 컨텍스트는 다음과 같이 2가지 단계로 나뉘어 진다.
일반적으로 실행 컨텍스트가 생성되는 단계에서 작용은 다음과 같다. 보통 실행 컨텍스트들은 값이 들어가 있지 않는 초기 값이라고 보면 된다.
대표적인 예시로, var는 선언과 초기화가 동시에 이뤄져서 언디파인드가 할당이 되고, let과 const는 선언만 일어나게 된다.
여기서 체인을 건다는 것은 어떤 링크가 걸린다고 이해하면 되겠다. 이런 스코프 체인을 만드는 과정을 스코프 체이닝이라고 한다. 코드를 훑으면서, 서로 서로 참조가 가능하게 끔 만드는 것이다. 이렇게 체이닝을 만들어 버리기 때문에, 호이스팅이 가능하다.
스코프 체이닝은 다음 그림과 같다.
여기서, 다시 사례로 풀어보자.
네임을 참조할 때, 바로 위의 사라를 참조한다.
그런데 왜? 리다는 참조하지 않는가? 당연한 순리라고 생각하면 쉽다. 즉, 어떤 지역 스코프 내에서 해당 값이 먼저 있다면, 그 값을 이용하는 것이다. 만약 없다면, 더 위의 아웃터(부모) 함수 스코프에서 찾는다. 이런 식으로 네임과 에이지는 지역변수를 먼저 참조해서 할당이 된다.
시티는, 현재 지역 변수 내에 값이 없다. 이럴 때, 시티는 아웃터 스코프를 참조한다.
이런 식으로 이너 스코프에서 , 계속 아웃터 스코프로 가면서 변수를 찾아가는 과정이 스코프 체인이다.
익스큐션 페이즈는 다음과 같이 실행 된다.
추가 예제로 다시 살펴보자.
처음에는 글로벌 오브젝트로 this가 있다. 당연히 크리에이션 단계니까 언디파인드가 되어 있다.
익스큐션 단계에는 a의 값이 할당이 된다.
그 다음에는 b라는 function이 creation 단계로 갈 것이다.
아규먼츠와 각종 매개 변수들이 담겨 있다. 당연히 c는 지금 크리에이션 단계니까 undefined다.
그 다음에 값이 다시 2로 할당이 된다.
이렇게 , 실행컨텍스트를 기반으로 해서 콜스택에 쌓여서 자바스크립트 코드가 실행된다고 생각하면 되겠다.
사실 실행 컨테스트는 엄청 광범위 한 개념이다. 이를 명확히 알기 위해서는 보다 더 범위를 넓혀야 한다. 하지만, 이번에는 간단하게 맛 보기 정도로만 했다. 따라서 우리가 보통 어떤 코드를 적을 때, 이런 범위에서 실행되고 하는 구나라고 인지하면 좋겠다.
추가적으로 이런 부분을 왜 알아야 되는 지에 대해 다시 한 번 생각을 짚고 넘어가면 좋겠다. 물론 몰라도 코드는 짤 수 있다. 하지만, 추후 디버깅은 물론이고 본인이 짠 코드의 흐름을 명확히 알기 위해서는 컴퓨터가 우리의 코드를 어떻게 처리하는 지에 대해서는 알 필요가 있다.
따라서 필자 역시 추후 더 깊은 과정은 더 이해를 한 뒤에 더 추가하도록 하겠다. 긴 글 읽어주셔서 감사하다 :)