본문 바로가기
Front-End/자바스크립트 (JavaScript)

[자바스크립트] 스코프 (Scope)

by MS_developer 2022. 9. 14.

 

처음 자바스크립트를 공부했을 때 변수의 선언과 할당을 배우면서 한 가지 의문점이 생겼다.

 

'let, const, var 같은 게 다양하게 나오는데 왜 let만 쓰지? 각각 의미가 다른가?'

 

해당 의문점을 해결하기 위해 스코프의 개념과 더불어 자료형의 종류에 대해서도 알아보자.


스코프(Scope)란?

MDN에선 스코프를 "현재 실행되는 컨텍스트로, 값과 표현식이 "표현"(visible)되거나 참조될 수 있다"라고 정의한다. 언뜻 듣기에는 이해하기 어려울 수 있지만, 실로 적절한 설명이라고 생각한다. 좀 더 추상적으로 다가가 보자면, 스코프는 마치 우리가 확대경scope를 통해 세상의 일정 부분만 "보이는" 것 처럼 제한된 영역을 말한다. 컴퓨터 시스템에서 "제한된 영역"이란 우리가 선언하고 할당하는 변수가 접근할 수 있는 범위를 말한다.

잘 되네요

위 코드를 살펴보자. 탬플릿 리터럴을 활용한 간단한 함수식을 선언했고, 호출했을 때 정상적으로 작동이 된다.

이 때 한 가지 호기심이 들었다. wantFall()이라는 함수 안에서 어쨌든 '가을'이라는 키워드가 필요해 변수를 선언하고 할당했으니, 밖에서도 사용할 수 있지 않을까? 라는 생각이 들었다.

대실패다. 뭐가 문제일까? 에러를 살펴봤다.

참조에러ReferenceError? 정확히는 모르겠지만 우리가 사용했던 ${fall}이라는 변수가 정의되지 않았다고 한다.

에러를 참고해 fall을 "가을"로 바꾸니 작동이 잘 된다.

문제점을 다시 되짚어 보면 결국 error가 말하고 있던 점은 fall이라는 변수를 함수식 내에서 선언했지만, 밖에서는 "참조"해 활용할 수 없다는 얘기였다. 이는 앞서 말했던 스코프를 벗어난 행동이기 때문이다. MDN 문서의 정의를 다시 한 번 생각해보면, fall이라는 변수는 "함수식 안"에서 실행된 컨텍스트다. 즉 함수를 호출하지 않는 한, 함수식 외부에서는 해당 변수를 사용하거나 바꿀 수 없다.

 


왜 스코프를 쓸까?

스코프를 쉽게 생각해보면, 전체 문서(window) 안에 각각의 "영역"을 선포하는 울타리가 쳐져 있는 것이다. 언뜻 보기엔 불편해 보이지만, 이러한 방식을 채택했을 때의 장점을 생각해보면 납득이 간다.

 

 

만약 우리가 대형 프로젝트에서 작업을 하고 있다고 가정해보자. 그동안 배웠던 간단한 지식들만으로도 거대한 하나의 웹사이트를 제작하고 관리하는데는 수많은 인력이 들 것을 예상할 수 있다. 프로젝트 중에는 내가 선언한 변수를 다른 사람이 그 존재를 모른 채 새로운 변수로 선언해 사용할 수도 있을 것이다. 이 경우에 기존에 사용하고 있던 변수의 값이 변경된다면 개발 중이던 기능에 의도치 않은 오류나 변화가 일어날 수 있다. 

내가 선언한 변수를 누군가 사용했다..

스코프는 위와 같은 경우를 어느 정도 방지할 수 있다. 만약 내가 fall이라는 변수를 단 한번만 사용할 것 이라면 함수식 안에 변수를 선언해 사용할 수 있을 것이다.

물론 위의 예시에도 문제점이 생긴다. 먼저 이전에 의도한 기능과는 다른 함수식이 완성되었다. 스코프는 한정된 "영역"안에 season이라는 변수가 선언되고 할당되었기 때문에 자유롭게 변수를 바꿀 수 없고, 기존에 만들었던 함수식보다 유연한 사용이 어렵다.

