Files
Todo-Project/COMPREHENSIVE_GUIDE.md
Hyungi Ahn 761757c12e Initial commit: Todo Project with dashboard, classification center, and upload functionality
- 📱 PWA 지원: 홈화면 추가 가능한 Progressive Web App
- 🎨 M-Project 색상 스키마: 하늘색, 주황색, 회색, 흰색 일관된 디자인
- 📊 대시보드: 데스크톱 캘린더 뷰 + 모바일 일일 뷰 반응형 디자인
- 📥 분류 센터: Gmail 스타일 받은편지함으로 스마트 분류 시스템
- 🤖 AI 분류 제안: 키워드 기반 자동 분류 제안 및 일괄 처리
- 📷 업로드 모달: 데스크톱(파일 선택) + 모바일(카메라/갤러리) 최적화
- 🏷️ 3가지 분류: Todo(시작일), 캘린더(마감일), 체크리스트(무기한)
- 📋 체크리스트: 진행률 표시 및 완료 토글 기능
- 🔄 시놀로지 연동 준비: 메일플러스 연동을 위한 구조 설계
- 📱 반응형 UI: 모든 페이지 모바일 최적화 완료
2025-09-19 08:52:49 +09:00

28 KiB

📚 Todo Project 종합 개발 가이드

"Simple Todo, Smart Integration"
간결한 할일 관리 + 시놀로지 생태계 연동으로 완벽한 개인 생산성 도구


🎯 프로젝트 개요

목표

사진과 메모를 기반으로 한 간단한 일정관리 시스템 구축

핵심 기능

  • 입력: 사진(선택) + 텍스트 메모
  • 분류: GTD형 / 캘린더형 / 체크리스트형
  • 플랫폼: iOS + Apple Watch + 웹

시스템 환경

  • 배포 서버: Synology DS1525+
  • 개발 환경: Mac mini M4 Pro (macOS)
  • 네트워크: LG U+ 2.5G + Synology Router

핵심 가치

  • 즉시 접근: 바로 켜서 바로 쓸 수 있는 간편함
  • 🎯 간결함: 복잡하지 않은 직관적인 인터페이스
  • 🔗 스마트 연동: 시놀로지 캘린더/메일과 자동 동기화
  • 📱 어디서나: 폰, 컴퓨터에서 동일한 경험

🏗 시스템 아키텍처

볼륨 매핑 구조

Synology NAS:
/volume3/docker/todo-app/     # 시스템/컨테이너
├── docker-compose.yml
├── app/                      # 애플리케이션 코드
└── config/                   # 설정 파일

/volume1/todo-data/           # 데이터 저장
├── database/                 # DB 파일
├── uploads/images/           # 업로드 이미지
└── backups/                  # 백업

기술 스택

Backend:  FastAPI (Python) / PostgreSQL
Frontend: Vanilla JS + Alpine.js + Tailwind CSS
Database: PostgreSQL (포트: 5434)
Deployment: Docker + Docker Compose
Integration: CalDAV, SMTP, DSM API

전체 구조

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Frontend      │    │    Backend      │    │   Synology      │
│   (4000)        │◄──►│    (9000)       │◄──►│   Services      │
│                 │    │                 │    │                 │
│ • PWA Support   │    │ • FastAPI       │    │ • Calendar      │
│ • Offline Mode  │    │ • SQLAlchemy    │    │ • MailPlus      │
│ • Auto Login    │    │ • PostgreSQL    │    │ • DSM API       │
└─────────────────┘    └─────────────────┘    └─────────────────┘

API 구조

POST   /api/items              # 생성
GET    /api/items?type={type}  # 조회
PUT    /api/items/{id}         # 수정
DELETE /api/items/{id}         # 삭제
POST   /api/upload/image       # 이미지

📁 프로젝트 구조

