[모던 자바스크립트 Deep Dive]14장 전역 변수의 문제점
14.1 변수의 생명 주기
- 생명 주기: 메모리 공간이 확보(allocate)된 시점 ~ 메모리 공간이 해제(release)되어 가용 메모리 풀(memory pool)에 반환되는 시점
- 전역 변수의 생명 주기: 애플리케이션의 생명 주기
14.1.1 지역 변수의 생명 주기
1
2
3
4
5
6
7
8
9
var x = "global";
function foo() {
console.log(x); // undefined
var x = "local";
}
foo();
console.log(x); // global
- 지역 변수의 생명 주기: 함수의 생명 주기
- 호이스팅은 스코프를 단위로 동작
- 함수 내의 변수는 전역 변수의 호이스팅과 달리, 함수가 실행될 때 호이스팅 된다.
- 즉, 호이스팅 = 변수 선언이 스코프의 선두로 올라온 것처럼 동작
- 정확히는, 변수는 자신이 등록된 스코프가 소멸(메모리 해제)할 때까지 유효
- 할당된 메모리 공간이 더 이상 참조되지 않을 때 가비지 콜렉터가 이를 해제해서 가용 메모리 풀에 반환
14.1.2 전역 변수의 생명 주기
- 전역 코드
- 특별한 진입점 없이 코드가 로드되면 곧바로 해석 및 실행
- 더 이상 실행할 문이 없을 때 종료
- 전역 객체
- 코드 실행 전 자바스크립트 엔진이 생성하는 특수한 객체
- 클라이언트 사이드 환경(브라우저)에서는 window, 서버 사이트 환경(Node.js)에서는 global 객체
- 참고로
window
는 웹페이지를 닫기 전까지 유효
- 참고로
- 전역 객체를 가리키는 식별자는 ES11부터
globalThis
로 통일 - 프로퍼티
- 표준 빌트인 객체
Object
,String
,Number
,Function
,Array
등
- 환경에 따른 호스트 객체
- 클라이언트 Web API 또는 Node.js의 호스트 API
**var
키워드로 선언한 전역 변수**와 전역 함수
- 표준 빌트인 객체
var
키워드로 선언한 전역 변수 = 전역 객체의 생명 주기
14.2 전역 변수의 문제점
- 암묵적 결합(implicit coupling)
- 모든 코드가 전역 변수를 참조 및 변경 가능
- 변수의 유효 범위가 커져 가독성이 나빠지고 상태가 의도치 않게 변경될 수 있다.
- 긴 생명 주기
- 메모리 리소스를 오랜 기간 소비
- 상태가 의도치 않게 변경될 수 있는 시간이 길어짐
- 심지어
var
키워드는 변수의 중복 선언도 허용1 2 3 4 5 6 7
var x = 1; // ... // 변수의 중복 선언. 기존 변수에 값을 재할당한다. var x = 100; console.log(x); // 100
- 심지어
- 스코프 체인 상에서 종점에 존재
- 변수 검색 시 전역 변수가 가장 마지막에 검색된다.
- 네임 스페이스 오염
- 파일이 분리되어 있어도 하나의 전역 스코프를 공유하므로 다른 파일에 중복된 이름이 존재할 수 있다.
14.3 전역 변수의 사용을 억제하는 방법
14.3.1 즉시 실행 함수
1
2
3
4
5
6
(function () {
var foo = 10; // 즉시 실행 함수의 지역 변수
// ...
})();
console.log(foo); // ReferenceError: foo is not defined
- 즉시 실행 함수: 정의와 동시에 단 한 번만 호출
- 코드를 즉시 실행 함수로 감싸, 변수를 즉시 실행 함수의 지역 변수로 만드는 방법
- 라이브러리 등에 자주 사용되는 방법
14.3.2 네임스페이스 객체
1
2
3
4
5
var MYAPP = {}; // 전역 네임스페이스 객체
MYAPP.name = "Lee";
console.log(MYAPP.name); // Lee
- 전역에 네임스페이스 역할을 할 객체를 생성하고, 전역 변수처럼 사용하고 싶은 변수를 프로퍼티에 추가
- 네임스페이스 객체를 중첩으로 넣어 계층을 만들 수 있다.
- 식별자 충돌은 방지하지만, 네임스페이스 객체가 전역 변수에 할당되어 좋은 방법은 아니다.
14.3.3 모듈 패턴
- 모듈 패턴: 관련이 있는 변수와 함수를 즉시 실행 함수 안에 모아 넣어 하나의 모듈 생성
- 클래스를 모방
- 전역 변수 억제 및 캡슐화 구현 가능
- 캡슐화: 프로퍼티와 메서드를 하나로 묶는 것으로, 정보은닉도 가능
- 프로퍼티: 객체의 상태
- 메서드: 프로퍼티를 참조하고 조작할 수 있는 동작(behavior)
- 정보 은닉: 객체의 특정 프로퍼티나 메서드를 감추는것
- 접근 제한자(access modifier): 공개 범위를 한정하는 제한자
- 자바스크립트를 빼고 대부분의 객체 지향 프로그래밍 언어가 사용
public
,private
,protected
등- 모듈 패턴을 사용해 접근 제한자를 사용한 것 같은 효과를 줄 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
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
14.3.4 ES6 모듈
- ES6 모듈은 파일 자체의 독자적인 모듈 스코프 제공
- ES6 모듈 내에서
var
키워드로 선언한 변수는 전역 변수가 아니다.
- ES6 모듈 내에서
script
태그에type = "module"
속성을 추가하면 로드된 자바스크립트 파일은 모듈로서 동작- 모듈 파일 확장자는
mjs
권장1 2
<script type="module" src="lib.mjs"></script> <script type="module" src="app.mjs"></script>
- 모듈 파일 확장자는
This post is licensed under CC BY 4.0 by the author.