Files
jaengseung-made/docs/superpowers/specs/2026-07-02-phase1-outsourcing-core-design.md

6.5 KiB

Phase 1 외주 코어 — 발주서 통합 · 제작 사례 허브 · 광고 관리 설계

  • 날짜: 2026-07-02
  • 선행: Phase 0 정리·삭제 (main 머지 완료, 2026-07-02-saas-operation-refactor-phase0-design.md)
  • 배경: 새 운영 비전 1축(SaaS 외주 메인)의 코어 정비. 로드맵은 Phase 0 스펙 §2 참조.

결정 사항 (CEO 확정, 2026-07-02)

결정 내용
발주서 표면화 mypage 내 의뢰 탭을 발주·진행 중심으로 개편 (신규 탭 아님, 4탭 유지)
예시 허브 /showcase 신규 허브 + TopNav 제작 사례. samples 8종 경로는 유지하고 링크만 연결
광고 관리 admin/marketing을 채널·캠페인 관리로 확장 (기존 에셋 기능 유지 + 채널 CRUD 탭)
admin/packs 페이지 제거, API 유지 (products·mypage가 API 공유)

워크스트림 5개 (서로 파일 비중첩, 순차 실행)

WS1. 발주서 — mypage 개편 + admin 뱃지

mypage (app/mypage/page.tsx)

  • 탭 라벨: 내 의뢰발주·진행 (탭 key requests 유지 — URL 호환)
  • 탭 콘텐츠를 projects API 배선으로 교체:
    • GET /api/projects (기존 선구현) → { projects: [{ id, title, status, total, created_at, milestones[] }] }
    • 발주서 카드: 제목 · 상태 뱃지(lib/request-status.ts 라벨 재사용) · 총액(₩ 포맷) · 마일스톤 타임라인(step_number 순, 완료/진행/대기 시각화)
    • accepted 이후 상태 카드에 "발주서 N호" 표기(quotes.id 기반)
  • 견적코드 연결 UI: 탭 상단 접이식 폼 → POST /api/projects/link (body: { code } — 기존 API 계약 그대로) → 성공 시 목록 갱신, 실패 시 에러 메시지
  • 빈 상태: "진행 중인 발주가 없습니다" + 견적코드 입력 + /outsourcing CTA
  • 기존 탭이 렌더하던 콘텐츠는 구현 시 확인 후 대체(주문 정보는 주문 내역 탭이 이미 담당)

admin (app/admin/quotes/page.tsx)

  • 리스트 행에서 accepted/in_progress/completed 상태에 "발주" 뱃지 표면화(라벨 병기). 사이드바 메뉴명·라우트는 변경하지 않음(최소 변경)

