안녕하세요! 오늘은 FastAPI 학습 5일차입니다.
지난 시간까지 메모리상의 리스트(items = [])를 가지고 놀았다면, 오늘은 진짜 데이터베이스를 연동해서 영구적으로 데이터를 저장하는 방법(SQLAlchemy)과, FastAPI의 킬러 기능인 비동기 프로그래밍(Async)에 대해 알아보겠습니다.

PUT과 DELETE까지 구현해서 완벽한 REST API를 만듭니다.async, await가 도대체 뭔지, 왜 빠른지 직접 눈으로 확인합니다.

우리는 지난 시간에 PATCH를 배웠죠. 그런데 PUT도 수정을 의미합니다. 차이가 뭘까요?
| 메소드 | 의미 | 비유 | 특징 |
|---|---|---|---|
| PUT | 전체 대체 (Replace) | "이 상자, 새 상자로 통째로 바꿔주세요." | 모든 필드 정보를 다 줘야 함 (필수) |
| PATCH | 부분 수정 (Update) | "상자 이름만 유성매직으로 고쳐주세요." | 바꾸고 싶은 필드만 주면 됨 (선택) |
코드 예시 (PUT):
@app.put("/items/{item_id}", response_model=ItemResponse)
def replace_item(item_id: int, item_request: ItemReplaceUpdateRequest, db: Session = Depends(get_db)):
# ... (조회 로직) ...
# 묻지도 따지지도 않고 덮어씌우기
item.name = item_request.name
item.price = item_request.price
db.add(item)
db.commit()
db.refresh(item)
return item



이제 fake_db = {} 따위는 버립니다. SQLAlchemy ORM을 사용하면 SQL 쿼리문(SELECT * FROM...)을 몰라도 파이썬 클래스처럼 데이터를 다룰 수 있습니다.
db.add(item): "이거 DB에 내보낼 준비 해!" (장바구니 담기)db.commit(): "진짜 저장해!" (결제 완료 - DB 반영)db.refresh(item): "방금 저장된 거 DB에서 다시 가져와!" (새로고침 - ID 등 자동생성 값 확인)
@app.post("/items", status_code=201)
def create_item(item_request: ItemCreateRequest, db: Session = Depends(get_db)):
# 1. ORM 객체 만들기
new_item = Item(name=item_request.name, price=item_request.price)
# 2. 세션에 추가하고 커밋
db.add(new_item)
db.commit()
# 3. 최신 정보 로드 (ID가 생성됨)
db.refresh(new_item)
return new_item

삭제는 더 쉽습니다. delete 하고 commit 하면 끝!

@app.delete("/items/{item_id}", status_code=204)
def delete_item(item_id: int, db: Session = Depends(get_db)):
# 1. 삭제할 놈 찾기
statement = select(Item).where(Item.id == item_id)
item = db.execute(statement).scalars().first()
if item is None:
raise HTTPException(status_code=404, detail="Item not found")
# 2. 삭제하고 커밋
db.delete(item)
db.commit()
return # 204는 내용이 없으므로 빈 리턴

FastAPI가 "Fast"한 이유는 바로 이 비동기 처리 덕분입니다.

await), 끓는 동안 파 썰고 김치 꺼냄. (멀티태스킹 고수)웹 서비스에서는 DB 조회, 외부 API 호출 같은 "기다리는 시간(I/O Bound)"이 아주 많습니다. 비동기는 이 시간을 알뜰하게 씁니다.


async def: "이 함수는 비동기 함수(코루틴)야!"라고 선언.await: "이 작업 끝날 때까지 잠깐 제어권 넘길게(다른 일 하고 있어)."asyncio.gather(): 여러 비동기 작업을 한 번에 실행.가짜 잠자기(sleep) 실험
1. 동기 방식 (Sync)
import time
def sync_task():
time.sleep(2) # 2초 멈춤
# 실행
sync_task() # 2초
sync_task() # 2초
# 총 4초 걸림 🐢
2. 비동기 방식 (Async)
import asyncio
async def async_task():
await asyncio.sleep(2) # 2초 기다릴 동안 다른 일 함
async def main():
# 두 작업을 동시에 던짐!
await asyncio.gather(async_task(), async_task())
# 실행
asyncio.run(main())
# 총 2초 걸림 (...) 🐇
결과: 비동기 처리를 하면 I/O 대기 시간이 겹쳐져서 전체 실행 시간이 획기적으로 줄어듭니다!
오늘 우리는 SQLAlchemy를 통해 코드를 데이터베이스와 연결하는 강력한 기술을 익혔고, 비동기 프로그래밍을 통해 서버의 성능을 극한으로 끌어올릴 준비를 마쳤습니다.

PUT vs PATCH 구분하기db.add, db.commit, db.refresh 삼박자 이해하기db.delete로 데이터 삭제하기async와 await로 효율적인 비동기 코드 작성하기다음 시간에는 이 비동기 기술을 데이터베이스에도 적용하는 방법과 기능 고도화를 진행해보겠습니다. 오늘도 고생 많으셨습니다! 👋