Node 기능 알아보기 - 2(내장 객체)

백지연·2022년 1월 12일
2

NodeJS

목록 보기
5/26
post-thumbnail

Node는 따로 설치하지 않아도 바로 사용 가능한 내장 객체와 내장 모듈을 제공한다. 이는 브라우저의 window객체와 비슷하다.

이번 포스팅에서는 Node 내장 객체1. global, 2. console, 3. 타이머, 4. filename, dirname, 5. exports, require, this, 6. process을 다루겠다.

책 Node.js 교과서(개정 2판) 책의 3강의 내용을 참고했다.
+모든 코드는 github주소에 있다.


Node 내장 객체

노드 프로그래밍 시 많이 쓰이는 내장 객체를 위주로 알아보겠다.

1. global

global 객체

  • 브라우저의 window와 같은 전역 객체
  • 모든 파일에서 접근 가능(전역 객체라서)
  • 사용 시, global을 생략 가능
  • 파일 간에 간단한 데이터를 공유할 때 사용하기도 함
  • global이 아닌 module을 이용하는 것이 좋음

+앞선 포스팅에서 계속 사용했던 require함수, console도 global.이 생략된 것! (global.require, global.console)
+Node에는 DOM이나 BOM이 없으므로, 웹에서 쓰이는 자바스크립트인 window와 document 객체는 Node에서 사용할 수 없다.

global객체 EXAMPLE )

입력(console)

$ node
> global

실행화면

입력(console)

> globalbal.console

실행화면
**Node 버전에 따라 콘솔 내용이 다를 수 있다.

전역 객체인 global을 이용한 EXAMPLE )

Git [3_nodeObject/1_global/globalA.js]

module.exports = () => global.message; // global.message 값을 반환하는 함수

Git [3_nodeObject/1_global/globalB.js]

// globalB에서 넣은 global.message값을 globalA에서도 접근할 수 있음
const A = require('./globalA'); // globalA 모듈의 함수를 호출한다. 여기서 A는 함수

global.message = '안녕하세요'; // global 객체에 속성명이 message인 값을 대입
console.log(A()); // globalA 모듈의 함수를 호출

입력(console)

$ node globalB

출력

안녕하세요

2. console

console객체

  • 보통 디버깅을 위해 사용
  • 개발하면서 변수에 값이 제대로 들어 있는지 확인하기 위해 사용

대표적인 콘솔 함수

  • console.time(레이블): console.timeEnd(레이블)과 대응되어 같은 레이블을 가진 time과 timeEnd 사이의 시간을 측정한다.
  • console.log(내용): 평범한 로그를 콘솔에 표시, console.log(내용, 내용, ...)처럼 여러 내용을 동시에 표시 가능
  • console.error(에러 내용): 에러를 콘솔에 표시
  • console.table(배열): 배열의 요소로 객체 리터럴을 넣으면, 객체의 속성들이 테이블 형식으로 표현됨
  • console.dir(객체, 옵션): 객체를 콘솔에 표시할 때 사용
  • console.trace(레이블): 에러가 어디서 발생했는지 추적할 수 있게 함

+console.time, console.trace의 경로는 컴퓨터 환경에 따라 다름


CONSOLE EXAMPLE )

Git [3_nodeObject/2_console/console.js]

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: 'hero', birth: 1998}]);

console.dir(obj, {colors: false, depth: 2}); // depth는 객체 안의 객체를 몇 단계까지 보여줄지를 결정, 기본값 : 2
console.dir(obj, {colors: true, depth: 1}); // colors에 true를 넣으면 콘솔에 색이 추가됨

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

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

function a(){
    b();
}

a();

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

출력

