TL;DR

  • HTTP 메서드와 FastAPI 데코레이터의 핵심 개념과 사용 범위를 한눈에 정리
  • 등장 배경과 필요한 이유를 짚고 실무 적용 포인트를 연결
  • 주요 특징과 체크리스트를 빠르게 확인

1. 개념

```python from fastapi import FastAPI

2. 배경

HTTP 메서드와 FastAPI 데코레이터이(가) 등장한 배경과 기존 한계를 정리한다.

3. 이유

이 주제를 이해하고 적용해야 하는 이유를 정리한다.

4. 특징

  • 1 데이터 전송 위치
  • 2 멱등성 (Idempotency)
  • 프론트엔드 코드 예시
  • 관련 키워드

5. 상세 내용

작성일: 2026-01-29 카테고리: Backend / HTTP / FastAPI 포함 내용: HTTP 메서드, GET, POST, PUT, DELETE, REST, CRUD, 멱등성, FastAPI 라우팅


1. FastAPI 데코레이터

from fastapi import FastAPI

app = FastAPI()

@app.get("/users")          # GET 요청
def get_users(): ...

@app.post("/users")         # POST 요청
def create_user(): ...

@app.put("/users/{id}")     # PUT 요청
def update_user(): ...

@app.delete("/users/{id}")  # DELETE 요청
def delete_user(): ...

@app.patch("/users/{id}")   # PATCH 요청
def partial_update(): ...
┌─────────────────────────────────────────────────────────────────┐
│                  FastAPI 데코레이터 = HTTP 메서드 매핑           │
│                                                                   │
│  @app.get("/path")    →  GET /path 요청이 오면 이 함수 실행     │
│  @app.post("/path")   →  POST /path 요청이 오면 이 함수 실행    │
│  @app.put("/path")    →  PUT /path 요청이 오면 이 함수 실행     │
│  @app.delete("/path") →  DELETE /path 요청이 오면 이 함수 실행  │
│                                                                   │
│  같은 URL이라도 메서드에 따라 다른 함수 실행!                    │
│                                                                   │
│  GET  /users  →  목록 조회                                       │
│  POST /users  →  새로 생성                                       │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

2. HTTP 메서드의 역사

┌─────────────────────────────────────────────────────────────────┐
│                    HTTP 메서드 진화 역사                         │
│                                                                   │
│  1991년 - HTTP/0.9                                               │
│  └── GET만 존재 (문서 가져오기만)                                │
│  └── 팀 버너스리가 웹 발명                                       │
│                                                                   │
│  1996년 - HTTP/1.0 (RFC 1945)                                    │
│  └── GET, POST, HEAD 추가                                        │
│  └── POST = 폼 데이터 전송용                                     │
│                                                                   │
│  1999년 - HTTP/1.1 (RFC 2616)                                    │
│  └── PUT, DELETE, OPTIONS, TRACE 추가                            │
│  └── 하지만 실제로는 GET/POST만 주로 사용                        │
│                                                                   │
│  2000년 - Roy Fielding, REST 논문 발표                           │
│  └── HTTP 메서드를 "의미있게" 사용하자!                          │
│  └── 각 메서드에 명확한 역할 부여                                │
│                                                                   │
│  2010년대 - RESTful API 대중화                                   │
│  └── GET/POST/PUT/DELETE = CRUD 매핑                             │
│  └── 현대 웹 API의 표준                                          │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

3. 전통적 이해 (MPA 시대)

┌─────────────────────────────────────────────────────────────────┐
│                   전통적 웹 (MPA 시대)                           │
│                                                                   │
│  사용자          브라우저              서버                      │
│    │                │                    │                       │
│    │  주소창 입력    │                    │                       │
│    │───────────────►│  GET /page.html    │                       │
│    │                │───────────────────►│                       │
│    │                │   HTML 페이지 반환  │                       │
│    │                │◄───────────────────│                       │
│    │   페이지 표시   │                    │                       │
│    │◄───────────────│                    │                       │
│    │                │                    │                       │
│    │  폼 작성 후     │                    │                       │
│    │  Submit 클릭   │  POST /submit      │                       │
│    │───────────────►│───────────────────►│                       │
│    │                │  새 페이지 반환     │                       │
│    │                │◄───────────────────│                       │
│    │                │                    │                       │
│                                                                   │
│  전통적 이해:                                                    │
│  GET = 페이지/리소스 가져오기                                    │
│  POST = 폼 데이터 서버에 제출                                    │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

4. 현대적 의미 (RESTful API)

┌─────────────────────────────────────────────────────────────────┐
│              현대 API에서 HTTP 메서드 = CRUD 매핑                │
│                                                                   │
│  ┌──────────┬──────────┬─────────────────────────────────────┐  │
│  │ 메서드   │ CRUD     │ 의미                                │  │
│  ├──────────┼──────────┼─────────────────────────────────────┤  │
│  │ GET      │ Read     │ 조회 (데이터 변경 없음)             │  │
│  │ POST     │ Create   │ 새로 생성                           │  │
│  │ PUT      │ Update   │ 전체 수정 (덮어쓰기)                │  │
│  │ PATCH    │ Update   │ 부분 수정                           │  │
│  │ DELETE   │ Delete   │ 삭제                                │  │
│  └──────────┴──────────┴─────────────────────────────────────┘  │
│                                                                   │
│  예시: 사용자 API                                                │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │  GET    /users       →  전체 사용자 목록 조회             │  │
│  │  GET    /users/1     →  1번 사용자 조회                   │  │
│  │  POST   /users       →  새 사용자 생성                    │  │
│  │  PUT    /users/1     →  1번 사용자 전체 정보 수정         │  │
│  │  PATCH  /users/1     →  1번 사용자 일부 정보 수정         │  │
│  │  DELETE /users/1     →  1번 사용자 삭제                   │  │
│  └───────────────────────────────────────────────────────────┘  │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

5. GET vs POST 핵심 차이

┌─────────────────────────────────────────────────────────────────┐
│                    GET vs POST 비교                              │
│                                                                   │
│  ┌─────────────┬─────────────────────┬─────────────────────┐    │
│  │             │        GET          │       POST          │    │
│  ├─────────────┼─────────────────────┼─────────────────────┤    │
│  │ 목적        │ 데이터 조회         │ 데이터 생성/전송    │    │
│  │ 데이터 위치 │ URL 쿼리스트링      │ 요청 Body           │    │
│  │ 데이터 크기 │ 제한 (2KB~8KB)      │ 제한 없음           │    │
│  │ 캐싱        │ ✅ 가능             │ ❌ 불가             │    │
│  │ 북마크      │ ✅ 가능             │ ❌ 불가             │    │
│  │ 히스토리    │ URL에 남음          │ 안 남음             │    │
│  │ 멱등성      │ ✅ 멱등             │ ❌ 비멱등           │    │
│  │ 안전성      │ ✅ 안전             │ ❌ 비안전           │    │
│  └─────────────┴─────────────────────┴─────────────────────┘    │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

5.1 데이터 전송 위치

GET 요청:
┌─────────────────────────────────────────────────────────────────┐
│  GET /search?keyword=python&page=1 HTTP/1.1                     │
│  Host: example.com                                               │
│                                                                   │
│  (Body 없음)                                                     │
│                                                                   │
│  → 데이터가 URL에 노출됨                                        │
│  → 브라우저 히스토리, 로그에 남음                               │
│  → 민감정보 ❌                                                  │
└─────────────────────────────────────────────────────────────────┘

POST 요청:
┌─────────────────────────────────────────────────────────────────┐
│  POST /login HTTP/1.1                                            │
│  Host: example.com                                               │
│  Content-Type: application/json                                  │
│                                                                   │
│  {"username": "kim", "password": "secret123"}                    │
│                                                                   │
│  → 데이터가 Body에 숨겨짐                                       │
│  → URL에 안 보임 (그래도 HTTPS 필수!)                           │
└─────────────────────────────────────────────────────────────────┘

5.2 멱등성 (Idempotency)

┌─────────────────────────────────────────────────────────────────┐
│                         멱등성이란?                              │
│                                                                   │
│  "같은 요청을 여러 번 해도 결과가 같다"                          │
│                                                                   │
│  GET /users/1  (10번 호출)                                       │
│  └── 매번 같은 사용자 정보 반환 ✅ 멱등                         │
│                                                                   │
│  DELETE /users/1  (10번 호출)                                    │
│  └── 첫 번째: 삭제됨                                            │
│  └── 두 번째~: 이미 없음 (404)                                  │
│  └── 결과는 같음 (사용자 없음) ✅ 멱등                          │
│                                                                   │
│  PUT /users/1 {name: "Kim"}  (10번 호출)                         │
│  └── 매번 같은 상태로 덮어씀 ✅ 멱등                            │
│                                                                   │
│  POST /users {name: "Kim"}  (10번 호출)                          │
│  └── 사용자 10명 생성됨! ❌ 비멱등                              │
│                                                                   │
│  왜 중요?                                                        │
│  └── 네트워크 오류로 재시도할 때                                │
│  └── 멱등하면 안전하게 재시도 가능                              │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

6. 현대 프론트엔드에서의 사용

┌─────────────────────────────────────────────────────────────────┐
│            SPA (React/Vue) + REST API 시대                       │
│                                                                   │
│  과거 (MPA):                                                     │
│  ┌────────────────────────────────────────────────────────┐     │
│  │  브라우저                          서버                 │     │
│  │    │  GET /page.html                │                   │     │
│  │    │───────────────────────────────►│                   │     │
│  │    │◄─── 전체 HTML 페이지 ──────────│                   │     │
│  │    │                                │                   │     │
│  │    │  POST /form (폼 제출)          │                   │     │
│  │    │───────────────────────────────►│                   │     │
│  │    │◄─── 새 HTML 페이지 (리다이렉트)│                   │     │
│  └────────────────────────────────────────────────────────┘     │
│                                                                   │
│  현재 (SPA):                                                     │
│  ┌────────────────────────────────────────────────────────┐     │
│  │  React App                         API 서버            │     │
│  │    │  GET /api/users                │                   │     │
│  │    │───────────────────────────────►│                   │     │
│  │    │◄─── JSON 데이터 ───────────────│                   │     │
│  │    │                                │                   │     │
│  │    │  POST /api/users (새 사용자)   │                   │     │
│  │    │───────────────────────────────►│                   │     │
│  │    │◄─── JSON 응답 ─────────────────│                   │     │
│  │    │                                │                   │     │
│  │    │  PUT /api/users/1 (수정)       │                   │     │
│  │    │───────────────────────────────►│                   │     │
│  │    │◄─── JSON 응답 ─────────────────│                   │     │
│  │    │                                │                   │     │
│  │    │  DELETE /api/users/1 (삭제)    │                   │     │
│  │    │───────────────────────────────►│                   │     │
│  │    │◄─── JSON 응답 ─────────────────│                   │     │
│  └────────────────────────────────────────────────────────┘     │
│                                                                   │
│  → 페이지 새로고침 없이 데이터만 주고받음                       │
│  → 모든 HTTP 메서드를 의미에 맞게 사용                          │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

프론트엔드 코드 예시

// React에서 API 호출
const api = {
    // 조회 - GET
    getUsers: () => fetch('/api/users'),
    getUser: (id) => fetch(`/api/users/${id}`),

    // 생성 - POST
    createUser: (data) => fetch('/api/users', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data)
    }),

    // 수정 - PUT
    updateUser: (id, data) => fetch(`/api/users/${id}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data)
    }),

    // 삭제 - DELETE
    deleteUser: (id) => fetch(`/api/users/${id}`, {
        method: 'DELETE'
    })
};

