Node/http 모듈로 서버 만들기

REST API 서버 만들기

webmaster 2022. 9. 5. 01:16
728x90

RestAPI

  • 서버에 요청을 보낼 때는 주소를 통해 요청의 내용을 표현한다
    • /index.html이면 index.html을 보내달라는 뜻이다
    • 항상 html을 요구할 필요는 없다(추상적인것도 가능하다)
    • 서버가 이해하기 쉬운 주소가 좋다(서버가 주도권을 가지고 있기 때문에 클라이언트는 서버가 정해주 주소로 접속해야한다)
  • REST API(Representational State Transfer)
    • 서버의 자원을 정의하고 자원에 대한 주소를 지정하는 방법이다(예측을 할 수 있어 구조파악은 쉽지만, 해킹에 취약한 단점이 있다)
    • /user이면 사용자 정보에 관한 정보를 요청하는 것이다
    • /post면 게시글에 관련된 자원을 요청하는 것이다
  • HTTP 요청 메서드
    • GET: 서버 자원을 가져오려고 할 때 사용한다
    • POST: 서버에 자원을 새로 등록하고자 할 때 사용(또는 뭘 써야할 지 애매할 때)한다
    • PUT: 서버의 자원을 요청에 들어있는 자원으로 치환하고자할 때 사용한다
    • PATCH: 서버 자원의 일부만 수정하고자 할 때 사용한다
    • DELETE: 서버의 자원을 삭제하고자할 때 사용한다

Http 프로토콜

클라이언트 - RESTAPI 서버
RestFul

  • 클라이언트가 누구든 서버와 HTTP 프로토콜로 소통 가능하다
    • iOS, 안드로이드, 웹이 모두 같은 주소로 요청 보낼 수 있다.
    • 서버와 클라이언트를 분리한다
  • RESTful
    • REST API를 사용한 주소 체계를 이용하는 서버이다
    • GET /user는 사용자를 조회하는 요청, POST /user는 사용자를 등록하는 요청한다(restful 하다)

REST 서버 만들기

RestServer코드만 살펴보자(나머지는 Git 에서 복붙하자): https://github.com/zerocho/nodejsbook 

const http = require("http");
const fs = require("fs").promises;

const users = {}; // 데이터 저장용

http
  .createServer(async (req, res) => {
    try {
      //서버는 반드시 응답을 해야한다 -> 30초 넘으면 오류 발생
      if (req.method === "GET") {
        //브라우저에서 접근할 경우
        if (req.url === "/") {
          const data = await fs.readFile("./restFront.html");
          res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
          //200은 성공, content-Type으로 html임을 알려준다.
          //writeHead 는 header를 작성해 주는것을 알 수 있다.
          return res.end(data);
        } else if (req.url === "/about") {
          const data = await fs.readFile("./about.html");
          res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
          return res.end(data);
        } else if (req.url === "/users") {
          res.writeHead(200, {
            "Content-Type": "application/json; charset=utf-8"
          });
          return res.end(JSON.stringify(users));
        }
        // /도 /about도 /users도 아니면
        try {
          const data = await fs.readFile(`.${req.url}`);
          return res.end(data);
        } catch (err) {
          // 주소에 해당하는 라우트를 못 찾았다는 404 Not Found error 발생
        }
      } else if (req.method === "POST") {
        if (req.url === "/user") {
          let body = "";
          // 요청의 body를 stream 형식으로 받음
          req.on("data", data => {
            body += data;
          });
          // 요청의 body를 다 받은 후 실행됨
          return req.on("end", () => {
            console.log("POST 본문(Body):", body);
            const { name } = JSON.parse(body);
            const id = Date.now();
            users[id] = name;
            res.writeHead(201, { "Content-Type": "text/plain; charset=utf-8" });
            res.end("ok");
          });
        }
      } else if (req.method === "PUT") {
        if (req.url.startsWith("/user/")) {
          const key = req.url.split("/")[2];
          let body = "";
          req.on("data", data => {
            body += data;
          });
          return req.on("end", () => {
            console.log("PUT 본문(Body):", body);
            users[key] = JSON.parse(body).name;
            res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
            return res.end("ok");
          });
        }
      } else if (req.method === "DELETE") {
        if (req.url.startsWith("/user/")) {
          const key = req.url.split("/")[2];
          delete users[key];
          res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
          return res.end("ok");
        }
      }
      res.writeHead(404);
      return res.end("NOT FOUND");
    } catch (err) {
      console.error(err);
      res.writeHead(500, { "Content-Type": "text/plain; charset=utf-8" });
      res.end(err.message);
    }
  })
  .listen(8082, () => {
    console.log("8082번 포트에서 서버 대기 중입니다");
  });

개발자도구(f12)의 네트워크 텝에서 볼 수 있다.

  • GET 메서드에서 /, /about 요청 주소는 페이지를 요청하는 것이므로 HTML 파일을 읽어서 전송한다
    • AJAX 요청을 처리하는 /users에서는 users 데이터를 전송합니다. JSON 형식으로 보내기 위해 JSON.stringify를 사용했다
    • 그 외의 GET 요청은 CSS나 JS 파일을 요청하는 것이므로 찾아서 보내주고, 없다면 404 NOT FOUND 에러를 응답한다
    • DELETE 메서드로 요청이 오면 주소에 들어 있는 키에 해당하는 사용자를 제거한다
  • 해당하는 주소가 없을 경우 404 NOT FOUND 에러를 응답한다
  • POST와 PUT 메서드는 클라이언트로부터 데이터를 받으므로 특별한 처리가 필요한데, req.on('data', 콜백)과 req.on('end', 콜백) 부분이 특별한 처리를 하는 부분이다
    • readStream으로 요청과 같이 들어오는 요청 본문을 받을 수 있다( 단, 문자열이므로 JSON으로 만드는 JSON.parse 과정이 한 번 필요하다)
  • 개발자도구(F12) Network 탭에서 요청 내용 실시간 확인 가능
    • Name은 요청 주소, Method는 요청 메서드, Status는 HTTP 응답 코드
    • Protocol은 HTTP 프로토콜, Type은 요청 종류(xhr은 AJAX 요청)
728x90

'Node > http 모듈로 서버 만들기' 카테고리의 다른 글

https, http2  (0) 2022.09.05
세션 사용하기  (0) 2022.09.05
쿠키 이해하기  (0) 2022.09.05
fs로 HTML 읽어 제공하기  (0) 2022.09.05
HTTP 서버 만들기  (0) 2022.09.05