평범한 로그입니다 쉼표로 구분해 여러 값을 찍을 수 있습니다
abc 1 true
에러 메시지는 console.error에 담아주세요.
┌─────────┬────────┬───────┐
│ (index) │  name  │ birth │
├─────────┼────────┼───────┤
│    0    │ '제로' │ 1994  │
│    1    │ 'hero' │ 1998  │
└─────────┴────────┴───────┘
{ outside: { inside: { key: 'value' } } }
{ outside: { inside: [Object] } }
시간 측정: 2.933ms
Trace: 에러 위치 추적
    at b (D:\2022상반기_nodejs교과서 학습\Study_Node\ch3\3_nodeObject\2_console\console.js:26:13)
    at a (D:\2022상반기_nodejs교과서 학습\Study_Node\ch3\3_nodeObject\2_console\console.js:30:5)
    at Object.<anonymous> (D:\2022상반기_nodejs교과서 학습\Study_Node\ch3\3_nodeObject\2_console\console.js:33:1)
    at Module._compile (node:internal/modules/cjs/loader:1097:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1149:10)
    at Module.load (node:internal/modules/cjs/loader:975:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:17:47
전체 시간: 16.814ms

실행화면

3. 타이머

대표적인 타이머 함수

  • setImmediate(콜백 함수): 콜백 함수를 즉시 실행
  • setTimeout(콜백 함수, 밀리초): 주어진 밀리초(1,000분의 1초) 이후에 콜백 함수를 실행
  • setInterval(콜백 함수, 밀리초): 주어진 밀리초마다 콜백 함수를 반복 실행

위의 3개의 함수는 모두 아이디를 반환하는데, 그 아이디를 이용해 아래의 함수를 사용

  • clearTimeout(아이디): setTimeout을 취소
  • clearInterval(아이디): setInterval을 취소
  • clearImmediate(아이디): setImmediate를 취소

Timer EXAMPLE )

Git [3_nodeObject/3_timer/timer.js]

const timeout = setTimeout(() => {
    console.log('1.5초 후 실행');
}, 1500);

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

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

setTimeout(() => {
    clearTimeout(timeout2); // timeout2는 3초를 주기로 출력이 되는데, 2.5초만에 취소했으므로 실행되지 않음
    clearInterval(interval); // 1초마다 실행이 2번(2초) 반복된 후, 2.5초가 되면 취소되므로 이후로는 실행되지 않음
}, 2500);

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

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

clearImmediate(immediate2); // 즉시 실행을 취소했기 때문에 실행되지 않음

출력

즉시 실행
1초마다 실행
1.5초 후 실행
1초마다 실행

4. filename, dirname

노드에서는 파일 사이에 모듈 관계가 있는 경우가 많으므로 현재 파일의 경로나 파일명을 알아야 한다.

filename, dirname EXAMPLE )

Git [3_nodeObject/4_filename/filename.js]

console.log(__filename);
console.log(__dirname);

출력
** 출력 경로는 컴퓨터 환경에 따라 다름

D:\2022상반기_nodejs교과서 학습\Study_Node\ch3\3_nodeObject\4_filename\filename.js
D:\2022상반기_nodejs교과서 학습\Study_Node\ch3\3_nodeObject\4_filename

5. (module), exports, require, this

1. exports

module을 먼저 읽고 오자.

위 링크(module)의 모듈 EXAMPLE )에서 module.exports를 사용했는데, module 객체 말고 exports객체로도 모듈을 만들 수 있다!

어떻게?
module.exports로 한 번에 대입하는 대신, 각각의 변수를 exports 객체에 하나씩 넣는다.

module.exports와 exports가 동일하게 동작하는 이유?
같은 객체를 참조하기 때문
단, module.exports에는 어떤 값이든 대입해도 되지만, exports에는 반드시 객체처럼 속성명과 속성값을 대입해야 한다.

exports -(참조)> module.exports -(참조)> {}
위와 같은 참조 관계가 있으므로 한 모듈에 exports 객체와 module.exports 객체를 동시에 사용하지 않는 것이 좋다.

나는 그냥 마음 편하게 module.exports를 써야겠다.


exports 객체로 수정한 module EXAMPLE )

실행을 위해 위 링크(module)의 Git [2_module/index.js] 파일과 Git [2_module/func.js] 파일을 현재 폴더에 추가했다.

Git [3_nodeObject/5_module_exports_require/var.js]

exports.odd = '홀수입니다';
exports.even = '짝수입니다';

입력

node index

출력

짝수입니다
홀수입니다

2. require

require

  • module을 불러옴
  • 함수이고, 함수는 객체이므로 객체로서 속성을 가짐
  • require.cache: require한 파일을 cache에 저장
  • require.main: 노드 실행 시 첫 모듈을 가리킴
  • require.main.filename: 첫 모듈의 이름을 알아냄

require EXAMPLE )

Git [3_nodeObject/5_module_exports_require/require.js]

console.log('require가 가장 위에 오지 않아도 됩니다.');

module.exports = '저를 찾아보세요.';

require('./var'); // 앞서 만든 var.js와 같은 폴더에 위치

console.log('rquire.cache입니다.');
console.log(require.cache);
console.log('require.main입니다.');
console.log(require.main === module); // 현재 파일이 첫 모듈인지 확인
console.log(require.main.filename); // 첫 모듈의 이름을 알아냄

출력

