본문 바로가기
JavaScript/Node.js

Node) 노드 기능 알아보기 - 노드 내장 객체 알아보기

by 박채니 2022. 12. 27.
안녕하세요, 코린이의 코딩 학습기 채니 입니다.
[Node.js 교과서]의 책을 참고하여 포스팅한 개인 공부 내용입니다.

 

노드 기능 알아보기

 

노드 내장 객체 알아보기

 

노드에서는 기본적인 내장 객체와 내장 모듈을 제공하며, 따로 설치하지 않아도 바로 사용할 수 있습니다. (브라우저의 window 객체와 비슷)

 

global

 

  • 전역 객체 (모든 파일에서 접근 가능)
  • 메소드 호출 시 global 생략 가능 (global.require → require 로 사용)
  • window와 document 객체를 노드에서 사용할 수 없어 이를 아우르는 globalThis 객체가 생성됨
    브라우저 환경에선 globalThis → window, 노드에선 globalThis → global
@콘솔출력값
> global
<ref *1> Object [global] {
  global: [Circular *1],
  queueMicrotask: [Function: queueMicrotask],
  clearImmediate: [Function: clearImmediate],
  setImmediate: [Function: setImmediate] {
    [Symbol(nodejs.util.promisify.custom)]: [Getter]
  },
  structuredClone: [Function: structuredClone],
  clearInterval: [Function: clearInterval],
  clearTimeout: [Function: clearTimeout],
  setInterval: [Function: setInterval],
  setTimeout: [Function: setTimeout] {
    [Symbol(nodejs.util.promisify.custom)]: [Getter]
  },
  atob: [Function: atob],
  btoa: [Function: btoa],
  performance: Performance {
    nodeTiming: PerformanceNodeTiming {
      name: 'node',
      entryType: 'node',
      startTime: 0,
      duration: 3558.353833999485,
      nodeStart: 1.6185420006513596,
      v8Start: 4.4828340001404285,
      bootstrapComplete: 23.200709000229836,
      environment: 14.673166999593377,
      loopStart: 32.78204200044274,
      loopExit: -1,
      idleTime: 3450.757752
    },
    timeOrigin: 1672118216112.88
  },
  fetch: [AsyncFunction: fetch]
}
> globalThis
<ref *1> Object [global] {
  global: [Circular *1],
  queueMicrotask: [Function: queueMicrotask],
  clearImmediate: [Function: clearImmediate],
  setImmediate: [Function: setImmediate] {
    [Symbol(nodejs.util.promisify.custom)]: [Getter]
  },
  structuredClone: [Function: structuredClone],
  clearInterval: [Function: clearInterval],
  clearTimeout: [Function: clearTimeout],
  setInterval: [Function: setInterval],
  setTimeout: [Function: setTimeout] {
    [Symbol(nodejs.util.promisify.custom)]: [Getter]
  },
  atob: [Function: atob],
  btoa: [Function: btoa],
  performance: Performance {
    nodeTiming: PerformanceNodeTiming {
      name: 'node',
      entryType: 'node',
      startTime: 0,
      duration: 7456.196583999321,
      nodeStart: 1.6185420006513596,
      v8Start: 4.4828340001404285,
      bootstrapComplete: 23.200709000229836,
      environment: 14.673166999593377,
      loopStart: 32.78204200044274,
      loopExit: -1,
      idleTime: 7309.061877
    },
    timeOrigin: 1672118216112.88
  },
  fetch: [AsyncFunction: fetch]
}
> globalThis === global
true
> global.console
Object [console] {
  log: [Function: log],
  warn: [Function: warn],
  dir: [Function: dir],
  time: [Function: time],
  timeEnd: [Function: timeEnd],
  timeLog: [Function: timeLog],
  trace: [Function: trace],
  assert: [Function: assert],
  clear: [Function: clear],
  count: [Function: count],
  countReset: [Function: countReset],
  group: [Function: group],
  groupEnd: [Function: groupEnd],
  table: [Function: table],
  debug: [Function: debug],
  info: [Function: info],
  dirxml: [Function: dirxml],
  error: [Function: error],
  groupCollapsed: [Function: groupCollapsed],
  Console: [Function: Console],
  profile: [Function: profile],
  profileEnd: [Function: profileEnd],
  timeStamp: [Function: timeStamp],
  context: [Function: context]
}

수많은 속성이 들어있는 것을 확인할 수 있으며, 전역 객체라는 점을 이용해 파일 간의 간단한 데이터를 공유할 때 사용되기도 합니다.

 

globalA.js

module.exports = () => global.message;

 

globalB.js

const A = require("./globalA");

global.message = "안녕하세요";
console.log(A());

