[Node] 노드 기능(1)

찐새·2023년 1월 16일
0

Node.js

목록 보기
2/6
post-thumbnail

1. REPL

브라우저의 콘솔처럼 노드도 콘솔 기능을 제공한다. REPL이라고 하며, 코드 읽기(Read), 해석(Eval), 결과 반환(Print), 종료까지 반복(Loop)의 약어이다.

노드를 설치했다면 터미널에 node를 입력하여 진입하여 자바스크립트 코드를 작성한다. 종료는 .exit을 입력한다.

$ node
Welcome to Node.js v18.13.0.
Type ".help" for more information.
> const x = "Hello Node"
undefined
> console.log(x)
Hello Node
undefined
> .exit

2. 자바스크립트 파일 실행

node 뒤에 js 확장자 파일명을 입력하면 터미널에서 해당 파일을 실행할 수 있다.

예를 들어, helloWorld.js 파일을 생성하여 다음 코드를 작성한다.

// helloWorld.js
function helloWorld(){
  console.log("hello world");
  helloNode();
};

function helloNode(){
  console.log("hello node");
};

helloWorld();

터미널에서 node helloWorld.js를 입력하면 파일의 코드가 실행된 후 종료된다.

$ node helloWorld.js
hello world
hello node

3. 모듈

노드의 모듈에는 CommonJS 모듈ECMAScript 모듈이 있다.

3-1. CommonJS 모듈

자바스크립트 표준이 아닌 CommonJS 모듈은 노드 생태계에서 가장 널리 쓰인다. 표준이 아님에도 많이 쓰인 이유는 표준 이전에 등장했기 때문이다.

// foo.js
function isOdd(x) {
  return (x % 2) ? true : false;
};

module.exports = {
  isOdd
}
/* or
exports.isOdd = function(x) {
  return (x % 2) ? true : false;
}
*/

// bar.js
const { isOdd } = require("./foo");
 
console.log(isOdd(10));
/* or 
const foo = require("./foo");

console.log(foo.isOdd(10)); 
*/

foo.js는 홀짝을 판별하는 함수를 모듈로 내보내고 있다. bar.js에서는 require("./foo")를 통해 foo.js가 내보낸 함수를 불러와 사용한다.

선언한 변수나 객체를 module.exports에 객체로 담아 내보낼 수도 있지만, exports.변수(객체)명으로도 내보낼 수 있다.

3-2. ECMAScript(ES) 모듈

ES 모듈은 자바스크립트 표준 모듈이다. 모듈을 내보내는 파일의 확장자는 .mjs를 사용한다.

// foo.mjs
export function isOdd(x) {
   return (x % 2) ? true : false;
 };

// bar.mjs
import { isOdd } from "./foo.mjs";
 
console.log(isOdd(10));
/* or 
import * as foo from "./foo.mjs";

console.log(foo.isOdd(10));
*/

파일에서 내보낼 변수나 객체를 export한다. 구조 분해 할당으로 필요한 것만 import하거나 as(alias)를 사용하여 파일 전체를 import할 수 있다.

만약 어떤 파일을 불러왔을 때 기본적으로 동작할 기능을 내보내야 한다면 export default를 사용한다.

3-3. 다이내믹 임포트(Dynamic Import)

조건부로 모듈을 불러오는 것을 다이내믹 임포트(Dynamic Import)라고 한다. CommonJS 모듈은 다이내믹 임포트가 가능하지만, ES 모듈에서는 불가능하다.

// dynamic.js
const { isOdd } = require("./foo");

const x = 11;

if (isOdd(x)) {
  const { helloWorld } = require("./helloWorld")
  helloWorld()
}
/* 결과 
$ node dynamic.js
hello world
hello node
*/

// dynamic.mjs
import { isOdd } from "./foo.mjs";

const x = 11;

if (isOdd(x)) {
  const { helloWorld } = import("./helloWorld")
  helloWorld()
}
/* 결과
$ node dynamic.mjs
file:///C:/.../learning_node.js/dynamic.mjs:7
  helloWorld()
  ^

TypeError: helloWorld is not a function
    at ?[90mfile:///C:/.../learning_node.js/?[39mdynamic.mjs:7:3
?[90m    at ModuleJob.run (node:internal/modules/esm/module_job:194:25)?[39m

Node.js v18.13.0
*/

ES 모듈에서 다이내믹 임포트를 사용할 때는 awaitimport 앞에 추가한다.

