본문 바로가기

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

[2024 Node.js 스터디] 조상혁 4주차 "Node.js 3장부터 5장까지"

반응형


이전에 백엔드를 한번 해보고 웹클라이언트 과제를 할 때도 node.js를 사용했지만 사실 그렇게 공부해본적은 없는 것 같다. 이번 기회에 node.js가 어떤건지 알고 잘 사용할 수 있도록 노력해야겠다.

 

3장 노드의 기능 

- 알면 좋은 것

 

js는 기본적으로 인터프리터 언어이기에 보통 컴파일 하지 않아도 실행이가능하다. 웹같이 동적으로 움직이는 사이트에는 가벼운 언어가 적합했기 때문이다. 하지만 웹도 발전하면서 무거운 사이트도 생겼다. 예를들면 지도가 같은 사이트가 있는데 지도같은 꽤나 무거운 작업들을 위해서 컴파일러의 존재가 필요하다고 생각한것 같다. 그래서 생긴 컴파일러가 V8엔진 node.js에서 사용하는 컴파일러 이다.

 

 

 

 

- REPL  

읽고, 해석하고, 결과물을 반환하고, 종료할 때까지 반복한다의 줄임말이자 앞말 그대로 실행하는 환경

터미널에 node 를 입력하면 사용가능하며 웹에서 개발자도구를 열면 나오는 콘솔과 같다.

 

 

따로 파일을 만들어 실행하는 것도 가능하다.

 

 

 

- 모듈

모듈이란 함수나 변수들의 집합을 말한다.

+ 위와같은 정의를 보면 class와 유사하다고 생각이 드는데 모듈은 클래스와 달리 상속을 통한 인스턴스화, 인터페이스 구현이 불가능하다.

 

노드는 모듈을 만들 수 있음이 JS와의 차별점 이라고 할 수 있다. 또한 보통 모듈을 하나의 파일에 관리하기 때문에 파일별로 모듈화할 수 있어 관리에 용이하다.

모듈 설명과 프로그램

 

CommonJs

 

nodeJs 에서 js 패키지를 불러올 때 사용하는 방식이다.

 

불릴 수 있도록 하는 방법 :exports

불러오는 방법 : require 

 

 

만약 에이,비가 exports 되지 않았더라면?

 

참조할 수 없게 되며 undefind 가 나타남을 볼 수 있다.

 

exports 주의사항



module.exports에는 어떤 값이든 대입해도 되지만, exports에는 반드시 객체처럼 속성명과 속성값을 대입해야 한다. exports에 다른 값을 대입하면 객체의 참조 관계가 끊겨 더는 모듈로 기능하지 않는다.

//test1.js

const test = {
	name: "cho",
}

exports = test; // 잘못된 예시 , 
exports.person = test;

//main.js

const user = require('./test1');

console.log(user.person);

 

[Node.JS] module.export 와 exports의 차이

 

 

require 주의사항

 

모듈이 서로 의존성을 갖고 서로를 참조하는 상황이 발생할 수 있는데 이를 순환참조라고 한다.

nodeJs는 순환참조시에 하나를 빈객체로 만들어버리니 주의!!

순환참조가 필요할 경우에는 평가순서를 만들어 주면 된다. 모듈의 순서를 정의하는 파일을 만들고 가져오면 해결

참조순환

 

ECMAScript 모듈

 

require로 파일을 불러왔듯이 import를 통해서 파일을 불러오는 방식이다.

 

CommonJs 에 require 가 있는데 이건 왜 필요한가?

 

CommonJs의 문제

  •    CommonJs 는 언어 표준이 아니기에 node.js를 지원하고. CommonJs 모듈을 시스템을 지원하는 환경에서만 사용가능
  • 정적 분석의 어려움 : require는 함수이기에 변수에 저장했다가 쓰는 것이 가능하다. 이런 동작은 코드참조 분석에 어려움을 만들고 실제 사용 코드만 포함하는 Tree shaking 같은 작업을 불편하게 만든다.
  • CommonJs는 동기적으로 동작하기 때문에 비동기 모듈을 정의하기 힘들다.

위와 같은 문제들을 해결하기 위해 등장한 것이 ECMAScript(ES) 이다.

 

 

 

다이나믹 임포트 

 

이름 그대로 동적으로 파일을 불러오는 작업이다.

exports 된 모듈을 조건문을 사용해서 불러온다.

 

