NodeJS의 모듈과 this 그리고 global

younoah·2022년 1월 12일
1

[nodeJS]

목록 보기
2/15

golobal 오브젝트

nodeJS에는 golobal이라는 객체가 존재한다.

전역에 어떤 변수를 선언하게 되면 해당 변수는 global 객체에 정의되게 된다.

(브라우저 위에서 동작하는 자바스크립트 런타임 환경은 windosw 객체에 정의된다.)

nodeJS에서 global 객체의 형태

console.log(global);

// 출력결과
/* <ref *1> Object [global] {
  global: [Circular *1],
  clearInterval: [Function: clearInterval],
  clearTimeout: [Function: clearTimeout],
  setInterval: [Function: setInterval],
  setTimeout: [Function: setTimeout] {
    [Symbol(nodejs.util.promisify.custom)]: [Getter]
  },
  queueMicrotask: [Function: queueMicrotask],
  performance: Performance {
    nodeTiming: PerformanceNodeTiming {
      name: 'node',
      entryType: 'node',
      startTime: 0,
      duration: 31.01824999973178,
      nodeStart: 1.1722079999744892,
      v8Start: 1.708416999783367,
      bootstrapComplete: 24.04904199996963,
      environment: 14.396042000036687,
      loopStart: -1,
      loopExit: -1,
      idleTime: 0
    },
    timeOrigin: 1641960743299.417
  },
  clearImmediate: [Function: clearImmediate],
  setImmediate: [Function: setImmediate] {
    [Symbol(nodejs.util.promisify.custom)]: [Getter]
  }
} */

global 객체 내부에는 setInterval, setTimeout 과 같이 자바스크립트에서 기본으로 제공해주는 다양한 변수들이 존재하는 것을 확인 할 수 있다.

global 객체에 어떤 것들이 있는지 자세하게 보고 싶다면 NodeJS 문서 - Global 를 확인해보자

정의와 사용

global.greeting1 = () => {
  global.console.log('hi, there!');
};

global.greeting1();
// hi, there!
greeting1();
// hi, there!

greeting2 = () => {
  console.log('hello, world!');
};

global.greeting2();
// hello, world!
greeting2();
// hello, world!

global 에 직접 정의를 하거나 전역에 정의하는 것은 같은 것이다. 사용할 때 global은 생략이 가능하다.

global 정의부 구경하기

// vscode에게 브라우저용인지 노드용인지 알려주기 위해 노드모듈 중에 하나인 fs를 임포트하여 노드용이라고 인식 시켜준다.
// 이렇게 하면 vscode에서 해당 파일이 노드용으로 인식되어 노드JS의 정의부를 탐색할 수 있다.
const fs = require('fs'); 

console.log(global); // global에 cmd + 왼쪽클릭을 하면 정의부로 이동할 수 있다.

이전 노드버전에서는 global 키워드 cmd + 왼쪽클릭을 하면 정의부로 가서 어떤것들이 정의되어있는지 확인할 수 있었다. 하지만 최신 node버전인 경우 타입으로 정의된 노드만 보여서 자세한 내용을 볼 수 없는데 이 곳 에서 정의를 자세하게 확인 할 수 있다.

콘솔의 다양한 메서드

콘솔에는 다양한 메서드가 존재한다. 하나씩 알아보자!

// log level
console.log('log'); // 개발용, 개발이 완료된 후 지원주자.
console.info('info'); // 정보 출력용
console.warn('warn'); // 경보 출력용
console.error('error'); // 에러, 사용자 에러, 시스템 에러 출력용

// 로그에 따라 레벨을 나누어서 출력할 수 있다. 심각한 에러의 정보를 출력하는 거라면 error를, 약간의 경고정도이면 warn을 사용하는 방식으로 의미적으로 사용하는게 좋다.

// assert - 참이 아닌 경우 출력
console.assert(2 === 3, 'not same!');
console.assert(2 === 2, 'same!');

// print object - 객체를 테일블로 출력
const student = { name: 'ellie', age: 20, company: { name: 'AC' } };
console.log(student);
// { name: 'ellie', age: 20, company: { name: 'AC' } }

console.table(student);
// ┌─────────┬──────┬─────────┐
// │ (index) │ name │ Values  │
// ├─────────┼──────┼─────────┤
// │  name   │      │ 'ellie' │
// │   age   │      │   20    │
// │ company │ 'AC' │         │
// └─────────┴──────┴─────────┘

console.dir(student, { showHidden: true, colors: false, depth: 0 });
// { name: 'ellie', age: 20, company: [Object] }


