실행 컨텍스트, 어떻게 설명할 수 있을까?

2025. 8. 18. 22:34·🎭JavaScript

 

Excution Context (실행 컨텍스트) 란

 

실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다. 

JS에는 동일한 환경에 있는 환경정보들을 모은 실행 컨텍스트를 콜스택에 쌓아올린 후 실행하여 코드의 환경과 순서를 보장할 수 있게 된다. 

 

풀어서 설명하면 스택의 경우 FILO (First In, Last Out) 의 구조이기에 순서를 보장,

콜스택 내부에 쌓인 실행 컨텍스트의 정보를 통해 환경을 보장할 수 있는 것이다.

 

여기서 환경이란 전역공간이 될 수 있고, 함수 즉 함수 내부의 환경이 될 수 있다

var temp = 'temp';
 
function b (){
  console.log('안녕하세용');
}
 
function a (){
  b();
}
 
a();

context_example


처음 자바스크립트 코드를 실행하는 순간 사진의 (1) 처럼 전역 컨텍스트가 콜스택에 담긴다.

(1) 콜스택엔 전역 컨텍스트를 제외하곤 다른 컨텍스트가 없기에 전역 컨텍스트와 관련된 코드를 진행
(2) 전역 컨텍스트와 관련된 코드를 진행 중 a함수를 실행하였기에 a 함수의 환경 정보들을 수집하여 a 실행 컨텍스트를 생성, 콜스택에 담는다. 콜스택 최상단에 a 실행 컨텍스트가 있기에 기존의 전역 컨텍스트와 관련된 코드의 실행을 일시적으로 중단한 후 a 실행 컨텍스트의 코드를 실행한다.

(3) a 함수 내부에서 b 함수를 실행하였기에 b 함수의 환경 정보들을 수집, 실행 컨텍스트를 생성, 콜스택에 담는다. 이전과 똑같이 콜스택 최상단에 b 실행 컨텍스트가 있기에 기존 a 실행 컨텍스트와 관련된 코드의 실행을 일시적 중단
(4) b 함수가 종료된 후 b 실행 컨텍스트가 콜스택에서 제거되고, 제거 후 콜스택 최상단에는 a 실행 컨텍스트가 있기에 이전에 중단된 지점부터 코드 진행이 재개
(5) a 함수 또한 종료된 후 실행 컨텍스트가 콜스택에서 제거. 이후엔 전역 공간에 실행할 코드가 남아있지 않다면 콜스택에서 전역 컨텍스트 또한 제거되며 콜스택에 아무 것도 남지 않은 상태로 종료

 

 

Excution Context (실행 컨텍스트)  속엔 어떤 정보가 있을까

우선 실행 컨텍스트 내부엔 variable environment, lexical environment, this binding 가 있다.

 

variable environment

VariableEnvironment 란 현재 컨텍스트 내부의 식별자 정보 environmentRecord,

외부 환경 정보 outerEnvironmentReference가 포함되어 있다.
VariableEnvironment 에 먼저 정보를 담고, 그대로 LexicalEnvironment 에 복사해 사용한다. 

 

LexicalEnvironment

LexicalEnvironment 는 초기에는 VariableEnvironment 와 같지만 변경 사항이 실시간으로 적용된다. 
즉, VariableEnvironment 초기 상태를 기억하고 있으며, LexicalEnvironment 최신 상태를 저장하고 있다. 

 

environmentRecord 

environmentRecord 란 현재 컨텍스트와 관련된 식별자와 식별자에 바인딩된 값이 기록되는 공간
더불어 실행 컨텍스트 내부 전체를 처음부터 끝까지 확인하며 순서대로 수집한다.

 

 

var ahr = 'gpfus';
 
console.log(ahr); // gpfus

 

console.log(ahr); // undefined
 
var ahr = 'gpfus';

 

선언하기도 전에 값을 호출했는데 Reference error 가 발생하지 않고 undefined (할당되지 않음) 만 출력된다. 

 

이것은 자바스크립트의 호이스팅이라는 현상과 관련이 있는데

"호이스팅이란?"

자바스크립트 코드는 실행되기 전에 준비과정(실행컨텍스트 생성) 을 거친다. 
이과정에서 엔진은 현재 스코프 안에있는 변수이름, 함수이름 같은 식별자들을 미리 다 수집해둔다.

즉, 코드를 한줄씩 읽기 전에 " 아 여기서는 이런 변수랑 함수들이 쓰이겠구나 "하고 목록을 만들어두는것
그래서 실제 코드에서는 변수를 선언하기전에 접근해도, 엔진 입장에서는 이미 그 이름을 알고있으니 동작하는것처럼 보이는 것이다 .이걸 => 호이스팅 이라고 부른다 


var vs let/const
var → 선언과 초기화가 동시에 일어나서 undefined로 미리 세팅됨.
let, const → 선언만 미리 되고, 초기화는 실제 코드 실행 시점에 일어남. 그래서 TDZ(Temporal Dead Zone) 라는 구간이 생김.

