우리가 사용할 변수를 선언할 때, 전역 변수로 선언하거나 지역변수로 선언해 사용하는 방법이 있다. 전역 변수와 지역변수의 개념에 대해서 잘 모를 때는 그냥 아무렇게나 사용했었는데 다시 공부하면서 공통으로 사용하는 변수만 전역 변수로 사용하고, 되도록이면 지역변수를 사용하는 것이 좋다는 것을 알게 되었다.
1. 전역변수와 지역변수
전역 변수는 프로그램 전체에서 접근할 수 있는 변수로, 글로벌 스코프를 갖는 변수이다. 즉, 함수 외부에서 선언된 변수라고 할 수 있으며, 프로그램이 종료되어야만 메모리에서 삭제되는 특성이 있다. 반면에, 지역변수는 함수 내부에서 선언된 변수로 함수가 실행되면 만들어지고 함수가 종료되면 메모리에서 삭제된다.
1) 전역변수와 지역변수의 사용 예제
// 전역변수
const name = 'Lia';
const submithandler = () => {
// 지역변수
const name = 'Minsu';
console.log(name); // 'Minsu'
}
submithandler();
console.log(name); // 'Lia'
이처럼 전역변수로 선언한 것보다 함수 내부에서 선언한 지역변수가 더 우위에 있다는 것을 알 수 있고, 같은 이름으로 선언했을 경우 함수 내부에서는 지역변수로 선언한 것이 실행된다는 특성을 가지고 있다.
2) var 키워드와 함수 레벨 스코프
var 키워드는 let, const와 달리 블록 레벨 스코프를 따르지 않고 함수 레벨 스코프를 따르기 때문에 전역 변수 사용 시 문제가 발생할 가능성이 높아진다.
1. 함수 레벨 스코프(var)
- 함수의 코드 블록만을 스코프로 인정하기 때문에 전역 함수 외부에서 생성한 변수는 모두 전역 변수가 된다.
- 그렇기 때문에 var 키워드를 사용하면 전역변수가 무분별하게 발생하는 문제를 야기할 수 있다.
var name = 'Lia';
console.log(name); // Lia
{
var name = 'Minsu'
}
console.log(name); //Minsu
위의 예시는 var 키워드를 사용한 예시인데, 함수 레벨 스코프를 따르는 var 키워드의 특성상 함수가 아닌 코드 블록 내의 변수는 전역 변수가 된다. 그렇기 때문에 위에서 선언한 name의 값을 재선언하여 새롭게 선언된 name 값이 console에 찍히는 것이다.
2. 블록 레벨 스코프(let, const)
- 모든 코드 블록 내에서 선언된 변수는 코드 블록 내에서만 유효하기 때문에 코드 블록 외부에서는 값을 참조할 수 없게 된다. 즉, 코드 블록 내부에서 선언한 변수는 지역 변수가 된다.
let name = 'Lia';
console.log(name); // Lia
{
let name = 'Minsu';
let num = 56;
}
console.log(name); // Lia
console.log(num); // Uncaught ReferenceError: num is not defined
위의 예시는 let을 사용한 예시인데 let의 경우 블록 레벨 스코프를 따르기 때문에 블록 내에서 선언된 것은 그 블록 내에서만 유효하다. 그렇기 때문에 var와는 달리 재선언이 되지 않고, 블록 내에서 선언한 num 역시 스코프 외에서는 값을 참조할 수 없게 된다.
2. 전역변수의 사용 이대로 괜찮을까?(전역 변수의 문제점)
전역 변수의 경우에는 프로그램 전체에서 접근이 가능하기 때문에 무분별한 사용은 예상치 못한 오류를 발생시킬 수 있다. 그렇기 때문에 반드시 사용해야 할 이유가 없다면 되도록이면 지역 변수를 사용해 선언해야 한다는 것이다.
전역 변수의 문제점을 다시한번 정리하자면,
1) 암묵적 결합과 중복 선언
- 모든 전역변수들은 암묵적으로 결합되어 있으며, 중복 선언이 일어날 경우 어디에서 어떻게 변경되었는지 찾기가 어렵다.
2) 긴 생명주기
- 전역 변수의 생명주기는 프로젝트가 실행되는 동안 계속 이어지기 때문에 생명주기가 길다.
- 생명주기가 길어지면 길어질수록 변수에 접근하고 재할당되는 과정이 발생할 가능성이 크다.
3) 네임스페이스 오염
- 자바스크립트는 파일이 분리되어있어도 하나의 전역 스코프를 공유한다.
- 그렇기 때문에 다른 파일에서 같은 이름으로 선언된 전역 변수가 같은 스코프 내에 존재할 경우 예상치 못한 결과를 가져올 수 있다.
4) 스코프 체인 상의 종점에 존재
- 전역 변수는 스코프 체인 상의 종점에 존재하기 때문에 변수를 찾을 때 전역 변수가 가장 마지막에 검색된다.
- 그렇기 때문에 전역 변수의 검색 속도가 느리다는 것이 단점이다.
3. 전역변수 억제 방법
전역 변수의 무분별한 사용을 막기 위해서는 되도록이면 지역변수를 선언하여 스코프의 범위를 좁혀주고, 생명주기를 짧게 하는 것이 방법이 될 수 있다.
1) 즉시 실행 함수를 사용할 것
- 즉시 실행 함수라는 것은 함수의 정의와 호출이 함께 일어나는 함수이다.
- 함수를 선언함과 동시에 즉시 실행시키며 함수의 지역을 생성하고, 함수 안에서 선언한 변수들은 모두 지역 변수가 된다.
2) 네임스페이스 객체
- 전역 스코프에 네임스페이스 객체를 하나 만들어 주어 사용하고자 하는 변수를 프로퍼티로 추가하면 된다.
3) 모듈 패턴
- 모듈 패턴이라는 것은 관련이 있는 변수와 함수를 모아 즉시 실행 함수로 감싸 하나의 모듈로 만드는 것이다.
- 모듈 패턴은 자바스크립트의 기능 중 하나인 클로저를 기반으로 동작한다.
- 클로저 : 자신이 선언될 당시의 환경을 기억하는 함수로 자바스크립트에서는 함수를 리턴할 때 클로저를 생성하며, 그 당시의 코드나 환경 등을 기억한다.
4) ES6 모듈
- ES6 모듈은 독자적인 모듈 스코프를 제공하기 때문에 모듈 내에서 var 키워드를 사용해도 이는 더 이상 전역 변수가 아니게 된다.
- 하지만 아직까지 Chrome61, FF 60, SF 10.1, Edge 16 이상 정도에서 지원한다.
- 예시
<script type='module' src='test.mjs'></script>
<script type='module' src='moduleTest.mjs'></script>