인프런 커뮤니티 질문&답변

산성님의 프로필 이미지

작성한 질문수

진짜! 자바스크립트(Javascript) - 기초부터 고급까지

VAR 변수의 문제점 2편

var 변수의 문제점 설명하실 때 질문 있습니다.

해결된 질문

작성

·

257

0

function testShadowing() {
    let x = 5;
    if (true) {
        let x = 10;
        console.log(x);
    }
    console.log(x);
}
testShadowing()

위와 같이 let으로 x 변수를 2번 할당했는데, 실제 메모리에는 어떻게 할당이 되나요?

블록 스코프라고 하더라도 함수 스코프 안에서 블록 스코프가 만들어 질 것으로 생각이 되는데(뇌피셜입니다.), 이미 함수 스코프에서 x라는 변수명을 사용하고 있어서 블록 스코프에서 x는 자바 스크립트 엔진에서 어떻게 받아들이고 실제 메모리에 어떤 식으로 메모리 할당을 하는지 궁금합니다.

답변 2

0

코딩맥스 CodingMax님의 프로필 이미지
코딩맥스 CodingMax
지식공유자

2024. 04. 19. 19:05

안녕하세요, 산성님! 질문 주셔서 감사합니다.

 

함수 스코프와 블록 스코프에서 같은 이름의 변수를 사용했을 때, 어떻게 메모리가 할당되는지를 질문하신 것 같아요.

 

예시 코드인 testShadowing 함수 안에서 let x = 5;로 변수 x를 선언했고 if 블록 안에서 let x = 10;으로 또 다시 변수 x를 선언했습니다.

이때 두 개의 x 변수는 각각 독립적으로 서로 다른 메모리 공간에 저장된답니다.

 

function testShadowing() { 
  let x = 5; 
  if (true) { 
    let x = 10; 
    console.log(x); 
  } 
  console.log(x); 
} 
testShadowing()

 

함수가 실행되면, 자바스크립트 엔진은 다음 순서로 동작합니다:

 

  1. 함수가 호출되면 실행 컨텍스트라는 특별한 공간이 만들어져요.

     

  2. 실행 컨텍스트 안에는 변수를 저장할 수 있는 환경이 마련되는데, 이걸 변수 환경이라고 합니다.

  3. 함수 안에 있는 변수들을 위한 공간이 변수 환경에 미리 만들어지는데요 var와 let, const 에 따라 초기값이 조금 다릅니다.

    1. 이때 let이나 const로 선언된 변수들은 uninitialized라는 상태가 됩니다.

    2. 반면에 var로 선언된 변수들은 undefined라는 값으로 초기화되죠

  4. 함수 코드가 한 줄씩 실행되면서 변수에 값이 할당되기 시작합니다.

    1. let이나 const로 선언된 변수들은 선언문이 실행되기 전까지는 사용할 수 없어요. 그래서 이 기간을 일시적 사각지대(Temporal Dead Zone, TDZ)라고 합니다.

    2. 선언문이 실행되면 비로소 변수에 값이 할당되고, 변수를 사용할 수 있게 되는 것이죠.

 

testShadowing 코드에 위 단계를 대입해 보면:

 

  1. testShadowing 함수가 호출되면 실행 컨텍스트가 만들어지고, 변수 x를 위한 공간이 만들어집니다.

  2. let x = 5;가 실행되면서 변수 x에 값 5가 할당되죠

  3. if 블록 안에서 let x = 10;이 실행되면, 새로운 블록 스코프가 만들어지고 그 안에 또 다른 변수 x가 생겨요. 이 x는 블록 바깥에 있는 x와는 다른 변수입니다.

  4. 블록 안에서 console.log(x);가 실행되면, 블록 안에 있는 x의 값인 10이 출력됩니다.

  5. 블록이 끝나면 블록 안에서 만들어진 x는 사라지게 됩니다. 즉 더 이상 접근할 수 없게 되는 것이죠.

  6. 함수 마지막에 있는 console.log(x);가 실행되면, 함수 바깥에 있는 x의 값인 5가 출력됩니다.

 

아래는 testShadowing 을 실행했을 때 스코프 체인의 모습니다. Block 스코프는 if 문 블럭 스코프를 Local 스코프는 testShadowing 함수 스코프를 나타냅니다. let 으로 x 변수를 선언 및 할당 했기 때문에 각 스코프마다 x 변수가 존재하는 것을 알 수 있습니다.

image

이렇게 let과 const 는 var 달리 블록 레벨 스코프를 갖기 때문에 서로 다른 스코프에서 같은 이름을 가진 변수를 여럿 선언하더라도 서로 다른 변수로 취급된다는 걸 알 수 있습니다. 이름이 같아서 하위 스코프의 변수가 상위 스코프의 변수를 가리는 이런 현상을 변수 쉐도잉이라고 합니다.

변수 쉐도잉이 발생하는 이유는 변수를 사용하려 할 때, 스코프 체인을 통해서 변수를 찾게 되는데 현재 실행 중인 코드에서 가장 가까운 스코프부터 찾기 때문입니다.

 

정리하면, 함수가 실행될 때 변수를 위한 공간은 미리 마련되지만, 실제로 변수에 값이 할당되는 건 해당 변수 선언문이 실행되는 시점이에요. 특히 let이나 const로 선언한 변수는 선언 전에 사용하려고 하면 에러가 발생하니 주의해야 합니다.

 

아래는 관련 수업의 링크입니다. 디버거를 같이 실행하면서 함수 실행 컨텍스트 및 스코프 체인을 설명하고 있어요. 참고하시면 좋을 것 같습니다.

 

- 함수 실행 컨텍스트 2편 - 다시 보는 함수 스코프와 블록 스코프

- https://www.inflearn.com/course/lecture?courseSlug=%EC%A7%84%EC%A7%9C-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B8%B0%EC%B4%88%EB%B6%80%ED%84%B0-%EA%B3%A0%EA%B8%89%EA%B9%8C%EC%A7%80&unitId=176250

- 스코프 체인과 참조 오류

- https://www.inflearn.com/course/lecture?courseSlug=%EC%A7%84%EC%A7%9C-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B8%B0%EC%B4%88%EB%B6%80%ED%84%B0-%EA%B3%A0%EA%B8%89%EA%B9%8C%EC%A7%80&unitId=177158

0

산성님의 프로필 이미지
산성
질문자

2024. 04. 19. 15:15

혹시 5로 초기화 되어 있던 x를 if 블록안에서 10으로 변경한 뒤에 다시 5로 바꾸는 일을 하게 되나요?

코딩맥스 CodingMax님의 프로필 이미지
코딩맥스 CodingMax
지식공유자

2024. 04. 19. 19:14

함수 스코프와 if 블록 스코프의 x 는 let 으로 선었기 때문에 블록 레벨 스코프를 갖습니다. 그래서 이름은 같을 지라도 전혀 다른(서로 다은 메모리 공간에 위치한) 변수입니다. 그래서 하나의 x를 5에서 10으로 값을 변경하는 일이 발생하지 않고 각 스코프에 있는 변수 x를 사용해 콘솔에 값을 출력합니다 😊

산성님의 프로필 이미지

작성한 질문수

질문하기