본문으로 건너뛰기
백엔드 기초집: 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) 미완료 상태