본문 바로가기

WINK-(Web & App)/Express.js (Node.js) 스터디

[2024 Node.js 스터디] 김민서 4주차

반응형
REPL

Read Eval Print Loop

콘솔에 node 입력 후 자바스크립트 코드 입력

입력한 코드를 읽고, 해석하고, 결과물을 반환하고, 종료할 때까지 반복함

여러 줄의 코드를 실행하기에는 불편함

 

JS 파일 실행하기

자바스크리브 파일을 만든 후 콘솔에서 node [자바스크립트 파일 경로]로 실행

확장자 생략 가능

 

모듈

모듈 - 특정한 기능을 하는 함수나 변수들의 집합

 

1. CommonJS 모듈

모듈이 될 파일과 모듈을 불러와서 사용할 파일이 필요함

// var.js 파일 (모듈로서 기능)
const odd = 'CJS 홀수';
const even = 'CJS 짝수';
module.exports = {
  odd,
  even,
};
// func.js 파일
const { odd, even } = require ('./var');

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

module.exports = checkOddOrEven;
// index.js 파일
const { odd, even } = require('./var');
const chenckNumber = require('./func');

function checkStringOddOrEven(str) {
  if (str.length % 2) {
    return odd;
  }
  return even;
}
console.log(checkNumber(10));
console.log(checkStringOddEven('hello'));

- 재사용되는 함수나 변수를 모듈로 만들어두면 편리함

- 모듈이 많아지고 관계가 얽히게 되면 구조를 파악하기 힘듦

- 노드에서는 대부분의 파일이 다른 파일을 모듈로 사용하고 있음

 

* require

- 모듈을 불러오는 함수

- 최상단에 위치할 필요가 없음(아무 곳에서나 사용 가능)

- 한번 require 하면 다음 번에 require 할 때는 새로 불러오지 않으며, require.cache에 있는 것이 재사용된다

 

* 순환 참조- 순환 참조되는 대상을 빈 객체로 만듦

 

2. ECMAScript 모듈

- 공식적인 자바스크립트 모듈 형식

// 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 checkOddEven;​
// index.mjs 파일
import { odd, even } from './var/mjs';
import checkNumber from './func.mjs';

function checkStringOddOrEven(str) {
  if (str.length % 2) {
    return odd;
  }
  return even;
}

console.log(checkNumber(10));
console.log(checkStringOddOrEven('hello'));

ES 모듈의 import, export default 는 문법 그 자체이다

 

3. 다이내믹 임포트

조건부로 모듈을 불러오는 것

ES 모듈은 if문 안에서 import 하는 것이 불가능해 이럴 때 다이내믹 임포트를 사용함

// dynamic.mjs 파일
const a = true;
if (a) {
  const m1 = await import('./func.mjs');
  console.log(m1);
  const m2 = await import('./var.mjs');
  console.log(m2);
}
$ node dynamic.mjs

import는 Promise를 반환해 await이나 then을 붙여야한다

 

4. __filename, __dirname

- __filename, __dirname 으로 경로에 대한 정보 제공

- 파일에 __filename, __dirname을 넣어두면 실행 시 현재 파일명과 현재 파일 경로로 바뀜

- ES 모듈에서는 사용할 수 없음, 대신 import.meta.url로 경로를 가져옴

 

노드 내장 객체

1. global

- 전역 객체

- 생략 가능

// globalA.js 파일
module.exports = () => global.message;
// globalB.js 파일
const A = require('./globalA');

global.message = '안녕하세용';
console.log(A());

globalB에서 넣은 global.message 값을 globalA에서도 접근 가능

 

2. console

디버깅을 위해 사용

  • console.time(레이블) : console.timeEnd(레이블)과 대응되어 같은 레이블을 가진 time과 timeEnd 사이의 시간을 측정
  • console.log(내용) :  평범한 로그를 콘솔에 표시
  • console.error(에러 내용) : 에러를 콘솔에 표시
  • console.table(배열) : 객체의 속성들이 테이블 형식으로 표현
  • console.dir(객체, 옵션) : 객체를 콘솔에 표시할 때 사용
  • console.trace(레이블) : 에러가 어디서 발생했는지 추적