Todo-Project/
├── README.md
├── DESIGN.md                    # 설계 문서
├── SYNOLOGY_INTEGRATION.md      # 시놀로지 연동 가이드
├── docker-compose.yml
├── .env.example
├── backend/
│   ├── Dockerfile
│   ├── pyproject.toml
│   ├── src/
│   │   ├── main.py
│   │   ├── core/
│   │   │   ├── config.py
│   │   │   ├── database.py
│   │   │   └── security.py
│   │   ├── models/
│   │   │   ├── user.py
│   │   │   └── todo.py
│   │   ├── schemas/
│   │   │   ├── auth.py
│   │   │   └── todo.py
│   │   ├── api/
│   │   │   ├── dependencies.py
│   │   │   └── routes/
│   │   │       ├── auth.py
│   │   │       ├── users.py
│   │   │       └── todos.py
│   │   └── integrations/
│   │       ├── synology/
│   │       │   ├── dsm_auth.py
│   │       │   ├── calendar_sync.py
│   │       │   └── mail_service.py
│   │       └── device_auth.py
│   └── migrations/
├── frontend/
│   ├── index.html
│   ├── login.html
│   ├── static/
│   │   ├── css/
│   │   │   └── main.css
│   │   ├── js/
│   │   │   ├── api.js
│   │   │   ├── auth.js
│   │   │   ├── todos.js
│   │   │   └── synology-sync.js
│   │   └── icons/
│   ├── components/
│   └── manifest.json            # PWA 설정
├── docs/
│   ├── API.md                   # API 문서
│   ├── DEPLOYMENT.md            # 배포 가이드
│   └── SECURITY.md              # 보안 가이드
└── database/
    └── init/
        └── 01_init.sql

📊 데이터베이스 설계

ERD (Entity Relationship Diagram)

┌─────────────┐         ┌─────────────┐         ┌─────────────┐
│    Users    │         │ TodoItems   │         │TodoComments │
├─────────────┤         ├─────────────┤         ├─────────────┤
│ id (PK)     │◄────────│ user_id(FK) │◄────────│todo_item_id │
│ email       │         │ content     │         │ content     │
│ password    │         │ status      │         │ created_at  │
│ full_name   │         │ start_date  │         └─────────────┘
│ is_active   │         │ estimated   │
│ created_at  │         │ completed   │
└─────────────┘         │ parent_id   │ ◄─┐
                        └─────────────┘   │
                               │          │
                               └──────────┘
                            (Self Reference)

상태 관리

TODO_STATES = {
    "draft": "검토 필요 - 아직 일정 미설정",
    "scheduled": "예정됨 - 일정 설정 완료", 
    "active": "진행중 - 현재 작업 중",
    "completed": "완료됨 - 작업 완료",
    "delayed": "지연됨 - 새로운 날짜로 연기"
}

데이터 플로우

1. 할일 생성 → 2. 일정 설정 → 3. 캘린더 동기화 → 4. 메일 알림
     ↓              ↓              ↓              ↓
   Draft         Scheduled      Calendar       Email
                                  Event        Sent

🔐 보안 설계

개인용 최적화 보안 모델

기기 등록 방식

class DeviceAuth:
    """개인 기기 인증 시스템"""
    
    def register_device(self, user_id, device_info):
        """신뢰할 수 있는 기기 등록"""
        # 기기 고유 ID 생성 (브라우저 fingerprint + 사용자 입력)
        device_id = self.generate_device_id(device_info)
        
        # 장기간 유효한 토큰 생성 (30일)
        device_token = self.create_device_token(user_id, device_id)
        
        return device_token
    
    def quick_login(self, device_token):
        """기기 토큰으로 빠른 로그인"""
        if self.is_valid_device_token(device_token):
            return self.create_session_token()
        return None

보안 레벨

  • Minimal: 기기 등록 후 비밀번호 불필요 (개인용 권장)
  • Balanced: 주기적 비밀번호 확인
  • Secure: 매번 인증 + 생체 인증

🔗 시놀로지 연동 설계

연동 개요

Todo-Project는 시놀로지 생태계와 양방향 연동되어 간결한 할일 관리전체 일정 조망을 동시에 제공합니다.

핵심 철학

  • Todo-Project: 빠른 할일 추가 및 관리 (간결함)
  • 시놀로지 캘린더: 전체 일정 조망 및 통합 관리 (완전성)
  • MailPlus: 외부 요청을 Todo로 자동 변환 (자동화)

🔄 간소화된 연동 플로우 새로운 접근

핵심 아이디어: 메일 중심 워크플로우

📧 MailPlus 메일 수신 
    ↓
📅 시놀로지 캘린더 이벤트 생성 (수동/자동)
    ↓  
