본문 바로가기
개발지식

[Javascript] 스코프 체이닝이란 무엇인가?

by 구라미 2024. 3. 5.

 

 

1. 스코프 체이닝이란?

스코프 체이닝은 프로그래밍에서 변수나 함수의 유효 범위 즉 스코프를 결정하는 과정을 설명하는 개념이다. 변수나 함수가 참조될 때 해당하는 범위를 찾는 메커니즘을 말한다.

스코프는 일반적으로 중첩된 함수나 블록의 범위를 가리키는데 이렇게 중첩된 스코프에서 변수나 함수를 참조할 때, 현재에 있는 스코프에서 찾지 못하면 외부 스코프로 차례차례 이동하여 탐색하는 과정을 스코프 체이닝이라고 한다. 이때 탐색의 과정은 최상위인 전역스코프부터 시작해서 필요한 변수나 함수가 있는 스코프까지 계속해서 진행되는데 이것이 스코프 체이닝의 과정이다.

대부분의 프로그래밍 언어에서 스코프 체이닝은 정적 스코프와 동적 스코프 두 가지 방식 중 하나를 따른다. 대부분의 언어는 정적 스코프를 사용하는데, 정적스코프는 변수나 함수의 스코프가 코드의 렉시컬 구조에 의해 결정되는 것이다. 동적 스코프는 실행 시점에 함수가 호출된 위치에 따라 스코프가 결정되는 방식이다.

 

2. 렉시컬 스코프란?

정적 스코프에서 변수나 함수의 스코프가 렉시컬 구조에 의해 결정된다고 했다. 렉시컬 스코프란 무엇일까?
렉시컬 스코프는 함수가 어디서 호출되었는지가 아니라 어디에 선언(정의)되었는지에 따라 변수의 유효 범위가 결정되는 스코프 규칙이다.

이러한 렉시컬 스코프를 다른 말로 정적 스코프라고 한다. 이는 코드가 작성된 렉시컬 구조(소스 코드 상의 위치)에 따라 변수의 스코프가 정의되기 때문이다.
예를 들어, 함수 A 안에서 함수 B가 선언되었고, 함수 B 안에서 변수 x를 참조한다고 한다면, 변수 x의 스코프는 함수 B의 범위에 해당한다. 어디에서 함수 B를 호출하든지 간에, 변수 x는 항상 함수 B의 스코프 안에 있습니다. 이것이 렉시컬 스코프의 핵심이다.

 

3. Javascript에서 어떻게 스코프를 정할까?

Javascript에서 스코프를 정하는 방식은 아래와 같다. 

1) 전역스코프

  • 스크립트의 가장 바깥쪽에 선언된 변수나 함수는 전역 스코프에 속한다.
  • 전역 스코프에 선언된 변수나 함수는 어디서든지 접근할 수 있다.
var globalVar = 'I am a global variable';

function globalFunction() {
    console.log('I am a global function');
}


2) 지역스코프

  • 함수 내에서 선언된 변수나 함수는 해당 함수의 지역 스코프에 속한다.
  • 지역 스코프에 선언된 변수나 함수는 해당 함수 내부에서만 접근할 수 있다.
function localFunction() {
    var localVar = 'I am a local variable';
    
    function innerFunction() {
        console.log(localVar); // localVar에 접근 가능
    }
    
    innerFunction();
    
    console.log(globalVar); // globalVar에 접근 가능 (전역 스코프)
}

localFunction();
console.log(localVar); // 에러: localVar는 localFunction 내부에서만 유효

 

3) 블록 스코프

  • ES6(ECMAScript 2015)부터 let과 const 키워드를 사용하여 블록 스코프를 생성할 수 있다.
  • 중괄호({})로 둘러싸인 코드 블록 내에서 선언된 변수는 블록 스코프에 속한다.
  • 블록 스코프에 선언된 변수는 해당 블록 내에서만 접근할 수 있다.

function blockScopeExample() {
    if (true) {
        let blockVar = 'I am a block-scoped variable';
        console.log(blockVar); // blockVar에 접근 가능
    }
    
    console.log(blockVar); // 에러: blockVar는 블록 스코프 내부에서만 유효
}

blockScopeExample();



4) 함수 스코프 vs 렉시컬 스코프

  • 함수 스코프는 함수 내에서 선언된 변수는 해당 함수 전체에서 유효하다는 개념이다.
  • 렉시컬 스코프는 함수를 어디에서 호출했는지가 아니라, 함수를 어디에 정의했는지에 따라 스코프가 결정된다.
var x = 10;

function funcScope() {
    var y = 20;
    console.log(x); // x에 접근 가능 (렉시컬 스코프)
    console.log(y); // y에 접근 가능 (함수 스코프)
}

funcScope();
console.log(x); // x에 접근 가능 (전역 스코프)
console.log(y); // 에러: y는 funcScope 함수의 지역 변수

 

4. 스코프 체이닝이 이뤄지는 과정

변수나 함수를 참조할 때, 현재 스코프에서 해당 식별자(변수 또는 함수)를 찾을 수 없을 때 외부 스코프로 이동하여 찾아가는것을 스코프 체이닝이라고 한다고 했다. 이 과정은 일반적으로 중첩된 함수나 블록의 스코프에서 발생하는데 그 과정의 흐름은 다음과 같다.

1) 변수 또는 함수 참조

- 코드에서 변수나 함수를 참조할 때 해당 식별자가 현재 스코프에 있는지 확인다.

2) 현재 스코프에서 식별자 검색

- 만약 해당 식별자가 현재 스코프에 있다면 더 이상 스코프 탐색을 하지 않는다.

3) 외부 스코프로 이동

- 현재 스코프에서 해당 식별자를 찾을 수 없다면, 외부 스코프로 이동하여 다시 탐색한다.

4) 외부 스코프에서 식별자 검색

- 외부 스코프에서 해당 식별자를 찾을 때까지 이 과정을 반복하는데 만약 최상위(전역) 스코프까지 도달하여도 식별자를 찾지 못한다면, 해당 변수나 함수는 정의되지 않았다는 에러가 발생한다.

var globalVar = 'I am a global variable';

function outerFunction() {
    var outerVar = 'I am an outer variable';
    
    function innerFunction() {
        var innerVar = 'I am an inner variable';
        console.log(globalVar); // 스코프 체이닝: 전역 스코프에서 globalVar를 찾음
        console.log(outerVar); // 스코프 체이닝: 외부 함수 스코프에서 outerVar를 찾음
        console.log(innerVar); // 현재 함수 스코프에서 innerVar를 찾음
    }
    
    innerFunction();
}

outerFunction();


이 예시에서 innerFunction()은 innerVar를 직접 정의했기 때문에 현재 스코프에서 바로 접근할 수 있다. 그러나 globalVar와 outerVar는 현재 스코프에 없으므로 스코프 체이닝을 통해 외부 스코프에서 해당 변수들을 찾는다.

댓글