프로그래밍 언어/NODE JS

REST와 라우팅 사용하기

· 코딩마이데이

REST에서는 주소 외에도 HTTP 요청 메서드라는 것을 사용합니다. 폼 데이터를 전송할 때 GET 또는 POST가 바로 요청 메서드입니다. 또한, PUT, PATCH, DELETE, OPTIONS 등의 메소드도 자주 사용됩니다.

  • GET : 서버 자원을 가져오고자 할 때 사용합니다. 요청의 본문에 데이터를 넣지 않습니다. 데이터를 서버로 보내야 한다면 쿼리스트링을 사용합니다.
  • POST : 서버에 자원을 가져오고자 할 때 사용합니다. 요청의 본문에 새로 등록할 데이터를 넣어 보냅니다.
  • PUT : 서버의 자원을 요청에 들어 있는 자원으로 치환하고자 할 때 사용합니다. 요청의 본문에 치환할 데이터를 넣어 보냅니다.
  • PATCH : 서버 자원의 일부만 수정하고자 할 때 사용합니다. 요청은 본문에 일부 수정할 데이터를 넣어 보냅니다.
  • DELETE : 서버의 자원을 삭제하고자 할 때 사용합니다. 요청의 본문에 데이터를 넣지 않습니다.
  • OPTIONS : 요청을 하기 전에 통신 옵션을 설명하기 위해 사용합니다.

HTTP 통신을 사용하면 클라이언트가 누구든 상관없이 같은 방식으로 서버와 소통할 수 있습니다. iOS, 안드로이드, 웹, 다른 서버가 모두 같은 주소로 요청을 보낼 수 있습니다. 즉, 서버와 클라이언트가 분리되어 있다는 뜻입니다. 이렇게 서버와 클라이언트를 분리하면 추후에 서버를 확장할 때 클라이언트에 구애되지 않아 좋습니다.

 

restFont.css

a {
  color: blue;
  text-decoration: none;
}

 

restFont.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>RESRful SERVER</title>
    <link rel="stylesheet" href="./restFont.css" />
  </head>
  <body>
    <nav>
      <a href="/">Home</a>
      <a href="/about">About</a>
    </nav>
    <div>
      <form id="form">
        <input type="text" id="username" />
        <button type="submit">등록</button>
      </form>
    </div>
    <div id="list"></div>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="./restFont.js"></script>
  </body>
</html>

 

restFont.js

async function getUser() {
  // 로딩 시 사용자 정보를 가져오는 함수
  try {
    const res = await axios.get("/users");
    const users = res.data;
    const list = document.getElementById("list");
    list.innerHTML = "";
    // 사용자마다 반복적으로 화면 표시 및 이벤트 연결
    Object.keys(users).map(function (key) {
      const userDiv = document.createElement("div");
      const span = document.createElement("span");
      span.textContent = users[key];
      const edit = document.createElement("button");
      edit.addEventListener("click", async () => {
        // 수정 버튼 클릭
        const name = prompt("바꿀 이름을 입력하세요");
        if (!name) {
          return alert("이름을 반드시 입력하셔야 합니다");
        }
        try {
          await axios.put("/user/" + key, { name });
          getUser();
        } catch (err) {
          console.error(err);
        }
      });
      const remove = document.createElement("button");
      remove.textContent = "삭제";
      remove.addEventListener("click", async () => {
        // 삭제 버튼 클릭
        try {
          await axios.delete("/user/" + key);
          getUser();
        } catch (err) {
          console.error(err);
        }
      });
      userDiv.appendChild(span);
      userDiv.appendChild(edit);
      userDiv.appendChild(remove);
      list.appendChild(userDiv);
      console.log(res.data);
    });
  } catch (err) {
    console.error(err);
  }
}

window.onload = getUser; // 화면 로딩 시 getUser 호출
// 폼 제출(submit) 시 실행
document.getElementById("form"),
  addEventListener("submit", async (e) => {
    e.preventDefault();
    const name = e.target.username.value;
    if (!name) {
      return alert("이름을 입력하세요");
    }
    try {
      await axios.post("/user", { name });
      getUser();
    } catch (err) {
      console.error(err);
    }
    e.target.username.value = "";
  });

 

about.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>RESTful SERVER</title>
    <link rel="stylesheet" href="./restFont.css" />
  </head>
  <body>
    <nav>
      <a href="/">Home</a>
      <a href="/about">About</a>
    </nav>
    <div>
      <h2>소개 페이지입니다.</h2>
      <p>사용자 이름을 등록하세요!</p>
    </div>
  </body>
</html>

 

restServer.js

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

http
  .createServer(async (req, res) => {
    try {
      console.log(req.method, req.url);
      if (req.method === "GET") {
        if (req.url === "/") {
          const data = await fs.readFile("./restFont.html");
          res.writeHead(200, { "Content-Type": "text/html; charset=urf-8" });
          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);
        }
        // 주소가 /도 /about도 아니면
        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);
            res.end("등록 성공");
          });
        }
      } 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;
            return res.end(JSON.stringify(users));
          });
        }
      } else if (req.method === "DELETE") {
        if (req.url.startsWith("/users/")) {
          const key = req.url.split("/")[2];
          delete users[key];
          return res.end(JSON.stringify(users));
        }
      }
      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번 포트에서 서버 대기 중입니다");
  });

 

콘솔

$ node restServer
8082번 포트에서 서버 대기 중입니다

Home 클릭 시

 

About 클릭 시

 

이제 웹 사이트에서 등록, 수정, 삭제를 해보면서 서버에 어떤 요청을 보내는지 확인해봅시다. Method 탭이 보이지 않으면 Name 탭을 마우스 오른쪽 클릭하여 Method에 체크하면 됩니다.

서버에 보내는 요청들 확인하기
Network 탭에서 네트워크 요청 내용을 실시간으로 볼 수 있습니다. REST 방식으로 주소를 만들었으므로 주소와 메소드만 봐도 요청 내용을 유추할 수 있습니다. Name은 요청 주소를, Method는 요청 메서드를, Status는 HTTP 응답 코드를, Protocol은 통신 프로토콜을, Type은 요청의 종류를 의미합니다. xhr은 AJAX 요청입니다.

'프로그래밍 언어 > NODE JS' 카테고리의 다른 글

https와 http2  (0) 2025.05.26
쿠키와 세션 이해하기  (1) 2025.05.23
요청과 응답 이해하기  (0) 2025.05.16
자주 발생하는 에러들  (0) 2025.05.13
예외 처리하기  (0) 2025.05.10