import { isOdd } from "./foo.mjs";

const x = 11;

if (isOdd(x)) {
  const { helloWorld } = await import("./helloWorld.mjs")
  helloWorld()
}
/* 결과
$ node dynamic.mjs
hello world
hello node
*.

3-4. filename, dirname

노드는 __filename__dirname을 통해 파일 경로에 대한 정보를 제공한다.

// path.js
console.log(`filename: ${__filename}, dirname: ${__dirname}`)


/* 결과
$ node path.js
filename: C:\...\learning_node.js\path.js, dirname: C:\...\learning_node.js
*/

// path.mjs
console.log(`filename: ${__filename}, dirname: ${__dirname}`)
/* 결과
$ node path.mjs
file:///C:/.../learning_node.js/path.mjs:1
console.log(`filename: ${__filename}, dirname: ${__dirname}`)
                         ^

ReferenceError: __filename is not defined in ES module scope
    at ?[90mfile:///C:/.../learning_node.js/?[39mpath.mjs:1:26
?[90m    at ModuleJob.run (node:internal/modules/esm/module_job:194:25)?[39m

Node.js v18.13.0
*/

ES 모듈에서는 __filename__dirname이 동작하지 않는다. 대신 import.meta.url로 경로를 가져올 수 있다.

// path.mjs
console.log(import.meta.url)

/* 결과
$ node path.mjs
file:///C:/.../learning_node.js/path.mjs
*/

4. 자주 사용하는 내장 객체

4-1. global

브라우저의 window와 같은 전역 객체이다. 별다른 호출없이 사용하는 requireconsole 등이 global에 속해 있다.

4-1-1. console

주로 디버깅에 사용한다. 대표적으로 console.log가 있다.

  • console.time(label) : console.timeEnd(label)과 대응되어 같은 label을 가진 timetimeEnd 사이의 시간을 측정한다.
  • console.error(error) : error 내용을 표시한다.
  • console.table(array) : 배열을 테이블 형식으로 표현한다.
  • console.dir(object, options?) : 객체를 콘솔에 표시할 때 사용한다. 옵션을 통해 색을 추가(color)하거나 객체 깊이(depth)를 확인할 수 있다. depth의 기본값은 2이다.
  • console.trace(label) : 에러 추적에 사용한다.

4-1-2. 타이머

  • setTimeout(callback, delay) : delay(ms) 이후에 callback을 실행한다.
  • setInterval(callback, delay) : delay(ms) 마다 callback을 반복 실행한다.
  • setImmediate(callback) : callback을 즉시 실행한다.
  • clearTimeout(id) : setTimeout을 취소한다.
  • clearInterval(id) : setInterval을 취소한다.
  • clearImmediate(id) : setImmediate를 취소한다.

4-1-3. process

현재 실행되고 있는 노드 프로세스에 대한 정보를 담고 있다.

  • process.version : 설치된 노드의 버전
  • process.arch : 프로세서 아키텍처 정보
  • process.platform : 운영체제 플랫폼 정보
  • process.pid : 현재 프로세스 아이디
  • process.uptime() : 프로세스 동작 시간. 단위는 초(second).
  • process.execPath : 노드 경로
  • process.cwd() : 현재 프로세스 실행 위치
  • process.cpuUsage() : 현재 cpu 사용량
  • process.env : 시스템의 환경 변수
  • process.nextTick(callback) : 이벤트 루프가 다른 콜백 함수보다 nextTick의 콜백 함수를 우선 처리하도록 만든다.
  • process.exit(code) : 실행 중인 노드 프로세스를 종료한다. 서버를 멈추므로 특수한 경우에만 사용한다. code로 아무것도 입력하지 않거나 0을 주입하면 정상 종료, 1을 주입하면 비정상 종료를 의미한다.

5. 자주 사용하는 내장 모듈

노드 내에는 많은 모듈이 내장되어 있다. 모듈 or node:모듈 형식으로 호출하면 노드가 알아서 내장 모듈을 파악해 가져온다. os를 예로 든다면 아래와 같다.

// os.js
const os = require("os"); // or const os = require("node:os");

// os.mjs
import os from "os"; // or import os from "node:os";

5-1. os

