본문으로 건너뛰기
백엔드 기초집: Python FastAPILESSON 15

테이블 모델과 CRUD(Create, Read)

난이도초급
예상 시간35분
선수지식이전 강의

15강. 테이블 모델과 CRUD(Create, Read)

1. 이번 강의에서 해결할 문제

API가 반환한 기록이 아직 데이터베이스에 남지 않습니다. ORM 테이블을 만들고 POST와 GET을 실제 Session 작업으로 바꿉니다.

2. 학습 목표

3. 핵심 개념

ORM 인스턴스는 처음에는 Python 객체이며 Session에 add한 뒤 commit해야 DB 트랜잭션이 확정됩니다. refresh는 DB가 만든 id와 기본값을 다시 읽습니다. 조회는 SQLAlchemy 2.x의 select(Model) 문장을 실행하고 scalar 결과를 사용합니다.

4. 단계별 코드 예시

파일 경로: game-ranking-api/app/models/record.py

app/models/record.py
from datetime import datetime

from sqlalchemy import DateTime, String, func
from sqlalchemy.orm import Mapped, mapped_column

from app.database import Base


class GameRecord(Base):
__tablename__ = "game_records"

id: Mapped[int] = mapped_column(primary_key=True)
game_name: Mapped[str] = mapped_column(String(80), index=True)
score: Mapped[int]
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())

파일 경로: game-ranking-api/app/routers/records.py

app/routers/records.py
from typing import Annotated

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy import select
from sqlalchemy.orm import Session

from app.database import get_db
from app.models.record import GameRecord
from app.schemas.record import RecordCreate, RecordRead

router = APIRouter(prefix="/records", tags=["records"])
DbSession = Annotated[Session, Depends(get_db)]


@router.post("", response_model=RecordRead, status_code=status.HTTP_201_CREATED)
def create_record(payload: RecordCreate, db: DbSession) -> GameRecord:
record = GameRecord(**payload.model_dump())
db.add(record)
db.commit()
db.refresh(record)
return record


@router.get("", response_model=list[RecordRead])
def list_records(db: DbSession) -> list[GameRecord]:
return list(db.scalars(select(GameRecord).order_by(GameRecord.id.desc())))


@router.get("/{record_id}", response_model=RecordRead)
def get_record(record_id: int, db: DbSession) -> GameRecord:
record = db.get(GameRecord, record_id)
if record is None:
raise HTTPException(status_code=404, detail="기록을 찾을 수 없습니다")
return record

파일 경로: game-ranking-api/app/main.py

app/main.py
from fastapi import FastAPI

from app.database import Base, engine
from app.models import record # metadata에 모델 등록
from app.routers import records

Base.metadata.create_all(bind=engine)
app = FastAPI(title="Game Ranking API")
app.include_router(records.router)

실행 위치: game-ranking-api/

python -m uvicorn app.main:app --reload
Invoke-RestMethod -Method Post http://127.0.0.1:8000/records -ContentType 'application/json' -Body '{"game_name":"Rule Break","score":1200}'
Invoke-RestMethod http://127.0.0.1:8000/records

5. 코드가 동작하는 이유

모델 import로 Base metadata에 테이블이 등록되고 create_all이 학습용 테이블을 만듭니다. POST가 검증된 payload로 ORM 객체를 만든 뒤 commit합니다. 응답 모델의 from_attributes=True가 ORM 속성을 JSON으로 읽습니다.

6. 자주 하는 실수와 해결법

7. 직접 실습

8. 이해 점검 질문 3개

9. 핵심 요약

MINI QUIZ

테이블 모델과 CRUD(Create, Read) 미니 퀴즈

선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.

0 / 2
  1. 문제 1“테이블 모델과 CRUD(Create, Read)” 실습 결과를 해석하는 올바른 기준은 무엇인가요?
  2. 문제 2‘모델을 import하기 전에 create_all합니다.’ 실수를 판단할 때 “테이블 모델과 CRUD(Create, Read)” 강의가 제시한 기준은 무엇인가요?
LESSON STATUS

학습을 마쳤나요?

직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.

15강. 테이블 모델과 CRUD(Create, Read) 미완료 상태