FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

자바스크립트의 특징이자, 문제인 전역 변수에 대해 알아봅시다. ## 전역 변수의 문제점 > 전역 변수를 남용하면 많은 문제점이 있다고 합니다. 무슨 이유일까요? ### 변수의 생명주기 > 변수는 자신이 선언된 위치에 생성되고 소멸합니다. 이를 생명 주기(Life Cycle)라고 해요. 예를 들어볼까요? 아래 예제는 `let`, `const`가 아닌 `var`를 사용하여 설명합니다. ```js var x = '전역'; function foo() { var y = '지역'; console.log(y); // 지역 return y; } foo(); console.log(y); // undefined ``` 함수 내부에 선언된 지역 변수(`y`)는 함수 호출 시 생성되고 함수 종료와 함께 소멸(`undefined`)합니다. 하지만 전역 변수(`x`)는 대체 언제 소멸, 아니 생성될까요? 우리는 호이스팅(Hoisting)에 대해 이해하고 있으니 변수 선언은 선언문의 위치 상관 없이 `가장 먼저 실행`됨을 알 수 있습니다. 이를 풀어서 말하면 런타임에 실행되는 것이 아니라, 그 이전 단계에서 자바스크립트 엔진에 의해 먼저 실행되는 것이라 할 수 있죠. 단, 이 설명은 지역 변수에 해당하지 않고, `전역 변수`에 해당합니다. 지역 변수는 위에서 언급한 그대로 실행되거든요! 그림으로 보면 이렇게 되겠죠? ```js var x = '전역'; // 전역 변수 x 생성 function foo() { // 지역 변수 y 생성 var y = '지역'; // 지역 변수 y 값 할당 console.log(y); return y; // 지역 변수 y 소멸 } foo(); console.log(y); // undefined // 전역 변수 x 유효 ```
### 전역 변수의 문제점? > 어디서든 접근하고 변경할 수 있다면, 그것은 과연 좋기만 할까요? 이제부터 전역 변수가 가지는 문제점과 그 이유를 하나씩 살펴봅니다. 1. 암묵적 결합(Implicit Coupling) - 전역 변수를 개발자가 `의도하여` 선언한 경우, 해당 코드를 **어디서든 참조하거나 할당하겠다**는 겁니다. - 변수의 유효 범위가 클수록 가독성은 나빠집니다. - 예측하지 못한 영역에서 변수의 상태가 변경될 위험성이 높아집니다. 2. 긴 생명 주기(Long Life Cycle) - 전역 변수는 `애플리케이션의 생명 주기`와 **동일**합니다. - 활성화 되어 있는 시간이 기므로, 메모리 자원도 오래 소비합니다. - 전역 변수의 상태를 변경하거나 변경할 수 있는 위험성이 높습니다. - `var` 키워드는 변수 중복 선언을 허용하므로 의도치 않은 재할당이 이뤄질 수 있습니다. 3. 스코프 체인의 종점(Endpoint to Scope Chain) - 전역 변수가 `가장 마지막에` 검색됩니다. 즉, **전역 변수의 검색 속도가 가장 느립니다**. 4. 전역 네임스페이스 오염(Global Namespace Pollution) - 자바스크립트는 `파일이 분리`되어 있어도 **하나의 전역 스코프를 공유**합니다. - 다른 파일에 동일한 이름의 전역 변수가 존재하면 문제가 발생할 위험성이 높아집니다.
### 개선하는 방법 > 전역 변수의 무분별한 사용은 위험한데, 어떻게 이를 방지(억제)할까요? 전역 변수를 **반드시** 사용해야 할 이유가 있다면 사용하는 것이 맞습니다. 그러나 변수의 스코프는 하위, 즉 좁을수록 좋습니다. 필요한 상황에서 생성과 소멸을 반복하게 만들어야 `명시적인 결합`이 가능해지니까요. 그럼 어떤 방식을 통해 방지할 수 있는지 알아볼까요? 1. 즉시 실행 함수(Immediately Invoked Function Expression) - `단 한 번 호출`되는 특성을 통해 **모든 변수를 즉시 실행 함수의 지역 변수**로 만드는 방법입니다. - 전역 변수를 생성하지 않으므로 `라이브러리`에 자주 사용됩니다. ```js (function(){ var x = 10; // IIFE의 지역 변수 }()); console.log(x); // ReferenceError: x is not defined ``` 1. 전역 네임스페이스 객체(Global Namespace Object) - 전역에 네임스페이스 역할을 담당할 객체를 선언하고, 사용할 전역 변수를 프로퍼티에 추가하는 방법입니다. - 네임스페이스를 가지므로 식별자가 충돌할 가능성은 낮아지나, 해당 객체가 `전역 변수`에 할당되므로 유용하진 않습니다. ```js var APP = {}; // 전역 네임스페이스 객체 // 원시 값 할당하기 App.school = false; // 참조 값 할당하기 App.person = { name: 'amy', age: 16, }; console.log(App.school); // false console.log(App.person.name); // amy ``` 3. 모듈 패턴(Module Pattern) - 클래스(Class)를 모방합니다. 변수, 함수를 모아 즉시 실행 함수로 감싸 하나의 모듈을 만드는 방법입니다. - 자바스크립트의 `클로저`를 기반으로 동작합니다. 나중에 더 자세히 알아봐요! - 접근 제어자가 존재하지 않는 자바스크립트에서 객체 지향 프로그래밍의 특징인 **캡슐화(Encapsulation)** 를 흉내 낼 수 있습니다. ```js var App = (function(){ // 외부에서 참조가 불가능한 private 변수 var year = 2021; return { older() { return ++year; }, younger() { return --year; }, getYear() { return year; } } }()); console.log(App.year); // undefined console.log(App.older()); // 2022 console.log(App.getYear()); // 2022 console.log(App.older()); // 2023 console.log(App.getYear()); // 2023 console.log(App.younger()); // 2022 console.log(App.getYear()); // 2022 ``` - 위 즉시 실행 함수는 객체를 반환합니다. 이 객체에는 외부에 노출시키고 싶은 변수, 함수를 담죠. 즉, 객체의 프로퍼티는 퍼블릭 멤버(Public Member)로 외부에서 참조가 가능하며, 객체에 추가하지 않은 프로퍼티는 프라이빗 멤버(Private Member)로 외부에서 참조할 수 없게 됩니다. 4. ES6 모듈 - ES6에 추가된 모듈은 **파일 자체의 모듈 스코프**를 제공합니다. 즉 모듈 내에서 선언한 전역 변수는 window 객체의 프]로퍼티가 아닙니다. - HTML에 `` 형태로 추가하면 로드된 자바스크립트 파일 `app.js`는 모듈로서 동작합니다. - 일반적으로 모던 브라우저가 아니면 사용할 수 없기에, Webpack 등의 모듈 번들러를 반드시 사용해야 합니다.


Back | FazBrowse Home | New Git URL