HTTP 메서드와 FastAPI 데코레이터
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, 라우팅