인공지능 개발자 수다(유튜브 바로가기) 자세히보기

Fastapi

[FastAPI] API의 Output (9)

Suda_777 2025. 1. 19. 19:11

목차

    반응형

     

    1. API의 Output

    API의 Output에는 어떠한 내용이 담겨있을까?

    데이터의 결과와 상태에 대한 데이터가 담겨 있다.

    구체적으로는 아래와 같다.

    • Pydantic (Response Model)
      • FastAPI는 Pydantic 모델을 사용하여 응답 데이터 구조를 정의
      • 클라이언트가 받을 데이터의 형태를 명확히 규정하고, 필요에 따라 필드 제한(예: 특정 필드만 출력)
    • Json 데이터
      • FastAPI는 기본적으로 JSON 포맷으로 응답을 반환한다.
    • HTTP 상태 코드
      • 응답 상태 코드는 요청이 성공했는지, 실패했는지, 그리고 실패 이유가 무엇인지 클라이언트에 알려줌

    결론적으로 Json 형태로 만들거나, Pydantic 형태로 만들고

    데이터와 상태코드를 담아 보내면 된다.

     


    2. 상태 코드

    2.1. 상태 코드 종류

    1xx: Informational (정보)

    • 요청이 수신되었고 처리가 진행 중

    2xx: Success (성공)

    • 200 OK: 요청이 성공적으로 처리됨.
    • 201 Created: 새로운 리소스가 성공적으로 생성됨.
    • 204 No Content: 요청이 성공했지만 응답 본문에 데이터가 없음.

    3xx: Redirection (리다이렉션)

    요청을 완료하려면 클라이언트가 추가 작업을 수행해야 함.

    • 301 Moved Permanently: 리소스가 영구적으로 다른 URL로 이동됨.
    • 302 Found: 리소스가 임시적으로 다른 URL에 있음.
    • 304 Not Modified: 캐시된 리소스를 사용할 수 있음.

    4xx: Client Error (클라이언트 오류)

    클라이언트의 요청에 문제가 있을 때 사용.

    • 400 Bad Request: 잘못된 요청.
    • 401 Unauthorized: 인증이 필요함.
    • 403 Forbidden: 요청이 허용되지 않음.
    • 404 Not Found: 요청한 리소스를 찾을 수 없음.
    • 422 Unprocessable Entity: 요청 데이터가 올바르지 않음.

    5xx: Server Error (서버 오류)

    서버가 요청 처리 중에 문제를 겪었을 때 사용.

    • 500 Internal Server Error: 서버 내부 오류.
    • 502 Bad Gateway: 잘못된 게이트웨이. (업스트림 서버의 문제, 요청을 처리하는 최종 서버)
    • 503 Service Unavailable: 서버가 일시적으로 요청을 처리할 수 없음
    • 504 Gateway Timeout: 게이트웨이가 시간 초과로 응답하지 못함

     

    2.2. FastAPI에서의 성공시 상태 코드

    • get
      • 200
    • post
      • 201 : 새로운 리소스 생성 시 201을 사용 하는 것이 표준
    • put/patch/delete
      • 200: 수정된 리소스를 반환할 때
      • 204: 성공했지만 응답 본문이 필요 없을 때

     

    2.3. 상태코드 설정 방법

    API가 성공 했을 때: 데코레이터의 매개변수에 status_code를 넣어준다.

    status_code를 설정하지 않으면 기본 값은 200 이다.

    class UserResponse(BaseModel):
        id: int
        name: str
        email: str
    
    @app.get("/user/{user_id}", response_model=UserResponse, status_code=201)
    async def get_user(user_id: int):
        return UserResponse(id=user_id, name="Alice", email="alice@example.com")

     

    API가 실패 했을 때 : HTTPException 에서 설정

    @app.post("/calculate")
    async def calculate(a: int, b: int):
        if a < 0 or b < 0:  # 입력값 검증
            raise HTTPException(status_code=422, detail="Inputs must be non-negative")
        
        try:
            result = a / b
        except ZeroDivisionError:
            raise HTTPException(status_code=400, detail="Division by zero is not allowed")
        
        return {"result": result}

    3. Json 응답

    3.1. 딕셔너리 사용

    가장 간편한 방법

    @app.get("/simple")
    async def simple_response():
        return {"message": "Hello, World!"}

     

    3.2. JSONResponse

    상태 코드, 응답 헤더, media_type 등을 제어

    • content: 딕셔너리 형태의 데이터
    • status_code: 코드번호
    @app.get("/custom")
    async def custom_response():
        data = {"message": "Custom response"}
        return JSONResponse(content=data,
        	status_code=201,
            headers={"X-Custom-Header": "CustomValue"},
            media_type="text/plain")

     

    쿠키도 추가할 수 있음

    @app.get("/set-cookie")
    async def set_cookie():
        response = JSONResponse(content={"message": "Cookie set"})
        response.set_cookie(key="my_cookie", value="cookie_value", httponly=True)
        return response

    4. Pydantic 모델 Response

    가장 추천되는 방법이다.

    @app.get() 의 파라미터로, response_model에 반환할 타입을 넣어준다.

    FastAPI는 자동으로 Pydantic 모델을 JSON으로 변환해 클라이언트에게 전송.

    class UserResponse(BaseModel):
        id: int
        name: str
        email: str
    
    @app.get("/user/{user_id}", response_model=UserResponse, status_code=201)
    async def get_user(user_id: int):
        return UserResponse(id=user_id, name="Alice", email="alice@example.com")

     


    5. Streaming Response

    Json 데이터를 스트리밍 형태로 return 한다.

    StreamingResponse 를 사용한다.

    from fastapi.responses import StreamingResponse
    import json
    
    @app.get("/stream-json")
    async def stream_json():
        def generate_data():
            yield json.dumps({"part": 1}) + "\n"
            yield json.dumps({"part": 2}) + "\n"
    
        return StreamingResponse(generate_data(), media_type="application/json")
    반응형