Node.js 인터뷰 질문 34
질문: Node.js의 전역 객체(global object)에 대해 설명해주세요.
답변:
Node.js의 전역 객체(global object)는 Node.js 환경에서 전역적으로 사용 가능한 객체로, 브라우저의 window
객체와 유사한 역할을 합니다. 이 객체는 모든 모듈에서 접근할 수 있으며, 전역 네임스페이스를 제공합니다.
전역 객체 소개
Node.js에서 전역 객체는 global
이라는 이름을 가지고 있습니다.
console.log(global); // 전역 객체 출력
모듈 내에서 선언된 변수, 함수 등은 기본적으로 해당 모듈의 스코프에 한정되지만, global
객체에 추가하면 모든 모듈에서 접근할 수 있습니다.
// 전역 변수 설정
global.myVariable = "Hello, World!";
// 다른 모듈에서 접근 가능
console.log(global.myVariable); // "Hello, World!" 출력
// 또는 직접 접근
console.log(myVariable); // "Hello, World!" 출력
주요 전역 객체의 속성과 메소드
Node.js의 전역 객체는 다양한 속성과 메소드를 제공합니다:
1. 전역 객체와 관련된 속성
global
: 전역 객체 자체를 참조globalThis
: ECMAScript 2020에서 도입된 표준화된 전역 객체 참조
console.log(global === globalThis); // true (Node.js에서)
2. 콘솔 관련 메소드
console
: 콘솔 출력을 위한 메소드 제공
console.log("정보 메시지");
console.error("오류 메시지");
console.warn("경고 메시지");
console.time("타이머");
console.timeEnd("타이머");
console.table([
{ name: "홍길동", age: 30 },
{ name: "김철수", age: 25 },
]);
3. 타이머 관련 함수
setTimeout(callback, delay[, ...args])
: 지정된 시간(ms) 후 콜백 실행clearTimeout(timeoutId)
: 예약된 타임아웃 취소setInterval(callback, delay[, ...args])
: 지정된 간격(ms)마다 콜백 실행clearInterval(intervalId)
: 설정된 인터벌 취소setImmediate(callback[, ...args])
: 현재 이벤트 루프 반복이 완료된 후 콜백 실행clearImmediate(immediateId)
: 예약된 immediate 취소
// setTimeout 예제
const timeoutId = setTimeout(() => {
console.log("3초 후 실행");
}, 3000);
// 필요시 취소
// clearTimeout(timeoutId);
// setInterval 예제
const intervalId = setInterval(() => {
console.log("2초마다 실행");
}, 2000);
// 10초 후 인터벌 중지
setTimeout(() => {
clearInterval(intervalId);
console.log("인터벌 중지");
}, 10000);
// setImmediate 예제
setImmediate(() => {
console.log("다음 이벤트 루프에서 실행");
});
4. 프로세스 관련 객체
process
: 현재 Node.js 프로세스에 대한 정보와 제어 제공
// 환경 변수 접근
console.log(process.env.NODE_ENV);
// 명령줄 인수
console.log(process.argv);
// 프로세스 종료
// process.exit(0);
// 현재 작업 디렉토리
console.log(process.cwd());
// 플랫폼 정보
console.log(process.platform);
// 메모리 사용량
console.log(process.memoryUsage());
// 다음 이벤트 루프 틱에서 콜백 실행
process.nextTick(() => {
console.log("다음 틱에서 실행");
});
5. 버퍼 클래스
Buffer
: 바이너리 데이터를 효율적으로 처리하기 위한 클래스
// 문자열로부터 버퍼 생성
const buf1 = Buffer.from("Hello, World!");
console.log(buf1.toString()); // "Hello, World!"
// 크기를 지정하여 버퍼 생성
const buf2 = Buffer.alloc(10);
buf2.write("안녕하세요");
console.log(buf2.toString()); // "안녕하세요"
6. 모듈 관련 객체 및 함수
require()
: 모듈을 로드하는 함수module
: 현재 모듈에 대한 참조exports
&__dirname
&__filename
: 이들은 모듈 스코프의 일부지만 각 모듈에서 전역적으로 사용 가능
// 모듈 로드
const fs = require("fs");
// 현재 모듈 정보
console.log(module);
// 현재 파일의 디렉토리 경로
console.log(__dirname);
// 현재 파일의 전체 경로
console.log(__filename);
// 모듈 내보내기
exports.hello = () => "Hello";
// 또는
module.exports = { hello: () => "Hello" };
7. URL 클래스 및 함수
URL
: URL을 파싱하고 조작하기 위한 클래스URLSearchParams
: URL 쿼리 문자열을 처리하기 위한 클래스
const url = new URL("https://example.com/path?query=value");
console.log(url.hostname); // "example.com"
console.log(url.pathname); // "/path"
console.log(url.searchParams.get("query")); // "value"
전역 객체 vs 모듈 스코프
Node.js의 모듈 시스템은 CommonJS를 기반으로 하며, 각 파일은 자체 모듈 스코프를 가집니다. 이는 모듈 내에서 정의된 변수, 함수, 클래스 등이 명시적으로 내보내지 않는 한 다른 모듈에서 접근할 수 없음을 의미합니다.
// module1.js
const privateVariable = "Private";
exports.publicVariable = "Public";
// module2.js
const module1 = require("./module1");
console.log(module1.privateVariable); // undefined
console.log(module1.publicVariable); // "Public"
하지만 global
객체에 추가한 항목은 모든 모듈에서 접근할 수 있습니다:
// module1.js
global.sharedVariable = "Shared";
// module2.js
console.log(sharedVariable); // "Shared"
전역 변수 사용 시 주의사항
전역 변수는 편리하지만 여러 단점이 있습니다:
- 네임스페이스 오염: 서로 다른 모듈이 같은 이름의 전역 변수를 사용하면 충돌이 발생합니다.
- 코드 복잡성: 전역 변수의 상태는 어디서든 변경될 수 있어 디버깅이 어려워집니다.
- 테스트 어려움: 전역 상태에 의존하는 코드는 테스트하기 어렵습니다.
- 가독성 감소: 전역 변수의 출처가 명확하지 않아 코드 이해가 어려워집니다.
따라서 전역 변수는 꼭 필요한 경우에만 제한적으로 사용하는 것이 좋습니다.
모듈 스코프에서 접근 가능한 '전역' 변수들
다음 항목들은 실제로는 모듈 스코프에 속하지만, 각 모듈에서 전역적으로 사용 가능합니다:
__dirname
: 현재 모듈의 디렉토리 경로__filename
: 현재 모듈의 파일 경로exports
: 모듈에서 내보내는 객체module
: 현재 모듈에 대한 참조require()
: 모듈을 불러오는 함수
console.log(__dirname); // 예: '/home/user/project'
console.log(__filename); // 예: '/home/user/project/app.js'
console.log(module); // 현재 모듈 객체
ECMAScript 모듈(ESM)에서의 전역 객체
Node.js는 CommonJS 외에도 ECMAScript 모듈(ESM)을 지원합니다. ESM을 사용할 때는 일부 차이점이 있습니다:
require
,exports
,module.exports
,__dirname
,__filename
은 사용할 수 없습니다.- 대신
import
와export
문을 사용합니다. - 파일 경로에 접근하려면
import.meta.url
을 사용합니다.
// ESM 예제 (*.mjs 파일 또는 package.json에 "type": "module" 설정)
import { fileURLToPath } from "url";
import { dirname } from "path";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
console.log(__dirname);
console.log(__filename);
브라우저의 window 객체와 비교
브라우저의 window
객체와 Node.js의 global
객체는 유사한 역할을 하지만 차이점이 있습니다:
- 브라우저에서는
var x = 1
과 같이 선언된 변수가window
객체의 속성이 되지만, Node.js에서는 모듈 스코프에 한정됩니다. - 브라우저에는
document
,location
등 DOM 관련 객체가 있지만, Node.js에는 이러한 객체가 없습니다. - Node.js에는
process
,Buffer
등 서버 환경에 특화된 객체가 있습니다.
전역 객체의 확장
global
객체를 확장하여 사용자 정의 함수나 변수를 추가할 수 있지만, 이는 권장되지 않습니다. 대신 모듈 시스템을 사용하여 기능을 구조화하는 것이 좋습니다.
필요한 경우 다음과 같이 유틸리티 모듈을 통해 공유 기능을 제공할 수 있습니다:
// utils.js
exports.formatDate = (date) => {
// 날짜 포맷팅 로직
return date.toISOString();
};
// 다른 파일에서 사용
const utils = require("./utils");
console.log(utils.formatDate(new Date()));
요약
- Node.js의 전역 객체
global
은 전체 애플리케이션에서 접근 가능한 변수와 함수를 제공합니다. - 주요 전역 객체 속성/메소드:
console
,setTimeout
,setInterval
,process
,Buffer
등 - 모듈 스코프에서 접근 가능한 '전역' 변수:
__dirname
,__filename
,exports
,module
,require
- 전역 변수는 네임스페이스 오염, 코드 복잡성 증가 등의 이유로 제한적으로 사용해야 합니다.
- ECMAScript 모듈(ESM)을 사용할 때는
import
/export
와import.meta.url
을 사용합니다. - 기능 공유에는 모듈 시스템을 활용하는 것이 좋습니다.
전역 객체를 이해하고 적절하게 사용하면 Node.js 애플리케이션의 구조를 더 명확하게 설계하고 유지보수하기 쉬운 코드를 작성할 수 있습니다.