섹션2 노드 기본기능

반응형

기본 사용법

노드는 기본적으로 모듈로 만들어서 사용한다.
다른파일에서 코드를 사용하는 방법은 내보내기 와 가져오기를 통해서 사용할수있는데
내보내는 방법은 module.exports 를 사용해서 내보낼 변수를 적어주면된다.

const odd = "홀수 입니다.";

const even = "짝수 입니다.";

// 내보내기 
module.exports = {
    odd,

    even,
};

이렇게 내보내진 변수들은 다른 파일에서 require 를 사용해서 받아 사용할수있다.

// 가져오기 
const { odd, even } = require("./number");

console.log(odd, even);

모듈 ?

모듈시스템은 CommonJs 와 ECMAScript 두가지 가 있다.

CommonJS

Nodejs 에서 보편적으로 사용되며
module.exports 로 모듈을 내보내고 require() 함수를 사용해 모듈을 가져와 사용할수있다.

function exampleFunction() {
    console.log("This is an example function."); 
} 
// 모듈 내보내기 
module.exports = exampleFunction;

// 모듈 가져오기 
const exampleFunction = require('./exampleModule');
exampleFunction(); // 출력: "This is an example function."

require () ?

CommonJS 의 모듈을 불러오는데 사용되는 함수이다.
이는 동기적으로 작동되고 애플리케이션 시작단계에서 주로 이루어진다.
모듈은 내장모듈, 외부 모듈 , 로컬 모듈 다양하게 존재하는데 이를 모두 사용할수있는 함수이다.

  • 내장모듈 - 파일시스템 , HTTP , 경로처리등을 위한 여러 내장모듈이 존재
  • 외부모듈 - npm 을 통해 설치한 모듈 ( express 등 )
  • 로컬모듈 - 자신의 프로젝트에서 정의한 모듈

작동 원리

  1. 파일 위치 확인 - 주어진 경로나 모듈이름을 기반으로 파일을 찾는다
  2. 캐싱 - 모듈은 한번 실행되며 그 결과는 캐시에 저장된다 . 이후에 동일한 모듈을 실행하면 캐싱된 결과를 반환하게된다.
  3. 파일로드 - 파일 시스템에서 파일을 찾아 로드한다
  4. 코드 실행 - 모듈의 코드가 실행되고 module.exports 에 할당된 값을 require 호출에 의해 반환된다.

module.exports == exports ?

module.exports 를 통해 값을 전달할수있다했다
그런데 exports 만 사용해서도 같은 기능을 할수있는데 무슨차이일까?
exports 는 module.exports의 참조 를 하는것 뿐이다 그렇기에 객체 전체를 대체하려면 module.exports 를 사용해야된다.

ES6 모듈시스템 import , export 도 지원하나 이는 설정이나 트랜스파일러가 필요하다.

ECMAScript

ES6에서 소개됬으며 현대 브라우저와 최신버전의 Nodejs 에서 사용할수있도록 지원된다.
export 로 모듈을 내보내고 import 로 모듈을 가져와 사용할수있다.
package.json"type": "module"을 선언함으로써 ESM을 사용할 수 있습니다.

// 모듈 내보내기 
export function exampleFunction() { 
    console.log("This is an example function."); 
}

// 모듈 가져오기
import { exampleFunction } from './exampleModule.js';
exampleFunction(); // 출력: "This is an example function."

비동기적으로 로드하며 컴파일타임에 모듈 구조를 분석할수있다.
또한 라이브 바인딩 ( 모듈값이 변경되면 해당변경사항이 모든 가져오기 에 반영됨 ) 을 지원한다.

this ?

노드에서의 this 는 js 와 비슷하다.
함수에서의 this 를 호출하면 글로벌 을 가르키게되지만
전역에서 this 를 불어오면 module.exports 객체를 불러오게된다.

function thisTest() {

    console.log("함수에서 호출 " + this);

}



console.log(`전역에서 호출 ${this}`); // 전역에서 호출 {}

thisTest(); // 함수에서 호출 global

노드의 내장객체

글로벌 객체

  • console
  • set메서드 , clear 메서드

프로세스

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

터미널 or Cmd 에서 node 실행후 

// 설치된 노드 버전 
process.version 

// 프로세서 아키텍처 정보 
process.arch

// 운영체제 플랫폼 정보  
process.platform

