렉시컬 스코프(Lexical Scope)와 클로저(Closure)

Published by

on

자바스크립트에서 스코프와 클로저는 한 번쯤은 꼭 이해하고 넘어가야 하는 개념입니다.

특히 렉시컬 스코프는 함수가 “어디서 실행되었는가”가 아니라 “어디서 정의되었는가”에 따라 변수를 참조한다는 점에서 중요합니다.

아래 예제를 보면 그 차이를 바로 이해할 수 있습니다.


렉시컬 스코프 (Lexical Scope)

렉시컬 스코프란 함수가 정의된 위치에 따라 변수의 접근 범위가 결정되는 것을 의미합니다.

즉, 함수 내부에서 변수를 찾을 때는 함수가 작성된 코드의 위치를 기준으로 스코프 체인을 타고 올라갑니다.

let outerVariable = "외부 변수";

function outerFunction() {
    let innerVariable = "내부 변수";

    function innerFunction() {
        console.log(outerVariable); // "외부 변수"
        console.log(innerVariable); // "내부 변수"
    }

    innerFunction();
}

outerFunction();

이 코드를 보면 innerFunction은 outerFunction 내부에 정의되어 있기 때문에,

outerFunction의 스코프와 전역 스코프에 모두 접근할 수 있습니다.

즉, 함수가 “정의된 위치”를 기준으로 어떤 변수를 사용할 수 있는지가 결정된다는 게 핵심입니다.


렉시컬 환경 (Lexical Environment)

렉시컬 환경은 말 그대로 현재 스코프에 어떤 변수들이 있고, 어떤 값을 가지고 있는지를 저장하는 구조입니다.

자바스크립트 엔진은 함수가 실행될 때마다 새로운 렉시컬 환경을 만들고,

여기에 변수 이름과 실제 값의 매핑을 저장합니다.

function createCounter() {
    let count = 0;

    return function() {
        count += 1;
        console.log(count);
    };
}

const counter = createCounter();
counter(); // 1
counter(); // 2

여기서 createCounter()를 호출하면 새로운 렉시컬 환경이 만들어지고, count라는 변수가 그 안에 저장됩니다.

createCounter의 실행이 끝났더라도, 반환된 내부 함수가 count를 계속 참조하고 있기 때문에

자바스크립트 엔진은 이 환경을 메모리에서 지우지 않습니다.

그 결과, counter()를 여러 번 호출할 때마다 이전 상태가 유지됩니다.

이게 바로 클로저(Closure) 입니다.


클로저의 핵심은 “기억”이다

클로저는 한마디로 말해 함수가 자신이 선언된 렉시컬 환경을 기억하는 구조입니다.

이 특성 덕분에 외부 함수의 실행이 끝난 뒤에도, 내부 함수는 외부 변수에 접근할 수 있습니다.

function makeAdder(x) {
    return function(y) {
        return x + y;
    };
}

const add5 = makeAdder(5);
console.log(add5(3)); // 8

이 예제에서 add5는 x = 5라는 값을 기억합니다.

함수가 반환된 이후에도, x는 여전히 살아 있고 y와 더해집니다.


데이터 은닉과 상태 유지

클로저는 단순히 변수를 기억하는 것 이상으로,

데이터 은닉상태 유지라는 실질적인 역할을 합니다.

function secureCounter() {
    let count = 0;
    return {
        increment() { count++; },
        get() { return count; }
    };
}

const counter = secureCounter();
counter.increment();
console.log(counter.get()); // 1

이 경우 count는 외부에서 직접 접근할 수 없습니다.

오직 increment와 get 메서드만이 내부 상태를 변경하거나 읽을 수 있습니다.

즉, 클로저를 이용하면 객체지향의 “private” 속성과 유사한 효과를 낼 수 있습니다.


정리

  • 렉시컬 스코프는 함수가 정의된 위치를 기준으로 변수 접근 범위를 결정한다.
  • 렉시컬 환경은 실행 시점에 스코프 내의 변수와 값을 저장하는 구조다.
  • 클로저는 내부 함수가 외부 함수의 렉시컬 환경을 기억하기 때문에, 외부 함수가 종료된 뒤에도 변수에 접근할 수 있다.

자바스크립트의 이벤트 핸들러, 비동기 콜백, 모듈 패턴 등은 모두 이 구조 위에서 작동합니다.

결국 렉시컬 스코프와 클로저를 이해하면, “자바스크립트가 변수를 언제, 어디서 찾는가”를 정확히 예측할 수 있게 됩니다.


참고

댓글 남기기

오픈바이브 | oftenvibe.com에서 더 알아보기

지금 구독하여 계속 읽고 전체 아카이브에 액세스하세요.

계속 읽기