Tech/Javascript

[Javascript] 자바스크립트 실행 컨텍스트(Execution Context)

lonnie(동현) 2022. 4. 20. 18:58

실행 컨텍스트는 자바스크립트에서 가장 중요한 핵심 개념 중에 하나입니다. 자바스크립트에서 작동하는 다양한 것들의 동작 원리를 담고 있기 때문입니다. 이를 정확히 이해하는 것은 자바스크립트 개발자에게 매우 중요합니다.

목표

  • 실행 컨텍스트에 대해서 이해한다

실행 컨텍스트란?

실행 컨텍스트는 실행 가능한 코드에 제공할 환경 정보들을 모아놓은 객체를 말합니다. 따라서, 우리가 코드를 작성하고 실행하게 된다면 실행 컨텍스트 내부에서 실행되고 있는 것입니다. 여기서 말하는 실행 가능한 코드는 아래와 같습니다.

  • 전역 코드 : 전역 영역에 존재하는 코드
  • 함수 코드 : 함수 내에 존재하는 코드
  • Eval 코드 : eval 함수로 실행되는 코드
  • block 코드 : while, if , for, function 등에서 만들어지는 {} 코드

자바스크립트 엔진은 코드를 실행하기 위해 여러 가지 정보를 알고 있어야 합니다. 그 정보는 아래와 같습니다.

  • 변수: 전역 변수, 지역 변수, 매개 변수, 객체의 프로퍼티
  • 함수 선언
  • 변수의 유효 범위(Scope)
  • this

실행 컨텍스트는 어떻게 동작할까?

컨텍스트는 아래와 같은 과정을 통해 동작하게 됩니다.

  • 일단 처음 코드를 실행시키면 모든 것을 포함하는 전역 컨텍스트가 생깁니다.
  • 컨텍스트 생성 시 컨텍스트 안에 변수 객체(arguments, variable), scope chain, this가 생성됩니다.
  • 컨텍스트 생성 후 함수가 실행되는데, 사용되는 변수들은 변수 객체 안에서 값을 찾고, 없다면 스코프 체인을 따라 올라가며 찾습니다.
  • 함수 실행이 마무리되면 해당 컨텍스트는 사라집니다.(클로저 제외)
  • 페이지가 종료되면 전역 컨텍스트는 사라집니다.

아래의 코드를 이 과정을 통해 천천히 살펴보겠습니다.

var name = 'lonnie'; 
function greet(word) { 
  console.log(word + ' ' + name); 
}
function say () { 
  var name = 'dongle'; 
  console.log(name); 
  greet('hello'); 
}
say();
// dongle
// hello lonnie
  1. 전역 컨텍스트가 생성됩니다.
  • 먼저 두 번째 과정에 따라 변수 객체, scope chain, this가 생성됩니다.
  • arguments(함수의 인자)는 없고, variable은 해당 스코프의 변수들입니다. 따라서 name, greet, say가 됩니다.
  • scope chain(스코프 체인)은 자신과 상위 스코프들의 변수 객체이기 때문에, 자기 자신인 전역 변수 객체가 됩니다.
  • this는 따로 설정되어 있지 않다면 window입니다.

이것을 객체 형식으로 표현하면 다음과 같습니다.

'전역 컨텍스트':{
  변수객체:{
    arguments: null,
    variable: ['name','greet','say'],
  },
  scopeChain: ['전역 변수 객체'],
  this: window,
}

이제 이 상태에서 코드를 위에서부터 실행하게 됩니다.

  1. greet와 say는 호이스팅에 의해 선언과 동시에 대입됩니다.
  2. 그 후 variable의 name에 'lonnie'가 대입됩니다.
    '전역 컨텍스트':{
    변수객체:{
     arguments: null,
     variable: [{name: 'lonnie'},{greet: function},{say: fuction}],
    },
    scopeChain: ['전역 변수객체'],
    this: window,
    }
  3. 함수 say()가 호출된 순간 새로운 컨텍스트인 say 함수 컨텍스트가 생깁니다.
  • arguments는 없고, variable은 name입니다.
  • scope chain은 say 변수 객체와 상위의 전역 변수 객체입니다.
  • this는 따로 설정하지 않았으니 window입니다.
    'say 함수 컨텍스트':{
    변수객체:{
      arguments: null,
      variable: ['name'],
    },
    scopeChain: ['say 변수 객체','전역 변수 객체'],
    this: window,
    }
  1. say()함수 내의 코드가 차례로 실행됩니다.
  • var name = 'dongle';에 의해 variable의 name에 'dongle'이 대입됩니다.
    'say 함수 컨텍스트':{
    변수객체:{
      arguments: null,
      variable: [{name : 'dongle'}]
    },
    scopeChain: ['say 변수 객체','전역 변수 객체'],
    this: window,
    }
  1. console.log(name);이 실행됩니다.
  • name 변수를 가장 먼저 say 컨텍스트 안에서 찾습니다.
  • variable에 dongle이라고 되어있으니, dongle이 콘솔에 찍히게 됩니다.
  1. greet('hello');를 실행시켜야 합니다.
  • 먼저 say 함수 컨텍스트 안에서 greet를 찾습니다.
  • say 함수 컨텍스트에서 찾을 수 없기 때문에, scope chain을 따라 올라가서 전역 변수 객체에서 찾습니다.
  • 전역 변수 객체의 variable에 greet라는 함수를 찾게 되고 이를 호출합니다.
  1. 마찬가지로, 함수 greet()함수가 호출된 순간 새로운 컨텍스트인 greet 함수 컨텍스트가 생깁니다.
  • arguments는 word = 'hello'이고, variable은 없습니다.
  • scope chain은 greet 변수 객체와 상위의 전역 변수 객체입니다.
  • this는 따로 설정하지 않았으니 window입니다.
    'greet 함수 컨텍스트':{
    변수객체:{
      arguments: [{word: 'hello'}],
      variable: null,
    },
    scopeChain: ['greet 변수 객체','전역 변수 객체'],
    this: window,
    }
  1. 이제 greet()함수 내 코드가 실행됩니다.
  • greet()함수 안에서 console.log(word + ' ' + name);를 실행하기 위해 word와 name을 찾아야 합니다.
  • 먼저 greet 변수 객체에서 word는 arguments에서 'hello'라고 되어있는 것을 찾을 수 있습니다.
  • name은 없으니 전역 변수 객체를 찾아봅니다. 전역 변수 객체에서 name은 'lonnie'라고 되어있는 것을 찾을 수 있습니다.
  • 따라서 hello lonnie가 콘솔에 찍히게 됩니다.
  • greet 함수 컨텍스트에 따르면, say 함수 컨텍스트와는 전혀 관계가 없는 것을 알 수 있습니다.
  1. greet함수가 종료되고 greet 함수 컨텍스트가 사라지고, say 함수의 실행이 마무리됩니다. 따라서 say 함수 컨텍스트도 사라지고, 마지막에 전역 컨텍스트로 사라집니다.

    글을 마치며

    실행 컨텍스트가 어떻게 동작하는지 따라가 보며 이해해보는 시간을 가졌습니다. 잘 몰랐던 부분이라 많이 헷갈려했는데, 이번을 계기로 어떤 식으로 동작하는지에 대해서 조금이나마 알게 된 것 같다고 생각합니다.
728x90
반응형