// 프로세스의 아이디  
process.pid

// 프로세스가 시작된후 흐른 시간
process.uptime()

// 노드의 경로
process.execPath

// 현재 프로세스가 실행되는 위치 
process.cwd() 

// 현재 cpu 사용량
process.cpuUsage() 

process.env

시스템 환경 변수들이 있는 객체
비밀키를 보관하는용도로사용됨
환경변수는 process.env 로 접근할수있음
NODE_OPTIONS( 노드 실행 옵션 ), UV_THREADPOOL_SIZE ( 스레드 풀 개수 ) 등
이런 변수들을 사용시 노드 실행시 영향을 미칠수있음

이벤트 루프

비동기함수들 예를들어 setTimeout() 이나 대표적인 Promise then 같은경우를 처리할때
함수마다 우선순위를 갖는 함수가있다.
precess.nextTick() 와 promise 는 대표적으로 setTimeout 과 같은 함수들보다 나중에 실행했어도 먼저 실행되는 우선순위를 갖게된다.

내장 모듈 사용해보기

OS

운영체제의 정보를 담고있음
https://nodejs.org/docs/latest/api/os.html#oseol

// 내장 모듈이라 간단히 사용할수있다.
const os = require('os');

os.cpus // cpu코어 정보를 보여준다.

path

경로처리를 위한 모듈이다.
https://nodejs.org/docs/latest/api/path.html

const path = require('path')

// 여러인자를 넣으면 하나의 경로로 합쳐준다. / 를 넣어도 상대경로로 처리한다.
path.join(__dirname, 'index.js');

// join과 비슷하지만 resolve 경로에 / 를 넣으면 절대경로로 처리하게된다.
path.resolve(__dirname, "/index.js")

url

url 작업하기 위한 유틸리티를 제공한다.

URL 객체의 주요 속성

  • href: 전체 URL 문자열.
  • protocol: 프로토콜 부분 (예: 'http:').
  • host: 호스트 이름과 포트 번호를 포함한 전체 호스트 부분.
  • hostname: 호스트 이름만.
  • port: 포트 번호.
  • pathname: URL의 경로 부분.
  • search: '?'로 시작하는 쿼리 문자열.
  • query: 쿼리 문자열의 내용. url.parse()를 사용할 때 true로 설정하면 객체 형식으로 반환됩니다.
  • hash: '#'로 시작하는 해시 부분.

![[스크린샷 2023-12-06 오후 7.18.59.png]]

const url = require('url'); 

// url 문자열 파싱 - Url 문자열을 url 객체로 변환한다.
const myURL = url.parse(경로);

// url 객체 생성 - WHATWG URL 표준 객체 생성
const newURL = new URL("http://example.com/path?name=value#hash");

console.log(myURL);
console.log(newURL);

dns

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

const dns = require("dns");



// 도메인 이름을 IPv4 , IPv6 주소로 해석한다. ( Nodejs의 네트워크 스택을 사용해 시스템 설정에 따라 해석한다.)

dns.lookup("naver.com", (err, address, family) => {

    console.log("주소:", address); // 주소: 223.130.195.95

    console.log("주소 체계:", family); // 주소 체계: 4

});



// resolve 함수: 지정된 도메인의 특정한 타입의 DNS 레코드를 해석합니다.

// resolve4는 IPv4 주소를, resolveMx는 메일 교환 레코드를 반환합니다.

dns.resolve4("example.com", (err, addresses) => {

    if (err) throw err;

    console.log(`IPv4 주소: ${JSON.stringify(addresses)}`);

});



dns.resolveMx("example.com", (err, addresses) => {

    if (err) throw err;

    console.log(`메일 교환기 주소: ${JSON.stringify(addresses)}`);

});



// setServers 함수: DNS 쿼리에 사용될 DNS 서버 주소를 변경합니다.

dns.setServers(["8.8.8.8", "8.8.4.4"]);

dns 모듈의 특징

  • 비동기적 동작: 대부분의 dns 모듈 함수는 네트워크 요청을 포함하기 때문에 비동기적으로 작동합니다. 콜백 함수를 통해 결과를 받습니다.
  • 에러 처리: DNS 쿼리 중 발생하는 오류는 콜백의 첫 번째 인자로 전달됩니다.
  • 다양한 레코드 타입 지원: resolve 함수를 사용하여 여러 DNS 레코드 타입(A, AAAA, MX, TXT, SRV, PTR 등)을 조회할 수 있습니다.
  • 네트워크 설정의 영향: lookup 함수는 시스템의 네트워크 설정(예: /etc/hosts 파일)을 사용하여 DNS 쿼리를 수행합니다.

