티스토리 뷰

REPL 사용하기

REPL(Read Eval Print Loop)이란 노드의 콘솔을 말한다. 자바스크립트는 스크립트 언어이므로 미리 컴파일하지 않아도 콘솔에서 코드를 실행할 수 있다.

노드의 REPL입력한 코드를 읽고(Read), 해석하고(Eval), 결과물을 반환하고(Print), 종료할 때까지 반복한다.(Loop)

JS 파일 실행하기

노드에서 자바스크립트 코드를 실행할때 REPL에 직접 코드를 입력하는 대신 자바스스크립트 파일을 만들어 실행할 수 있다.

콘솔에서 REPL로 들어가는 명령어는 node이고 노드를 통해 파일을 실행하는 명령어는 node [자바스크립트 파일 경로]이다.

모듈로 만들기

모듈이란 특정한 기능을 하는 함수나 변수들의 집합을 말한다.

모듈로 만들어두면 여러 프로그램에 해당 모듈을 재사용할 수 있다. 이것은 자바스크립트에서 코드를 재사용하기 위해 함수로 만드는 것과 비슷하다.

모듈은 단 한번만 실행되고 실행된 모듈은 공유되므로 어느 한 모듈에서 멤버변수를 수정하면 다른 모듈에서도 변경사항을 확인할 수 있다.

노드는 코드를 모듈로 만들 수 있다는 점에서 브라우저의 자바스크립트와 다르다.

노드에서는 두가지 형식의 모듈을 사용한다.

  • CommonJS 모듈
  • ECMAScript 모듈

CommonJS 모듈

CommonJS 모듈은 표준 자바스크립트 모듈은 아니지만 표준이 나오기 이전부터 쓰이던 방식이기에 노드 생태계에서 가장 널리 쓰이는 모듈이다.

module

모듈을을 만들 때는 모듈이 될 파일과 모듈을 불러와서 사용할 파일이 필요하다.

// var.js
const odd = 'CJS 홀수입니다';
const even = 'CJS 짝수입니다';

module.exprots = {
    odd,
    even,
};
// func.js
const {odd, even} = require('./var');

function checkOddOrEven(num) {
    if(num % 2) {
        return odd;
    }
    return even;
}

module.exports = checkOddOrEven;

require 함수 안에 불러올 모듈의 경로를 적는다.
파일 경로에서 jsjson 같은 확장자는 생락할 수 있다.
다른 모듈을 사용하는 파일을 다시 모듈로 만들 수 있다.
module.exprots에는 객체에만 대입해야하는 것은 아니며 함수나 변수를 대입해도 된다.
모듈 하나가 여러 개의 모듈을 사용할 수 있다.

모듈화 장점 모듈화 단점
여러 파일에 걸쳐 재사용되는 함수나 변수를 모듈로 만들어두면 편리하다 모듈이 많아지고 모듈 간의 관계가 얽히게 되면 구조를 파악하기 어렵다

module.exportexport는 같은 객체를 참조하고 있다.

console.log(module.exports === exports) // true

// exports -> module.exports -> {}

exportsmodule.exports를 참조하고 module.exports는 빈 객체({ })를 참조한다.

require

require는 함수이고, 함수는 객체이므로 객체로서 속성 몇개를 가지고 있다.
require가 반드시 파일 최상단에 위치할 필요가 없고, module.exports도 최하단에 위치할 필요가 없다.

require.cache

파일 이름이 속성명으로 들어가 있다.
속성 값으로는 각 파일의 모듈 객체가 들어있다.
한번 require한 파일은 require.cache에 저장되어 재사용된다.

require.main

require.main은 노드 실행 시 첫 모듈을 가리킨다
require.main 객체의 모양은 require.cache의 모듈 객체와 같다.

순환참조

A라는 모듈 을 참조하는 파일 B가 있는데 파일 A 파일도 B 모듈을 참조한다면 서로 참조하고 있으므로 require를 계속 반복하게 되는데 이것을 순환참조라 부른다.

노드는 순환 참조가 있을 경우에는 순환 참조되는 대상을 빈 객체로 만든다.

ECMAScript 모듈

ECMAScript모듈(ES모듈)은 공식적인 자바스크립트 모듈 형식이다.
브라우저에서도 ES 모듈을 사용할 수 있어 브라우저와 노드에 같은 모듈 형식을 사용할 수 있다는 장점이 있다.

