Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 82 additions & 81 deletions README.ko.md
Original file line number Diff line number Diff line change
@@ -1,119 +1,120 @@
<div align="center">
<img src="apps/web/public/logo.png" width="72" alt="쯔동여지도 로고" />
<h1>쯔동여지도 · Tzudong Map</h1>
<p>쯔양 영상에 등장한 맛집을 지도에서 찾고, 방문 경험을 나누는 서비스입니다.</p>
<p>
<img src="apps/web/public/logo.png" width="72" alt="쯔동여지도 로고" />
</p>
<h1>Tzudong Map</h1>
<p><strong>쯔양 영상 속 맛집을 지도 중심으로 탐색하는 제품입니다.</strong></p>
<p>
<a href="https://tzudong.app">라이브 앱</a>
·
<a href="https://github.com/twoimo/tzudong/releases/latest">최신 릴리즈</a>
·
<a href="README.md">English</a>
·
<a href="https://www.tzudong.app">지도 둘러보기</a> ·
<a href="README.md">English</a> ·
<a href="docs/README.md">문서 안내</a> ·
<a href="CHANGELOG.ko.md">변경 기록</a>
·
<a href="LICENSE">MIT</a>
</p>
<p>
<img alt="Next.js 16" src="https://img.shields.io/badge/Next.js-16-black?logo=nextdotjs" />
<img alt="React 19" src="https://img.shields.io/badge/React-19-149eca?logo=react&logoColor=white" />
<img alt="TypeScript" src="https://img.shields.io/badge/TypeScript-strict-3178c6?logo=typescript&logoColor=white" />
<img alt="Supabase" src="https://img.shields.io/badge/Supabase-PostgreSQL%20%2B%20Auth-3ecf8e?logo=supabase&logoColor=white" />
<img alt="Runtime" src="https://img.shields.io/badge/runtime-Node%2024.x%20%2B%20Bun-c8a2c8" />
<img alt="React 19" src="https://img.shields.io/badge/React-19-149eca?logo=react&amp;logoColor=white" />
<img alt="TypeScript" src="https://img.shields.io/badge/TypeScript-strict-3178c6?logo=typescript&amp;logoColor=white" />
<img alt="Supabase" src="https://img.shields.io/badge/Supabase-PostgreSQL%20%2B%20Auth-3ecf8e?logo=supabase&amp;logoColor=white" />
</p>
</div>

