HTTP 메서드와 FastAPI 데코레이터
TL;DR
- HTTP 메서드, GET, POST, PUT, DELETE, PATCH, REST, RESTful API, CRUD, 멱등성, FastAPI, 라우팅
- HTTP 메서드와 FastAPI 데코레이터를 알아두면 설계 판단과 구현 선택을 더 분명하게 할 수 있다.
- 원문 전체는 아래 상세 내용에 그대로 포함했다.
1. 개념
HTTP 메서드, GET, POST, PUT, DELETE, PATCH, REST, RESTful API, CRUD, 멱등성, FastAPI, 라우팅
2. 배경
HTTP 메서드와 FastAPI 데코레이터가 등장한 배경과 문제 상황을 이해하는 데 도움이 된다.
3. 이유
HTTP 메서드와 FastAPI 데코레이터를 알아두면 설계 판단과 구현 선택을 더 분명하게 할 수 있다.
4. 특징
HTTP 메서드와 FastAPI 데코레이터의 특징, 장단점, 적용 포인트를 원문에서 자세히 확인할 수 있다.
5. 상세 내용
HTTP 메서드와 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, 라우팅