백엔드 기초집: 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
0 / 2테이블 모델과 CRUD(Create, Read) 미니 퀴즈
선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.
LESSON STATUS
15강. 테이블 모델과 CRUD(Create, Read) 미완료 상태학습을 마쳤나요?
직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.