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

산성님의 프로필 이미지
산성

작성한 질문수

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

VAR 변수의 문제점 2편

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

해결된 질문

작성

·

277

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
지식공유자

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

 

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

 

예시 코드인 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

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

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

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

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

산성님의 프로필 이미지
산성

작성한 질문수

질문하기