본문 바로가기

Node.js

3. 노드 기본 [Node]

노드 기본,

노드가 기본적으로 제공하는 내장 객체와 내장 모듈을 알아본다.

 

공통적으로 다운로드 없이 사용할 수 있다.

차이점으로 내장 모듈은 import, require해야 사용할 수 있다.

 

암기할 필요없다. 부담없이 학습하자.

(필요할 때 찾아보며 사용하면 된다.)

 

 

1. 노드 내장 객체

  1. global
    1. 노드의 전역 객체
    2. 브라우저에서 Window와 동일한 역할을 한다. (globalThis로 구분없이 사용할 수 있다.)
    3. 모든파일에서 접근가능하다.
    4. 생략해서 작성할 수 있다. ( global.console.log("abc") === console.log("abc") )
  2. console
    1. 브라우저에서의 console 객체와 거의 동일
    2. console.log("⭐") : 평범한 로깅
    3. console.error ("⭐") : 에러 로깅
    4. console.dir ("⭐", {옵션}) : 객체 로깅
    5. console.trace() : 호출스택 로깅
    6. console.time("⭐") ~ console.timeEnd("⭐") : 둘 사이 시간 경과 알려준다.
  3. timer
    1. set 메서드에 clear 메서드가 대응된다.
    2. set 메서드의 리턴값(아이디)을 clear 메서드에 넣어서 취소할 수 있다.
    3. 밀리초 == 초 * 1000
    4. setTimeout(콜백함수, 밀리초) : 밀리초 이후 콜백함수 실행 (clearTimeout)
    5. setInterval(콜백함수, 밀리초) : 밀리초마다 콜백함수 반복 실행 (clearInterval)
    6. setImmediate(콜백함수) : 즉시 콜백함수 실행 (clearImmediate)
  4. process
    1. 현재 실행중인 노드프로세스에 대한 정보를 담고있다.
    2. process.version : 설치된 노드의 버전
    3. process.arch : 프로세서 아키텍처 정보
    4. process.platform : 운영체제 플랫폼 정보
    5. process.pid : 현재 프로세스의 아이디
    6. process.uptime() : 프로세스가 시작된 후 흐른 시간(단위는 초)
    7. process.execPath : 노드의 경로
    8. process.cwd() : 현재 프로세스가 실행되는 위치
    9. process.cpuUsage() : 현재 cpu 사용량
    10. process.env.⭐ : process.env는 시스템 환경 변수들이 들어있는 객체. 비밀키를 보관하는 용도로 사용된다. 일부 환경 변수는 노드 실행시 영향을 미친다.(NODE_OPTIONS UV_THREADPOOL_SIZE) 신중하게 사용.
    11. process.nextTick(콜백함수) : 이벤트루프가 다른 콜백함수들보다 nextTick의 콜백함수를 우선적으로 처리한다.(like promise, so 남용금지)
    12. process.exit(코드) : 현재 프로세스 종료 (코드가 없거나 0 : 정상종료, 이외의 코드는 비정상 종료를 의미한다.) 

 