import 로도 동적 불러오기가 가능한데 Promise를 반환하기 때문에 앞에  await이나 then을 붙여야 가능!!

 

내장 객체

global : window와 같은 전역 객체이다. 남용하면 코드의 유지보수성을 해친다.

console : global 객체 안에 있으며 보통 디버깅을 위해 사용한다.

콘솔 함수 종류

 

타이머 : 타이머 기능을 제공하는 함수

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

process : 현재 실행중인 노드 프로세스

 -  보통 운영체제나 환경별로 다른동작이 필요할 떄 사용된다.

process.env : 시스템 환경변수이다.

process.nextTick(콜백) : 이벤트 루프가 다른 콜백 함수들보다 nextTick의 콜백 함수를 우선으로 처리하도록 한다.

// process.nextTick setImmediate setTimeout보다 먼저 실행

 

내장 모듈

  • os
    • 내장객체이나 require('os')  ,  require('node:os') 로 불러올 수 있다.
    • 운영체제의 정보와 경로,cpu정보,메모리정보를 얻을 수 있다.
  • path
    • 폴더와 파일의 경로의 조작을 도와주는 모듈
    • 파일 경로에서 파일의 확장자나 파일명만 가져올 수도 있다.
  • url
    • 인터넷 주소를 조작하도록 돕는 모듈
  • dns
    • 도메인을 통해 IP나 DNS의 정보를 얻고자 할 때 사용
  • crypto
    • 암호화를 도와주는 모듈
    • 암호화 함수이나 단방향 암호화이기에 복호화할 수 없 해시 함수라고도 불린다.
  • util
    • 편의 기능들을 모아둔 모듈
    • util.deprecate: 조만간 사라지는 함수인 경우 사용 ,  첫 번째 인수로 넣은 함수를 사용했을 때 경고 메시지가 출력
    • util.promisify: 콜백 패턴을 프로미스 패턴으로 변
  • worker_threads
    • 멀티 쓰레드로 작업하기 위한 모듈
    • 어렵고 코드양이 많이질 수 있으며 무조건적으로 효율이 좋진 않지만 실행속도를 줄일 수 있다.
  • child_process
    • 노드에서 다른프로그램의 실행을 할 수 있게 해주는 모듈

이외 모듈

 

 

 

 

 

파일 시스템

저를 읽어주세요.
const fs = require('fs');

 

위 코드를 통해 불러오며 readFile 함수를 통해서 경로를 지정

 

fs.readFile('./readme.txt', (err, data) => {
  if (err) {
    throw err;
  }
  console.log(data);
  console.log(data.toString());
});

 

$ node readFile
<Buffer ec a0 80 eb a5 bc 20 ec 9d bd ec 96 b4 ec a3 bc ec 84 b8 ec 9a 94 2e>
저를 읽어주세요.

 

readFile 은 파일 읽기 요청만 보내는 것이기 때문에 바로 처리 되지 않는다.

readFileSync 는 return을 받아오기에 바로 처리한다.

 

 

버퍼와 스트림

 

버퍼 : 파일을 읽을 때 파일크기만큼의 공간을 마련하는데 이때 메모리에 저장되는 데이터를 말한다.

스트림 : 버퍼를 좀 더 작게 나누어 편하게 전송할 수 있도록 한 것

 

버퍼메소드

  • from(문자열): 문자열을 버퍼로 바꿀 수 있습니다. length 속성은 버퍼의 크기를 알립니다. 바이트 단위입니다.
  • toString(버퍼): 버퍼를 다시 문자열로 바꿀 수 있습니다. 이때 base64나 hex를 인수로 넣으면 해당 인코딩으로도 변환 가능합니다.
  • concat(배열): 배열 안에 든 버퍼들을 하나로 합칩니다.
  • alloc(바이트): 빈 버퍼를 생성합니다. 바이트를 인수로 넣으면 해당 크기의 버퍼가 생성됩니다.

 

 

스레드 풀

  • 시스템의 성능저하를 막기위해서 사용된다.
  • 작업처리에 사용되는 스레드를 제한된 개수만큼 정해놓고 작업큐에 들어오는 작업들을 하나씩 처리하는 것이다.
  • 스레드풀은 직접 컨트롤 할 수는 없지만 , 개수는 조절 할 수 있다.

 

이벤트

