[JavaScript] 스코프(Scope) 개념정리

2026. 3. 10. 22:17·우아한테크코스
728x90

스코프란?

스코프는 식별자가 유요한 범위를 의미한다.

쉽게 말하면 자바스크립트 엔진이 코드를 실행할 때, 변수나 함수 같은 식별자를 어디까지 참조할 수 있는지를 결정하는 규칙이다.

 

모든 식별자(변수 이름, 함수 이름, 클래스 이름 등)는 자신이 선언된 위치에 따라 참조 가능한 유효 범위가 결정된다.

"스코프"란 개념이 없다면 같은 이름의 변수가 여러 곳에서 선언될 때 충돌이 발생하고, 코드가 예측 불가능하게 동작하지 않을까?

스코프는 이러한 네임스페이스 충돌을 방지하는 메커니즘이기도 하다.

 

단계별로 이해해보도록 하자.

 

**시작하기 전에 아랫글을 추천한다.**

 

[JavaScript] var / let / const 호이스팅과 TDZ

호이스팅이란?호이스팅은 자바스크립트 엔진이 코드 실행 전에 변수 선언을 해당 스코프의 최상단으로 끌어올리는 동작이다.중요한 건 var, let, const 셋 다 호이스팅이 된다는 점이다.💡차이는

bbin-guuuu.tistory.com

 


식별자 결정

식별자 결정은 자바스크립트 엔진이 이름이 같은 두 식별자 중 어떤 것을 참조해야 할지 판단하는 과정이다.

var x = "Global";

function foo() {
  var x = "Local";
  console.log(x); // "Local"
}

foo();
console.log(x); // "Global"

foo() 내부에서 x를 참조하면 자신의 지역 스코프(foo() 함수 내부)에서 먼저 찾는다.

전역에서의 x와 foo 내부의 x는 이름이 같지만 서로 다른 스코프에 존재하는 별개의 변수다.

자바스크립트 엔진은 코드의 실행 문맥(context) 을 고려해서 어떤 식별자를 참조할지 결정한다.

 

아직 지역 스코프, 전역 스코프 등 이해가 되지 않는다면 아래 스코프 체인에서 설명하는 사진을 참고하도록 하자.


스코프의 종류

스코프는 크게 전역 스코프와 지역 스코프로 나뉜다.

 

전역 스코프는 코드의 가장 바깥 영역이다.

전역 스코프에 선언된 변수는 어디서든 참조할 수 있다.

 

지역 스코프는 함수 내부와 같이 특정 영역 안에서만 유효한 범위다.

지역 스코프에 선언된 변수는 그 스코프와 하위 스코프에서만 참조할 수 있다.

출처: youngminss GitHub

예를 들어보겠다.

var globalVar = "나는 전역";

function example() {
  var localVar = "나는 지역";
  console.log(globalVar); // "나는 전역" (전역 참조 가능)
}

example();
console.log(localVar); // ReferenceError (지역 변수는 외부 참조 불가)

 

전역 변수는 함수 내부에서도 참조할 수 있지만, 지역 변수는 해당 함수 바깥(상위 스코프)에서 접근하면 ReferenceError가 발생한다.

지역 스코프는 외부로부터 내부 변수를 보호하는 캡슐 역할을 한다.


함수 레벨 스코프와 블록 레벨 스코프

자바스크립트에서는 스코프를 만드는 방식이 키워드에 따라 다르다.

 

함수 레벨 스코프는 var 키워드로 선언된 변수에 해당한다.

var는 오직 함수의 코드 블록(함수 몸체)만을 지역 스코프로 인정한다.

즉, if, for, while 같은 블록 안에서 var로 선언해도 지역 변수가 되지 않고 전역 변수처럼 동작한다.

var x = 1;

if (true) {
  var x = 10; // 같은 전역 변수 x를 덮어씀
}

console.log(x); // 10

위 코드를 살펴보자.

if 블록 안에서 var x = 10으로 선언했지만, var는 블록을 스코프로 인정하지 않기 때문에 전역의 x를 그대로 덮어쓴다.

의도치 않은 전역 변수 오염이 발생할 수 있어 var는 현대 자바스크립트에서 지양된다.

 

블록 레벨 스코프는 let과 const로 선언된 변수에 해당한다.

let/const는 if, for, while, try-catch 등 함수 블록 뿐만 아니라 모든 코드 블록을 지역 스코프로 인정한다.

let x = 1;

if (true) {
  let x = 10; // 블록 내부의 별개 변수
}

console.log(x); // 1

블록 안의 x와 바깥의 x는 완전히 별개의 변수로 취급된다.

블록이 끝나면 내부의 x는 소멸한다.


스코프 체인

함수 안에 함수를 중첩하면 스코프도 계층적으로 쌓인다

이 계층 구조를 스코프 체인이라고 한다.

 

자바스크립트 엔진은 변수를 참조할 때, 현재 스코프에서 먼저 찾고 없으면 상위 스코프 방향으로 순서대로 올라가며 탐색한다.

전역 스코프까지 올라갔을 때도 없으면 ReferenceError가 발생한다.

이 탐색 방향은 하위 -> 상위로만 이루어지며, 상위 스코프는 하위 스코프의 변수를 참조할 수 없다.

출처: youngminss GitHub

위 사진을 보자.

inner 함수에서 y를 참조할때, 자신의 지역 스코프(파란색) -> outer 함수의 지역 스코프(초록색) -> 전역 스코프(빨간색) 순서로 탐색하게 되는데, y는 자신의 스코프에 없고 그 다음 순서인 outer 함수의 지역 스코프에도 없고 전역 스코프에서 찾게된다.