3. 타이머

  • setTimeout(콜백 함수, 밀리초) : 주어진 밀리초 이후에 콜백 함수를 실행
  • setInterval(콜백 함수, 밀리초) : 주어진 밀리초마다 콜백 함수를 반복 실행
  • setImmediate(콜백 함수) : 콜백 함수를 직시 실행
  • clearTimeout(아이디): setTimeout을 취소
  • clearInterval(아이디) : setInterval을 취소
  • clearImmediate(아이디) : setImmediate를 취소

4. process

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

  • process.version : 설치된 노드의 버전
  • process.arch : 프로세스 아키텍처 정보
  • process.platform : 운영체제 플랫폼 정보
  • process.pid : 현재 프로세스의 아이디
  • process.uptime() : 프로세스가 시작된 후 흐른 시간
  • process.execPath : 노드의 경로
  • process.cwd() : 현재 프로세스가 실행되는 위치
  • process.cpuUsage() : 현재 cpu 사용량

5. process.env

서비스의 중요한 키를 저장하는 공간으로 사용

 

6. process.nextTick

이벤트 루프가 다른 콜백 함수들보다 nextTick의 콜백 함수를 우선으로 처리하도록 만듦

 

7. process.exit

실행 중인 노드 프로세스를 종료

특수한 경우를 제외하고는 서버에서 잘 사용하지 않음

서버 외의 독립적인 프로그램에서 수동으로 노드를 멈추기 위해 사용

 

8. 기타 내장 객체

  • URL, URLSearchParams
  • AbortController, FormData, fetch, Headers, Request, Response, Event, EventTarget
  • TextDecoder
  • TextEncoder
  • WebAssembly

 

노드 내장 모듈 사용하기

운영체제 정보 접근, 클라이언트가 요청한 주소에 대한 정보 접근의 기능을 하는 모듈을 제공

노드의 모듈은 버전마다 차이가 있음

 

1. OS

os 모듈에 운영체제의 정보가 담겨 있어 가져올 수 있음

require('os') 또는 require('node:os') 로 내장 모듈 os를 불러옴

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

2. path

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

운영체제별로 경로 구분자가 달라 이 모듈이 필요

  • path.sep: 경로의 구분자, 윈도는 \이고, POSIX는 /
  • path.delimiter: 환경 변수의 구분자, 윈도는 세미콜론(;)이고, POSIX는 콜론(:)
  • path.dirname(경로): 파일이 위치한 폴더 경로를 보여줌
  • path.extname(경로): 파일의 확장자를 보여줌
  • path.basename(경로, 확장자): 파일의 이름(확장자 포함)을 표시, 파일의 이름만 표시하고 싶으면 basename의 두 번째 인수로 파일의 확장자를 넣기
  • path.parse(경로): 파일 경로를 root, dir, base, ext, name으로 분리
  • path.format(객체): path.parse()한 객체를 파일 경로로 합침
  • path.normalize(경로): /나 \를 실수로 여러 번 사용했거나 혼용했을 때 정상적인 경로로 변환
  • path.isAbsolute(경로): 파일의 경로가 절대경로인지 상대경로인지를 true false로 알림
  • path.relative(기준경로, 비교경로): 경로를 두 개 넣으면 첫 번째 경로에서 두 번째 경로로 가는 방법을 알림
  • path.join(경로, …): 여러 인수를 넣으면 하나의 경로로 합침
  • path.resolve(경로, …): path.join()과 비슷하지만 차이가 있다

3. url

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

  • url.format(객체): 분해되었던 url 객체를 다시 원래 상태로 조립
  • getAll(키): 키에 해당하는 모든 값을 가져옴
  • get(키): 키에 해당하는 첫 번째 값만 가져옴
  • has(키): 해당 키가 있는지 없는지를 검사
  • keys(): searchParams의 모든 키를 반복기(iterator)(ES2015 문법) 객체로 가져옴
  • values(): searchParams의 모든 값을 반복기 객체로 가져옴
  • append(키, 값): 해당 키를 추가, 같은 키의 값이 있다면 유지하고 하나 더 추가
  • set(키, 값): append와 비슷하지만 같은 키의 값들을 모두 지우고 새로 추가
  • delete(키): 해당 키를 제거
  • toString(): 조작한 searchParams 객체를 다시 문자열로 만듦. 이 문자열을 search에 대입하면 주소 객체에 반영

