# repository.py
from sqlalchemy import select, delete
def delete_todo(session: Session, todo_id: int) -> None:
session.execute(delete(ToDo).where(ToDo.id == todo_id))
session.commit()
session.execute() 완전 이해하기
먼저 전체 맥락 이해하기
지금까지 배운 SQLAlchemy 조회 방법들
SQLAlchemy 실행 메서드 비교
| 메서드 | 용도 | 반환값 |
| session.scalars() | 조회 (여러 개) | 객체 목록 |
| session.scalar() | 조회 (한 개) | 객체 하나 |
| session.execute() | 뭐든 다 실행 | Result 객체 |
session.execute() 는 조회/추가/수정/삭제 전부 다 실행할 수 있는 만능 메서드
session.execute() 구조 분해
현재 코드 완전 분해
session.execute(delete(ToDo).where(ToDo.id == todo_id))
# ↑ ↑ ↑
# 실행해줘 무엇을? 어떤 조건으로?
# ToDo 삭제 id가 todo_id인 것만
자연어로 읽으면:
"ToDo 테이블에서 id가 todo_id인 행을 삭제하는 SQL을 실행"
내부적으로 어떤 SQL이 실행되냐면
실제 실행되는 SQL
# Python 코드
session.execute(delete(ToDo).where(ToDo.id == todo_id))
# SQLAlchemy가 자동으로 번역한 SQL
DELETE FROM todo WHERE todo.id = 1
# ↑
# todo_id 값
echo=True 설정 덕분에 콘솔에 이런 로그가 찍힌다.
scalars vs execute 차이
scalars vs execute 비교
# scalars → 조회 전용, 결과를 Python 객체로 바로 반환
todos = session.scalars(select(ToDo))
# [ToDo(id=1...), ToDo(id=2...)] ← 바로 객체 리스트
# execute → 만능, Result 객체 반환
result = session.execute(select(ToDo))
# <sqlalchemy.engine.result.ChunkedIteratorResult> ← Result 객체
# .scalars(), .fetchall() 등으로 꺼내야 함
# 삭제할 때는 반환값이 필요 없으니까 그냥 실행만
session.execute(delete(ToDo).where(ToDo.id == todo_id))
delete() 문법 더 이해하기
delete() 문법 구조
from sqlalchemy import delete
delete(ToDo) # ToDo 전체 삭제 (위험)
delete(ToDo).where(ToDo.id == 1) # id가 1인 것만 삭제
delete(ToDo).where(ToDo.is_done == True) # 완료된 것만 삭제
delete().where() 동작 흐름
delete(ToDo)
↓
"todo 테이블에서 삭제할 준비"
↓
.where(ToDo.id == todo_id)
↓
"id가 todo_id인 것만"
↓
session.execute()
↓
실제 SQL 실행
"DELETE FROM todo WHERE id = 1"
↓
session.commit()
↓
DB에 반영 완료
select / delete / update 비교
CRUD 각각 어떻게 쓰는지
from sqlalchemy import select, delete, update
# 조회 (Read)
session.scalars(select(ToDo).where(ToDo.id == 1))
# 삭제 (Delete)
session.execute(delete(ToDo).where(ToDo.id == 1))
# 수정 (Update)
session.execute(
update(ToDo)
.where(ToDo.id == 1)
.values(is_done=True)
)
# 추가 (Create) → execute 대신 add 사용
session.add(ToDo(contents="할일", is_done=False))
💡 핵심 요약:
session.execute() = SQL 구문을 실행하는 만능 메서드
delete(ToDo).where(조건) = 조건에 맞는 행 삭제 SQL 생성
session.execute() 만으로는 DB에 안 반영되고, session.commit() 까지 해야 실제 반영.
# main.py
# delete 성공 상태 코드 : 204
# 204는 응답 받는 body가 없기 때문에 return이 없거나 빈 return을 줘도 된다.
@app.delete("/todos/{todo_id}", status_code=204)
def delete_todo_handler(
todo_id: int,
session: Session = Depends(get_db),):
# 삭제하기 위해선 todo id가 유효한지 확인
todo: ToDo | None = get_todo_by_todo_id(session=session, todo_id=todo_id)
if not todo:
raise HTTPException(status_code=404, detail="Todo Not Fount")
delete_todo(session=session, todo_id=todo_id)
- 아이디를 먼저 조회를 해서 todo를 확인한 후 투두가 있으면 delete 요청을 하고 todo가 없으면 404를 리턴
- 204인 경우에는 별도로 return문을 적지 않아도 응답으로 반환할 데이터가 없기 때문에 먼저 처리를 해주면 에러를 발생시키고 그게 아닌 경우에는 데이터를 삭제해줄 수 있어 코드 가독성을 위해 에러문을 위로 처리(if no todo:)
swagger 확인


'FastAPI > 데이터베이스' 카테고리의 다른 글
| ORM 적용 - PATCH API (0) | 2026.06.25 |
|---|---|
| ORM 적용 - POST API (0) | 2026.06.24 |
| 파이참 - Refactoring (0) | 2026.06.16 |
| ORM 적용 - GET 단일 조회 API (0) | 2026.06.16 |
| ORM 적용 - HTTP Response 처리 (1) | 2026.06.14 |