[Modern JS Deep Dive] CH14-전역 변수의 문제점

Boo Sung Jun·2022년 7월 4일
0

JavaScript

목록 보기
6/27
post-thumbnail

Modern JavaScript Deep Dive 스터디 - CH14 전역 변수의 문제점

참고 자료: ⟪모던 자바스크립트 Deep Dive⟫"(이웅모 지음,위키북스, 2020)


1. 변수의 생명 주기

  • 변수: 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 or 그 메모리 공간을 식별하기 위해 붙인 이름
  • 변수는 생명 주기(life cycle) 존재
  • 변수의 생명 주기: 메모리 공간 확보(allocate) -> 메모리 공간 해제(release) -> 가용 메모리 풀(memory pool)에 반환

1) 지역 변수의 생명 주기

  • 함수 내부에 선언된 지역 변수 -> 함수 호출시 생성, 함수 종료시 소멸

2) 전역 변수 생명 주기

  • 전역 코드: 코드 로드 되자마자 곧바로 해석되고 실행
  • => 전역 변수 생명주기는 전역 코드의 마지막 문이 실행되어 더 이상 실행할 문이 없을 때 까지
  • => var 키워드로 선언한 전역 변수는 전역 객체의 생명 주기와 일치

    전역 객체(global object)

    • 코드 실행 전 단계에서 자바스크립트 엔진에 의해 어떤 객체보다도 먼저 생성되는 특수한 객체
    • 브라우저(클라이언트 사이드)에서는 window, Node.js(서버 사이드 환경) 에서는 global 객체가 해당

2. 전역 변수의 문제점

1) 암묵적 결합(implicit coupling)

  • 전역 변수는 코드 내 어디서든 참조하고 할당 가능 -> 모든 코드가 전역 변수를 참조하고 변경할 수 있는 암묵적 결합 허용
  • 변수의 유효범위가 클수록 코드의 가독성은 나빠짐 + 의도치 않게 상태가 변경될 수 있는 위험도 증가

2) 긴 생명주기

  • 전역 변수는 프로그램이 종료하기 전까지 메모리 공간에 할당
  • var 키워드로 선언한 변수 경우, 변수의 중복 선언을 허용 -> 변수 이름이 중복될 가능성이 높고 의도치 않은 재할당 발생 가능

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

MYAPP.person = {
  name: "Boo",
  age: "25",
};

console.log(MYAPP.person.name);  // Boo

3) 모듈 패턴 사용

  • 클래스(class) 를 모방해서 관련이 있는 변수와 함수를 모아 즉시 실행 함수로 감싸 하나의 모듈을 만드는 방법
  • 클로저(closure) 기반으로 동작
  • 전역 변수의 억제와 캡슐화(encapsulation) 구현 가능 -> 정보 은닉(information hiding) 가능
var Counter = (function () {
  // private 변수 -> 외부에서 참조 불가
  var num = 0;

  // public 변수 -> 외부에서 참조 가능
  // 외부로 공개할 데이터나 메서드를 프로퍼티로 추가한 객체를 반환
  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 모듈

  • 파일 자체의 독자적인 모듈 스코프를 제공
  • 모듈 내에서 var 키워드로 선언한 변수 는 더는 전역 변수가 아님 -> window 객체의 프로퍼티도 아님
  • 모던 브라우저 에서는 ES6 모듈을 사용 가능
  • script태그type="module" 어트리뷰트 추가해서 사용
  • 모듈의 파일 확장자는 mjs를 권장
<script type="module" src="lib.mjs"></script>
<script type="module" src="app.mjs"></script>

ES6 모듈

  • IE를 포함한 구형 브라우저에서는 동작 안함
  • Webpack 등의 모듈 번들러를 일반적으로 사용(트랜스파일링이나 번들링이 필요)

0개의 댓글