해당 글은 Node.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번 포트에서 서버 대기중입니다!');
})
res.writeHead는 응답에 대한 정보를 기록하는 메서드이다.
이 정보가 기록되는 부분을 헤더 라고 부른다.
res.write메서드의 첫 번째 인수는 클라이언트로 보낼 데이터이다.
res.end는 응답을 종료하는 메서드이다. 만약 인수가 있다면 그 데이터도 클라이언트로 보내고 응답을 종료한다.
HTML파일을 따로 만들어서 보내는 방법도 있다.
//server2.html
<!DOCTYPE html>
<html lang="en">
<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;
http.createServer(async (req,res)=>{
try{
const data = await fs.readFile('./server2.html');
res.writeHead(200, {'Content-Type':'text/html; charset = utf-8'});
res.end(data);
}catch(err){
console.error(err);
res.writeHead(500,{'Content-Type':'text/plain;charset = utf-8'});
res.end(err.message);
}
}).listen(8081, ()=>{
console.log('8081번 포트에서 대기 중입니다!');
});
REST는 REpresentational State Transfer의 줄임말이며, 서버의 자원을 정의하고 자원에 대한 주소를 지정하는 방법을 가리킨다.
/user 이면 사용자 정보에 관련된 자원을 요청하는 것이고
/post 라면 게시글에 관련된 자원을 요청하는 것이라고 추측할 수 있다.
단순이 명사만 있으면 어떤 동작을 행하는지 모르기 때문에 HTTP요청 메서드라는 것을 사용한다.
서버 자원을 가져오고자 할 때 사용한다.
데이터를 서버로 보내야 한다면 쿼리스트링을 사용한다.
브라우저에서 캐싱할 수도 있으므로 같은 GET요청을 할 때 캐시에서 가져올 수도 있다.
서버에 자원을 등록하고자 할 때 사용한다.
요청의 본문에 새로 등록할 데이터를 넣어 보낸다.
서버의 자원을 요청에 들어 있는 자원으로 치환하고자 할 때 사용한다.
서버 자원의 일부분만 수정하고자 할 때 사용한다.
서버의 자원을 삭제하고자 할 때 사용한다. 요청의 본문에 데이터를 넣지 않는다.
요청을 하기 전에 통신 옵션을 설명하기 위해 사용한다.
클라이언트가 누구인지 기억하기 위해 서버는 요청에 대한 응답을 할 때 쿠키라는 것을 같이 보낸다.
쿠키는 유효기간이 있으며 단순한 키-값의 쌍이다.
서버로부터 쿠키가 오면 웹 브라우저는 쿠키를 저장해 두었다가 다음에 요청할 때마다 쿠키를 동봉해서 보낸다.
쿠키는 요청의 헤더에 담겨 전송된다.
const http = require('http');
http.createServer((req, res)=>{
console.log(req.url, req.headers.cookie);
res.writeHead(200, {'Set-Cookie':'mycookie=test'});
res.end('Hello Cookie');
}).listen(8082,()=>{
console.log('8082번 포트에서 서버 대기 중입니다!');
});
이러한 방식으로 mycookie = test라는 쿠키를 심을 수 있다.
const http = require('http');
const fs = require('fs').promises;
const url = require('url');
const qs = require('querystring');
const parseCookies = (cookie = '')=>
cookie
.split(';')
.map(v=>v.split('='))
.reduce((acc, [k,v])=>{
acc[k.trim()]=decodeURIComponent(v);
return acc;
},{});
http.createServer(async (req, res)=>{
const cookies = parseCookies(req.headers.cookie);
if(req.url.startsWith('/login')){
const { query }=url.parse(req.url);
const{name}=qs.parse(query);
const expires = new Date();
expires.setMinutes(expires.getMinutes()+5);
res.writeHead(302, {
Location:'/',
'Set-Cookie':`name=${encodeURIComponent(name)}; Expires=${expires.toGMTString()};HttpOnly;Path=/`,
});
res.end();
}
else if(cookies.name){
res.writeHead(200, {'Content-Type':'text/plain; charset=utf-8'});
res.end(`${cookies.name}님 안녕하세요`);
}else{
try{
const data = await fs.readFile('./cookie2.html');
res.writeHead(200, {'Content-Type':'text/html; charset=utf-8'});
res.end(data);
}catch(err){
res.writeHead(500,{'Content-Type':'text/plain;charset=utf-8'});
res.end(err.message);
}
}
}).listen(8083, ()=>{
console.log('8083번 포트에서 대기 중입니다.');
})
https는 웹 서버에 SSL암호화를 추가한다.
GET이나 POST요청을 할 때 오가는 데이터를 암호화해서 중간에 다른 사람이 요청을 가로채더라도 내용을 확인할 수 없게 한다.
하지만 서버에서 암호화를 적용하려면 인증기관에서 인증서를 구입해야 하고, 인증서 발급 과정은 복잡하고 도메인도 필요하므로 소개하지 않는다.
노드의 http2모듈은 SSL 암호화와 더불어 최신HTTP프로토콜인 http/2를 사용할 수 있게 한다.
http/2는 요청 및 응답 방식이 기존 http/1.1보다 크게 개선되어 훨씬 효율적으로 요청을 보낸다.
cluster모듈은 기본적으로 싱글 프로세스로 동작하는 노드가 CPU코어를 모두 사용할 수 있게 해주는 모듈이다.
포트를 공유하는 노드 프로세스를 여러 개 둘 수도 있으므로, 요청이 많이 들어왔을 때 병렬로 실행된 서버만큼 요청이 분산되게 할 수 있다.
const http = require('http');
const numCPUs = require('os').cpus().length;
if(cluster.isMaster){
console.log(`마스터 프로세스 아이디: ${process.pid}`);
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>');
}).listen(8084);
console.log(`${process.pid}번 워커 실행`);
}