운영체제의 정보를 가져온다.

  • os.arch() : process.arch와 동일
  • os.platform() : process.platform과 동일
  • os.type() : 운영체제 종류
  • os.uptime() : 운영체제 부팅 후 동작 시간(초)
  • os.hostname() : 컴퓨터 이름
  • os.release() : 운영체제 버전
  • os.homedir() : 홈 디렉토리 경로
  • os.tmpdir() : 임시 파일 저장 경로
  • os.cpus() : 컴퓨터 코어 정보
  • os.freemem() : 사용 가능한 메모리(RAM)
  • os.totalmem() : 전체 메모리 용량

5-2. path

디렉토리와 파일 경로를 쉽게 조작하도록 도와준다. 운영체제마다 경로 구분자가 다르다. 윈도 타입\로, POSIX 타입/로 구분한다.

  • path.sep : 경로 구분자(윈도 = \, POSIX = /)
  • path.delimiter : 환경 변수 구분자(윈도 = ;, POSIX = :)
  • path.dirname(경로) : 파일이 위치한 디렉토리 경로
  • path.extname(경로) : 파일 확장자
  • path.basename(경로, 확장자) : 확장자를 포함한 파일명 표시. 파일명만 표시하려면 두 번째 인수로 확장자를 넣는다.
  • path.parse(경로) : 파일 경로를 root, dir, base, ext, name으로 분리
  • path.format(객체) : path.parse()한 객체를 파일 경로로 병합
  • path.normalize(경로) : /\를 실수로 여러 번 사용했거나 혼용했을 때 정상적인 경로로 변환
  • path.isAbsolute(경로) : 파일 경로가 절대 경로인지 상대 경로인지 true/false로 알려준다.
  • path.relative(기준경로, 비교경로) : 기준경로에서 비교경로로 가는 방법을 알려준다.
  • path.join(경로, …) : 여러 인수를 하나의 경로로 합친다. 맨 앞의 /를 상대경로로 인식해 처리한다.
  • ex) path.join("/learning_node.js", "/foo.mjs") ➡️ \learning_node.js\foo.mjs
  • path.resolve(경로, …) : path.join()과 비슷하나, 맨 앞의 /가 붙은 경로를 무시한다.
  • ex) path.resolve("/learning_node.js", "/foo.mjs") ➡️ C:\foo.mjs

윈도 타입에서 POSIX 타입을 사용하려면 path.posix.sep 등을 사용하고, 반대는 path.win32.sep 등을 사용한다.

5-3. url

인터넷 주소를 조작하는 모듈이다. url 형식은 웹 표준을 정하는 단체인 WHATWG 방식을 따른다.

WHATWG URL

URLurl 모듈의 내장 객체이면서 노드의 내장 객체이기 때문에 따로 호출하지 않아도 사용할 수 있다. 아래는 new URL("http://example.com")을 출력한 결과다.

URL {
  href: 'http://example.com/',
  origin: 'http://example.com',
  protocol: 'http:',
  username: '',
  password: '',
  host: 'example.com',
  hostname: 'example.com',
  port: '',
  pathname: '/',
  search: '',
  searchParams: URLSearchParams {},
  hash: ''
}

파싱된 url은 url.format()으로 다시 병합할 수 있다.

host 없이 pathname만으로는 주소를 처리할 수 없다. 이때는 new URL(pathname, host)로 적어야 한다.

또한, 보통 데이터를 전달할 때 query string을 통한다. url 마지막에 ?로 시작하여 key=value의 형태를 갖는다. searchParams 메서드가 이러한 부분을 처리한다.

URL {
  href: 'http://example.com/?q=params',
  // (...)
  search: '?q=params',
  searchParams: URLSearchParams { 'q' => 'params' },
  // (...)
}

searchParams에는 다음과 같은 메서드가 존재한다.

  • getAll(key) : 키에 해당하는 모든 값을 가져온다.
  • get(key) : 키에 해당하는 첫 번째 값만 가져온다.
  • has(key) : 해당 키가 있는지 확인한다.
  • keys() : 모든 키를 iterable한 객체로 가져온다.
  • values() : 모든 값을 iterable한 객체로 가져온다.
  • append(key, value) : 해당 키를 추가한다. 같은 키의 값이 있으면 유지하고 추가한다.
  • set(key, value) : 모든 키-값을 지우고 새로 추가한다.
  • delete(key) : 해당 키를 제거한다.
  • toString() : 조작한 searchParams 객체를 문자열로 만든다.

참고
Node.js 공식 사이트
Node.js 교과서 개정 3판

profile
프론트엔드 개발자가 되고 싶다

0개의 댓글