ITADN
chanwoo040531/lecture · 文件
文件最后提交记录最后更新时间
该仓库无文件或尚未加载
README.md

Todo API 과제

Python과 FastAPI를 사용해 Todo 관리용 REST API를 구현합니다. Todo의 생성, 조회, 수정, 삭제 기능은 필수이며, 데이터는 SQLite에 저장합니다.

필수 기술

  • Python 3.12 이상
  • FastAPI
  • SQLite
  • Git / GitHub

ORM, 패키지 관리 도구, 프로젝트 구조는 자유롭게 선택합니다.

구현 방향

Todo에는 제목과 완료 여부가 포함되어야 합니다. 설명, 마감일, 우선순위, 태그, 검색, 페이지네이션, 인증 등의 기능은 자유롭게 추가할 수 있습니다.

API 경로와 응답 형식은 직접 설계하며, 적절한 HTTP 메서드와 상태 코드를 사용합니다. 잘못된 입력과 존재하지 않는 데이터에 대한 처리도 구현합니다.

Claude Code를 포함한 AI 코딩 도구는 자유롭게 사용할 수 있습니다. 제출 시에는 코드의 구조와 동작을 설명할 수 있어야 합니다.

README에는 실행 방법, 사용 기술, API 목록, 구현한 기능을 작성하고, GitHub 저장소 형태로 제출합니다.

실행 방법

데이터는 Render Postgres(무료 플랜)에 저장합니다. 실행 전 환경변수를 설정해야 합니다.

  • DATABASE_URL — 앱이 접속할 Postgres 연결 문자열 (로컬 개발 시 Render 대시보드의 External Database URL을 사용)
  • TEST_DATABASE_URL — 테스트 전용 접속 문자열. 운영 DB와 반드시 분리된 데이터베이스/스키마를 가리켜야 합니다 (테스트가 매번 TRUNCATE를 실행하므로, 운영 DB를 가리키면 데이터가 삭제됩니다)

두 값 모두 실제 접속 자격증명을 포함하므로 이 저장소에는 커밋하지 않습니다 (.env 등 로컬 파일로 관리).

export DATABASE_URL="postgresql://..."
uv sync
uv run uvicorn app.main:app --reload

서버 실행 후 http://localhost:8000 에서 정적 UI를, http://localhost:8000/docs 에서 API 문서를 확인할 수 있습니다.

테스트 실행:

export TEST_DATABASE_URL="postgresql://..."
uv run pytest

Render 무료 플랜 관련 주의사항

  • 무료 Postgres 인스턴스는 생성 후 30일이 지나면 만료/삭제됩니다. 학습/과제 목적 이상의 영구 운영에는 적합하지 않습니다.
  • 무료 Web Service는 일정 시간 요청이 없으면 슬립 상태가 되며, 이후 첫 요청은 응답이 느릴 수 있습니다.

사용 기술

  • Python 3.12+
  • FastAPI, Uvicorn
  • PostgreSQL (Render, psycopg 3, ORM 미사용)
  • bcrypt (비밀번호 해싱)
  • uv (패키지 관리)

배포

Render Web Service(무료 플랜, Singapore 리전)로 배포되어 있습니다: https://todo-api-d7dr.onrender.com

API 엔드포인트

MethodPath설명인증 필요
GET/health헬스 체크X
POST/todosTodo 생성X
GET/todosTodo 목록 조회X
GET/todos/{todo_id}Todo 단건 조회X
PUT/todos/{todo_id}Todo 수정X
DELETE/todos/{todo_id}Todo 삭제X
POST/signup회원가입X
POST/login로그인, 세션 쿠키 발급X
POST/logout로그아웃, 세션 무효화X
GET/me현재 로그인한 사용자 조회O

구현한 기능

  • Todo CRUD (제목/설명/완료 여부, 생성·수정 시각 자동 관리)
  • 이메일/비밀번호 기반 회원가입 (bcrypt로 비밀번호 해싱, 이메일 중복 시 409)
  • 세션 기반 로그인/로그아웃 — 자체 sessions 테이블에 토큰을 저장하고, 서명 없는 불투명 토큰을 httponly 쿠키로 발급하는 방식으로 구현 (Starlette SessionMiddleware/itsdangerous는 사용하지 않음)
  • app/static/index.html에 로그인/회원가입/로그아웃을 위한 정적 UI 추가
  • 잘못된 입력(빈 제목, 짧은 비밀번호, 잘못된 이메일 형식 등)과 존재하지 않는 리소스에 대한 422/404/401/409 처리

설계 노트

  • 이번 범위에서 /todos/* 엔드포인트에는 로그인을 강제하지 않습니다. 인증이 필요하도록 확장하려면 각 라우터에 Depends(get_current_user)를 추가하면 됩니다.
  • 로그인 쿠키는 로컬 HTTP 개발 환경 기준으로 secure=False로 설정되어 있습니다. HTTPS로 배포할 경우 app/main.pyset_cookie 호출에서 secure=True로 변경해야 합니다.