WS2. /showcase — 제작 사례 허브

  • 신규 app/showcase/page.tsx (서버 컴포넌트, PublicShell 레이아웃 자동 적용)
    • Hero: "제작 사례" 타이틀 + 운영 실증 카피 한 줄
    • 데모 카드 그리드(8종): bakery·corporate·dashboard·game·interior·portfolio·reading·shopping — 제목·한줄 설명·태그·"데모 보기" 버튼(/work/website/samples/[slug], 새 탭)
    • 실운영 서비스 섹션: NAS 실서비스(로또 랩·주식 대시보드·여행 갤러리 등) 소개 카드 — 링크 없는 텍스트 카드(개인 서비스라 외부 링크 없음)
    • 카피 가드레일: "대기업 N년차" 류 자격 어필 금지, "실서비스 직접 운영" 실증 서술 사용
  • 데이터: 신규 lib/showcase-samples.ts — 8종 메타(slug·title·description·tags) 단일 소스. 단위 테스트 1개(8종 slug 무결성)
  • TopNav (app/components/TopNav.tsx:9-12): { href: '/showcase', label: '제작 사례' } 추가 (외주 개발 / 소프트웨어 / 제작 사례 순)
  • robots.ts (app/robots.ts): disallow에서 죽은 경로 3개(/payment/·/freelance·/services/website) 제거. /showcase는 색인 허용, /work/website/samples/*의 기존 noindex(layout robots)는 유지 — 데모 자체는 검색 노출 안 함
  • 디자인: --jsm-* 토큰만, gradient/blur/보라/이모지 금지

WS3. admin 광고 관리 (marketing 재편)

  • 사이드바 (AdminSidebar.tsx): 메뉴명 마케팅광고 관리 (href /admin/marketing 유지)
  • 페이지 (app/admin/marketing/page.tsx): 상단 탭 2개로 재구성
    • [채널·캠페인] (신규 기본 탭): ad_channels CRUD 테이블 — 채널명·URL(외부 링크)·상태(active/paused 토글)·메모·등록일. 행 추가/수정/삭제
    • [에셋]: 기존 썸네일·배너·체크리스트 기능 그대로 이동(코드 보존)
  • API: 신규 app/api/admin/ad-channels/route.ts (GET 목록/POST 생성) + app/api/admin/ad-channels/[id]/route.ts (PATCH 수정/DELETE 삭제). admin_token 검증은 기존 admin API 패턴(verifyAdminTokenNode) 동일 적용
  • DB: 신규 마이그레이션 supabase/migrations/2026-07-02-phase1-ad-channels.sql
    CREATE TABLE IF NOT EXISTS ad_channels (
      id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
      name text NOT NULL,
      url text,
      status text NOT NULL DEFAULT 'active' CHECK (status IN ('active','paused')),
      memo text,
      created_at timestamptz NOT NULL DEFAULT now(),
      updated_at timestamptz NOT NULL DEFAULT now()
    );
    ALTER TABLE ad_channels ENABLE ROW LEVEL SECURITY;
    -- service_role만 접근(관리자 API 전용) — 별도 policy 없음(기본 거부)
    
    클라우드+NAS 양쪽 적용 (운영 규칙)

WS4. admin/packs 페이지 제거

  • 삭제: app/admin/packs/page.tsx (+디렉토리), AdminSidebar의 /admin/packs 메뉴 항목
  • 유지: /api/admin/packs, /api/admin/packs/upload-url (products 페이지·mypage 다운로드가 소비)
  • products 페이지가 packs API로 파일 배정을 이미 지원함을 확인(감사 완료) — 기능 공백 없음

WS5. 문서·검증

  • CLAUDE.md: 핵심 IA에 /showcase 추가, mypage 탭 서술 갱신, admin 서술(광고 관리·packs 제거) 갱신
  • 이메일 플로우 점검(변경 없음, 검증만): contact 접수 메일 → quote 발송 메일 → 수락 알림 메일 경로가 Phase 0 이후에도 온전한지 코드 경로 확인
  • 검증: npm test(신규 showcase 테스트 포함) · npm run build · 가드레일 grep(gradient|purple|violet|blur 신규 파일) · 수동 확인 안내(마이페이지 발주 탭, /showcase, admin 광고 관리)

범위 밖 (다음 Phase)

  • 사주·타로·음악(Phase 2·3)
  • TopNav의 별도 서비스 진입점(Phase 2에서 서비스와 함께)
  • 사이트 내 프로모션 배너 노출 관리(광고 관리 확장분 — 추후)
  • quotes 테이블 스키마 변경(발주서는 뷰 차원 표면화만)

리스크·주의

  • projects API는 quotes.user_id 기반 — 비회원 의뢰는 견적코드 연결 전까지 마이페이지에 안 보임(의도된 동작, track/[token]이 커버)
  • projects/link의 코드 형식(public_token)은 기존 구현 계약을 따름 — 구현 시 실제 필드명 확인
  • admin/marketing 재편 시 기존 에셋 데이터(정적 ASSETS 배열)는 코드 이동만, 손실 없음