본문 바로가기

개발/정의

스코프(Scope)란?

 

스코프는 자바스크립트를 이용하는 데에 있어 필수적인 개념입니다.

이 포스팅 뒤로 클로저에 대해 알아볼 건데,

그전에 앞서 스코프의 정의가 먼저 필요하기 때문에 스코프 정의를 먼저 정리해보겠습니다.

 

 

스코프(Scope)의 정의

 

함수를 작성할 때 아래와 같이 중괄호 '{ }'를 이용하여 함수의 범위를 작성합니다.

function hello(){
	alert('함수 작성');
}

즉, [변수가 영향을 미치는 범위], [변수의 유효 범위],  [코드가 유효한 범위]라고 할 수 있으며 규칙입니다.

그리고 스코프의 종류에따라 변수, 함수, 코드 등의 유효 범위가 달라질 수 있습니다.

 

스코프(Scope)의 종류

스코프의 종류에 대해 알기 쉽게 알아봅시다.

 

1.동작

- 정적 스코프

- 동적 스코프

 

2.레벨

- 함수 레벨 스코프

- 블록 레벨 스코프

- 전역 스코프

- 지역 스코프

 

3.추가로 알아야할 사항

- 스코프 체인

 

 

 

스코프가 단순히 범위라고만 알고 있으면 안 되는 이유는 선언의 시점에 따라 값이 달라질 수 있기 때문입니다.

그래서 동작에 따라 나뉘는 정적 스코프, 동적 스코프에 대해 알아봅시다.

 

동작

- 정적 스코프

Javascript는 정적 스코프의 특성을 가지고 있습니다.

정적 스코프의 규칙에 따라 호출 스택과 관계없이 선언 시점에 스코프를 결정합니다.

function home(){
    var sister = '여동생 숙제 중';
}

function getSister(){
	console.log(sister); // sister is not defined
}

getSister(); 

sister is not defined이 되는 이유는 정적 스코프이기 때문입니다.

함수를 호출할 때가 아니라 선언할 때 스코프가 정해지고 외부 변수는 내부 변수에 접근할 수 없기 때문에 not defined이 됩니다.

 

 

 

- 동적 스코프

정적 스코프와는 반대로 동적 스코프의 선언은 런타임 도중에 실행 콘텍스트나 호출 콘텍스트에 의해 결정됩니다.

 

[정적 스코프일 때]

var sister = '여동생 숙제 중';

function home(){
    var sister = '여동생 집에없다';
    getSister();
}

function getSister(){
	console.log(sister); // 여동생 숙제 중
}

home();

 

[동적 스코프일 때]

var sister = '여동생';

function home(){
    var sister = '여동생 집에없다';
    getSister();
}

function getSister(){
	console.log(sister); // 여동생 집에없다
}

home();

 

즉,

정적 스코프는 소스코드가 작성된 콘텍스트에서 결정되며 

동적 스코프는 프로그램 런타임 도중에 실행 콘텍스트나 호출 콘텍스트에서 결정됩니다.

 

 

 

레벨

- 함수 레벨 스코프

var로 선언된 변수, 함수들은 함수 레벨 스코프가 됩니다.

함수가 유효 범위입니다.

function hello(name){
  if(name){
  	var greet = name + '님 안녕하세요';
  }

  console.log(greet); // 이하나님 안녕하세요
}

hello('이하나');

function이 유효 범위이므로 if 스코프 내에 선언된 greet는 hello 변수 내에서 접근 가능합니다.

아래 블록 레벨과 비교해서 보면 더욱 확실히 개념을 잡을 수 있을 것입니다.

 

 

- 블록 레벨 스코프

ES6부터 지원하기 시작한 let, const 키워드로 선언된 변수, 함수들은 블록 레벨 스코프가 됩니다.

블록이 유효 범위입니다.

function hello(name){
  if(name){
  	let greet = name + '님 안녕하세요';
  }

  console.log(greet); // greet is not defined
}

hello('이하나');

if의 스코프가 유효 범위이므로 greet에 접근하지 못하여 not defined이 나옵니다.

 

함수 레벨 스코프가 사용하기에는 더 편리하지만 블록 레벨 스코프보다 스코프의 범위가 넓으므로 코드에 대한 복잡성을 증가하는 요인이 됩니다. 따라서 변수의 유효 범위는 좁을수록 좋고 선택이 가능하다면 블록 레벨 스코프를 사용해야 합니다. 

 

 

- 전역 스코프

전체가 범위며 전역 스코프에서 변수를 선언하게 되면 어디서든지 참조할 수 있는 전역 변수가 됩니다.

하나의 html에서 두 개의 js파일을 로드해서 사용할 때에도 전역 변수는 사용이 가능합니다.

// index.js
var global = '난 글로벌해';

// pages.js
console.log('global'); // 난 글로벌해

전역 변수를 남발하게 되면 변수이나 함수의 중복이 될 가능성이 커지며 코드를 예측할 수 없어집니다.

그렇기 때문에 즉시 실행 함수를 사용해서 전역 변수를 해당 파일(모듈)에서만 범위를 억제하는 방법들이 많이 쓰입니다.

(function(){
	var APP = APP || {};
    
    APP.info = {
    	name : 'chat app',
        version : '1.2.1'
    };
    
    APP.Start = function(){
    	// ....
    };
        
    console.log(APP.info.name); // chat app
})();

console.log(APP.info.name); // APP is not defined

 

 

- 지역 스코프

함수 코드 블록이 만든 스코프로 함수 내부와 하위 함수의 변수와 함수만 참조가 가능합니다.

function local(){
	var me = '난 지역이야';   
}

function callLocal(){
	console.log(me); // me is not defined
}

callLocal();

지역에서 선언한 건 같은 지역에서만 참조가 됩니다.

함수 스코프나 블록 스코프를 생각하면 쉬울 것 같습니다.

 

 

 

추가로 알아야 할 사항

- 스코프 체인(Scope Chain)

내부 함수에서 외부 함수의 변수에 접근은 가능하지만

외부 함수에서 내부 함수의 변수에는 접근할 수 없습니다.

스코프 체인은 내부 함수에서 변수를 찾기 위해 외부 함수로 접근할 때에 탐색을 하게 되는 관계를 말합니다.

 

스코프의 탐색은 해당 스코프 내부를 먼저 탐색하고 선언된 것이 없다면 한 단계 위의 스코프를 탐색하며  반복적으로 이루어 집니다. 

찾을 때까지 과정을 반복하면서 상위 환경을 참조하려고 합니다.

 

이 과정은 해당 선언을 찾거나 null이 될 때(더 이상의 참조가 불가능할 때) 탐색을 멈춥니다.

이것을 스코프 체인이라고 합니다.

 

 


참조 링크