FastAPI를 이용한 RESTful API 개발 가이드라인

data_jeong·2024년 4월 1일

슬픈팀장로그

목록 보기
2/2
post-thumbnail

API의 정의 및 원칙

  • 응용 프로그래밍 인터페이스(API)는 서로 다른 소프트웨어 애플리케이션이 통신하고 데이터를 교환할 수 있도록 해주는 매개체입니다.
  • API는 개발자가 소프트웨어 컴포넌트, 웹 서버 또는 서비스와 상호 작용하기 위해 따라야 할 규칙을 정의합니다.

현대 웹 개발에서 RESTful API가 중요한 이유

  • RESTful API는 대표적 상태 전송(REST) 아키텍처 스타일을 따르며,
    확장성, 상태 비저장성, 독립적인 요청 처리 능력을 강조합니다.

REST API와 RESTful API의 차이점

  • REST API는 REST 아키텍처 원칙을 따르는 API를 의미합니다.
  • RESTful API는 REST 원칙을 엄격하게 준수하는 API를 지칭하며, 상태를 저장하지 않고(GET, POST, PUT, DELETE 등의 메소드 사용), 리소스에 대한 요청을 처리합니다.

1. RESTful API 설계 원칙

1.1. 기본 설계 원칙

  • 자원(Resource)의 식별: URI는 정보의 자원을 식별해야 합니다. 예를 들어, 사용자 정보에 접근하는 URI는 /users와 같이 명사를 사용해야 합니다.
  • 자원에 대한 행위는 HTTP 메소드로 표현: GET(조회), POST(생성), PUT(수정), DELETE(삭제) 등을 사용합니다.

1.2. 엔드포인트 설계 예시

  • 사용자 정보 조회: GET /users
  • 사용자 정보 추가: POST /users
  • 사용자 정보 수정: PUT /users/{id}
  • 사용자 정보 삭제: DELETE /users/{id}

1.3. 상태 코드 약속

  • 200 OK: 요청 성공
  • 201 Created: 새로운 리소스 생성 성공
  • 400 Bad Request: 잘못된 요청
  • 404 Not Found: 리소스를 찾을 수 없음
  • 500 Internal Server Error: 서버 내부 오류

1.4. 추가 설계 가이드라인

리소스 버전 관리

  • 버전 관리: API의 변경을 관리하기 위해 URI에 버전을 명시합니다. 예: */api/v1/users는 API 버전 1의 사용자 리소스를 나타냅니다.

보안 고려 사항

  • HTTPS 사용: 데이터 전송 시 HTTPS를 사용하여 암호화를 제공합니다. 이는 데이터 무결성 및 기밀성 보장에 중요합니다.
  • 인증 및 권한 부여: 적절한 인증과 권한 부여 메커니즘을 구현하여 리소스에 대한 접근을 제어합니다. 예를 들어, OAuth, JWT 등을 활용할 수 있습니다.

명확한 리소스 식별과 행동 표현

  • 명확한 리소스 식별: URI를 통해 리소스와 해당 리소스에 수행할 수 있는 행동을 명확하게 식별합니다. /users는 사용자의 집합을, /users/{id}는 특정 사용자를 지칭합니다.
  • HTTP 메소드 활용: 리소스에 대한 행동은 적절한 HTTP 메소드를 통해 표현됩니다. GET은 조회, POST는 생성, PUT은 수정, DELETE는 삭제를 나타냅니다.

적절한 상태 코드 사용

  • 응답 상태 코드: 각 API 요청의 결과를 명확하게 나타내는 HTTP 상태 코드를 사용합니다. 200 OK, 201 Created, 400 Bad Request, 404 Not Found, 500 Internal Server Error 등이 흔히 사용됩니다.

2.1. 간단한 FastAPI 애플리케이션 예시

from fastapi import FastAPI, HTTPException

app = FastAPI()

@app.get("/users")
async def read_users():
    return [{"username": "user1"}, {"username": "user2"}]

@app.post("/users")
async def create_user(user: User):
    # 사용자 생성 로직
    return {"username": "new_user"}