require가 가장 위에 오지 않아도 됩니다.
rquire.cache입니다.
[Object: null prototype] {
  'D:\\2022상반기_nodejs교과서 학습\\Study_Node\\ch3\\3_nodeObject\\5_module_exports_require\\require.js': Module {
    id: '.',
    path: 'D:\\2022상반기_nodejs교과서 학습\\Study_Node\\ch3\\3_nodeObject\\5_module_exports_require',
    exports: '저를 찾아보세요.',
    filename: 'D:\\2022상반기_nodejs교과서 학습\\Study_Node\\ch3\\3_nodeObject\\5_module_exports_require\\require.js',
    loaded: false,
    children: [ [Module] ],
    paths: [
      'D:\\2022상반기_nodejs교과서 학습\\Study_Node\\ch3\\3_nodeObject\\5_module_exports_require\\node_modules',
      'D:\\2022상반기_nodejs교과서 학습\\Study_Node\\ch3\\3_nodeObject\\node_modules',
      'D:\\2022상반기_nodejs교과서 학습\\Study_Node\\ch3\\node_modules',
      'D:\\2022상반기_nodejs교과서 학습\\Study_Node\\node_modules',
      'D:\\2022상반기_nodejs교과서 학습\\node_modules',
      'D:\\node_modules'
    ]
  },
  'D:\\2022상반기_nodejs교과서 학습\\Study_Node\\ch3\\3_nodeObject\\5_module_exports_require\\var.js': Module {
    id: 'D:\\2022상반기_nodejs교과서 학습\\Study_Node\\ch3\\3_nodeObject\\5_module_exports_require\\var.js',
    path: 'D:\\2022상반기_nodejs교과서 학습\\Study_Node\\ch3\\3_nodeObject\\5_module_exports_require',
    exports: { odd: '홀수입니다', even: '짝수입니다' },
    filename: 'D:\\2022상반기_nodejs교과서 학습\\Study_Node\\ch3\\3_nodeObject\\5_module_exports_require\\var.js',
    loaded: true,
    children: [],
    paths: [
      'D:\\2022상반기_nodejs교과서 학습\\Study_Node\\ch3\\3_nodeObject\\5_module_exports_require\\node_modules',
      'D:\\2022상반기_nodejs교과서 학습\\Study_Node\\ch3\\3_nodeObject\\node_modules',
      'D:\\2022상반기_nodejs교과서 학습\\Study_Node\\ch3\\node_modules',
      'D:\\2022상반기_nodejs교과서 학습\\Study_Node\\node_modules',
      'D:\\2022상반기_nodejs교과서 학습\\node_modules',
      'D:\\node_modules'
    ]
  }
}
require.main입니다.
true
D:\2022상반기_nodejs교과서 학습\Study_Node\ch3\3_nodeObject\5_module_exports_require\require.js

+require.cache 출력 추가 설명

  • require.cache 객체에 require.js나 var.js 같은 파일 이름이 속성명으로 들어있음
  • 속성값으로는 각 파일의 모듈 객체가 들어있음
  • 속성을 보면 module.export(exports)나, 로딩 여부(loaded), 부모(parent), 자식(children) 모듈 관계를 찾을 수 있음

--
모듈이 서로 순환참조(circular dependency)하는 EXAMPLE )

이 예제는 dep1과 dep2가 서로를 참조하고 있다. dep-run.js를 통해 dep1을 실행시킨다면 어떨까?

조금만 생각해보면,
require('./dep1') -> require('./dep2') -> require('./dep1') -> ...
이 과정이 계속 반복되는 것을 알 수 있는데, 한번 실행해보자.

Git [3_nodeObject/5_module_exports_require/dep1.js]

const dep2 = require('./dep2');
console.log('require dep2', dep2);
module.exports = () => {
    console.log('dep2', dep2);
};

Git [3_nodeObject/5_module_exports_require/dep2.js]

const dep1 = require('./dep1');
console.log('require dep1', dep1);
module.exports = () => {
    console.log('dep2', dep1);
};

Git [3_nodeObject/5_module_exports_require/dep-run.js]

const dep1 = require('./dep1');
const dep2 = require('./dep2');
dep1();
dep2();

입력

node dep-run

출력