// var.mjs
export const odd = 'MJS 홀수입니다';
export const even = 'MJS 짝수입니다';
// func.mjs
import {odd, even} from './var.mjs';

function checkOddOrEven(num){
    if(num%2){
        return odd;
    }
    return even;
}

export default checkOddOrEven;

ES모듈의 importexport defaultrequiremodule처럼 함수나 객체가 아닌 문법 그 자체다.
파일도 js가 아닌 mjs다. mjs 확장자 대신 js 확장자를 사용하면서 ES모듈을 사용하려면 package.jsontype: "module" 속성을 넣어야한다.
CommonJS 모듈과는 다르게 import시 파일 경로에서 js, mjs 같은 확장자는 생략할 수 없다.

차이점 ComonJS 모듈 ECMAScript 모듈
문법 require('./a');
module.exports = A;
const A = require('./a');
exports.C = D;
const E = F; exports.E = E;
const {C, E} = require('./b');
import './a.mjs';
export default A;
import A from './a.mjs';

export const C = D; const E = F;

export {E};
import {C, E} from './b.mjs';
확장자 js
cjs
js (package.jsontype: "module" 필요)
mjs
확장자 생략 가능 불가능
다이나믹 임포트 가능 불가능
인덱스(index)생략 가능( require('./folder') ) 불가능( import './folder/index.mjs' )
top level await 불가능 가능
__filename,
__dirname,
require, module.exports,
exports
사용 가능 사용 불가능(__filename 대신 import.meta.url 사용)
서로 간 호출 가능  

CommonJS 모듈과 ES 모듈 서로 간에 잘 호환되지 않는 케이스가 많으므로 웬만하면 한가지 형식만 사용하는것이 좋다.

다이나믹 임포트

CommonJS 모듈에서는 모듈을 동적으로 불러올 수가 있다.(dynamic import)
ES는 다이나믹 임포트가 불가능해 import함수를 사용해 동적으로 불러온다.

// dynamic.js
const a = false;
if(a){
    require('./func');
}
// dynamic.mjs
const a = true;
if(a){
    import './func.mjs'; // ES모듈은 다이나믹 임포트 불가능
}

// import 함수 사용해 동적 불러오기
const a = true;
if(a){
    const m1 = await import('./func.mjs');
    console.log(m1);
    const m2 = await import('./var.mjs');
    console.log(m2);
}

importPromise를 반환하므로 awaitthen을 붙여야한다.
ES 모듈의 최상위 스코프에서는 async 함수 없이도 await를 할 수 있다.(top level await)

__filename, __dirname

노드는 __filename, __dirname 키워드로 경로에 대한 정보를 제공한다.
하지만 경로가 문자열로 반환되기도 하고 \나 / 같은 경로 구분자 문제도 있기에 path 모듈을 함께 사용한다.

console.log(__filename); // 파일의 이름까지 경로 표시
console.log(__dirname); // 파일이있는 폴더까지 경로 표시

ES모듈에서는 __filename__dirname 대신 import.meta.url을 사용해 경로를 가져온다.

console.log(import.meta.url);

노드 내장 객체

CommonJS 모듈에서 require 함수나 module 객체는 노드 내장 객체이기 때문에 따로 선언하지 않았음에도 사용할 수 있다.
노드에서는 기본적인 내장객체와 내장 모듈을 제공한다.
내장 객체와 내장 모듈은 브라우저의 window 객체와 비슷하다.

global

브라우저의 window와 같은 전역 객체이며 모든 파일에서 접근할 수 있다.
require함수는 원래 global.require이지만 global이 생략된거다.
console 객체도 원래는 global.console이다.

console

console 객체는 보통 디버깅을 위해 사용된다.

const string = 'abc';
const number = 1;
const boolean = true;
const obj = {
    outside: {
        inside: {
            key: 'value',
        }
    }
}
console.time('전체 시간');
console.log('평범한 로그','쉼표로 구분해 여러 값을 찍을 수 있다', string, number, boolean, obj);
console.error('에러 메시지는 console.error에 담기')

console.table([{name:'bear', birth:1999}, {name:'hero', 1988}]);

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

console.time('시간 측정');

console.tiemEnd('시간 측정');

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