util

각종 편의를 모아둔 모듈, 주로 디버깅, 검사 , 상속을위한 도구들이 포함되있다.
deprecated()

  • util.promisify - 콜백 패턴을 사용하는 함수를 Promise 로 반환하는 함수로 변환한다.
              콜백 기반 비동기코드를 async/awaiit 문법으로 쉽게 관리할수있다 
              콜백이 ( error , data) => {} 형식이여야한다.
const util = require("util");
const fs = require("fs");

const readFile = util.promisify(fs.readFile);

async function readConfig() {

try {
const data = await readFile("/path/to/config.json", "utf8");
console.log(data);

} catch (err) {
    console.error("Error reading file:", err);

}

}

crypto 암호화

crypto 모듈을 사용해서 유저의 비밀번호 나 암호화를 해야되는 데이터를 조작할수있다.

단방향 암호화

암호화는 가능하지만 복호화는 불가능한 것을 의미한다.
대표적으로 해시 기법이 존재 한다.
해시기법은 간단하게 입력받은데이터를 알고리즘으로 고정된 길이의 무작위 출력값으로 변환시키는거다.
감자를 입력하면 토마토로 변환되는 알고리즘을 사용하는 해시기법이 있다 가정해보고 변환된 값을 서버에 저장하고 사용자가 감자를 입력하고 이를 변환한 값이 서버에 가지고있는 값과 동일할때만 처리를 해주는 방식으로 진행된다.
이렇게 하면 해킹에 서버데이터를 가져가도 유저의 암호를 찾기는 어렵다.

해시 알고리즘 종류

  • MD5 (Message Digest Algorithm 5): 빠른 속도를 제공하지만, 보안 취약점으로 인해 더 이상 안전하다고 여겨지지 않습니다.
  • SHA-1 (Secure Hash Algorithm 1): MD5보다는 안전하지만, 해시 충돌에 취약한 것으로 밝혀졌습니다.
  • SHA-256 (Secure Hash Algorithm 256bit): Bitcoin과 같은 암호화폐에서 널리 사용되며, 현대 보안 표준에서 권장되는 알고리즘 중 하나입니다.

양방향 암호화

양방향 암호화는 데이터를 암호화 한후 그것을 복호화해서 원래의 데이터로 되돌릴수있는 암호화 방식이다.
대칭키 암호화 와 비대칭키 암호화가 있는데 암호화 , 복호화 할때 사용되는 키를 동일하게 같고있으면 대칭키
암호화에 공개키를 복호화 에는 비밀키를 사용하는 방식이 비대칭키 암호화라고 한다.

worker_threads

멀티스레딩 기능을 제공한다 . 이를통해 단일 스레드 제한을 넘어 CPU를 더 효율적으로 사용할수있다.
멀티스레드를 사용하면 독립적인 실행환경을 갖추게되는데 이는 V8엔진의 인스턴스 , 이벤트루프, 로컬 스토리지를 갖는다는 의미이다.
이렇게 생성된 워커 는 메인스레드와 데이터를 교환할수잇으며 postMessage() 와 message 이벤트를 통해 이뤄진다.


const { Worker, isMainThread, parentPort } = require("worker\_threads");

if (isMainThread) {


// 메인 스레드에서 실행되는 코드

const worker = new Worker(__filename);

worker.on("message", (message) =>

    console.log(`Received from worker: ${message}`)

);

worker.postMessage("Hello, worker!");


} else {


// 워커 스레드에서 실행되는 코드

parentPort.on("message", (message) => {

    console.log(`Received from main: ${message}`);

    parentPort.postMessage(message.toUpperCase());


});

}

new Worker() 를 사용하여 새로운 워커 스레드를 생성합니다.
worker.postMessage() 메서드로 워커에 메시지를 보내고
worker.on('message', ...) 를 사용하여 워커로부터 메시지를 받습니다.
worker.terminate() 메서드를 통해 종료할 수 있습니다.

child_process

fs

파일시스템 에 접근하는 모듈
파일,폴더 생성 삭제 읽기 쓰기 기능을 지원하고