2. 노드 내장 모듈

  1. os
    1. const os = require("os");
    2. 운영체제의 정보를 담고 있다.
    3. os.cpus() : 컴퓨터의 코어정보
  2. path
    1. const path = require("path");
    2. 맥과 리눅스 등 운영체제에 따라 경로(분기)처리에 차이가 있다.
    3. path.join(__dirname, "var.js") : join에 여러 인자를 넣으면 하나의 경로로 합쳐준다. (__dirname : 파일이 위치한 폴터의 경로 추출)
  3. url
    1. WHATWG(웹 표준)방식의 url을 사용한다.
    2. 과거 노드에서만 사용하던 방식의 url이 있었으나, 이제는 가급적 사용하지 않는다.
    3. url모듈은 내장 객체이기도 하다. (require생략 가능)
    4. const myURL = new URL("⭐")
    5. myURL.searchParams.getAll("🍊") : 🍊(키)에 해당하는 모든 값 가져온다.
    6. myURL.searchParams.get("🍊") : 🍊(키)에 해당하는 첫번째 값만 가져온다.
    7. myURL.searchParams.has("🍊") : 🍊(키)의 존재유무를 검사한다.(T or F)
    8. myURL.searchParams.keys() : 모든 키를 반복기(iterator) 객체로 가져온다.
    9. myURL.searchParams.values() : 모든 값을 반복기(iterator) 객체로 가져온다.
    10. myURL.searchParams.append("🙏", "❤️") : (기존에서) 추가
    11. myURL.searchParams.set( "🙏", "❤️" ) : 같은 키의 값을 모두 지우고 추가
    12. myURL.searchParams.delete( "🙏" ) : 🙏(키) 삭제
    13. myURL.searchParams.toString() : searchParams객체를 다시 문자열로 만든다.
    14. 과거 queryString을 많이 사용했었다. 요즘은 searchParams를 많이 쓴다.

  1. dns
    1. 도메인을 통해 IP, 기타 DNS정보 얻고자 할 때 사용한다.
    2. dns는 특정 서버의 IP를 알아내야 할 때 쓰면 된다.
    3. import dns from "dns/promises"
    4. cosnt ip = await dns.lookup("⭐") : ⭐의 ip주소를 가져온다.
  2. crypto
    1. 단방향 암호화 : 암호화는 가능하지만 복호화는 불가능하다.
    2. 단방향 암호화의 대표주자는 해시(sha512)이다. 문자열을 고정된 길이의 다른 문자열로 바꾸는 방식이다.
    3. 노드에서 단방향 암호화는 pbkdf2와 scrypt를 지원한다.
    4. 양방향 암호화 : 대칭형 암호화로 복호화가 가능하다.
    5. 복호화를 위해서 Key가 사용된다. (암호화 할때와 복호화 할때 Key가 일치해야 한다.)
    6. 노드는 createCipheriv를 지원한다.
    7. Key만 뺏으면 털리기에 취약하다.
  3. util
    1. 각종 편의 기능을 모아둔 모듈이다.
    2. const util = require("util")
    3. util.deprecate(⭐) : 잘못 만든 함수에 경고를 집어 넣을때 사용된다. (사용자 있을 수 있기에 삭제X)
    4. util.promisify(⭐) : 콜백 패턴을 프로미스 패턴으로 바꿔준다. (then과 catch 사용이 가능하다.)
  4. worker_threads
    1. 노드에서 멀티스레드 방식의 작업을 지원한다.
    2. 암호화, 압축 구현하는 경우에 사용된다. 사용빈도가 낮다. 
  5. child_process
    1. 파이썬 프로그램을 실행할 수 있다. (파이썬이 설치되어 있어야 한다. 노드는 단지 실행만 해준다.)
  6. fs
    1. 파일 시스템 접근 모듈
    2. 브라우저는 제한적으로만 가능하지만, 노드는 fs모듈을 통해 가능하다.
    3. 파일/폴더 생성, 삭제, 읽기, 쓰기가 가능하다.
    4. fs.readFile( "./⭐.txt", (err, data) => { ~ } ) : 콜백형태로 파일 읽기 (비동기이므로 순서 보장이 안된다.)
    5. const data = fs.readFileSync( "./⭐.txt" ) : 간단하게 동기형태로 파일 읽기 (백그라운드 X) 그러나 이 방식은 순서유지를 위해 비동기의 장점을 포기한 형태이므로 비효율적이다. 서버 초기화 등의 상황에서 사용
    6. const fs = require("fs").promises : 포로미스형태로 파일 읽기
const fs = require("fs");

fs.readFile("./⭐.txt", (err, data) => {
	if (err) {
    	throw err;
    }
    console.log(data);
    console.log(data.toString());
});
const fs = require("fs").promises;

fs.readFile("./⭐.txt")
	.then((data) => {
    	console.log(data);
        console.log(data.toString());
    })
    .catch((err) => {
    	throw err;
    })

 

3. 버퍼, 스트림, pipe (fs+)

버퍼 : 일정한 크기로 모아두는 데이터, 일정한 크기가 되면 한번에 데이터 처리 (형식 : 16진법)
버퍼링 : 버퍼에 데이터가 찰때까지 데이터를 모으는 작업
스트림 : 데이터의 흐름, 일정한 크기로 나눠서 여러번에 걸쳐서 데이터 처리
스트리밍 : 일정한 크기로 데이터를 지속적으로 전달하는 작업

 

스트림은 버퍼(청크)의 크기를 작게해서, 주기적으로 데이터를 전달한다.