---
[기능](#기능) · [미리보기](#미리보기) · [로컬 개발](#로컬-개발) · [저장소 구성](#저장소-구성) · [문서 안내](#문서-안내)

Tzudong Map은 먹방 영상의 장소 근거를 사용자용 지도, 운영자용 검수 콘솔, 콘텐츠 제작용 스토리보드 워크스페이스로 바꿉니다.
## 기능

[핵심 기능](#핵심-기능) · [스택](#스택) · [빠른 시작](#빠른-시작) · [제품 투어](#제품-투어)
- **맛집 탐색:** 국내·해외 지도에서 맛집을 검색·필터링하고, 상세 패널에서 영상 출처를 확인합니다.
- **방문 경험 공유:** 리뷰, 도장, 랭킹, 좋아요, 프로필을 통해 방문 기록과 커뮤니티 활동을 이어갑니다.
- **데이터 관리:** 보호된 관리자 콘솔에서 검수, 출처 확인, 승인과 변경 이력을 관리합니다.
- **콘텐츠 제작:** 스토리보드·썸네일 워크스페이스에서 기획, 생성, 수정을 진행합니다.
- **영상 근거 처리:** 백엔드 워커가 크롤링, 평가, 미디어 처리와 공개용 데이터 생성을 담당합니다.

## 핵심 기능

| 제품 영역 | 역할 |
| --- | --- |
| **지도 탐색** | 검색, 필터, 음식 마커 클러스터, 현재 위치 흐름, 맛집 상세 바텀시트. |
| **커뮤니티 루프** | 리뷰, 도장, 랭킹, 좋아요, 프로필 화면으로 반복 사용 경험 구성. |
| **관리자 운영** | 보호된 검수, source readback, 승인/삭제/복원, 감사 가능한 mutation 흐름. |
| **스토리보드 워크스페이스** | 채팅 기반 기획, 10컷 생성, 컷 메타데이터, 이미지 재생성, provider readiness UX. |
| **근거 중심 파이프라인** | 크롤링, Rule/LLM-as-a-Judge 평가, fail-closed 검증, Supabase 적재 payload 생성. |
## 미리보기

## 스택
저장소에 보존된 화면 시연입니다.

- 프런트엔드: Next.js 16 (App Router), React 19, Tailwind CSS, Lucide 아이콘.
- 웹 런타임: Node 24.x. 일상 설치/유닛은 Bun을 쓸 수 있고, 릴리스 패키지 권위는 npm 11.6.2, `package.json`, `package-lock.json`입니다.
- TypeScript: 네이티브 CLI `@typescript/native` `7.0.2`, 안정 API/호환 브리지는 `6.0.2` (`npm run typecheck:parity`).
- 직렬 승격: `develop -> data -> main`. 이 트리는 hosted apply, 법령 준수, 라이브 URL 상태를 주장하지 않습니다.
- 변경 기록: [CHANGELOG.ko.md](CHANGELOG.ko.md) / [CHANGELOG.md](CHANGELOG.md).
- 문서 색인: [docs/README.md](docs/README.md). 제품 설계: [docs/product/DESIGN.md](docs/product/DESIGN.md).

## 빠른 시작

Node 24.x와 npm 11.6.2를 사용합니다. 웹 패키지는 `apps/web`에 있습니다.
<p align="center">
<img src="apps/web/public/images/readme-product-tour.gif" width="900" alt="데스크톱 지도 탐색과 맛집 상세 화면" />
</p>

```bash
git clone https://github.com/twoimo/tzudong.git
cd tzudong/apps/web
npm ci
```
<details>
<summary>모바일 화면과 스토리보드 워크스페이스</summary>

저장소가 관리하는 [로컬 Supabase 스택](backend/supabase/README.md)을 준비하고 마이그레이션한 뒤, `apps/web`에서 실행합니다.
<table>
<tr>
<td width="50%"><strong>홈 지도</strong><br /><img src="apps/web/public/images/readme-mobile-home-map.gif" alt="모바일 지도와 맛집 상세 화면" /></td>
<td width="50%"><strong>리뷰 피드</strong><br /><img src="apps/web/public/images/readme-mobile-reviews-feed.gif" alt="모바일 리뷰 피드" /></td>
</tr>
<tr>
<td width="50%"><strong>도장</strong><br /><img src="apps/web/public/images/readme-mobile-stamp-passport.gif" alt="모바일 도장 화면" /></td>
<td width="50%"><strong>랭킹·프로필</strong><br /><img src="apps/web/public/images/readme-mobile-leaderboard-ranking.gif" alt="모바일 랭킹과 프로필" /></td>
</tr>
</table>

```bash
npm run dev -- --port 8080
```
![스토리보드 워크스페이스](apps/web/public/images/readme-storyboard-demo.gif)

[http://127.0.0.1:8080](http://127.0.0.1:8080)을 엽니다. 개발 실행기는 생성된 로컬 스택, 허용된 브라우저 origin, 마이그레이션 ledger를 검증한 뒤 webpack으로 Next.js를 시작합니다. Bun 명령과 명시적 hosted 디버깅은 [웹 개발 안내](apps/web/README.md)를 참고하세요.
</details>

## 제품 투어
## 로컬 개발

### Desktop
[apps/web/package.json](apps/web/package.json)에 선언된 **Node.js 24.x**와 **npm 11.6.2**를 사용합니다. 로컬 데이터베이스에는 Python 3와 Docker Compose도 필요합니다. 고정된 도구 버전과 준비 사항은 [로컬 스택 운영 안내](docs/operations/nightly-regression.md#local-compose-bootstrap)를 따릅니다.

**지도 탐색과 맛집 상세**
1. 저장소를 복제하고 웹 의존성을 설치합니다.

<p align="center">
<img src="apps/web/public/images/readme-product-tour.gif" width="900" alt="쯔동여지도 데스크톱 제품 투어" />
</p>
```sh
git clone https://github.com/twoimo/tzudong.git
cd tzudong/apps/web
npm ci
```

**관리자 스토리보드 워크스페이스**
2. 저장소 루트에서 [준비 절차](docs/operations/nightly-regression.md#local-compose-bootstrap)에 따라 저장소가 관리하는 [로컬 Supabase 스택](backend/supabase/README.md)을 생성하고 마이그레이션합니다.
3. `apps/web`로 돌아와 개발 서버를 실행합니다.

![10컷 스토리보드를 생성하는 스토리보드 워크스페이스](apps/web/public/images/readme-storyboard-demo.gif)
```sh
npm run dev
```

### Mobile
[http://127.0.0.1:3000](http://127.0.0.1:3000)을 엽니다. 실행기는 생성된 로컬 환경, 서비스 준비 상태, 브라우저 origin, 마이그레이션 대장을 확인한 뒤 Next.js를 시작합니다. Hosted 디버깅과 지도 공급자 설정은 [웹 개발 안내](apps/web/README.md)를 참고하세요.

<table>
<tr>
<td width="50%"><strong>홈 지도</strong><br /><small>마커 탐색 → 맛집 상세 전체 보기</small><br /><img src="apps/web/public/images/readme-mobile-home-map.gif" alt="홈 지도 마커 탐색과 맛집 상세 전체 화면 모바일 데모" /></td>
<td width="50%"><strong>리뷰 피드</strong><br /><small>리뷰 스크롤 → 맛집 상세 열기</small><br /><img src="apps/web/public/images/readme-mobile-reviews-feed.gif" alt="리뷰 피드 모바일 데모" /></td>
</tr>
<tr>
<td width="50%"><strong>도장 페이지</strong><br /><small>도장 맛집 탐색 → 상세 읽기</small><br /><img src="apps/web/public/images/readme-mobile-stamp-passport.gif" alt="도장 페이지 모바일 데모" /></td>
<td width="50%"><strong>랭킹 프로필</strong><br /><small>1위 프로필 → 탭 전환</small><br /><img src="apps/web/public/images/readme-mobile-leaderboard-ranking.gif" alt="랭킹과 프로필 모바일 데모" /></td>
</tr>
</table>
일상 개발에는 Bun도 사용할 수 있습니다. 릴리스 패키지의 기준은 npm manifest와 lockfile입니다. `apps/web`에서 사용하는 주요 검사 명령은 다음과 같습니다.

## 로컬 아키텍처
```sh
npm run lint
npm run test:unit
npm run typecheck:parity
```

대화형 워크플로: [storyboard-local-mlx.html](docs/architecture/storyboard-local-mlx/storyboard-local-mlx.html)
변경한 동작에 필요한 검사는 [검증 안내](docs/agents/verification.md)에 따라 선택합니다.

워크플로 소스: [storyboard-local-mlx.workflow.json](docs/architecture/storyboard-local-mlx/storyboard-local-mlx.workflow.json)
## 저장소 구성

대화형 라이프사이클: [storyboard-local-mlx.lifecycle.html](docs/architecture/storyboard-local-mlx/storyboard-local-mlx.lifecycle.html)
| 경로 | 역할 |
| --- | --- |
| [apps/web/](apps/web/) | Next.js 공개 앱, 맛집 지도, 커뮤니티, 보호된 관리자 콘솔. |
| [backend/](backend/) | 파이프라인 제어, 크롤러, 평가, 미디어 워커, Supabase 마이그레이션. |
| [docs/](docs/) | 제품 설계, 아키텍처, 운영과 릴리스 안내. |

라이프사이클 소스: [storyboard-local-mlx.lifecycle.json](docs/architecture/storyboard-local-mlx/storyboard-local-mlx.lifecycle.json)
웹 앱과 백엔드 워커는 Supabase를 데이터 저장 경계로 사용합니다. 오래 걸리는 크롤링·미디어 처리는 백엔드 워커가 맡습니다. 상세 흐름은 [백엔드 아키텍처](backend/ARCHITECTURE.md)와 [데이터 계약](backend/DATA_CONTRACTS.md)에 있습니다.

대화형 지도 발견: [map-discovery.html](docs/architecture/map-discovery/map-discovery.html)
| 웹 스택 | 도구·서비스 |
| --- | --- |
| Next.js 16 · React 19 · TypeScript | Tailwind CSS · Radix UI · Lucide |
| Node.js 24.x · npm 11.6.2 | 일상 개발용 Bun |
| Supabase | PostgreSQL · Auth · Storage |

지도 발견 소스: [map-discovery.workflow.json](docs/architecture/map-discovery/map-discovery.workflow.json)
정확한 의존성은 [package.json](apps/web/package.json)과 [package-lock.json](apps/web/package-lock.json)을 기준으로 확인합니다.

라이프사이클 첫 화면은 세 가지 경계를 모델합니다. 메모리: 통합 RAM (M=128 GiB), 이미지 동시성 (c=1), 상주 (sum r_i <= M_headroom) (디스크 존재는 상주가 아닙니다. PNG 원본과 WebP 파생본은 모델 예산 밖입니다). 큐 대기: (W=t_claim-t_enqueue) if a live heartbeat exists, else (W=inf) with no cloud failover (stale leaseToken -> 409 worker_lease_lost). FSM 불변식: revision_conflict / project_busy / exclusive claim / lease_lost no durable write / restore = 불변 스냅샷에서 새 리비전(모델 호출 없음) / fail-closed / serial scenes / no stale overwrite. Viewer UI는 meta.locale이 생략되어 영어로 떨어집니다.
## 문서 안내

외부 인공지능은 기본 비활성화입니다. 텍스트와 이미지 공급자는 서로 독립입니다(`local-mlx`, `chatgpt-manual`, `grok-manual`; `manual`, `openai-api`, `xai-api`는 명시적으로 켠 경우에만). 큐에 넣은 것만으로 성공이 아닙니다. 워커가 작업을 원자적으로 claim하고, 루프백 `mlx-serve`를 호출하고, PNG 원본과 WebP 파생본을 저장한 뒤 관리자 UI가 결과를 다시 읽어야 합니다. 가드는 원자적 claim, lease/heartbeat 만료, revision/version 충돌입니다. 복원은 이제 불변 DB 스냅샷을 사용합니다. 버전 미리보기와 확인된 프로젝트 전체/단일 장면 복원이 과거 텍스트, 장면 순서, 에셋 참조, 출처, 원본 이미지 바이트를 보존합니다. 복원은 모델 호출이나 작업 큐잉 없이 새 리비전을 쓰고, 현재 공급자 설정과 동의는 그대로 유지합니다. 적용된 프로젝트의 이력은 마이그레이션이 캡처한 상태에서 시작하며 지어낸 이전 버전을 만들지 않습니다. 소유자/관리자 확인, 현재 리비전, 사용 중 프로젝트 거부, 멱등 요청 ID가 이 작업을 보호합니다. 다이어그램은 의도된 파이프라인을 설명합니다. 호스티드 apply와 실제 운영 세션은 별도 증거입니다.
| 시작점 | 내용 |
| --- | --- |
| [문서 색인](docs/README.md) | 공통 안내와 문서별 위치. |
| [웹 개발](apps/web/README.md) | 로컬·Hosted 개발, 환경 설정, 웹 명령. |
| [백엔드 운영](backend/README.md) | 파이프라인 진입점, 환경변수 계약, 실행 요약. |
| [제품 설계](docs/product/DESIGN.md) · [아키텍처 도식](docs/architecture/) | 제품 화면과 시스템 구조. |
| [검증](docs/agents/verification.md) · [Nightly 운영](docs/operations/nightly-regression.md) | 변경 범위별 검사와 독립 회귀 검사. |
| [릴리스 안내](docs/agents/release.md) | 보호된 승격, 롤백, 배포 후 확인. |
| [성능 근거](apps/web/performance/) · [변경 기록](CHANGELOG.ko.md) | 측정 시점·범위·한계와 변경 이력. |

## 개인정보
변경은 보호된 `develop → data → main` 순서로 승격합니다. 운영 배포에는 릴리스 안내에 따른 커밋 승인과 배포 후 확인이 필요합니다. CI, Nightly 회귀 검사, 운영 배포 상태는 각각 기록합니다.

소스 보호는 fail-closed입니다. 회원 생성은 게시된 방침 확인에 묶이고, 검증된 보호자 경로가 있기 전까지 만 14세 미만 가입은 막히며, 광고 동의는 목적/채널/야간을 분리하고, 공용 필터와 메모리 전용 기기 위치, 삭제·보존·사고의 Preview → Confirm → Apply → Readback → Audit을 유지합니다.
## 보안과 라이선스

이 보호 장치는 법령 준수나 운영 증명이 아닙니다. 외부 증거 게이트는 2026-09-22에 보류되었으며 제품 보호 장치는 계속 fail-closed로 유지됩니다. 현재 승격, 롤백, 배포 readback 요건은 [docs/agents/release.md](docs/agents/release.md)를 따릅니다. 위 라이브 앱/릴리즈 링크는 상태 참조일 뿐입니다.
보안 문제는 [SECURITY.md](SECURITY.md)에 따라 제보해 주세요. 소스 라이선스는 [MIT](LICENSE)입니다.
Loading
Loading