웹 개발/node.js

Node.js(2)

SolartheNomad 2023. 4. 12. 17:26

 

http 모듈

 

http.createServer

- 서버의 응답내용을 지정해준다. 

- 매개변수로 request, response를 가지고 있는데 request를 줄여 req라 표현하고, response를 줄여 res라 표현해준다. 

 

createServer.js

const http = require('http');

http.createServer((req, res) => {
  // 여기에 어떻게 응답할지 적어줍니다
});

 

 

server1.js

const http = require('http');

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번 포트에서 서버 대기 중입니다!');
});

 

listen 메서드

 .listen(포트번호, () => { 
    함수이름
});

 

- 위에서 res.write로 출력하는(응답하는) 동작이 성공적으로 실행되었을 때 서버 연결을 해주는 메서드

- 클라이언트에 공개할 포트 번호와 포트 연결 완료 후 실행될 콜백 함수를 넣는다. 

- http.createServer().listen(포트 이름, 실행할 함수)

- 8080 포트에서 요청이 오길 기다리게 됨 

 

res.writeHead

res.writeHead(성공적인 요청/실패한 요청 등등의요청번호, { 'Content-Type': 'text/html; charset=utf-8'//요청에대한 정보 즉 헤더 });

- 응답에 대한 정보를 기록하는 메서드

 

 

 

res.write

- 서버에서 클라이언트로 응답을 보낼 때 body에  데이터를 담아서 보냄 

res.write('클라이언트로 보낼 데이터');

 

res.end

- 서버의 응답을 종류하는 메서드

res.end('클라이언트로 보낼 데이터');

 

 

통신 과정 

 

server1-1.js

const http = require('http');

const server = http.createServer((req, res) => {  
 //server = http.createServer(()) =>{}) 로, 변수에 응답을 담는다. 
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  res.write('<h1>Hello Node!</h1>');
  res.end('<p>Hello Server!</p>');
});
server.listen(8080);

server.on('listening', () => {  //정상적으로 서버와 클라이언트가 연결되었을 떄 
  console.log('8080번 포트에서 서버 대기 중입니다!');
});
server.on('error', (error) => {   //에러 메세지와 에러 출력시의 case
  console.error(error);
});

 

서버를 여러개 띄어보기 

server1-2.js

const http = require('http');

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번 포트에서 서버 대기 중입니다!');
  });

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(8081, () => { // 서버 연결
    console.log('8081번 포트에서 서버 대기 중입니다!');
  });

 

 

fs 모듈

res.write res.end에 일일이 HTML을 적는 것은 비효율적이므로 미리 HTML 파일을 만들어놓고, fs가 데이터를 읽어드린다. 

 

server2.html 

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Node.js 웹 서버</title>
</head>
<body>
    <h1>Node.js 웹 서버</h1>
    <p>만들 준비되셨나요?</p>
</body>
</html>

 

 

 

server2.js

const http = require('http');
const fs = require('fs').promises;  //fs 모듈을 사용하는데, async-await 비동기적 함수를 동기적으로 사용할 수 있게 해준다. 

http.createServer(async (req, res) => {
  try {
    const data = await fs.readFile('./server2.html'); // 요청이 들어오면 fs 모듈로 HTML 파일을 읽어 data 변수에 저장한다.
    res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
    res.end(data);  //실행이 정상적으로 될 때 ,res.end나 res.write에 실행하고자 하느 데이터를 담는다. 
  } catch (err) {  //실행이 정상적으로 되지 않을 때
    console.error(err);
    res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });
    res.end(err.message); //  예기치 못한 에러가 발생한 경우에는 에러 메시지를 응답
  }
})
  .listen(8081, () => {
    console.log('8081번 포트에서 서버 대기 중입니다!');
  });

 

라우팅

- 요청별로 다른 응답을 할 수 있도록 하는 것 

- css나 js 또는 이미지 같은 파일을 요청할 수도 있고 특정 동작을 행하는 것을 요청할 수 있다는 것을 명심해야함 (.html 형식만 요청하는게 절대 아님)

 

REST API(API 문서에 넣어서 정의해야 한다.)

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

- REAST API 요청 메서드 

 

 GET: 서버 자원을 가져오고자 할 때 사용하며,  요청의 본문(body)에 데이터를 넣지 않고, url에 넣어서 보낸다. 데이터를 서버로 보내야 한다면 쿼리스트링을 사용한다. 

 POST: 서버에 자원을 새로 등록하고자 할 때 사용한다. 요청의 본문에 새로 등록할 데이터를 넣어 보낸다.

 PUT: 서버의 자원을 요청에 들어 있는 자원으로 치환하고자 할 때 사용하고 요청의 본문에 치환할 데이터를 넣어 보낸다.

 PATCH: 서버 자원의 일부만 수정하고자 할 때 요청의 본문에 일부 수정할 데이터를 넣어 보낸다.

 DELETE: 서버의 자원을 삭제하고자 할 때 사용하며 요청의 본문에 데이터를 넣지 않음

 OPTIONS: 요청을 하기 전에 통신 옵션을 설명하기 위해 사용한다. 

 

 

 

