TIL

<모던 자바스크립트 Deep Dive> 14장 전역 변수의 문제점 요약

낭만인 2022. 2. 17. 21:35

14. 전역 변수의 문제점

1) 변수의 생명 주기

- 변수는 생성, 소멸되는 생명 주기(Life cycle)를 가짐

- "자신이 선언된 위치"에서 생성, 소멸되는데 따라서 전역 변수는 애플리케이션 생명 주기를 갖고, 지역 변수는 함수 생명 주기를 가짐

function foo() {
	var x = 'local';
    console.log(x); // local
    return x;
}

foo();
console.log(x); // ReferenceError: x is not defined
//지역 변수 x는 foo 함수가 호출되어 실행되는 동안에만 유효함

 

- 단, 지역 변수의 경우 해당 함수 스코프가 어딘가에서 계속 참조 중이라면 사라지지 않음

- 호이스팅이란 변수 선언이 스코프의 선두에 이루어지는 것을 뜻하며, 자바스크립트 엔진에 의해 전역 변수는 실행 전 제일 먼저, 지역 변수는 함수 내부에서 제일 먼저 선언이 이루어짐

var x = 'global';

function foo() {
	console.log(x); // undefined - 호이스팅에 의해 변수의 선언만 이루어진 상태
	var x = 'local';
}

foo();
console.log(x); // global

 

- 특히 전역 변수는 var 키워드로 선언된 경우, 전역 객체의 프로퍼티가 되어 전역 객체의 생명 주기를 가지게 됨

- 전역 객체란 코드 실행 전 자바스크립트 엔진에 의해 가장 먼저 생성되는 특수한 객체로, 클라이언트 사이드 환경(브라우저)에서는 window, 서버 사이드 환경(Node.js)에서는 global 객체를 의미

 

 

2) 전역 변수의 문제점

1. 암묵적 결합

- 모든 코드가 전역 변수를 참조, 변경 가능하게 되는 것을 뜻함

- 코드의 가독성이 나빠지고, 상태 변경의 위험성 높아짐

 

2. 긴 생명 주기

- 전역 변수는 생명주기가 길기 때문에 상태 변경에 의한 오류가 발생할 확률 높아짐

 

3. 스코프 체인 상에서 종점에 존재

- 전역 변수는 스코프 체인 상에서 종점에 존재하기 때문에, 가장 마지막에 검색되므로 검색 속도가 제일 느리다고 할 수 있음

 

4. 네임스페이스 오염

- 전역 변수는 파일이 달라도 전체가 공유함

- 동일 이름의 전역 변수나 함수가 존재할 위험성 존재

 

 

3) 전역 변수의 사용을 억제하는 방법

- "전역 변수를 반드시 사용해야 할 이유를 찾지 못한다면 지역 변수를 사용해야 한다."

 

1. 즉시 실행 함수

- 모든 코드를 즉시 실행 함수 블록으로 감쌈 -> 전역 변수 사라짐

(function () {
	var foo = 10; // 즉시 실행 함수의 지역 변수
    // ..
}());

console.log(foo); // ReferenceError: foo is not defined

 

2. 네임스페이스 객체

- 네임스페이스의 역할을 하는 객체에 전역 변수처럼 사용하고 싶은 변수를 프로퍼티에 추가

var MYAPP = {}; // 전역 네임스페이스 객체

MYAPP.name = 'Lee';

console.log(MYAPP.name); // Lee

 

3. 모듈 패턴

- 관련있는 변수, 함수를 즉시 실행 함수로 감싸 하나의 모듈로 만듦

- 흡사 클래스와 같음

- 전역 변수의 억제 + 캡슐화(+ 정보은닉)

- 정보은닉과 관련하여, 자바스크립트는 접근제한자가 따로 없으므로 개발자가 직접 만들어주어야 함(퍼블릭 멤버, 프라이빗 멤버)

var Counter = (function () {
	// private 변수
	var num = 0;
    
    // 외부로 공개할 데이터나 메서드를 프로퍼티로 추가한 객체를 반환
    return {
    	increase() {
         return ++num;
        },
        decrease() {
         return --num;
        }
    }
}());

// private 변수는 외부로 노출되지 않음
console.log(Counter.num); // undefined

console.log(Counter.increase()); // 1
console.log(Counter.increase()); // 2
console.log(Counter.decrease()); // 1
console.log(Counter.decrease()); // 0

 

4. ES6 모듈

- 전역 변수 사용이 불가함

- 독자적 모듈 스코프를 제공

- 모듈 어트리뷰트를 추가하여 사용 가능하며 구형 브라우저는 사용이 불가함

<script type="module" src="lib.mjs"></script>
<script type="module" src="app.mjs"></script>

 

- 일반적으로 브라우저보다 웹팩 등의 모듈 번들러를 사용

 

 

 

 

 

참고 : 도서 <모던 자바스크립트 Deep Dive>