5 min to read
스코프(scope)
스코프 (Scope)
스코프는 코드 내 변수, 함수, 객체의 접근성과 가시성을 정의하는 역할임. 전역(Global), 로컬(Local)이 있음.
함수나 블록 외부에서 선언된 변수는 글로벌 스코프를 보유하므로 코드베이스 어디서든 엑세스 및 수정할 수 있음. 반대로 변수가 블록내 혹은 함수 내에서 선언된 경우 로컬 스코프라서 해당 함수나 해당 블록 내로 스코프가 제한됨.
let
과 const
선언으로 블록 스코프가 등장했으며, 중괄호{} 로 캡슐화된 블록 내 이런 키워드를 활용하면 그 안에서 선언된 변수가 블록 스코프를 획득함. 이는 그 블록과 그 안의 중첩블록 스코프 내에서 엑세스 가능함.
또한 JS는 함수 스코프를 허용하는데, 이는 함수 내에서 선언된 변수가 함수 외부의 가시성을 배제하고 함수 스코프 내에서먼 엑세스 할 수 있음을 나타냄.
JS 스코프를 이해하면 런타임 중 변수, 함수, 객체 접근성과 가시성을 동적 제어할 수 있음.
블록(Block)
중괄호로 둘러싸인 블록은 명령문을 통합하는 역할을 하고, 이런 다목적 블록은 if/else문, 스위치문, for 와 while 루프 같은 흐름 제어 문을 포함해 다양한 시나리오에 적용됨.
블록은 새 스코프를 생성하며, 블록 내 일련의 문을 포함시켜 변수와 함수가 널리 사용되는 주변 스코프와 분리된 별도의 환경을 구축함. 이 스코프의 로컬화는 요소의 가시성 및 접근성에 대한 더 나은 제어 환경을 제공함으로서 다른 부분의 코드와 의도치 않은 충돌을 방지할 수 있음.
블록은 IIFE(immediately-invoked function expressions) 즉시 호출 함수 표현식인 자체 실행 함수를 제작할 때 유용함. 블록 내에 함수를 캡슐화 하고 즉시 호출하면 명시적인 함수 호출 없이 포함된 코드를 실행 가능.
본질적으로 블록은 조직 단위 역할을 하여 코드내에서 순서와 구조를 조성함. 이는 흐름 제어를 촉진, 스코프를 설정, 독립적 실행 단위 생성을 지원함.
예시1: if문은 x가 0보다 큰 경우에만 실행되는 코드블록을 만듬.
if(x > 0){
console.log("x is greater than 0");
x--;
}
예시2:
let
및const
키워드를 사용해 변수와 함수에 대한 새로운 스코프를 만듬.
{
let x = 10;
const y = 20;
// x와 y는 이 블록 내에서만 접근가능.
}
console.log(x);
console.log(y);
// ReferenceError: x와 y는 정의되지 않음.
JS의 스코프 지정 규칙은 변수를 넘어 확장되며 함수, 인수, 클로저까지 포함됨. 함수가 다른 함수 내 중첩시 해당 함수는 바깥쪽 함수의 변수 및 인수에 대한 엑세스를 상속받음. 이를 클로저라고 하는데 이 덕분에 내부 함수는 부모 함수의 실행이 완료된 후에도 부모 함수의 상태를 유지 및 활용가능. 이 기능을 사용해 개발자는 외부 스코프의 컨텍스트 및 변수를 활용해 캡슐화된 자체 포함 코드단위를 만들 수 있음.
글로벌 스코프
글로벌 스코프는 실행 컨텍스트 내 가장 높은 수준의 스코프임. 이는 다른 함수나 블록 외부에서 정의된 변수와 함수를 포함하므로 전체 프로그램에서 엑세스 가능함. 모든 코드의 기본 스코프 역할을 하며 변수나 함수가 블록 내에 포함되지 않고 선언되면 자동으로 글로벌 스코프의 일부가 됨.
웹 브라우저의 컨텍스트에서 글로벌 스코프는 창 객체에 해당하며, 글로벌 스코프 내 정의된 변수와 함수는 페이지의 모든 스크립트에서 엑세스가 가능하며 브라우저의 JS콘솔에서 사용할 수도 있음. 그러나 글로벌 스코프를 과도하게 사용하면 코드베이스에서 이름 충돌이나 예기치 못한 동작이 발생할 수 있으니 주의할 것.
글로벌 스코프에 지나치게 의존하면 변수나 함수가 정의된 위치나 사용법을 식별하기 어려워지기 때문에 유지보수가 어려워짐. 따라서 글로벌 스코프는 꼭 필요한 경우에만 사용하는 것이 좋음. 대신 함수 스코프나 블록 스코프를 수용시 더 작고 관리하기 편한 스코프를 만들 수 있음.
var globalVariable = "This variable is in the global scope";
function globaclFunction();{
console.log("This function is in the global scope");
}
Scope Pollution(스코프 오염)
글로벌 스코프를 불필요하고 과도하게 사용시 스코프 오염이 발생해 충돌 및 의도치 않은 결과가 발생함. 이런 상황은 로컬 스코프 내에서 선언된 변수가 글로벌 스코프에서 선언된 변수와 이름이 동일해 로컬 변수가 글로벌 변수를 가리거나 덮어 쓰는 경우에 발생함.
스코프 오염이 발생하면 혼란 및 유지보수가 어려워지고 글로벌 변수를 의도치 않은 수정시 예상치 못한 동작이 발생하여 추적하기 어려운 버그가 발생할 수 있음.
따라서 적절한 범위 내에서 변수 캡슐화 및 우선순위를 지정하는 것이 좋음. 변수의 범위를 적절하게 지정하면 이름 지정 충돌 위험을 줄일 수 있음.
모듈식 프로그래밍 방식을 준수하고 함수 스코프 또는 블록 스코프를 사용해 글로벌 스코프에 대한 의존도를 최소화하는 것이 좋음.
예시1:
var
,let
,const
키워드 없이 글로벌 스코프를 사용함.
x = 10; // x는 글로벌 변수
function myFunction(){
x = 20; // x는 는 글로벌 변수 변수임으로 전 값을 덮어씀.
}
예시2: 로컬 변수와 동일한 이름의 글로벌 변수 사용. 변수 x는 myFunction 함수 내 글로벌 변수와 동일한 이름을 가진 로컬 변수로 선언됨. 로컬 변수가 글로벌 변수를 덮어쓰므로 이름 지정충돌, 예기치 않은 동작이 발생.
let x = 10; // 글로벌 변수
function myFunction(){
let x = 20; // 로컬 변수
}
예시3: 실수로 글로벌 변수 수정. myFunction 함수는 동일 이름을 가진 로컬 변수를 선언하지 않고 글로벌 변수 x값을 수정함.
let x = 10; // 글로벌 변수
function myFunction(){
x = x + 1; // 글로벌 변수를 수정함.
}
스코프 오염시 지침
var
,let
,const
키워드를 사용해 변수를 선언할 것.- 고유한 변수 이름 사용
- 글로벌 변수 사용 최소화
- 글로벌 변수 직접 수정 금지 : 예기치 않은 동작을 예방하려면 변수를 함수에 인수로 전달하고 함수 스코프 내에서 수정을 수행해 변경 사항을 예측 가능하게 유지할 것.
- 프라이빗 변수에 대한 클로저 활용 : 변수가 의도한 범위 밖에서 엑세스 되거나 수정되지 않도록 하려면 클로저를 활용해 프라이빗 변수를 생성하여 캡슐화하면 됨.
- strict 모드 활성화 : 스크립트나 함수 시작부분에
'use strict';
를 추가해 strict 모드 활설화시 스코프 오염을 방지할 수 있음. - 글로벌 및 로컬 스코프의 차이점 이해
- 블록 및 함수 스코프의 이해: 블록 내에서
let
,const
로 선언된 변수는 블록 스코프를 가지며 함수 내에서 선언된 변수는 함수 스코프를 가짐.