4.dns

DNS를 다룰 때 사용하는 모듈

주로 도메인을 통해 IP나 기타 DNS 정보를 얻고자 할 때 사용

dns.lookup이나 dns.resolve(도메인)으로 ip 주소를 얻을 수 있음

 

5. crypto

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

   

    (1) 단방향 암호화 - 복호화(암호화된 문자열을 원래 문자열로 되돌려놓는 것) 할 수 없는 암호화 방식

  • createHash(알고리즘): 사용할 해시 알고리즘을 넣음
  • update(문자열): 변환할 문자열을 넣음
  • digest(인코딩): 인코딩할 알고리즘을 넣음, 결과물로 변환된 문자열을 반환

    (2) 양방향 암호화 - 암호화된 문장열을 복호화할 수 있으며 키라는 것이 사용됨

  • crypto.createCipheriv(알고리즘, 키, iv): 암호화 알고리즘과 키, iv를 넣음
  • cipher.update(문자열, 인코딩, 출력 인코딩): 암호화할 대상과 대상의 인코딩, 출력 결과물의 인코딩을 넣음
  • cipher.final(출력 인코딩): 출력 결과물의 인코딩을 넣으면 암호화가 완료
  • crypto.createDecipheriv(알고리즘, 키, iv): 복호화할 때 사용, 암호화할 때 사용했던 알고리즘과 키, iv를 그대로 넣기
  • decipher.update(문자열, 인코딩, 출력 인코딩): 암호화된 문장, 그 문장의 인코딩, 복호화할 인코딩을 넣음
  • decipher.final(출력 인코딩): 복호화 결과물의 인코딩을 넣음

6. util

각종 편의 기능을 모아둔 모듈

계속해서 API가 추가되며 사라지는 경우도 있음

  • util.deprecate: 함수가 deprecated 처리되었음을 알림. 첫 번째 인수로 넣은 함수를 사용했을 때 경고 메시지가 출력, 두 번째 인수로 경고 메시지 내용을 넣기
  • util.promisify: 콜백 패턴을 프로미스 패턴으로 바꿈. 바꿀 함수를 인수로 제공하기    

7. worker_threads

- 멀티 스레드 방식으로 작업 가능

- isMainThread로 현재 코드가 메인 스레드나 워커 스레드에서 실행되는지 구분

- 워커에서 on 메서드를 사용할 때는 직접 워커를 종료해야 한다

 

8. child_process

노드에서 다른 프로그램을 실행하고 싶거나 명령어를 수행하고 싶을 때 사용

다른 언어의 코드를 실행하고 결괏값을 받을 수 있다

 

9. 기타 모듈들

  • async_hooks: 비동기 코드의 흐름을 추적할 수 있는 실험적인 모듈
  • dgram: UDP와 관련된 작업을 할 때 사용
  • net: TCP나 IPC 통신을 할 때 사용
  • perf_hooks: 성능 측정을 할 때 console.time보다 더 정교하게 측정
  • querystring: URLSearchParams가 나오기 이전에 쿼리스트링을 다루기 위해 사용했던 모듈
  • string_decoder: 버퍼 데이터를 문자열로 바꾸는 데 사용
  • tls: TLS와 SSL에 관련된 작업을 할 때 사용
  • tty: 터미널과 관련된 작업을 할 때 사용
  • v8: v8 엔진에 직접 접근할 때 사용
  • vm: 가상 머신에 직접 접근할 때 사용
  • wasi: 웹어셈블리를 실행할 때 사용하는 실험적인 모듈

 

파일 시스템 접근하기

