[JavaScript] Global This

자바스크립트에서 this라는 키워드는 정말 자주 보이죠?
그런데 정확히 알고 있지 않으면 이 this가 어떤 것을 가리키는지 항상 헷갈리더라구요.
함수 안에서, 객체 안에서, 어떤 때는 undefined가 나오고, 또 어떤 때는 window가 나오고…
this가 자주 나오는만큼 헷갈리지 않게 정확하게 알고 있는다면
개발을 할 때 이 this가 무엇을 가리키는지를 알아내느라 걸리는 시간이 대폭 줄겠죠!
그래서 오늘은 this에 대해 알아보려고 합니다. 그런데 this중에서
오늘은 전역 공간에서의 this, 즉 global this에 대해 알아보려고 합니다!
1️⃣ 전역 객체란?
우리가 자바스크립트를 실행할 때, 항상 어떤 "기본적인 환경"이 먼저 만들어지는데요, 그 환경의 최상단에 있는 요소를 전역 객체(Global Object) 라고 부릅니다.
이 전역 객체는 우리 코드에서 자주 사용하는 내장 객체들! 예를 들어 setTimeout, Math, console 같은 것들을 담고 있습니다.
그런데 말입니다…
환경에 따라 이 전역 객체의 이름이 다릅니다...!
실행 환경 | 전역 객체 이름 |
브라우저 | window |
Node.js | global |
같은 자바스크립트인데 이름이 위와 같이 달라서 환경에 따라 코드를 다르게 짜야 했고, 그게 우리 개발자들은 너무 귀찮았던 거죠^^
2️⃣ this를 전역에서 쓰면 뭐가 될까?
그렇다면 전역 스코프에서 this를 출력해보면 어떻게 될까요?
브라우저에서 실행해보면
console.log(this); // window
전역에서 this는 window와 같다고 나와요!
그래서 this.alert('Hello!') 이런 식으로도 쓸 수 있었죠.
그런데 Node.js에서는?
console.log(this); // {}
전역 객체가 아니라 위와 같이 {}로 나오게 됩니다.
❓ 왜 Node.js에선 전역의 this가 {}일까?
Node.js는 우리가 작성한 자바스크립트 코드를 파일 하나하나를 "모듈"로 취급해서 실행합니다.
그리고 이 모듈 내부 코드를 그냥 실행하는 게 아니라, 자동으로 함수로 감싸서 실행합니다.
예를 들어 설명하자면! 우리가 작성한 JS 파일이 있다고 가정해보겠습니다.
// myFile.js
console.log(this);
그럼 Node.js 내부에선 이 파일을 실제로는 아래와 같이 함수로 감싸서 실행합니다.
(function(exports, require, module, __filename, __dirname) {
console.log(this); // 여기서의 this는 누굴까요?
})();
이건 Node.js가 파일을 모듈로 처리하기 위해 내부적으로 자동으로 감싸는 함수인데, 이걸 모듈 래퍼(wrapper) 함수라고 부릅니다. 우리가 작성한 코드가 전부 이 함수 안에서 실행되는 셈이죠!
그럼 위 함수 안에서의 this는 대체 뭘까요?
자바스크립트에서 일반 함수 안에서 this는 호출 방식에 따라 다르게 결정됩니다.
- 전역에서 호출하면 → 브라우저에선 window, Node에선 global
- 객체의 메서드로 호출하면 → 그 객체가 this
- new로 호출하면 → 새로 생성된 인스턴스가 this
- strict mode에서 일반 함수라면 → this는 undefined
그런데 Node.js 모듈은 엄격 모드(strict mode) 처럼 동작합니다!!!
Node.js는 모든 모듈 파일을 실행할 때, 우리가 use strict를 명시하지 않아도 내부적으로 엄격 모드처럼 작동합니다.
그래서 this가 자동으로 전역 객체를 가리키지 않고, 그 대신 모듈 전용 객체인 module.exports와 관련된 빈 객체 {}가 되는 겁니다.
쉽게 비유하여 설명해보자면
(function () {
'use strict'; // 암묵적으로 적용됨
console.log(this); // 여기서 this는 undefined (strict mode니까)
})();
그런데 Node.js는 위 함수에서 this를 exports와 연결된 객체로 명시적으로 바인딩해서 실행합니다.
(function () {
console.log(this); // 여기서 this는 {}
}).call(module.exports); // ← 이렇게 실행됨
// Node.js에서
console.log(this); // {}
그래서 최종적으로 Node.js환경에서 전역의 this는 빈 객체가 되는 것 이죠.
3️⃣ 그래서 등장한 globalThis
이런 혼란을 해결하기 위해 등장한 것이 바로 globalThis 입니다!
ES2020(ES11)에서 표준으로 도입된 전역 객체 접근 방법입니다.
console.log(globalThis);
위와 같이 사용하게 되면
- 브라우저에서는 👉 window
- Node.js에서는 👉 global
- Web Worker에서는 👉 self
모든 환경에서 일관되게 "진짜 전역 객체"를 가리켜줍니다!!
4️⃣ 사용 예시
환경 무관 전역 변수 선언하기
전에는 브라우저용 코드는 아래와 같이 작성 했었고,
window.myAppName = 'HelloApp';
Node.js에서는?
global.myAppName = 'HelloApp';
이렇게 작성을 했었죠.
하지만 이제는
globalThis.myAppName = 'HelloApp';
이렇게 통일할 수 있는 것 입니다!
이렇게 하면 어떤 환경에서 실행하든 문제 없이 작동하니까 라이브러리나 범용 코드를 작성할 때 정말 편리해집니다!
5️⃣ 주의사항
this와 globalThis는 다릅니다!!!
✅ this는 실행 환경과 위치에 따라 다르게 동작합니다.
위 2번에서 설명 드렸다시피 각각의 환경에 따라 가리키는 것은 아래 표와 같습니다.
환경 | 코드 위치 | this가 가리키는 것 | globalThis가 가리키는 것 |
브라우저 | 전역 스코프 | window (전역 객체) | window (전역 객체) |
Node.js | 모듈 파일 내부 | {} (module.exports) | global (전역 객체) |
즉, Node.js에서는 전역처럼 보여도 함수 안이니까 전역 객체가 아니라는 것 입니다! 헷갈리죠?ㅎㅎ
이걸 모르고 this.setTimeout() 같은 코드를 쓰면 TypeError가 발생합니다... 왜냐하면 {}에는 setTimeout 같은 전역 함수가 없거든요!
✨ 정리
구문 | 브라우저 | Node.js (모듈 안) |
this | window | {} |
window | ✅ 있음 | ❌ 없음 |
global | ❌ 없음 | ✅ 있음 |
globalThis | ✅ window | ✅ global |