7. FastAPI 실제 예시

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI()

# 데이터 모델
class User(BaseModel):
    name: str
    email: str

# 임시 DB
users_db = {}

# GET - 조회 (데이터 변경 없음)
@app.get("/users")
def get_users():
    """모든 사용자 목록 반환"""
    return list(users_db.values())

@app.get("/users/{user_id}")
def get_user(user_id: int):
    """특정 사용자 조회"""
    if user_id not in users_db:
        raise HTTPException(status_code=404, detail="User not found")
    return users_db[user_id]

# POST - 생성 (새 리소스 만듦)
@app.post("/users")
def create_user(user: User):
    """새 사용자 생성"""
    user_id = len(users_db) + 1
    users_db[user_id] = {"id": user_id, **user.dict()}
    return users_db[user_id]

# PUT - 전체 수정 (덮어쓰기)
@app.put("/users/{user_id}")
def update_user(user_id: int, user: User):
    """사용자 정보 전체 수정"""
    if user_id not in users_db:
        raise HTTPException(status_code=404, detail="User not found")
    users_db[user_id] = {"id": user_id, **user.dict()}
    return users_db[user_id]

# DELETE - 삭제
@app.delete("/users/{user_id}")
def delete_user(user_id: int):
    """사용자 삭제"""
    if user_id not in users_db:
        raise HTTPException(status_code=404, detail="User not found")
    del users_db[user_id]
    return {"message": "User deleted"}

