# SaaS 운영 리팩토링 — 로드맵 + Phase 0(정리·삭제) 설계 - 날짜: 2026-07-02 - 배경: 4개 병렬 감사(공개 라우트/API/보존 서브시스템/admin)로 전 기능의 생사를 판정한 뒤, CEO가 운영 비전을 재정의함. 이 문서는 전체 로드맵과 Phase 0 상세 설계를 담는다. --- ## 1. 운영 비전 (CEO 확정) ### 1축 — SaaS 외주 개발 (메인) - 모든 의뢰는 **발주서**로 관리 - 외주 프로그램 소개 페이지 (제품 소개 + 제품/의뢰 금액) - 의뢰 폼 ↔ 이메일 연동 - 회원 관리 + 회원 페이지 (회원 정보, 발주서 확인) - 관리자: 발주 관리 · 회원 관리 · 수익 관리 · 노출 서비스 관리 · 제품 관리 · 광고 관리 - 완성 제품(웹사이트·프로그램) 예시 페이지 ### 2축 — 별도 서비스 - **사주**: 회원별로 보고, 결과를 마이페이지에서 재확인 - **타로**: 동일 패턴 (이 repo에 자체 구현) - **음악**: "나의 이야기를 음악으로" — 개별 음악 제작 + 영상화까지, 고도화 필요 ### 핵심 결정 (2026-07-02 Q&A) | 결정 | 내용 | |------|------| | 발주서 정의 | **견적 수락 시 그 견적이 발주서로 전환**. 기존 contact→quote→order 상태머신 유지, 문서 개념만 통합. 마이페이지·admin 모두 발주서 중심 리네이밍 | | 타로 구축 | 이 repo 자체 구현 (Next.js API에서 AI 직접 호출 + Supabase 회원별 저장). NAS tarot-lab 연동 아님 | | 과금 | 별도 서비스(사주·타로·음악 체험) **무료**, **음악 영상화만 유료(계좌이체)**. 외주는 기존 발주서·계좌이체 | | 삭제 확정 | eBay 세트 + packages/subscription + PortOne 잔재 | | gyeol/CONTOUR | **의도적 숨김 보존** (삭제 안 함) | | IA 재편 시점 | Phase 0은 삭제만. TopNav·홈 개편은 각 Phase에서 해당 기능과 함께 | --- ## 2. 로드맵 (4 Phase 순차, 각자 독립 스펙→플랜→구현) | Phase | 내용 | 스펙 | |-------|------|------| | **0** | 정리·삭제 (이 문서) | 이 문서 §3 | | **1** | 외주 코어 — 발주서 개념 통합(마이페이지·admin 리네이밍+뷰), `/work/website/samples` 8종을 "완성 제품 예시"로 정식 재노출, projects API 마이페이지 배선, admin 광고 관리 신설(admin/marketing 재편) | 추후 | | **2** | 사주 재활성(무료화) + 타로 신규 구현, 회원별 결과 저장·마이페이지 재확인 탭 | 추후 | | **3** | 음악 고도화 — 스토리 입력→음악 생성→영상화(유료·계좌이체 발주), studio 콜백 결함 해소 | 추후 | **순차 이유**: 삭제부터 하면 이후 작업의 탐색 노이즈가 사라짐. mypage와 service_settings를 여러 Phase가 만지므로 병렬 진행 시 충돌. 매 Phase가 배포 가능 상태로 종료. --- ## 3. Phase 0 상세 — 정리·삭제 원칙: **비전에 없는 기능 + 도달 불가능한 죽은 코드 제거. IA(네비·홈)는 건드리지 않음.** 외부 URL 호환을 위해 next.config.ts 리다이렉트는 전부 유지. ### 3-1. 삭제 목록 #### A. eBay 세트 (특정 클라이언트 제안용 리드 도구 — 용도 종료) | 대상 | 경로 | |------|------| | 문진 제출 API | `app/api/questionnaire/submit/route.ts` | | admin 문진 페이지 | `app/admin/questionnaire/page.tsx` | | admin 문진 API | `app/api/admin/questionnaire/route.ts`, `app/api/admin/questionnaire/[id]/route.ts` | | admin 문서 페이지 | `app/admin/documents/page.tsx` | | admin 문서 API | `app/api/admin/documents/[filename]/route.ts` | | eBay 라이브러리 | `lib/ebay-tools/` (crawler·pricing·ai-analyzer·types, import 0회 확인) | | 콘텐츠 | `CONTENT/ebay-tool-questionnaire.html`, `CONTENT/ebay-tool-proposal.html`, `CONTENT/ARCHITECTURE_EBAY_PARTS_TOOL.md` | | 사이드바 | AdminSidebar에서 문진·문서 메뉴 항목 제거 | | DB | `questionnaire_responses`, `ebay_search_history` DROP | #### B. packages + subscription (SaaS 피벗 잔재 — 재개 시 재설계) | 대상 | 경로 | |------|------| | 페이지 | `app/packages/` (page + layout) | | 카탈로그 | `lib/saas-catalog.ts` (빈 배열) | | 구독 API | `app/api/subscription/route.ts`, `app/api/subscription/[id]/route.ts` (프론트 호출 0회) | | 구독 cron | `app/api/cron/subscription-expiry/route.ts` + `vercel.json` crons 항목(유일 항목이므로 crons 비움) | | 서비스 토글 | `service_settings`에서 `packages` 행 제거, admin/services 목록·`HideableService` 타입에서 `'packages'` 제거 | | DB | `subscriptions` DROP | **파급 수정 (subscriptions 참조 3곳)**: - `app/api/admin/stats/route.ts` — 구독 집계 제거 - `app/api/admin/members/route.ts` — 구독 카운트 제거 - `app/work/saju/result/page.tsx` — 구독 확인 로직 제거 (사주 무료화 방향과 일치) #### C. PortOne 결제 잔재 (계좌이체 단일 소스 확정) | 대상 | 경로 | |------|------| | 컴포넌트 | `app/components/PaymentButton.tsx` | | 페이지 | `app/payment/` 전체 (test — 코드 스스로 "배포 전 삭제" 명시 · fail · success) | | API | `app/api/payment/confirm/route.ts` | | 라이브러리 | `lib/payment-channels.ts`, `lib/products.ts` (소비처가 전부 삭제 대상임을 확인) | | 의존성 | `@portone/browser-sdk` (package.json) | **파급 수정**: `app/work/saju/page.tsx`, `app/work/saju/result/SajuAISection.tsx`의 PaymentButton import·사용 제거 (무료 전환). `/payment/success`로 push하는 코드는 PaymentButton뿐이므로 함께 소멸. #### D. 리다이렉트에 가려 렌더 불가능한 페이지 (redirect는 유지) - `app/work/page.tsx` (`/work`→`/outsourcing`) - `app/work/freelance/page.tsx` (`/work/freelance`→`/outsourcing`) - `app/work/website/page.tsx` (`/work/website`→`/outsourcing`) - `app/music/packs/page.tsx` (`/music/packs`→`/products`) - 전이 고아: `app/components/ContactForm.tsx` (유일 소비처가 죽은 `/work/freelance`), `lib/freelance-portfolio.ts` (소비처가 죽은 `/work`·`/work/freelance`뿐) 주의: `app/work/website/samples/*` 8종은 **삭제 금지** — `/services/website/samples/:slug` 리다이렉트 목적지로 도달 가능하며 Phase 1 재활용 자산. #### E. 2026-06 라이트 재설계 잔재 - `app/components/deepfield/HeroField.tsx` (import 0회, 스펙상 "보존만"이었으나 새 비전으로 폐기 확정) - `app/components/deepfield/useFieldMode.ts` (HeroField 전용) - `lib/deepfield-mode.ts` + `lib/__tests__/deepfield-mode.test.ts` (체인 고아) - 의존성 `three` 제거 (HeroField가 유일 사용처임을 확인) - 잔존: `deepfield/{ScrollReveal,ShowcaseGrid,ShowcaseCard,CountUp}.tsx`는 활성 — 유지 #### F. 고아 API - `app/api/track/[token]/route.ts` — 추적 페이지가 Supabase 직접 조회, 라우트 호출 0회 - `app/api/saju/lotto/route.ts` — 프론트 fetch 0회, 외부 엔진용. 비전 무관 ### 3-2. 유지 목록 (비전에 엮이거나 의도적 보존) | 자산 | 이유 | 활용 Phase | |------|------|-----------| | `app/api/projects/`, `app/api/projects/link/` | "회원 페이지에서 발주서 확인" 용도의 선구현(quotes+milestones 집계) | Phase 1 배선 | | `/work/website/samples/*` 8종 | 완성 제품 예시 페이지 자산 | Phase 1 재노출 | | telegram 3종 (webhook·connect·setup) + `lib/telegram.ts` | mypage 연결 UI 활성, 알림 채널 재활용 여지. 단 subscription-expiry 소비처 제거로 `sendMessage` 소비처가 줄어드는 것은 무방 | Phase 2~3 | | gyeol 세트 (`/gyeol`, `/api/survey`, admin/survey, `survey_responses`) | CEO 의도적 숨김 보존 | — | | `admin/marketing` | 광고 관리로 재편 예정 | Phase 1 | | `admin/packs` 페이지 + `/api/admin/packs*` | 페이지는 자칭 레거시(products가 대체)나 API는 products 페이지·mypage 다운로드가 공유 — Phase 0에서는 건드리지 않고 Phase 1에서 products로 완전 통합 후 페이지 제거 검토 | Phase 1 | | `portfolio/[token]` + `admin/portfolio-token` | 위시캣 등 지원용 토큰 공유 도구 | — | | saju 페이지·API (analyze, save-interpretation) | 별도 서비스 2축, 무료화 후 재활성 | Phase 2 | | music 페이지·studio API | 음악 고도화 기반 (콜백 결함은 Phase 3에서 해소) | Phase 3 | | next.config.ts 리다이렉트 전체 | 외부 유입 URL 호환 | — | ### 3-3. DB 마이그레이션 신규 파일 `supabase/migrations/2026-07-02-phase0-cleanup.sql` 1개: ```sql DROP TABLE IF EXISTS questionnaire_responses; DROP TABLE IF EXISTS ebay_search_history; DROP TABLE IF EXISTS subscriptions; DELETE FROM service_settings WHERE id = 'packages'; ``` - **클라우드 Supabase + NAS self-host 양쪽 적용** (운영 규칙) - `survey_responses`는 건드리지 않음 (gyeol 보존) - 기존 마이그레이션 파일(004_subscriptions.sql 등)은 이력이므로 삭제하지 않음 ### 3-4. 검증 1. `npm test` (vitest) 통과 — deepfield-mode.test.ts 삭제 반영 2. `npm run build` 성공 (standalone) 3. 잔존 참조 grep 스윕 0건: `PaymentButton|payment-channels|lib/products|saas-catalog|ebay|questionnaire|subscription|freelance-portfolio|ContactForm|HeroField|useFieldMode|deepfield-mode|portone|from 'three'` 4. admin 사이드바에서 제거된 메뉴(문진·문서) 링크 없음 확인 5. 수동: `/admin/services`에 packages 미표시, `/admin/dashboard`·`/admin/members` 정상 렌더(구독 집계 제거 후) ### 3-5. 산출물 - 삭제 커밋(들) + 마이그레이션 파일 + CLAUDE.md 갱신(삭제된 기능 서술 제거: PortOne 보존 서술, 숨김 서비스 표에서 packages 등) --- ## 4. Phase 1~3 개요 (각자 별도 스펙에서 상세화) ### Phase 1 — 외주 코어 (발주서 통합) - quotes의 `accepted` 이후 상태를 "발주서"로 표면화: 마이페이지 "내 발주서" 탭(projects API 배선), admin 발주 관리 뷰 리네이밍 - `/work/website/samples/*` → 완성 제품 예시 허브로 재노출(TopNav 반영) - admin "광고 관리" 신설 (admin/marketing 재편) - admin/packs 페이지의 products 통합 마무리 후 페이지 제거 검토 - 이메일 연동 점검 (contact·quote·order Resend 플로우) ### Phase 2 — 사주 + 타로 (회원 연동) - 사주: service_settings 토글 ON + 무료화 + 결과 저장을 회원 계정에 연결, 마이페이지 재확인 탭 - 타로: 자체 구현 (AI 호출 API + 카드 UI + Supabase 저장 + 마이페이지) - TopNav에 별도 서비스 진입점 ### Phase 3 — 음악 고도화 - "나의 이야기를 음악으로": 스토리 입력 → 음악 생성(Suno, 폴링) → 영상화 의뢰(유료·계좌이체 발주서) - `/api/studio/callback` 댕글링 해소(폴링 전용 확정 또는 콜백 구현) --- ## 5. 감사 근거 (2026-07-02 병렬 감사 요약) - 공개 라우트: LIVE 11 / HIDDEN 8 / DEAD-shadowed 4 / ORPHAN 11 - API: admin 21종 전부 ACTIVE, 고아 5~6종(track·saju/lotto·subscription×2·projects×2), 외부 트리거 3종 정상 - admin: 고아 없음, packs만 명시적 레거시(products가 대체) - 고아 파일: ebay-tools 4, deepfield 잔재 3, ContactForm, freelance-portfolio