이처럼 스코프가 체인처럼 연결되어 상위로 탐색하는 동작이 스코프 체인이다.


렉시컬 스코프

렉시컬 스코프는 함수의 상위 스코프가 어디서 결정되느냐에 관한 규칙이다.

자바스크립트는 렉시컬 스코프를 따른다.

 

렉시컬 스코프에서 함수의 상위 스코프는 함수가 호출된 위치가 아니라, 함수가 선언(정의)된 위치에 따라 결정된다.

함수가 어디에 선언되었는지가 그 함수의 스코프 체인을 확정짓는다.

const x = "전역";

function inner() {
  console.log(x);
}

function outer() {
  const x = "outer";
  inner(); // outer 안에서 호출하지만...
}

outer(); // "전역"

inner는 outer 안에서 호출되었지만, 선언은 전역에서 이루어졌다.

렉시컬 스코프 규칙에 따라 inner의 상위 스코프는 outer가 아니라 전역으로 이미 결정되어 있다.

따라서 x를 참조하면 전역의 "전역"이 출력된다.

반대로, 함수가 호출된 위치에 따라 스코프가 동적으로 결정되는 방식을 다이나믹 스코프(Dynamic Scope)라고 한다.
자바스크립트는 다이나믹 스코프가 아닌 렉시컬 스코프를 채택하고 있다.

렉시컬 스코프와 스코프 체인? 헷갈리지 않아?

사실 필자는 이 두 개념이 헷갈렸다.

사실 두개가 동일하게 자신의 지역 스코프에서 참조할 식별자가 없으면 상위 스코프로 하나씩 올라가며 참조할 식별자를 찾는 과정이라 생각했다.

 

하지만 렉시컬 스코프와 스코프 체인은 비슷해 보이지만 서로 다른 층위의 개념이다.

 

렉시컬 스코프는 스코프 체인의 모양이 어떻게 결정되는지에 관한 규칙이다.

"이 함수의 상위 스코프는 어디냐?"라는 질문에 답하는 것이 렉시컬 스코프이며, 그 답은 항상 선언된 위치다.

 

스코프 체인은 이미 결정된 스코프 구조를 바탕으로, 식별자를 실제로 탐색하는 동작이다.

현재 스코프에서 시작해 상위 스코프로 올라가며 찾는 과정 자체가 스코프 체인이다.

 

코드를 보며 이해해보자.

const a = "전역";

function outer() {
  const a = "outer";
  return inner;
}

function inner() {
  console.log(a);
}

outer()(); // "전역"

이 예시에서 inner가 outer 내부에서 반환되어 실행되었지만, inner의 상위 스코프는 선언된 위치인 전역이다(렉시컬 스코프).

그리고 a를 찾기 위해 inner의 스코프 -> 전역 스코프 순으로 탐색한다(스코프 체인).

렉시컬 스코프가 체인의 구조를 결정하고, 스코프 체인은 그 구조를 따라 탐색한다.

 

두 개념의 관계를 한 문장으로 정리하면,
렉시컬 스코프가 스코프 체인의 모양을 결정하고, 스코프 체인은 그 모양대로 식별자를 탐색한다.
728x90

'우아한테크코스' 카테고리의 다른 글

[JavaScript] var / let / const 호이스팅과 TDZ  (0) 2026.03.10
[TDD] TDD와 페어프로그래밍  (2) 2026.03.08
[우아한테크코스 8기] 레벨 1 Gemini Canvas 웹앱 만들기 회고  (0) 2026.03.01
[우아한테크코스 8기] 웹 프론트엔드 최종 합격 후기  (4) 2026.01.30
[우아한테크코스 8기] 프리코스 오픈미션 회고 💡  (2) 2025.11.25
'우아한테크코스' 카테고리의 다른 글
  • [JavaScript] var / let / const 호이스팅과 TDZ
  • [TDD] TDD와 페어프로그래밍
  • [우아한테크코스 8기] 레벨 1 Gemini Canvas 웹앱 만들기 회고
  • [우아한테크코스 8기] 웹 프론트엔드 최종 합격 후기
프론트 개발자 김현중
프론트 개발자 김현중
👋반갑습니다 저는 나눔을 실천하는 개발자 꿈나무 김현중입니다⌨️🚀
  • 프론트 개발자 김현중
    삥구의 개발블로그
    프론트 개발자 김현중
  • 전체
    오늘
    어제
    • 분류 전체보기 (106)
      • 알고리즘 (5)
      • Swift (3)
      • 컴퓨터네트워크 (1)
      • React (39)
      • Docker (1)
      • SQL (8)
      • Database (2)
      • 배포 (1)
      • Spring (9)
      • TypeScript (5)
      • Next.js (13)
      • Git (1)
      • 회고 (1)
      • 컴퓨터그래픽스 (2)
      • Python (1)
      • Brew (1)
      • LangChain (2)
      • React Native (1)
      • 우아한테크코스 (10)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    nextjs
    react
    frontend
    database
    appRouter
    Spring
    Next.js
    ReactHooks
    springboot
    프론트엔드
    백준
    회고
    typescript
    우테코
    웹개발
    java
    우아한테크코스
    Backend
    데이터베이스
    javascript
  • 최근 댓글

  • 최근 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.1
프론트 개발자 김현중
[JavaScript] 스코프(Scope) 개념정리
상단으로

티스토리툴바