💠정리 
- 실행 컨텍스트 생성 시, LexicalEnvironment → environmentRecord 안에 식별자가 미리 기록된다.
- 이것 때문에 변수가 마치 코드 최상단으로 끌어올려진 것처럼 보인다 → 호이스팅.
- 단, var/let/const는 동작 방식이 조금 다르다.

 

 

outerEnvironmentReference

const message = 'hello';

const showInfo = () => {
  const dog = {
    age: 10,
    breed: 'yorkshire terrier',
  };
  const cat = {
    age: 4,
    breed: 'yorkshire terrier',
  };
  console.log(message); // ✅ 가능
  console.log(dog);     // ✅ 가능
  console.log(cat);     // ✅ 가능
};

showInfo(); 
// 'hello', { age: 10, breed: 'yorkshire terrier' }, { age: 4, breed: 'yorkshire terrier' }

console.log(dog); // ❌ ReferenceError
console.log(cat); // ❌ ReferenceError

 

 

1. 스코프(범위)

  • 함수 안에서 선언된 변수 dog,cat은 함수 안에서만 쓸 수 있다.
  • 함수 밖에서는 아예 모른다고 생각하면됨

 

2. 외부 변수 접근

  • 함수 안에서는 함수 밖에서 선언된 변수(message)를 그대로 쓸수 있다. 
  • 왜냐면 함수가 만들어질때, 자기가 "어디서 만들어졌는지"를 기억하기 떄문

3. outerEnvironmentReference

  • 이게 바로 "내가 만들어졌을때의 바깥 환경을 기억하는 메모" 같은 역할을 함
  • showinfo 는 전역에서 선언됐으니까 , 전역에 있는 변수 message를 기억하고 있어서 쓸수 있음

 

4. 중첩 규칙

  • 이 참조는 항상 바깥 -> 더바깥-> 전역 순으로만 찾아간다.
  • 같은 이름이 여러군데 있으면 가장 가까운것만 씀

✨정리 비유 
함수 안은 작은 방이라고 생각하면 됨
방 안에서 만든 물건(dog, cat)은 그 방 안에서만 쓸 수 있다
하지만 방 안에서는 "거실(전역)"에 있는 물건(message)도 가져다 쓸 수 있음
왜냐하면 방이 지어질 때 이미 "거실이랑 연결돼 있어" 하고 기억하기 때문!!

outerEnvironmentReference

 

const greeting = 'hello';
const name = 'Tom';

const saySomething = () => {
  const greeting = 'hi';
  console.log(greeting); // ?
  console.log(name);     // ?
  console.log(age);      // ?
};

saySomething();

 

실행 결과

  1. greeting → 'hi'
  2. name → 'Tom'
  3. age → ReferenceError (정의되지 않음)

1) greeting 변수

  • 함수 안에서 greeting = 'hi'가 선언됨.
  • 엔진은 변수를 찾을 때 "현재 스코프(함수 내부)" 부터 확인함.
  • 여기서 이미 greeting을 찾았으니, 바깥에 있는 'hello'는 가려짐(= 변수 은닉화).
    => 결과: 'hi'

2) name 변수

  • 함수 안에는 name이 없음.
  • 그래서 바깥 환경(전역 스코프)을 확인.
  • 전역에서 name = 'Tom'을 찾음.
    =>  결과: 'Tom'

3) age 변수

  • 함수 안에도 없음.
  • 전역 스코프에도 없음.
  • 더 이상 참조할 곳이 없으니 에러 발생.
    =>   결과: ReferenceError: age is not defined

 

함수는 만들어질 때 자기가 선언된 위치의 환경을 기억함.

  • 변수를 찾을 때:
    1. 자신의 스코프(환경) 먼저 확인
    2. 없으면 바깥 환경(outerEnvironmentReference) 확인
    3. 그래도 없으면 계속 위로 올라감 (→ 전역까지)
  • 이런 연결 구조를 스코프 체인이라고 부름.
  • outerEnvironmentReference는 이 스코프 체인을 가능하게 하는 핵심 장치!

 

함수 안에서 변수를 찾을 때는 "안 → 바깥 → 더 바깥 → 전역" 순서로 찾는다
✨ 정리된 결론
  • LexicalEnvironment → “변수들이 적혀 있는 메모장”
  • outerEnvironmentReference → “바깥 메모장으로 연결되는 화살표”
  • scope chain → “이 화살표들을 따라가며 변수를 찾는 연결 고리” 라고 생각하자 

outerEnvironmentReference는 함수가 선언된 위치의 LexicalEnvironment를 기억합니다.
변수에 접근할 때,

1. 현재 LexicalEnvironment(메모장)에서 찾고 없으면
2. outerEnvironmentReference(바깥으로 향하는 화살표) 를 따라 바깥 LexicalEnvironment(메모장)로 이동하며 탐색
3. 이 과정을 반복하다가 끝까지 없으면 에러 난다.

이처럼 안쪽 → 바깥쪽으로 변수를 차례로 찾아가는 과정을 scope chain이라 하고,
outerEnvironmentReference는 이 scope chain을 가능하게 하는 핵심 요소입니다.

 

 

