[Node] http 서버

찐새·2023년 1월 19일
0

Node.js

목록 보기
5/6
post-thumbnail

1. http 서버

http 모듈은 클라이언트의 요청을 처리한다. createServer(콜백) 메서드로 서버를 생성하고, 요청이 들어올 때마다 콜백을 실행한다. 콜백에는 요청을 뜻하는 req(request)와 응답을 뜻하는 res(response)가 매개변수로 들어있다.

import http from "http";

const server = 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>");
});

server.listen(4000, () => {
  console.log("Server on http://localhost:4000");
});

콜백의 res.writeHead는 응답의 정보가 담긴 헤더(header)를 작성한다. 200이라는 숫자는 http 상태 코드로, 브라우저가 요청의 성공 여부를 판단하는 코드이다. 여러 상태 코드는 MDN - HTTP 상태 코드에서 확인할 수 있다.

res.write는 본문을 작성하는 구간이고, res.end는 응답의 종료를 의미한다.

listen(포트, 콜백)으로 서버를 이벤틀 리스너에 등록한다. 여기서 콜백은 on을 이용하여 따로 동작할 수 있다.

server.listen(4000);

server.on("listening", () => {
  console.log("Server on http://localhost:4000");
});

server.on("error", (err) => {
  console.log(err);
});

변경 사항은 자동으로 반영되지 않으니 서버를 종료했다가 다시 실행해야 한다.

createServer를 여러 개 생성하여 여러 서버를 구동할 수도 있다. 이때 포트 번호는 저마다 달라야 한다.

1-1. fs로 html파일 보내기

fs 모듈의 promises를 가져와 비동기 형식으로 html 파일을 읽었다.

import http from "http";
import { promises } from "fs";

const server = http.createServer(async (req, res) => {
  try {
    const data = await promises.readFile("./server.html");
    res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
    res.end(data);
  } catch (error) {
    res.writeHead(500, { "Content-Type": "text/html; charset=utf-8" });
    res.end(error.message);
  }
});

server.listen(4000);

server.on("listening", () => {
  console.log("Server on http://localhost:4000");
});

2. REST API

RESTREpresentational State Transfer의 약자로, 주소를 통해 서버에 자원을 요청하는 일종의 규칙이다. url/todolist를 포함한다면 할 일 목록을 요청하는 것으로 볼 수 있다.

이때, 무슨 동작을 원하는지 알 수 없기 때문에 HTTP 요청 메서드를 사용해 요청 동작을 수행한다. 자주 사용하는 메서드는 다음과 같다.

  • GET : 서버 자원을 가져온다. 서버에 데이터를 보내야 하면 쿼리스트링(?key=value)을 사용한다.
  • POST : 서버에 자원을 새로 등록한다.
  • PUT : 서버에 있는 자원을 요청에 담긴 자원으로 바꾼다.
  • PATCH : 서버에 있는 자원의 일부만 수정한다.
  • DELETE 서버 자원을 삭제한다.
http.createServer(async (req, res) => {
  try {
    if (req.method === "GET") {
      if (req.url === "/") {
        // "/" 페이지 처리
      } else if (req.url === "/detail") {
        // "/detail" 페이지 처리
      }
    } else if (req.method === "POST") {
      if (req.url === "/new") {
        // new 본문 처리
      }
    } else if (req.method === "PUT") {
      // PUT 처리
    } else if (req.method === "DELETE") {
      // DELETE 처리
    }
  } catch (err) {
    // error 처리
  }
});

3. 쿠키 / 세션

서버는 클라이언트의 요청을 구분하지 못한다. 요청을 구분하기 위한 방법으로 쿠키세션이 있다.

3-1. 쿠키

쿠키키-값으로 저장된 정보이며 유효기간이 있다. 서버에서 미리 클라이언트를 추정할 정보를 쿠키로 만들어 응답하고, 클라이언트는 서버에 요청을 보낼 때마다 쿠키를 동봉한다.

import http from "http";

const server = http.createServer(async (req, res) => {
  res.writeHead(200, { "Set-Cookie": "mycookie=test" });
  res.end("<h1>Hello Cookie!</h1>");
});

server.listen(4000);

server.on("listening", () => {
  console.log("Server on http://localhost:4000");
});

개발자 도구의 네트워크 탭을 확인하면 Response HeadersSet-Cookie: mycookie=test가 담겨 있음을 확인할 수 있다.

자주 사용하는 쿠키 설정은 아래와 같다.

  • 쿠키명=쿠키값 : 기본 쿠키 값
  • Expires=날짜 : 만료 기한. 기본값은 클라이언트 종료이다.
  • Max-age=초 : 날짜 대신 초를 입력할 수 있다. 해당 초 경과 후 쿠키가 제거된다. Expires 보다 우선한다.
  • Domain=도메인명 : 쿠키가 전송될 도메인을 특정한다. 기본값은 현재 도메인이다.
  • Path=URL : 쿠키가 전송될 URL을 특정한다. 기본값은 "/"이다. 기본값으로 설정했다면 모든 URL에 쿠키를 전송할 수 있다.
  • Secure : HTTPS일 경우에만 쿠키가 전송된다.
  • HttpOnly : true일 시 자바스크립트에서 쿠키에 접근할 수 없다. 쿠키 조작 방지를 위해 설정하는 편이 좋다.

3-2. 세션

어플리케이션 탭을 확인해 보면 쿠키의 문제점을 알 수 있다. 설정한 쿠키값이 그대로 노출된다. 이러한 이유로 개인정보를 쿠키에 저장하는 것은 적절하지 못하다. 이때 세션을 사용할 수 있다. 쿠키에 session=value를 저장하여 서버에서 개인정보를 처리하도록 한다.

const server = http.createServer(async (req, res) => {
  let user = "Cookie";
  if (req.headers.cookie) {
    const [key, value] = req.headers.cookie.split("=");
    if (value === "AA1234") {
      user = "Test";
    }
  }
  res.writeHead(200, {
    "Set-Cookie": `session=AA1234`,
  });
  res.end(`<h1>Hello ${user}!</h1>`);
});

세션 값에 임의의 문자열을 기입했다. 서버에서 쿠키에 담긴 session의 값을 확인하고 처리한다. 보안을 위한다면 검증된 라이브러리를 사용하는 것이 좋다.

4. https / http2

https는 웹 서버에 SSL 암호화를 추가하는 모듈이다. 요청과 응답 데이터를 암호화하여 누군가 요청을 가로채더라도 확인할 수 없게 만든다.

서버에 적용하려면 인증 기관에서 발급받은 인증서가 필요하다. Let's Encrypt 같은 기관에서 무료로 발급해준다고도 한다.

http2 모듈은 SSL 암호화와 더불어 최신 HTTP 프로토콜인 http/2를 사용할 수 있다. http/1.1 보다 개선되어 훨씬 효율적으로 요청을 보낸다.

http/1.1 vs http/2


참고
Node.js 공식 사이트
Node.js 교과서 개정 3판

profile
프론트엔드 개발자가 되고 싶다

0개의 댓글