일련의 과정들을 일부 해소하고 좀 더 자유롭게 변수를 사용하고 제한할 수 있는 방법이 바로 스코프를 사용하는 가장 큰 이유가 아닐까 생각한다.


전역 스코프(Global scope)와 지역 스코프(Local scope)

스코프는 위 그림처럼 중첩이 가능하다. 마치 울타리 안에 울타리를 두르는 것과 같다고 생각하면 조금 수월하다. 단, 바깥쪽에서 선언한 변수는 안쪽 스코프에서 사용 가능하지만, 반대로 안쪽 스코프에서 선언된 변수는 밖에서 사용할 수 없다는 사실을 숙지하고 스코프의 종류를 살펴보자.

 

1. 전역 스코프 (Global Scope)

전역 스코프는 말 그대로 전체 영역Global을 아우르는 스코프로, 어떤 위치(스코프)에서든 자유롭게 사용할 수 있는 범위다. 위의 예시를 참조해 봤을 때, 전역 스코프는 변수 A가 선언된 가장 넓은 공간이다. 이에 따라 변수 A는 전역변수(전역 스코프에 선언된 변수)라고 칭하며, 프로그램 전체에서 접근할 수 있는 변수이다. 

 

2. 지역 스코프 (Local Scope)

지역 스코프는 [스코프1]을 제외한 모든 스코프를 일컫는데, 특정 코드 안에서만 사용할 수 있는 범위다. 전역 스코프에 전역변수가 있듯, 제한된 영역(지역)에서만 사용할 수 있는 변수를 지역변수라고 한다.

위와 같이 변수를 선언했을 때 같은 이름을 가지고 있는 변수가 있다면 해당 지역 스코프에서 선언된 지역변수가 전역변수보다 높은 우선순위를 가지고 있다.

변수를 선언하지 않은 경우 기존의 변수(예시의 경우 밖에 선언된 전역변수)에 새로운 값을 재할당 할 수 있는데, 이 경우 변수값이 완전히 변해버리므로 조심하도록 하자. 또한 위처럼 전역변수의 경우 변수값이 쉽게 변할 수 있으므로 필요한 경우가 아니라면 전역변수의 선언을 지양하는 게 좋아보인다.

 

또한 지역 스코프는 두 가지 스코프로 나눌 수 있다.

A. 함수 스코프(Function Scope)

함수 스코프는 함수가 선언되었을 때 생성되는 스코프로 해당 함수 내에서 선언된 변수는 함수 내에서만 접근 가능하다. 함수 스코프에서는 var 키워드를 사용하는데, 함수 내에서 변수를 선언하는데 사용한 var 키워드는 지역 변수로 유지된다. (함수 밖에서 사용한 var 키워드는 전역 변수로 취급된다.)

 

B. 블록 스코프(Block Scope)

블록 스코프는 블록(중괄호){}을 기준으로 생성되는 스코프로 해당 블록 내에서 선언된 변수는 블록에서만 접근이 가능하다. 블록 스코프는 let, const 키워드를 사용한다. var 키워드와의 차이점을 확인하기 위해 아래 예시를 확인해보자.

첫 번째 변수의 경우 정상적으로 작동 되었는데, 왜 두 번째 변수는 에러가 나왔을까? 앞서 언급했듯 var 키워드는 함수 스코프를 따르므로 for 반복문 안에서 선언된 변수 i를 사용할 수 있다. 하지만 두 번째 함수식에서 사용된 let 키워드는 변수 i를 (안쪽)블록문으로 제한하기 때문에 for 반복문 외부에서 i를 사용할 때 "참조에러"가 발생한다.

 

따라서 상황과 용도에 알맞게 let,const,var 키워드를 사용하면 될 것 같다. 단, 개인이 아닌 프로젝트 규모의 프로그래밍을 한다면 실수로 전역변수로 활용되지 않기 위해 var 키워드 사용은 지양하되 알맞게 사용하는 게 좋을 것 같다는 생각이 든다.


참조

 

 

댓글