안녕하세요, 똑똑한개발자에서 프론트엔드 개발을 하고 있습니다.👋

똑똑한개발자

똑똑한개발자 프론드엔드 팀은 매주 월요일 오후에 javascript 기초에 대한 스터디를 진행하고 있습니다.

자바스크립트의 핵심적인 기본개념과 동작원리에 대해 스터디 구성원 한 사람이 파트 1개씩을 맡아

간단하게 발표하고 그에 대한 의견들을 공유하고 나누는 형태로 진행합니다.

첫 시간에는 자바스크립트의 ‘데이터’와 ‘불변성’에 대해 간략하게 알아보는 시간을 가졌고

이번에는 자바스크립트의 ‘실행 컨텍스트’에 대해 이야기를 나눠보는 시간을 가졌습니다.

이번 블로그 포스팅은 ‘코어 자바스크립트’를 참고하여 작성했습니다.

코어 자바스크립트

똑똑한개발자 프론트엔드 팀에서는 기본적으로 typescript기반의 리액트(Next.js)를 활용하여 프로젝트를 진행합니다.

typescript는 점점 그 점유율이 높아져가는 프로그래밍 언어이나, 기본적으로 javascript를 베이스로 한 js의 슈퍼셋 언어로 널리 알려져있습니다. 당연히 자바스크립트의 기본적인 개념이나 동작원리를 모두 상속하고 있으니 자바스크립트에서 중요한 개념인 실행 컨텍스트에 대해 알아보겠습니다.

실행 컨텍스트. 말이 참 어렵습니다. 구글에서 실행컨텍스트에 대해 검색해보면,

‘실행컨텍스트 execution context는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체’ 라고 정의하고 있습니다.

실행컨텍스트에 대해 자세하게 알아보기 전에 간단한 자료구조에 대해 학습을 해야합니다.

주니어, 시니어 개발자를 막론하고 개발을 하다보면 누구나 한번쯤은 들어봤을만한 자료구조인 ‘스택’과 ‘큐’가 바로 그것입니다.

스택과 큐

Stack and Queue

스택과 큐는 자료를 저장하고 호출하는 것을 나타내는 자료구조인데, 비슷해보이지만 조금 다릅니다.

스택

Stack

스택은 무언가를 차곡차곡 쌓아올리는 것을 의미합니다. 스택의 가장 큰 특징은 ‘LIFO(Last In First Out)’을 들 수 있는데, 이는 Ctrl(Cmd) + Z의 작동방식과 유사합니다. 스택으로 데이터를 저장할 경우 push()로 데이터를 차곡차곡 쌓아올리고, pop()메서드로 데이터를 뺄 수 있습니다. 이 때, 가장 나중에 들어갔던 데이터가 가장 먼저 호출되어 스택의 밖으로 인출됩니다.

Stack

큐는 정해진 한 곳(top)을 통해서 push(), pop()이 이루어지는 스택과는 달리 한쪽 끝에서 삽입, 반대쪽 끝에서 삭제작업이 이루어집니다. 큐의 가장 큰 특징은 ‘FIFO(Last In First Out)’에 대해 자주 언급되는데, 이는 일상생활에서 줄을 서서 기다리는것, 또는 은행에서 번호표를 뽑고 자신의 순서를 기다리는 방식과 유사합니다. 큐로 데이터를 저장할 경우 가장 먼저 저장했던 데이터가 가장 먼저 호출되어 큐의 밖으로 인출됩니다.

실행컨텍스트는 실행할 코드에 제공할 환경에 대한 정보들을 모아 컨텍스트를 구성하고, 이를 콜 스택 Call Stack에 쌓아올렸다가 스택의 자료구조 방식과 동일하게 콜스택의 가장 위에있는 코드를 순차적으로 실행합니다.

// ----------------(1) 전역컨텍스트
var a = 1;
function outer() {
  function inner() {
    console.log("1:", a); //undefined
    var a = 3;
  }
  inner(); // ----------(2) inner() 함수 실행
  console.log("2:", a); //1
}
outer(); // -----------(3) outer() 함수 실행
console.log("3:", a); // 1

간단한 예제 코드입니다(출처: 코어 자바스크립트) 자바스크립트는 특정 실행 컨텍스트가 활성화 될 때 해당 컨텍스트에 관련된 코드를 실행하는 환경정보를 수집하여 실행 컨텍스트 객체(활성 객체)에 저장합니다. 이 객체에 앞으로 사용하게 될 매개변수, 사용자가 정의한 변수 및 객체를 저장하고 새로 만들어진 컨텍스트로 접근 가능하게 되어있습니다. 이 객체에 저장되는 정보는 다음과 같습니다. (이는 엔진 내부에서 접근할 수 있고, 사용자가 직접적으로 접근하는 객체가 아닙니다.)

  • Variable Environment: 현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경 정보, 선언시점의 Lexical Environment의 스냅샷, 변경사항이 반영되지 않습니다.
  • Lexical Environment: 최초에는 VariableEnvironment와 같지만, 변경사항이 실시간으로 반영됩니다.
  • This Binding: { this } 식별자가 바라봐야 할 대상 객체 (this 식별자는 ‘코어 자바스크립트’ 3장 ‘this’와 연관지어 함께보면 좋습니다.)

다시 예제코드로 돌아가서, 저 코드를 콘솔에 찍어보면 어떤 결과가 출력될까요?

(스크롤을 잠시 멈추고, 생각해봅시다.)

(jsfiddle 사이트로 연결됩니다. ‘Run’버튼으로 실행시켜주세요) 정답

이 예제코드에 대해 알아보려면 실행 컨텍스트 내의 개념 한가지를 더 알고 보면 쉽습니다.

  • 스코프체인 : 현재 컨텍스트의 유효범위를 나타내는 스코프 정보를 생성합니다. 여러 스코프에서 동일한 식별자를 선언한 경우, 무조건 스코프 체인상에서 가장 먼저 발견된 식별자에만 접근이 가능합니다.

inner() 함수에서 등장하는 console.log(a)의 결과는 왜 ‘undefined’일까요? ==> inner() 스코프의 Lexical Environment에 ‘a’라는 식별자가 이미 존재합니다(var a = 3). 따라서 스코프 체인 검색을 더 이상 진행하지 않고, inner()함수 내부의 ‘a’는 3으로 선언되어 함수가 종료됩니다. 따라서, 전역에서 선언한 동일한 변수 ‘a’에 접근할 수 없습니다. 이러한 형태의 코드를 변수 은닉화 variable shadowing라고 합니다.

후기

‘실행 컨텍스트’를 중점적으로 알아보기 위해 비동기처리 및 이벤트 루프와 같은 내용은 함께 기록하지 않았습니다. 실행컨텍스트의 개념을 이해하고 좀 더 풍부하고 확장된 학습을 하고싶으신 분이 있으실것같아 참고가 될만한 좋은 영상을 남깁니다.

어쨌든 이벤트 루프는 무엇입니까? | Philip Roberts | JSConf EU Event Loop

luke's profile image

luke

2021-07-15 18:00

Read more posts by this author