3e73967c7b
UI overhaul to a darktable tone-and-manner and a set of features adapted from
darktable's proven patterns (reimplemented in our Electron/TS stack; no GPL code).
Design reskin:
- Dark neutral-gray palette + amber accent, flat/squared corners, no card shadows,
compact darktable-style top bar (logo + pipe-separated view tabs), denser 15px base
- Done via design tokens (Tailwind slate/brand/radius/shadow remap) — minimal churn
Metadata & collections (Phase A/B):
- exifr now captures GPS + camera; asset table ALTER-migrated (gpsLat/gpsLon/camera,
metaVersion backfill on re-index)
- Collection facet bar (year timeline / camera / color-label) filters the grid
Map & relation finder (Phase C):
- Leaflet + online OSM map tab; geotagged photos as markers
- relationService: related photos by place (GPS<1km) + time (+/-2d) + CLIP similarity
Easy mode (Phase D):
- easyMode setting (menu / onboarding); scales the whole UI (rem) + bigger thumbnails
+ large icon nav with plain labels (4050 accessibility)
Library usability:
- Video thumbnails (representative frame capture in the inference worker)
- Media filter (All / Photos / Videos) to separate them
- Clearer culling labels ("Good shots" / "To cull") + explanation tooltip
- Multi-select tiles -> Export selected to a folder (copy, best-cut extraction) and
Delete to Recycle Bin (shell.trashItem) behind a confirm dialog
- ONNX Runtime wasm bundled locally (offline) via copy-ort-wasm + asarUnpack
Docs: DARKTABLE_REVIEW (feasibility + roadmap A->D). All typecheck/tests/build green;
boot smoke verified each phase.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
108 lines
9.8 KiB
Markdown
108 lines
9.8 KiB
Markdown
# darktable 차용 검토 & 메타데이터/탐색 기능 로드맵
|
||
|
||
> 상태: 검토/계획 초안 · 2026-06-01
|
||
> 대상: darktable 5.4.1 소스(C/GTK/Lua) 참고 + PhotoAI 기획서("메타데이터 기반 자동 분류/연관 탐색")
|
||
> 베이스: 현재 PhotoAI (Electron + React/TS, 인덱스 DB + 얼굴/CLIP/컬링)
|
||
|
||
---
|
||
|
||
## 0. 먼저, 솔직한 핵심 정정 2가지
|
||
|
||
**(1) "darktable 엔진을 가져다 쓴다"는 건 사실상 불가합니다 — 하지만 안 가져와도 됩니다.**
|
||
- darktable은 **C/GTK/Lua** 데스크톱 앱입니다. 우리는 **Electron/TypeScript**라 darktable의 코드/엔진을 in-process로 링크할 수 없습니다.
|
||
- darktable을 끌어오는 유일한 방법은 (a) 바이너리 동봉 후 CLI 호출(`darktable-cli`) 또는 (b) 같은 하위 라이브러리(`exiv2`) 사용인데, **둘 다 GPL3 전염 + 무거운 네이티브 의존**(우리가 better-sqlite3에서 겪은 빌드 지옥)을 유발합니다. 권장하지 않습니다.
|
||
- **좋은 소식**: darktable이 메타데이터에 쓰는 기능 대부분을, 우리는 **이미 설치된 `exifr`로 그대로 얻습니다.** exifr는 EXIF뿐 아니라 **GPS(위도/경도), IPTC, 카메라/렌즈** 까지 파싱합니다. 즉 "메타데이터 추출 엔진"은 **darktable 없이 이미 확보**되어 있습니다.
|
||
|
||
→ 결론: **darktable의 코드가 아니라 "검증된 UX 패턴과 데이터 모델"을 차용**하고, 추출은 exifr로 우리 스택에서 재구현합니다. (GPL/네이티브 회피)
|
||
|
||
**(2) 기획서의 "자녀별 자동 분류(시나리오 A)"는 이미 상당 부분 구현되어 있습니다.**
|
||
- 우리 **정리(Organize) 탭 = 얼굴 인식으로 인물(자녀)별 + 날짜별 폴더 자동 분류**. 이게 정확히 시나리오 A입니다. "AI 태깅"을 새로 만들 필요 없이 기존 얼굴 매칭이 그 역할을 합니다.
|
||
- 따라서 이번 단계의 **진짜 새 가치는 "장소(GPS) 기반 탐색"과 "탐색 UX(필터 트리/타임라인/지도)", "4050 쉬운 모드"** 입니다.
|
||
|
||
---
|
||
|
||
## 1. darktable에서 가져올 만한 것 (모듈 매핑)
|
||
|
||
| darktable 소스 | 개념 | 우리 차용 방식 | 가치 |
|
||
|----------------|------|----------------|------|
|
||
| `views/lighttable.c` | 그리드 + 필름스트립 + 별점/색라벨 + 줌 | **이미 보유**(라이브러리 그리드/별점/색라벨). 필름스트립/줌은 보강 여지 | 중 |
|
||
| `libs/collect.c` | 좌측 **컬렉션 필터 트리**(폴더/날짜/카메라/태그/색라벨/평점/**GPS 위치**) | 우리 인덱스 DB로 **필터 트리 패널** 재구현 | **높음** |
|
||
| lighttable 하단 | **타임라인**(연/월 빠른 이동) | 인덱스의 exifYear/Month로 타임라인 바 | **높음** |
|
||
| `views/map.c` + `libs/geotagging.c` | **GPS 지도 뷰** + 지오태깅 | Leaflet(JS) + OSM 타일로 지도/클러스터 재구현 | **높음(신규)** |
|
||
| `libs/metadata.c` / `metadata_view.c` | 메타데이터 표시 + **XMP 사이드카** | 메타 패널은 재구현. XMP는 **선택적 내보내기**(상호운용) | 중 |
|
||
| `libs/tagging.c` | 태그 | 향후(현재 별점/색라벨로 일부 대체) | 낮음 |
|
||
| `views/darkroom.c` | RAW 편집 | **비목표(기획서 동의)** — 복잡도의 근원, 제외 | - |
|
||
|
||
---
|
||
|
||
## 2. 우리 현황 ↔ 기획서 매핑
|
||
|
||
| 기획서 항목 | 현재 상태 | 필요 작업 |
|
||
|-------------|----------|-----------|
|
||
| 자녀별 자동 분류(시나리오 A) | ✅ **구현됨**(정리 탭, 얼굴+날짜) | (유지) |
|
||
| 메타데이터 추출(EXIF) | ✅ 부분(촬영일) | **GPS/IPTC/카메라 추가**(exifr, 쉬움) |
|
||
| 썸네일 캐싱/프리뷰 | ✅ 구현됨(canvas→webp) | (유지) |
|
||
| 컬렉션 필터 트리(인물/연/도시) | ❌ | **신규** — 인덱스 기반 트리 패널 |
|
||
| 타임라인 | ❌ | **신규** — 연/월 스크롤 바 |
|
||
| 장소/여행지 탐색(시나리오 B) | ❌ | **신규** — GPS 지도 + 연관 탐색 |
|
||
| Relation Finder(동일 GPS/시간) | ❌ | **신규** — GPS+시간(+인물) 연관 그룹 |
|
||
| 4050 쉬운 모드(대형 버튼/구어체) | ❌ | **신규** — 접근성 UI 모드 |
|
||
| XMP 사이드카 | ⚠️ 우리 SQLite 인덱스가 대체 | **선택** — 내보내기로 상호운용 |
|
||
| 사용성(구어체 레이블) | ⚠️ 일부 | 쉬운 모드와 함께 |
|
||
|
||
---
|
||
|
||
## 3. 기획서 평가 + 정정 제안
|
||
|
||
- 👍 방향성(메타데이터 기반 분류 + 연관 탐색 + 단순 UX)은 우리 자산과 잘 맞습니다.
|
||
- ✏️ **정정 1**: "darktable 엔진 확보"는 exifr로 대체(§0-1). 기술 리스크/라이선스 회피.
|
||
- ✏️ **정정 2**: "AI 태깅으로 자녀 분류"는 이미 있는 **얼굴 인식**으로 충족(§0-2). 중복 개발 불필요.
|
||
- ➕ **추가 제안**: 연관 탐색을 GPS만이 아니라 **GPS + 시간 + 인물(얼굴) + 시각유사도(CLIP)** 를 결합하면 darktable보다 강력합니다(darktable엔 얼굴/의미검색이 없음). "이 사진과 관련된 사진" = 같은 장소·시기·인물·비슷한 장면.
|
||
- ➕ **추가 제안**: "쉬운 모드"는 별도 앱이 아니라 **기존 UI에 토글되는 접근성 레이아웃**으로 — 유지보수 1벌.
|
||
|
||
---
|
||
|
||
## 4. 리파인된 로드맵 (제안)
|
||
|
||
- **Phase A — 풍부한 메타데이터 캡처** *(선행, 저비용)*
|
||
인덱서의 exifr 호출을 확장해 **GPS(위/경도) · 카메라/렌즈 · IPTC**를 인덱스 DB에 저장. (지도/필터 트리의 데이터 토대)
|
||
- **Phase B — 컬렉션 필터 트리 + 타임라인** *(탐색 UX 핵심)*
|
||
좌측 패널: **인물 / 연도 / 도시(역지오코딩) / 카메라**로 즉시 필터. 하단 **타임라인**으로 연·월 점프. (darktable collect.c + lighttable 타임라인)
|
||
- **Phase C — 지도(Place) 뷰 + Relation Finder** *(시나리오 B)*
|
||
GPS 좌표를 지도에 클러스터로 표시. 사진 클릭 → **연관 사진**(같은 장소·시기·인물·유사장면) 패널. (darktable map.c를 우리식으로)
|
||
- **Phase D — 4050 쉬운 모드(접근성)** *(차별화 UX)*
|
||
대형 버튼·큰 썸네일·구어체 레이블("언제 찍었나요?/어디인가요?")의 **토글형 간편 레이아웃**. (기획서 "리모컨 UI")
|
||
- **(선택) XMP 사이드카 내보내기** — Lightroom/darktable 상호운용.
|
||
|
||
> 권장 1순위: **Phase A + B**(데이터 + 탐색 UX). 우리가 이미 색인한 자산이 즉시 "탐색 가능한 라이브러리"가 됩니다. GPS 지도(C)는 그 다음, 쉬운 모드(D)는 UX 마감.
|
||
|
||
---
|
||
|
||
## 5. 결정 — 확정(2026-06-01)
|
||
- **진행**: **A+B 먼저**(메타데이터 + 컬렉션 트리/타임라인). 이후 C(지도) → D(쉬운 모드).
|
||
- **지도 타일(Phase C)**: **온라인 OSM**.
|
||
- 비고: 라이브러리 그리드의 **인물(자녀)별 필터**는 인덱스에 얼굴-프로필 매칭을 저장하는 후속 작업(B.2)으로 둠. A+B는 연도/카메라/평점/색라벨/타임라인 우선.
|
||
|
||
## 5-1. 구현 현황
|
||
|
||
- [x] **Phase A 완료(2026-06-01)**: exifr로 **GPS(위/경도) + 카메라 모델** 추출(`readMeta`), `asset` 테이블에 `gpsLat/gpsLon/camera` 컬럼 + 기존 DB **ALTER 마이그레이션**. `metaVersion`으로 구버전 행은 재색인 시 **GPS/카메라 backfill**(기존 썸네일 재사용 → 저비용). 부팅 시 110-asset DB 마이그레이션 무오류 확인.
|
||
- [x] **Phase B 완료(2026-06-01)**: `indexDb.facets`(연도/카메라/색라벨 집계) + `AssetQuery` 확장(year/camera/label) + 라이브러리 그리드에 **컬렉션 패싯 바**(연도 타임라인 · 카메라 칩 · 색라벨, 카운트 포함) 추가. 필터는 즉시 그리드에 반영.
|
||
- 비고: **인물(자녀)별 필터**(B.2)와 **월 단위 타임라인**, **쉬운모드(D)**는 후속. 기존 사진의 GPS/카메라는 **재색인 1회**로 채워짐.
|
||
- [x] **Phase C 완료(2026-06-01)**: **Leaflet + 온라인 OSM 타일** 지도 탭 — GPS 사진을 마커로 표시(클릭 시 썸네일 팝업). **연관 탐색(Relation Finder)**: `relationService`가 **장소(GPS 1km 이내) + 시간(±2일) + 시각유사도(CLIP)** 를 결합해 "이 사진과 관련된 사진"을 랭킹(darktable의 GPS 연관에 인물/의미까지 확장). CSP에 OSM 타일 도메인 허용. typecheck/build/부팅 스모크 통과.
|
||
- [x] **Windows 설치파일 빌드**: `AI Photo Organizer-0.1.0-win-x64.exe`(190MB, ORT wasm/모델 동봉, asar 언팩 검증).
|
||
- [x] **Phase D 완료(2026-06-01)**: **4050 쉬운 모드** — `easyMode` 설정(영속화) 토글(메뉴 보기 · 온보딩). 켜면 `<html class="easy">`로 ① rem 기준 **전체 UI 확대**(16→20px) ② **썸네일 그리드 3열로 큼직** ③ 상단이 **대형 아이콘+구어체 버튼**(사진 정리/내 사진/사진 찾기/지도/중복 정리). 기존 UI를 토글 1벌로 재사용(유지보수 단순). typecheck/build/부팅 스모크 통과.
|
||
|
||
## 7-1. 최종 구현 현황 (요약)
|
||
|
||
탭 5개: **정리 / 라이브러리 / 검색 / 지도 / 그룹·정화** + **쉬운 모드** 토글.
|
||
- 정리: 얼굴+날짜 자동 분류(시나리오 A) · 라이브러리: 색인/썸네일/컬링/별점·색라벨/컬렉션 필터(연도·카메라)
|
||
- 검색: CLIP 자연어(한국어 번역) · 지도: GPS+연관탐색(시나리오 B) · 그룹·정화: 근접중복+휴지통
|
||
- 남은 후속: 인물(자녀)별 필터(B.2) · 월 타임라인 · 역지오코딩(도시명) · 가족 공유(미래)
|
||
|
||
## 6. (구) 결정이 필요했던 사항
|
||
|
||
1. **지도 타일 소스**: 온라인 OSM 타일(간단, 인터넷 필요) vs 오프라인 타일 동봉(용량 큼). → 온라인 권장(로컬-퍼스트지만 지도는 예외적으로 온라인 허용).
|
||
2. **역지오코딩(좌표→도시명)**: 온라인 API(Nominatim 등, 쿼터/인터넷) vs 좌표만 표시. → v1은 좌표/지도 우선, 도시명은 후속.
|
||
3. **쉬운 모드 범위**: 별도 단순 화면 1개 vs 전체 탭의 대형화 토글.
|
||
4. **진행 우선순위**: A+B 먼저 / 지도(C) 우선 / 쉬운 모드(D) 우선 / 전부.
|