feat: 풀스택 할일관리 앱 구현 (통합 모달 + 간트차트)

- Backend: FastAPI + MongoDB + Redis (카테고리, 할일 CRUD, 파일 첨부, 검색, 대시보드)
- Frontend: Next.js 15 + Tailwind + React Query + Zustand
- 통합 TodoModal: 생성/수정 모달 통합, 탭 구조 (기본/태그와 첨부)
- 간트차트: 카테고리별 할일 타임라인 시각화
- TodoCard: 제목/카테고리/우선순위/태그/첨부 한줄 표시
- Docker Compose 배포 (Frontend:3010, Backend:8010, MongoDB:27021, Redis:6391)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jungwoo choi
2026-02-12 15:45:03 +09:00
parent b54811ad8d
commit 074b5133bf
81 changed files with 17027 additions and 19 deletions

View File

@ -1,17 +1,55 @@
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager
from datetime import datetime
app = FastAPI(title="API", version="1.0.0")
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
from app.config import get_settings
from app.database import connect_db, disconnect_db
@app.get("/health")
async def health_check():
return {"status": "healthy", "timestamp": datetime.now().isoformat()}
@asynccontextmanager
async def lifespan(app: FastAPI):
"""서버 시작/종료 이벤트: MongoDB + Redis 연결 관리"""
await connect_db()
yield
await disconnect_db()
def create_app() -> FastAPI:
settings = get_settings()
app = FastAPI(
title="todos2 API",
description="확장형 할일 관리 애플리케이션 API",
version="1.0.0",
lifespan=lifespan,
)
# CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 라우터 등록
from app.routers import todos, categories, tags, search, dashboard, uploads
app.include_router(todos.router)
app.include_router(categories.router)
app.include_router(tags.router)
app.include_router(search.router)
app.include_router(dashboard.router)
app.include_router(uploads.router)
# 헬스 체크
@app.get("/health", tags=["health"])
async def health_check():
return {"status": "healthy", "timestamp": datetime.now().isoformat()}
return app
app = create_app()