Files
hyungi_document_server/docs/storage_layout.md
Hyungi Ahn 768fc36746 docs(storage): Storage PR-1 — read-only inventory + 정책 문서
Storage Backbone NAS 트랙의 첫 PR. plan v6 명시대로 read-only inventory PR
— 운영 변경 / mount 변경 / file_path 갱신 / asset 이동 모두 0건. 문서만.

산출물:
- docs/storage_layout.md  영구 정책 문서 (정책 / 마운트 매트릭스 / NFS 옵션 baseline)
- reports/storage_inventory_2026-05-11.md  측정 결과 snapshot

핵심 인사이트:
1. NAS binary layer 는 이미 잘 분리되어 있음 — PKM/extracted_images/
   study_question_images 모두 이미 NAS. 추가 이관 PR-3/4 작업량 거의 없음.
2. 현 GPU NFS mount = plan v6 권고안 baseline 과 정확히 같음
   (soft, vers=4.1, timeo=10, retrans=3) — PR-2 는 mount 옵션 변경 아닌
   애플리케이션 layer (정규화 wrapper / 장애 처리 / uid 매핑) 에 집중.
3. fastapi 만 NAS rw, worker 는 ro — 원본 안전 분리 OK.
4. Postgres pgdata = 1.1GB (DB 본체 이관 안 함, plan 결정 = GPU 잔류).
5. PR-4 도입 시 extracted_emails/ 신규 디렉토리 추가 예정 (Storage PR-5 합류).

실측 명령: SSH 100.111.160.84 → df/mount/du/docker volume ls/docker run
-v ... alpine du. 모두 read-only. 운영 영향 0.
2026-05-11 07:23:28 +09:00

8.3 KiB
Raw Permalink Blame History

Storage Layout — Document Server

버전: 2026-05-11 (Storage PR-1 read-only inventory 결과 반영) 역할 분리 원칙: feedback_knowledge_in_db_blob_in_nas.md — 지식·검색 대상 = DB, binary·source = NAS. Plan 정합: ~/.claude/plans/beszel-tingly-sloth.md v6 의 Storage Backbone 트랙.

전제

  • DB 본체 (Postgres) = GPU 서버 잔류 (CPU/RAM 우위, 결정 라운드 9).
  • NAS = bulk binary / source / 변경 적은 자료 backbone.
  • AI 호출은 GPU/맥미니로 라우팅 (Document Server 와 별 채널).

머신 / 마운트 토폴로지 (2026-05-11 실측)

머신 역할 IP 디스크
GPU 서버 (RTX 4070 Ti Super, Ubuntu) Docker 호스트 — fastapi / postgres / worker / Caddy / frontend LAN 192.168.1.186 / Tailscale 100.111.160.84 rootfs 936G / 182G used / 715G free
DS1525+ (Synology) NFS export + Hyper Backup + DR Tier 1 LAN 192.168.1.227 / Tailscale 100.101.79.37 /volume4 3.5TB / 401GB used / 3.1TB free
Mac mini M4 Pro MLX inference (Document Server 외부) LAN 192.168.1.x / Tailscale 100.76.254.116 (Document Server storage 영역 0)

GPU 서버의 NFS mount (/proc/mounts 실측):

192.168.1.227:/volume4/Document_Server  /mnt/nas/Document_Server
  nfs4 rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,
  soft,proto=tcp,timeo=10,retrans=3,_netdev

의미:

  • 이미 soft mount + timeo=10 + retrans=3 적용 중 → plan v6 Storage PR-2 의 "실측 후 mount 전략 결정" 의 현 baseline 이 곧 권고안. 변경 필요 X.
  • vers=4.1, NFSv4 (NFSv3 아님 → grace period / lock 처리 OK).
  • LAN 직결 (Tailscale 경유 아님) — D10 (DS1525+ Tailscale TCP 차단) 영향 없음.

NAS volume 안 Document Server layout

/mnt/nas/Document_Server/ (= NAS /volume4/Document_Server/):