// 시간 측정
console.time('for loop');
for (let i = 0; i < 10; i++) {
  i++;
}
console.timeEnd('for loop');
// for loop: 0.031ms


// counting
function a() {
  console.count('a function'); // 해당 함수가 몇번 호출되었는지 실행될 때마다 카운트 값을 출력해준다.
}
a();
// a function: 1
a();
// a function: 2
console.countReset('a function'); // 여태까지 카운트된 것을 초기화해준다.
a();
// a function: 1

// trace - 해당 함수가 어떻게 호출되었는지 정보를 출력해준다.
function f1() {
  f2();
}
function f2() {
  f3();
}
function f3() {
  console.log('f3');
  console.trace();
}

f1();
// Trace
//     at f3 (/Users/uno/Desktop/web/nodejs/4-node-module/2-console/app.js:44:11)
//     at f2 (/Users/uno/Desktop/web/nodejs/4-node-module/2-console/app.js:40:3)
//     at f1 (/Users/uno/Desktop/web/nodejs/4-node-module/2-console/app.js:37:3)
//     at Object.<anonymous> (/Users/uno/Desktop/web/nodejs/4-node-module/2-console/app.js:46:1)
//     at Module._compile (node:internal/modules/cjs/loader:1101:14)
//     at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
//     at Module.load (node:internal/modules/cjs/loader:981: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

nodejs의 this

브라우저에서의 this와 nodejs의 this는 살짝 다르다. (브라우저에서의 this)

this는 어떤 scope에서 어떻게 사용하냐에 따라 근본이 달라진다.

  1. function에서 사용한다면

    • 함수로써 호출한다면 this는 전역객체(global)을 가리킨다.
    • 메서드로써 호출한다면 this는 메서드를 호출한 객체을 가리킨다.
    • 생성자 함수 호출이라면 this는 인스턴스화 된 객체를 가리킨다.
  2. class에서 사용한다면 this는 인스턴스화 된 객체를 가리킨다.

  3. (⚠️집중!) global scope에서 사용한다면 this는 module.export(module에 있는 exports)를 나타낸다.

    // 만약 노드 전역공간이라면
    console.log(this === module.exports); // true
    
    // 만약 브라우저 전역공간이라면
    console.log(this === window); // true

    브라우저에서는 global scope에서 사용한다면 this는 window를 가리킨다.)

모듈

nodejs에서 모듈을 사용하는것은 크게 2가지가 있다.

  1. nodeJS 전용으로 사용하는 모듈 방식과 (Commonjs)

  2. 자바스크립트 es6버전 이상에서 제공하는 모듈 방식이 있다. (ECMAScriptModules)

둘중 어느것을 사용해도 무방하다.

nodeJS 전용 commonjs

  • 내보내기 (module.export)
// 내보내는 파일
let count = 0;

function getCount() {
  return count;
}

funtionc increase() {
  counter++;
}

module.exports.getCount = getCount;
module.exports.increase = increase;

모듈을 생략하고 exports.getCount = getCount; 와 같은 방식으로 사용해도 무방하다.

하지만 혹시나 export라는 객체가 선언되어있다면 에러가 발생하므로 되도록 module.exports 로 사용하자.

  • 가져오기 (require)
// 사용하는 파일
const counter = require('./counter.js');

counter.increase();
counter.increase();
counter.increase();
console.log(counter.getCount());

자바스크립트에서 제공하는 방식 (modules)

자바스크립트에서 제공하는 최신 문법을 사용하려면 package.json 설정파일이 필요하다.

  • package.json

우선 아래 명령어로 package.json 파일을 생성한다.

$ npm init

package.json 파일에서 type 필드에 값을 "modules" 로 설정한다.

이렇게 하면 node로 js파일을 실행할 때 modules 방식으로 동작 시킬 수 있다.

