-
Notes from reading 🔖 You Don't Know JS Yet - 9JavaScript 2026. 1. 3. 16:11
### 파트 2 - chapter 4 전역 스코프
- 최신 JS 프로그램에서는 대부분 코드를 전역이 아닌 함수/모듈에 작성한다
- 다만, 렉시컬 스코프를 이해하고 전역 스코프에 접근하며 사용할 줄 아는 것도 중요하다
- 여러 파일로 분리된 JS 파일을 JS 엔진은 어떻게 실행 시점에 하나로 연결시키는가? (브라우저 기준)
- ES 모듈을 사용하면, 파일을 각자 하나씩 로딩함. 로딩 후 import 문으로 다른 모듈을 참조하며 이때 스코프는 공유 X 배타적으로 협력함
- 구축 과정에 번들러가 관여하는 경우, 파일 전체가 하나로 합쳐져 브라우저및 JS엔진에 전달된다. 브라우저 및 JS 엔진은 하나의 거대한 JS 파일만 처리한다. 이 경우엔 파일 내 코드 조각끼리 참조할 때 사용할 이름 등록 등 메커니즘이 추가로 필요해진다.
번들러는 다양한 빌드 환경 설정이 가능하며, 그중에 파일 내용 전체를 래퍼 함수, 유니버설 모듈(UMD)등을 사용하여 하나의 스코프 하나로 묶이게 할 수 있다. (이 경우엔 코드 조각은 자신을 다른 코드에서 참조할 수 있도록 하는 지역변수를 공유 스코프 내부에서 등록한다) - 전역 스코프를 사용할 수 있다. ES6가 아니고, 모든 코드 조각을 하나로 아우르는 스코프가 없는 경우엔, 코드들이 서로 참조할 수 있는 유일한 방법이 전역스코프다.
- 꼭 다른 코드 참조가 아니어도, 전역스코프는 다양한 기능이 있는데 JS 내장 기능 활용 (NaN, Date(), eval, parseInt, WebAssembly 등의 기능) 혹은 특정 호스팅 환경에서 제공하는 내장 기능 사용(console, DOM, 타이머, 웹 API)의 경우가 있다.
- 변수는 전역에 때려 넣으면 안된다. (버그 가능성 높음)
- 하지만 모든 프로그램이 전역 스코프를 통해 연결 되는 것은 부정할 수 없다.
- 호스팅 환경에 따라 JS 전역스코프는 좀 다르다
- window 객체는 브라우저에서 JS 파일을 단독으로 사용할 때 전역 스코프가 처리되는 환경이다. (가장 순수한 환경)
- 섀도잉 변수를 생각하면, 전역을 가리는 전역 변수가 있을 수 있다. => 전역에 뭔가 선언할 때 실수를 막는 좋은 방법은, 항상 var를 쓰는 것이다. (let, const는 블록 스코프에서만 쓰기)
- DOM 전역변수 -> id 속성이 있는 DOM 요소에 대응되는 변수는 자동으로 전역에 등록된다 (브라우저 기능) id 속성값이 유효하지 않은 렉시컬 이름일경우, 오직 전역 객체를 통해서만 DOM 요소에 접근이 가능하다 (자동으로 등록되는 전역 변수에 의존하면 안좋다)
- 웹 워커는 JS 프로그램이 돌아가는 스레드가 아닌 별도의 스레드에서 코드 동작을 실행시킬 수 있다.
- 웹 워커의 코드는 DOM에 접근이 불가능하다. (navigator API 등 일부 웹 API는 예외)
- 메인 JS 프로그램과 웹 워커는 전역 스코프를 공유하지 않음
- 웹 워커에서 전역 객체를 참조하려면 일반적으로 self를 사용한다.
- ES6 모듈의 경우는 최상위 var 선언이 전역변수가 되지 않고 모듈 범위 스코프의 변수가 된다.
- 이 모듈 범위 스코프는 묶여서 전역 스코프의 하위 스코프가 된다. (렉시컬 식별자를 통해 접근 가능)
- ES 모듈에서는 전역 스코프에 대해서 의존성을 낮추는 것을 권장한다.
- Node.js에서는 엔트리 파일을 포함한 모든 JS 파일을 모듈로 처리한다. (Common JS)
- 따라서 각 JS 파일이 자체 스코프를 가지게 된다.
- Node.js에서 진짜 전역 변수를 선언하는 유일한 방법은 global에 프로퍼티를 추가하는 것이다. (window 객체와 유사)
- 전역 스코프 객체 참조를 얻을 수 있는 꼼수 -> globalThis
const theGlobalScopeObject = (new Function("return this"))();- ES2020부터 globalThis가 표준화됨 (전역 스코프 객체 참조)
/* * ============================================ * Part 2 - Chapter 4 : Global Scope * ============================================ * * 이 파일은 "전역 스코프가 환경마다 어떻게 다르게 동작하는지"를 * 하나의 흐름으로 설명하기 위한 예제다. */ /** * [1] 브라우저 전역 스코프 (window) * <script>로 직접 로딩된 가장 순수한 환경 */ // var / function → 전역 객체(window)에 프로퍼티로 등록됨 var globalVar = "I am global var"; function globalFn() {} console.log(window.globalVar); // "I am global var" console.log(window.globalFn); // function // let / const → 전역 스코프에 존재하지만 window에는 등록되지 않음 let globalLet = "I am global let"; const globalConst = "I am global const"; console.log(window.globalLet); // undefined console.log(window.globalConst); // undefined /** * [2] 전역 섀도잉과 실수 방지 패턴 */ // 전역에 let / const를 쓰면 같은 스코프에서 재선언 불가 → 바로 에러 // let globalVar = 123; // SyntaxError // 그래서 "전역에선 var만 써라"라는 옛 패턴이 나옴 // 실수로 같은 이름을 선언하면 덮어쓰기라도 되지, 죽지는 않음 /** * [3] 전역은 코드 연결 지점이기도 하다 * (모듈 시스템이 없던 시절) */ // fileA.js var sharedValue = 1; // fileB.js function increment() { sharedValue++; } // → 두 파일이 전역 스코프를 통해 연결됨 increment(); console.log(sharedValue); // 2 /** * [4] 전역 스코프의 또 다른 역할 * JS 내장 기능 & 호스팅 환경 API */ console.log(NaN); console.log(parseInt("42")); console.log(Date.now()); console.log(console); // 브라우저 호스팅 환경 제공 API setTimeout(() => {}, 1000); /** * [5] DOM 전역 변수 (브라우저 특수 기능) * * <div id="my-element"></div> */ // id가 유효한 식별자면 자동으로 전역 변수 등록 console.log(myElement); // DOM Element (브라우저) // id가 유효하지 않으면 전역 변수 X // <div id="my-element"></div> console.log(window["my-element"]); // DOM Element // ⚠️ 자동 전역 DOM 변수에 의존하면 안 됨 (충돌, 가독성, 예측 불가) /** * [6] ES Module (ESM) * <script type="module"> */ // ❌ 모듈에서는 var라도 전역 변수가 아님 var moduleVar = "module scoped"; console.log(window.moduleVar); // undefined // 모듈 스코프는 전역 스코프의 "하위 스코프" export const exportedValue = 123; // 다른 모듈에서 // import { exportedValue } from "./module.js"; /** * [7] 번들러 관점 (개념 설명) * * (function () { * // 모든 파일이 이 함수 스코프 안에 들어감 * var moduleA = ... * var moduleB = ... * })(); * * → 전역 오염 방지 * → 내부에서만 공유되는 "가짜 전역 스코프" 생성 */ /** * [8] Web Worker * 메인 스레드와 전역 스코프 공유 ❌ */ // worker.js self.workerValue = 42; console.log(self.workerValue); // 42 // console.log(window); // ReferenceError // document 접근 불가 /** * [9] Node.js (CommonJS) * 모든 파일이 모듈 */ // file.js var nodeVar = "not global"; console.log(global.nodeVar); // undefined // 진짜 전역 변수 선언 방법 global.realGlobal = "I am truly global"; // 다른 파일에서도 접근 가능 console.log(global.realGlobal); /** * [10] globalThis * 환경에 상관없이 전역 객체 참조 */ console.log(globalThis); // 브라우저 → window // Node.js → global // Worker → self globalThis.shared = "cross-env global"; /** * [11] 전역 객체 참조 꼼수 (비추천) */ const theGlobalScopeObject = (new Function("return this"))(); console.log(theGlobalScopeObject === globalThis); // true (대부분 환경) /** * ============================================ * 결론 * ============================================ * * - 전역 스코프는 피해야 하지만 * - 모든 JS 프로그램은 결국 전역에서 시작됨 * - 환경별 전역 객체(window / global / self)를 이해해야 * 모듈, 번들러, 워커 구조가 보인다 */'JavaScript' 카테고리의 다른 글
Notes from reading 🔖 You Don't Know JS Yet - 10 (1) 2026.01.17 Notes from reading 🔖 You Don't Know JS Yet - 8 (0) 2025.12.27 Notes from reading 🔖 You Don't Know JS Yet - 7 (0) 2025.12.11 JavaScript AbortController 사용법 정리 (0) 2025.10.11 Symbol.for와 Symbol알아보기 (with. 활용 방법) (0) 2025.09.01