콘텐츠로 이동

앱 개요: AI 요약 Todo

이번 섹션에서는 AI 요약 Todo 앱을 처음부터 끝까지 직접 만든다. ML 모델이 핵심이 아니라, 실제 웹 서비스가 어떻게 연결되는지 — 프론트엔드, 백엔드, DB, 프록시 — 그 배선(wiring)을 경험하는 것이 목표다.

  1. 할 일 생성 — 제목과 메모를 입력해 새 Todo를 추가할 수 있다.
  2. 목록 조회 — 모든 Todo를 최신순으로 목록에서 확인할 수 있다.
  3. 완료 토글 — 체크박스를 클릭해 완료/미완료를 전환할 수 있다.
  4. 메모 요약 — “요약” 버튼을 누르면 긴 메모가 2~3문장으로 요약된다.
  5. 삭제 — 더 이상 필요 없는 Todo를 삭제할 수 있다.
┌─────────────────────────────────────┐
│ AI 요약 Todo [+] │ ← 헤더 + 생성 버튼
├─────────────────────────────────────┤
│ ☐ FastAPI 공부하기 │ ← TodoItem
│ 메모: 섹션 07 다시 읽기... │
│ [요약] [삭제] │
├─────────────────────────────────────┤
│ ☑ nginx 설정 │ ← 완료 항목 (취소선)
│ [요약] [삭제] │
└─────────────────────────────────────┘
│ 제목: [____________] │ ← TodoForm
│ 메모: [____________] │
│ [추가] │
└─────────────────────────────────────┘

화면은 단일 페이지(SPA)이고 세 개의 영역으로 구성된다.

  • TodoList — 전체 목록 렌더링
  • TodoItem — 개별 항목 (토글, 요약, 삭제)
  • TodoForm — 새 항목 입력
MethodPath요청 Body응답
POST/api/todos{title, memo}Todo 객체
GET/api/todosTodo 배열
GET/api/todos/{id}Todo 객체
PATCH/api/todos/{id}/toggle업데이트된 Todo
DELETE/api/todos/{id}204 No Content
POST/api/todos/{id}/summary{summary: string}

모든 경로에 /api/ 접두사를 붙인다. nginx가 이 경로를 FastAPI로 프록시하고, 나머지는 React 빌드 파일로 서빙한다.

CREATE TABLE todos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
memo TEXT NOT NULL DEFAULT '',
done INTEGER NOT NULL DEFAULT 0, -- SQLite boolean
created_at TEXT NOT NULL -- ISO 8601
);

Python 측 SQLAlchemy 모델과 대응된다.

class Todo(Base):
__tablename__ = "todos"
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
memo: Mapped[str] = mapped_column(default="")
done: Mapped[bool] = mapped_column(default=False)
created_at: Mapped[str]
Browser
│ HTTP :80
nginx
├── / → React 빌드 정적 파일 (dist/)
│ SPA fallback: try_files $uri /index.html
└── /api/ → FastAPI (Uvicorn :8000)
└── SQLite (app.db)

브라우저는 nginx 포트 80 하나만 바라본다. React와 FastAPI가 같은 origin(localhost:80)에서 서빙되므로 CORS 설정이 필요 없다. 개발 중에만 React Dev Server(:5173)와 FastAPI(:8000)가 별도로 뜨고, 이때만 CORS를 허용한다.

ai-summary-todo/
├── backend/
│ ├── app/
│ │ ├── main.py # FastAPI 앱 진입점, CORS, lifespan
│ │ ├── db.py # SQLAlchemy 엔진, 세션, Base
│ │ ├── models.py # Todo ORM 모델
│ │ ├── schemas.py # Pydantic 요청/응답 스키마
│ │ ├── routes.py # API 라우터
│ │ └── summarizer.py # 요약 로직 (규칙 기반)
│ └── requirements.txt
├── frontend/
│ ├── src/
│ │ ├── App.tsx
│ │ ├── api.ts # fetch 래퍼, 타입 정의
│ │ ├── main.tsx
│ │ └── components/
│ │ ├── TodoList.tsx
│ │ ├── TodoItem.tsx
│ │ └── TodoForm.tsx
│ ├── index.html
│ ├── package.json
│ └── vite.config.ts
├── nginx/
│ └── nginx.conf
├── docker-compose.yml # 선택
└── README.md
레이어기술이유
프론트엔드React + TypeScript + Vite섹션 06에서 학습한 내용 활용
백엔드FastAPI + Uvicorn섹션 07에서 학습한 내용 활용
DBSQLite + SQLAlchemy 2.0섹션 08에서 학습한 내용 활용
프록시nginx섹션 04에서 학습한 리버스 프록시
AI 요약규칙 기반 (첫 N문장)외부 API 없이 동작, 나중에 LLM 교체 가능

다음 챕터에서 실제 프로젝트를 생성하고 개발 환경을 구성한다.