@콘솔출력값
$ node global/globalB
안녕하세요

globalA 모듈의 함수는 global.message 값을 반환하고, globalB에서는 global의 message 속성을 '안녕하세요' 값으로 대입하였습니다.

그 후 globalA 모듈에서 넘겨 받은 함수를 호출하니, globalB에서 넣은 '안녕하세요'가 출력되는 것을 확인할 수 있습니다.

 

console

 

  • 보통 디버깅을 위해 사용
  • 브라우저의 console과 비슷
const string = "abc";
const number = 1;
const boolean = true;
const obj = {
  outside: {
    inside: {
      key: "value",
    },
  },
};

console.time("전체 시간"); // 타이머
console.log("평범한 로그입니다 쉼표로 구분해 여러 값을 찍을 수 있습니다.");
console.log(string, number, boolean);
console.error("에러 메세지는 console.error에 담음!");

console.table([
  { name: "제로", birth: 1994 },
  { name: "chany", birth: 1999 },
]);

console.dir(obj, { color: false, depth: 2 });
console.dir(obj, { color: true, depth: 1 });

console.time("시간 측정");
for (let i = 0; i < 100000; i++) {}
console.timeEnd("시간 측정");

function b() {
  console.trace("에러 위치 추적");
}
function a() {
  b();
}
a();

console.timeEnd("전체 시간");

@콘솔출력값
$ node part3/console