console.timeEnd('전체 시간');
  • console.tiem(레이블): console.timeEnd(레이블)과 대응되어 사이의 시간을 측정한다.
  • console.log(내용): 평범한 로그를 콘솔에 표시한다.
  • console.error(에러 내용): 에러를 콘솔에 표시한다.
  • console.table(배열): 배열의 요소로 리터럴을 넣으면, 객체의 속성들이 테이블 형식으로 표현된다.
  • console.dir(객체, 옵션): 객체를 콘솔에 표시할 때 사용한다. 옵션의 colors나 depth로 색을 추가하거나 객체 안의 객체를 몇 단계까지 보여줄지를 결정한다.
  • console.trace(레이블): 에러가 어디서 발생했는지 추적할 수 있게 한다.

타이머

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

setTimeout(콜백, 0)setImmediate(콜백)은 이벤트 루프를 거친뒤 즉시 실행된다.
하지만 파일 시스템 접근, 네트워킹 같은 I/O작업의 콜백 함수 안에서 타이머를 호출하는 경우의 setImmediatesetTimeout보다 먼저 실행된다.

process

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

process.env

시스템의 환경 변수들을 가지고 있는 객체다.
시스템 환경 변수 외에도 임의로 환경 변수를 저장할 수 있다.
중요한 비밀번호는 process.env에 넣어서 사용할 수 있다.

process.nextTick(콜백)

이벤트 루프가 다른 콜백 함수들보다 nextTick의 콜백 함수를 우선으로 처리하도록 만든다.
setImmediatesetTimeout보다 먼저 실행된다.
process.nextTickPromise를 마이크로태스크(microtask)라고 부른다.

process.exit(코드)

실행 중인 노드 프로세스를 종료한다.
인수를 주지 않거나 0을 주면 정상 종료를 뜻하고, 1을 주면 비정상 종료를 뜻한다.


노드 내장 모듈

노드는 웹 브라우저와 달리 운영체제 정보와 클라이언트가 요청한 주소에 대한 정보를 가져올 수 있는 기능을 제공하는 모듈을 제공한다.

os

노드는 os 모듈에 담겨있는 운영체제의 정보를 가져올 수 있다.

const os = require("os");

console.log("운영체제 정보-------------------------");
console.log("os.arch():", os.arch()); // process.arch와 동일하다
console.log("os.platform():", os.platform()); // process.platform과 동일하다.
console.log("os.type():", os.type()); // 운영체제의 종류를 보여준다
console.log("op.uptime():", os.uptime()); // 운영체제 부팅 이후 흐른 시간(초)을 보여준다.
console.log("os.hostname():", os.hostname()); // 컴퓨터의 이름을 보여준다.
console.log("os.release():", os.release()); // 운영체제의 버전을 보여준다.

console.log("경로--------------------------------");
console.log("os.homedir():", os.homedir()); // 홈 디렉터리 경로를 보여준다.
console.log("os.tmpdir():", os.tmpdir()); // 임시 파일 저장 경로를 보여준다.

console.log("cpu 정보----------------------------");
console.log("os.cpus()", os.cpus()); // 컴퓨터의 코어 정보를 보여준다.
console.log("os.cpus().length", os.cpus().length); // 컴퓨터의 코어 갯수를 보여준다.

console.log("메모리 정보----------------------------");
console.log("os.freemem():", os.freemem()); // 사용 가능한 메모리(RAM)를 보여준다.
console.log("os.totalmem():", os.totalmem()); // 전체 메모리 용량을 보여준다.
운영체제 정보-------------------------
os.arch(): arm64
os.platform(): darwin
os.type(): Darwin
op.uptime(): 27160
os.hostname(): username-MacBook-Air.local
os.release(): 24.0.0
경로--------------------------------
os.homedir(): /Users/username
os.tmpdir(): /var/folders/hj/5h93y06944b3t4033f3lw65m0000gn/T
cpu 정보----------------------------
os.cpus() [
  {
    model: 'Apple M1',
    speed: 2400,
    times: { user: 2160970, nice: 0, sys: 1770290, idle: 17638770, irq: 0 }
  },
  {
    model: 'Apple M1',
    speed: 2400,
    times: { user: 2011390, nice: 0, sys: 1605750, idle: 17966290, irq: 0 }
  },
  {
    model: 'Apple M1',
    speed: 2400,
    times: { user: 1700650, nice: 0, sys: 1148670, idle: 18765040, irq: 0 }
  },
  {
    model: 'Apple M1',
    speed: 2400,
    times: { user: 1442300, nice: 0, sys: 863360, idle: 19333200, irq: 0 }
  },
  {
    model: 'Apple M1',
    speed: 2400,
    times: { user: 2106880, nice: 0, sys: 358090, idle: 19214630, irq: 0 }
  },
  {
    model: 'Apple M1',
    speed: 2400,
    times: { user: 3020150, nice: 0, sys: 314120, idle: 18349880, irq: 0 }
  },
  {
    model: 'Apple M1',
    speed: 2400,
    times: { user: 1438210, nice: 0, sys: 163820, idle: 20091230, irq: 0 }
  },
  {
    model: 'Apple M1',
    speed: 2400,
    times: { user: 700630, nice: 0, sys: 100760, idle: 20896620, irq: 0 }
  }
]
os.cpus().length 8
메모리 정보----------------------------
os.freemem(): 96321536
os.totalmem(): 17179869184

 

