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"

전역 변수 사용 시 주의사항

전역 변수는 편리하지만 여러 단점이 있습니다:

  1. 네임스페이스 오염: 서로 다른 모듈이 같은 이름의 전역 변수를 사용하면 충돌이 발생합니다.
  2. 코드 복잡성: 전역 변수의 상태는 어디서든 변경될 수 있어 디버깅이 어려워집니다.
  3. 테스트 어려움: 전역 상태에 의존하는 코드는 테스트하기 어렵습니다.
  4. 가독성 감소: 전역 변수의 출처가 명확하지 않아 코드 이해가 어려워집니다.

따라서 전역 변수는 꼭 필요한 경우에만 제한적으로 사용하는 것이 좋습니다.

모듈 스코프에서 접근 가능한 '전역' 변수들

다음 항목들은 실제로는 모듈 스코프에 속하지만, 각 모듈에서 전역적으로 사용 가능합니다:

  • __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은 사용할 수 없습니다.
  • 대신 importexport 문을 사용합니다.
  • 파일 경로에 접근하려면 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 객체는 유사한 역할을 하지만 차이점이 있습니다:

  1. 브라우저에서는 var x = 1과 같이 선언된 변수가 window 객체의 속성이 되지만, Node.js에서는 모듈 스코프에 한정됩니다.
  2. 브라우저에는 document, location 등 DOM 관련 객체가 있지만, Node.js에는 이러한 객체가 없습니다.
  3. 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/exportimport.meta.url을 사용합니다.
  • 기능 공유에는 모듈 시스템을 활용하는 것이 좋습니다.

전역 객체를 이해하고 적절하게 사용하면 Node.js 애플리케이션의 구조를 더 명확하게 설계하고 유지보수하기 쉬운 코드를 작성할 수 있습니다.

results matching ""

    No results matching ""