[Day69] HTTP Request와 멱등성(Idempotent)

Validator·2023년 9월 20일
0

HTTP 요청과 멱등성(Idempotent)이란?

개요

HTTP(HyperText Transfer Protocol)는 웹 상에서 데이터를 주고받기 위한 규약이다. HTTP 프로토콜을 사용할 때는 다양한 종류의 요청 메소드가 있다. 이 중에서도 "멱등성(Idempotent)"이라는 특성을 가지는 요청 메소드에 대해서 중점적으로 좀 학습해보았다.

멱등성(Idempotent)의 정의

멱등성(Idempotent)은 같은 작업을 여러 번 수행하더라도 동일한 결과를 반환해야 한다는 특성이다. HTTP 컨텍스트에서 이는 같은 요청을 하나 이상 실행하더라도 서버의 상태는 동일하게 유지되어야 함을 의미한다.

멱등성을 가지는 HTTP 메소드

HTTP 메소드 중에서는 GET, HEAD, PUT, DELETE 등이 멱등성을 가진다.

  • GET: 서버에서 특정 리소스를 가져오는 작업을 수행한다. 같은 리소스에 대한 GET 요청을 여러 번 수행해도 서버 상태가 변하지 않는다.
  • HEAD: GET 메소드와 유사하지만, 리소스의 본문을 반환하지 않고 헤더 정보만을 가져온다. 여기에서도 멱등성이 유지된다.
  • PUT: 서버의 특정 리소스를 업데이트하거나 새 리소스를 생성한다. 같은 리소스에 대한 PUT 요청을 여러 번 실행해도 최종 상태는 동일하다.
  • DELETE: 서버의 특정 리소스를 삭제한다. 같은 리소스에 대한 DELETE 요청을 여러 번 수행하더라도 결과는 동일하다. (만약에 마지막 배열 요소를 제거한다는 식으로 DELETE가 구현된다면 이는 멱등성을 가지지 않고 있다고 해야할 것이다!!)

코드 예시: Node.js와 Express 활용

이제 Node.js와 Express 라이브러리를 사용해 간단한 RESTful API를 구축하며 멱등성을 확인하는 코드 예시를 살펴본다.

프로젝트 설정

먼저, 새 프로젝트 폴더를 생성하고 필요한 노드 패키지를 설치한다.

npm init -y
npm install express

앱 기본 설정

Express를 불러오고, 간단한 데이터 구조를 만든다.

const express = require('express');
const app = express();
app.use(express.json());

const tasks = [
  { id: 1, name: 'Task 1' },
  { id: 2, name: 'Task 2' },
  { id: 3, name: 'Task 3' }
];

GET 요청

GET 요청은 멱등성을 가지므로 같은 요청을 여러 번 해도 결과는 동일해야 한다. 다음은 전체 태스크 목록을 반환하는 GET 요청과, 특정 태스크를 반환하는 GET 요청의 코드 예시다.

app.get('/tasks', (req, res) => {
  res.send(tasks);
});

app.get('/tasks/:id', (req, res) => {
  const task = tasks.find(t => t.id === parseInt(req.params.id));
  if (!task) return res.status(404).send('Task not found');
  res.send(task);
});

GET 요청은 데이터를 변경하지 않으므로 동일한 요청을 여러 번 수행하더라도 반환되는 결과와 서버의 상태는 변하지 않는다.

HTTP 메소드: HEAD, PUT, DELETE

HEAD 요청

HEAD 요청은 GET 요청과 유사하지만, 리소스의 본문을 반환하지 않고 헤더 정보만을 가져온다. 이러한 요청도 GET과 마찬가지로 서버의 상태를 변경하지 않는다. 따라서 멱등성이 유지된다.

HEAD 요청 코드 예시

app.head('/tasks/:id', (req, res) => {
  const task = tasks.find(t => t.id === parseInt(req.params.id));
  if (!task) return res.status(404).send('Task not found');
  res.status(200).send();
});

PUT 요청

PUT 요청은 특정 리소스를 새로운 상태로 업데이트하거나, 해당 리소스가 없을 경우 새로 생성한다. 멱등성을 가지므로 동일한 PUT 요청을 여러 번 실행해도 최종 상태는 동일하다.

PUT 요청 코드 예시

app.put('/tasks/:id', (req, res) => {
  let task = tasks.find(t => t.id === parseInt(req.params.id));
  if (!task) {
    task = { id: parseInt(req.params.id), name: req.body.name };
    tasks.push(task);
  } else {
    task.name = req.body.name;
  }
  res.send(task);
});

DELETE 요청

DELETE 요청은 서버의 특정 리소스를 삭제한다. 같은 리소스에 대한 DELETE 요청을 여러 번 수행하더라도 결과는 동일하다.

DELETE 요청 코드 예시

app.delete('/tasks/:id', (req, res) => {
  const task = tasks.find(t => t.id === parseInt(req.params.id));
  if (!task) return res.status(404).send('Task not found');

  const index = tasks.indexOf(task);
  tasks.splice(index, 1);

  res.send(task);
});

멱등성을 가지지 않는 HTTP 메소드: POST, PATCH

POST 요청

POST 요청은 새로운 리소스를 생성하기 위한 메소드다. 같은 POST 요청을 여러 번 실행하면 서버의 상태가 계속해서 변하므로 멱등성이 없다고 하겠다!

POST 요청 코드 예시

let nextId = 4;

app.post('/tasks', (req, res) => {
  const task = {
    id: nextId,
    name: req.body.name
  };
  tasks.push(task);
  nextId++;

  res.status(201).send(task);
});

PATCH 요청

PATCH 요청은 리소스의 일부만을 업데이트한다. 이 메소드 역시 같은 요청을 여러 번 수행하면 서버의 상태가 변하므로 멱등성이 없다.

PATCH 요청 코드 예시

app.patch('/tasks/:id', (req, res) => {
  const task = tasks.find(t => t.id === parseInt(req.params.id));
  if (!task) return res.status(404).send('Task not found');

  task.name = req.body.name || task.name;

  res.send(task);
});

멱등성(Idempotent)은 API를 설계하거나 사용할 때 매우 중요한 개념이므로 잘 이해하고 있어야 한다.

0개의 댓글