{
  "name": "5-module",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "type": "module", // "commonjs"로 하면 nodejs전용 모듈방식을 따른다.
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
  • 내보내기 (module.export)
// 내보내는 파일
let count = 0;

export function increase() {
  count++;
}

export function getCount() {
  return count;
}

모듈을 생략하고 exports.getCount = getCount; 와 같은 방식으로 사용해도 무방하다.

하지만 혹시나 export라는 객체가 선언되어있다면 에러가 발생하므로 되도록 module.exports 로 사용하자.

  • 가져오기 (require)
// 사용하는 파일
// import {getCount, increase} from './counter.js';
import * as counter from './counter.js';

counter.increase();
counter.increase();
counter.increase();
console.log(counter.getCount());

OS 모듈

내 서버가 동작하고 있는 환경에 대한 정보를 알기 위해 사용한다.

const os = require('os');

console.log(os.EOL === '\n'); // 맥의 줄바꿈 형식
console.log(os.EOL === '\r\n'); // 윈도우의 줄바꿈 형식

console.log(os.totalmem()); // 전체 메모리
console.log(os.freemem()); // 사용가능한 메모리
console.log(os.type()); // 운영체제 타입
console.log(os.userInfo()); // 사용자 정보
console.log(os.cpus()); // cpu 정보
console.log(os.homedir()); // 홈디렉토리 경로
console.log(os.hostname()); // 호스트 이름

process 모듈

node 프로그램이 동작하고 있는 즉, node의 프로세스 정보를 알기 위해 사용한다.

const process = require('process');

console.log(process.execPath); // 현재 실행되고 있는 위치
console.log(process.version); // 노드의 버전
console.log(process.pid); // 프로세스 아이디
console.log(process.ppid); // 프로세스 부모의 아이디
console.log(process.platform); // 플랫폼 정보
console.log(process.env); // 환경변수 정보
console.log(process.uptime()); // node가 얼마나 실행되었는지
console.log(process.cwd()); // 현재 실행되고 있는 node의 경로
console.log(process.cpuUsage()); // cpu 사용량


// process.nextTick
// nextTick은 setTimeout과 비슷하다.
// 지금 당장 실행하는게 아니고 태스크큐에 콜백으로 넘기고 실행하게 도와주는 메서드이다.
// nextTick이 단순히 nextTick의 콜백 함수를 태스크 큐에 넣는데 그치는게 아니라, 태스크 큐에서 대기 중인 콜백들 중에서 가장 선처리 될 수 있도록 강제

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

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

for (let i = 0; i < 100; i++) {
  console.log('for loop');
}

// 출력
// for loop ...
// nextTick
// setTimeout

타이머

setTimeout : 특정 ms 이후 콜백을 태스크큐에 넣어준다.

setImmediate : 즉시 콜백을 태스크큐에 넣준다. (setTimeout(..., 0) 과 동일하다.)

process.nextTick : 즉시 콜백을 태스큐의 맨 처음에 넣어준다.

console.log('code1');
setTimeout(() => {
  console.log('setTimeout 0');
}, 0);

console.log('code2');
setImmediate(() => {
  console.log('setImmediate');
});

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

// 출력
// code1
// code2
// code3
// process.nextTick
// setImmediate
// setTimeout 0

path 모듈

파일의 경로를 접근하거나 경로에 대해 어떤 처리를 할 때 유용하게 사용할 수 있다.

// example in /Users/uno/Desktop/node/path.js
const path = require('path');

// 운영체제별 경로 표현 방식
// POSIX (Unix: Mac, Linux): 'Users/temp/myfile.html'
// Windows: 'C:\\temp\\myfile.html'

console.log(__dirname); // 현재 파일이 위치한 디렉토리 경로
// Users/uno/Desktop/node
console.log(__filename); // 현재 파일의 경로
// Users/uno/Desktop/node/path.js

console.log(path.sep); // 경로 구분자 (운영체제별 상이)
// /
console.log(path.delimiter); // 환경변수 구분자 (운영체제별 상이)
// :

// basename
console.log(path.basename(__filename)); // 현재 파일 혹은 폴더 이름
// path.js
console.log(path.basename(__filename, '.js')); // 파일이름에서 확장자면 제거
// path

// dirname
console.log(path.dirname(__filename)); // 현재 디렉토리 이름
// Users/uno/Desktop/node

// extension
console.log(path.extname(__filename)); // 파일의 확장자
// .js

//parse
const parsed = path.parse(__filename); // 파싱
console.log(parsed); // 객체 형태
// {
//   root: '/',
//   dir: '/Users/uno/Desktop/node',
//   base: 'path.js',
//   ext: '.js',
//   name: 'path'
// }
console.log(parsed.root);
// /
console.log(parsed.name);
// path

const str = path.format(parsed); // parsed된 객체를 기존의 경로 문자열로 변환
console.log(str);

// isAbsolute 절대 경로인지 상대경로인지
console.log('isAbsolute?', path.isAbsolute(__dirname));
// true
console.log('isAbsolute?', path.isAbsolute('../'));
// false

// normalize - 경로에 이상한 부분을 자동으로 수정
console.log(path.normalize('./folder////////sub'));
// './folder/sub'

// join - 경로를 편하게 조합
console.log(__dirname + path.sep + 'image');
// Users/uno/Desktop/node/image
console.log(path.join(__dirname, 'image'));
// // Users/uno/Desktop/node/image
profile
console.log(noah(🍕 , 🍺)); // true

0개의 댓글