이벤트 리스닝

  •  on(이벤트명, 콜백)
  • once(이벤트명, 콜백)
  •  addListener(이벤트명, 콜백)

이벤트 실행

  • emit(이벤트명)

이벤트 제거 

  • removeAllListeners(이벤트명)
  • removeListener(이벤트명, 리스너)
  • off(이벤트명, 콜백)

이벤트 확인

  • listenerCount(이벤트명)

예외처리

서버가 멈추는 일은 발생해선 안되기 때문에 매우 중요하다.

try/catch를 통해 일부에서 오류가 발생해도 멈추기않고 동작할 수 있다.

uncaughtException 의 대부분의 에러를 처리할 수 있는 것 같지만 다음 코드가 동작하지 않을 가능성을 내포하고 있다.

 

 


4장 http 모듈로 서버 만들기

서버 동작해보기

 

http 모듈을 써야하니 불러옵니다.

const http = require('http');

createServer  메서드 뒤에 listen 메서드를 붙이고 클라이언트에 공개할 포트 번호와 포트 연결 완료 후 실행될 콜백 함수

http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  res.write('<h1>Hello Node!</h1>');
  res.end('<p>Hello Server!</p>');
})
  .listen(8080, () => { // 서버 연결
    console.log('8080번 포트에서 서버 대기 중입니다!');
  });

서버가 성공적으로 동작

+ 포트만 같지 않다면 한번에 여러개의 서버를 열 수도 있다.

 

소스코드 변경

 

 

변경사항이 생길때마다 재실행이 번거롭기 때문에 재실행 해주는 nodemon 이라는 npm 라이브러리를 쓰면 편하다.

 

res 객체

 

res 객체는 res.writeHead res.write, res.end 메서드가 존재한다.

writeHead : 상태코드

write : 데이터 형식

end : 보내는 데이터

네트워크에서 확인할 수 있다.

 

http 상태코드

  • 2XX : 성공을 알리는 상태코드
  • 3XX : 리다이렉션 ( 페이지 이동 ) 을 나타내는 코드
  • 4XX : 요청오류
  • 5XX : 서버오류

REST와 라우팅

 

- REST는 REpresentational State Transfer의 줄임말로, 서버의 자원을 정의하고 자원에 대한 주소를 지정하는 방법

구체적 개념 : http 매소드들을 통해 해당 자원에 대한 CRUD Operation을 적용하는 것

CRUD Operation
Create : 생성(POST)
Read : 조회(GET)
Update : 수정(PUT)
Delete : 삭제(DELETE)
HEAD: header 정보 조회(HEAD)

출처: https://hahahoho5915.tistory.com/54 [넌 잘하고 있어:티스토리]

 

 - 라우팅이란 어떤 네트워크 내에서 통신 데이터를 보낼 경로를 선택하는 일련의 과정

웹 클라이언트 과제중 사용했던 api

쿠키와 세션

 

쿠키 

 

  • HTTP의 일종으로 사용자가 어떤 웹 사이트를 방문할 경우, 해당 사이트가 사용하고 있는 서버에서 사용자의 컴퓨터에 저장하는 작은 기록 정보 파일이다.
  • HTTP에서 클라이언트의 상태정보를 쿠키 형태로 클라이언트 PC에 저장하였다가 필요 시 정보를 참조하거나 재사용할 수 있다.
  • Key-Value쌍으로 구성되어 있는 데이터 파일이다.
  • 쿠키이름, 쿠키값, 만료시간, 전송할 도메인명, 전송할 경로, 보안연결여부, HttpOnly여부로 구성되어 있다.
  • 도메인 당 20개의 쿠키를 가질 수 있다.
  • 하나의 쿠키는 4KB(= 4096 byte)까지 저장이 가능하다.

 

세션

 

  • 브라우저가 종료되기 전까지 클라이언트의 요청을 유지하게 해주는 기술을 세션이라고 한다.
  • 웹 서버에 웹 컨테이너의 상태를 유지하기 위한 정보를 저장한다.
  • 웹 서버에 저장되는 쿠키(세션 쿠키 / session cookie)이다.
  • 브라우저를 닫거나, 서버에서 세션을 삭제했을 때만 삭제가 되기 때문에 쿠키보다 비교적 보안적으로 우수하다.
    저장 데이터에 제한이 없다.(서버 용량 허용 범위 내에서)
  • 각 클라이언트에 고유 세션 ID(Session ID)를 부여한다. 세션 ID를 통해 클라이언트를 구분하여 각 요구에 맞는 서비스를 제공한다.

 

