본문 바로가기
JavaScript Study

JavaScript - #17. 전역변수의 문제점

by KMS_99 2023. 8. 31.

앞서서 계속 배우고 있지만 자바스크립트에서 전역변수의 무분별한 사용은 위험하다.

 

오늘은 그 이유에 대해서 알아 볼 예정이다.

 

1. 변수의 생명주기

변수는 선언되고 할당되며 필요성이 없어지면 소멸한다.

우리는 이러한 과정을 변수의 생명주기라고한다.

 

- 지역 변수의 생명주기

지역변수는 해당 지역의 생명주기와 같이 생성되고 소멸한다.

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

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

foo 라는 함수는 함수선언문에 의해 정의 되어있지만 정의만 된다고 생성되는 것이 아니다.

함수 실행문이 있어야 생성될 수 있다.

foo() 실행문이 실행되고 난 후 함수 foo는 실행되며 이 함수가 실행되고 나서야 내부에 있는 변수들이 생성되고 초기화 될 수 있다.

foo 함수가 실행이 되고 순서에 맞게 코드블록이 실행을 마치게 되면 함수는 소멸한다. 그렇다면 함수 내부에서 선언되었던 변수들은 참조가 가능할까?

해당 함수의 지역변수 x도 같이 소멸한 것을 볼 수 있다.

이 지역변수 x은 함수가 실행됨가 동시에 호이스팅이 발생하여, 스코프 최상단에서 undefined를 가진 변수로 초기화가 진행된다. 그후 값의 할당이 발생한다.

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

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

이 코드에서 확인 할 수 있듯이 함수 내부에서도 호이스팅이 일어난다는 것이다.

즉, 호이스팅은 전역변수가 아닌 지역변수에서도 일어나며, 이때 변수가 가진 스코프의 생성과 동시에 호이스팅됨을 알 수 있다.

또한 함수가 끝난 후 해당 변수에 참조할 수 없는 것을 보았을 때, 지역변수의 생명주기는 함수의 생명주기와 동일한 것을 알 수 있다.

 

- 전역 변수의 생명주기

전역변수는 코드의 실행과 동시에 호이스팅되어 초기화 된다.

전역변수의 생성 시점은 코드가 실행 될 때라고 할 수 있다.

 

그렇다면 전역변수의 소멸 시점은 언제일까?

 

전역변수는 전역객체의 프로퍼티가 된다.

전역변수는 코드가 실행될 때 코드 전체에서 존재하는 객체라고 생각하면 되겠다.

브라우저 환경에서 전역객체는 window이며, var로 선언된 전역 변수는 모두 window의 프로퍼티로 등록된다.

따라서 전역변수는 전역객체 window의 생성과 소멸시점을 따르며, window의 소멸시점은 더이상 실행시킬 코드가 없을 때이다. 즉 코드가 끝날 때까지로 정의될 수 있다.

 

2. 전역변수의 문제점

- 암묵적 결합

전역변수를 사용한다면, 어디서든 참조가능하여 변경될 수 있는 암묵적 결합을 허용하게 된다.

이는 코드의 규모가 커지면 커질 수록 코드 가독성이 나빠지며, 의도치 않게 상태가 변경되는 위험성이 높아진다.

 

- 긴 생명주기

전역변수의 생명주기가 지역변수의 생명주기보다 길기 때문에 메모리 리소스도 오랜시간 소비하게된다.

또한 전역변수의 상태가 변화 할 수 있는 시간도 길기 때문에 위험성이 높다.

 

- 스코프체인 종점에 존재

앞서 알아본 스코프 체인에서는 작은 스코프 단위 부터 상위 스코프로 한단계씩 탐색하여 원하는 변수를 참조한다고 하였다. 전역변수가 있는 스코프인 전역스코프는 마지막에 탐색되는 스코프로 만약 여러 함수가 중첩된 함수 내에서 전역변수를 참조한다고 하였을 때 해당 변수를 찾는 시간이 오래 걸릴 것이다.

 

- 네임스페이스 오염

자바스크립트의 가장 큰 문제점은 파일이 분리되어있어도 하나의 전역스코프를 공유하게되는 것이다.

따라서 다른 파일 내에서 동일한 이름으로 명명된 전역변수나 전역 함수가 같은 스코프 내에 존재할 경우 예상치 못한 결과를 불러온다.

 

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

전역변수의 무분별한 사용은 위험하며, 사용 할 이유가 없다면 사용을 지양해야한다. 

전역변수의 사용을 억제하는 몇가지 방법을 알아보자

- 즉시 실행 함수

함수 정의와 동시에 호출되는 즉시실행함수는 단 한번 호출된다. 

(function(){
    var num =100;
}())

console.log(num); //ReferenceError

 

- 네임스페이스 객체

전역에 네임스페이스 역할을 담당할 객체를 생성하고 전역변수처럼 사용하고 싶은 변수를 프로퍼티로 추가한다.

var MYAPP = {};

MYAPP.name ='Lee';

console.log(MYAPP.name);

이 방법은 객체의 프로퍼티가 변수의 역할을 대신하는 것이다. 식별자 충돌을 방지하는 기능이 있다.

 

- 모듈패턴

모듈 패턴은 클래스를 모방해서 관련이 있는 변수와 함수를 모아 즉시 실행함수로 감싸 하나의 모듈을 만든다.

정확한 이해는 클로저를 배워야 하므로 이런 것이 있다만 알면 되겠다.

 

캡슐화는 프로퍼티와 프로퍼티를 참조할 수 있는 동작인 메서드를 하나로 묶는 것을 이야기한다. 캡슐화는 객체의 특정 프로퍼티나 메서드를 감출 목적으로 사용도 가능하며 이를 정보 은닉이라고 한다.

 

자바스크립트는 타 언어의 public, private, proteceted 처럼 접근 제한자가 없기 때문에 제한을 두는데 모듈패턴이 유용하다.

var Counter = (function(){
    var number = 0;

    return {
        increase(){
            return ++number;
        },
        decrease(){
            return --number;
        }
    }
}())

console.log(Counter.number); // undefined
console.log(Counter.increase());
console.log(Counter.increase());
console.log(Counter.decrease());
console.log(Counter.decrease());

 

- ES6 모듈

ES6 모듈을 사용하면 더는 전역변수를 사용할 수 없다. ES6 모듈은 파일 자체의 독자적인 모듈 스코프를 제공한다.

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

'JavaScript Study' 카테고리의 다른 글

JavaScript - #19. 프로퍼티 어트리뷰트  (0) 2023.09.11
JavaScript - #18. let, const  (0) 2023.08.31
JavaScript - #16. 스코프  (0) 2023.08.30
JavaScript - #15. 함수(2)  (0) 2023.08.29
JavaScript - #14. 함수(1)  (0) 2023.08.29