JS - 스코프(Scope)

이지호_tech 2024. 4. 24. 13:21

스코프(Scope) 란

변수나 함수같은 식별자가 유효한 범위를 의미한다.
크게 Global Scope / Local Scope로 분류된다.

JS엔진 입장에서 오류가 발생하는걸 알수 잇는 방법은 오류가 발생한 문이 실행 되기전 에 프로그램 내 스코프와 변수 관계 전부를 사전 파악하는 것이다.

프로그램이 컴파일 되는 이 시점에 스코프는 결정이 된다. (== 런타임 환경에는 영향을 받지 않는다.)

이렇게 컴파일 타임에 결정되는 스코프를 렉시컬 스코프라고 한다.

컴파일 도중에 프로그램 실행에 필요한 모든 렉시컬 스코프가 들어간 지도가 만들어지고, 실제 각 스코프를 실행해야만 하는 런타임 전까지 스코프가 생성되지 않는다
(렉시컬 : 컴파일 단계 중 첫 단계인 렉싱(파싱) 을 의미)

 

사실 프로그램이 실행 되는 동안 js 엔진은 변수가 속한 스코프 정보를 이미 알고 잇기때문에 변수가 어떤 스코프에서 왔는지 여러개를 탐색할 필요가 없다!

정리하자면
선언을 하든 표현식을 쓰든 함수를 정의하면 새로운 스코프가 만들어진다.
스코프 중첩을 어떻게 만들었는지에 따라 스코프 계층 관계가 만들어지고, 이를 스코프 체인이라고 부른다.

스코프 체인은 변수를 위 혹은 바깥쪽 방향으로만 접근 가능하도록 통제한다.
새 스코프가 생기면 변수를 넣을 새로운 공간이 만들어진다.

스코프 체인 내, 다른 계층에 있는 스코프에 이름이 같은 변수가 있으면 섀도잉 때문에 바깥 스코프에 있는 변수에 접근할 수 없게 된다.

 

전역 스코프(Global Scope)
프로그램의 시작부터 끝까지 어디서든 접근할 수 있는 변수나 함수 등의 식별자가 존재하는 범위를 의미.
모든 지역 스코프에서 접근이 가능하다.
코드를 모듈 단위로 쪼개는 개발 방식이 자리 잡으면서 전역 네임스페이스에 식별자를 저장하는 방식을 지금은 많이 쓰지 않는다.

 

지역 스코프(Local Scope)

특정 함수 또는 코드 블록 내에서만 변수나 함수등의 식별자가 유효한 범위를 의미

지역 스코프에 선언된 식별자는 해당 함수나 블록 외부에서는 접근할 수 없다.  이는 데이터를 캡슐화하고, 외부의 영향으로부터 변수를 보호하는 데 유용하다.

특징 

- 접근 제한: 지역 스코프에 선언된 변수는 해당 스코프 내에서만 접근 가능.
- 생명주기: 지역 변수는 함수나 블록이 실행될 때 생성되고, 실행이 종료되면 소멸.
- 메모리 효율: 지역 변수는 사용이 끝나면 메모리에서 제거되므로, 메모리 관리에 효율적.

 

본질적으로, 스코프가 필요한 이유는?

정보 보안 분야에는 최소 권한의 원칙( POLP ) 이라는 규율이 존재한다.
시스템 구성 요소에는 최소한의 권한을 부여하고 접근도 최소화 하며 노출 역시 최소화 해야 한다는 설계 원칙으로, 방어적인 아키텍처 설계를 대변한다.
POLP를 기반으로 아키텍처를 설계해 각 구성 요소가 필요한 최소한의 기능으로 연결되면, 한 구성 요소의 손상이나 장애가 시스템에 미치는 영향이 최소화 되므로 시스템 전체 보안이 더 강력해진다.

POLP를 지킬때, 노출을 최소화 하고 싶은 항목은 그럼 무엇일까?
=> 스코프마다 등록된 변수의 노출이다.
이름 충돌 / 예기치 않은 작동 , 의도하지 않은 종속성이 일어나기에 기본적으로 필요한 최소한의 것만 노출하고 나머지는 가능한 비공개로 유지한다.

핵심은 렉시컬 스코프 규칙에 맞게 코드를 작성하면 프로그램의 변수를 운영 목적와 의미에 맞게 체계화할 수 있다는 점!
변수를 정리하는 데 있어서 가장 중요한 것은 변수를 불필요한 범위에 과도하게 노출되지 않도록 하는 것!

 

function createCalculator(initialValue) {
    let currentValue = initialValue; // `currentValue`는 `createCalculator`의 지역 변수입니다.

    return {
        add: function(number) {
            currentValue += number;
            return currentValue;
        },
        subtract: function(number) {
            currentValue -= number;
            return currentValue;
        },
        getCurrentValue: function() {
            return currentValue;
        }
    };
}

const calculator = createCalculator(10);
console.log(calculator.getCurrentValue()); // 10
console.log(calculator.add(5)); // 15
console.log(calculator.subtract(3)); // 12
// console.log(currentValue); // 오류: `currentValue`는 `createCalculator` 함수 스코프 내에서만 접근 가능합니다.

 

해당 예시에서
currentValue에 대한 접근은 오직 createCalculator가 반환하는 객체의 메서드를 통해서만 가능합니다. 
이는 변수를 의도치 않게 변경하는 것을 방지하고, 함수의 사용자가 사용할 수 있는 인터페이스를 명확하게 정의합니다.

변수를 적적한 범위 내에서만 사용하도록 구성함으로써, 코드의 안전성과 유지보수성을 높이는 방법을 보여줍니다.