(JS) 전역 변수의 문제점

호두파파·2021년 2월 14일
0

Scope & Hoisting

목록 보기
4/4

변수의 생명 주기

변수는 선언에 의해 생성되고 할당을 통해 값을 갖는다. 그리고 가비지 컬랙터에 의해 언젠가 소멸된다. 즉, 변수는 생명주기를 지니고 있다.

전역 변수의 생명 주기는 애플리케이션의 생명 주기와 같다. 하지만, 함수 내부에서 선언된 지역 변수는 함수가 호출되면 생성되고 함수가 종료되면 소멸한다.

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

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

지역변수 x는 함수 foo가 호출되기 전까지는 생성되지 않는다. 함수가 종료되면 지역변수도 소멸되어 생명주기가 종료된다.즉, 함수가 호출되어 실행되는 동안에만 지역변수는 유효를 가진다.

전역의 var 키워드

var키워드로 선언한 전역 변수는 전역 객체의 프로퍼티가 된다.

브라우저 환경에서 전역 객체는 window이기 때문에 브라우저 환경에서 var키워드로 선언한 전역변수는 window의 프로퍼티가 된다.

이 전역 객체 window는 웹페이지 종료 시점까지 유효하며, 전역변수 var키워드는 웹페이지가 종료할때까지 유효하다.

전역 변수 선언의 문제점

1. 암묵적 결합 (implicit coupling)

전역 변수는 내 의도와는 다르게 어디서든지 전역변수를 참조 및 변경이 가능하다.
이는 암문적 결합을 허용하는 것으로 변수의 유효 범위가 크면 클수록 코드의 가독성이 나빠지고 의도치 않게 상태가 바뀔 수 있다.

2. 긴 생명주기

전역 변수는 생명주기가 프로그램의 종료시점과 거의 일치하므로, 이는 상태 변경기회를 늘리게 된다. 의도치 않은 실수가 발생할 가능성이 높다.

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

전역 변수는 스코프 체인 상에서 종점에 존재한다. 이는 변수를 검색할 때 전역변수가 가장 마지막에 검색된다는 것을 의미한다. 결국, 전역변수의 검색속도가 가장 느리다라는 것을 의미하기도 한다.

4. 네임 스페이스 오염

JS의 가장큰 문제는 .js파일이 분리되어 있어도 하나의 전역 스코프를 공유하는 것이다. 협엽을 진행하게 될 경우 전역 변수 이름으로 충돌이 생길 확률이 매우 높다


전역 변수 사용 억제 방법

변수의 스코프는 좁을 수록 좋다.

1. 즉시 실행 함수

즉시 실행 함수는 함수 정의와 호출을 동시에 진행한다. 모든 코드를 즉시 실행 함수로 감싸면 모든 변수는 즉시 실행 함수의 지역 변수가 된다. 이러한 특성은 전역 변수의 사용을 제한하는 것도 한 방법이다.

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

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

2. 네임 스페이스 객체

네임 스페이스 객체는 말 그대로 NameSpace 역할을 담당할 객체를 생성하고, 전역 변수처럼 사용하고 싶은 변수를 프로퍼티로 추가하는 방법이다.

let nameSpace = {}; // 전역 네임 스페이스 객체

nameSpace.person = {
  name: 'Yang',
  address: 'seoul'
};

console.log(nameSpace.person.name); // Yang

네임 스페이스 안에 객체를 만들어서 계층적으로도 활용이 가능하다.
네임스페이스를 분리해 식별자 충돌을 방지하는 효과는 있으나 네임 스페이스 객체 자체가 전역 변수에 할당이 되므로 유용하지 않다.

3. 모듈 패턴

클래스를 모방해 관련이 있는 변수와 함수를 모아 즉시 실행 함수로 감싸 하나의 모듈을 형성한다.

모듈 패턴은 JS의 강력한 기능인 클로저를 기반으로 동작한다. 이는 전역 변수의 억제와 캡슐화까지 구현할 수 있다.

캡슙화
외부에 공개될 필요가 없는 정보를 외부에 노출하지 않고 숨기는 것(정보 은닉)

모듈 패턴은 전역 네임 스페이스의 오염을 막는 기능은 물론 한정적이기는 하지만 캡슐화를 구현하기 위해 사용한다.

// 변수에 즉시 실행 함수 할당
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 모듈

전역 변수의 남발을 억제하기 위해서 ES6에서 도입된 모듈을 사용할 수 있다.

profile
안녕하세요 주니어 프론트엔드 개발자 양윤성입니다.

0개의 댓글