ThisBinding

this

자바스크립트에서 this는 "지금 이 코드를 누가 불렀는지"를 가리킨다.\

 

1. 전역에서 this

console.log(this);

전역에서는 this = 전역 객체 (window 또는 global)

 

2. 객체 안에서 this

const person = {
  name: 'Tom',
  sayName: function () {
    console.log(this.name);
  }
};

person.sayName(); // "Tom"

메소드(sayName) 안에서는 this = 그 메소드를 가진 객체(person)

 

3. 그냥 함수 안에서 this

function show() {
  console.log(this);
}

show(); 
// 일반 함수 호출 → 전역 객체

함수 단독 호출 시 this = 전역 객체

 

4. 화살표 함수에서 this

const person = {
  name: 'Tom',
  say: () => {
    console.log(this.name);
  }
};

person.say(); // undefined

화살표 함수는 자기만의 this가 없음.
바깥 스코프의 this를 그대로 씀. (여기서는 전역 → undefined)

 

전역에서 → 전역 객체

객체의 메소드에서 → 그 객체

그냥 함수 호출 → 전역 객체

화살표 함수 → 바깥 스코프의 this

 

ThisBinding이란?

  • 자바스크립트는 함수를 실행할 때마다 실행 컨텍스트라는 걸 만든다.
  • 실행 컨텍스트 안에는 여러 정보가 들어가는데, 그중 하나가 “이 함수 안에서 this가 누구를 가리킬까?” 이다.
  • 그걸 저장해 두는 게 바로 ThisBinding
this = “누가 이 함수를 불렀냐” ( 실행될 때마다 달라지고)
ThisBinding = “그 정보를 실행 컨텍스트에 저장해두는 것” ( 그때그때 this가 누구인지 기록해두는 것)

 

 

더보기

그렇다면 이제 답해보자!!!

 

🤔 “자바스크립트의 실행 컨텍스트 대해 설명해보세요.”

실행 컨텍스트는 자바스크립트 코드가 실행되는 환경을 의미합니다.
여기에는 변수·함수 선언, 스코프, this 바인딩 정보 등이 담기고, 이 정보들을 토대로 코드가 실행됩니다.
실행 컨텍스트는 전역 실행 컨텍스트와 함수 실행 컨텍스트로 나눌 수 있으며, 함수가 호출될 때마다 새로운 실행 컨텍스트가 생성되어 콜 스택에 쌓이고, 실행이 끝나면 제거됩니다.

 

🤔 “스코프 체인에 대해 설명해보세요.”

스코프 체인은 현재 실행 컨텍스트의 변수 환경과 상위 컨텍스트들을 연결한 구조입니다.
변수를 찾을 때 자바스크립트 엔진은 현재 스코프에서 먼저 확인하고, 없으면 스코프 체인을 따라 상위 스코프를 차례대로 탐색합니다.

 

🤔 “스코프에 대해 설명해보세요.”

스코프는 식별자를 찾아내는 규칙입니다. 자바스크립트는 렉시컬 스코프(정적 스코프)를 따르기 때문에, 함수가 호출된 위치가 아니라 선언된 위치에 따라 상위 스코프가 결정됩니다.
ES6 이전에는 전역 스코프와 함수 스코프만 있었지만, ES6에서 let/const가 도입되면서 블록 스코프도 지원하게 되었습니다.

 

🤔 “호이스팅에 대해 설명해보세요.”

호이스팅은 실행 컨텍스트가 생성될 때, 엔진이 변수와 함수 선언을 먼저 메모리에 등록하는 동작을 말합니다.
그래서 코드상으로는 아래에 있어도, 선언이 마치 코드 최상단으로 끌어올려진 것처럼 동작합니다.
다만 var와 let/const는 호이스팅 방식에 차이가 있으며, let/const의 경우 TDZ(Temporal Dead Zone)로 인해 선언 전에 접근 시 에러가 발생합니다.

 

 

----

https://gamguma.dev/post/2022/04/js_execution_context

https://www.jeong-min.com/71-execution-context/

'🎭JavaScript' 카테고리의 다른 글

Javascript 비동기 처리 동작원리  (0) 2024.11.11
'🎭JavaScript' 카테고리의 다른 글
  • Javascript 비동기 처리 동작원리
gprorogpfus
gprorogpfus
:- >
  • gprorogpfus
    gpfusdldks
    gprorogpfus
  • 전체
    오늘
    어제
    • 분류 전체보기 (55)
      • 🎭JavaScript (2)
      • 👚 CSS (1)
      • ⚛️ React (13)
      • 🌃 Next.js (5)
        • 🔜 next.js-study (3)
      • 🥏TypeScript (10)
      • 🏴알고리즘 (2)
      • 🌴트러블슈팅 (3)
      • ⛲ 프로젝트 (6)
        • 👖gproro-shop-app (8)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 글쓰기
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    JavaScript
    GIT
    Redux
    TypeScript
    react
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
gprorogpfus
실행 컨텍스트, 어떻게 설명할 수 있을까?
상단으로

티스토리툴바