평범한 로그입니다 쉼표로 구분해 여러 값을 찍을 수 있습니다.
abc 1 true
에러 메세지는 console.error에 담음!
┌─────────┬─────────┬───────┐
│ (index) │  name   │ birth │
├─────────┼─────────┼───────┤
│    0    │ '제로'  │ 1994  │
│    1    │ 'chany' │ 1999  │
└─────────┴─────────┴───────┘
{ outside: { inside: { key: 'value' } } }
{ outside: { inside: [Object] } }
시간 측정: 0.999ms
Trace: 에러 위치 추적
    at b (/Users/parkchaeeun/project/playground-cepark/part3/console.js:30:11)
    at a (/Users/parkchaeeun/project/playground-cepark/part3/console.js:33:3)
    at Object.<anonymous> (/Users/parkchaeeun/project/playground-cepark/part3/console.js:35:1)
    at Module._compile (node:internal/modules/cjs/loader:1159:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
    at Module.load (node:internal/modules/cjs/loader:1037:32)
    at Module._load (node:internal/modules/cjs/loader:878:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:23:47
전체 시간: 7.201ms

 

  • console.time(레이블) 
    : console.timeEnd(레이블)과 대응되어 같은 레이블을 가진 time과 timeEnd 사이의 시간 측정
  • console.log(내용)
    : 평범한 로그 콘솔에 표시, 여러 내용을 동시에 표시도 가능
  • console.error(에러 내용)
    : 에러를 콘솔에 표시
  • console.table(배열)
    : 배열의 요소로 객체 리터럴을 넣으면, 객체 속성들이 테이블 형식으로 표현
  • console.dir(객체, 옵션)
    : 객체를 콘솔에 표시할 때 사용, 옵션의 color를 true로 하면 콘솔에 색 추가, depth는 객체 안의 객체를 몇 단계까지 보여줄지 결정(기본 2)
  • console.trace(레이블)
    : 에러가 어디서 발생했는지 추적

 

타이머

 

  • setTimeout(콜백 함수, 밀리초)
    : 주어진 밀리초 이후에 콜백 함수 실행
  • setInterval(콜백 함수, 밀리초)
    : 주어진 밀리초마다 콜백 함수 반복 실행
  • setImmediate(콜백 함수)
    : 콜백 함수 즉시 실행
  • clearTimeout(아이디)
    : setTimeout 취소
  • clearInterval(아이디)
    : setInterval 취소
  • clearImmediate(아이디)
    : setImmediate 취소

timer.js

const timeout = setTimeout(() => {
  console.log("1.5초 뒤에 실행");
}, 1500);

const interval = setInterval(() => {
  console.log("1초마다 실행");
}, 1000);

const timeout2 = setTimeout(() => {
  console.log("실행되지 않습니다.");
}, 3000);

setTimeout(() => {
  clearTimeout(timeout2);
  clearInterval(interval);
}, 2500);

const immediate = setImmediate(() => {
  console.log("즉시 실행");
});

const immediate2 = setImmediate(() => {
  console.log("실행되지 않습니다.");
});

clearImmediate(immediate2);

@콘솔출력값
$ node part3/timer

즉시 실행
1초마다 실행
1.5초 뒤에 실행
1초마다 실행

 

타이머는 콜백 기반 API이지만, 프로미스 방식을 사용할 수도 있습니다.

 

timerPromise.mjs (노드 내장 모듈)

import { setTimeout, setInterval } from "timers/promises";

await setTimeout(3000);
console.log("3초 뒤 실행");

for await (const startTime of setInterval(1000, Date.now())) {
  console.log("1초마다 실행", new Date(startTime));
}

@콘솔출력값
$ node part3/timerPromise.mjs

3초 뒤 실행
1초마다 실행 2022-12-27T05:47:40.800Z
1초마다 실행 2022-12-27T05:47:40.800Z
1초마다 실행 2022-12-27T05:47:40.800Z
1초마다 실행 2022-12-27T05:47:40.800Z
1초마다 실행 2022-12-27T05:47:40.800Z
...

timers/promises 모듈에서의 setTimeout은 몇 밀리초를 기다릴지 정할 수 있으며,

setInterval(밀리초, 시작값)은 for await of 문법과 함께 사용할 수 있습니다.

 

process

 

  • 현재 실행되고 있는 노드 프로세스에 대한 정보를 담은 객체
> process.version
'v18.12.1' // 설치된 노드 버전
> process.arch
'arm64' // 프로세서 아키텍처 정보
> process.platform
'darwin' // 운영체제 플랫폼 정보
> process.pid
2907 // 현재 프로세스의 아이디
> process.uptime()
35.859721209 // 프로세스가 시작된 후 흐른 시간 (초 단위)
> process.execPath
'/usr/local/bin/node' // 노드 경로
> process.cwd()
'/Users/parkchaeeun/project/playground-cepark' // 현재 프로세스가 실행되는 위치
> process.cpuUsage()
{ user: 512692, system: 78497 } // 현재 cpu 사용량

 

process.env

- 시스템의 환경 변수

process.env를 입력하면 많은 정보가 출력되는데, UV_THREADPOOL_SIZE와 NODE_OPTIONS가 대표적입니다.

 

  • NODE_OPTIONS
    : 노드를 실행할 때의 옵션들을 입력받는 환경 변수
  • UV_THREADPOOL_SIZE
    : 노드에서 기본적으로 사용하는 스레드 풀의 스레드 개수를 조절할 수 있음

이 외에도 임의로 환경 변수를 저장할 수도 있습니다.

process.env는 서비스의 중요한 키를 저장하는 공간으로도 사용됩니다. (서버나 DB 비밀번호, 각종 API 키 등)

const secretId = process.env.SECRET_ID;
const secretCode = process.env.SECRET_CODE;

 

process.nextTick(콜백)

- 이벤트 루프가 다른 콜백 함수들보다 nextTick의 콜백 함수를 우선으로 처리하도록 만듦

setImmediate(() => {
  console.log("immediate");
});

process.nextTick(() => {
  console.log("nextTick");
});

setTimeout(() => {
  console.log("timeout");
}, 0);

Promise.resolve().then(() => console.log("promise"));

@콘솔출력값
$ node part3/nextTick

nextTick
promise
timeout
immediate

process.nextTick은 setImmediate나 setTimeout보다 먼저 실행됩니다.

Promise 또한 resolve된 Promise도 nextTick처럼 다른 콜백들보다 우선시 됩니다.

이를 마이크로태스크 라고 구분하여 부릅니다.

 

process.exit(코드)

- 실행 중인 노드 프로세스 종료

- 서버 환경에서 사용 시 서버가 멈추므로, 특수한 경우에만 사용

- 서버 외 독립적인 프로그램에서는 수동으로 노드를 멈추기 위해 사용

let i = 1;

setInterval(() => {
  if (i === 5) {
    console.log("종료!");
    process.exit();
  }
  console.log(i);
  i += 1;
}, 1000);

@콘솔출력값
$ node part3/exit

1
2
3
4
종료!

process.exit 메소드는 인수로 코드 번호를 줄 수 있습니다.

  • 0 : 정상 종료
  • 1 : 비정상 종료

따라서 에러가 발생해서 종료하는 경우에는 1을 넣어줍니다.

 

기타 내장 객체

 

fetch를 노드에서도 쓸 수 있게 됨에 따라 브라우저에 존재하던 객체들이 노드에도 동일하게 생성되어 브라우저의 코드를 일부 재사용할 수 있습니다.

 

  • URL, URLSearchParam
  • AbortController, FormData, fetch, Headers, Request, Response, Event, EventTarget
    : 브라우저에서 사용하던 API가 노드에도 동일하게 생성
  • TextDecoder
    : Buffer를 문자열로 바꿈
  • TextEncoder
    : 문자열을 Buffer로 바꿈
  • WebAssembly
    : 웹어셈블리 처리 담당