REST API 문서 정의 

 

쿠키

- 키 - 값 쌍

- 서버로부터 쿠키가 오면 웹 브라우저는 쿠키를 저장해두었다가 다음에 요처할 때마다 쿠키를 동봉해서 보내고 서버는다음  요청에 들어 있는 쿠키를 읽어서 사용자가 누구인지 파악함 

- 쿠키는 요청의 헤더(Cookie)에 담겨 전송되고 브라우저는 응답의 헤더(Set-Cookie)에 따라 쿠키를 저장한다. 

 

 

쿠키를 직접 생성하고 요청자의 브라우저에 넣어보기 

cookie.js

const http = require('http');

http.createServer((req, res) => {
//  req.url은 주소의 path와 search 부분을 알린다.
  console.log(req.url, req.headers.cookie);  //req.header.cookie : req 객체에 담겨 있는 쿠키를 가져 가져온다. 
  res.writeHead(200, { 'Set-Cookie': 'mycookie=test' });
  res.end('Hello Cookie');
})
  .listen(8083, () => {
    console.log('8083번 포트에서 서버 대기 중입니다!');
  });
콘솔

 

 

쿠키값 설정하기

 

- 쿠키명=쿠키값: 기본적인 쿠키의 값입니다. mycookie=test 또는 name=zerocho와 같이 설정함

- Expires=날짜: 만료 기한입니다. 이 기한이 지나면 쿠키가 제거된다. 기본값은 클라이언트가 종료될 때까지임

- Max-age=초: Expires와 비슷하지만 날짜 대신 초를 입력할 수 있으며 해당 초가 지나면 쿠기가 제거된다. Expires보다 우선적으로 시행된다. 

 Domain=도메인명: 쿠키가 전송될 도메인을 특정할 수 있습니다. 기본값은 현재 도메인입니다.

 Path=URL: 쿠키가 전송될 URL을 특정할 수 있습니다. 기본값은 ‘/’이고, 이 경우 모든 URL에서 쿠키를 전송할 수 있습니다.

 Secure: HTTPS일 경우에만 쿠키가 전송됩니다.

 HttpOnly: 설정 시 자바스크립트에서 쿠키에 접근할 수 없습니다. 쿠키 조작을 방지하기 위해 설정하는 것이 좋습니다.

 

 

세션

 

 

 

https

- http + SSL 암호화

 

https.js

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번 포트에서 서버 대기 중입니다!');
  });

- http.createServer이 인자 두 개를 받는다. 

- 두 번째 인수는 앞에서 본 서버 로직이고, 첫 번째 인수는 인증서에 관련된 옵션 객체이다. 

- 인증서 확장자 : perm ,cert, key, ca

- fs.readFileSync : 인증서를 읽어오는 메서드 

 

 

 

http2 모듈 - http 통신 방식을 훨씬 간편하고 효율적으로 바꿔준 통신 방식으로 노드 모듈 안에 포함되어 있다. 

 

http2.js

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

http2.createSecureServer({
  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번 포트에서 서버 대기 중입니다!');
  });

- https 모듈을 http2로, createServer 메서드를 createSecure Server 메서드로 바꾸면 된다.

 

cluster - 싱글 프로세스로 동작하는 노드가 CPU 코어를 모두 사용할 수 있게 해주는 모듈이다.- 이말을 쉽게 해보자면, . 포트를 공유하는 노드 프로세스를 여러 개 둘 수 있어, 요청이 많이 들어왔을 때 병렬로 실행된 서버의 개수만큼 요청이 분산되게 할 수 있도록 해준다. 

 

 

cluster.js

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
  console.log(`마스터 프로세스 아이디: ${process.pid}`);
  // CPU 개수만큼 워커를 생산
  for (let i = 0; i < numCPUs; i += 1) {
    cluster.fork();
  }
  // 워커가 종료되었을 때
  cluster.on('exit', (worker, code, signal) => {
    console.log(`${worker.process.pid}번 워커가 종료되었습니다.`);
    console.log('code', code, 'signal', signal);
  });
} else {
  // 워커들이 포트에서 대기
  http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
    res.write('<h1>Hello Node!</h1>');
    res.end('<p>Hello Cluster!</p>');
    setTimeout(() => { // 워커가 존재하는지 확인하기 위해 1초마다 강제 종료
      process.exit(1);
    }, 1000);
  }).listen(8086);

  console.log(`${process.pid}번 워커 실행`);