8. 정리

┌─────────────────────────────────────────────────────────────────┐
│                        핵심 정리                                 │
│                                                                   │
│  전통적 이해 (여전히 유효):                                      │
│  ├── GET = 페이지/데이터 가져오기                                │
│  └── POST = 폼 데이터 전송                                       │
│                                                                   │
│  현대적 의미 (RESTful API):                                      │
│  ├── GET    = Read   (조회)                                      │
│  ├── POST   = Create (생성)                                      │
│  ├── PUT    = Update (전체 수정)                                 │
│  ├── PATCH  = Update (부분 수정)                                 │
│  └── DELETE = Delete (삭제)                                      │
│                                                                   │
│  핵심 차이:                                                      │
│  ┌──────────┬────────────────────────────────────────────────┐  │
│  │ GET      │ URL에 데이터, 캐싱 가능, 멱등, 안전            │  │
│  │ POST     │ Body에 데이터, 캐싱 불가, 비멱등, 비안전       │  │
│  │ PUT      │ Body에 데이터, 멱등 (같은 요청 = 같은 결과)    │  │
│  │ DELETE   │ 멱등 (여러 번 삭제해도 결과 같음)              │  │
│  └──────────┴────────────────────────────────────────────────┘  │
│                                                                   │
│  FastAPI 데코레이터:                                             │
│  @app.get/post/put/delete("/path")                               │
│  = "이 HTTP 메서드 + 이 경로로 오면 이 함수 실행"               │
│                                                                   │
└─────────────────────────────────────────────────────────────────┘

관련 키워드

HTTP 메서드, GET, POST, PUT, DELETE, PATCH, REST, RESTful API, CRUD, 멱등성, FastAPI, 라우팅