[JS] 모던 Javascript Deep Dive 14장 - 전역 변수의 문제점
업데이트:
전역 변수는 사용을 지양해야 한다. 그 이유와 전역 변수 사용 억제 방법에는 무엇이 있는지 알아보자.
[01] 변수의 생명 주기
변수는 생성되면 언제가 소멸한다. 이것을 변수의 생명 주기라 하는데 생명 주기가 없다면 한번 선언된 변수는 프로그램을 종료하지 않는 한 영원히 메모리 공간에 남아있는다.
- 변수의 생명 주기 = 메모리 공간이 확보된 시점부터 메모리 공간이 해제되는 시점까지
지역 변수의 생명 주기
지역 변수의 생명 주기는 다르다. 함수 내부에서 선언되면 함수가 호출되어 실행되는 동안에만 유효하다.
- 지역 변수의 생명 주기 = 함수의 생명 주기
🔍 지역 변수가 함수보다 더 오래 생존하는 경우
함수 내부에서 지역 변수가 선언되면 함수가 생성한 스코프에 등록된다. 변수는 스코프가 소멸될 때까지는 유효한데 누군가 스코프를 참조하고 있다면 스코프는 해제되지 않고 생존한다. 이것은 클로저와 관련이 있으므로 24장에서 더 자세히 다룬다고 한다.
스코프를 단위로 동작하는 호이스팅
var x = 'global';
function foo(){
console.log(x); // 이미 foo() 스코프 안에서 var 키워드로 x가 선언되고 undefined로 할당되어 있으므로 undefined가 출력
var x = 'local';
}
foo();
console.log(x); //global
지역 변수는 지역 스코프 내에서 호이스팅이 일어난다. 즉 호이스팅은 스코프를 단위로 동작한다.
전역 변수의 생명 주기
- 전역 변수의 생명 주기 = 애플리케이션의 생명 주기
🔍 전역 객체
전역 객체는 코드가 실행되기 이전 단계에 자바스크립트 엔진에 의해 어떤 객체보다도 먼저 생성되는 특수한 객체이다. 브라우저에서는 window, Node.js 에서는 global 객체를 의미한다.
var gVar = 5;
alert(window.gVar); // 5 (var로 선언한 변수는 전역 객체 window의 프로퍼티가 된다.)
var 키워드로 선언한 전역 변수는 전역 객체 window의 프로퍼티가 된다.
그런데 window 객체는 웹페이지를 닫기 전까지는 유효하다.
그러므로 var 키워드로 선언한 전역 변수의 생명 주기는 전역 객체의 생명 주기와 일치한다.
[02] 전역 변수의 문제점
암묵적 결합
코드 어디서든 참조할 수 있고 할당할 수 있는 변수는 암묵적 결합을 허용한다는 것이다. 변수의 유효 범위가 클수록 코드의 가독성은 나빠지고 의도치 않게 상태가 변경될 수 있는 위험이 있다.
긴 생명 주기
전역 변수는 생명 주기가 길다. 지역 변수는 그에 비해 생존 시간이 짧다.
이것은 전역 변수보다 상태 변경에 의한 오류가 발생할 확률이 작고 메모리 리소스도 짧은 기간 소비한다는 것을 의미한다.
스코프 체인 상에서 종점에 존재
전역 변수는 스코프 체인 상에서 가장 마지막에 존재한다. 변수를 검색할 때 끝까지 검색하느라 전역 변수의 검색 속도가 가장 느릴 것이다.
네임스페이스 오염
파일이 분리되어 있다 해도 하나의 전역 스코프를 공유한다는 것이 문제이다. 다른 파일에서 동일한 이름의 전역변수나 전역 함수가 같은 스코프 내에 존재할 경우 예상치 못한 결과가 생길 수 있다.
[03] 전역 변수의 사용을 억제하는 방법
전역 변수를 절대 사용하지 말라는 것은 아니지만 전역 변수를 반드시 사용해야 할 이유를 찾지 못한다면 지역 변수를 사용하라는 것이다.
즉시 실행 함수 사용
// () 소괄호 안에 감싼 함수 : 즉시 실행 함수
(function () {
var MYAPP = {};
MYAPP.student = {
name: 'Lee',
gender: 'male'
};
console.log(MYAPP.student.name); // Lee
}());
console.log(MYAPP.student.name); // Uncaught ReferenceError: MYAPP is not defined
즉시 실행 함수를 사용하면 즉시 실행되고 그 후 전역에서 바로 사라진다.
그래서 즉시 실행 함수 밖에서 출력한 학생의 이름은 출력되지 않은 것을 볼 수 있다.
네임스페이스 객체 - 최소한의 전역 변수 사용
var MYAPP = {};// 전역 네임스페이스 객체
MYAPP.name = 'Lee';
console.log(MYAPP.name); // 'Lee'
네임스페이스 역할을 담당할 객체를 생성하고 전역 변수처럼 사용하고 싶은 변수를 프로퍼티로 추가하는 방법이다.
식별자 충돌을 방지하는 효과는 있지만 네임 스페이스 객체 자체가 전역 변수에 할당되므로 그다지 유용한 방법은 아니다.
모듈 패턴
모듈 패턴은 클로저를 기반으로 동작한다. 전역 변수의 억제와 캡슐화까지 구현 가능하다.
📢 캡슐화 : 프로퍼티와 메서드를 하나로 묶는 것. 특정 프로퍼티나 메서드를 감추는 정보 은닉의 목적으로 사용하기도 함.
24장 클로저에서 자세히 살펴볼 예정이다.
ES6 모듈
ES6 모듈은 파일 자체의 독자적인 모듈 스코프를 제공한다.
script 태그에 type="module"
어트리뷰트를 추가하면 로드된 자바스크립트 파일은 모듈로서 동작한다. ES6 모듈의 파일 확장자는 모듈임을 명확히 하기 위해 mjs를 사용하도록 권장한다.
<script type="module" src="lib.mjs"></script>
<script type="module" src="app.mjs"></script>
일반적으로는 아직까지는 ES6모듈보다는 Webpack 모듈 번들러를 사용한다고 하는데 48/49장에서 자세히 알아볼 것이다.
댓글남기기