Skip to content

제3장 3.4: 우주선 CRUD 작업

학습 시간: 1시간


1. CRUD: 우주 임무 관리의 전체 주기

지금까지는 데이터만 읽었습니다(Read). 그러나 진정한 비행 통제 센터는 모든 것을 할 수 있어야 합니다:

  • Create (생성): 새로운 위성을 궤도에 진입시킵니다.
  • Read (읽기): 기존 우주선의 상태를 요청합니다.
  • Update (업데이트): 궤도를 수정하거나 소프트웨어를 업데이트합니다.
  • Delete (삭제): 오래된 위성을 궤도에서 이탈시킵니다.

이 네 가지 작업인 CRUD는 대부분의 API의 기본을 이룹니다. 이 장에서는 우리 함대 관리를 위한 완전한 주기를 구현할 것입니다.


2. Create: 새로운 우주선 발사 (POST)

새로운 우주선을 생성하기 위해 POST 메서드를 사용할 것입니다. 새로운 우주선에 대한 데이터는 요청 본문에 JSON 형식으로 전달됩니다.

단계 1: 들어오는 데이터를 위한 새로운 Pydantic 모델 생성 새로운 모델이 왜 필요할까요? 우주선을 생성할 때 id를 모르기 때문입니다. id는 서버가 할당해야 합니다.

이 모델을 main.py에 추가하세요:

# main.py
from pydantic import BaseModel, Field

class SpaceshipCreate(BaseModel):
    """새로운 우주선 생성을 위한 모델 (ID 없음)."""
    name: str = Field(..., min_length=3, max_length=50)
    type: str
    launch_year: int = Field(..., gt=1950)
    status: str
이 모델은 Spaceship 모델과 거의 동일하지만, 들어오는 데이터의 유효성 검사에 사용될 것입니다.

단계 2: POST /spaceships 엔드포인트 구현

# main.py
import random # 파일 상단에 이 임포트를 추가하세요

# ... 나머지 코드 ...

@app.post("/spaceships", response_model=Spaceship, status_code=201)
def create_spaceship(ship: SpaceshipCreate):
    """
    레지스트리에 새로운 우주선을 추가합니다.
    """
    # 우주선을 위한 새롭고 고유한 ID를 생성합니다.
    new_id = max(db_spaceships.keys() or [0]) + 1

    # 전체 Spaceship 모델에 해당하는 우주선 객체를 생성합니다.
    new_ship = Spaceship(id=new_id, **ship.dict())

    # 우리의 "데이터베이스"에 저장합니다.
    db_spaceships[new_id] = new_ship.dict()

    return new_ship
설명:

  • @app.post(...): POST 요청을 위한 데코레이터를 사용합니다.
  • status_code=201: 성공적으로 생성될 경우 201 Created 상태를 반환하도록 지정합니다.
  • ship: SpaceshipCreate: 여기에 마법이 있습니다! FastAPI는 요청 본문(JSON)을 자동으로 가져와 SpaceshipCreate 모델에 따라 유효성을 검사한 다음, ship 객체로 함수에 전달합니다.
  • new_id = ...: 새로운 ID를 생성하기 위한 간단한 로직입니다.
  • **ship.dict(): 수신된 ship 모델의 데이터를 전체 모델로 "언팩"합니다.
  • response_model=Spaceship: 응답은 id를 포함하여 전체 모델에 따를 것입니다.

3. Update: 코스 수정 (PUT)

기존 리소스를 완전히 업데이트하려면 PUT 메서드가 사용됩니다.

PUT /spaceships/{ship_id} 엔드포인트 구현:

# main.py
from fastapi import FastAPI, HTTPException # 임포트를 업데이트하세요

# ... 나머지 코드 ...

@app.put("/spaceships/{ship_id}", response_model=Spaceship)
def update_spaceship(ship_id: int, ship_update: SpaceshipCreate):
    """
    우주선 데이터를 완전히 업데이트합니다.
    """
    if ship_id not in db_spaceships:
        raise HTTPException(status_code=404, detail="우주선이 발견되지 않았습니다.")

    updated_ship = Spaceship(id=ship_id, **ship_update.dict())
    db_spaceships[ship_id] = updated_ship.dict()

    return updated_ship

  • ship_update: SpaceshipCreate: 들어오는 데이터의 유효성 검사를 위해 다시 이 모델을 사용합니다.
  • HTTPException: 해당 id를 가진 우주선이 발견되지 않으면, FastAPI의 표준 예외를 "던져" 아름다운 404 코드의 JSON 응답으로 변환됩니다.

