Python FastAPI - 1 [HTTP Methods]

LshDevLog·2026년 5월 1일

python

목록 보기
15/16
post-thumbnail
  • 이번 포스트에서는 FastAPI에서 사용하는 HTTP Methods를 기초부터 정리

  • FastAPI의 라우팅과 요청 처리는 Starlette 기반으로 동작함

    • Starlette
      • Python용 경량 ASGI 웹 프레임워크
      • FastAPI는 내부적으로 Starlette를 활용해서 웹 요청 처리, 라우팅, WebSocket, 미들웨어같은 기능을 수행함
      • FastAPI는 Starlette 위에 타입 검증(Pydantic), 자동 문서화(OpenAPI) 등을 추가한 프레임워크
  • HTTP Methods

    • 클라이언트가 서버 리소스에 어떤 동작을 원하는지 표현하는 요청 방식
    • 같은 URL이라도 메서드에 따라 의미가 달라짐
      • GET /users -> 사용자 조회
      • POST /users -> 사용자 생성
      • PUT /users/1 -> 사용자 전체 수정
      • PATCH /users/1 -> 사용자 일부 수정
      • DELETE /users/1 -> 사용자 삭제


GET

from fastapi import FastAPI

app = FastAPI()

@app.get("/users")
def get_users():
    return {"users": ["Kim", "Lee"]}
  • 서버의 데이터 조회
  • 특징
    • 서버 데이터를 바꾸지 않는 것이 원칙
    • 가장 많이 사용됨
    • 브라우저 주소 입력창도 GET 요청


POST

  • 새로운 데이터를 생성하거나 특정 작업 요청 시 사용
  • 회원가입, 로그인, 게시글 작성 등
  • 사용자가 입력한 데이터를 서버로 보낼 때 Query Parameter 혹은 JSON Body로 변환하여 전달

Query Parameter (쿼리 파라미터)

from fastapi import FastAPI

app = FastAPI()

@app.post("/users")
def create_user(name: str, age: int):
    return {
        "name": name,
        "age": age
    }
# 요청

POST /users?name=Kim&age=25
  • 쿼리 파라미터 방식
    • 간단한 파라미터 1~2개 받을 때 쉽고 편하게 사용
    • 구조화된 데이터 처리에 한계가 있음
    • 데이터가 많아지면 불편해지고 관리가 어려워짐
    • URL에 노출되므로 민감한 정보 전달에 부적합

JSON Body (요청 본문)

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class UserCreate(BaseModel):
    name: str
    age: int

@app.post("/users")
def create_user(user: UserCreate):
    return user
# 요청

{
  "name": "Kim",
  "age": 25
}
  • Pydantic 사용
    • JSON 자동 파싱
    • 타입 검증 자동 수행
    • 코드 가독성 좋음
    • 데이터 구조가 명확해짐
    • Swagger 문서 자동 생성됨
    • 쿼리 파라미터보다 JSON Body 사용이 더 권장됨

# 잘못된 요청

{
  "name": "Kim",
  "age": "hello"
}
422 Unprocessable Entity
  • 요청 데이터가 모델 조건과 맞지 않으면 FastAPI가 자동으로 422 오류를 반환


PUT

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class UserUpdate(BaseModel):
    name: str
    age: int
    email: str

@app.put("/users/{user_id}")
def update_user(user_id: int, user: UserUpdate):
    return {
        "user_id": user_id,
        "user": user
    }
  • 리소스를 전체 수정(덮어쓰기)할 때 사용
  • 전체 데이터를 다시 보내서 교체하는 방식
  • 전체를 교체하는 개념이므로 필요한 필드를 모두 보내는 것이 일반적임
  • Pydantic 모델을 사용하여 필드를 정의
  • 일부 데이터를 빼면 FastAPI가 422 오류 반환함

PUT /users/1
  • 1번 유저 전체 정보 수정

{
  "name": "Kim",
  "age": 25,
  "email": "kim@test.com"
}
  • 기존 데이터가 이러한데
# PUT /users/1 요청 Body
{
  "name": "Lee"
}
  • PUT은 전체 수정 의미이므로 일부 필드만 보내는 방식은 일반적으로 적합하지 않음


PATCH

from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional

app = FastAPI()

class UserUpdate(BaseModel):
    name: Optional[str] = None
    age: Optional[int] = None
    email: Optional[str] = None
    # name: str | None = None
    # age: int | None = None
    # email: str | None = None

@app.patch("/users/{user_id}")
def update_user(user_id: int, user: UserUpdate):
    update_data = user.model_dump(exclude_unset=True)

    return {
        "user_id": user_id,
        "update_data": update_data
    }
  • 기존 리소스 일부만 수정
  • typingOptional 사용
    • typing 모듈
      • 파이썬에서 타입을 명시하기 위한 모듈
    • Optional
      • PATCH는 일부 필드만 전달되기 때문에 필드가 없어도 에러가 발생하지 않도록 해야함
      • Optional은 값이 전달되지 않아도 에러가 발생하지 않도록 하기 위해 사용
      • name: Optional[str] = Nonestr이거나 None이 가능(에러 X)
      • name: str | None = None식으로도 작성 가능
    • Noneunset
      • None
        • null을 명시적으로 보냄
      • unset
        • 값을 아예 보내지 않음

update_data = user.model_dump(exclude_unset=True)
  • model_dump
    • Pydantic 모델을 Python dict로 변환
    • FastAPI에서는 요청 -> Pydantic 객체 변환되지만 실제 로직(DB 저장 등)은 dict 형태가 필요
    • exclude_unset
      • 사용자가 실제로 보낸 필드만 추출 (요청에 포함되지 않은 필드는 제외)
      • PATCH에서 부분 수정 시 불필요한 필드 덮어쓰기를 방지하기 위해 사용

PATCH /users/1
  • 요청
{
  "age": 30
}
  • age만 수정되고 name, email은 유지됨


DELETE

from fastapi import FastAPI
from fastapi import status
from fastapi.responses import Response

app = FastAPI()

@app.delete("/users/{user_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_user(user_id: int):
    return
  • 서버에 있는 리소스를 삭제할 때 사용
  • 보통 URL에 삭제 대상의 ID 포함 (Path Parameter)
  • Request Body 없이 사용하는 경우가 일반적
  • DELETE는 멱등성(idempotent)이 중요
    • 같은 DELETE 요청을 여러 번 보내도 최종적으로 리소스가 삭제된 상태라는 점은 동일
  • status 모듈
    • HTTP 상태 코드를 숫자 대신 의미 있는 상수 이름으로 사용할 수 있게 해주는 모듈

DELETE /users/1
  • 1번 유저 삭제

응답 형태

{
  "message": "deleted"
}
  • 메시지 반환

204 No Content
  • 상태 코드 반환 (권장)
  • DELETE는 보통 204 No Content를 사용하여 응답 Body없이 처리하는 것이 일반적이며 필요한 경우 메시지와 함께 반환하기도 함

0개의 댓글