4. http 모듈로 서버 만들기

진영민·2022년 9월 4일
0

Node.js 교과서

목록 보기
3/13

해당 글은 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와 라우팅 사용하기

REST는 REpresentational State Transfer의 줄임말이며, 서버의 자원을 정의하고 자원에 대한 주소를 지정하는 방법을 가리킨다.

주소는 명사를 사용한다.

/user 이면 사용자 정보에 관련된 자원을 요청하는 것이고
/post 라면 게시글에 관련된 자원을 요청하는 것이라고 추측할 수 있다.

단순이 명사만 있으면 어떤 동작을 행하는지 모르기 때문에 HTTP요청 메서드라는 것을 사용한다.

GET

서버 자원을 가져오고자 할 때 사용한다.
데이터를 서버로 보내야 한다면 쿼리스트링을 사용한다.
브라우저에서 캐싱할 수도 있으므로 같은 GET요청을 할 때 캐시에서 가져올 수도 있다.

POST

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

PUT

서버의 자원을 요청에 들어 있는 자원으로 치환하고자 할 때 사용한다.

PATCH

서버 자원의 일부분만 수정하고자 할 때 사용한다.

DELETE

서버의 자원을 삭제하고자 할 때 사용한다. 요청의 본문에 데이터를 넣지 않는다.

OPTIONS

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

쿠키와 세션

클라이언트가 누구인지 기억하기 위해 서버는 요청에 대한 응답을 할 때 쿠키라는 것을 같이 보낸다.
쿠키는 유효기간이 있으며 단순한 키-값의 쌍이다.
서버로부터 쿠키가 오면 웹 브라우저는 쿠키를 저장해 두었다가 다음에 요청할 때마다 쿠키를 동봉해서 보낸다.

쿠키는 요청의 헤더에 담겨 전송된다.

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와 http2

https

https는 웹 서버에 SSL암호화를 추가한다.
GET이나 POST요청을 할 때 오가는 데이터를 암호화해서 중간에 다른 사람이 요청을 가로채더라도 내용을 확인할 수 없게 한다.

하지만 서버에서 암호화를 적용하려면 인증기관에서 인증서를 구입해야 하고, 인증서 발급 과정은 복잡하고 도메인도 필요하므로 소개하지 않는다.

http2

노드의 http2모듈은 SSL 암호화와 더불어 최신HTTP프로토콜인 http/2를 사용할 수 있게 한다.
http/2는 요청 및 응답 방식이 기존 http/1.1보다 크게 개선되어 훨씬 효율적으로 요청을 보낸다.

cluster

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}번 워커 실행`);
}
profile
코린이

0개의 댓글