4. Delete: 궤도 이탈 (DELETE)

리소스를 삭제하려면 DELETE 메서드가 사용됩니다. 일반적으로 이러한 엔드포인트는 응답 본문을 반환하지 않습니다.

DELETE /spaceships/{ship_id} 엔드포인트 구현:

# main.py
from fastapi import FastAPI, HTTPException, Response, status # 임포트를 업데이트하세요

# ... 나머지 코드 ...

@app.delete("/spaceships/{ship_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_spaceship(ship_id: int):
    """
    레지스트리에서 우주선을 삭제합니다.
    """
    if ship_id not in db_spaceships:
        raise HTTPException(status_code=404, detail="우주선이 발견되지 않았습니다.")

    del db_spaceships[ship_id]

    # 204 상태로 빈 응답을 반환합니다.
    return Response(status_code=status.HTTP_204_NO_CONTENT)

  • status_code=status.HTTP_204_NO_CONTENT: 명시적으로 204 No Content 상태를 지정합니다.
  • del db_spaceships[ship_id]: 사전에서 항목을 삭제합니다.
  • return Response(...): 삭제된 객체에 대한 데이터가 클라이언트에 필요 없으므로 빈 응답을 반환합니다.

5. /docs에서 전체 주기 테스트

uvicorn이 재시작되었을 것입니다.

  1. http://127.0.0.1:8000/docs를 엽니다. 이제 완전한 CRUD 작업 세트를 갖게 되었습니다!
  2. POST: POST /spaceships 엔드포인트를 확장하고 "Try it out"을 클릭한 다음, JSON 본문을 작성하고 (예: "제임스 웹 우주 망원경" 생성) "Execute"를 클릭합니다. 새로운 망원경 데이터와 함께 201 응답을 받아야 합니다.
  3. GET: 이제 GET /spaceships를 실행합니다. 목록에 새로운 망원경이 나타나야 합니다.
  4. PUT: 새로운 망원경의 ID를 사용하여 PUT /spaceships/{ship_id}를 통해 데이터를 업데이트합니다. 예를 들어, 상태를 변경합니다.
  5. DELETE: 동일한 ID를 사용하여 DELETE /spaceships/{ship_id}를 통해 망원경을 삭제합니다. 204 상태의 빈 응답을 받아야 합니다.
  6. 확인: 망원경이 목록에서 삭제되었는지 확인하려면 GET /spaceships를 다시 실행합니다.

복습 퀴즈

1. 새로운 리소스를 생성하는 데 사용되는 HTTP 메서드는 무엇입니까?

2. `DELETE` 작업에 대한 표준 성공 상태 코드는?

3. FastAPI는 POST 요청 본문에서 데이터를 어떻게 받습니까?

4. `raise HTTPException(status_code=404)`는 다음을 위해 사용됩니다:

5. 리소스 생성을 위해 (`POST`) 별도의 `SpaceshipCreate` 모델을 생성한 이유는 무엇입니까?


🚀 장 요약:

당신은 완전한 CRUD 주기를 구현하여 당신의 API를 단순한 "정보판"에서 완전한 함대 제어 센터로 탈바꿈시켰습니다!

  • Create: POST /spaceships 새로운 기체 출시용.
  • Read: GET /spaceshipsGET /spaceships/{id} 데이터 획득용.
  • Update: PUT /spaceships/{id} 임무 업데이트용.
  • Delete: DELETE /spaceships/{id} 기체 폐기용.

당신의 함대는 완벽하게 통제됩니다! 다음 장에서는 FastAPI가 우리를 위해 상세한 "작동 지침서" — 대화형 Swagger 문서를 자동으로 생성하는 방법을 살펴보겠습니다.

📌 확인:

  • 5개의 모든 엔드포인트(GET (2), POST, PUT, DELETE)가 /docs에서 보이고 작동합니다.
  • 리소스를 성공적으로 생성, 읽기, 업데이트 및 삭제할 수 있습니다.
  • 존재하지 않는 ID를 요청하면 404 오류가 반환됩니다.

⚠️ 오류가 발생하면:

  • NameError: HTTPException, Response, status를 임포트했는지 확인하세요.
  • KeyError: 아마도 이미 삭제된 ID에 접근하려고 시도 중일 수 있습니다.
  • PUT 또는 POST 작업이 잘못된 경우: 함수 인수에 올바른 Pydantic 모델(SpaceshipCreate)을 사용하고 있는지 확인하세요.