fs 모듈로 파일 시스템에 접근 (파일을 생성 또는 삭제, 읽기 또는 쓰기, 폴더 만들기 또는 지우기

1. 동기 메서드와 비동기 메서드

비동기 방식으로 하되 순서를 유지하기 -> readFile의 콜백에 다음 readFile 넣기

 

2. 버퍼와 스트림

버퍼링 : 영상을 재생할 수 있을 때까지 데이터를 모으는 동작

스트리밍 : 방송인의 컴퓨터에서 시청자의 컴퓨터로 영상 데이터를 조금씩 전송하는 동작

 

노드의 버퍼 : 메모리에 저장된 데이터 

  • from(문자열): 문자열을 버퍼로 바꿀 수 있다
  • toString(버퍼): 버퍼를 다시 문자열로 바꿀 수 있다
  • concat(배열): 배열 안에 든 버퍼들을 하나로 합친다
  • alloc(바이트): 빈 버퍼를 생성

노드의 스트림 : 버퍼의 크기를 작게 만들고 여러 번에 걸쳐 나눠 보내는 것을 편리하게 만든 것

 

3. 기타 fs 메서드 

  • fs.access(경로, 옵션, 콜백): 폴더나 파일에 접근할 수 있는지를 체크 / F_OK는 파일 존재 여부, R_OK는 읽기 권한 여부, W_OK는 쓰기 권한 여부를 체크
  • fs.mkdir(경로, 콜백): 폴더를 만드는 메서드
  • fs.open(경로, 옵션, 콜백): 파일의 아이디(fd 변수)를 가져오는 메서드
  • fs.rename(기존 경로, 새 경로, 콜백): 파일의 이름을 바꾸는 메서드
  • fs.readdir(경로, 콜백): 폴더 안의 내용물을 확인할 수 있다
  • fs.unlink(경로, 콜백): 파일을 지울 수 있다
  • fs.rmdir(경로, 콜백): 폴더를 지울 수 있다

 

이벤트 이해하기
  •  on(이벤트명, 콜백): 이벤트 이름과 이벤트 발생 시의 콜백을 연결
  • addListener(이벤트명, 콜백): on과 기능이 같다
  • emit(이벤트명): 이벤트를 호출하는 메서드
  • once(이벤트명, 콜백): 한 번만 실행되는 이벤트
  • removeAllListeners(이벤트명): 이벤트에 연결된 모든 이벤트 리스너를 제거
  • removeListener(이벤트명, 리스너): 이벤트에 연결된 리스너를 하나씩 제거
  • off(이벤트명, 콜백): 노드 10 버전에서 추가된 메서드로, removeListener와 기능이 같다
  • listenerCount(이벤트명): 현재 리스너가 몇 개 연결되어 있는지 확인

 

예외 처리하기

자주 발생하는 에러들

  • node: command not found: 환경 변수가 제대로 설정되어 있지 않은 것
  • ReferenceError: 모듈 is not defined: 모듈을 require했는지 확인
  • Error: Cannot find module 모듈명: 해당 모듈을 require했지만 설치하지 않음 npm i 명령어로 설치하기
  • Error [ERR_MODULE_NOT_FOUND]: 존재하지 않는 모듈을 불러오려 할 때 발생
  • Error: Can't set headers after they are sent: 요청에 대한 응답을 보낼 때 응답을 두 번 이상 보냄
  • FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed- JavaScript heap out of memory: 코드를 실행할 때 메모리가 부족해서 스크립트가 정상적으로 작동하지 않는 경우
  • UnhandledPromiseRejectionWarning: Unhandled promise rejection: 프로미스 사용 시 catch 메서드를 붙이지 않으면 발생
  • EADDRINUSE 포트 번호: 해당 포트 번호에 이미 다른 프로세스가 연결
  • EACCES 또는 EPERM: 노드가 작업을 수행하는 데 권한이 충분하지 않음
  • EJSONPARSE: package.json 등의 JSON 파일에 문법 오류가 있을 때 발생
  • ECONNREFUSED: 요청을 보냈으나 연결이 성립하지 않을 때 발생
  • ETARGET: package.json에 기록한 패키지 버전이 존재하지 않을 때 발생
  • ETIMEOUT: 요청을 보냈으나 응답이 시간 내에 오지 않을 때 발생
  • ENOENT: no such file or directory: 지정한 폴더나 파일이 존재하지 않는 경우

 

요청과 응답 이해하기

- 클라이언트에서 서버로 요청을 보내고, 서버에서는 요청의 내용을 읽고 처리한 뒤 클라이언트에 응답을 보냄

- 요청과 응답은 이벤트 방식이라고 생각하면 된다

- 클라이언트로부터 요청이 왔을 때 어떤 작업을 수행할지 이벤트 리스너를 미리 등록해야함

 

* res.writeHead : 응답에 대한 정보를 기록하는 메서드

* res.end : 메서드의 첫 번째 인수는 클라이언트로 보낼 데이터

 

 

REST와 라우팅 사용하기

REST : 서버의 자원을 정의하고 자원에 대한 주소를 지정하는 방법

  • GET: 서버 자원을 가져오고자 할 때 사용
  • POST: 서버에 자원을 새로 등록하고자 할 때 사용
  • PUT: 서버의 자원을 요청에 들어 있는 자원으로 치환하고자 할 때 사용
  • PATCH: 서버 자원의 일부만 수정하고자 할 때 사용
  • DELETE: 서버의 자원을 삭제하고자 할 때 사용
  • OPTIONS: 요청을 하기 전에 통신 옵션을 설명하기 위해 사용

 

쿠키와 세션 이해하기

쿠키 : 서버가 요청에 대한 응답을 할 때 보내는 것, 유효 기간이 있으며 name=zerocho와 같이 단순한 '키-값'의 쌍, 요청의 헤더에 담겨 전송됨

  • 쿠키명=쿠키값: 기본적인 쿠키의 값, mycookie=test 또는 name=zerocho와 같이 설정
  • Expires=날짜: 만료 기한
  • Max-age=초: Expires와 비슷하지만 날짜 대신 초를 입력가능
  • Domain=도메인명: 쿠키가 전송될 도메인을 특정 가능
  • Path=URL: 쿠키가 전송될 URL을 특정 가능
  • Secure: HTTPS일 경우에만 쿠키가 전송
  • HttpOnly: 설정 시 자바스크립트에서 쿠키에 접근할 수 없음

 

https와 http2

https 모듈은 웹 서버에 SSL 암호화를 추가함

노드의 http2 모듈은 SSL 암호화와 더불어 최신 HTTP 프로토콜인 http/2를 사용할 수 있게 함

 

 

cluster

싱글 프로세스로 동작하는 노드가 CPU 코어를 모두 사용할 수 있게 해주는 모듈

마스터 프로세스와 워커 프로세스가 있다

 

npm

노드 패키지 매니저

패키지가 다른 패키지를 사용할 수 있다 => 의존 관계

 

package.json

설치한 패키지의 버전을 관리하는 파일

노드 프로젝트를 시작하기 전에는 폴더 내부에 무조건 package.json을 만들어야 한다

  • package name: 패키지의 이름
  • version: 패키지의 버전
  • entry point: 자바스크립트 실행 파일 진입점
  • test command: 코드를 테스트할 때 입력할 명령어를 의미
  • git repository: 코드를 저장해둔 깃(Git) 저장소 주소를 의미
  • keywords: 키워드는 npm 공식 홈페이지(https://npmjs.com)에서 패키지를 쉽게 찾을 수 있게 한다
  • license: 해당 패키지의 라이선스를 넣기

 

패키지 버전

노드 패키지들의 버전은 항상 세 자리로 이루어져있다 -> SemVer 방식의 버전 넘버링을 따르기 때문

- 첫 번째 자리 : 메이저 버전

- 두 번째 자리 : 마이너 버전

- 세 번째 자리 : 패치 버전

새 버전 배포 후 버전 내용 수정 금지

버전만 보고 에러 발생 여부 가늠 가능

 

 

npm 명령어
  • npm uninstall [패키지 이름] : 해당 패키지를 제거하는 명령어
  • npm search [검색어] : npm의 패키지를 검색가능
  • npm info [패키지 이름] : 패키지의 세부 정보를 파악하고자 할 때 사용하는 명령어
  • npm login : npm 로그인을 위한 명령어
  • npm whoami : 로그인한 사용자가 누구인지 알림
  • npm logout : npm login으로 로그인한 계정을 로그아웃할 때 사용
  • npm version [버전] : package.json의 버전을 올림
  • npm deprecate [패키지 이름] [버전] [메시지] : 해당 패키지를 설치할 때 경고 메시지를 띄우게 하는 명령어
  • npm publish : 자신이 만든 패키지를 배포할 때 사용
  • npm unpublish : 배포한 패키지를 제거할 때 사용
반응형