path

폴더와 파일의 경로를 쉽게 조작하도록 도와주는 모듈이다.

const path = require("path");

const string = __filename;

console.log("path.sep:", path.sep); // 경로의 구분자를 말한다 윈도우는 \, POSIX는 /이다.
console.log("path.delimiter:", path.delimiter); // 환경번수의 구분자이다. process.env.PATH를 입력하면 여러 개의 경로가 이 구분자로 구분되어있다. 윈도우는 세미콜론(;)이고, POSIX는 콜론(:)이다.
console.log("-------------------------------");
console.log("path.dirname():", path.dirname(string)); // 파일이 위치한 폴더 경로를 보여준다.
console.log("path.extname():", path.extname(string)); // 파일의 확장자를 보여준다.
console.log("path.basename():", path.basename(string)); // 파일의 이름(확장자 포함)을 표시한다. 파일에 이름만 표시하고 싶다면 base
console.log(
  "path.basename - extname:",
  path.basename(string, path.extname(string))
); // 파일의 이름만 표시하고 싶다면 basename의 두 번째 인수로 파일의 확장자를 넣으면 된다.
console.log("-------------------------------");
console.log("path.parse():", path.parse(string)); // 파일의 경로를 root, dir, base, ext, name으로 분리한다.
console.log(
  "path.format():",
  path.format({
    dir: "/Users/username/study",
    name: "path",
    ext: ".js",
  })
); // path.parse()한 객체를 파일 경로로 합친다.
console.log(
  "path.normalize():",
  path.normalize("////Users////username//study/path.js")
); // /나 \를 실수로 여러 번 사용했거나 혼용했을 때 정상적인 경로로 변환한다.
console.log("-------------------------------");
console.log("path.isAbsolute(/Users):", path.isAbsolute("/Users")); // 파일의 경로가 절대경로인지 상대경로인지 true나 false로 알려준다.
console.log("path.isAbsolute(./path):", path.isAbsolute("./path")); // 파일의 경로가 절대경로인지 상대경로인지 true나 false로 알려준다.
console.log(
  "path.relative():",
  path.relative("/Users/username/study/nodejs/ch3/path.js", "/Users")
); // 첫 번째 경로에서 두 번째 경오로 가는 방법을 알려준다.
console.log("path.join():", path.join(__dirname, "..", "..", "..", "..", ".")); // 여러 인수를 넣으면 하나의 경로로 합친다.
console.log("path.resolve():", path.resolve(__dirname, "..", "..", "..", ".")); // path.join과 비슷하지만 path.join은 상대경로로 처리하고 path.resolve는 절대경로로 처리한다.
path.sep: /
path.delimiter: :
-------------------------------
path.dirname(): /Users/username/study/nodejs/ch3
path.extname(): .js
path.basename(): path.js
path.basename - extname: path
-------------------------------
path.parse(): {
  root: '/',
  dir: '/Users/username/study/nodejs/ch3',
  base: 'path.js',
  ext: '.js',
  name: 'path'
}
path.format(): /Users/username/study/path.js
path.normalize(): /Users/username/study/path.js
-------------------------------
path.isAbsolute(/Users): true
path.isAbsolute(./path): false
path.relative(): ../../../../..
path.join(): /Users
path.resolve(): /Users/username

url

인터넷 주소를 쉽게 조작하도록 도와주는 모듈이다.

const url = require("url");