버퍼의 크기가 크다는 것은 많은 메모리 차지를 의미한다.

대용량 데이터 처리에 있어서 버퍼의 크기를 줄여 데이터를 전달하는 스트림은 필수이다.

주기적으로 데이터를 전달하는 특성을 살려 스트리밍과 같은 작업에서도 스트림이 필수이다.

 

const buffer = Buffer.from("abcd");

console.log(buffer);
console.log(buffer.length);
console.log(buffer.toString());

const array = [Buffer.from("abc"), Buffer.from("def"), Buffer.from("ghi")];

// concat 버퍼합치기, toString 스트링으로 바꾸기
console.log(Buffer.concat(array).toString()); 

// alloc 텅빈 5바이트짜리 버퍼 만들기
console.log(Buffer.alloc(5));

 

const fs = require("fs");

//createReadStream

const readStream = fs.createReadStream("./⭐.txt", {highWaterMark : 16});
// highWaterMark 최대 스트림 크기
const data = [];

readStream.on("data", (chunk) => {
	data.push(chunk);
    console.log("data :", chunk, chunck.length);
});

readStream.on("end", () => {
	console.log("end :", Buffer.concat(data).toString());
});

readStream.on("error", (err) => {
	console.log("error :", err)
});


//createWriteStream

const writeStream = fs.createWriteStream("./⭐.txt");

writeStream.on("finish", () => {
	console.log("파일쓰기완료");
})

writeStream.write("abc");
writeStream.write("def");
writeStream.end();

 

비동기에는 에러처리가 필수이다!👍

 

파일에서 읽어온 데이터를 또다른 파일에 작성하는 코드를 작성해보자.

읽어온 스트림 데이터를 또다른 파일에 작성할 때는 pip메서드를 사용한다.

 

버퍼방식과 스트림방식을 비교해보면 파일의 크기가 클수록,

메모리 면에서 스트림방식에 큰 장점을 느낄 수 있다.

const fs = require("fs");

console.log("before :", process.memoryUsage().rss);


// 방식1 : 버퍼

const dataB = fs.readFileSync("./⭐.txt");
fs.writeFileSync("./🍊.txt", dataB);


console.log("buffer :", process.memoryUsage().rss);

 

const fs = require("fs");

console.log("before :", process.memoryUsage().rss);


// 방식2 : 스트림

const readStream = fs.createReadStream("./⭐.txt");
const writeStream = fs.createWriteStream("./🍊.txt");
readStream.pipe(writeStream);


readStream.on("end", () =>{
	console.log("buffer :", process.memoryUsage().rss);
});

 

 

4. 예외처리

예외는 처리하지 못한 에러를 의미한다.

JS는 싱글스레드기반이기에 에러를 만나면 프로세스 전체가 멈추는 상황을 야기한다.

따라서 에러처리가 필수이다.

 

기본적으로 try catch문으로 예외처리를 한다.

 

try catch를 통한 에러처리가 필요없는 곳이 있다. (프로세스 멈추지 않는 경우)

a. 노드 비동기 메서드의 에러는 따로 처리하지 않아도 된다. 콜백 함수에서 에러 객체를 제공하기 때문이다.

b. 프로미스의 에러는 따로 처리하지 않아도 된다. (단, 버전이 올라가면 달라질 수 있다. (현 노드14는 괜춘) )

 

 

uncaughtException를 통해 에러를 한방에 처리할 수 있다.

프로세스 정지를 막아준다. 하지만 에러는 찾아서 해결하는 것이 맞다.

복구 작업용으로 사용하기에 부적합하고, 에러 내용 기록용으로만 사용하는 것이 좋다.

process.on("uncaughtException", (err) =>{
	console.log("예기치 못한 에러", err)
})

..

 

 

 

참고❤️

https://www.zerocho.com/book/1

 

ZeroCho Blog

ZeroCho의 Javascript와 Node.js 그리고 Web 이야기

www.zerocho.com

 

 

'Node.js' 카테고리의 다른 글

2. express (서버제작 level 2) [express]  (0) 2024.11.11
1. http (서버제작 level 1) [express]  (1) 2024.11.05
4. 패키지 [Node]  (2) 2024.11.04
2. 노드 사용법 [Node]  (0) 2024.11.03
1. 노드? [Node]  (2) 2024.10.17