@app.put("/users/{user_id}")
async def update_user(user_id: int, user: User):
    # 사용자 업데이트 로직
    return {"username": "updated_user"}

@app.delete("/users/{user_id}")
async def delete_user(user_id: int):
    # 사용자 삭제 로직
    return {"message": "User deleted"}

2.2. 에러 처리 예시

@app.get("/users/{user_id}")
async def read_user(user_id: int):
    if user_id not in users_database:
        raise HTTPException(status_code=404, detail="User not found")
    return {"username": "user1"}

3. 가이드라인과 잘 만들어진 RESTful API 예제

  1. 명확한 리소스 식별: 리소스와 행동을 명확하게 식별할 수 있는 URI를 사용합니다. 예: /users는 사용자의 집합을, /users/{id}는 특정 사용자를 지칭합니다.
  2. HTTP 메소드 활용: 리소스에 대한 행동(생성, 조회, 수정, 삭제)은 HTTP 메소드(GET, POST, PUT, DELETE)를 통해 표현합니다.
  3. 상태 코드를 통한 응답 정의: 요청의 성공 또는 실패를 명확하게 알려주는 HTTP 상태 코드를 사용합니다. 예: 200 OK, 201 Created, 404 Not Found.
  4. 버전 관리: API의 변경 사항을 관리하기 위해 버전을 명시합니다. 예: /api/v1/users.
  5. 보안 고려: HTTPS를 사용하여 데이터 전송 시 암호화를 제공하고, 인증과 권한 부여 메커니즘을 구현합니다

3.1. 잘 만들어진 RESTful API 예제

아래는 사용자 관리를 위한 RESTful API의 기본 CRUD 연산을 구현한 예제입니다.

from fastapi import FastAPI, HTTPException, Depends
from fastapi.security import OAuth2PasswordBearer
from pydantic import BaseModel
from typing import List, Dict

app = FastAPI()

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

class User(BaseModel):
    id: int
    name: str
    email: str

users: Dict[int, User] = {}

# 사용자 인증을 위한 간단한 예시 함수
def get_current_user(token: str = Depends(oauth2_scheme)):
    # 여기서는 단순화를 위해 토큰 검증을 생략합니다.
    # 실제 애플리케이션에서는 여기서 토큰을 검증하고 사용자를 식별하는 로직이 필요합니다.
    return {"user_id": token}

@app.post("/api/v1/users/", response_model=User)
def create_user(user: User):
    if user.id in users:
        raise HTTPException(status_code=400, detail="User already exists")
    users[user.id] = user
    return user

@app.get("/api/v1/users/", response_model=List[User])
def read_users(current_user: User = Depends(get_current_user)):
    return list(users.values())

@app.put("/api/v1/users/{user_id}", response_model=User)
def update_user(user_id: int, user: User, current_user: User = Depends(get_current_user)):
    if user_id not in users:
        raise HTTPException(status_code=404, detail="User not found")
    users[user_id] = user
    return user

@app.delete("/api/v1/users/{user_id}")
def delete_user(user_id: int, current_user: User = Depends(get_current_user)):
    if user_id not in users:
        raise HTTPException(status_code=404, detail="User not found")
    del users[user_id]
    return {"detail": "User deleted"}
  1. 명확한 리소스 식별과 버전 관리: URI를 사용하여 리소스를 명확하게 식별합니다(/api/v1/users/는 사용자의 집합을, /api/v1/users/{id}는 특정 사용자를 지칭). 또한, API의 버전(v1)을 URI에 포함시켜 API의 버전을 명시합니다.
  2. HTTP 메소드 활용: 리소스에 대한 행동(생성, 조회, 수정, 삭제)은 적절한 HTTP 메소드를 사용하여 표현합니다.
  3. 상태 코드를 통한 응답 정의: 각 작업의 성공 또는 실패를 명확하게 알려주는 상태 코드(200 OK, 201 Created, 404 Not Found 등)를 사용합니다.
  4. 보안 고려: OAuth2PasswordBearer를 사용하여 인증 메커니즘을 구현합니다. 이 예제에서는 간단한 토큰 기반 인증을 도입했습니다. 실제 애플리케이션에서는 이 토큰을 검증하여 사용자를 식별하는 추가 로직이 필요합니다.