경로 용도 크기 변경 빈도 분류
PKM/ 사용자 컨텐츠 원본 (knowledge + 입력 inbox + references) 38GB 일 단위 이미 NAS ✓
PKM/Knowledge/ 정리된 지식 자료 (압력용기, ASME, 가스, 등) 31GB 일 단위 이미 NAS ✓
PKM/References/ 레퍼런스 PDF 5.5GB 주 단위 이미 NAS ✓
PKM/Inbox/ 업로드 진입 (drag-drop / file_watcher) 1.5GB 시간 단위 이미 NAS ✓
PKM/.preview/ LibreOffice PDF 변환 cache (소량, 6 entry) 신규 업로드 시 이미 NAS ✓ (검토: GPU 로 이동 가치 작음)
PKM/Recordings/ 음성 녹음 20KB 거의 X 이미 NAS ✓
PKM/Videos/ 비디오 116KB 거의 X 이미 NAS ✓
PKM/Archive/ 아카이브 0 이미 NAS ✓
Main/ 별 디렉토리 (의미 확인 필요) 14GB ? 이미 NAS ✓
extracted_images/ Markdown Phase 1B.5 추출 이미지 (document_images) 1.2MB 변환 시 이미 NAS ✓
study_question_images/ 가스기사 문제 첨부 이미지 (PR-8) 12MB 회차 업로드 시 이미 NAS ✓
프로그래밍 전 참고 자료/ (소량) 56KB 거의 X 이미 NAS ✓

결론: NAS 의 binary/source layer 는 이미 잘 구성되어 있음. 추가 이관 후보 (Storage PR-3/4 candidate) 는 사실상 없음 — 단, PR-4 MailPlus ingest 도입 시 extracted_emails/ 신규 디렉토리 추가 예정.

GPU 서버 local storage (Postgres + worker 모델 + 로그)

경로 / Volume 용도 크기 분류
Postgres data dir (pgdata named volume) DB 본체 1.1GB GPU 잔류 (plan 결정)
hyungi_document_server_ollama_data Ollama 모델 weight (embedding / 분류 / 임베딩 등) 11.9GB GPU 잔류 (GPU 인접 필수)
hyungi_document_server_stt_models STT (faster-whisper 등) 모델 3.0GB GPU 잔류
hyungi_document_server_reranker_cache bge-reranker-v2-m3 cache 2.1GB GPU 잔류
hyungi_document_server_ocr_models OCR 모델 1.4GB GPU 잔류
hyungi_document_server_marker_models marker-pdf cache 4KB (외부 HF cache 사용 추정) GPU 잔류
hyungi_document_server_caddy_data Caddy ACME / log (작음) GPU 잔류
~/Documents/code/hyungi_Document_Server/logs/ fastapi 로그 (rotation) 21MB GPU 잔류

합계: AI 모델 캐시 ~18.5GB + Postgres 1.1GB + 로그/Caddy < 100MB ≈ GPU local 20GB 사용 중.

컨테이너 마운트 매트릭스 (docker-compose.yml 발췌)

컨테이너 마운트 모드 비고
postgres pgdata:/var/lib/postgresql/data + ./migrations:/docker-entrypoint-initdb.d rw DB 본체 named volume
kordoc-service ${NAS}/Document_Server:/documents ro PDF/HWP parse
ocr-service ${NAS}/Document_Server:/documents + ocr_models:/root/.cache ro + rw
marker-service ${NAS}/Document_Server:/documents + marker_models:/models ro + rw PDF→markdown
stt-service ${NAS}/Document_Server:/documents + stt_models:/root/.cache ro + rw
ai-gateway / ollama ollama_data:/root/.ollama rw GPU 인접
reranker reranker_cache:/data rw
fastapi ${NAS}/Document_Server:/documents + ./config.yaml ./domain_policy.yaml ./scripts ./logs ./migrations rw + ro/rw NAS 쓰기 권한은 fastapi 만
caddy ./Caddyfile + caddy_data:/data rw