버퍼와 스트림

버퍼

데이터를 일정한 크기로 모아두고 모아둔데이터를 한번에 처리
즉 데이터전체가 메모리에 저장될때까지 기다린후 처리를 시작한다.


const buffer = Buffer.from("버퍼로 바꿔보세요");

console.log(buffer);

console.log(buffer.length);

console.log(buffer.toString());

const array = \[


Buffer.from("띄엄 "),

Buffer.from("띄엄 "),

Buffer.from("띄어쓰기 "),


\];

console.log(Buffer.concat(array).toString());

console.log(Buffer.alloc(5));

스트림

데이터의 연속적인 흐름을 다루는 객체다
작은데이터 조각 (Chunk) 으로 나누어서 데이터를 계속 처리하는것

데이터를 작게 나눠서 처리하기때문에 서버 메모리 효율이 좋다
Stream 모듈을 사용해서 스트림의 읽기 쓰기 수정 같은 기능을 사용할수있다.
이벤트 기반으로 작동되기에 data 이벤트를 발생시킨다


const fs = require("fs");

const readStream = fs.createReadStream("./readme3.text", { highWaterMark: 6 });

// 기본값은 64kb 이기에 그보다 작게 나눌려면 highWaterMark 를 사용하면된다.  
const data = \[\];

// 읽기  
readStream.on("data", (chunk) => {


data.push(chunk);

console.log("data", chunk, chunk.length);


});

readStream.on("end", () => {


console.log("end", Buffer.concat(data).toString());


});

readStream.on("error", (err) => {

console.log("error", err);


});


// 작성하기 


const writeStream = fs.createWriteStream('./writeme2.txt');

writeStream.on('finish', () => {

console.log('파일쓰기 완료');

});

writeStream.write('글작성중입니다 \\n');

writeStream.write('두번째 글작성입니다. \\n');

writeStream.end();

여기서 readStream.on () 메소드를 사용해서 하는데
on()메소드는 특정 이벤트가 발생했을때 실행될 콜백함수를 등록하는데 사용된다.
아래와 같은 특정이벤트가 발생되면 실행될 콜백함수를 사용하는것이다 .

1. data

  • 스트림에서 새로운 데이터 조각이 사용 가능할 때마다 발생합니다.
  • 이 이벤트의 콜백 함수는 읽은 데이터 조각을 인자로 받습니다.

2. end

  • 스트림에서 더 이상 읽을 데이터가 없을 때 발생합니다.
  • 이 이벤트는 스트림의 끝을 나타냅니다.

3. error

  • 스트림에서 오류가 발생했을 때 발생합니다.
  • 오류 정보를 포함하는 이벤트 객체를 받습니다.

4. close

  • 스트림이 닫혔을 때 발생합니다.
  • 파일 시스템 스트림에서 주로 사용됩니다.

스레드풀

기본적으로 노드는 스레드를 4개사용한다.
자신의 cpu 갯수가 더많아서 스레드를 더 사용하고싶다면 UV_THREADPOOL_SIZE 를 조정해서 스레드폴을 확장시킬수있다.

예외처리

예외처리하지못한 에러가 발생하면 노드가 멈추기때문에 예외처리는 필수로 해야한다.
콜백함수에서 에러를 담고있다면 거기서 예외처리하면된다.
Promise 에는 catch 를 꼭 붙이자 -> 높은 노드에서는 노드를 강제종료할수있다

try catch

process.on('uncaughtException' , (err) => {})

다른쪽에서 에러가 발생해도 해당 구문을 통해 에러가 출력이된다.
단순 에러 기록용으로 사용된다.
노드 에서 이 콜백함수의 동작을 모두 보장하지않기때문에 에러를 복구하기위한 코드를 작성하는건 안된다.

프로세스 종료

윈도우


netstat -ano | findstr 포트  
taskkill /pid 프로세스아이디 /f

맥 / 리눅스


lsof -i tcp:포트  
kill -9 프로세스아이디

프로세스 아이디 알아내는법

```

process.pid

반응형

'백엔드 > Nodejs' 카테고리의 다른 글

섹션4 npm  (0) 2023.12.15
섹션3 노드 기본  (0) 2023.12.15
섹션1 알아두어야할 자바스크립트  (0) 2023.12.09
Nodejs ?  (1) 2023.12.06