https 와 http2

 

https://blog.naver.com/skinfosec2000/222135874222

 

https는 http + security 로 보안을 강화한 것이다. 보안을 위하여 암호화를 추가하는데 사용을 위해서는 인증서를 인증기관에서 구매해야 한다.

아래는 https 서버인데 기존과의 차이는 createServer( cert, key, ca ) 인증옵션 객체와 서버로직 2가지를 인수로 받는다.

 

+ http2 모듈은 SSL 암호화와 더불어 최신 프로토콜인 http/2를 이용할 수 있다.

const https = require('https');
const fs = require('fs');

https.createServer({
  cert: fs.readFileSync('도메인 인증서 경로'),
  key: fs.readFileSync('도메인 비밀 키 경로'),
  ca: [
    fs.readFileSync('상위 인증서 경로'),
    fs.readFileSync('상위 인증서 경로'),
  ],
}, (req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  res.write('<h1>Hello Node!</h1>');
  res.end('<p>Hello Server!</p>');
})
  .listen(443, () => {
    console.log('443번 포트에서 서버 대기 중입니다!');
  });

 

 

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

cpu가 멀티 코어일 경우 하나만 사용하는 것은 재대로 활용하지 못하고 있는 것이기에 이를 도와주는 모듈이다.

 

  • 기본적으로 싱글 스레드인 노드가 CPU 코어를 모두 사용할 수 있게 해주는 모듈
  • 포트를 공유하는 노드 프로세스를 여러 개 둘 수 있음
  • 요청이 많이 들어왔을 때 병렬로 실행된 서버의 개수만큼 요청이 분산됨
  • 서버에 무리가 덜 감
  • 코어가 8개인 서버가 있을 때: 보통은 코어 하나만 활용
  • cluster로 코어 하나당 노드 프로세스 하나를 배정 가능
  • 성능이 8배가 되는 것은 아니지만 개선됨

단점: 컴퓨터 자원(메모리, 세션 등) 공유 못 함. 각각 독립적인 프로세스를 띄우는거라, 서로 공유가 안됨.
-> Redis 등 별도 서버로 해결

출처: https://inpa.tistory.com/entry/NODE-📚-cluster-모듈-코어를-추가로-사용 [Inpa Dev 👨‍💻:티스토리]

 


 

5장 패키지 매니저

NPM : Node Package Manager의 약어로, 이름 그대로 노드 패키지 매니저를 의미합니다.

+ 추가적으로 yarn,pnpm 이 있습니다. 

 

!! 주의사항 !!

다른 패키지 매니저를 혼용해서 사용하는 경우에는 오류가 발생할 확률이 있다.

함께 프로젝트를 진행한다면 패키지 매니저를 통일하는 것이 좋은 방법

 

package.json : 지금까지 다운한 패키지들의 로그

package-lock.json : 패키지 간의 의존 관계를 명시한 파일

node_modules :

 Express가 의존하는 패키지. 패키지 하나가 다른 여러 패키지에 의존하고, 그 패키지들은 또 다른 패키지들에 의존 관계가 복잡하게 얽혀 있어 package.json이 필요하다.

 

npm 시작하기

npm init

 

 

라이선스 - 오픈 소스라고 해서 모든 패키지를 아무런 제약 없이 사용할 수 있는 것은 아니다. 라이선스(license)별로 제한 사항이 있으므로 설치 전에 반드시 라이선스를 확인해야 한다.

 

최신버전 다운받기

npm i express@latest 또는 npm i express@x 를 사용하면 안정된 최신버전을 다운할 수 있다.

 

기타 npm 명령어

  • npm outdated // 업데이트 패키지 확인
  • npm uninstall [패키지 이름] // 패키지 제거
  • npm search [검색어] // 패키지 검색
  • npm info [패키지 이름] // 패키지 세부정보 파악
  • npm login // npm 에 로그인 ( 패키지 배포시에 필요 )
  • npm whoami // 로그인유저 확인
  • npm version [버전] // package.json의 버전 업그래이드
  • npm publish 패키지 배포

 

후기 

node.js 생각보다 모듈이 너무 많다 이거 다 적으면 백과사전 일듯..

반응형