스코프 — 변수가 어디까지 보이는가

같은 이름의 변수가 왜 어떤 곳에서는 보이고 어떤 곳에서는 안 보이는지, 그 경계를 정하는 규칙.

Seobway · · 6분

왜 이게 필요한가

아래 코드는 마지막 줄에서 터진다. 왜 그런지 설명할 수 있어야 나머지 전부가 풀린다.

function outer() {
  const secret = "숨김";
  console.log(secret); // "숨김"
}

outer();
console.log(secret); // ReferenceError: secret is not defined

secret 은 분명 만들어졌는데 밖에서는 없는 취급이다. 변수는 아무 데서나 보이지 않는다.
어디까지 보이는지를 정하는 경계가 스코프다.


어떻게 동작하는가

스코프는 이름을 찾는 범위다. 자바스크립트는 변수를 만나면 안쪽부터 바깥쪽으로
차례차례 뒤진다. 찾으면 멈추고, 끝까지 못 찾으면 ReferenceError.

경계는 세 종류다.

어디에서도 보인다. 파일 맨 바깥에 선언한 것.

const app = "blog";     // 어디서든 보인다

전역은 누구나 덮어쓸 수 있다는 뜻이기도 하다. 그래서 적을수록 좋다.

찾는 순서를 그림으로 보면 이렇다. 안쪽 상자에서 시작해 바깥으로 나간다.

인터랙티브 다이어그램: 이름을 찾아 바깥으로 나간다 (단계별로 재생할 수 있다)

  1. 블록 안에서 `msg` 를 찾는다. 여기에는 없다.
  2. 한 칸 바깥, 함수 몸통에서 다시 찾는다. 여기 있다.
  3. 만약 함수에도 없었다면 전역까지 올라간다.
  4. 전역에도 없으면 그때 ReferenceError 가 난다.

이 사슬을 스코프 체인이라고 부른다. 그리고 중요한 것 하나 — 이 사슬은
함수를 어디서 호출했느냐가 아니라 어디에 썼느냐로 정해진다.

const name = "전역";

function print() {
  console.log(name);   // 항상 "전역"
}

function run() {
  const name = "안쪽";
  print();             // "안쪽" 이 아니라 "전역" 이 찍힌다
}

run();

print 는 자기가 쓰여 있는 자리의 바깥을 본다. run 이 부른 것과 무관하다.
이 규칙을 렉시컬 스코프라고 한다. 코드를 읽는 것만으로 어떤 변수가 쓰일지 확정할 수 있다는 뜻이라,
디버깅이 훨씬 쉬워진다.


직접 확인

출력 순서를 먼저 예측하고 실행해라. 값을 바꿔 가며 다시 돌려도 된다 (Ctrl+Enter).

const where = "전역";

function outer() {
  const where = "함수";

  if (true) {
    const where = "블록";
    console.log("1:", where);
  }

  console.log("2:", where);
}

outer();
console.log("3:", where);

// var 로 바꿔 보면 2번이 어떻게 달라지는지 확인해라

흔한 실수


한 줄 정리

스코프는 이름을 찾는 범위이고, 안쪽에서 바깥쪽으로 한 방향으로만 찾는다.
그 사슬은 코드가 쓰인 자리로 정해진다.

참고

  1. [1] Scope — MDN Web Docs 용어 사전
  2. [2] let — MDN Web Docs
  3. [3] Executable Code and Execution Contexts — ECMAScript 사양

관련 글