📋 Todo 자동 추가 (메일 내용 + 첨부파일 포함)
    ↓
🔄 캘린더 ↔ Todo 양방향 동기화

장점

  • 단순함: 복잡한 API 연동 최소화
  • 자연스러움: 기존 메일 워크플로우 활용
  • 유연성: 다양한 메일 클라이언트에서 작동
  • 안정성: 시놀로지 기본 기능 활용

간소화된 구현 방법

1. 메일 모니터링 (핵심 기능)

class SimpleMailMonitor:
    """간단한 메일 모니터링 서비스"""
    
    def __init__(self, imap_server, username, password):
        self.imap_server = imap_server
        self.username = username
        self.password = password
    
    async def check_new_emails(self):
        """새 메일 확인 (IMAP)"""
        import imaplib
        import email
        
        mail = imaplib.IMAP4_SSL(self.imap_server, 993)
        mail.login(self.username, self.password)
        mail.select('inbox')
        
        # 읽지 않은 메일 검색
        status, messages = mail.search(None, 'UNSEEN')
        
        new_emails = []
        for msg_id in messages[0].split():
            status, msg_data = mail.fetch(msg_id, '(RFC822)')
            email_body = msg_data[0][1]
            email_message = email.message_from_bytes(email_body)
            
            new_emails.append({
                'id': msg_id,
                'subject': email_message['Subject'],
                'from': email_message['From'],
                'body': self._extract_body(email_message),
                'attachments': self._extract_attachments(email_message)
            })
        
        mail.close()
        mail.logout()
        return new_emails

2. 메일 → Todo 자동 변환 서비스

class MailToTodoService:
    """메일을 Todo로 자동 변환하는 간단한 서비스"""
    
    def __init__(self, mail_monitor, todo_service):
        self.mail_monitor = mail_monitor
        self.todo_service = todo_service
        
    async def monitor_emails(self):
        """메일 모니터링 및 자동 변환"""
        while True:
            try:
                new_emails = await self.mail_auth.check_new_emails()
                
                for email in new_emails:
                    if self._is_todo_email(email):
                        todo_item = await self._convert_email_to_todo(email)
                        await self.todo_service.create_todo(todo_item)
                        
                        # 캘린더에도 동기화
                        await self.calendar_sync.sync_todo_to_calendar(todo_item)
                        
            except Exception as e:
                logger.error(f"메일 모니터링 오류: {e}")
            
            await asyncio.sleep(60)  # 1분마다 체크
    
    def _is_todo_email(self, email):
        """Todo 변환 대상 메일인지 판단"""
        # 제목에 특정 키워드 포함
        todo_keywords = ['할일', 'TODO', 'Task', '작업', '요청']
        subject = email['subject'].lower()
        
        return any(keyword.lower() in subject for keyword in todo_keywords)
    
    async def _convert_email_to_todo(self, email):
        """메일을 Todo 항목으로 변환"""
        # 제목에서 할일 내용 추출
        content = self._extract_todo_content(email['subject'])
        
        # 본문에서 날짜/시간 추출
        due_date = self._extract_date_from_body(email['body'])
        
        # 첨부파일 처리
        attachments = await self._save_attachments(email['attachments'])
        
        todo_data = {
            'content': content,
            'description': email['body'],
            'due_date': due_date,
            'attachments': attachments,
            'source': 'email',
            'source_id': email['id'],
            'sender': email['from']
        }
        
        return todo_data
    
    def _extract_todo_content(self, subject):
        """제목에서 할일 내용 추출"""
        # "할일: 문서 검토" → "문서 검토"
        # "TODO: Review document" → "Review document"
        import re
        
        patterns = [
            r'할일:\s*(.+)',
            r'TODO:\s*(.+)',
            r'Task:\s*(.+)',
            r'작업:\s*(.+)',
            r'요청:\s*(.+)'
        ]
        
        for pattern in patterns:
            match = re.search(pattern, subject, re.IGNORECASE)
            if match:
                return match.group(1).strip()
        
        return subject  # 패턴이 없으면 전체 제목 사용
    
    def _extract_date_from_body(self, body):
        """본문에서 날짜 추출"""
        import re
        from datetime import datetime, timedelta
        
        # 날짜 패턴들
        date_patterns = [
            r'(\d{4}-\d{2}-\d{2})',  # 2024-01-15
            r'(\d{2}/\d{2}/\d{4})',  # 01/15/2024
            r'(\d{1,2}월\s*\d{1,2}일)',  # 1월 15일
            r'(내일|tomorrow)',
            r'(다음주|next week)',
            r'(이번주|this week)'
        ]
        
        for pattern in date_patterns:
            match = re.search(pattern, body, re.IGNORECASE)
            if match:
                date_str = match.group(1)
                return self._parse_date_string(date_str)
        
        # 기본값: 3일 후
        return datetime.now() + timedelta(days=3)
    
    async def _save_attachments(self, attachments):
        """첨부파일을 NAS에 저장"""
        saved_files = []
        
        for attachment in attachments:
            # /volume1/todo-data/attachments/ 에 저장
            file_path = f"/data/attachments/{attachment['filename']}"
            
            with open(file_path, 'wb') as f:
                f.write(attachment['content'])
            
            saved_files.append({
                'filename': attachment['filename'],
                'path': file_path,
                'size': len(attachment['content'])
            })
        
        return saved_files