require dep1 {}
require dep2 [Function (anonymous)]
dep2 [Function (anonymous)]
dep2 {}
(node:23100) Warning: Accessing non-existent property 'Symbol(nodejs.util.inspect.custom)' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
(node:23100) Warning: Accessing non-existent property 'constructor' of module exports inside circular dependency
(node:23100) Warning: Accessing non-existent property 'Symbol(Symbol.toStringTag)' of module exports inside circular dependency
(node:23100) Warning: Accessing non-existent property 'Symbol(Symbol.iterator)' of module exports inside circular dependency
(node:23100) Warning: Accessing non-existent property 'Symbol(nodejs.util.inspect.custom)' of module exports inside circular dependency
(node:23100) Warning: Accessing non-existent property 'constructor' of module exports inside circular dependency
(node:23100) Warning: Accessing non-existent property 'Symbol(Symbol.toStringTag)' of module exports inside circular dependency
(node:23100) Warning: Accessing non-existent property 'Symbol(Symbol.iterator)' of module exports inside circular dependency

dep1의 module.exports가 함수가 아닌, 빈 객체로 만든다. 에러를 발생하지 않으므로 순환 참조를 발생시키지 않는 것이 중요하다.

3. this

노드에서 this는 위치에 따라 가리키는 것이 다르다.
+앞서 this를 잠깐 언급했었다.

  • 최상위 스코프의 this: module.exports(또는 exports 객체)
  • 함수 선언문 내부의 this: global 객체

Git [this.js]

// 최상위 스코프에 존재하는 this
console.log(this); // {}
console.log(this === module.exports); // true
console.log(this === exports) // true

// 함수 선언문 내부의 this
function whatIsThis() {
    console.log('function', this === exports, this === global);
}

whatIsThis(); // function false true

출력

{}
true
true
function false true

6. process

process
현재 실행되고 있는 Node 프로세스에 대한 정보를 담고 있음

운영체제나 실행 환경별로 다른 동작을 하고 싶을 때 사용하는 정보들

  • process.version: 설치된 노드 버전
  • process.arch: 프로세서 아키텍처 정보
  • process.platform: 운영체제 플랫폼 정보
  • process.pid: 운영체제 플랫폼 정보(linux나 drawin, freebsd 등의 값일 수도 있음)
  • process.uptime(): 프로세스가 시작된 후 흐른 시간(단위: 초)
  • process.execPath: 노드의 경로
  • process.cwd(): 현재 프로세스가 실행되는 위치
  • process.cpuUsage(): 현재 cpu 사용량

입출력(REPL)
** 결과값은 컴퓨터마다 차이가 있음

$ node
> process.version
'v17.3.0'
> process.arch
'x64'
> process.platform
'win32'
> process.pid
23976
> process.uptime()
17.5943639
> process.execPath
'C:\\Program Files\\nodejs\\node.exe'
> process.cwd()
'D:\\2022상반기_nodejs교과서 학습\\Study_Node\\ch3\\3_nodeObject\\5_module_exports_require'
> process.cpuUsage()
{ user: 421000, system: 218000 }

1. process.env

process.env
시스템의 환경 변수 정보가 출력

대표적인 환경 변수 EXAMPLE )
**형태 : 환경변수 = 값

  • NODE_OPTIONS=--max-old-space-size=8192 // 노드를 실행할 때의 옵션들을 입력받는 환경 변수
  • UV_THREADPOOL_SIZE=8 // 노드에서 기본적으로 사용하는 스레드풀의 스레드 개수를 조절

중요한 비밀번호를 process.env속성으로 대체하는 EXAMPLE)

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

사실 이 부분이 잘 이해가 가진 않지만 뒤에서 더 다룬다고하니 일단 넘어가보려한다,,

2. process.nextTick(콜백)

Git [3_nodeObject/4_nodeModule/nextTick.js]

setImmediate(() => {
    console.log('immediate');
});
process.nextTick(()=> {
    console.log('nextTick');
});
setTimeout(()=> {
    console.log('timeout');
}, 0);
Promise.resolve().then(() => console.log('promise'));

입력

node nextTick

출력

nextTick
promise
timeout
immediate

3. process.exit(코드)

process.exit
실행 중인 노드 프로세스를 수동으로 종료

  • (코드)에 인수를 주지 않거나 0을 준 경우 -> 정상 종료
  • (코드)에 1을 준 경우 -> 비정상 종료(에러가 발생해서 종료하는 경우)

process.exit() EXAMPLE )

Git [3_nodeObject/4_nodeModule/exist.js]

let i = 1;
setInterval(() => { 
    if (i===5){
        console.log('종료!');
        process.exit();
    }
    console.log(i);
    i+=1;
}, 1000); // 1초마다 반복

입력

node exit

출력

1
2
3
4
종료!

원래 내장 모듈까지 공부하려 했는데 생각보다 양이 많아서 다음으로 미뤘다..ㅠㅠ

잘못된 정보 수정 및 피드백 환영합니다!!

profile
TISTORY로 이사중! https://delay100.tistory.com

0개의 댓글