관찰:

  • worker 컨테이너 (kordoc/ocr/marker/stt) 는 모두 NAS read-only 마운트 → 원본 안전.
  • fastapi 만 NAS rw → 업로드/preview/extracted_images 쓰기 단일 책임.
  • ./migrations 이 postgres 의 docker-entrypoint-initdb.d 와 fastapi 의 /app/migrations 양쪽에 마운트. 단 실제 migration runner 는 fastapi init_db() 만 사용 (postgres init scripts 는 첫 생성 시만 실행 → 효과 X, 안전).

정책 정리

NAS 에 두는 것 (binary / source / 변경 적음)

  • 사용자 컨텐츠 원본 (PKM/*)
  • 변환 cache (PKM/.preview/, extracted_images/)
  • 학습 자료 첨부 (study_question_images/)
  • 향후: extracted_emails/ (PR-4)

GPU 서버 local 에 두는 것 (latency 민감 / hot path / 큰 caching)

  • Postgres data dir (DB 본체)
  • HNSW index, pgvector index (Postgres 내부)
  • AI 모델 weight cache (embedding / OCR / STT / reranker / marker / ollama)
  • worker 임시 캐시 (각 컨테이너 named volume)
  • 로그 (./logs)

명확하게 어디에 두지 않음

  • 검색 인덱스: Postgres 안 (pgvector + pg_trgm) — NAS X
  • chunk text: Postgres 안 (document_chunks.text_content) — NAS X
  • 메모 본문: Postgres 안 (documents.extracted_text) — NAS X
  • AI 분류 결과: Postgres 안 (documents.ai_domain/ai_tags) — NAS X

NFS mount 옵션 권고 (Storage PR-2 baseline)

현 GPU 서버 mount = 이미 권고안과 같음:

192.168.1.227:/volume4/Document_Server /mnt/nas/Document_Server  nfs4
  rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,
  soft,proto=tcp,timeo=10,retrans=3,_netdev

근거:

  • soft — NAS down 시 process 영구 hang 회피 (plan v6 Storage PR-2 핵심 요구). 단 쓰기 도중 부분 실패 위험 → fastapi 의 upload / extract / marker worker 가 fsync + rename(atomic) + DB row 작성 ordering 필수 (코드 검토는 PR-2 영역).
  • timeo=10/retrans=3 — 1초 단위 timeout × 3회. 30초 안 NAS 응답 없으면 EIO. 운영 1년+ 안정 (별 incident 없음).
  • vers=4.1 — NFSv3 의 lock daemon 불필요, idempotent.
  • _netdev — boot 시 network 이후 마운트.

Storage PR-2 시 점검 항목 (read-only PR-1 scope 외)

  • 한글 NFC/NFD 정규화 wrapper (feedback_nfs_korean_path_normalize.md) — 기존 document_images 경로 처리 코드 일반화
  • uid/gid 매핑 (Synology user ↔ Docker container user)
  • NAS 장애 시뮬레이션 gate (운영 mount 아닌 isolated test mount 부터)
  • 쓰기 경로 fsync + rename(atomic) + 실패 명시 처리

백업 정책

  • NAS = Synology Hyper Backup (DR Tier 1, 별 트랙 project_db_backup.md 참조)
  • Postgres = pkm DB → Tier 0 GPU + Tier 1 DS1525+ Vol3 + Tier 2 C2 Hyper Backup (별 트랙)
  • AI 모델 캐시 = 백업 불필요 (재다운로드 가능)

다음 단계

  • Storage PR-2 (NFS 표준화 + 정규화 wrapper + 장애 시뮬 gate) — 운영 변경 동반 → 별 PR
  • Storage PR-3/4 (원본 이관) — 현 상태 이미 NAS, 추가 작업 0
  • Storage PR-5 (events raw_metadata 첨부 = extracted_emails) — events PR-4 (MailPlus ingest) 와 합류