⚙️ 환경 설정

환경 변수 설정

# .env 파일
# 시놀로지 메일 설정 (필수)
SYNOLOGY_MAIL_SERVER=your-nas.synology.me
SYNOLOGY_MAIL_USERNAME=todo_user
SYNOLOGY_MAIL_PASSWORD=your_secure_password

# 메일 모니터링 설정
ENABLE_MAIL_MONITORING=true
MAIL_CHECK_INTERVAL=60  # 초 단위
TODO_KEYWORDS=할일,TODO,Task,작업,요청

# 첨부파일 저장 경로
ATTACHMENTS_PATH=/data/attachments

시놀로지 NAS 설정

1. MailPlus 설정
# MailPlus 패키지에서:
1. IMAP 활성화: 설정 → IMAP/POP3 → IMAP 활성화
2. 포트: 993 (SSL) 또는 143 (일반)
3. 전용 계정 생성: todo_mail_user
4. 권한: MailPlus 접근만 허용
2. 캘린더 설정 (선택사항)
# Calendar 패키지에서:
1. 새 캘린더 생성: "Todo Tasks"
2. 색상: 보라색 (#6366f1)
3. 메일에서 일정 추가 기능 활성화

🔧 사용 방법

1. 메일로 할일 추가

제목: 할일: 프로젝트 문서 검토
본문: 
- 마감일: 2024-01-20
- 예상 소요시간: 2시간
- 첨부파일: project_spec.pdf

→ Todo 앱에 자동으로 추가됨

2. 캘린더 연동 (선택)

MailPlus → 캘린더 이벤트 생성 → Todo 동기화
캘린더에서 완료 처리 → Todo 상태 자동 업데이트

3. 첨부파일 관리

메일 첨부파일 → NAS 저장 (/data/attachments/)
Todo에서 파일 링크로 접근 가능

📱 프론트엔드 설계

PWA (Progressive Web App) 구조

// manifest.json
{
    "name": "Todo Project",
    "short_name": "Todo",
    "start_url": "/",
    "display": "standalone",
    "theme_color": "#6366f1",
    "shortcuts": [
        {
            "name": "빠른 할일 추가",
            "url": "/quick-add"
        }
    ]
}

오프라인 지원

// Service Worker
self.addEventListener('fetch', event => {
    if (event.request.url.includes('/api/todos')) {
        event.respondWith(
            // 온라인: API 호출
            // 오프라인: 로컬 캐시 사용
            caches.match(event.request) || fetch(event.request)
        );
    }
});

상태 관리

class TodoState {
    constructor() {
        this.todos = [];
        this.syncQueue = []; // 오프라인 시 동기화 대기열
        this.isOnline = navigator.onLine;
    }
    
    async addTodo(content) {
        const todo = this.createTodo(content);
        
        if (this.isOnline) {
            await this.syncToServer(todo);
        } else {
            this.syncQueue.push({action: 'create', todo});
        }
        
        return todo;
    }
}

간결한 인터페이스 원칙

메인 화면

<!-- 최소한의 요소만 표시 -->
<div class="todo-app">
    <!-- 빠른 입력 -->
    <input class="quick-add" placeholder="할일을 입력하세요..." />
    
    <!-- 간단한 탭 -->
    <div class="tabs">
        <button class="tab active">진행중</button>
        <button class="tab">완료</button>
    </div>
    
    <!-- 할일 목록 -->
    <div class="todo-list">
        <!-- 할일 아이템들 -->
    </div>
</div>

모바일 최적화

  • 터치 친화적: 44px 이상 터치 영역
  • 햅틱 피드백: 액션 시 진동 피드백
  • 풀투리프레시: 아래로 당겨서 새로고침
  • 오프라인 표시: 네트워크 상태 표시

색상 시스템

:root {
    --primary: #6366f1;      /* 보라색 - 메인 컬러 */
    --success: #10b981;      /* 초록색 - 완료 */
    --warning: #f59e0b;      /* 주황색 - 진행중 */
    --danger: #ef4444;       /* 빨간색 - 지연 */
    --gray: #6b7280;         /* 회색 - 대기 */
}

🎯 코딩 표준 및 규칙

핵심 원칙: "간결함 (Simplicity)"

"복잡함은 버그의 온상이다. 간결함이 최고의 아름다움이다."

파일 크기 제한

핵심 로직 파일 (엄격)

  • 모델 파일 (models/): 최대 200줄
  • 스키마 파일 (schemas/): 최대 150줄
  • 설정 파일 (config.py): 최대 100줄

서비스 파일 (보통)

  • API 라우터: 최대 400줄
  • 서비스 클래스: 최대 350줄
  • 통합 서비스: 최대 500줄

프론트엔드 파일 (유연)

  • JavaScript 파일: 최대 300줄
  • HTML 파일: 최대 250줄
  • CSS 파일: 최대 200줄

함수/메서드 크기 제한

  • 단순 함수: 최대 20줄
  • 비즈니스 로직 함수: 최대 40줄
  • 통합/조합 함수: 최대 60줄
  • 초기화 함수: 최대 30줄

간결성 규칙

1. 한 가지 일만 하기

# ❌ 나쁜 예 - 여러 일을 함
def process_todo_and_send_email_and_update_calendar(todo):
    # 할일 처리
    # 이메일 발송
    # 캘린더 업데이트
    pass

# ✅ 좋은 예 - 각각 분리
def process_todo(todo): pass
def send_notification_email(todo): pass  
def update_calendar(todo): pass

2. 명확한 이름 사용

# ❌ 나쁜 예
def calc(x, y, z): pass
def proc_data(d): pass

# ✅ 좋은 예
def calculate_estimated_time(start, duration, buffer): pass
def process_todo_item(todo_data): pass

3. 중복 제거

# ❌ 나쁜 예 - 중복 코드
def create_synology_event(todo):
    event = CalendarEvent()
    event.title = f"📋 {todo.content}"
    event.start_time = todo.start_date
    # ... 공통 로직

# ✅ 좋은 예 - 공통 로직 분리
def create_base_event(todo):
    return CalendarEvent(
        title=f"📋 {todo.content}",
        start_time=todo.start_date
    )

def create_synology_event(todo):
    event = create_base_event(todo)
    # 시놀로지 특화 로직만
    return event

🐳 Docker 설정

docker-compose.yml (Production - NAS)

version: '3.8'

services:
  frontend:
    build: ./frontend
    container_name: todo-web
    ports:
      - "4000:80"
    depends_on:
      - backend
    restart: unless-stopped

  backend:
    build: ./backend
    container_name: todo-api
    ports:
      - "9000:9000"
    volumes:
      - /volume3/docker/todo-app/app:/app
      - /volume1/todo-data:/data
    environment:
      - DATABASE_URL=postgresql://todouser:${DB_PASSWORD}@database:5432/todo
      - UPLOAD_PATH=/data/uploads/images
      - TZ=Asia/Seoul
    depends_on:
      - database
    restart: unless-stopped

  database:
    image: postgres:15-alpine
    container_name: todo-db
    ports:
      - "5434:5432"
    volumes:
      - /volume1/todo-data/database:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=todo
      - POSTGRES_USER=todouser
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    restart: unless-stopped

🔄 개발 워크플로우

Mac 로컬 개발 구조

~/Developer/todo-app/
├── backend/
│   ├── main.py
│   ├── requirements.txt
│   ├── Dockerfile
│   └── docker-compose.dev.yml
├── frontend/
│   └── (React/Vue 파일)
├── ios/
│   └── TodoApp.xcodeproj
└── README.md

1단계: 로컬 개발 (Mac)

# 프로젝트 시작
cd ~/Developer/todo-app
docker-compose -f docker-compose.dev.yml up

# API 테스트
curl http://localhost:9000/api/items

# 프론트엔드 개발
npm run dev  # http://localhost:4000

2단계: NAS 배포

# Mac에서 푸시
git add .
git commit -m "기능 추가"
git push gitea main

# NAS SSH 접속
ssh admin@nas-ip

# 배포
cd /volume3/docker/todo-app
git pull
docker-compose down
docker-compose up -d --build

3단계: iOS 앱 연동

// Development
let API_BASE = "http://192.168.1.100:9000"

// Production  
let API_BASE = "https://your.synology.me:9000"

🚀 빠른 시작

포트 설정

개발 환경 설정

  1. 환경 변수 설정
cp .env.example .env
# .env 파일에서 시놀로지 연동 정보 설정 (선택사항)
  1. Docker로 실행
docker-compose up -d
  1. 브라우저에서 접속
http://localhost:4000
  1. 개인용 설정 (권장)
  • 첫 접속 시 "개인용으로 설정" 선택
  • 내 기기 등록으로 자동 로그인 활성화

초기 설정 명령어

# Mac: 프로젝트 생성
mkdir -p ~/Developer/todo-app/{backend,frontend,ios}
cd ~/Developer/todo-app

# NAS: 폴더 생성
ssh admin@nas-ip
sudo mkdir -p /volume3/docker/todo-app
sudo mkdir -p /volume1/todo-data/{database,uploads/images,backups}

# Git 초기화
git init
git remote add origin http://nas-ip:3000/username/todo-app.git

첫 배포 테스트

# 1. 간단한 API 작성
echo "from fastapi import FastAPI
app = FastAPI()
@app.get('/')
def read_root():
    return {'status': 'ok'}" > backend/main.py

# 2. Dockerfile 생성
echo "FROM python:3.11-slim
WORKDIR /app
RUN pip install fastapi uvicorn
COPY . .
CMD ['uvicorn', 'main:app', '--host', '0.0.0.0', '--port', '9000']" > backend/Dockerfile

# 3. 배포 및 테스트
docker build -t todo-api backend/
docker run -p 9000:9000 todo-api
curl http://localhost:9000

📝 구현 로드맵

Phase 1: 백엔드 (Week 1)

  • Docker 환경 구성
  • FastAPI 기본 CRUD
  • PostgreSQL 스키마
  • 이미지 업로드 처리
  • JWT 인증

Phase 2: 웹 프론트엔드 (Week 1)

  • React/Vue 프로젝트 설정
  • 3가지 분류 UI
  • 이미지 업로드 컴포넌트
  • PWA 설정
  • 반응형 디자인

Phase 3: iOS 앱 (Week 2-3)

  • SwiftUI 기본 구조
  • API Service 클래스
  • 카메라/갤러리 연동
  • 오프라인 캐싱
  • 푸시 알림

Phase 4: Apple Watch (Week 1)

  • WatchOS 타겟 추가
  • 오늘 할일 뷰
  • 체크 기능
  • 컴플리케이션

시놀로지 연동 (1단계)

  • 시놀로지 인증 시스템
  • 시놀로지 캘린더 연동
  • PWA 모바일 지원
  • 브라우저 확장 프로그램
  • 오프라인 기능

🔧 NAS 설정 체크리스트

Container Manager

1. 프로젝트 생성
   - 이름: todo-app
   - 경로: /volume3/docker/todo-app
   
2. 포트 설정
   - Frontend: 4000
   - Backend: 9000
   - Database: 5434
   
3. 볼륨 마운트
   - 소스: /volume1/todo-data
   - 타겟: /data

리버스 프록시 (선택)

제어판 > 로그인 포털 > 고급 > 리버스 프록시
- 소스: https://todo.your-domain.me
- 대상: http://localhost:4000
- HSTS, HTTP/2 활성화

🧪 테스트 전략

테스트 피라미드

    ┌─────────────┐
    │   E2E Tests │  ← 사용자 시나리오
    ├─────────────┤
    │ Integration │  ← API + DB 통합
    │    Tests    │
    ├─────────────┤
    │  Unit Tests │  ← 개별 함수/클래스
    └─────────────┘

중요 테스트 케이스

  • 할일 CRUD: 생성, 조회, 수정, 삭제
  • 상태 전환: Draft → Active → Completed
  • 시놀로지 연동: 캘린더 동기화, 메일 발송
  • 오프라인 모드: 네트워크 없이 기본 기능
  • 기기 인증: 등록, 로그인, 토큰 갱신

🛠 도구 및 자동화

코드 품질 도구

# Python
pip install flake8 black isort

# 라인 수 체크
find . -name "*.py" -exec wc -l {} + | sort -n

# 복잡도 체크
pip install mccabe
flake8 --max-complexity=5 .

pre-commit 훅

# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: check-file-size
        name: Check file size
        entry: bash -c 'find . -name "*.py" -exec wc -l {} + | awk "$1 > 300 {print $2 " exceeds 300 lines (" $1 ")"; exit 1}"'
        language: system

📈 성능 최적화

프론트엔드 최적화

  • 지연 로딩: 필요한 컴포넌트만 로드
  • 가상 스크롤: 많은 할일 목록 처리
  • 캐싱: 자주 사용하는 데이터 캐시
  • 압축: 정적 파일 gzip 압축

백엔드 최적화

  • 데이터베이스 인덱스: 자주 조회하는 컬럼
  • 연결 풀링: 데이터베이스 연결 재사용
  • 캐싱: Redis를 통한 세션 캐시
  • 비동기 처리: FastAPI async/await 활용

🔄 동기화 전략

실시간 동기화

class SyncManager:
    """동기화 관리자"""
    
    async def sync_todo_change(self, todo_id, action):
        """할일 변경 시 동기화"""
        
        # 1. 로컬 상태 업데이트
        await self.update_local_state(todo_id, action)
        
        # 2. 시놀로지 캘린더 동기화
        if self.synology_enabled:
            await self.sync_to_calendar(todo_id, action)
        
        # 3. 다른 기기에 알림 (WebSocket)
        await self.notify_other_devices(todo_id, action)

충돌 해결

  • Last Write Wins: 마지막 수정이 우선
  • 사용자 선택: 충돌 시 사용자가 선택
  • 자동 병합: 단순한 변경사항은 자동 병합

📌 참고사항

보안

  • JWT 토큰 구현 필수
  • HTTPS 설정 (Let's Encrypt)
  • 환경변수로 민감정보 관리

백업

  • Hyper Backup으로 자동 백업 설정
  • /volume1/todo-data 전체 백업
  • Git으로 코드 버전 관리

모니터링

  • Synology Resource Monitor 활용
  • Docker 로그: docker logs todo-api
  • 에러 추적: Sentry 고려

📋 체크리스트

코드 작성 전

  • 이 기능이 정말 필요한가?
  • 더 간단한 방법은 없는가?
  • 기존 코드를 재사용할 수 있는가?

코드 작성 중

  • 함수가 30줄을 넘지 않는가?
  • 하나의 함수가 한 가지 일만 하는가?
  • 변수명이 명확한가?

코드 작성 후

  • 파일이 300줄을 넘지 않는가?
  • 중복 코드가 있는가?
  • 다른 개발자가 쉽게 이해할 수 있는가?

🎯 1단계 목표 (시놀로지 연동)

  1. 할일 → 캘린더: 일정 설정 시 시놀로지 캘린더에 'todo' 태그로 등록
  2. 메일 알림: MailPlus를 통한 검토 정보 발송
  3. 상태 동기화: 완료 시 '완료' 태그로 변경
  4. 지연 처리: 지연 시 캘린더 날짜 자동 수정

🤝 기여 방법

이 프로젝트는 개인용으로 시작되었지만, 유용한 기능이나 개선사항이 있다면 언제든 기여해주세요!


📄 라이선스

이 프로젝트는 기존 Document Server 프로젝트에서 분리되어 독립적으로 개발되고 있습니다.


이 종합 가이드를 따라가면 체계적이고 간결한 Todo 앱을 개발할 수 있습니다! 🚀