const { URL } = url;

const myURL = new URL(
  "http://www.gilbut.co.kr/book/bookList.aspx?sercate1=001001000#anchor"
);

console.log("new URL():", myURL);
console.log("url.format():", url.format(myURL));
new URL(): URL {
  href: 'http://www.gilbut.co.kr/book/bookList.aspx?sercate1=001001000#anchor',
  origin: 'http://www.gilbut.co.kr',
  protocol: 'http:',
  username: '',
  password: '',
  host: 'www.gilbut.co.kr',
  hostname: 'www.gilbut.co.kr',
  port: '',
  pathname: '/book/bookList.aspx',
  search: '?sercate1=001001000',
  searchParams: URLSearchParams { 'sercate1' => '001001000' },
  hash: '#anchor'
}
url.format(): http://www.gilbut.co.kr/book/bookList.aspx?sercate1=001001000#anchor

dns

DNS를 다룰 때 사용하는 모듈이다. 주로 도메인을 통해 IP나 기타 DNS 정보를 얻을때 사용한다.

crypto

다양한 방식의 암호화를 도와주는 모듈이다.

util

각종 편의 기증을 모아둔 모듈이다.

worker_threads

노드에서 멀티 스레드 방식으로 작업을 할 수 있게 도와주는 모듈이다.

child_process

노드에서 지금 실행중인 파일이아닌 다른 파일을 실행하거나 명령어를 수행하고 싶을때 사용하는 모듈이다.


fs 모듈

fs모듈은 파일 시스템에 접근하는 모듈이다.

동기 메서드와 비동기 메서드

버퍼와 스트림

버퍼링은 데이터를 모으는 동작이다. 파일을 읽을 때 메모리에 파일 크기만큼 공간을 마련해두며 파일 데이터를 메모리에 저장하는데 이때의 메모리를 버퍼라한다.

스트리밍은 데이터를 조금씩 전송하는 동작이다. 버퍼의 크기를 작게 만들고 여러 번에 걸쳐 나눠 보내는 방식을 스트림이라 한다.

이벤트

커스텀 이벤트를 만들 수 있다.

const EventEmitter = require("events");

const myEmitter = new EventEmitter();

myEmitter.on("이벤트1", () => {
  console.log("이벤트 1");
});

myEmitter.addListener("이벤트2", () => {
  console.log("이벤트 2");
});

myEmitter.on("이벤트2", () => {
  console.log("이벤트2 추가");
});

myEmitter.once("이벤트3", () => {
  console.log("이벤트 3");
});

myEmitter.emit("이벤트1"); // 이벤트1
myEmitter.emit("이벤트2"); // 이벤트2 이벤트2 추가
myEmitter.emit("이벤트3"); // 이벤트3
myEmitter.emit("이벤트3"); // 실행 안 됨

myEmitter.removeAllListeners("이벤트2");

const event2Listener = () => {
  console.log("이벤트2 a");
};

myEmitter.on("이벤트2", event2Listener);

myEmitter.off("이벤트2", event2Listener);

예외처리

노드는 싱글 스레드로 작동하기 때문에 메인 스레드에서 에러가 발생하면 프로세스 전체가 멈출 수 있다. 그렇기 떄문에 에어를 처리하는 방법을 알아둬야한다. 에러가 발생할 것 같은 부분에 try/catch문으로 감싸면 된다.

try {
    // 에러가 발생한다면
}
catch(err) {
    // 여기서 에러처리
}

참고

 

Node.js 교과서 : 네이버 도서

네이버 도서 상세정보를 제공합니다.

search.shopping.naver.com

 

 

[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지 강의 | 제로초(조현영) - 인프런

제로초(조현영) | 노드가 무엇인지부터, 자바스크립트 최신 문법, 노드의 API, npm, 모듈 시스템, 데이터베이스, 테스팅 등을 배우고 5가지 실전 예제로 프로젝트를 만들어 나갑니다. 클라우드에 서

www.inflearn.com

 

 

[JS] 📚 모듈 사용하기 import / export 완벽 💯 정리

자바스크립트 모듈 개발하는 애플리케이션의 크기가 커지면 언젠간 파일을 여러 개로 분리해야 하는 시점이 옵니다. 이때 분리된 파일 각각을 '모듈(module)'이라고 부르는데, 모듈은 대개 클래스

inpa.tistory.com

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함