# 개발 로그 ## 2026-04-02 — v2 전환 설계 완료 ### 결정 사항 - DEVONthink 탈피 결정. v1의 구조적 한계(AppleScript 취약성, macOS GUI 의존, 13개 DB 복잡성)를 더 이상 감수하지 않기로 함 - 자체 웹앱 방향 확정. 기술 스택: FastAPI + PostgreSQL/pgvector + SvelteKit + Docker - OmniFocus 탈피 → Synology Calendar (CalDAV VTODO)로 대체 - Synology 서비스 활용 극대화: Office(문서 편집/미리보기), Drive(파일 관리), Calendar(태스크), MailPlus(이메일+알림) - Document_Server 전체를 Synology Drive가 관리. PKM 하위 폴더로 자동분류 영역 분리 - 문서 "원본" 정의 확정: immutable(PDF, 수신 HWP 등) / editable(Synology Office 포맷) / note(Markdown) - .docx/.xlsx는 교환 형식으로 취급. 서버에 영구 보관하지 않음 - 데이터 3계층: 원본(NAS) → 가공(PostgreSQL) → 파생(pgvector+캐시) - kordoc 통합 결정 (HWP/HWPX/PDF → Markdown 파싱, Node.js 마이크로서비스) - AI 전략: Qwen3.5-35B-A3B(MLX) 우선, Claude API는 종량제로 최후 수단. GPU 서버에 AI Gateway 배치 - Anthropic 약관 확인: 구독 OAuth의 서드파티 사용은 약관상 금지(2026.01~). 자동화에는 API 키만 사용 - NanoClaw는 선택적 확장(대화형 인터페이스)으로 위치, 핵심 파이프라인 비의존 - 장기 로드맵: GPU 서버 확장 → 메인 서버 승격, Mac mini → Roon Core 전용, Synology 장기 유지 ### 산출물 - `docs/architecture-v2.md` — 17개 섹션 + 부록 2개 (전체 시스템 설계) - 마이그레이션 계획서 — Step 1~5 (프로젝트 리네임+정리) + Phase 0~5 (v2 개발) - 프로젝트 리네임: DEVONThink_my server → hyungi_Document_Server ### 배경 논의 (Cowork 세션) - v1에서 16개 커밋 중 절반 이상이 AppleScript 버그 수정이었던 점이 전환의 직접적 계기 - Synology Office iframe 임베드로 DEVONthink 미리보기 대체 가능성 논의 - HWP 대응으로 kordoc(광진구청 류승인 주무관 제작, MIT 라이선스) 조사 및 채택 - 편집 가능 문서의 "원본이 뭐냐" 논의 → Synology Office 포맷이 원본, .docx/.xlsx는 교환용 - 가공 데이터 보관 전략 논의 → 파일로 저장하지 않고 PostgreSQL에만 저장, 버전 추적으로 선택적 재가공 ## 2026-04-02 — 프로젝트 리네임 + v2 전환 실행 ### Step 1: 사전 정리 ✅ - architecture-v2.md 커밋 (`852b7da`) - v1-archive 브랜치 + v1-final 태그 생성 (v1 상태 완벽 보존) ### Step 2: v1 파일 정리 ✅ - v1 전용 파일 git rm 완료 (`e48b6a2`) - 삭제: applescript/, launchd/, v1 scripts, v1 docs, tests/test_classify.py, requirements.txt - 유지: scripts/prompts/classify_document.txt, credentials.env.example (v2 필드로 갱신) ### Step 3: Gitea 리포 리네임 + 로컬 폴더 리네임 ✅ - Gitea: devonthink_home → hyungi_document_server - 로컬 폴더: DEVONThink_my server → hyungi_Document_Server - git remote set-url + git ls-remote 검증 + push 완료 ### Step 4: 문서 전면 재작성 ✅ - CLAUDE.md — v2 기준으로 전면 재작성 - README.md — 프로젝트명, 기술 스택, 디렉토리 구조 갱신 - docs/deploy.md — Docker Compose 기반 배포 가이드로 교체 - docs/claude-code-commands.md → docs/development-stages.md 변환 - docs/architecture-v2.md → docs/architecture.md 승격 ### Step 5: v2 프로젝트 스캐폴딩 ✅ - 전체 디렉토리 구조 생성 (app/, services/kordoc/, gpu-server/, frontend/, migrations/, tests/) - 동작하는 최소 코드 수준: FastAPI main.py, PostgreSQL 스키마, kordoc server.js, config.yaml 등 - docker-compose.yml, Caddyfile, credentials.env.example 생성 - tests/__init__.py + conftest.py 포함 ### Step 1~5 전체 완료. --- ## 2026-04-02 — Phase 0: 기반 구축 시작 ### users 테이블 + ORM 모델 추가 ✅ - `migrations/001_initial_schema.sql`에 users 테이블 포함 (username, password_hash, totp_secret, is_active) - `app/models/user.py` — SQLAlchemy 2.0 Mapped 스타일 ORM 모델 - architecture.md 섹션 6 스키마와 일치 ### Auth API 엔드포인트 구현 ✅ - `app/api/auth.py` — 4개 엔드포인트: POST /login (JWT발급+TOTP), POST /refresh, GET /me, POST /change-password - `app/core/auth.py` — bcrypt 비밀번호 해싱, JWT 발급/검증, TOTP 검증, get_current_user 의존성 - Pydantic 스키마: LoginRequest, TokenResponse, RefreshRequest, ChangePasswordRequest, UserResponse ### main.py 라우터 등록 + health 강화 ✅ - auth 라우터 등록: `/api/auth` prefix - health 엔드포인트에 DB 연결 상태 포함 (connected/disconnected) - lifespan 핸들러로 DB 초기화/정리 ### Docker 설정 수정 ✅ ### 초기 admin 유저 시드 스크립트 ✅ ### 셋업 위자드 구현 ✅ (`a601991`) - `app/api/setup.py` — 6개 엔드포인트: GET /status, POST /admin, POST /totp/init, POST /totp/verify, POST /verify-nas, GET / (HTML) - `app/templates/setup.html` — Jinja2 단일 HTML, Vanilla JS + qrcode.js CDN, 3단계 위자드 - `app/main.py` — setup 라우터 등록 + 셋업 미들웨어 (유저 0명 시 /setup 리다이렉트, /health /docs 등 바이패스) - Rate Limiting: IP당 5분 내 5회 실패 시 차단 - TOTP 흐름: init에서 secret 반환(DB 미저장) → verify에서 코드 검증 후 DB 저장 - scripts/seed_admin.py CLI 백업 수단 유지 - requirements.txt에 jinja2 추가 ### Phase 0 완료 기준 달성 상태 - ✅ docker compose up → FastAPI 구동 - ✅ DB 스키마 (users, documents, tasks, processing_queue) - ✅ JWT + TOTP 인증 (로그인, 토큰 갱신, 비밀번호 변경) - ✅ 셋업 위자드 (관리자 생성 + TOTP + NAS 확인) - ✅ /health — DB 연결 상태 포함 - ✅ /docs — OpenAPI 문서 - ⬜ NAS SMB 마운트 실제 검증 (Mac mini 배포 시) - ⬜ config.yaml 로딩 검증 (Mac mini 배포 시) --- ## 2026-04-02 — Phase 1: 데이터 마이그레이션 파이프라인 구현 완료 ### Step 1: kordoc /parse 실제 구현 ✅ - `services/kordoc/server.js` — stub → 실제 파싱 구현 (kordoc ^1.7.0 + pdfjs-dist ^4.0.0) - HWP/HWPX/PDF → Markdown 변환, .md/.txt 직접 읽기, 이미지는 requires_ocr 플래그 반환 - 타임아웃 30초, 파일 미존재 404, 파싱 실패 422 ### Step 2: 큐 소비자 인프라 ✅ - `app/workers/queue_consumer.py` — APScheduler AsyncIOScheduler 1분 간격 실행 - 배치 처리: extract=5, classify=3, embed=1 - stage 체이닝: extract → classify → embed 자동 enqueue - stale 항목 자동 복구 (processing 상태 10분 초과) - `app/main.py` — lifespan에 APScheduler 연결, yield 후 shutdown 보장 ### Step 3: 텍스트 추출 워커 ✅ - `app/workers/extract_worker.py` — 포맷별 분기 처리 - KORDOC_FORMATS (hwp, hwpx, pdf) → kordoc HTTP POST - TEXT_FORMATS (md, txt, csv, json, xml, html) → 직접 파일 읽기 - IMAGE_FORMATS → Phase 2 OCR로 연기 ### Step 4: AI 분류 워커 ✅ - `app/workers/classify_worker.py` — extracted_text 8000자 → AIClient.classify() 호출 - `app/ai/client.py` — strip_thinking(), parse_json_response() 추가 (v1 pkm_utils.py에서 포팅) - Qwen3.5의 태그 제거 + 비정형 JSON 파싱 로직 ### Step 5: 벡터 임베딩 워커 ✅ - `app/workers/embed_worker.py` — nomic-embed-text-v1.5 (GPU 서버), 6000자 제한 - GPU 서버 불가 시 graceful fail → 재시도 ### Step 6: DEVONthink 마이그레이션 스크립트 ✅ - `scripts/migrate_from_devonthink.py` — --dry-run, --source-dir, --target-dir, --database-url 지원 - DEVONthink 내보내기 → NAS PKM 구조 복사 + documents/processing_queue DB 등록 ### Phase 1 완료 기준 달성 상태 - ✅ kordoc 파싱 (HWP/HWPX/PDF → Markdown) - ✅ 큐 소비자 + APScheduler 연동 - ✅ extract → classify → embed 워커 3개 - ✅ AI 클라이언트 think 태그 / JSON 파싱 보강 - ✅ 마이그레이션 스크립트 - ⬜ Step 7: 통합 테스트 + 배치 실행 (Mac mini 배포 후) --- ## 2026-04-02 — Phase 2: 핵심 기능 구현 완료 (`4b69533`) ### 문서 CRUD API ✅ - `app/api/documents.py` — 5개 엔드포인트 - POST /api/documents/ — 파일 업로드 (Inbox 저장 + extract 큐 등록) - GET /api/documents/ — 목록 조회 (페이징 + domain/source/format 필터) - GET /api/documents/{id} — 단건 조회 - PATCH /api/documents/{id} — 메타데이터 수동 수정 - DELETE /api/documents/{id} — DB 삭제 (기본), ?delete_file=true로 파일도 삭제 ### 하이브리드 검색 API ✅ - `app/api/search.py` — GET /api/search/?q={query}&mode={mode} - 4가지 모드: fts, trgm, vector, hybrid (기본) - hybrid 가중치: FTS 0.4 + Trigram 0.2 + Vector 0.4 - 벡터 불가 시 FTS 0.6 + Trigram 0.4 폴백 - 결과에 snippet(200자) 포함 ### 파일 워처 ✅ - `app/workers/file_watcher.py` — Inbox 디렉토리 5분 간격 스캔 - 신규 파일: Document 생성 + extract 큐 등록 - 변경 파일: 해시 비교 → 재추출 큐 등록 - .DS_Store, .tmp, .part 등 무시 파일 처리 ### 벡터 인덱스 마이그레이션 ✅ - `migrations/002_vector_index.sql` — IVFFlat 인덱스 (cosine, lists=50) - 문서 수 증가 시 lists 값 조정 필요 ### Phase 2 완료 기준 달성 상태 - ✅ 문서 CRUD API (업로드, 목록, 조회, 수정, 삭제) - ✅ 하이브리드 검색 (FTS + Trigram + Vector) - ✅ Inbox 파일 워처 (신규/변경 자동 감지 → 파이프라인 등록) - ✅ 처리 파이프라인 전체 동작 (upload/watch → extract → classify → embed → search) - ⬜ 문서 뷰어 UI (Phase 4로 이관) - ⬜ SvelteKit 프론트엔드 (Phase 4로 이관)