3 분 소요

fetch를 통해 외부 api의 정보를 받아오는 연습을 했었는데, 직접 서버를 만들어 보지는 못했다. 이번 시간에서는 직접 서버를 여는 연습을 해 볼 것이다. 기존의 우리가 사용했던 Node.js를 통해서 서버를 열 수 있지만, express라는 프레임워크를 이용해서도 서버를 열 수 있다. 이번 시간에서는 Node.js를 이용해 서버를 여는 방법을 알아보겠다.

Node로 서버 열기

서버를 만들기 위해서는 http라는 모듈을 사용해야 한다. http에서는 여러가지 메소드들이 있는데, 그 중에서 http.createServer를 이용하여 서버를 만들 수 있다. 매개변수로는 request, response가 있는데, 요청과 반응에 따라 적절하게 사용할 수 있다.

const http = require("http");

const server = http.createServer((req, res) => {
  //...
});

이렇게 서버를 만들었는데, 아직 서버를 연 것은 아니다. server.listen을 통해 서버를 열 수 있는데, 매개변수로는 port번호가 들어오게 된다. port번호는 어떤 번호로 서버를 열 것인가를 정해주는 것이다.

const http = require("http");

const server = http.createServer((req, res) => {
  //...
});

server.listen(8000);

포트 번호는 보통 3000 ~ 8000 대를 이용하게 되는데, 포트 번호에 따라 의미가 달라지게 된다. 우리는 http 통신을 위한 서버이므로 http - 웹 페이지 전송을 하는 포트번호 8000대를 이용하는 것이 좋다.

request와 response

  • request request는 보통 서버로 요청을 보낼 때 사용하게 된다. 예를 들어 메세지를 보내줘 라는 식으로 서버에 전달을 하면, 서버는 request를 통해서 메세지를 받아 메세지를 전송해준다. request는 header와 body로 이루어져 있다.

    • header : HTTP verb(get, post, delete), URI, HTTP 버전
    • body(optional) : 요청할 메세지
  • response response는 요청을 받은 메세지에 대한 응답 메세지 이다. 예를 들어, 메세지를 보내줘 라는 요청을 받고, 메세지를 보낸 것에 대한 응답 즉 잘 보냈는지, 에러가 났는지에 대한 메세지를 의미한다. response도 request와 마찬가지로 header와 body로 이루어져 있다.

    • header : Status code, Reason Phrases
    • body(optional) : Requested Message

client와 server 통신

이제 본격적으로 client와 server 간의 통신을 해보겠다. 먼저 client의 request를 보도록 하겠다.

  • client request

    post(path, body) {
        fetch(`http://localhost:4999/${path}`, {
        method: "POST",
        body: JSON.stringify(body),
        headers: {
            "Content-Type": "application/json",
        },
    

    client 측에서 fetch를 통하여 통신을 이루도록 하였는데, url으로는 http://localhost:4999/${path} 이다. path에 따라 url이 달라질 것이다. method는 ‘POST’로, header에는 “Content-Type”: “application/json”를 넣었고, body에는 json으로 구성된 데이터를 보내게 될 것이다.

  • server에서 request 받아오기

    우선 client에서 보낸 request에 대한 메세지를 받기 위해서는 request를 사용하면 되는데, request.headers와 request.method, request.url를 통해 headers와 method, url을 알아 볼 수 있다.

    const http = require("http");
    const server = http.createServer((req, res) => {
      console.log(req.headers);
      console.log(req.method); // POST
      console.log(req.url); //
    });
    server.listen(8000);
    

    이렇게 request에서 어떤 url로 요청을 보냈고, method, headers를 알 수 있다. 이때 headers를 통해 어떤 content-type으로 보냈는지에 대해 알 수 있다.

    • application/json : text를 주고 받을 때 사용.
    • text/html : text가 아닌 html을 주고 받을 때 사용.

    request의 content-type은 application/json이므로, text를 주고 받는다 라는 것을 알 수 있다.

    request에서 보낸 데이터를 받고 싶을 때, 한번에 데이터가 전송이 된다면 좋겠지만, 우리가 유튜브를 볼 때, 버퍼링이 생기듯이 조각조각 나누어서 보내준다. 따라서 우리는 이때, stream의 방식을 이용하여 데이터를 받게된다.

    const http = require("http");
    const server = http.createServer((req, res) => {
      if (req.method === "POST" && req.url === "/lower") {
        const body = [];
        req
          .on("data", (chunk) => {
            console.log(chunk); // request 메세지의 buffer가 들어온다.
            body.push(chunk);
          })
          .on("end", () => {
            body = Buffer.concat(body).toString();
          });
      }
    });
    server.listen(8000);
    

    request의 메소드와 url를 설정하여 보냈으므로, 각 method와 url이 동일 할 때 동작 하도록 if문을 설정한다.

    요청한 데이터는 조각으로 나누어져 들어오므로, 데이터를 담을 배열을 하나 만들어 거기에 담는다. 이때 데이터를 받기 위해선 on이라는 메소드를 사용하는데, on에는 매개변수로 data, end, error 등 여러가지 이벤트를 처리 할 수 있도록 한다.

    데이터를 받아오는 이벤트 이므로, on(‘data’, chunk => {}) 를 사용하여 데이터 덩어리들을 body라는 배열에 담는다.

    데이터를 다 보냈으면 다시 req.on(‘end’)를 통해 데이터를 다 보냈을 때 콜백 함수를 만들게 되는데, 데이터는 buffer형식으로 담겨져 있고, 헤더의 content-type이 application/json 이므로 버퍼를 합쳐서 string 형식으로 변환할 수 있도록 한다.

  • server에서 client로 보내주기

    client에서 요청한 것

    • ‘/lower’로 입력받는 string을 소문자로 바꿔주기
    • ‘/upper’로 입력받은 string을 대문자로 바꿔주기

    각 url에 따라 데이터를 소문자화 하고, 대문자화를 한다. 이 string을 다시 client로 보내줘야 하는데, response의 header를 작성을 해주어 보내줘야 한다. 만약 잘 되었다면, status code를 200으로 보내고, 잘 안되었다면 404를 작성한다.

    요청한 것을 다시 보내줘야 하므로, response.end를 이용한다. end를 이용하는 이유는 요청한 것을 그대로 내버려 두면 서버는 계속해서 돌게 되므로 end 메소드를 사용한다. end에 보낼 데이터를 매개변수로 넣어주게 되면 데이터는 client로 전송 된다.

  • cors 설정

    여기서 데이터가 client로 요청이 되면 좋지만, fetch 오류가 뜬다. 그 이유는 cors를 설정하지 않았기 때문이다. 따라서 request의 헤더부분을 통해 origin을 찾아 낸 후, header를 설정 해 준다.

    const defaultCorsHeader = {
      "Access-Control-Allow-Origin": "*", // 여기에 request origin을 넣는다.
      "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
      "Access-Control-Allow-Headers": "Content-Type, Accept",
      "Access-Control-Max-Age": 10,
    };
    

    origin을 설정 한 후 res의 헤더에 설정을 하면 정상적으로 서버 통신이 이루어 진다.

댓글남기기