4. RESTful API 문서화 및 테스트

FastAPI는 OpenAPI 스펙을 기반으로 한 자동 문서화 기능을 제공합니다.

4.1. 문서화 도구

Swagger UIReDoc은 FastAPI가 제공하는 두 가지 주요 문서화 도구입니다. 이 도구들을 통해 개발자와 사용자는 API의 엔드포인트, 가능한 요청 및 예상 응답에 대한 상세 정보를 쉽게 확인할 수 있습니다.

  • Swagger UI: FastAPI 서버를 실행한 후, 브라우저에서 /docs 경로로 이동하여 접근할 수 있습니다. Swagger UI는 API의 인터랙티브한 문서를 제공하며, 실제 API 요청을 보내고 응답을 테스트할 수 있는 기능을 지원합니다.
  • ReDoc: /redoc 경로를 통해 접근할 수 있으며, Swagger UI와 비슷하지만 다른 스타일의 문서화를 제공합니다. ReDoc은 API 문서를 좀 더 읽기 쉬운 형식으로 제공합니다.

4.2. 문서화 도구 사용 규칙

Swagger UI

  1. 엔드포인트 명세: 모든 API 엔드포인트는 Swagger UI를 통해 명세되어야 합니다. 이는 메소드, 파라미터, 요청 본문 및 예상 응답을 포함합니다.
  2. 실시간 테스트: 개발자는 Swagger UI의 테스트 기능을 활용하여 API를 실시간으로 테스트하고, 응답을 검증해야 합니다.
  3. 문서의 업데이트 유지: API의 변경 사항이 있을 때마다 Swagger 문서를 즉시 업데이트하여, 문서가 항상 최신 상태를 유지하도록 합니다.

ReDoc

  1. 읽기 쉬운 문서 제공: ReDoc을 사용하여 API 문서를 좀 더 읽기 쉬운 형식으로 제공하며, 비개발자가 이해하기 쉬운 설명을 추가합니다.
  2. 정적 문서화: ReDoc을 통해 생성된 API 문서는 프로젝트의 정적 웹사이트에 포함시켜 배포할 수 있습니다. 이를 통해 API의 소비자가 언제든지 접근 가능한 문서를 제공합니다.

4.3. 테스트 도구

  • Postman: 개발자가 API 엔드포인트에 대한 HTTP 요청을 보내고, 응답을 확인할 수 있게 해주는 인기 있는 도구입니다. 헤더, 바디, 쿼리 파라미터 등을 손쉽게 조작하며, 다양한 요청 메소드(GET, POST, DELETE, PUT 등)에 대한 지원이 가능합니다.

  • pytest: Python 기반의 테스트 프레임워크로, FastAPI 애플리케이션의 기능 및 통합 테스트를 자동화하기 위해 사용됩니다. pytest를 사용하여 API의 다양한 시나리오를 테스트하고, 예상치 못한 버그를 사전에 발견할 수 있습니다.

4.4. 테스트 도구 사용 규칙

  • Postman을 사용한 테스트:

    1. 테스트 케이스 작성: 각 API 엔드포인트에 대해 성공 및 실패 시나리오를 포함한 테스트 케이스를 작성합니다.
    2. 환경 설정: 개발, 스테이징, 프로덕션 등 다양한 환경에 대한 설정을 구성합니다.
    3. 공유 및 협업: 팀 내에서 Postman 컬렉션을 공유하여 모든 개발자가 동일한 테스트 케이스에 액세스하고 업데이트할 수 있도록 합니다.
  • pytest를 사용한 테스트

    1. 자동화된 테스트: pytest를 사용하여 API의 기능적 및 통합 테스트를 자동화합니다.
    2. 테스트 커버리지: pytest와 함께 테스트 커버리지 도구를 사용하여 코드 베이스 내 테스트되지 않은 영역을 식별합니다.

해당 글은 아래 글을 참조하여 작성한 글입니다
https://medium.com/@techworldwithmilan/rest-api-design-best-practices-2eb5e749d428

profile
데이터를 주력으로 하는 잡부입니다!

0개의 댓글