vvamuri
샘플 리포트vamuri 가 만든 가상 앱(원데이 클래스 수강권 판매)을 실제로 진단한 결과예요. 실제 서비스가 아니고, 출시 전에 자주 생기는 빈틈을 일부러 넣었어요.내 서비스도 무료로 진단
샘플 › 원데이 클래스 수강권 (샘플 · 가상 앱) › 전체 리포트
원데이 클래스 수강권 (샘플 · 가상 앱)기준 커밋 40d1750 · 2026-10-27공개 2026-10-27 03:41

출시 전에
48개만 풀면 됩니다.

79개 항목을 읽었습니다. 막는 것부터 근거(파일·줄)와 푸는 순서를 적었어요.

79항목
2통과
67문제
7해당없음
3미확인
48출시를 막는 것

먼저 할 3가지

이것부터 하면 나머지는 순서대로 풀립니다 · 체크는 여러분 화면에만 남습니다

수량·금액 경계 — 0 · 음수 · 소수 · 상한 · 합계 오버플로

API 에서 classes.price 조회해 금액 대조 + 0/음수 거부 + DB CHECK 제약 추가

브라우저가 받는 응답에 서버 시크릿이 없다

NEXT_PUBLIC_TOSS_SECRET_KEY → TOSS_SECRET_KEY 로 변경 (서버 전용)

모든 API 라우트가 권한을 명시하고 미명시는 기본 거부다

orders 테이블 RLS 활성화 · 웹훅 서명 검증 추가 · API 인증 미들웨어 추가

3개 다 하셨네요.다시 진단하면 바뀐 것만 맨 위에 보여 드려요.내 서비스도 진단받기

요약

잘 되어 있는 곳 · 비어 있는 곳 · 가장 먼저 걸리는 것

잘 되어 있는 곳 토스페이먼츠 결제창 연동과 승인 호출 자체는 붙어 있고, .env.example 이 코드가 읽는 키를 빠짐없이 적고 있어요. 의존성도 군더더기 없이 쓰는 것만 있어요.

비어 있는 곳 결제 금액을 브라우저가 보낸 값 그대로 믿고, 토스 시크릿 키가 NEXT_PUBLIC_ 이름이라 화면 코드에 실려 나가요. /admin 은 로그인 없이 열리고 수강생 전화번호가 그대로 보이며, orders 테이블에 RLS 가 없어요. 약관·처리방침 링크는 # 이고, 탈퇴 기능이 없어요.

가장 먼저 금액을 서버에서 다시 계산하기 (4.2), 시크릿 키를 서버 전용으로 옮기기 (1.2), 관리자 화면과 주문 테이블 막기 (2.1). 셋 다 코드 몇 줄이라 반나절이면 끝나요.

출시를 막는 것 48

고쳤음 0/48 · 체크는 여러분 화면에만 남습니다

1. 시크릿

1.1저장소와 전 히스토리에 시크릿이 없다문제차단
근거
커밋 파일 ○ — .env.example 만 있음 (git ls-files) · 히스토리 ? — 이번 진단은 현재 파일만 봤어요 · 방지 장치 ✕ — gitleaks/secret-scan 설정 없음 (glob → 0건) · CI 단계 ✕ — .github/workflows 없음
풀리는 곳
코드
고칠 방향
gitleaks 설정 추가 · CI 스캔 단계 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[1.1] 저장소와 전 히스토리에 시크릿이 없다
지금 상태: 커밋 파일 ○ — .env.example 만 있음 (git ls-files) · 히스토리 ? — 이번 진단은 현재 파일만 봤어요 · 방지 장치 ✕ — gitleaks/secret-scan 설정 없음 (glob → 0건) · CI 단계 ✕ — .github/workflows 없음
관련 위치: .github/workflows, gitleaks/secret-scan
할 일: gitleaks 설정 추가 · CI 스캔 단계 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
1.2브라우저가 받는 응답에 서버 시크릿이 없다문제차단
근거
공개 접두 변수 ✕ — NEXT_PUBLIC_TOSS_SECRET_KEY (app/api/checkout/confirm/route.ts:10 — 서버 전용 비밀이 NEXT_PUBLIC_ 접두로 노출) · 클라이언트 참조 ✕ — app/classes/page.tsx:16 NEXT_PUBLIC_TOSS_CLIENT_KEY (클라이언트 키는 정상, 하지만 SECRET_KEY 가 NEXT_PUBLIC_ 로 노출됨) · 오류 본문 ○ — 오류 처리 없음 (catch 문 0건) · 도메인 제한 기록 ✕ — 없음 · 빌드 산출물 ③
풀리는 곳
코드
고칠 방향
NEXT_PUBLIC_TOSS_SECRET_KEY → TOSS_SECRET_KEY 로 변경 (서버 전용)
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[1.2] 브라우저가 받는 응답에 서버 시크릿이 없다
지금 상태: 공개 접두 변수 ✕ — NEXT_PUBLIC_TOSS_SECRET_KEY (app/api/checkout/confirm/route.ts:10 — 서버 전용 비밀이 NEXT_PUBLIC_ 접두로 노출) · 클라이언트 참조 ✕ — app/classes/page.tsx:16 NEXT_PUBLIC_TOSS_CLIENT_KEY (클라이언트 키는 정상, 하지만 SECRET_KEY 가 NEXT_PUBLIC_ 로 노출됨) · 오류 본문 ○ — 오류 처리 없음 (catch 문 0건) · 도메인 제한 기록 ✕ — 없음 · 빌드 산출물 ③
관련 위치: app/api/checkout/confirm/route.ts:10, app/classes/page.tsx:16
할 일: NEXT_PUBLIC_TOSS_SECRET_KEY → TOSS_SECRET_KEY 로 변경 (서버 전용)

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
1.3로그 채널별로 개인정보·토큰이 찍히지 않는다문제차단
근거
앱 로그 ✕ — console.log('confirm', { paymentKey, orderId, amount }) (app/api/checkout/confirm/route.ts:5 — paymentKey 토큰 노출) · DB 오류 로그 ○ — ORM 로깅 설정 없음 (Supabase 클라이언트는 기본 로깅 안 함) · 접근 로그 ○ — 프록시 없음 (middleware.ts 없음 · 00-map.md:26) · 재설정 토큰 — — 기능 없음
풀리는 곳
코드
고칠 방향
console.log 에서 paymentKey 제거 또는 마스킹
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[1.3] 로그 채널별로 개인정보·토큰이 찍히지 않는다
지금 상태: 앱 로그 ✕ — console.log('confirm', { paymentKey, orderId, amount }) (app/api/checkout/confirm/route.ts:5 — paymentKey 토큰 노출) · DB 오류 로그 ○ — ORM 로깅 설정 없음 (Supabase 클라이언트는 기본 로깅 안 함) · 접근 로그 ○ — 프록시 없음 (middleware.ts 없음 · 00-map.md:26) · 재설정 토큰 — — 기능 없음
관련 위치: app/api/checkout/confirm/route.ts:5
할 일: console.log 에서 paymentKey 제거 또는 마스킹

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
1.4프로덕션 시크릿 주입 경로가 실제로 있고, 개발 기본값·누락이면 부팅이 거부된다문제차단
근거
배포 설정 ✕ — 없음 (Dockerfile · docker-compose · vercel.json · fly.toml → 0건) · 부팅 검사 ✕ — 없음 (lib/supabase.ts:4-5 ! 연산자만 — 런타임 오류는 내지만 부팅 전 검증 없음) · 검사 spec ✕ — 테스트 없음 (*.test.* → 0건) · 집합 차 ✕ — 코드 읽음 {NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, NEXT_PUBLIC_TOSS_CLIENT_KEY, NEXT_PUBLIC_TOSS_SECRET_KEY, ADMIN_EMAIL} − 배포 주입 {} = 전부 누락 (배포 설정 없음)
풀리는 곳
코드
고칠 방향
부팅 시 필수 env 검증 추가 · 배포 설정에 env 주입 명시
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[1.4] 프로덕션 시크릿 주입 경로가 실제로 있고, 개발 기본값·누락이면 부팅이 거부된다
지금 상태: 배포 설정 ✕ — 없음 (Dockerfile · docker-compose · vercel.json · fly.toml → 0건) · 부팅 검사 ✕ — 없음 (lib/supabase.ts:4-5 ! 연산자만 — 런타임 오류는 내지만 부팅 전 검증 없음) · 검사 spec ✕ — 테스트 없음 (.test. → 0건) · 집합 차 ✕ — 코드 읽음 {NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, NEXT_PUBLIC_TOSS_CLIENT_KEY, NEXT_PUBLIC_TOSS_SECRET_KEY, ADMIN_EMAIL} − 배포 주입 {} = 전부 누락 (배포 설정 없음)
관련 위치: lib/supabase.ts:4-5
할 일: 부팅 시 필수 env 검증 추가 · 배포 설정에 env 주입 명시

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.

2. 접근 제어

2.1모든 API 라우트가 권한을 명시하고 미명시는 기본 거부다문제차단
근거
라우트 ✕ — app/api/checkout/confirm/route.ts (POST) · app/api/webhooks/toss/route.ts (POST) 총 2개 · 전역 가드 ✕ — middleware.ts 없음 · RLS 전수 ✕ — orders 테이블 RLS 없음 (001_init.sql:9-19 — classes 만 RLS, orders 는 누구나 조회·수정 가능) · 신원 위조 ✕ — app/api/webhooks/toss/route.ts:4-6 body.data.orderId 를 그대로 신뢰 (서명 검증 없음) · 미명시 처리 ✕ — 인증 검사 없음 (auth/guard/Depends → 0건) · 테스트 ✕ — 없음
풀리는 곳
코드
고칠 방향
orders 테이블 RLS 활성화 · 웹훅 서명 검증 추가 · API 인증 미들웨어 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[2.1] 모든 API 라우트가 권한을 명시하고 미명시는 기본 거부다
지금 상태: 라우트 ✕ — app/api/checkout/confirm/route.ts (POST) · app/api/webhooks/toss/route.ts (POST) 총 2개 · 전역 가드 ✕ — middleware.ts 없음 · RLS 전수 ✕ — orders 테이블 RLS 없음 (001_init.sql:9-19 — classes 만 RLS, orders 는 누구나 조회·수정 가능) · 신원 위조 ✕ — app/api/webhooks/toss/route.ts:4-6 body.data.orderId 를 그대로 신뢰 (서명 검증 없음) · 미명시 처리 ✕ — 인증 검사 없음 (auth/guard/Depends → 0건) · 테스트 ✕ — 없음
관련 위치: app/api/checkout/confirm/route.ts, app/api/webhooks/toss/route.ts, app/api/webhooks/toss/route.ts:4-6, auth/guard/Depends
할 일: orders 테이블 RLS 활성화 · 웹훅 서명 검증 추가 · API 인증 미들웨어 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
2.2소유자·테넌트 격리 — 남의 id 로 조회·수정·취소하면 404/403 (IDOR)문제차단
근거
WHERE user_id ✕ — app/admin/page.tsx:8 .select('*') (조건 없음 — 전체 조회) · app/api/checkout/confirm/route.ts:17 .eq('id', orderId) (user_id 검증 없음 — 남의 주문도 PAID 처리 가능) · app/api/webhooks/toss/route.ts:6 .eq('id', body.data.orderId) (소유자 검증 없음) · 신원 서버 결정 ✕ — 클라이언트가 보낸 orderId (app/pay/success/page.tsx:11 쿼리 파라미터) 를 그대로 사용 · 404/403 구분 ✕ — 없음 · IDOR 테스트 ✕ — 없음
풀리는 곳
코드
고칠 방향
orders 테이블에 WHERE user_id 조건 추가 · 세션에서 user_id 추출
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[2.2] 소유자·테넌트 격리 — 남의 id 로 조회·수정·취소하면 404/403 (IDOR)
지금 상태: WHERE user_id ✕ — app/admin/page.tsx:8 .select('') (조건 없음 — 전체 조회) · app/api/checkout/confirm/route.ts:17 .eq('id', orderId) (user_id 검증 없음 — 남의 주문도 PAID 처리 가능) · app/api/webhooks/toss/route.ts:6 .eq('id', body.data.orderId) (소유자 검증 없음) · 신원 서버 결정 ✕ — 클라이언트가 보낸 orderId (app/pay/success/page.tsx:11 쿼리 파라미터) 를 그대로 사용 · 404/403 구분 ✕ — 없음 · IDOR 테스트 ✕ — 없음
관련 위치: 404/403, app/admin/page.tsx:8, app/api/checkout/confirm/route.ts:17, app/api/webhooks/toss/route.ts:6, app/pay/success/page.tsx:11
할 일: orders 테이블에 WHERE user_id 조건 추가 · 세션에서 user_id 추출

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
2.3서버 액션·라우트 핸들러·엣지 함수가 API 가드를 우회해 DB 를 직접 만지지 않는다문제차단
근거
웹 앱 DB 드라이버 ✕ — lib/supabase.ts:3-6 (클라이언트 앱에서 Supabase 직접 생성 · app/classes/page.tsx:8 · app/admin/page.tsx:8 브라우저에서 직접 DB 조회) · API 호출 단일화 ✕ — 클라이언트 컴포넌트가 supabase.from() 직접 호출 (app/classes/page.tsx:8·13 · app/admin/page.tsx:8) · 우회 경로 ✕ — 있음 (서버 액션은 없지만 클라이언트가 DB 직접 조회) · 서버 액션 인증 — — 서버 액션 없음
풀리는 곳
코드
고칠 방향
클라이언트의 직접 DB 접근 제거 · API 라우트로 전환
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[2.3] 서버 액션·라우트 핸들러·엣지 함수가 API 가드를 우회해 DB 를 직접 만지지 않는다
지금 상태: 웹 앱 DB 드라이버 ✕ — lib/supabase.ts:3-6 (클라이언트 앱에서 Supabase 직접 생성 · app/classes/page.tsx:8 · app/admin/page.tsx:8 브라우저에서 직접 DB 조회) · API 호출 단일화 ✕ — 클라이언트 컴포넌트가 supabase.from() 직접 호출 (app/classes/page.tsx:8·13 · app/admin/page.tsx:8) · 우회 경로 ✕ — 있음 (서버 액션은 없지만 클라이언트가 DB 직접 조회) · 서버 액션 인증 — — 서버 액션 없음
관련 위치: app/admin/page.tsx:8, app/classes/page.tsx:8, lib/supabase.ts:3-6
할 일: 클라이언트의 직접 DB 접근 제거 · API 라우트로 전환

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.

3. 인증

3.4운영에서 실제로 동작하는 가입·로그인 경로가 하나 이상 있다문제차단
근거
✕ 경로는 있으나(app/login/page.tsx:8 카카오 OAuth) 공급자 연결 확인 불가 — Supabase 콘솔 설정에서만 확인됨 (코드에 공급자 연결 상태 없음 · .env.example의 SUPABASE_URL/ANON_KEY 예시값) · ✕ 로그인 후 세션 확인 코드 없음 (앱 전체에 getSession|getUser|auth().user 호출 0건)
풀리는 곳
외부 + 코드
고칠 방향
Supabase 콘솔에서 카카오 OAuth 공급자 연결 확인 + 세션 확인 코드 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[3.4] 운영에서 실제로 동작하는 가입·로그인 경로가 하나 이상 있다
지금 상태: ✕ 경로는 있으나(app/login/page.tsx:8 카카오 OAuth) 공급자 연결 확인 불가 — Supabase 콘솔 설정에서만 확인됨 (코드에 공급자 연결 상태 없음 · .env.example의 SUPABASE_URL/ANON_KEY 예시값) · ✕ 로그인 후 세션 확인 코드 없음 (앱 전체에 getSession¦getUser¦auth().user 호출 0건)
관련 위치: SUPABASE_URL/ANON_KEY, app/login/page.tsx:8
할 일: Supabase 콘솔에서 카카오 OAuth 공급자 연결 확인 + 세션 확인 코드 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
3.5모든 역할(고객 · 판매자 · 직원 · 관리자)에 비밀번호 복구와 계정 잠금 경로가 닫혀 있다문제차단
근거
— 비밀번호 복구 (OAuth 전용, 해당 없음) · ✕ 계정 잠금 전무 (검색: lock|locked|attempts|failed.*login → 0건) · ✕ 잠금 해제 경로 없음
풀리는 곳
코드
고칠 방향
로그인 시도 횟수 제한 + 잠금 구현
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[3.5] 모든 역할(고객 · 판매자 · 직원 · 관리자)에 비밀번호 복구와 계정 잠금 경로가 닫혀 있다
지금 상태: — 비밀번호 복구 (OAuth 전용, 해당 없음) · ✕ 계정 잠금 전무 (검색: lock¦locked¦attempts¦failed.login → 0건) · ✕ 잠금 해제 경로 없음
할 일: 로그인 시도 횟수 제한 + 잠금 구현

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.

4. 입력 검증

4.1모든 쓰기 입력(body · param · query · header)이 스키마/파서를 거치고, 모르는 필드는 거부문제차단
근거
✕ 입력 검증 라이브러리 없음 (검색: zod|yup|joi|class-validator|pydantic → 0건) · ✕ API 입력 무검증 (app/api/checkout/confirm/route.ts:4 req.json() 결과를 바로 구조분해, 스키마 없음) · ✕ 웹훅 입력 무검증 (app/api/webhooks/toss/route.ts:4 req.json() 바로 사용) · ✕ 클라이언트 입력 무검증 (app/classes/page.tsx:11-12 prompt() 결과를 ! 로만 처리)
풀리는 곳
코드
고칠 방향
zod 등 스키마 라이브러리 추가 + 모든 API 경로에 검증 적용
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[4.1] 모든 쓰기 입력(body · param · query · header)이 스키마/파서를 거치고, 모르는 필드는 거부
지금 상태: ✕ 입력 검증 라이브러리 없음 (검색: zod¦yup¦joi¦class-validator¦pydantic → 0건) · ✕ API 입력 무검증 (app/api/checkout/confirm/route.ts:4 req.json() 결과를 바로 구조분해, 스키마 없음) · ✕ 웹훅 입력 무검증 (app/api/webhooks/toss/route.ts:4 req.json() 바로 사용) · ✕ 클라이언트 입력 무검증 (app/classes/page.tsx:11-12 prompt() 결과를 ! 로만 처리)
관련 위치: app/api/checkout/confirm/route.ts:4, app/api/webhooks/toss/route.ts:4, app/classes/page.tsx:11-12
할 일: zod 등 스키마 라이브러리 추가 + 모든 API 경로에 검증 적용

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
4.2수량·금액 경계 — 0 · 음수 · 소수 · 상한 · 합계 오버플로문제차단
근거
✕ 금액 검증 없음 (app/api/checkout/confirm/route.ts:4 amount 를 req.json()에서 받아 토스로 그대로 전달 · 0/음수/상한 검사 없음) · ✕ 서버 금액 재계산 없음 (app/pay/success/page.tsx:11 클라이언트가 보낸 amount 를 그대로 confirm API 로 전달 · classes 테이블 price 와 대조 안 함) · ✕ DB 제약 없음 (supabase/migrations/001_init.sql:4·15 price·amount 필드가 int not null 만, CHECK 제약 없음 — 음수 허용) · ○ 소수 가드 (001_init.sql:4·15 int 타입)
풀리는 곳
코드
고칠 방향
API 에서 classes.price 조회해 금액 대조 + 0/음수 거부 + DB CHECK 제약 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[4.2] 수량·금액 경계 — 0 · 음수 · 소수 · 상한 · 합계 오버플로
지금 상태: ✕ 금액 검증 없음 (app/api/checkout/confirm/route.ts:4 amount 를 req.json()에서 받아 토스로 그대로 전달 · 0/음수/상한 검사 없음) · ✕ 서버 금액 재계산 없음 (app/pay/success/page.tsx:11 클라이언트가 보낸 amount 를 그대로 confirm API 로 전달 · classes 테이블 price 와 대조 안 함) · ✕ DB 제약 없음 (supabase/migrations/001_init.sql:4·15 price·amount 필드가 int not null 만, CHECK 제약 없음 — 음수 허용) · ○ 소수 가드 (001_init.sql:4·15 int 타입)
관련 위치: app/api/checkout/confirm/route.ts:4, app/pay/success/page.tsx:11, supabase/migrations/001_init.sql:4
할 일: API 에서 classes.price 조회해 금액 대조 + 0/음수 거부 + DB CHECK 제약 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.

5. 결제 · 환불 · 동시성

5.1PG 선정·계약이 끝났다문제차단
근거
✕ PG 선정 ○ · ✕ 계약 여부 ?<br>• app/api/checkout/confirm/route.ts:7 https://api.tosspayments.com/v1/payments/confirm — 토스페이먼츠로 선정됨<br>• .env.example:3-4 test_ck_ · test_sk_ — 테스트 키만 예시로 제공<br>• 계약·심사 상태 기록 문서 없음 (검색: `docs
풀리는 곳
계약
고칠 방향
심사
저장소 밖에서 할 일계약·콘솔·서류처럼 코드로 안 풀리는 일이에요. 위 "고칠 방향" 대로 직접 하거나, 출시 패키지로 같이 할 수 있어요.
5.2테스트/목 결제는 운영에서 막혀 있다문제차단
근거
✕ 운영 키 검증 · ✕ 테스트 모드 거부<br>• app/api/checkout/confirm/route.ts:10 process.env.NEXT_PUBLIC_TOSS_SECRET_KEY — 키 검증 없음, test_ 접두사 확인 없음<br>• app/classes/page.tsx:16 process.env.NEXT_PUBLIC_TOSS_CLIENT_KEY — 클라이언트 키도 검증 없음<br>• 부팅 시 키 검증 코드 없음 (검색: startsWith.*test_|NODE_ENV.*production → 0건)
풀리는 곳
코드
고칠 방향
부팅 시 운영 환경이면 test_ 키 거부·테스트 모드 표시 제거
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.2] 테스트/목 결제는 운영에서 막혀 있다
지금 상태: ✕ 운영 키 검증 · ✕ 테스트 모드 거부 • app/api/checkout/confirm/route.ts:10 process.env.NEXT_PUBLIC_TOSS_SECRET_KEY — 키 검증 없음, test_ 접두사 확인 없음 • app/classes/page.tsx:16 process.env.NEXT_PUBLIC_TOSS_CLIENT_KEY — 클라이언트 키도 검증 없음 • 부팅 시 키 검증 코드 없음 (검색: startsWith.test_¦NODE_ENV.production → 0건)
관련 위치: app/api/checkout/confirm/route.ts:10, app/classes/page.tsx:16
할 일: 부팅 시 운영 환경이면 test_ 키 거부·테스트 모드 표시 제거

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5.3승인 멱등성 · 금액 검증 · 상태 머신문제차단
근거
✕ 멱등 · ✕ 금액 검증 · ✕ 상태 머신<br>• app/api/checkout/confirm/route.ts:4 amount 파라미터를 PG 에 그대로 전달 — 서버 재계산 없음<br>• app/api/checkout/confirm/route.ts:17 .update({ status: 'PAID' }).eq('id', orderId) — WHERE status 조건 없음, 중복 호출 시 덮어씀<br>• supabase/migrations/001_init.sql — CHECK 제약 없음 (검색: CHECK|CONSTRAINT → 0건)
풀리는 곳
코드
고칠 방향
주문 조회·금액 재계산·비교 · UPDATE WHERE status='PENDING' · CHECK (status IN …)
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.3] 승인 멱등성 · 금액 검증 · 상태 머신
지금 상태: ✕ 멱등 · ✕ 금액 검증 · ✕ 상태 머신 • app/api/checkout/confirm/route.ts:4 amount 파라미터를 PG 에 그대로 전달 — 서버 재계산 없음 • app/api/checkout/confirm/route.ts:17 .update({ status: 'PAID' }).eq('id', orderId) — WHERE status 조건 없음, 중복 호출 시 덮어씀 • supabase/migrations/001_init.sql — CHECK 제약 없음 (검색: CHECK¦CONSTRAINT → 0건)
관련 위치: app/api/checkout/confirm/route.ts:17, app/api/checkout/confirm/route.ts:4, supabase/migrations/001_init.sql
할 일: 주문 조회·금액 재계산·비교 · UPDATE WHERE status='PENDING' · CHECK (status IN …)

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5.4웹훅 서명 검증 · 중복 방지 · 순서 역전문제차단
근거
✕ 서명 검증 · ✕ 중복 방지 · ✕ 순서 역전<br>• app/api/webhooks/toss/route.ts:4 await req.json() — 서명 검증 없음, PG 재조회 없음 (검색: signature|verify|fetch.*payments → 0건)<br>• app/api/webhooks/toss/route.ts:6 .update({ status: body.data.status }) — 이벤트 id 저장 없음, 중복 수신 시 덮어씀<br>• 순서 역전 분기 없음 (검색: eventType|event.*id|webhook.*log → 0건)
풀리는 곳
코드
고칠 방향
토스 서명 검증 또는 paymentKey 로 PG 재조회 · 이벤트 id 유니크 저장 · 상태 전이 조건
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.4] 웹훅 서명 검증 · 중복 방지 · 순서 역전
지금 상태: ✕ 서명 검증 · ✕ 중복 방지 · ✕ 순서 역전 • app/api/webhooks/toss/route.ts:4 await req.json() — 서명 검증 없음, PG 재조회 없음 (검색: signature¦verify¦fetch.payments → 0건) • app/api/webhooks/toss/route.ts:6 .update({ status: body.data.status }) — 이벤트 id 저장 없음, 중복 수신 시 덮어씀 • 순서 역전 분기 없음 (검색: eventType¦event.id¦webhook.log → 0건)
관련 위치: app/api/webhooks/toss/route.ts:4, app/api/webhooks/toss/route.ts:6
할 일: 토스 서명 검증 또는 paymentKey 로 PG 재조회 · 이벤트 id 유니크 저장 · 상태 전이 조건

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5.5고객이 돌아오지 않을 때 끝낼 주체문제차단
근거
✕ PG 조회 · ✕ 대사 작업 · ✕ 알림<br>• PG 조회 API 없음 (검색: GET.*payments|fetch.*payments.*key → confirm 만 있음, GET 없음)<br>• 잡·큐 없음 (검색: cron|schedule|queue|job|worker → 0건)<br>• 운영자 알림 없음 (검색: alert|notify|mail|send → ADMIN_EMAIL 변수만, 발송 코드 없음)
풀리는 곳
코드
고칠 방향
PENDING 30분 이상 주문 조회·PG 재조회·상태 동기화 cron · 슬랙·메일 알림
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.5] 고객이 돌아오지 않을 때 끝낼 주체
지금 상태: ✕ PG 조회 · ✕ 대사 작업 · ✕ 알림 • PG 조회 API 없음 (검색: GET.payments¦fetch.payments.key → confirm 만 있음, GET 없음) • 잡·큐 없음 (검색: cron¦schedule¦queue¦job¦worker → 0건) • 운영자 알림 없음 (검색: alert¦notify¦mail¦send → ADMIN_EMAIL 변수만, 발송 코드 없음)
할 일: PENDING 30분 이상 주문 조회·PG 재조회·상태 동기화 cron · 슬랙·메일 알림

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5.6결제 실패 경로와 실 PG e2e문제차단
근거
✕ 실패 분기 ○ · ✕ 중복 방지 · ✕ e2e<br>• app/api/checkout/confirm/route.ts:15 if (!res.ok) return Response.json({ ok: false }) — 실패 응답은 있음<br>• app/pay/success/page.tsx:12 j.ok ? '결제 완료!' : '결제 실패' — 실패 메시지 있음<br>• 중복 클릭 방지 없음 (검색: disabled|pending|loading → 0건) · 주문 유니크 제약 없음 (001_init.sql — payment_key 유니크 없음)<br>• e2e 없음 (검색: e2e|test|spec|cypress|playwright → 0건)
풀리는 곳
코드
고칠 방향
버튼 비활성·payment_key 유니크 · 토스 테스트 모드 e2e (성공·실패·취소)
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.6] 결제 실패 경로와 실 PG e2e
지금 상태: ✕ 실패 분기 ○ · ✕ 중복 방지 · ✕ e2e • app/api/checkout/confirm/route.ts:15 if (!res.ok) return Response.json({ ok: false }) — 실패 응답은 있음 • app/pay/success/page.tsx:12 j.ok ? '결제 완료!' : '결제 실패' — 실패 메시지 있음 • 중복 클릭 방지 없음 (검색: disabled¦pending¦loading → 0건) · 주문 유니크 제약 없음 (001_init.sql — payment_key 유니크 없음) • e2e 없음 (검색: e2e¦test¦spec¦cypress¦playwright → 0건)
관련 위치: app/api/checkout/confirm/route.ts:15, app/pay/success/page.tsx:12
할 일: 버튼 비활성·payment_key 유니크 · 토스 테스트 모드 e2e (성공·실패·취소)

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5.7취소·환불 규정 확정 및 코드·약관·고지 일치문제차단
근거
✕ 환불 규정 · ✕ 약관 · ✕ 결제 전 고지<br>• 환불 코드 없음 (검색: refund|cancel|환불|취소 → 0건)<br>• 약관 없음 (app/login/page.tsx:9 <a href="#">이용약관</a> — href="#", 실제 파일 없음)<br>• 결제 전 고지 없음 (app/classes/page.tsx — 결제 전 동의·고지 화면 없음, prompt() 후 바로 결제)<br>• 규정·약관·고지 셋 모두 부재
풀리는 곳
코드·결정
고칠 방향
환불 규정 확정 → 함수·약관·결제 전 고지 문안 작성 및 동의 체크 · 주문 행에 버전 기록
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.7] 취소·환불 규정 확정 및 코드·약관·고지 일치
지금 상태: ✕ 환불 규정 · ✕ 약관 · ✕ 결제 전 고지 • 환불 코드 없음 (검색: refund¦cancel¦환불¦취소 → 0건) • 약관 없음 (app/login/page.tsx:9 <a href="#">이용약관</a> — href="#", 실제 파일 없음) • 결제 전 고지 없음 (app/classes/page.tsx — 결제 전 동의·고지 화면 없음, prompt() 후 바로 결제) • 규정·약관·고지 셋 모두 부재
관련 위치: app/classes/page.tsx, app/login/page.tsx:9
할 일: 환불 규정 확정 → 함수·약관·결제 전 고지 문안 작성 및 동의 체크 · 주문 행에 버전 기록

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5.8환불 실행 — 부분·재시도·알림문제차단
근거
✕ 환불 코드 · ✕ 부분 환불 · ✕ 재시도<br>• 환불 코드 없음 (검색: refund|cancel|환불 → 0건)<br>• PG 취소 호출 없음 (검색: cancel|refund → 0건)<br>• 환불 상태·큐 없음 (001_init.sql — status 열에 REFUND 언급 없음)
풀리는 곳
코드
고칠 방향
토스 취소 API 호출 (트랜잭션 밖) · 부분 환불 지원 · 실패 시 재시도 큐·알림
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.8] 환불 실행 — 부분·재시도·알림
지금 상태: ✕ 환불 코드 · ✕ 부분 환불 · ✕ 재시도 • 환불 코드 없음 (검색: refund¦cancel¦환불 → 0건) • PG 취소 호출 없음 (검색: cancel¦refund → 0건) • 환불 상태·큐 없음 (001_init.sql — status 열에 REFUND 언급 없음)
할 일: 토스 취소 API 호출 (트랜잭션 밖) · 부분 환불 지원 · 실패 시 재시도 큐·알림

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5.9판매자 측 취소·배상 규정·행위자 권한문제차단
근거
✕ 판매자·운영자 취소 · ✕ 배상 규정<br>• 관리자 화면 읽기만 (app/admin/page.tsx:8 .select('*') — 취소·환불 쓰기 라우트 없음)<br>• 취소·환불 API 없음 (app/api — checkout/confirm · webhooks/toss 만, cancel 엔드포인트 없음)<br>• 배상 조항 없음 (약관 파일 자체가 없음)
풀리는 곳
코드·결정
고칠 방향
관리자 취소·환불 API · 일괄 환불 기능 · 약관에 배상 조항 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.9] 판매자 측 취소·배상 규정·행위자 권한
지금 상태: ✕ 판매자·운영자 취소 · ✕ 배상 규정 • 관리자 화면 읽기만 (app/admin/page.tsx:8 .select('') — 취소·환불 쓰기 라우트 없음) • 취소·환불 API 없음 (app/api — checkout/confirm · webhooks/toss 만, cancel 엔드포인트 없음) • 배상 조항 없음 (약관 파일 자체가 없음)
관련 위치: app/admin/page.tsx:8, app/api, checkout/confirm, webhooks/toss
할 일: 관리자 취소·환불 API · 일괄 환불 기능 · 약관에 배상 조항 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5.11동시성 — DB 가 최종 방어선(부분 유니크 · EXCLUDE · CHECK), 판정은 잠금 아래 한 문장, 만료 선점이 자정(自淨)된다문제차단
근거
제약 ✕ · 잠금 ✕ · 만료 정리 — · 동시성 spec ✕ · 부하 ③<br><br>[5.11-a] supabase/migrations/001_init.sql:1-19 — UNIQUE/EXCLUDE/CHECK 제약 없음 (검색 → 0건)<br>[5.11-b] app/classes/page.tsx:13-15 — INSERT 에 조건부 WHERE · FOR UPDATE · ON CONFLICT 없음, 트랜잭션 없음 (단순 .insert())<br>[5.11-c] 검색 worker|cron|cleanup|expire|ttl → 0건 — 만료 정리 없음, 이 서비스엔 선점 개념 없음(장바구니·hold 없음) — 해당없음 —<br>[5.11-d] 검색 k6|locust|artillery|describe|it\( → 0건 — 동시성 spec 없음
풀리는 곳
코드
고칠 방향
재고(seats) 감소 시 DB 제약(CHECK seats >= 0) 추가 · 주문 INSERT 를 seats > 0 WHERE 조건부 UPDATE 로 변경 · 동시성 테스트 작성
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.11] 동시성 — DB 가 최종 방어선(부분 유니크 · EXCLUDE · CHECK), 판정은 잠금 아래 한 문장, 만료 선점이 자정(自淨)된다
지금 상태: 제약 ✕ · 잠금 ✕ · 만료 정리 — · 동시성 spec ✕ · 부하 ③ [5.11-a] supabase/migrations/001_init.sql:1-19 — UNIQUE/EXCLUDE/CHECK 제약 없음 (검색 → 0건) [5.11-b] app/classes/page.tsx:13-15 — INSERT 에 조건부 WHERE · FOR UPDATE · ON CONFLICT 없음, 트랜잭션 없음 (단순 .insert()) [5.11-c] 검색 worker¦cron¦cleanup¦expire¦ttl → 0건 — 만료 정리 없음, 이 서비스엔 선점 개념 없음(장바구니·hold 없음) — 해당없음 — [5.11-d] 검색 k6¦locust¦artillery¦describe¦it\( → 0건 — 동시성 spec 
관련 위치: UNIQUE/EXCLUDE/CHECK, app/classes/page.tsx:13-15, supabase/migrations/001_init.sql:1-19
할 일: 재고(seats) 감소 시 DB 제약(CHECK seats >= 0) 추가 · 주문 INSERT 를 seats > 0 WHERE 조건부 UPDATE 로 변경 · 동시성 테스트 작성

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.

6. 환경 분리 · 배포

6.1프로덕션 환경이 실제로 있다문제차단
근거
✕ 배포 대상 선언 없음 (검색: Dockerfile|vercel.json|fly.toml|render.yaml|Procfile → 0건) · ✕ TLS/HSTS/리다이렉트 설정 없음 (middleware.ts 없음) · ✕ 스테이징 결정 기록 없음 (docs 디렉터리 없음)
풀리는 곳
결정/코드
고칠 방향
배포 플랫폼 선택 및 설정 파일 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[6.1] 프로덕션 환경이 실제로 있다
지금 상태: ✕ 배포 대상 선언 없음 (검색: Dockerfile¦vercel.json¦fly.toml¦render.yaml¦Procfile → 0건) · ✕ TLS/HSTS/리다이렉트 설정 없음 (middleware.ts 없음) · ✕ 스테이징 결정 기록 없음 (docs 디렉터리 없음)
관련 위치: TLS/HSTS
할 일: 배포 플랫폼 선택 및 설정 파일 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
6.2배포 재현성문제차단
근거
✕ Dockerfile/빌드 스크립트 없음 (검색: Dockerfile → 0건) · ✕ .dockerignore 없음 (ls → 없음) · ○ package.json:4 scripts.build: "next build" 존재
풀리는 곳
코드
고칠 방향
Dockerfile 또는 플랫폼 빌드 설정 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[6.2] 배포 재현성
지금 상태: ✕ Dockerfile/빌드 스크립트 없음 (검색: Dockerfile → 0건) · ✕ .dockerignore 없음 (ls → 없음) · ○ package.json:4 scripts.build: "next build" 존재
할 일: Dockerfile 또는 플랫폼 빌드 설정 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
6.3배포 절차 — 마이그레이션 · 시드 · 헬스 · 롤백문제차단
근거
✕ 워크플로/스크립트 없음 (.github/workflows 디렉터리 없음) · ✕ 시드 동기화 없음 (검색: seed → 0건) · ✕ 헬스체크 없음 (검색: health|liveness|readiness → 0건) · ✕ 롤백 절차 없음 (README.md:11-17 개발 실행만)
풀리는 곳
코드
고칠 방향
배포 워크플로 및 절차 문서 작성
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[6.3] 배포 절차 — 마이그레이션 · 시드 · 헬스 · 롤백
지금 상태: ✕ 워크플로/스크립트 없음 (.github/workflows 디렉터리 없음) · ✕ 시드 동기화 없음 (검색: seed → 0건) · ✕ 헬스체크 없음 (검색: health¦liveness¦readiness → 0건) · ✕ 롤백 절차 없음 (README.md:11-17 개발 실행만)
관련 위치: .github/workflows
할 일: 배포 워크플로 및 절차 문서 작성

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
6.4환경변수 — 코드 ↔ 예시 ↔ 배포 설정문제차단
근거
○ 코드가 읽는 5개 키 전부 .env.example 에 있음 (lib/supabase.ts:4-5 · app/api/checkout/confirm/route.ts:10 · app/classes/page.tsx:16 · .env.example:1-5) · ✕ 배포 설정 없음 (compose/플랫폼 변수 파일 없음) · ✕ 대조 spec 없음 (검색: *.test.*|*.spec.* → 0건)
풀리는 곳
코드
고칠 방향
배포 설정 추가 및 환경변수 대조 테스트 작성
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[6.4] 환경변수 — 코드 ↔ 예시 ↔ 배포 설정
지금 상태: ○ 코드가 읽는 5개 키 전부 .env.example 에 있음 (lib/supabase.ts:4-5 · app/api/checkout/confirm/route.ts:10 · app/classes/page.tsx:16 · .env.example:1-5) · ✕ 배포 설정 없음 (compose/플랫폼 변수 파일 없음) · ✕ 대조 spec 없음 (검색: .test.¦.spec. → 0건)
관련 위치: app/api/checkout/confirm/route.ts:10, app/classes/page.tsx:16, lib/supabase.ts:4-5
할 일: 배포 설정 추가 및 환경변수 대조 테스트 작성

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
6.5정책값이 결정값이다문제차단
근거
✕ .env.example:3-4 토스 키가 test_ck_xxxxxxxx · test_sk_xxxxxxxx (테스트 접두사) · ✕ .env.example:5 owner@example.com (예시값) · ✕ 결정 기록 없음 (검색: ADR|설계|결정 → 0건) · ✕ 세션 TTL · 보유 기간 · 수수료 설정 없음 (검색 → 0건)
풀리는 곳
결정/코드
고칠 방향
프로덕션 값 결정 및 .env.example 갱신
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[6.5] 정책값이 결정값이다
지금 상태: ✕ .env.example:3-4 토스 키가 test_ck_xxxxxxxx · test_sk_xxxxxxxx (테스트 접두사) · ✕ .env.example:5 owner@example.com (예시값) · ✕ 결정 기록 없음 (검색: ADR¦설계¦결정 → 0건) · ✕ 세션 TTL · 보유 기간 · 수수료 설정 없음 (검색 → 0건)
할 일: 프로덕션 값 결정 및 .env.example 갱신

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
6.7개발 시드 · 목 결제 · 디버그 도구 프로덕션 거부문제차단
근거
✕ 시드 스크립트 없음 (검색: seed → 0건 — 환경 가드도 없음) · ✕ 목 게이트웨이 부팅 거부 없음 (.env.example:3-4 test_ 키가 기본값 — 환경 검사 없음) · — API 문서 UI 없음 (검색: swagger|graphql → 0건) · ✕ 관리자 경로 무인증 (app/admin/page.tsx:5 주석 "메뉴에는 안 보이게 해 둠" — URL 직접 접근 가능)
풀리는 곳
코드
고칠 방향
환경 가드 추가 (test_ 키 거부, 관리자 인증)
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[6.7] 개발 시드 · 목 결제 · 디버그 도구 프로덕션 거부
지금 상태: ✕ 시드 스크립트 없음 (검색: seed → 0건 — 환경 가드도 없음) · ✕ 목 게이트웨이 부팅 거부 없음 (.env.example:3-4 test_ 키가 기본값 — 환경 검사 없음) · — API 문서 UI 없음 (검색: swagger¦graphql → 0건) · ✕ 관리자 경로 무인증 (app/admin/page.tsx:5 주석 "메뉴에는 안 보이게 해 둠" — URL 직접 접근 가능)
관련 위치: app/admin/page.tsx:5
할 일: 환경 가드 추가 (test_ 키 거부, 관리자 인증)

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.

7. 에러 처리

7.15xx 응답에 스택 없음 + 전역 필터 + 요청 id문제차단
근거
✕ 전역 예외 필터 없음 (Next.js App Router error.tsx 없음 — 검색: error.tsx → 0건) · ✕ 요청 id 미들웨어 없음 (검색: requestId|request_id|correlation → 0건) · ✕ 에러 응답 구성 없음 (app/api/checkout/confirm/route.ts:15 !res.ok 시 {ok: false} 만 — 메시지 없음)
풀리는 곳
코드
고칠 방향
전역 error.tsx · 요청 id 미들웨어 · 5xx 필터 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[7.1] 5xx 응답에 스택 없음 + 전역 필터 + 요청 id
지금 상태: ✕ 전역 예외 필터 없음 (Next.js App Router error.tsx 없음 — 검색: error.tsx → 0건) · ✕ 요청 id 미들웨어 없음 (검색: requestId¦request_id¦correlation → 0건) · ✕ 에러 응답 구성 없음 (app/api/checkout/confirm/route.ts:15 !res.ok 시 {ok: false} 만 — 메시지 없음)
관련 위치: app/api/checkout/confirm/route.ts:15
할 일: 전역 error.tsx · 요청 id 미들웨어 · 5xx 필터 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
7.3외부 호출 타임아웃 · 재시도문제차단
근거
✕ 토스 confirm API 타임아웃 없음 (app/api/checkout/confirm/route.ts:7 fetch — timeout/AbortSignal 없음) · ✕ 재시도 정책 없음 (검색: retry|attempts → 0건) · ✕ 멱등 키 없음 (route.ts:7-14 paymentKey · orderId 는 토스가 생성 — 재시도 시 중복 가능)
풀리는 곳
코드
고칠 방향
fetch 타임아웃 추가 (PG 필수)
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[7.3] 외부 호출 타임아웃 · 재시도
지금 상태: ✕ 토스 confirm API 타임아웃 없음 (app/api/checkout/confirm/route.ts:7 fetch — timeout/AbortSignal 없음) · ✕ 재시도 정책 없음 (검색: retry¦attempts → 0건) · ✕ 멱등 키 없음 (route.ts:7-14 paymentKey · orderId 는 토스가 생성 — 재시도 시 중복 가능)
관련 위치: app/api/checkout/confirm/route.ts:7, timeout/AbortSignal
할 일: fetch 타임아웃 추가 (PG 필수)

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.

8. 테스트 · CI

8.1머지된 코드 자동 검증 · CI 분 예산문제차단
근거
✕ 워크플로 없음 (.github/workflows 디렉터리 없음) · ✕ 자동 검증 없음 (검색: *.test.*|*.spec.* → 0건)
풀리는 곳
코드
고칠 방향
GitHub Actions 워크플로 추가 (빌드 · 테스트)
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[8.1] 머지된 코드 자동 검증 · CI 분 예산
지금 상태: ✕ 워크플로 없음 (.github/workflows 디렉터리 없음) · ✕ 자동 검증 없음 (검색: .test.¦.spec. → 0건)
관련 위치: .github/workflows
할 일: GitHub Actions 워크플로 추가 (빌드 · 테스트)

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
8.2결제 · 환불 · 동시성 통합 테스트 + e2e문제차단
근거
✕ spec 파일 없음 (검색: *.test.*|*.spec.* → 0건) · ✕ 결제 테스트 없음 (app/api/checkout/confirm/route.ts:7 토스 confirm — 테스트 없음) · — 환불 없음 (검색: refund|환불 → 0건) · ✕ 동시성 테스트 없음 (supabase/migrations/001_init.sql:6 seats — 감소 로직 없음)
풀리는 곳
코드
고칠 방향
결제 · 재고 통합 테스트 작성
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[8.2] 결제 · 환불 · 동시성 통합 테스트 + e2e
지금 상태: ✕ spec 파일 없음 (검색: .test.¦.spec. → 0건) · ✕ 결제 테스트 없음 (app/api/checkout/confirm/route.ts:7 토스 confirm — 테스트 없음) · — 환불 없음 (검색: refund¦환불 → 0건) · ✕ 동시성 테스트 없음 (supabase/migrations/001_init.sql:6 seats — 감소 로직 없음)
관련 위치: app/api/checkout/confirm/route.ts:7, supabase/migrations/001_init.sql:6
할 일: 결제 · 재고 통합 테스트 작성

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.

11. 운영 · 모니터링 · 인수인계

11.1에러 추적(국외 이전 고지 포함) + 헬스체크가 DB·큐를 보고 공개 경로로 도달 + 알림 사슬이 1회 울렸다문제차단
근거
에러 추적 ✕ · 헬스체크 ✕ · 알림 ✕ · 실 발화 기록 ✕<br>에러 추적: 없음 (검색: sentry|@sentry|bugsnag|rollbar → 0건)<br>헬스체크: 없음 (검색: /health|/ping|/ready|healthcheck → 0건)<br>알림: 없음 (검색: slack|discord|webhook|notification|alert → 0건 — .env.example:5 ADMIN_EMAIL 변수명만 존재, 메일 발송 구현 없음)<br>실 발화 기록: 없음 (저장소 내 문서 없음)
풀리는 곳
코드
고칠 방향
Sentry 류 SDK 추가 · /health 경로 생성 (Supabase 연결 확인) · 알림 연결 설정 · 테스트 발화 후 기록 문서화
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[11.1] 에러 추적(국외 이전 고지 포함) + 헬스체크가 DB·큐를 보고 공개 경로로 도달 + 알림 사슬이 1회 울렸다
지금 상태: 에러 추적 ✕ · 헬스체크 ✕ · 알림 ✕ · 실 발화 기록 ✕ 에러 추적: 없음 (검색: sentry¦@sentry¦bugsnag¦rollbar → 0건) 헬스체크: 없음 (검색: /health¦/ping¦/ready¦healthcheck → 0건) 알림: 없음 (검색: slack¦discord¦webhook¦notification¦alert → 0건 — .env.example:5 ADMIN_EMAIL 변수명만 존재, 메일 발송 구현 없음) 실 발화 기록: 없음 (저장소 내 문서 없음)
할 일: Sentry 류 SDK 추가 · /health 경로 생성 (Supabase 연결 확인) · 알림 연결 설정 · 테스트 발화 후 기록 문서화

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
11.2백업 보존일 + 복구 리허설 + 롤백 리허설(소요 시간 기록)문제차단
근거
백업 설정 ✕ · 복구 리허설 ✕ · 롤백 리허설 ✕<br>백업 설정: 없음 (검색: backup|snapshot|restore|dump → 0건 · Supabase 플랫폼 자동 백업은 콘솔 설정이나 저장소에 보존일 언급 없음)<br>리허설 기록: 없음 (검색: runbook|procedure|operation|rehearsal → 0건)<br>롤백 명령: 없음 (supabase/migrations 에 up 만, down 없음)
풀리는 곳
문서
고칠 방향
Supabase 콘솔 백업 설정 확인 후 보존일 문서화 · DB 복구 리허설 수행 및 기록 · 마이그레이션 롤백 스크립트 작성 · 애플리케이션 이전 버전 배포 절차 문서화
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[11.2] 백업 보존일 + 복구 리허설 + 롤백 리허설(소요 시간 기록)
지금 상태: 백업 설정 ✕ · 복구 리허설 ✕ · 롤백 리허설 ✕ 백업 설정: 없음 (검색: backup¦snapshot¦restore¦dump → 0건 · Supabase 플랫폼 자동 백업은 콘솔 설정이나 저장소에 보존일 언급 없음) 리허설 기록: 없음 (검색: runbook¦procedure¦operation¦rehearsal → 0건) 롤백 명령: 없음 (supabase/migrations 에 up 만, down 없음)
관련 위치: supabase/migrations
할 일: Supabase 콘솔 백업 설정 확인 후 보존일 문서화 · DB 복구 리허설 수행 및 기록 · 마이그레이션 롤백 스크립트 작성 · 애플리케이션 이전 버전 배포 절차 문서화

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
11.3비용 상한 — 예산 알람(50/80/100%) · 스토리지 자동 확장 상한 · 공개 버킷 트래픽 앞단문제차단
근거
예산 알람 ✕ · 스토리지 상한 ✕ · CDN —<br>예산 알람: 없음 (검색: budget|cost|billing|alarm → 0건)<br>스토리지 상한: 없음 (Supabase DB · 스토리지 사용 없음 — 00-map.md:16 확인, 설정 문서 없음)<br>CDN: 해당 없음 (객체 스토리지 미사용)
풀리는 곳
외부/문서
고칠 방향
Supabase 프로젝트 예산 알람 설정 (콘솔) · DB 용량 상한 정책 수립 · 설정값 문서화
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[11.3] 비용 상한 — 예산 알람(50/80/100%) · 스토리지 자동 확장 상한 · 공개 버킷 트래픽 앞단
지금 상태: 예산 알람 ✕ · 스토리지 상한 ✕ · CDN — 예산 알람: 없음 (검색: budget¦cost¦billing¦alarm → 0건) 스토리지 상한: 없음 (Supabase DB · 스토리지 사용 없음 — 00-map.md:16 확인, 설정 문서 없음) CDN: 해당 없음 (객체 스토리지 미사용)
할 일: Supabase 프로젝트 예산 알람 설정 (콘솔) · DB 용량 상한 정책 수립 · 설정값 문서화

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
11.5운영 환경에서 관리 명령(첫 관리자 생성 · 잠금 해제 · 카탈로그 동기화)을 실행할 경로가 있다문제차단
근거
CLI 실행 경로 ✕ · 비밀번호 노출 위험 ③<br>CLI 실행 경로: 없음 (Dockerfile · docker-compose 없음 · 플랫폼 명시 없음 · package.json:4 scripts.dev/build/start 만)<br>관리 명령: 없음 (첫 관리자 생성 스크립트 · 잠금 해제 · 카탈로그 동기화 코드 전무)<br>절차 문서: 없음 (검색: procedure|admin|operation → 0건)
풀리는 곳
코드/문서
고칠 방향
배포 플랫폼 결정 후 CLI 실행 경로 문서화 (Vercel 등 매니지드면 로컬 스크립트 + Supabase SQL) · 관리자 초기화 스크립트 작성 · classes 카탈로그 시드 스크립트 작성 · 절차 문서 작성
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[11.5] 운영 환경에서 관리 명령(첫 관리자 생성 · 잠금 해제 · 카탈로그 동기화)을 실행할 경로가 있다
지금 상태: CLI 실행 경로 ✕ · 비밀번호 노출 위험 ③ CLI 실행 경로: 없음 (Dockerfile · docker-compose 없음 · 플랫폼 명시 없음 · package.json:4 scripts.dev/build/start 만) 관리 명령: 없음 (첫 관리자 생성 스크립트 · 잠금 해제 · 카탈로그 동기화 코드 전무) 절차 문서: 없음 (검색: procedure¦admin¦operation → 0건)
관련 위치: scripts.dev/build/start
할 일: 배포 플랫폼 결정 후 CLI 실행 경로 문서화 (Vercel 등 매니지드면 로컬 스크립트 + Supabase SQL) · 관리자 초기화 스크립트 작성 · classes 카탈로그 시드 스크립트 작성 · 절차 문서 작성

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
11.6인수인계 — 실행·배포 문서, 외부 계정 대장(소유자 · 2FA · 복구 메일 · 결제수단 · 접근자), 시크릿 대장(위치 · 회전일)문제차단
근거
실행 문서 ○ · 배포 문서 ✕ · 계정 대장 ✕ · 시크릿 대장 ✕<br>실행 문서: README.md:11-17 (cp .env.example .env.local · npm install · npm run dev)<br>배포 문서: 없음 (검색: deploy|runbook|operation → 0건 · README 개발 환경만)<br>계정 대장: 없음 (검색: account|credential|owner|2FA → 0건)<br>시크릿 대장: 없음 (검색: secret|rotation|rotate → 0건 · .env.example:1-5 키 목록만)
풀리는 곳
문서
고칠 방향
배포 플랫폼·절차 문서 작성 · Supabase·토스페이먼츠·배포 플랫폼 계정 대장 작성 (소유자 · 2FA · 복구 메일 · 결제수단 · 접근자) · 시크릿 대장 작성 (위치: Supabase 프로젝트 설정 · 토스 개발자센터 · 플랫폼 환경변수 / 회전일 정책)
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[11.6] 인수인계 — 실행·배포 문서, 외부 계정 대장(소유자 · 2FA · 복구 메일 · 결제수단 · 접근자), 시크릿 대장(위치 · 회전일)
지금 상태: 실행 문서 ○ · 배포 문서 ✕ · 계정 대장 ✕ · 시크릿 대장 ✕ 실행 문서: README.md:11-17 (cp .env.example .env.local · npm install · npm run dev) 배포 문서: 없음 (검색: deploy¦runbook¦operation → 0건 · README 개발 환경만) 계정 대장: 없음 (검색: account¦credential¦owner¦2FA → 0건) 시크릿 대장: 없음 (검색: secret¦rotation¦rotate → 0건 · .env.example:1-5 키 목록만)
할 일: 배포 플랫폼·절차 문서 작성 · Supabase·토스페이먼츠·배포 플랫폼 계정 대장 작성 (소유자 · 2FA · 복구 메일 · 결제수단 · 접근자) · 시크릿 대장 작성 (위치: Supabase 프로젝트 설정 · 토스 개발자센터 · 플랫폼 환경변수 / 회전일 정책)

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.

12. 출시 품질

12.2판매자(운영 당사자)가 실제 운영에 필요한 쓰기 — 취소 · 환불 · 입장/수령 확인문제차단
근거
판매자 콘솔 쓰기 ✕ · 환불 ✕ · 입장 확인 ✕<br>판매자 콘솔: app/admin/page.tsx:8-18 (orders 조회만 · 쓰기 없음)<br>환불: 없음 (검색: cancel|refund|환불|취소 → 0건)<br>입장 확인: 없음 (수강생 출석 체크 로직 없음 · orders.status 가 PAID 로만 종결)
풀리는 곳
코드
고칠 방향
app/admin 에 환불 버튼 추가 (토스 결제 취소 API 호출) · 입장 확인 화면 추가 (QR 스캔 또는 주문 ID 검색 → orders.status 를 ATTENDED 등으로 업데이트)
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[12.2] 판매자(운영 당사자)가 실제 운영에 필요한 쓰기 — 취소 · 환불 · 입장/수령 확인
지금 상태: 판매자 콘솔 쓰기 ✕ · 환불 ✕ · 입장 확인 ✕ 판매자 콘솔: app/admin/page.tsx:8-18 (orders 조회만 · 쓰기 없음) 환불: 없음 (검색: cancel¦refund¦환불¦취소 → 0건) 입장 확인: 없음 (수강생 출석 체크 로직 없음 · orders.status 가 PAID 로만 종결)
관련 위치: app/admin/page.tsx:8-18
할 일: app/admin 에 환불 버튼 추가 (토스 결제 취소 API 호출) · 입장 확인 화면 추가 (QR 스캔 또는 주문 ID 검색 → orders.status 를 ATTENDED 등으로 업데이트)

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
12.3메일·문자 실발송 + 도달(SPF/DKIM/DMARC, 스팸함) + 거래 알림(주문 확인) 템플릿문제차단
근거
발송 어댑터 ✕ · DNS 인증 ✕ · 템플릿 ✕ · 실발송 ③<br>발송 어댑터: 없음 (검색: nodemailer|resend|smtp|sendgrid|ses|mailgun|postmark → 0건)<br>DNS 인증: 없음 (검색: SPF|DKIM|DMARC → 0건)<br>템플릿: 없음 (메일 템플릿 파일 없음 · .env.example:5 ADMIN_EMAIL 변수만)<br>주문 확인: app/pay/success/page.tsx:12 "마이페이지에서 예약 코드를 확인하세요" 문구만 (실제 발송 없음)
풀리는 곳
코드/외부/문서
고칠 방향
Resend 류 발송 어댑터 추가 · 주문 확인 메일 템플릿 작성 · 도메인 DNS SPF/DKIM/DMARC 설정 · app/api/checkout/confirm/route.ts:17 뒤에 메일 발송 로직 추가 · 실발송 테스트 후 기록
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[12.3] 메일·문자 실발송 + 도달(SPF/DKIM/DMARC, 스팸함) + 거래 알림(주문 확인) 템플릿
지금 상태: 발송 어댑터 ✕ · DNS 인증 ✕ · 템플릿 ✕ · 실발송 ③ 발송 어댑터: 없음 (검색: nodemailer¦resend¦smtp¦sendgrid¦ses¦mailgun¦postmark → 0건) DNS 인증: 없음 (검색: SPF¦DKIM¦DMARC → 0건) 템플릿: 없음 (메일 템플릿 파일 없음 · .env.example:5 ADMIN_EMAIL 변수만) 주문 확인: app/pay/success/page.tsx:12 "마이페이지에서 예약 코드를 확인하세요" 문구만 (실제 발송 없음)
관련 위치: app/pay/success/page.tsx:12
할 일: Resend 류 발송 어댑터 추가 · 주문 확인 메일 템플릿 작성 · 도메인 DNS SPF/DKIM/DMARC 설정 · app/api/checkout/confirm/route.ts:17 뒤에 메일 발송 로직 추가 · 실발송 테스트 후 기록

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
12.4핵심 흐름 5개 수동 통과표(날짜 · 수행자) + 모바일 실기기 2대(HTTPS 호스트 뒤)문제차단
근거
통과표 ✕ · 실기기 기록 ✕<br>통과표: 없음 (검색: test.*checklist|test.*pass|manual.*test → 0건)<br>실기기 기록: 없음 (저장소 내 문서 없음)
풀리는 곳
결정
고칠 방향
핵심 흐름 정의 (예: 로그인 · 클래스 목록 · 결제 · 결제 확인 · 관리자 조회) · 수동 테스트 통과표 작성 (날짜 · 수행자) · 모바일 2대 (iOS · Android) 실기기 테스트 후 기록 문서화
저장소 밖에서 할 일계약·콘솔·서류처럼 코드로 안 풀리는 일이에요. 위 "고칠 방향" 대로 직접 하거나, 출시 패키지로 같이 할 수 있어요.

13. 국내 법규

13.1사업자 정보·통신판매업 번호 footer + 개인정보 보호책임자 + 문의 동선문제차단
근거
사업자 정보 ✕ · 통판 번호 ✕ · 보호책임자 ✕ · 문의 동선 ✕<br>app/layout.tsx:3 <footer>© 공방 원데이</footer> — 저작권 표시만, 사업자 정보·통판 번호·보호책임자 없음<br>검색: 고객센터|상담|문의|contact|support → 0건
풀리는 곳
코드
고칠 방향
footer 에 사업자 정보·통판 번호·보호책임자·연락 수단(메일/전화) 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[13.1] 사업자 정보·통신판매업 번호 footer + 개인정보 보호책임자 + 문의 동선
지금 상태: 사업자 정보 ✕ · 통판 번호 ✕ · 보호책임자 ✕ · 문의 동선 ✕ app/layout.tsx:3 <footer>© 공방 원데이</footer> — 저작권 표시만, 사업자 정보·통판 번호·보호책임자 없음 검색: 고객센터¦상담¦문의¦contact¦support → 0건
관련 위치: app/layout.tsx:3
할 일: footer 에 사업자 정보·통판 번호·보호책임자·연락 수단(메일/전화) 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
13.2약관 — 구매·지급·청약철회·환급 조항, 거래 구조(중개자 고지), 자리 표시자 0, 효력일 순서문제차단
근거
약관 문안 ✕ · 자리 표시자 — · 효력일 ✕<br>app/login/page.tsx:9 <a href="#">이용약관</a> — href="#", 실제 문안 없음<br>검색: 약관|terms → 링크만, 문안 파일(md·json·CMS) 없음
풀리는 곳
코드/결정
고칠 방향
약관 문안 작성(구매·청약철회·환급·중개자 여부 명시), 효력일 기재, 문안 파일 추가 및 링크 수정
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[13.2] 약관 — 구매·지급·청약철회·환급 조항, 거래 구조(중개자 고지), 자리 표시자 0, 효력일 순서
지금 상태: 약관 문안 ✕ · 자리 표시자 — · 효력일 ✕ app/login/page.tsx:9 <a href="#">이용약관</a> — href="#", 실제 문안 없음 검색: 약관¦terms → 링크만, 문안 파일(md·json·CMS) 없음
관련 위치: app/login/page.tsx:9
할 일: 약관 문안 작성(구매·청약철회·환급·중개자 여부 명시), 효력일 기재, 문안 파일 추가 및 링크 수정

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
13.3처리방침 — 수집 항목·처리위탁·보존 기간·국외 이전·판매자 제공 항목이 코드 사실과 일치문제차단
근거
처리방침 문안 ✕ · 코드 대조 ✕<br>app/login/page.tsx:9 <a href="#">개인정보처리방침</a> — href="#", 실제 문안 없음<br>코드 사실: supabase/migrations/001_init.sql:13-14 buyer_name text, buyer_phone text (이름·전화 수집) · app/api/checkout/confirm/route.ts:7-14 토스페이먼츠 API 전송 → 문안 없어 대조 불가
풀리는 곳
코드/결정
고칠 방향
처리방침 문안 작성(수집: 이름·전화·결제정보 / 위탁: 토스·Supabase / 국외 이전: Supabase 위치 확인 / 보존: 거래 5년), 문안 파일 추가 및 링크 수정
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[13.3] 처리방침 — 수집 항목·처리위탁·보존 기간·국외 이전·판매자 제공 항목이 코드 사실과 일치
지금 상태: 처리방침 문안 ✕ · 코드 대조 ✕ app/login/page.tsx:9 <a href="#">개인정보처리방침</a> — href="#", 실제 문안 없음 코드 사실: supabase/migrations/001_init.sql:13-14 buyer_name text, buyer_phone text (이름·전화 수집) · app/api/checkout/confirm/route.ts:7-14 토스페이먼츠 API 전송 → 문안 없어 대조 불가
관련 위치: app/api/checkout/confirm/route.ts:7-14, app/login/page.tsx:9, supabase/migrations/001_init.sql:13-14
할 일: 처리방침 문안 작성(수집: 이름·전화·결제정보 / 위탁: 토스·Supabase / 국외 이전: Supabase 위치 확인 / 보존: 거래 5년), 문안 파일 추가 및 링크 수정

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
13.4동의 — 필수/선택 분리 · 만 14세 · 마케팅 분리·철회 · 결제 전 취소 규정 동의와 버전 기록문제차단
근거
필수/선택 분리 ✕ · 만 14세 ✕ · 마케팅 분리 — · 결제 전 동의 ✕ · 버전 기록 ✕<br>app/login/page.tsx:9 <p>가입하면 <a href="#">이용약관</a>과 <a href="#">개인정보처리방침</a>에 동의한 것으로 봅니다.</p> — 체크박스 없음, 묵시 동의<br>supabase/migrations/001_init.sql:9-19 orders 테이블 — 동의 버전 열 없음<br>app/classes/page.tsx:10-26 결제 흐름 — 취소 규정 동의 체크 없음
풀리는 곳
코드
고칠 방향
가입 화면에 체크박스(필수: 약관·방침·만 14세, 선택: 마케팅) 추가, 결제 전 취소 규정 동의 체크박스 추가, orders.consent_version 열 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[13.4] 동의 — 필수/선택 분리 · 만 14세 · 마케팅 분리·철회 · 결제 전 취소 규정 동의와 버전 기록
지금 상태: 필수/선택 분리 ✕ · 만 14세 ✕ · 마케팅 분리 — · 결제 전 동의 ✕ · 버전 기록 ✕ app/login/page.tsx:9 <p>가입하면 <a href="#">이용약관</a>과 <a href="#">개인정보처리방침</a>에 동의한 것으로 봅니다.</p> — 체크박스 없음, 묵시 동의 supabase/migrations/001_init.sql:9-19 orders 테이블 — 동의 버전 열 없음 app/classes/page.tsx:10-26 결제 흐름 — 취소 규정 동의 체크 없음
관련 위치: app/classes/page.tsx:10-26, app/login/page.tsx:9, supabase/migrations/001_init.sql:9-19
할 일: 가입 화면에 체크박스(필수: 약관·방침·만 14세, 선택: 마케팅) 추가, 결제 전 취소 규정 동의 체크박스 추가, orders.consent_version 열 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
13.5거래기록 5년 보존 vs 탈퇴·삭제 정책, 탈퇴 동선문제차단
근거
탈퇴 동선 ✕ · 보존 정책 ✕<br>검색: 탈퇴|withdraw|delete.*account → 0건, 탈퇴 기능 없음<br>supabase/migrations/001_init.sql:9-19 orders 테이블 — 보존·익명화 정책 명시 없음
풀리는 곳
코드/결정
고칠 방향
탈퇴 동선 추가(마이페이지·설정), 탈퇴 시 주문 행 보존 정책 결정(거래 5년 vs 개인정보 삭제), 익명화 로직 구현
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[13.5] 거래기록 5년 보존 vs 탈퇴·삭제 정책, 탈퇴 동선
지금 상태: 탈퇴 동선 ✕ · 보존 정책 ✕ 검색: 탈퇴¦withdraw¦delete.account → 0건, 탈퇴 기능 없음 supabase/migrations/001_init.sql:9-19 orders 테이블 — 보존·익명화 정책 명시 없음
관련 위치: supabase/migrations/001_init.sql:9-19
할 일: 탈퇴 동선 추가(마이페이지·설정), 탈퇴 시 주문 행 보존 정책 결정(거래 5년 vs 개인정보 삭제), 익명화 로직 구현

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
13.6판매자 불이행 보상(소비자분쟁해결기준)과 배상 주체, 연령 제한 상품의 확인 강제문제차단
근거
보상 조항 ✕ · 배상 집행 ✕ · 연령 확인 —<br>검색: 보상|배상|손해|불이행 → 0건, 약관 없음(13.2)<br>검색: age|연령|미성년 → 0건, 연령 제한 상품 해당 없음(원데이 클래스)
풀리는 곳
코드/결정
고칠 방향
약관에 불이행 보상 조항 추가(배상 주체: 판매자 직접 or 플랫폼 중개), 코드의 환불·보상 집행 경로 구현
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[13.6] 판매자 불이행 보상(소비자분쟁해결기준)과 배상 주체, 연령 제한 상품의 확인 강제
지금 상태: 보상 조항 ✕ · 배상 집행 ✕ · 연령 확인 — 검색: 보상¦배상¦손해¦불이행 → 0건, 약관 없음(13.2) 검색: age¦연령¦미성년 → 0건, 연령 제한 상품 해당 없음(원데이 클래스)
할 일: 약관에 불이행 보상 조항 추가(배상 주체: 판매자 직접 or 플랫폼 중개), 코드의 환불·보상 집행 경로 구현

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
13.7변호사 검토 — 질문 목록·발송일·회신이 한 곳에 기록된다문제차단
근거
검토 기록 ✕<br>검색: 검토|review|lawyer|변호사|법무 → 0건<br>docs 디렉터리 없음, .github/issues 없음(이슈 기록은 저장소 밖이라 확인 못 함)
풀리는 곳
결정/외부
고칠 방향
변호사 검토 질문 목록 작성(약관·처리방침·거래 구조·책임 범위), 발송 및 회신 문서 작성, 저장소에 기록(docs/legal-review.md 또는 이슈)
저장소 밖에서 할 일계약·콘솔·서류처럼 코드로 안 풀리는 일이에요. 위 "고칠 방향" 대로 직접 하거나, 출시 패키지로 같이 할 수 있어요.

14. 국내 연동

14.1PG 심사 서류 + 실 도메인 서비스 URL문제차단
근거
심사용 URL ? · 도메인 명시 ✕<br>README.md:1-3 "⚠️ vamuri 샘플용 가상 앱 … 실제 서비스가 아니고" — 운영 도메인 없음 명시<br>.env.example:3-4 test_ck_xxxxxxxx · test_sk_xxxxxxxx — 테스트 키, 프로덕션 심사 전<br>서류(사업자등록증·통판·신분증·통장)는 외부 — 확인 불가(?)
풀리는 곳
외부
고칠 방향
운영 도메인 확보, 도메인에 약관·처리방침·사업자 정보 배포, PG 심사 서류 제출
저장소 밖에서 할 일계약·콘솔·서류처럼 코드로 안 풀리는 일이에요. 위 "고칠 방향" 대로 직접 하거나, 출시 패키지로 같이 할 수 있어요.
14.2메일 공급자 프로덕션 액세스 · 도메인 인증(DKIM) · 바운스 처리문제차단
근거
메일 어댑터 구현 ✕ · DKIM ✕ · 바운스 처리 ✕<br>검색: nodemailer|resend|sendgrid|ses|smtp|mailer → 0건, 메일 어댑터 없음<br>.env.example:5 ADMIN_EMAIL=owner@example.com — 수신 주소만, 발신 구현 없음
풀리는 곳
코드/외부
고칠 방향
메일 공급자(Resend·SendGrid·SES 등) 선택 및 어댑터 구현, 발신 도메인 DKIM 설정, 바운스 웹훅 처리 코드 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[14.2] 메일 공급자 프로덕션 액세스 · 도메인 인증(DKIM) · 바운스 처리
지금 상태: 메일 어댑터 구현 ✕ · DKIM ✕ · 바운스 처리 ✕ 검색: nodemailer¦resend¦sendgrid¦ses¦smtp¦mailer → 0건, 메일 어댑터 없음 .env.example:5 ADMIN_EMAIL=owner@example.com — 수신 주소만, 발신 구현 없음
할 일: 메일 공급자(Resend·SendGrid·SES 등) 선택 및 어댑터 구현, 발신 도메인 DKIM 설정, 바운스 웹훅 처리 코드 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.

영역별 판정 14

1시크릿041
1.1저장소와 전 히스토리에 시크릿이 없다문제차단
근거
커밋 파일 ○ — .env.example 만 있음 (git ls-files) · 히스토리 ? — 이번 진단은 현재 파일만 봤어요 · 방지 장치 ✕ — gitleaks/secret-scan 설정 없음 (glob → 0건) · CI 단계 ✕ — .github/workflows 없음
풀리는 곳
코드
고칠 방향
gitleaks 설정 추가 · CI 스캔 단계 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[1.1] 저장소와 전 히스토리에 시크릿이 없다
지금 상태: 커밋 파일 ○ — .env.example 만 있음 (git ls-files) · 히스토리 ? — 이번 진단은 현재 파일만 봤어요 · 방지 장치 ✕ — gitleaks/secret-scan 설정 없음 (glob → 0건) · CI 단계 ✕ — .github/workflows 없음
관련 위치: .github/workflows, gitleaks/secret-scan
할 일: gitleaks 설정 추가 · CI 스캔 단계 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
1.2브라우저가 받는 응답에 서버 시크릿이 없다문제차단
근거
공개 접두 변수 ✕ — NEXT_PUBLIC_TOSS_SECRET_KEY (app/api/checkout/confirm/route.ts:10 — 서버 전용 비밀이 NEXT_PUBLIC_ 접두로 노출) · 클라이언트 참조 ✕ — app/classes/page.tsx:16 NEXT_PUBLIC_TOSS_CLIENT_KEY (클라이언트 키는 정상, 하지만 SECRET_KEY 가 NEXT_PUBLIC_ 로 노출됨) · 오류 본문 ○ — 오류 처리 없음 (catch 문 0건) · 도메인 제한 기록 ✕ — 없음 · 빌드 산출물 ③
풀리는 곳
코드
고칠 방향
NEXT_PUBLIC_TOSS_SECRET_KEY → TOSS_SECRET_KEY 로 변경 (서버 전용)
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[1.2] 브라우저가 받는 응답에 서버 시크릿이 없다
지금 상태: 공개 접두 변수 ✕ — NEXT_PUBLIC_TOSS_SECRET_KEY (app/api/checkout/confirm/route.ts:10 — 서버 전용 비밀이 NEXT_PUBLIC_ 접두로 노출) · 클라이언트 참조 ✕ — app/classes/page.tsx:16 NEXT_PUBLIC_TOSS_CLIENT_KEY (클라이언트 키는 정상, 하지만 SECRET_KEY 가 NEXT_PUBLIC_ 로 노출됨) · 오류 본문 ○ — 오류 처리 없음 (catch 문 0건) · 도메인 제한 기록 ✕ — 없음 · 빌드 산출물 ③
관련 위치: app/api/checkout/confirm/route.ts:10, app/classes/page.tsx:16
할 일: NEXT_PUBLIC_TOSS_SECRET_KEY → TOSS_SECRET_KEY 로 변경 (서버 전용)

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
1.3로그 채널별로 개인정보·토큰이 찍히지 않는다문제차단
근거
앱 로그 ✕ — console.log('confirm', { paymentKey, orderId, amount }) (app/api/checkout/confirm/route.ts:5 — paymentKey 토큰 노출) · DB 오류 로그 ○ — ORM 로깅 설정 없음 (Supabase 클라이언트는 기본 로깅 안 함) · 접근 로그 ○ — 프록시 없음 (middleware.ts 없음 · 00-map.md:26) · 재설정 토큰 — — 기능 없음
풀리는 곳
코드
고칠 방향
console.log 에서 paymentKey 제거 또는 마스킹
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[1.3] 로그 채널별로 개인정보·토큰이 찍히지 않는다
지금 상태: 앱 로그 ✕ — console.log('confirm', { paymentKey, orderId, amount }) (app/api/checkout/confirm/route.ts:5 — paymentKey 토큰 노출) · DB 오류 로그 ○ — ORM 로깅 설정 없음 (Supabase 클라이언트는 기본 로깅 안 함) · 접근 로그 ○ — 프록시 없음 (middleware.ts 없음 · 00-map.md:26) · 재설정 토큰 — — 기능 없음
관련 위치: app/api/checkout/confirm/route.ts:5
할 일: console.log 에서 paymentKey 제거 또는 마스킹

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
1.4프로덕션 시크릿 주입 경로가 실제로 있고, 개발 기본값·누락이면 부팅이 거부된다문제차단
근거
배포 설정 ✕ — 없음 (Dockerfile · docker-compose · vercel.json · fly.toml → 0건) · 부팅 검사 ✕ — 없음 (lib/supabase.ts:4-5 ! 연산자만 — 런타임 오류는 내지만 부팅 전 검증 없음) · 검사 spec ✕ — 테스트 없음 (*.test.* → 0건) · 집합 차 ✕ — 코드 읽음 {NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, NEXT_PUBLIC_TOSS_CLIENT_KEY, NEXT_PUBLIC_TOSS_SECRET_KEY, ADMIN_EMAIL} − 배포 주입 {} = 전부 누락 (배포 설정 없음)
풀리는 곳
코드
고칠 방향
부팅 시 필수 env 검증 추가 · 배포 설정에 env 주입 명시
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[1.4] 프로덕션 시크릿 주입 경로가 실제로 있고, 개발 기본값·누락이면 부팅이 거부된다
지금 상태: 배포 설정 ✕ — 없음 (Dockerfile · docker-compose · vercel.json · fly.toml → 0건) · 부팅 검사 ✕ — 없음 (lib/supabase.ts:4-5 ! 연산자만 — 런타임 오류는 내지만 부팅 전 검증 없음) · 검사 spec ✕ — 테스트 없음 (.test. → 0건) · 집합 차 ✕ — 코드 읽음 {NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, NEXT_PUBLIC_TOSS_CLIENT_KEY, NEXT_PUBLIC_TOSS_SECRET_KEY, ADMIN_EMAIL} − 배포 주입 {} = 전부 누락 (배포 설정 없음)
관련 위치: lib/supabase.ts:4-5
할 일: 부팅 시 필수 env 검증 추가 · 배포 설정에 env 주입 명시

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
1.5키 회전 절차가 키마다 있고 한 번 리허설했다미확인권장
근거
이전 키 슬롯 ✕ — 없음 (검색: _PREVIOUS|_OLD|rotation → 0건) · 절차 문서 ✕ — 없음 (docs 디렉터리 없음 · README 실행 섹션만) · 리허설 기록 ✕ — 없음
풀리는 곳
결정
고칠 방향
키 회전 절차 문서 작성 · 리허설 실행
저장소 밖에서 할 일계약·콘솔·서류처럼 코드로 안 풀리는 일이에요. 위 "고칠 방향" 대로 직접 하거나, 출시 패키지로 같이 할 수 있어요.
2접근 제어041
2.1모든 API 라우트가 권한을 명시하고 미명시는 기본 거부다문제차단
근거
라우트 ✕ — app/api/checkout/confirm/route.ts (POST) · app/api/webhooks/toss/route.ts (POST) 총 2개 · 전역 가드 ✕ — middleware.ts 없음 · RLS 전수 ✕ — orders 테이블 RLS 없음 (001_init.sql:9-19 — classes 만 RLS, orders 는 누구나 조회·수정 가능) · 신원 위조 ✕ — app/api/webhooks/toss/route.ts:4-6 body.data.orderId 를 그대로 신뢰 (서명 검증 없음) · 미명시 처리 ✕ — 인증 검사 없음 (auth/guard/Depends → 0건) · 테스트 ✕ — 없음
풀리는 곳
코드
고칠 방향
orders 테이블 RLS 활성화 · 웹훅 서명 검증 추가 · API 인증 미들웨어 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[2.1] 모든 API 라우트가 권한을 명시하고 미명시는 기본 거부다
지금 상태: 라우트 ✕ — app/api/checkout/confirm/route.ts (POST) · app/api/webhooks/toss/route.ts (POST) 총 2개 · 전역 가드 ✕ — middleware.ts 없음 · RLS 전수 ✕ — orders 테이블 RLS 없음 (001_init.sql:9-19 — classes 만 RLS, orders 는 누구나 조회·수정 가능) · 신원 위조 ✕ — app/api/webhooks/toss/route.ts:4-6 body.data.orderId 를 그대로 신뢰 (서명 검증 없음) · 미명시 처리 ✕ — 인증 검사 없음 (auth/guard/Depends → 0건) · 테스트 ✕ — 없음
관련 위치: app/api/checkout/confirm/route.ts, app/api/webhooks/toss/route.ts, app/api/webhooks/toss/route.ts:4-6, auth/guard/Depends
할 일: orders 테이블 RLS 활성화 · 웹훅 서명 검증 추가 · API 인증 미들웨어 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
2.2소유자·테넌트 격리 — 남의 id 로 조회·수정·취소하면 404/403 (IDOR)문제차단
근거
WHERE user_id ✕ — app/admin/page.tsx:8 .select('*') (조건 없음 — 전체 조회) · app/api/checkout/confirm/route.ts:17 .eq('id', orderId) (user_id 검증 없음 — 남의 주문도 PAID 처리 가능) · app/api/webhooks/toss/route.ts:6 .eq('id', body.data.orderId) (소유자 검증 없음) · 신원 서버 결정 ✕ — 클라이언트가 보낸 orderId (app/pay/success/page.tsx:11 쿼리 파라미터) 를 그대로 사용 · 404/403 구분 ✕ — 없음 · IDOR 테스트 ✕ — 없음
풀리는 곳
코드
고칠 방향
orders 테이블에 WHERE user_id 조건 추가 · 세션에서 user_id 추출
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[2.2] 소유자·테넌트 격리 — 남의 id 로 조회·수정·취소하면 404/403 (IDOR)
지금 상태: WHERE user_id ✕ — app/admin/page.tsx:8 .select('') (조건 없음 — 전체 조회) · app/api/checkout/confirm/route.ts:17 .eq('id', orderId) (user_id 검증 없음 — 남의 주문도 PAID 처리 가능) · app/api/webhooks/toss/route.ts:6 .eq('id', body.data.orderId) (소유자 검증 없음) · 신원 서버 결정 ✕ — 클라이언트가 보낸 orderId (app/pay/success/page.tsx:11 쿼리 파라미터) 를 그대로 사용 · 404/403 구분 ✕ — 없음 · IDOR 테스트 ✕ — 없음
관련 위치: 404/403, app/admin/page.tsx:8, app/api/checkout/confirm/route.ts:17, app/api/webhooks/toss/route.ts:6, app/pay/success/page.tsx:11
할 일: orders 테이블에 WHERE user_id 조건 추가 · 세션에서 user_id 추출

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
2.3서버 액션·라우트 핸들러·엣지 함수가 API 가드를 우회해 DB 를 직접 만지지 않는다문제차단
근거
웹 앱 DB 드라이버 ✕ — lib/supabase.ts:3-6 (클라이언트 앱에서 Supabase 직접 생성 · app/classes/page.tsx:8 · app/admin/page.tsx:8 브라우저에서 직접 DB 조회) · API 호출 단일화 ✕ — 클라이언트 컴포넌트가 supabase.from() 직접 호출 (app/classes/page.tsx:8·13 · app/admin/page.tsx:8) · 우회 경로 ✕ — 있음 (서버 액션은 없지만 클라이언트가 DB 직접 조회) · 서버 액션 인증 — — 서버 액션 없음
풀리는 곳
코드
고칠 방향
클라이언트의 직접 DB 접근 제거 · API 라우트로 전환
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[2.3] 서버 액션·라우트 핸들러·엣지 함수가 API 가드를 우회해 DB 를 직접 만지지 않는다
지금 상태: 웹 앱 DB 드라이버 ✕ — lib/supabase.ts:3-6 (클라이언트 앱에서 Supabase 직접 생성 · app/classes/page.tsx:8 · app/admin/page.tsx:8 브라우저에서 직접 DB 조회) · API 호출 단일화 ✕ — 클라이언트 컴포넌트가 supabase.from() 직접 호출 (app/classes/page.tsx:8·13 · app/admin/page.tsx:8) · 우회 경로 ✕ — 있음 (서버 액션은 없지만 클라이언트가 DB 직접 조회) · 서버 액션 인증 — — 서버 액션 없음
관련 위치: app/admin/page.tsx:8, app/classes/page.tsx:8, lib/supabase.ts:3-6
할 일: 클라이언트의 직접 DB 접근 제거 · API 라우트로 전환

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
2.4관리자 응답이 개인정보를 가리고, 열람·검색이 기록된다문제권장
근거
관리자 API ✕ — app/admin/page.tsx:15 buyer_name · buyer_phone 원문 표시 · 열람 감사 로그 ✕ — 없음 (검색: audit|log.*admin → 0건) · 관리자 콘솔 ○ — 있음 (app/admin/page.tsx — 인증은 없지만 화면은 존재)
풀리는 곳
코드
고칠 방향
개인정보 마스킹 (전화 뒷자리) · 열람 로그 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[2.4] 관리자 응답이 개인정보를 가리고, 열람·검색이 기록된다
지금 상태: 관리자 API ✕ — app/admin/page.tsx:15 buyer_name · buyer_phone 원문 표시 · 열람 감사 로그 ✕ — 없음 (검색: audit¦log.admin → 0건) · 관리자 콘솔 ○ — 있음 (app/admin/page.tsx — 인증은 없지만 화면은 존재)
관련 위치: app/admin/page.tsx, app/admin/page.tsx:15
할 일: 개인정보 마스킹 (전화 뒷자리) · 열람 로그 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
2.5스토리지 버킷은 전부 비공개, 읽기는 서명 URL/CDN, 업로드 키는 서버가 만든다해당없음차단
근거
— 스토리지 기능 없음 (검색: upload|storage|bucket|S3|blob → 0건 · 00-map.md:15)
풀리는 곳
—
고칠 방향
—
3인증033
3.1비밀번호는 느린 해시(argon2 · scrypt · bcrypt)로만, 가역 저장은 전용 키가 있는 것(TOTP 비밀 등)만해당없음—
근거
해당 없음 — Supabase OAuth (카카오) 단일 경로 사용, 비밀번호 인증 자체 없음 (app/login/page.tsx:8 signInWithOAuth({ provider: 'kakao' }) · 비밀번호 필드·해시·저장 코드 전무)
풀리는 곳
—
고칠 방향
—
3.2세션 쿠키 Secure · HttpOnly · SameSite · Domain 없음, 파기·정지가 요청마다 즉시 반영미확인차단
근거
? Supabase SDK 기본값에 의존 — 쿠키 설정 코드 없음 (lib/supabase.ts:3-5 createClient 호출만, 세션 관리·로그아웃 구현 전무) · ? 로그아웃 경로 없음 (검색: signOut|logout|로그아웃 → 0건) · ? 세션 파기·재설정 로직 없음
풀리는 곳
코드
고칠 방향
Supabase Auth 쿠키 설정 확인 + 로그아웃 경로 구현
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[3.2] 세션 쿠키 Secure · HttpOnly · SameSite · Domain 없음, 파기·정지가 요청마다 즉시 반영
지금 상태: ? Supabase SDK 기본값에 의존 — 쿠키 설정 코드 없음 (lib/supabase.ts:3-5 createClient 호출만, 세션 관리·로그아웃 구현 전무) · ? 로그아웃 경로 없음 (검색: signOut¦logout¦로그아웃 → 0건) · ? 세션 파기·재설정 로직 없음
관련 위치: lib/supabase.ts:3-5
할 일: Supabase Auth 쿠키 설정 확인 + 로그아웃 경로 구현

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
3.3인증번호·재설정 토큰은 해시 저장 · 1회성 · 만료 · 시도 횟수 제한 · 발송 한도(IP 존 + 주소별 백오프)해당없음—
근거
해당 없음 — OAuth 단일 경로, 인증번호·재설정 토큰 기능 자체 없음 (검색: reset|forgot|recovery|토큰|OTP|code → 0건)
풀리는 곳
—
고칠 방향
—
3.4운영에서 실제로 동작하는 가입·로그인 경로가 하나 이상 있다문제차단
근거
✕ 경로는 있으나(app/login/page.tsx:8 카카오 OAuth) 공급자 연결 확인 불가 — Supabase 콘솔 설정에서만 확인됨 (코드에 공급자 연결 상태 없음 · .env.example의 SUPABASE_URL/ANON_KEY 예시값) · ✕ 로그인 후 세션 확인 코드 없음 (앱 전체에 getSession|getUser|auth().user 호출 0건)
풀리는 곳
외부 + 코드
고칠 방향
Supabase 콘솔에서 카카오 OAuth 공급자 연결 확인 + 세션 확인 코드 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[3.4] 운영에서 실제로 동작하는 가입·로그인 경로가 하나 이상 있다
지금 상태: ✕ 경로는 있으나(app/login/page.tsx:8 카카오 OAuth) 공급자 연결 확인 불가 — Supabase 콘솔 설정에서만 확인됨 (코드에 공급자 연결 상태 없음 · .env.example의 SUPABASE_URL/ANON_KEY 예시값) · ✕ 로그인 후 세션 확인 코드 없음 (앱 전체에 getSession¦getUser¦auth().user 호출 0건)
관련 위치: SUPABASE_URL/ANON_KEY, app/login/page.tsx:8
할 일: Supabase 콘솔에서 카카오 OAuth 공급자 연결 확인 + 세션 확인 코드 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
3.5모든 역할(고객 · 판매자 · 직원 · 관리자)에 비밀번호 복구와 계정 잠금 경로가 닫혀 있다문제차단
근거
— 비밀번호 복구 (OAuth 전용, 해당 없음) · ✕ 계정 잠금 전무 (검색: lock|locked|attempts|failed.*login → 0건) · ✕ 잠금 해제 경로 없음
풀리는 곳
코드
고칠 방향
로그인 시도 횟수 제한 + 잠금 구현
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[3.5] 모든 역할(고객 · 판매자 · 직원 · 관리자)에 비밀번호 복구와 계정 잠금 경로가 닫혀 있다
지금 상태: — 비밀번호 복구 (OAuth 전용, 해당 없음) · ✕ 계정 잠금 전무 (검색: lock¦locked¦attempts¦failed.login → 0건) · ✕ 잠금 해제 경로 없음
할 일: 로그인 시도 횟수 제한 + 잠금 구현

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
3.6관리자 로그인은 2단계(TOTP) + 잠금, 등록·복구·해제가 운영 환경에서 실행 가능문제권장
근거
✕ 관리자 콘솔 있음 (app/admin/page.tsx:5 "사장님 화면 — 메뉴에는 안 보이게 해 둠") · ✕ 인증 전무 (app/admin/page.tsx:6-8 세션 확인·권한 검사 없이 바로 orders 조회) · ✕ 2단계 인증 없음 (검색: TOTP|totp|authenticator|2fa|twoFactor → 0건) · ✕ 잠금 없음
풀리는 곳
코드
고칠 방향
관리자 세션 확인 + 역할 검사 + TOTP 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[3.6] 관리자 로그인은 2단계(TOTP) + 잠금, 등록·복구·해제가 운영 환경에서 실행 가능
지금 상태: ✕ 관리자 콘솔 있음 (app/admin/page.tsx:5 "사장님 화면 — 메뉴에는 안 보이게 해 둠") · ✕ 인증 전무 (app/admin/page.tsx:6-8 세션 확인·권한 검사 없이 바로 orders 조회) · ✕ 2단계 인증 없음 (검색: TOTP¦totp¦authenticator¦2fa¦twoFactor → 0건) · ✕ 잠금 없음
관련 위치: app/admin/page.tsx:5, app/admin/page.tsx:6-8
할 일: 관리자 세션 확인 + 역할 검사 + TOTP 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
4입력 검증131
4.1모든 쓰기 입력(body · param · query · header)이 스키마/파서를 거치고, 모르는 필드는 거부문제차단
근거
✕ 입력 검증 라이브러리 없음 (검색: zod|yup|joi|class-validator|pydantic → 0건) · ✕ API 입력 무검증 (app/api/checkout/confirm/route.ts:4 req.json() 결과를 바로 구조분해, 스키마 없음) · ✕ 웹훅 입력 무검증 (app/api/webhooks/toss/route.ts:4 req.json() 바로 사용) · ✕ 클라이언트 입력 무검증 (app/classes/page.tsx:11-12 prompt() 결과를 ! 로만 처리)
풀리는 곳
코드
고칠 방향
zod 등 스키마 라이브러리 추가 + 모든 API 경로에 검증 적용
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[4.1] 모든 쓰기 입력(body · param · query · header)이 스키마/파서를 거치고, 모르는 필드는 거부
지금 상태: ✕ 입력 검증 라이브러리 없음 (검색: zod¦yup¦joi¦class-validator¦pydantic → 0건) · ✕ API 입력 무검증 (app/api/checkout/confirm/route.ts:4 req.json() 결과를 바로 구조분해, 스키마 없음) · ✕ 웹훅 입력 무검증 (app/api/webhooks/toss/route.ts:4 req.json() 바로 사용) · ✕ 클라이언트 입력 무검증 (app/classes/page.tsx:11-12 prompt() 결과를 ! 로만 처리)
관련 위치: app/api/checkout/confirm/route.ts:4, app/api/webhooks/toss/route.ts:4, app/classes/page.tsx:11-12
할 일: zod 등 스키마 라이브러리 추가 + 모든 API 경로에 검증 적용

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
4.2수량·금액 경계 — 0 · 음수 · 소수 · 상한 · 합계 오버플로문제차단
근거
✕ 금액 검증 없음 (app/api/checkout/confirm/route.ts:4 amount 를 req.json()에서 받아 토스로 그대로 전달 · 0/음수/상한 검사 없음) · ✕ 서버 금액 재계산 없음 (app/pay/success/page.tsx:11 클라이언트가 보낸 amount 를 그대로 confirm API 로 전달 · classes 테이블 price 와 대조 안 함) · ✕ DB 제약 없음 (supabase/migrations/001_init.sql:4·15 price·amount 필드가 int not null 만, CHECK 제약 없음 — 음수 허용) · ○ 소수 가드 (001_init.sql:4·15 int 타입)
풀리는 곳
코드
고칠 방향
API 에서 classes.price 조회해 금액 대조 + 0/음수 거부 + DB CHECK 제약 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[4.2] 수량·금액 경계 — 0 · 음수 · 소수 · 상한 · 합계 오버플로
지금 상태: ✕ 금액 검증 없음 (app/api/checkout/confirm/route.ts:4 amount 를 req.json()에서 받아 토스로 그대로 전달 · 0/음수/상한 검사 없음) · ✕ 서버 금액 재계산 없음 (app/pay/success/page.tsx:11 클라이언트가 보낸 amount 를 그대로 confirm API 로 전달 · classes 테이블 price 와 대조 안 함) · ✕ DB 제약 없음 (supabase/migrations/001_init.sql:4·15 price·amount 필드가 int not null 만, CHECK 제약 없음 — 음수 허용) · ○ 소수 가드 (001_init.sql:4·15 int 타입)
관련 위치: app/api/checkout/confirm/route.ts:4, app/pay/success/page.tsx:11, supabase/migrations/001_init.sql:4
할 일: API 에서 classes.price 조회해 금액 대조 + 0/음수 거부 + DB CHECK 제약 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
4.3XSS·SQL 주입 — 위험 API 0건, 바인딩만, 템플릿 보간은 상수·허용 목록통과차단
근거
○ XSS 위험 API 없음 (검색: dangerouslySetInnerHTML|innerHTML|eval|new Function → 0건) · ○ SQL 주입 없음 (Supabase 클라이언트 쿼리 빌더만 사용 · app/api/checkout/confirm/route.ts:17 .update({ status: 'PAID', payment_key: paymentKey }).eq('id', orderId) — 파라미터 바인딩) · ○ 템플릿 보간 상수만 (app/classes/page.tsx:23-24 ${location.origin} 브라우저 내장 객체)
풀리는 곳
—
고칠 방향
—
4.4업로드 — MIME · 크기 · 매직 넘버 · 픽셀 검증, 키는 서버가 만들고 완료 때 실제 바이트를 다시 본다해당없음—
근거
해당 없음 — 업로드 기능 없음 (검색: upload|multer|formidable|multipart|storage → 0건)
풀리는 곳
—
고칠 방향
—
4.5비정상 입력(잘못된 id · 토큰 · NUL · 거대 본문)이 500 이 아니라 400 이고, 프록시 본문 상한이 API 상한과 맞는다문제권장
근거
✕ id 파싱 검증 없음 (app/api/checkout/confirm/route.ts:4 orderId 를 req.json()에서 받아 .eq('id', orderId) 로 바로 사용 · UUID 형식 검증 없음) · ✕ NUL/제어문자 가드 없음 (전체 코드에 입력 정제 로직 없음) · — 프록시 없음 (middleware.ts·nginx·Caddy 설정 전무 · 00-map.md:26 "프록시/엣지: 없음")
풀리는 곳
코드
고칠 방향
입력 스키마에 UUID 검증 추가 + 문자열 정제
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[4.5] 비정상 입력(잘못된 id · 토큰 · NUL · 거대 본문)이 500 이 아니라 400 이고, 프록시 본문 상한이 API 상한과 맞는다
지금 상태: ✕ id 파싱 검증 없음 (app/api/checkout/confirm/route.ts:4 orderId 를 req.json()에서 받아 .eq('id', orderId) 로 바로 사용 · UUID 형식 검증 없음) · ✕ NUL/제어문자 가드 없음 (전체 코드에 입력 정제 로직 없음) · — 프록시 없음 (middleware.ts·nginx·Caddy 설정 전무 · 00-map.md:26 "프록시/엣지: 없음")
관련 위치: app/api/checkout/confirm/route.ts:4
할 일: 입력 스키마에 UUID 검증 추가 + 문자열 정제

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5결제 · 환불 · 동시성0120
5.1PG 선정·계약이 끝났다문제차단
근거
✕ PG 선정 ○ · ✕ 계약 여부 ?<br>• app/api/checkout/confirm/route.ts:7 https://api.tosspayments.com/v1/payments/confirm — 토스페이먼츠로 선정됨<br>• .env.example:3-4 test_ck_ · test_sk_ — 테스트 키만 예시로 제공<br>• 계약·심사 상태 기록 문서 없음 (검색: `docs
풀리는 곳
계약
고칠 방향
심사
저장소 밖에서 할 일계약·콘솔·서류처럼 코드로 안 풀리는 일이에요. 위 "고칠 방향" 대로 직접 하거나, 출시 패키지로 같이 할 수 있어요.
5.2테스트/목 결제는 운영에서 막혀 있다문제차단
근거
✕ 운영 키 검증 · ✕ 테스트 모드 거부<br>• app/api/checkout/confirm/route.ts:10 process.env.NEXT_PUBLIC_TOSS_SECRET_KEY — 키 검증 없음, test_ 접두사 확인 없음<br>• app/classes/page.tsx:16 process.env.NEXT_PUBLIC_TOSS_CLIENT_KEY — 클라이언트 키도 검증 없음<br>• 부팅 시 키 검증 코드 없음 (검색: startsWith.*test_|NODE_ENV.*production → 0건)
풀리는 곳
코드
고칠 방향
부팅 시 운영 환경이면 test_ 키 거부·테스트 모드 표시 제거
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.2] 테스트/목 결제는 운영에서 막혀 있다
지금 상태: ✕ 운영 키 검증 · ✕ 테스트 모드 거부 • app/api/checkout/confirm/route.ts:10 process.env.NEXT_PUBLIC_TOSS_SECRET_KEY — 키 검증 없음, test_ 접두사 확인 없음 • app/classes/page.tsx:16 process.env.NEXT_PUBLIC_TOSS_CLIENT_KEY — 클라이언트 키도 검증 없음 • 부팅 시 키 검증 코드 없음 (검색: startsWith.test_¦NODE_ENV.production → 0건)
관련 위치: app/api/checkout/confirm/route.ts:10, app/classes/page.tsx:16
할 일: 부팅 시 운영 환경이면 test_ 키 거부·테스트 모드 표시 제거

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5.3승인 멱등성 · 금액 검증 · 상태 머신문제차단
근거
✕ 멱등 · ✕ 금액 검증 · ✕ 상태 머신<br>• app/api/checkout/confirm/route.ts:4 amount 파라미터를 PG 에 그대로 전달 — 서버 재계산 없음<br>• app/api/checkout/confirm/route.ts:17 .update({ status: 'PAID' }).eq('id', orderId) — WHERE status 조건 없음, 중복 호출 시 덮어씀<br>• supabase/migrations/001_init.sql — CHECK 제약 없음 (검색: CHECK|CONSTRAINT → 0건)
풀리는 곳
코드
고칠 방향
주문 조회·금액 재계산·비교 · UPDATE WHERE status='PENDING' · CHECK (status IN …)
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.3] 승인 멱등성 · 금액 검증 · 상태 머신
지금 상태: ✕ 멱등 · ✕ 금액 검증 · ✕ 상태 머신 • app/api/checkout/confirm/route.ts:4 amount 파라미터를 PG 에 그대로 전달 — 서버 재계산 없음 • app/api/checkout/confirm/route.ts:17 .update({ status: 'PAID' }).eq('id', orderId) — WHERE status 조건 없음, 중복 호출 시 덮어씀 • supabase/migrations/001_init.sql — CHECK 제약 없음 (검색: CHECK¦CONSTRAINT → 0건)
관련 위치: app/api/checkout/confirm/route.ts:17, app/api/checkout/confirm/route.ts:4, supabase/migrations/001_init.sql
할 일: 주문 조회·금액 재계산·비교 · UPDATE WHERE status='PENDING' · CHECK (status IN …)

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5.4웹훅 서명 검증 · 중복 방지 · 순서 역전문제차단
근거
✕ 서명 검증 · ✕ 중복 방지 · ✕ 순서 역전<br>• app/api/webhooks/toss/route.ts:4 await req.json() — 서명 검증 없음, PG 재조회 없음 (검색: signature|verify|fetch.*payments → 0건)<br>• app/api/webhooks/toss/route.ts:6 .update({ status: body.data.status }) — 이벤트 id 저장 없음, 중복 수신 시 덮어씀<br>• 순서 역전 분기 없음 (검색: eventType|event.*id|webhook.*log → 0건)
풀리는 곳
코드
고칠 방향
토스 서명 검증 또는 paymentKey 로 PG 재조회 · 이벤트 id 유니크 저장 · 상태 전이 조건
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.4] 웹훅 서명 검증 · 중복 방지 · 순서 역전
지금 상태: ✕ 서명 검증 · ✕ 중복 방지 · ✕ 순서 역전 • app/api/webhooks/toss/route.ts:4 await req.json() — 서명 검증 없음, PG 재조회 없음 (검색: signature¦verify¦fetch.payments → 0건) • app/api/webhooks/toss/route.ts:6 .update({ status: body.data.status }) — 이벤트 id 저장 없음, 중복 수신 시 덮어씀 • 순서 역전 분기 없음 (검색: eventType¦event.id¦webhook.log → 0건)
관련 위치: app/api/webhooks/toss/route.ts:4, app/api/webhooks/toss/route.ts:6
할 일: 토스 서명 검증 또는 paymentKey 로 PG 재조회 · 이벤트 id 유니크 저장 · 상태 전이 조건

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5.5고객이 돌아오지 않을 때 끝낼 주체문제차단
근거
✕ PG 조회 · ✕ 대사 작업 · ✕ 알림<br>• PG 조회 API 없음 (검색: GET.*payments|fetch.*payments.*key → confirm 만 있음, GET 없음)<br>• 잡·큐 없음 (검색: cron|schedule|queue|job|worker → 0건)<br>• 운영자 알림 없음 (검색: alert|notify|mail|send → ADMIN_EMAIL 변수만, 발송 코드 없음)
풀리는 곳
코드
고칠 방향
PENDING 30분 이상 주문 조회·PG 재조회·상태 동기화 cron · 슬랙·메일 알림
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.5] 고객이 돌아오지 않을 때 끝낼 주체
지금 상태: ✕ PG 조회 · ✕ 대사 작업 · ✕ 알림 • PG 조회 API 없음 (검색: GET.payments¦fetch.payments.key → confirm 만 있음, GET 없음) • 잡·큐 없음 (검색: cron¦schedule¦queue¦job¦worker → 0건) • 운영자 알림 없음 (검색: alert¦notify¦mail¦send → ADMIN_EMAIL 변수만, 발송 코드 없음)
할 일: PENDING 30분 이상 주문 조회·PG 재조회·상태 동기화 cron · 슬랙·메일 알림

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5.6결제 실패 경로와 실 PG e2e문제차단
근거
✕ 실패 분기 ○ · ✕ 중복 방지 · ✕ e2e<br>• app/api/checkout/confirm/route.ts:15 if (!res.ok) return Response.json({ ok: false }) — 실패 응답은 있음<br>• app/pay/success/page.tsx:12 j.ok ? '결제 완료!' : '결제 실패' — 실패 메시지 있음<br>• 중복 클릭 방지 없음 (검색: disabled|pending|loading → 0건) · 주문 유니크 제약 없음 (001_init.sql — payment_key 유니크 없음)<br>• e2e 없음 (검색: e2e|test|spec|cypress|playwright → 0건)
풀리는 곳
코드
고칠 방향
버튼 비활성·payment_key 유니크 · 토스 테스트 모드 e2e (성공·실패·취소)
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.6] 결제 실패 경로와 실 PG e2e
지금 상태: ✕ 실패 분기 ○ · ✕ 중복 방지 · ✕ e2e • app/api/checkout/confirm/route.ts:15 if (!res.ok) return Response.json({ ok: false }) — 실패 응답은 있음 • app/pay/success/page.tsx:12 j.ok ? '결제 완료!' : '결제 실패' — 실패 메시지 있음 • 중복 클릭 방지 없음 (검색: disabled¦pending¦loading → 0건) · 주문 유니크 제약 없음 (001_init.sql — payment_key 유니크 없음) • e2e 없음 (검색: e2e¦test¦spec¦cypress¦playwright → 0건)
관련 위치: app/api/checkout/confirm/route.ts:15, app/pay/success/page.tsx:12
할 일: 버튼 비활성·payment_key 유니크 · 토스 테스트 모드 e2e (성공·실패·취소)

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5.7취소·환불 규정 확정 및 코드·약관·고지 일치문제차단
근거
✕ 환불 규정 · ✕ 약관 · ✕ 결제 전 고지<br>• 환불 코드 없음 (검색: refund|cancel|환불|취소 → 0건)<br>• 약관 없음 (app/login/page.tsx:9 <a href="#">이용약관</a> — href="#", 실제 파일 없음)<br>• 결제 전 고지 없음 (app/classes/page.tsx — 결제 전 동의·고지 화면 없음, prompt() 후 바로 결제)<br>• 규정·약관·고지 셋 모두 부재
풀리는 곳
코드·결정
고칠 방향
환불 규정 확정 → 함수·약관·결제 전 고지 문안 작성 및 동의 체크 · 주문 행에 버전 기록
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.7] 취소·환불 규정 확정 및 코드·약관·고지 일치
지금 상태: ✕ 환불 규정 · ✕ 약관 · ✕ 결제 전 고지 • 환불 코드 없음 (검색: refund¦cancel¦환불¦취소 → 0건) • 약관 없음 (app/login/page.tsx:9 <a href="#">이용약관</a> — href="#", 실제 파일 없음) • 결제 전 고지 없음 (app/classes/page.tsx — 결제 전 동의·고지 화면 없음, prompt() 후 바로 결제) • 규정·약관·고지 셋 모두 부재
관련 위치: app/classes/page.tsx, app/login/page.tsx:9
할 일: 환불 규정 확정 → 함수·약관·결제 전 고지 문안 작성 및 동의 체크 · 주문 행에 버전 기록

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5.8환불 실행 — 부분·재시도·알림문제차단
근거
✕ 환불 코드 · ✕ 부분 환불 · ✕ 재시도<br>• 환불 코드 없음 (검색: refund|cancel|환불 → 0건)<br>• PG 취소 호출 없음 (검색: cancel|refund → 0건)<br>• 환불 상태·큐 없음 (001_init.sql — status 열에 REFUND 언급 없음)
풀리는 곳
코드
고칠 방향
토스 취소 API 호출 (트랜잭션 밖) · 부분 환불 지원 · 실패 시 재시도 큐·알림
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.8] 환불 실행 — 부분·재시도·알림
지금 상태: ✕ 환불 코드 · ✕ 부분 환불 · ✕ 재시도 • 환불 코드 없음 (검색: refund¦cancel¦환불 → 0건) • PG 취소 호출 없음 (검색: cancel¦refund → 0건) • 환불 상태·큐 없음 (001_init.sql — status 열에 REFUND 언급 없음)
할 일: 토스 취소 API 호출 (트랜잭션 밖) · 부분 환불 지원 · 실패 시 재시도 큐·알림

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5.9판매자 측 취소·배상 규정·행위자 권한문제차단
근거
✕ 판매자·운영자 취소 · ✕ 배상 규정<br>• 관리자 화면 읽기만 (app/admin/page.tsx:8 .select('*') — 취소·환불 쓰기 라우트 없음)<br>• 취소·환불 API 없음 (app/api — checkout/confirm · webhooks/toss 만, cancel 엔드포인트 없음)<br>• 배상 조항 없음 (약관 파일 자체가 없음)
풀리는 곳
코드·결정
고칠 방향
관리자 취소·환불 API · 일괄 환불 기능 · 약관에 배상 조항 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.9] 판매자 측 취소·배상 규정·행위자 권한
지금 상태: ✕ 판매자·운영자 취소 · ✕ 배상 규정 • 관리자 화면 읽기만 (app/admin/page.tsx:8 .select('') — 취소·환불 쓰기 라우트 없음) • 취소·환불 API 없음 (app/api — checkout/confirm · webhooks/toss 만, cancel 엔드포인트 없음) • 배상 조항 없음 (약관 파일 자체가 없음)
관련 위치: app/admin/page.tsx:8, app/api, checkout/confirm, webhooks/toss
할 일: 관리자 취소·환불 API · 일괄 환불 기능 · 약관에 배상 조항 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5.10영수증 링크 · 환불 소요 고지 · 내역 조회문제권장
근거
✕ 영수증 · ✕ 소요 고지 · ✕ 내역 조회<br>• 영수증 링크 없음 (검색: 영수증|receipt|매출전표 → 0건)<br>• 환불 소요 문구 없음 (검색: 소요|영업일|refund.*time → 0건)<br>• 주문 내역 화면 없음 (app/pay/success/page.tsx:12 "마이페이지" 언급 — 실제 페이지 없음, 검색: mypage|마이페이지 → 0건)
풀리는 곳
코드
고칠 방향
마이페이지 생성 · 주문 내역·영수증 링크 (토스 receiptUrl) · 환불 시 소요 시간 고지
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.10] 영수증 링크 · 환불 소요 고지 · 내역 조회
지금 상태: ✕ 영수증 · ✕ 소요 고지 · ✕ 내역 조회 • 영수증 링크 없음 (검색: 영수증¦receipt¦매출전표 → 0건) • 환불 소요 문구 없음 (검색: 소요¦영업일¦refund.time → 0건) • 주문 내역 화면 없음 (app/pay/success/page.tsx:12 "마이페이지" 언급 — 실제 페이지 없음, 검색: mypage¦마이페이지 → 0건)
관련 위치: app/pay/success/page.tsx:12
할 일: 마이페이지 생성 · 주문 내역·영수증 링크 (토스 receiptUrl) · 환불 시 소요 시간 고지

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5.11동시성 — DB 가 최종 방어선(부분 유니크 · EXCLUDE · CHECK), 판정은 잠금 아래 한 문장, 만료 선점이 자정(自淨)된다문제차단
근거
제약 ✕ · 잠금 ✕ · 만료 정리 — · 동시성 spec ✕ · 부하 ③<br><br>[5.11-a] supabase/migrations/001_init.sql:1-19 — UNIQUE/EXCLUDE/CHECK 제약 없음 (검색 → 0건)<br>[5.11-b] app/classes/page.tsx:13-15 — INSERT 에 조건부 WHERE · FOR UPDATE · ON CONFLICT 없음, 트랜잭션 없음 (단순 .insert())<br>[5.11-c] 검색 worker|cron|cleanup|expire|ttl → 0건 — 만료 정리 없음, 이 서비스엔 선점 개념 없음(장바구니·hold 없음) — 해당없음 —<br>[5.11-d] 검색 k6|locust|artillery|describe|it\( → 0건 — 동시성 spec 없음
풀리는 곳
코드
고칠 방향
재고(seats) 감소 시 DB 제약(CHECK seats >= 0) 추가 · 주문 INSERT 를 seats > 0 WHERE 조건부 UPDATE 로 변경 · 동시성 테스트 작성
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.11] 동시성 — DB 가 최종 방어선(부분 유니크 · EXCLUDE · CHECK), 판정은 잠금 아래 한 문장, 만료 선점이 자정(自淨)된다
지금 상태: 제약 ✕ · 잠금 ✕ · 만료 정리 — · 동시성 spec ✕ · 부하 ③ [5.11-a] supabase/migrations/001_init.sql:1-19 — UNIQUE/EXCLUDE/CHECK 제약 없음 (검색 → 0건) [5.11-b] app/classes/page.tsx:13-15 — INSERT 에 조건부 WHERE · FOR UPDATE · ON CONFLICT 없음, 트랜잭션 없음 (단순 .insert()) [5.11-c] 검색 worker¦cron¦cleanup¦expire¦ttl → 0건 — 만료 정리 없음, 이 서비스엔 선점 개념 없음(장바구니·hold 없음) — 해당없음 — [5.11-d] 검색 k6¦locust¦artillery¦describe¦it\( → 0건 — 동시성 spec 
관련 위치: UNIQUE/EXCLUDE/CHECK, app/classes/page.tsx:13-15, supabase/migrations/001_init.sql:1-19
할 일: 재고(seats) 감소 시 DB 제약(CHECK seats >= 0) 추가 · 주문 INSERT 를 seats > 0 WHERE 조건부 UPDATE 로 변경 · 동시성 테스트 작성

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
5.12쓰기 경로(선점·주문) 레이트 리밋 + 사용자당 동시 보유 상한 + 정원형은 등급별 정원문제권장
근거
레이트 리밋 ✕ · 사용자당 상한 ✕ · 등급별 정원 —<br><br>[5.12-a] 검색 rate.?limit|middleware → 0건 — 프록시/미들웨어 설정 없음<br>[5.12-b] supabase/migrations/001_init.sql:9-19 — orders 테이블에 사용자당 활성 선점 제약 없음<br>[5.12-c] 이 서비스엔 좌석 등급·티켓 종류가 없음 (classes.seats 는 총 정원 1개뿐) — 해당없음 —
풀리는 곳
코드
고칠 방향
API Routes 에 rate limit 미들웨어 추가 · 사용자당 활성 주문 수 제약 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[5.12] 쓰기 경로(선점·주문) 레이트 리밋 + 사용자당 동시 보유 상한 + 정원형은 등급별 정원
지금 상태: 레이트 리밋 ✕ · 사용자당 상한 ✕ · 등급별 정원 — [5.12-a] 검색 rate.?limit¦middleware → 0건 — 프록시/미들웨어 설정 없음 [5.12-b] supabase/migrations/001_init.sql:9-19 — orders 테이블에 사용자당 활성 선점 제약 없음 [5.12-c] 이 서비스엔 좌석 등급·티켓 종류가 없음 (classes.seats 는 총 정원 1개뿐) — 해당없음 —
관련 위치: supabase/migrations/001_init.sql:9-19
할 일: API Routes 에 rate limit 미들웨어 추가 · 사용자당 활성 주문 수 제약 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
6환경 분리 · 배포070
6.1프로덕션 환경이 실제로 있다문제차단
근거
✕ 배포 대상 선언 없음 (검색: Dockerfile|vercel.json|fly.toml|render.yaml|Procfile → 0건) · ✕ TLS/HSTS/리다이렉트 설정 없음 (middleware.ts 없음) · ✕ 스테이징 결정 기록 없음 (docs 디렉터리 없음)
풀리는 곳
결정/코드
고칠 방향
배포 플랫폼 선택 및 설정 파일 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[6.1] 프로덕션 환경이 실제로 있다
지금 상태: ✕ 배포 대상 선언 없음 (검색: Dockerfile¦vercel.json¦fly.toml¦render.yaml¦Procfile → 0건) · ✕ TLS/HSTS/리다이렉트 설정 없음 (middleware.ts 없음) · ✕ 스테이징 결정 기록 없음 (docs 디렉터리 없음)
관련 위치: TLS/HSTS
할 일: 배포 플랫폼 선택 및 설정 파일 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
6.2배포 재현성문제차단
근거
✕ Dockerfile/빌드 스크립트 없음 (검색: Dockerfile → 0건) · ✕ .dockerignore 없음 (ls → 없음) · ○ package.json:4 scripts.build: "next build" 존재
풀리는 곳
코드
고칠 방향
Dockerfile 또는 플랫폼 빌드 설정 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[6.2] 배포 재현성
지금 상태: ✕ Dockerfile/빌드 스크립트 없음 (검색: Dockerfile → 0건) · ✕ .dockerignore 없음 (ls → 없음) · ○ package.json:4 scripts.build: "next build" 존재
할 일: Dockerfile 또는 플랫폼 빌드 설정 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
6.3배포 절차 — 마이그레이션 · 시드 · 헬스 · 롤백문제차단
근거
✕ 워크플로/스크립트 없음 (.github/workflows 디렉터리 없음) · ✕ 시드 동기화 없음 (검색: seed → 0건) · ✕ 헬스체크 없음 (검색: health|liveness|readiness → 0건) · ✕ 롤백 절차 없음 (README.md:11-17 개발 실행만)
풀리는 곳
코드
고칠 방향
배포 워크플로 및 절차 문서 작성
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[6.3] 배포 절차 — 마이그레이션 · 시드 · 헬스 · 롤백
지금 상태: ✕ 워크플로/스크립트 없음 (.github/workflows 디렉터리 없음) · ✕ 시드 동기화 없음 (검색: seed → 0건) · ✕ 헬스체크 없음 (검색: health¦liveness¦readiness → 0건) · ✕ 롤백 절차 없음 (README.md:11-17 개발 실행만)
관련 위치: .github/workflows
할 일: 배포 워크플로 및 절차 문서 작성

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
6.4환경변수 — 코드 ↔ 예시 ↔ 배포 설정문제차단
근거
○ 코드가 읽는 5개 키 전부 .env.example 에 있음 (lib/supabase.ts:4-5 · app/api/checkout/confirm/route.ts:10 · app/classes/page.tsx:16 · .env.example:1-5) · ✕ 배포 설정 없음 (compose/플랫폼 변수 파일 없음) · ✕ 대조 spec 없음 (검색: *.test.*|*.spec.* → 0건)
풀리는 곳
코드
고칠 방향
배포 설정 추가 및 환경변수 대조 테스트 작성
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[6.4] 환경변수 — 코드 ↔ 예시 ↔ 배포 설정
지금 상태: ○ 코드가 읽는 5개 키 전부 .env.example 에 있음 (lib/supabase.ts:4-5 · app/api/checkout/confirm/route.ts:10 · app/classes/page.tsx:16 · .env.example:1-5) · ✕ 배포 설정 없음 (compose/플랫폼 변수 파일 없음) · ✕ 대조 spec 없음 (검색: .test.¦.spec. → 0건)
관련 위치: app/api/checkout/confirm/route.ts:10, app/classes/page.tsx:16, lib/supabase.ts:4-5
할 일: 배포 설정 추가 및 환경변수 대조 테스트 작성

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
6.5정책값이 결정값이다문제차단
근거
✕ .env.example:3-4 토스 키가 test_ck_xxxxxxxx · test_sk_xxxxxxxx (테스트 접두사) · ✕ .env.example:5 owner@example.com (예시값) · ✕ 결정 기록 없음 (검색: ADR|설계|결정 → 0건) · ✕ 세션 TTL · 보유 기간 · 수수료 설정 없음 (검색 → 0건)
풀리는 곳
결정/코드
고칠 방향
프로덕션 값 결정 및 .env.example 갱신
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[6.5] 정책값이 결정값이다
지금 상태: ✕ .env.example:3-4 토스 키가 test_ck_xxxxxxxx · test_sk_xxxxxxxx (테스트 접두사) · ✕ .env.example:5 owner@example.com (예시값) · ✕ 결정 기록 없음 (검색: ADR¦설계¦결정 → 0건) · ✕ 세션 TTL · 보유 기간 · 수수료 설정 없음 (검색 → 0건)
할 일: 프로덕션 값 결정 및 .env.example 갱신

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
6.6국내 리전 · DB 암호화 · 큐/캐시 인증문제권장
근거
✕ 리전 설정 없음 (Supabase 클라이언트는 URL 기반 — lib/supabase.ts:4 NEXT_PUBLIC_SUPABASE_URL 만) · ✕ DB ssl 옵션 명시 없음 (Supabase SDK 기본값 확인 불가) · — 큐/캐시 없음 (검색: redis|queue → 0건)
풀리는 곳
외부/코드
고칠 방향
Supabase 프로젝트 리전 확인 및 SSL 명시
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[6.6] 국내 리전 · DB 암호화 · 큐/캐시 인증
지금 상태: ✕ 리전 설정 없음 (Supabase 클라이언트는 URL 기반 — lib/supabase.ts:4 NEXT_PUBLIC_SUPABASE_URL 만) · ✕ DB ssl 옵션 명시 없음 (Supabase SDK 기본값 확인 불가) · — 큐/캐시 없음 (검색: redis¦queue → 0건)
관련 위치: lib/supabase.ts:4
할 일: Supabase 프로젝트 리전 확인 및 SSL 명시

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
6.7개발 시드 · 목 결제 · 디버그 도구 프로덕션 거부문제차단
근거
✕ 시드 스크립트 없음 (검색: seed → 0건 — 환경 가드도 없음) · ✕ 목 게이트웨이 부팅 거부 없음 (.env.example:3-4 test_ 키가 기본값 — 환경 검사 없음) · — API 문서 UI 없음 (검색: swagger|graphql → 0건) · ✕ 관리자 경로 무인증 (app/admin/page.tsx:5 주석 "메뉴에는 안 보이게 해 둠" — URL 직접 접근 가능)
풀리는 곳
코드
고칠 방향
환경 가드 추가 (test_ 키 거부, 관리자 인증)
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[6.7] 개발 시드 · 목 결제 · 디버그 도구 프로덕션 거부
지금 상태: ✕ 시드 스크립트 없음 (검색: seed → 0건 — 환경 가드도 없음) · ✕ 목 게이트웨이 부팅 거부 없음 (.env.example:3-4 test_ 키가 기본값 — 환경 검사 없음) · — API 문서 UI 없음 (검색: swagger¦graphql → 0건) · ✕ 관리자 경로 무인증 (app/admin/page.tsx:5 주석 "메뉴에는 안 보이게 해 둠" — URL 직접 접근 가능)
관련 위치: app/admin/page.tsx:5
할 일: 환경 가드 추가 (test_ 키 거부, 관리자 인증)

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
7에러 처리031
7.15xx 응답에 스택 없음 + 전역 필터 + 요청 id문제차단
근거
✕ 전역 예외 필터 없음 (Next.js App Router error.tsx 없음 — 검색: error.tsx → 0건) · ✕ 요청 id 미들웨어 없음 (검색: requestId|request_id|correlation → 0건) · ✕ 에러 응답 구성 없음 (app/api/checkout/confirm/route.ts:15 !res.ok 시 {ok: false} 만 — 메시지 없음)
풀리는 곳
코드
고칠 방향
전역 error.tsx · 요청 id 미들웨어 · 5xx 필터 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[7.1] 5xx 응답에 스택 없음 + 전역 필터 + 요청 id
지금 상태: ✕ 전역 예외 필터 없음 (Next.js App Router error.tsx 없음 — 검색: error.tsx → 0건) · ✕ 요청 id 미들웨어 없음 (검색: requestId¦request_id¦correlation → 0건) · ✕ 에러 응답 구성 없음 (app/api/checkout/confirm/route.ts:15 !res.ok 시 {ok: false} 만 — 메시지 없음)
관련 위치: app/api/checkout/confirm/route.ts:15
할 일: 전역 error.tsx · 요청 id 미들웨어 · 5xx 필터 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
7.2화면 — 루트 error/not-found/loading, 빈 상태, 실패 안내문제권장
근거
✕ 루트 error.tsx · not-found.tsx · loading.tsx 없음 (검색 → 0건) · ○ 빈 상태 있음 (app/classes/page.tsx:31 classes.map — 빈 배열이면 안 보임) · ✕ 실패 안내 부족 (app/pay/success/page.tsx:12 "결제 실패" 만 — 다음 행동 없음)
풀리는 곳
코드
고칠 방향
루트 error.tsx · 결제 실패 안내 개선
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[7.2] 화면 — 루트 error/not-found/loading, 빈 상태, 실패 안내
지금 상태: ✕ 루트 error.tsx · not-found.tsx · loading.tsx 없음 (검색 → 0건) · ○ 빈 상태 있음 (app/classes/page.tsx:31 classes.map — 빈 배열이면 안 보임) · ✕ 실패 안내 부족 (app/pay/success/page.tsx:12 "결제 실패" 만 — 다음 행동 없음)
관련 위치: app/classes/page.tsx:31, app/pay/success/page.tsx:12
할 일: 루트 error.tsx · 결제 실패 안내 개선

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
7.3외부 호출 타임아웃 · 재시도문제차단
근거
✕ 토스 confirm API 타임아웃 없음 (app/api/checkout/confirm/route.ts:7 fetch — timeout/AbortSignal 없음) · ✕ 재시도 정책 없음 (검색: retry|attempts → 0건) · ✕ 멱등 키 없음 (route.ts:7-14 paymentKey · orderId 는 토스가 생성 — 재시도 시 중복 가능)
풀리는 곳
코드
고칠 방향
fetch 타임아웃 추가 (PG 필수)
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[7.3] 외부 호출 타임아웃 · 재시도
지금 상태: ✕ 토스 confirm API 타임아웃 없음 (app/api/checkout/confirm/route.ts:7 fetch — timeout/AbortSignal 없음) · ✕ 재시도 정책 없음 (검색: retry¦attempts → 0건) · ✕ 멱등 키 없음 (route.ts:7-14 paymentKey · orderId 는 토스가 생성 — 재시도 시 중복 가능)
관련 위치: app/api/checkout/confirm/route.ts:7, timeout/AbortSignal
할 일: fetch 타임아웃 추가 (PG 필수)

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
7.4백그라운드 잡 실패 → 재시도 · DLQ · 알림해당없음권장
근거
— 백그라운드 잡 없음 (검색: queue|job|worker|cron|schedule → 0건)
풀리는 곳
—
고칠 방향
—
8테스트 · CI040
8.1머지된 코드 자동 검증 · CI 분 예산문제차단
근거
✕ 워크플로 없음 (.github/workflows 디렉터리 없음) · ✕ 자동 검증 없음 (검색: *.test.*|*.spec.* → 0건)
풀리는 곳
코드
고칠 방향
GitHub Actions 워크플로 추가 (빌드 · 테스트)
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[8.1] 머지된 코드 자동 검증 · CI 분 예산
지금 상태: ✕ 워크플로 없음 (.github/workflows 디렉터리 없음) · ✕ 자동 검증 없음 (검색: .test.¦.spec. → 0건)
관련 위치: .github/workflows
할 일: GitHub Actions 워크플로 추가 (빌드 · 테스트)

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
8.2결제 · 환불 · 동시성 통합 테스트 + e2e문제차단
근거
✕ spec 파일 없음 (검색: *.test.*|*.spec.* → 0건) · ✕ 결제 테스트 없음 (app/api/checkout/confirm/route.ts:7 토스 confirm — 테스트 없음) · — 환불 없음 (검색: refund|환불 → 0건) · ✕ 동시성 테스트 없음 (supabase/migrations/001_init.sql:6 seats — 감소 로직 없음)
풀리는 곳
코드
고칠 방향
결제 · 재고 통합 테스트 작성
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[8.2] 결제 · 환불 · 동시성 통합 테스트 + e2e
지금 상태: ✕ spec 파일 없음 (검색: .test.¦.spec. → 0건) · ✕ 결제 테스트 없음 (app/api/checkout/confirm/route.ts:7 토스 confirm — 테스트 없음) · — 환불 없음 (검색: refund¦환불 → 0건) · ✕ 동시성 테스트 없음 (supabase/migrations/001_init.sql:6 seats — 감소 로직 없음)
관련 위치: app/api/checkout/confirm/route.ts:7, supabase/migrations/001_init.sql:6
할 일: 결제 · 재고 통합 테스트 작성

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
8.3의존성 취약점 — 주기 감사 + 보안 알림문제권장
근거
✕ audit 단계 없음 (워크플로 없음) · ✕ Dependabot/Renovate 설정 없음 (검색: .github/dependabot.yml|renovate.json → 0건) · ✕ lockfile 없음 (ls → package-lock.json · yarn.lock · pnpm-lock.yaml 전부 없음)
풀리는 곳
코드
고칠 방향
Dependabot 설정 · npm ci 위한 lockfile 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[8.3] 의존성 취약점 — 주기 감사 + 보안 알림
지금 상태: ✕ audit 단계 없음 (워크플로 없음) · ✕ Dependabot/Renovate 설정 없음 (검색: .github/dependabot.yml¦renovate.json → 0건) · ✕ lockfile 없음 (ls → package-lock.json · yarn.lock · pnpm-lock.yaml 전부 없음)
관련 위치: .github/dependabot.yml, Dependabot/Renovate
할 일: Dependabot 설정 · npm ci 위한 lockfile 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
8.4새 spec 자동 실행 + 커버리지문제후순위
근거
✕ 테스트 러너 설정 없음 (검색: jest.config|vitest.config → 0건) · ✕ spec 없음 (검색: *.test.*|*.spec.* → 0건) · ✕ 커버리지 설정 없음 (package.json:4 scripts 에 test 명령 없음)
풀리는 곳
코드
고칠 방향
테스트 러너 설정 · 커버리지 설정 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[8.4] 새 spec 자동 실행 + 커버리지
지금 상태: ✕ 테스트 러너 설정 없음 (검색: jest.config¦vitest.config → 0건) · ✕ spec 없음 (검색: .test.¦.spec. → 0건) · ✕ 커버리지 설정 없음 (package.json:4 scripts 에 test 명령 없음)
할 일: 테스트 러너 설정 · 커버리지 설정 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
9성능030
9.1피크 부하 1회 측정(p95 · 에러율 · BUSY 비율) + 느린 쿼리 로그문제권장
근거
측정 ✕ · 느린 쿼리 로그 ✕ · 임계값 근거 ✕ · 관리형 DB 파라미터 ③<br><br>[9.1-a] 검색 k6|locust|artillery|siege|loadtest → 0건 — 부하 측정 스크립트/기록 없음<br>[9.1-b] 검색 log_min_duration|slow.?query|maxQueryExecutionTime → 0건 — 느린 쿼리 로그 설정 없음<br>[9.1-c] 검색 pool.*size|timeout|semaphore → 0건 — 세마포어/타임아웃/풀 크기 설정 없음 (Supabase 클라이언트 기본값)
풀리는 곳
코드/외부
고칠 방향
부하 테스트 도구로 피크 측정 실행 · Supabase 대시보드에서 느린 쿼리 로그 활성화
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[9.1] 피크 부하 1회 측정(p95 · 에러율 · BUSY 비율) + 느린 쿼리 로그
지금 상태: 측정 ✕ · 느린 쿼리 로그 ✕ · 임계값 근거 ✕ · 관리형 DB 파라미터 ③ [9.1-a] 검색 k6¦locust¦artillery¦siege¦loadtest → 0건 — 부하 측정 스크립트/기록 없음 [9.1-b] 검색 log_min_duration¦slow.?query¦maxQueryExecutionTime → 0건 — 느린 쿼리 로그 설정 없음 [9.1-c] 검색 pool.size¦timeout¦semaphore → 0건 — 세마포어/타임아웃/풀 크기 설정 없음 (Supabase 클라이언트 기본값)
할 일: 부하 테스트 도구로 피크 측정 실행 · Supabase 대시보드에서 느린 쿼리 로그 활성화

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
9.2목록 질의 수가 행 수에 비례하지 않고(N+1 없음), FK·조회 조건에 인덱스문제권장
근거
N+1 ○ · FK 인덱스 ✕<br><br>[9.2-a] app/admin/page.tsx:8 — .select('*').order('created_at') 루프 안 쿼리 없음, lazy relation 없음 — N+1 없음 ○<br>[9.2-b] supabase/migrations/001_init.sql:11 — class_id int references classes(id) FK 있음, 검색 CREATE INDEX → 0건 — FK 열 인덱스 없음<br>[9.2-c] app/admin/page.tsx:8 ORDER BY created_at — created_at 인덱스 없음
풀리는 곳
코드
고칠 방향
orders(class_id) · orders(created_at) 인덱스 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[9.2] 목록 질의 수가 행 수에 비례하지 않고(N+1 없음), FK·조회 조건에 인덱스
지금 상태: N+1 ○ · FK 인덱스 ✕ [9.2-a] app/admin/page.tsx:8 — .select('').order('created_at') 루프 안 쿼리 없음, lazy relation 없음 — N+1 없음 ○ [9.2-b] supabase/migrations/001_init.sql:11 — class_id int references classes(id) FK 있음, 검색 CREATE INDEX → 0건 — FK 열 인덱스 없음 [9.2-c] app/admin/page.tsx:8 ORDER BY created_at — created_at 인덱스 없음
관련 위치: app/admin/page.tsx:8, supabase/migrations/001_init.sql:11
할 일: orders(class_id) · orders(created_at) 인덱스 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
9.3공개 조회 캐싱 · 일반 API 레이트 리밋 · 이미지 파생본/CDN · 큐 메모리 상한문제권장
근거
캐싱 ✕ · 레이트 리밋 ✕ · 이미지 — · 큐 —<br><br>[9.3-a] 검색 Cache-Control|revalidate|ISR → 0건 — 캐시 헤더 설정 없음<br>[9.3-b] 검색 rate.?limit|middleware → 0건 — catch-all rate limit 없음 (5.12 와 중복)<br>[9.3-c] 검색 next/image|cdn|cloudfront|signed.*url → 0건 — 이미지 업로드/표시 기능 없음 — 해당없음 —<br>[9.3-d] 검색 redis|queue|bull → 0건 — 큐 없음 — 해당없음 —
풀리는 곳
코드
고칠 방향
공개 GET (app/classes/page.tsx) 에 revalidate 설정 추가 · API rate limit 미들웨어 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[9.3] 공개 조회 캐싱 · 일반 API 레이트 리밋 · 이미지 파생본/CDN · 큐 메모리 상한
지금 상태: 캐싱 ✕ · 레이트 리밋 ✕ · 이미지 — · 큐 — [9.3-a] 검색 Cache-Control¦revalidate¦ISR → 0건 — 캐시 헤더 설정 없음 [9.3-b] 검색 rate.?limit¦middleware → 0건 — catch-all rate limit 없음 (5.12 와 중복) [9.3-c] 검색 next/image¦cdn¦cloudfront¦signed.url → 0건 — 이미지 업로드/표시 기능 없음 — 해당없음 — [9.3-d] 검색 redis¦queue¦bull → 0건 — 큐 없음 — 해당없음 —
관련 위치: next/image
할 일: 공개 GET (app/classes/page.tsx) 에 revalidate 설정 추가 · API rate limit 미들웨어 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
10구조021
10.1코어 모델 업종 명사 고착 없음 · 설계 노트 갱신해당없음권장
근거
— 설계 노트 없음 (검색: ADR|설계 → 0건) · ○ 테이블명 classes · orders (supabase/migrations/001_init.sql:1,9 — 원데이 클래스 업종에 고착, 확장 예정 없음 → README.md:1 "샘플용 가상 앱" 명시)
풀리는 곳
—
고칠 방향
—
10.2미사용 의존성 0 · any 0(결제·주문) · 중복 컴포넌트문제후순위
근거
○ 의존성 4개 전부 사용 (package.json:5-10 next · react · supabase · tosspayments 전부 import 있음) · ✕ 결제·주문 모듈 any 3건 (app/classes/page.tsx:7 any[] · :10 c: any · app/admin/page.tsx:7 any[]) · ○ @ts-ignore 없음 (검색 → 0건) · — 중복 컴포넌트 없음 (앱 1개)
풀리는 곳
코드
고칠 방향
결제·주문 타입 정의 (Order · Class 인터페이스)
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[10.2] 미사용 의존성 0 · any 0(결제·주문) · 중복 컴포넌트
지금 상태: ○ 의존성 4개 전부 사용 (package.json:5-10 next · react · supabase · tosspayments 전부 import 있음) · ✕ 결제·주문 모듈 any 3건 (app/classes/page.tsx:7 any[] · :10 c: any · app/admin/page.tsx:7 any[]) · ○ @ts-ignore 없음 (검색 → 0건) · — 중복 컴포넌트 없음 (앱 1개)
관련 위치: app/admin/page.tsx:7, app/classes/page.tsx:7
할 일: 결제·주문 타입 정의 (Order · Class 인터페이스)

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
10.3README · AI 규칙 파일이 코드와 맞는다문제후순위
근거
○ README.md:14-16 기동 순서 cp .env.example .env.local → npm install → npm run dev ↔ package.json:4 scripts.dev: "next dev" 일치 · ○ 상태 표 없음 (README 에 "상태 표" 없음) · ✕ "목업/준비 중" 서술 문제 (app/pay/success/page.tsx:12 "마이페이지에서 예약 코드를 확인하세요" — 실제 마이페이지 없음, 검색: app/my|app/profile → 0건) · ✕ AI 규칙 파일 없음 (검색: CLAUDE.md|AGENTS.md|.cursorrules → 0건)
풀리는 곳
코드/결정
고칠 방향
마이페이지 구현 또는 안내 수정 · AI 규칙 파일 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[10.3] README · AI 규칙 파일이 코드와 맞는다
지금 상태: ○ README.md:14-16 기동 순서 cp .env.example .env.local → npm install → npm run dev ↔ package.json:4 scripts.dev: "next dev" 일치 · ○ 상태 표 없음 (README 에 "상태 표" 없음) · ✕ "목업/준비 중" 서술 문제 (app/pay/success/page.tsx:12 "마이페이지에서 예약 코드를 확인하세요" — 실제 마이페이지 없음, 검색: app/my¦app/profile → 0건) · ✕ AI 규칙 파일 없음 (검색: CLAUDE.md¦AGENTS.md¦.cursorrules → 0건)
관련 위치: app/my, app/pay/success/page.tsx:12, app/profile
할 일: 마이페이지 구현 또는 안내 수정 · AI 규칙 파일 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
11운영 · 모니터링 · 인수인계070
11.1에러 추적(국외 이전 고지 포함) + 헬스체크가 DB·큐를 보고 공개 경로로 도달 + 알림 사슬이 1회 울렸다문제차단
근거
에러 추적 ✕ · 헬스체크 ✕ · 알림 ✕ · 실 발화 기록 ✕<br>에러 추적: 없음 (검색: sentry|@sentry|bugsnag|rollbar → 0건)<br>헬스체크: 없음 (검색: /health|/ping|/ready|healthcheck → 0건)<br>알림: 없음 (검색: slack|discord|webhook|notification|alert → 0건 — .env.example:5 ADMIN_EMAIL 변수명만 존재, 메일 발송 구현 없음)<br>실 발화 기록: 없음 (저장소 내 문서 없음)
풀리는 곳
코드
고칠 방향
Sentry 류 SDK 추가 · /health 경로 생성 (Supabase 연결 확인) · 알림 연결 설정 · 테스트 발화 후 기록 문서화
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[11.1] 에러 추적(국외 이전 고지 포함) + 헬스체크가 DB·큐를 보고 공개 경로로 도달 + 알림 사슬이 1회 울렸다
지금 상태: 에러 추적 ✕ · 헬스체크 ✕ · 알림 ✕ · 실 발화 기록 ✕ 에러 추적: 없음 (검색: sentry¦@sentry¦bugsnag¦rollbar → 0건) 헬스체크: 없음 (검색: /health¦/ping¦/ready¦healthcheck → 0건) 알림: 없음 (검색: slack¦discord¦webhook¦notification¦alert → 0건 — .env.example:5 ADMIN_EMAIL 변수명만 존재, 메일 발송 구현 없음) 실 발화 기록: 없음 (저장소 내 문서 없음)
할 일: Sentry 류 SDK 추가 · /health 경로 생성 (Supabase 연결 확인) · 알림 연결 설정 · 테스트 발화 후 기록 문서화

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
11.2백업 보존일 + 복구 리허설 + 롤백 리허설(소요 시간 기록)문제차단
근거
백업 설정 ✕ · 복구 리허설 ✕ · 롤백 리허설 ✕<br>백업 설정: 없음 (검색: backup|snapshot|restore|dump → 0건 · Supabase 플랫폼 자동 백업은 콘솔 설정이나 저장소에 보존일 언급 없음)<br>리허설 기록: 없음 (검색: runbook|procedure|operation|rehearsal → 0건)<br>롤백 명령: 없음 (supabase/migrations 에 up 만, down 없음)
풀리는 곳
문서
고칠 방향
Supabase 콘솔 백업 설정 확인 후 보존일 문서화 · DB 복구 리허설 수행 및 기록 · 마이그레이션 롤백 스크립트 작성 · 애플리케이션 이전 버전 배포 절차 문서화
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[11.2] 백업 보존일 + 복구 리허설 + 롤백 리허설(소요 시간 기록)
지금 상태: 백업 설정 ✕ · 복구 리허설 ✕ · 롤백 리허설 ✕ 백업 설정: 없음 (검색: backup¦snapshot¦restore¦dump → 0건 · Supabase 플랫폼 자동 백업은 콘솔 설정이나 저장소에 보존일 언급 없음) 리허설 기록: 없음 (검색: runbook¦procedure¦operation¦rehearsal → 0건) 롤백 명령: 없음 (supabase/migrations 에 up 만, down 없음)
관련 위치: supabase/migrations
할 일: Supabase 콘솔 백업 설정 확인 후 보존일 문서화 · DB 복구 리허설 수행 및 기록 · 마이그레이션 롤백 스크립트 작성 · 애플리케이션 이전 버전 배포 절차 문서화

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
11.3비용 상한 — 예산 알람(50/80/100%) · 스토리지 자동 확장 상한 · 공개 버킷 트래픽 앞단문제차단
근거
예산 알람 ✕ · 스토리지 상한 ✕ · CDN —<br>예산 알람: 없음 (검색: budget|cost|billing|alarm → 0건)<br>스토리지 상한: 없음 (Supabase DB · 스토리지 사용 없음 — 00-map.md:16 확인, 설정 문서 없음)<br>CDN: 해당 없음 (객체 스토리지 미사용)
풀리는 곳
외부/문서
고칠 방향
Supabase 프로젝트 예산 알람 설정 (콘솔) · DB 용량 상한 정책 수립 · 설정값 문서화
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[11.3] 비용 상한 — 예산 알람(50/80/100%) · 스토리지 자동 확장 상한 · 공개 버킷 트래픽 앞단
지금 상태: 예산 알람 ✕ · 스토리지 상한 ✕ · CDN — 예산 알람: 없음 (검색: budget¦cost¦billing¦alarm → 0건) 스토리지 상한: 없음 (Supabase DB · 스토리지 사용 없음 — 00-map.md:16 확인, 설정 문서 없음) CDN: 해당 없음 (객체 스토리지 미사용)
할 일: Supabase 프로젝트 예산 알람 설정 (콘솔) · DB 용량 상한 정책 수립 · 설정값 문서화

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
11.4로그 보존·검색 · 외부 가동 감시 · 장애 런북(결제 · 중복 판매 · DB 복구 · 시크릿 회전 · 관리자 잠금 해제)문제권장
근거
로그 보존 ✕ · 외부 감시 ✕ · 런북 ✕<br>로그: 없음 (검색: log.*retention|winston|pino|bunyan|logging → 0건 · app/api/checkout/confirm/route.ts:5 console.log 1건만)<br>외부 감시: 없음 (검색: uptimerobot|pingdom|monitor → 0건)<br>런북: 없음 (검색: runbook|procedure → 0건 · README.md 개발 실행만)
풀리는 곳
문서/외부
고칠 방향
로그 수집 설정 (Next.js 로깅 + 플랫폼 연동) · UptimeRobot 류 외부 감시 설정 · 결제/DB/시크릿/관리자 장애 런북 작성
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[11.4] 로그 보존·검색 · 외부 가동 감시 · 장애 런북(결제 · 중복 판매 · DB 복구 · 시크릿 회전 · 관리자 잠금 해제)
지금 상태: 로그 보존 ✕ · 외부 감시 ✕ · 런북 ✕ 로그: 없음 (검색: log.retention¦winston¦pino¦bunyan¦logging → 0건 · app/api/checkout/confirm/route.ts:5 console.log 1건만) 외부 감시: 없음 (검색: uptimerobot¦pingdom¦monitor → 0건) 런북: 없음 (검색: runbook¦procedure → 0건 · README.md 개발 실행만)
관련 위치: app/api/checkout/confirm/route.ts:5
할 일: 로그 수집 설정 (Next.js 로깅 + 플랫폼 연동) · UptimeRobot 류 외부 감시 설정 · 결제/DB/시크릿/관리자 장애 런북 작성

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
11.5운영 환경에서 관리 명령(첫 관리자 생성 · 잠금 해제 · 카탈로그 동기화)을 실행할 경로가 있다문제차단
근거
CLI 실행 경로 ✕ · 비밀번호 노출 위험 ③<br>CLI 실행 경로: 없음 (Dockerfile · docker-compose 없음 · 플랫폼 명시 없음 · package.json:4 scripts.dev/build/start 만)<br>관리 명령: 없음 (첫 관리자 생성 스크립트 · 잠금 해제 · 카탈로그 동기화 코드 전무)<br>절차 문서: 없음 (검색: procedure|admin|operation → 0건)
풀리는 곳
코드/문서
고칠 방향
배포 플랫폼 결정 후 CLI 실행 경로 문서화 (Vercel 등 매니지드면 로컬 스크립트 + Supabase SQL) · 관리자 초기화 스크립트 작성 · classes 카탈로그 시드 스크립트 작성 · 절차 문서 작성
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[11.5] 운영 환경에서 관리 명령(첫 관리자 생성 · 잠금 해제 · 카탈로그 동기화)을 실행할 경로가 있다
지금 상태: CLI 실행 경로 ✕ · 비밀번호 노출 위험 ③ CLI 실행 경로: 없음 (Dockerfile · docker-compose 없음 · 플랫폼 명시 없음 · package.json:4 scripts.dev/build/start 만) 관리 명령: 없음 (첫 관리자 생성 스크립트 · 잠금 해제 · 카탈로그 동기화 코드 전무) 절차 문서: 없음 (검색: procedure¦admin¦operation → 0건)
관련 위치: scripts.dev/build/start
할 일: 배포 플랫폼 결정 후 CLI 실행 경로 문서화 (Vercel 등 매니지드면 로컬 스크립트 + Supabase SQL) · 관리자 초기화 스크립트 작성 · classes 카탈로그 시드 스크립트 작성 · 절차 문서 작성

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
11.6인수인계 — 실행·배포 문서, 외부 계정 대장(소유자 · 2FA · 복구 메일 · 결제수단 · 접근자), 시크릿 대장(위치 · 회전일)문제차단
근거
실행 문서 ○ · 배포 문서 ✕ · 계정 대장 ✕ · 시크릿 대장 ✕<br>실행 문서: README.md:11-17 (cp .env.example .env.local · npm install · npm run dev)<br>배포 문서: 없음 (검색: deploy|runbook|operation → 0건 · README 개발 환경만)<br>계정 대장: 없음 (검색: account|credential|owner|2FA → 0건)<br>시크릿 대장: 없음 (검색: secret|rotation|rotate → 0건 · .env.example:1-5 키 목록만)
풀리는 곳
문서
고칠 방향
배포 플랫폼·절차 문서 작성 · Supabase·토스페이먼츠·배포 플랫폼 계정 대장 작성 (소유자 · 2FA · 복구 메일 · 결제수단 · 접근자) · 시크릿 대장 작성 (위치: Supabase 프로젝트 설정 · 토스 개발자센터 · 플랫폼 환경변수 / 회전일 정책)
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[11.6] 인수인계 — 실행·배포 문서, 외부 계정 대장(소유자 · 2FA · 복구 메일 · 결제수단 · 접근자), 시크릿 대장(위치 · 회전일)
지금 상태: 실행 문서 ○ · 배포 문서 ✕ · 계정 대장 ✕ · 시크릿 대장 ✕ 실행 문서: README.md:11-17 (cp .env.example .env.local · npm install · npm run dev) 배포 문서: 없음 (검색: deploy¦runbook¦operation → 0건 · README 개발 환경만) 계정 대장: 없음 (검색: account¦credential¦owner¦2FA → 0건) 시크릿 대장: 없음 (검색: secret¦rotation¦rotate → 0건 · .env.example:1-5 키 목록만)
할 일: 배포 플랫폼·절차 문서 작성 · Supabase·토스페이먼츠·배포 플랫폼 계정 대장 작성 (소유자 · 2FA · 복구 메일 · 결제수단 · 접근자) · 시크릿 대장 작성 (위치: Supabase 프로젝트 설정 · 토스 개발자센터 · 플랫폼 환경변수 / 회전일 정책)

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
11.7비개발자용 운영 절차(입점 · 정지 · 환불 처리) + 데이터 복구 가능성(hard delete 에 복구 재료)문제권장
근거
운영 절차 ✕ · 복구 재료 ✕<br>운영 절차: 없음 (검색: procedure|operation → 0건 · "비개발자용 화면 절차" 문서 없음)<br>환불 처리: 없음 (검색: cancel|refund|환불|취소 → 0건 · app/admin/page.tsx 조회만 가능, 쓰기 없음)<br>삭제: 없음 (orders 테이블에 deleted_at 같은 soft delete 컬럼 없음 · supabase/migrations/001_init.sql:9-19)<br>복구 재료: 없음 (감사 테이블 없음 · 스냅샷 절차 없음)
풀리는 곳
코드/문서
고칠 방향
환불 처리 화면 (/admin 에 환불 버튼) 추가 · 클래스 등록/수정/삭제 화면 및 절차 문서 작성 · orders 테이블 soft delete (deleted_at) 추가 또는 감사 로그 테이블 생성 · 운영 절차 문서 작성
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[11.7] 비개발자용 운영 절차(입점 · 정지 · 환불 처리) + 데이터 복구 가능성(hard delete 에 복구 재료)
지금 상태: 운영 절차 ✕ · 복구 재료 ✕ 운영 절차: 없음 (검색: procedure¦operation → 0건 · "비개발자용 화면 절차" 문서 없음) 환불 처리: 없음 (검색: cancel¦refund¦환불¦취소 → 0건 · app/admin/page.tsx 조회만 가능, 쓰기 없음) 삭제: 없음 (orders 테이블에 deleted_at 같은 soft delete 컬럼 없음 · supabase/migrations/001_init.sql:9-19) 복구 재료: 없음 (감사 테이블 없음 · 스냅샷 절차 없음)
관련 위치: app/admin/page.tsx, supabase/migrations/001_init.sql:9-19
할 일: 환불 처리 화면 (/admin 에 환불 버튼) 추가 · 클래스 등록/수정/삭제 화면 및 절차 문서 작성 · orders 테이블 soft delete (deleted_at) 추가 또는 감사 로그 테이블 생성 · 운영 절차 문서 작성

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
12출시 품질150
12.1목업·시안·가짜 데이터 화면이 실 사용자에게 보이지 않는다 — 메뉴 시드 · 폴백 이미지 · "검수용" 버튼 포함통과차단
근거
목업 import ○ · 메뉴 시드 ○ · 외부 이미지 ○ · 테스트 문구 ○<br>목업: 없음 (검색: from .*mock|fixture|dummy|PreviewFab|검수용|미리보기|시안 → 0건)<br>메뉴: app/page.tsx:3 (고정 링크 2개 /classes · /login — 실제 페이지 존재)<br>외부 이미지: 없음 (검색: picsum|placeholder|lorempixel|unsplash\.it → 0건)<br>테스트 문구: 없음 (검색: 준비.*중|테스트|coming.*soon|work.*in.*progress → 0건)
풀리는 곳
—
고칠 방향
—
12.2판매자(운영 당사자)가 실제 운영에 필요한 쓰기 — 취소 · 환불 · 입장/수령 확인문제차단
근거
판매자 콘솔 쓰기 ✕ · 환불 ✕ · 입장 확인 ✕<br>판매자 콘솔: app/admin/page.tsx:8-18 (orders 조회만 · 쓰기 없음)<br>환불: 없음 (검색: cancel|refund|환불|취소 → 0건)<br>입장 확인: 없음 (수강생 출석 체크 로직 없음 · orders.status 가 PAID 로만 종결)
풀리는 곳
코드
고칠 방향
app/admin 에 환불 버튼 추가 (토스 결제 취소 API 호출) · 입장 확인 화면 추가 (QR 스캔 또는 주문 ID 검색 → orders.status 를 ATTENDED 등으로 업데이트)
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[12.2] 판매자(운영 당사자)가 실제 운영에 필요한 쓰기 — 취소 · 환불 · 입장/수령 확인
지금 상태: 판매자 콘솔 쓰기 ✕ · 환불 ✕ · 입장 확인 ✕ 판매자 콘솔: app/admin/page.tsx:8-18 (orders 조회만 · 쓰기 없음) 환불: 없음 (검색: cancel¦refund¦환불¦취소 → 0건) 입장 확인: 없음 (수강생 출석 체크 로직 없음 · orders.status 가 PAID 로만 종결)
관련 위치: app/admin/page.tsx:8-18
할 일: app/admin 에 환불 버튼 추가 (토스 결제 취소 API 호출) · 입장 확인 화면 추가 (QR 스캔 또는 주문 ID 검색 → orders.status 를 ATTENDED 등으로 업데이트)

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
12.3메일·문자 실발송 + 도달(SPF/DKIM/DMARC, 스팸함) + 거래 알림(주문 확인) 템플릿문제차단
근거
발송 어댑터 ✕ · DNS 인증 ✕ · 템플릿 ✕ · 실발송 ③<br>발송 어댑터: 없음 (검색: nodemailer|resend|smtp|sendgrid|ses|mailgun|postmark → 0건)<br>DNS 인증: 없음 (검색: SPF|DKIM|DMARC → 0건)<br>템플릿: 없음 (메일 템플릿 파일 없음 · .env.example:5 ADMIN_EMAIL 변수만)<br>주문 확인: app/pay/success/page.tsx:12 "마이페이지에서 예약 코드를 확인하세요" 문구만 (실제 발송 없음)
풀리는 곳
코드/외부/문서
고칠 방향
Resend 류 발송 어댑터 추가 · 주문 확인 메일 템플릿 작성 · 도메인 DNS SPF/DKIM/DMARC 설정 · app/api/checkout/confirm/route.ts:17 뒤에 메일 발송 로직 추가 · 실발송 테스트 후 기록
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[12.3] 메일·문자 실발송 + 도달(SPF/DKIM/DMARC, 스팸함) + 거래 알림(주문 확인) 템플릿
지금 상태: 발송 어댑터 ✕ · DNS 인증 ✕ · 템플릿 ✕ · 실발송 ③ 발송 어댑터: 없음 (검색: nodemailer¦resend¦smtp¦sendgrid¦ses¦mailgun¦postmark → 0건) DNS 인증: 없음 (검색: SPF¦DKIM¦DMARC → 0건) 템플릿: 없음 (메일 템플릿 파일 없음 · .env.example:5 ADMIN_EMAIL 변수만) 주문 확인: app/pay/success/page.tsx:12 "마이페이지에서 예약 코드를 확인하세요" 문구만 (실제 발송 없음)
관련 위치: app/pay/success/page.tsx:12
할 일: Resend 류 발송 어댑터 추가 · 주문 확인 메일 템플릿 작성 · 도메인 DNS SPF/DKIM/DMARC 설정 · app/api/checkout/confirm/route.ts:17 뒤에 메일 발송 로직 추가 · 실발송 테스트 후 기록

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
12.4핵심 흐름 5개 수동 통과표(날짜 · 수행자) + 모바일 실기기 2대(HTTPS 호스트 뒤)문제차단
근거
통과표 ✕ · 실기기 기록 ✕<br>통과표: 없음 (검색: test.*checklist|test.*pass|manual.*test → 0건)<br>실기기 기록: 없음 (저장소 내 문서 없음)
풀리는 곳
결정
고칠 방향
핵심 흐름 정의 (예: 로그인 · 클래스 목록 · 결제 · 결제 확인 · 관리자 조회) · 수동 테스트 통과표 작성 (날짜 · 수행자) · 모바일 2대 (iOS · Android) 실기기 테스트 후 기록 문서화
저장소 밖에서 할 일계약·콘솔·서류처럼 코드로 안 풀리는 일이에요. 위 "고칠 방향" 대로 직접 하거나, 출시 패키지로 같이 할 수 있어요.
12.5보안 헤더(HSTS · nosniff · Referrer-Policy · CSP) · SEO(sitemap · robots) · 비공개 호스트 noindex · 상세 페이지 OG문제권장
근거
보안 헤더 ✕ · sitemap ✕ · robots ✕ · 관리자 noindex ✕ · OG ○<br>보안 헤더: 없음 (검색: helmet|X-Frame-Options|Content-Security-Policy|X-Content-Type-Options|HSTS|Strict-Transport → 0건)<br>sitemap: 없음 (app/sitemap.ts 없음)<br>robots: 없음 (app/robots.ts 없음)<br>관리자 noindex: 없음 (app/admin/page.tsx 에 metadata 없음)<br>OG: app/layout.tsx:1 metadata (title 만 · og 태그 없음)
풀리는 곳
코드
고칠 방향
next.config 또는 middleware.ts 에 보안 헤더 추가 · app/sitemap.ts · app/robots.ts 생성 · app/admin/page.tsx 에 export const metadata = { robots: { index: false } } 추가 · 상세 페이지 OG 메타 추가 (예: app/classes/[id]/page.tsx 의 generateMetadata)
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[12.5] 보안 헤더(HSTS · nosniff · Referrer-Policy · CSP) · SEO(sitemap · robots) · 비공개 호스트 noindex · 
지금 상태: 보안 헤더 ✕ · sitemap ✕ · robots ✕ · 관리자 noindex ✕ · OG ○ 보안 헤더: 없음 (검색: helmet¦X-Frame-Options¦Content-Security-Policy¦X-Content-Type-Options¦HSTS¦Strict-Transport → 0건) sitemap: 없음 (app/sitemap.ts 없음) robots: 없음 (app/robots.ts 없음) 관리자 noindex: 없음 (app/admin/page.tsx 에 metadata 없음) OG: app/layout.tsx:1 metadata (title 만 · og 태그 없음)
관련 위치: app/admin/page.tsx, app/layout.tsx:1, app/robots.ts, app/sitemap.ts
할 일: next.config 또는 middleware.ts 에 보안 헤더 추가 · app/sitemap.ts · app/robots.ts 생성 · app/admin/page.tsx 에 export const metadata = { robots: { index: false } } 추가 · 상세 페이지 OG 메타 추가 (예: app/classes/[id]/page.tsx 의 generateMetadata)

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
12.6접근성 기본 — 대비 검사 통과 이력, 키보드 조작, 스크린리더 금액 낭독문제권장
근거
대비 검사 ✕ · 키보드 ✕ · aria ✕<br>대비 검사: 없음 (검색: contrast|color.*ratio|wcag|a11y|accessibility → 0건 · 스크립트·CI 없음)<br>키보드: 없음 (검색: aria-|role=|tab.*index|keyboard|onKey → 0건 · app/classes/page.tsx:35 button 은 기본 접근성 있으나 명시 핸들러 없음)<br>금액 aria: 없음 (app/classes/page.tsx:34 {c.price.toLocaleString()}원 — aria-label 없음)
풀리는 곳
코드
고칠 방향
axe-core 류 대비 검사 도구 추가 · 테스트 실행 후 이력 문서화 · 핵심 버튼에 키보드 핸들러 추가 (이미 작동하나 명시) · 금액 표시에 <span aria-label="가격 {c.price}원">{c.price.toLocaleString()}원</span> 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[12.6] 접근성 기본 — 대비 검사 통과 이력, 키보드 조작, 스크린리더 금액 낭독
지금 상태: 대비 검사 ✕ · 키보드 ✕ · aria ✕ 대비 검사: 없음 (검색: contrast¦color.ratio¦wcag¦a11y¦accessibility → 0건 · 스크립트·CI 없음) 키보드: 없음 (검색: aria-¦role=¦tab.index¦keyboard¦onKey → 0건 · app/classes/page.tsx:35 button 은 기본 접근성 있으나 명시 핸들러 없음) 금액 aria: 없음 (app/classes/page.tsx:34 {c.price.toLocaleString()}원 — aria-label 없음)
관련 위치: app/classes/page.tsx:34, app/classes/page.tsx:35
할 일: axe-core 류 대비 검사 도구 추가 · 테스트 실행 후 이력 문서화 · 핵심 버튼에 키보드 핸들러 추가 (이미 작동하나 명시) · 금액 표시에 <span aria-label="가격 {c.price}원">{c.price.toLocaleString()}원</span> 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
13국내 법규070
13.1사업자 정보·통신판매업 번호 footer + 개인정보 보호책임자 + 문의 동선문제차단
근거
사업자 정보 ✕ · 통판 번호 ✕ · 보호책임자 ✕ · 문의 동선 ✕<br>app/layout.tsx:3 <footer>© 공방 원데이</footer> — 저작권 표시만, 사업자 정보·통판 번호·보호책임자 없음<br>검색: 고객센터|상담|문의|contact|support → 0건
풀리는 곳
코드
고칠 방향
footer 에 사업자 정보·통판 번호·보호책임자·연락 수단(메일/전화) 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[13.1] 사업자 정보·통신판매업 번호 footer + 개인정보 보호책임자 + 문의 동선
지금 상태: 사업자 정보 ✕ · 통판 번호 ✕ · 보호책임자 ✕ · 문의 동선 ✕ app/layout.tsx:3 <footer>© 공방 원데이</footer> — 저작권 표시만, 사업자 정보·통판 번호·보호책임자 없음 검색: 고객센터¦상담¦문의¦contact¦support → 0건
관련 위치: app/layout.tsx:3
할 일: footer 에 사업자 정보·통판 번호·보호책임자·연락 수단(메일/전화) 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
13.2약관 — 구매·지급·청약철회·환급 조항, 거래 구조(중개자 고지), 자리 표시자 0, 효력일 순서문제차단
근거
약관 문안 ✕ · 자리 표시자 — · 효력일 ✕<br>app/login/page.tsx:9 <a href="#">이용약관</a> — href="#", 실제 문안 없음<br>검색: 약관|terms → 링크만, 문안 파일(md·json·CMS) 없음
풀리는 곳
코드/결정
고칠 방향
약관 문안 작성(구매·청약철회·환급·중개자 여부 명시), 효력일 기재, 문안 파일 추가 및 링크 수정
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[13.2] 약관 — 구매·지급·청약철회·환급 조항, 거래 구조(중개자 고지), 자리 표시자 0, 효력일 순서
지금 상태: 약관 문안 ✕ · 자리 표시자 — · 효력일 ✕ app/login/page.tsx:9 <a href="#">이용약관</a> — href="#", 실제 문안 없음 검색: 약관¦terms → 링크만, 문안 파일(md·json·CMS) 없음
관련 위치: app/login/page.tsx:9
할 일: 약관 문안 작성(구매·청약철회·환급·중개자 여부 명시), 효력일 기재, 문안 파일 추가 및 링크 수정

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
13.3처리방침 — 수집 항목·처리위탁·보존 기간·국외 이전·판매자 제공 항목이 코드 사실과 일치문제차단
근거
처리방침 문안 ✕ · 코드 대조 ✕<br>app/login/page.tsx:9 <a href="#">개인정보처리방침</a> — href="#", 실제 문안 없음<br>코드 사실: supabase/migrations/001_init.sql:13-14 buyer_name text, buyer_phone text (이름·전화 수집) · app/api/checkout/confirm/route.ts:7-14 토스페이먼츠 API 전송 → 문안 없어 대조 불가
풀리는 곳
코드/결정
고칠 방향
처리방침 문안 작성(수집: 이름·전화·결제정보 / 위탁: 토스·Supabase / 국외 이전: Supabase 위치 확인 / 보존: 거래 5년), 문안 파일 추가 및 링크 수정
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[13.3] 처리방침 — 수집 항목·처리위탁·보존 기간·국외 이전·판매자 제공 항목이 코드 사실과 일치
지금 상태: 처리방침 문안 ✕ · 코드 대조 ✕ app/login/page.tsx:9 <a href="#">개인정보처리방침</a> — href="#", 실제 문안 없음 코드 사실: supabase/migrations/001_init.sql:13-14 buyer_name text, buyer_phone text (이름·전화 수집) · app/api/checkout/confirm/route.ts:7-14 토스페이먼츠 API 전송 → 문안 없어 대조 불가
관련 위치: app/api/checkout/confirm/route.ts:7-14, app/login/page.tsx:9, supabase/migrations/001_init.sql:13-14
할 일: 처리방침 문안 작성(수집: 이름·전화·결제정보 / 위탁: 토스·Supabase / 국외 이전: Supabase 위치 확인 / 보존: 거래 5년), 문안 파일 추가 및 링크 수정

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
13.4동의 — 필수/선택 분리 · 만 14세 · 마케팅 분리·철회 · 결제 전 취소 규정 동의와 버전 기록문제차단
근거
필수/선택 분리 ✕ · 만 14세 ✕ · 마케팅 분리 — · 결제 전 동의 ✕ · 버전 기록 ✕<br>app/login/page.tsx:9 <p>가입하면 <a href="#">이용약관</a>과 <a href="#">개인정보처리방침</a>에 동의한 것으로 봅니다.</p> — 체크박스 없음, 묵시 동의<br>supabase/migrations/001_init.sql:9-19 orders 테이블 — 동의 버전 열 없음<br>app/classes/page.tsx:10-26 결제 흐름 — 취소 규정 동의 체크 없음
풀리는 곳
코드
고칠 방향
가입 화면에 체크박스(필수: 약관·방침·만 14세, 선택: 마케팅) 추가, 결제 전 취소 규정 동의 체크박스 추가, orders.consent_version 열 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[13.4] 동의 — 필수/선택 분리 · 만 14세 · 마케팅 분리·철회 · 결제 전 취소 규정 동의와 버전 기록
지금 상태: 필수/선택 분리 ✕ · 만 14세 ✕ · 마케팅 분리 — · 결제 전 동의 ✕ · 버전 기록 ✕ app/login/page.tsx:9 <p>가입하면 <a href="#">이용약관</a>과 <a href="#">개인정보처리방침</a>에 동의한 것으로 봅니다.</p> — 체크박스 없음, 묵시 동의 supabase/migrations/001_init.sql:9-19 orders 테이블 — 동의 버전 열 없음 app/classes/page.tsx:10-26 결제 흐름 — 취소 규정 동의 체크 없음
관련 위치: app/classes/page.tsx:10-26, app/login/page.tsx:9, supabase/migrations/001_init.sql:9-19
할 일: 가입 화면에 체크박스(필수: 약관·방침·만 14세, 선택: 마케팅) 추가, 결제 전 취소 규정 동의 체크박스 추가, orders.consent_version 열 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
13.5거래기록 5년 보존 vs 탈퇴·삭제 정책, 탈퇴 동선문제차단
근거
탈퇴 동선 ✕ · 보존 정책 ✕<br>검색: 탈퇴|withdraw|delete.*account → 0건, 탈퇴 기능 없음<br>supabase/migrations/001_init.sql:9-19 orders 테이블 — 보존·익명화 정책 명시 없음
풀리는 곳
코드/결정
고칠 방향
탈퇴 동선 추가(마이페이지·설정), 탈퇴 시 주문 행 보존 정책 결정(거래 5년 vs 개인정보 삭제), 익명화 로직 구현
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[13.5] 거래기록 5년 보존 vs 탈퇴·삭제 정책, 탈퇴 동선
지금 상태: 탈퇴 동선 ✕ · 보존 정책 ✕ 검색: 탈퇴¦withdraw¦delete.account → 0건, 탈퇴 기능 없음 supabase/migrations/001_init.sql:9-19 orders 테이블 — 보존·익명화 정책 명시 없음
관련 위치: supabase/migrations/001_init.sql:9-19
할 일: 탈퇴 동선 추가(마이페이지·설정), 탈퇴 시 주문 행 보존 정책 결정(거래 5년 vs 개인정보 삭제), 익명화 로직 구현

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
13.6판매자 불이행 보상(소비자분쟁해결기준)과 배상 주체, 연령 제한 상품의 확인 강제문제차단
근거
보상 조항 ✕ · 배상 집행 ✕ · 연령 확인 —<br>검색: 보상|배상|손해|불이행 → 0건, 약관 없음(13.2)<br>검색: age|연령|미성년 → 0건, 연령 제한 상품 해당 없음(원데이 클래스)
풀리는 곳
코드/결정
고칠 방향
약관에 불이행 보상 조항 추가(배상 주체: 판매자 직접 or 플랫폼 중개), 코드의 환불·보상 집행 경로 구현
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[13.6] 판매자 불이행 보상(소비자분쟁해결기준)과 배상 주체, 연령 제한 상품의 확인 강제
지금 상태: 보상 조항 ✕ · 배상 집행 ✕ · 연령 확인 — 검색: 보상¦배상¦손해¦불이행 → 0건, 약관 없음(13.2) 검색: age¦연령¦미성년 → 0건, 연령 제한 상품 해당 없음(원데이 클래스)
할 일: 약관에 불이행 보상 조항 추가(배상 주체: 판매자 직접 or 플랫폼 중개), 코드의 환불·보상 집행 경로 구현

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
13.7변호사 검토 — 질문 목록·발송일·회신이 한 곳에 기록된다문제차단
근거
검토 기록 ✕<br>검색: 검토|review|lawyer|변호사|법무 → 0건<br>docs 디렉터리 없음, .github/issues 없음(이슈 기록은 저장소 밖이라 확인 못 함)
풀리는 곳
결정/외부
고칠 방향
변호사 검토 질문 목록 작성(약관·처리방침·거래 구조·책임 범위), 발송 및 회신 문서 작성, 저장소에 기록(docs/legal-review.md 또는 이슈)
저장소 밖에서 할 일계약·콘솔·서류처럼 코드로 안 풀리는 일이에요. 위 "고칠 방향" 대로 직접 하거나, 출시 패키지로 같이 할 수 있어요.
14국내 연동032
14.1PG 심사 서류 + 실 도메인 서비스 URL문제차단
근거
심사용 URL ? · 도메인 명시 ✕<br>README.md:1-3 "⚠️ vamuri 샘플용 가상 앱 … 실제 서비스가 아니고" — 운영 도메인 없음 명시<br>.env.example:3-4 test_ck_xxxxxxxx · test_sk_xxxxxxxx — 테스트 키, 프로덕션 심사 전<br>서류(사업자등록증·통판·신분증·통장)는 외부 — 확인 불가(?)
풀리는 곳
외부
고칠 방향
운영 도메인 확보, 도메인에 약관·처리방침·사업자 정보 배포, PG 심사 서류 제출
저장소 밖에서 할 일계약·콘솔·서류처럼 코드로 안 풀리는 일이에요. 위 "고칠 방향" 대로 직접 하거나, 출시 패키지로 같이 할 수 있어요.
14.2메일 공급자 프로덕션 액세스 · 도메인 인증(DKIM) · 바운스 처리문제차단
근거
메일 어댑터 구현 ✕ · DKIM ✕ · 바운스 처리 ✕<br>검색: nodemailer|resend|sendgrid|ses|smtp|mailer → 0건, 메일 어댑터 없음<br>.env.example:5 ADMIN_EMAIL=owner@example.com — 수신 주소만, 발신 구현 없음
풀리는 곳
코드/외부
고칠 방향
메일 공급자(Resend·SendGrid·SES 등) 선택 및 어댑터 구현, 발신 도메인 DKIM 설정, 바운스 웹훅 처리 코드 추가
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[14.2] 메일 공급자 프로덕션 액세스 · 도메인 인증(DKIM) · 바운스 처리
지금 상태: 메일 어댑터 구현 ✕ · DKIM ✕ · 바운스 처리 ✕ 검색: nodemailer¦resend¦sendgrid¦ses¦smtp¦mailer → 0건, 메일 어댑터 없음 .env.example:5 ADMIN_EMAIL=owner@example.com — 수신 주소만, 발신 구현 없음
할 일: 메일 공급자(Resend·SendGrid·SES 등) 선택 및 어댑터 구현, 발신 도메인 DKIM 설정, 바운스 웹훅 처리 코드 추가

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
14.3문자·알림톡 공급자 — 인증용과 거래 알림용 분리, 발신번호 사전등록, 예산값해당없음차단
근거
문자·알림톡 사용 —<br>검색: sms|문자|alimtalk|알림톡|ncp|solapi → 0건<br>app/login/page.tsx:8 카카오 OAuth 로그인 — 문자 인증 미사용<br>app/pay/success/page.tsx:12 "마이페이지에서 예약 코드를 확인하세요" — 문자 알림 미사용(화면 안내만)
풀리는 곳
—
고칠 방향
문자 기능 자체가 없음, 인증·거래 알림 모두 미사용
14.4소셜 로그인 콘솔 등록 — redirect_uri 글자 일치, 처리방침 URL 공개가 심사 선행(카카오)문제권장
근거
redirect_uri 설정 ? · 처리방침 공개 URL ✕<br>app/login/page.tsx:8 supabase.auth.signInWithOAuth({ provider: 'kakao' }) — Supabase 가 redirect_uri 자동 구성, 코드에 명시 없음<br>app/login/page.tsx:9 <a href="#">개인정보처리방침</a> — href="#", 공개 URL 없음(13.3)<br>카카오 콘솔 등록 상태는 외부 — 확인 불가(?)
풀리는 곳
외부/코드
고칠 방향
처리방침 공개 URL 확보(문안 작성 → 배포), Supabase/카카오 콘솔에서 redirect_uri 등록 확인
코딩 도구에 붙여넣기Claude Code · Cursor · Codex 등에 그대로
출시 전 점검에서 이 항목이 걸렸어. 고쳐 줘.

[14.4] 소셜 로그인 콘솔 등록 — redirect_uri 글자 일치, 처리방침 URL 공개가 심사 선행(카카오)
지금 상태: redirect_uri 설정 ? · 처리방침 공개 URL ✕ app/login/page.tsx:8 supabase.auth.signInWithOAuth({ provider: 'kakao' }) — Supabase 가 redirect_uri 자동 구성, 코드에 명시 없음 app/login/page.tsx:9 <a href="#">개인정보처리방침</a> — href="#", 공개 URL 없음(13.3) 카카오 콘솔 등록 상태는 외부 — 확인 불가(?)
관련 위치: app/login/page.tsx:8, app/login/page.tsx:9
할 일: 처리방침 공개 URL 확보(문안 작성 → 배포), Supabase/카카오 콘솔에서 redirect_uri 등록 확인

지켜 줄 것:
- 먼저 관련 파일을 읽고 무엇을 바꿀지 짧게 계획부터 보여 줘.
- 이 항목과 관계없는 파일은 바꾸지 마. 비밀 값(키·토큰)은 코드에 넣지 말고 환경변수로.
- 끝나면 바꾼 파일 목록과 이유, 그리고 고쳐졌는지 내가 확인하는 방법을 한 줄로 알려 줘.
14.5지도·주소 등 외부 키의 운영 도메인 등록미확인권장
근거
외부 키 사용 —<br>검색: naver.*map|kakao.*map|google.*map|지도 → 0건<br>검색: API.*KEY|GOOGLE|NAVER|KAKAO (.env.example 제외) → 0건, 지도·주소 API 미사용
풀리는 곳
—
고칠 방향
지도·주소 API 를 사용하지 않음, 운영 도메인 등록 필요 없음
저장소 밖에서 할 일계약·콘솔·서류처럼 코드로 안 풀리는 일이에요. 위 "고칠 방향" 대로 직접 하거나, 출시 패키지로 같이 할 수 있어요.

실행해야 확정되는 것

읽기만으로는 못 본 조건 — 확인 방법
A · 결제·환불
  • 5.1 계약 여부 ? — 토스페이먼츠 계약 완료 여부 · 운영 키 발급 여부 확인 (외부 계약 상태)
  • 5.6 e2e ③ — 토스 테스트 모드로 실제 결제 흐름 실행 (성공·실패·취소·뒤로가기 시나리오)
B · 동시성·성능
  • 5.11 부하 ③ — k6/artillery 로 동시 100 사용자가 같은 class_id 에 주문 생성, 성공 수가 seats 를 초과하는지 확인
  • 9.1 관리형 DB 파라미터 ③ — Supabase 대시보드 → Settings → Database → log_min_duration_statement 설정 확인
  • 상세
C · 환경·배포·에러·CI·구조
  • 6.1 — 실제 운영 환경 존재: 배포 후 curl -I https://<도메인> 으로 TLS · HSTS 확인
  • 6.6 — Supabase DB SSL: Supabase 콘솔 → Settings → Database → SSL enforcement 확인
  • 8.1 — CI 분 예산: GitHub Settings → Actions → Usage this month 확인
D · 법규·연동
  • 14.1 PG 심사 서류: 사업자등록증·통신판매업 신고증·대표자 신분증·통장 사본 준비 여부는 외부 서류함 확인
  • 14.1 실 도메인 배포: 브라우저로 운영 도메인 접속 → 약관·처리방침·사업자 정보 표시 확인
  • 14.2 DKIM·바운스: 메일 공급자 콘솔에서 도메인 인증 상태 확인, 바운스 웹훅 엔드포인트 등록 확인
  • 14.4 소셜 로그인 콘솔: Supabase 대시보드 → Authentication → Providers → Kakao 설정 확인, 카카오 개발자 콘솔에서 redirect_uri·처리방침 URL 등록 확인
  • orders RLS: psql 또는 Supabase SQL Editor 에서 SELECT * FROM orders (익명 세션) 실행 → 조회되면 RLS 부재 확인
  • 재고 감소: 브라우저 두 개로 동시 구매 시도 → seats 초과 판매 여부 확인
  • 웹훅 검증: curl 로 /api/webhooks/toss 에 임의 JSON POST → status 변경되면 검증 부재 확인
E · 시크릿·접근 제어
  • 1.1 히스토리 검색 — git log --all -S'AKIA' --name-only --format='%h' · git log --all -G'PASSWORD=' --name-only --format='%h' (패턴: AKIA · sk_live · sk_test · -----BEGIN · PASSWORD= · SECRET= · DATABASE_URL=postgres://)
  • 1.2 빌드 산출물 grep — npm run build && grep -r "test_sk_" .next/ (NEXT_PUBLIC_TOSS_SECRET_KEY 가 번들에 포함되는지)
  • 1.5 전체 — 키 회전 절차 문서 작성 → 스테이징 리허설 실행 → 기록 저장소 커밋
F · 인증·입력 검증
  • 3.2: Supabase 콘솔 Authentication > Settings 에서 세션 쿠키 설정(Secure · HttpOnly · SameSite) 확인 · 브라우저 개발자 도구 Application > Cookies 에서 실제 쿠키 속성 확인
  • 3.4: Supabase 콘솔 Authentication > Providers 에서 Kakao OAuth 연결 상태(Client ID · Secret 입력 여부) 확인 · 로컬에서 로그인 버튼 클릭 → 카카오 인증 화면 뜨는지 확인
  • 3.6: /admin 경로를 비로그인 상태에서 접근해 주문 목록이 뜨는지 확인 (뜨면 인증 없음 확인됨)
  • 4.1: /api/checkout/confirm POST 에 {"paymentKey":"x","orderId":"y","amount":-1000,"extraField":"evil"} 전송 → extraField 거부 여부 · 음수 amount 거부 여부 확인
  • 4.2: /api/checkout/confirm POST 에 {"paymentKey":"x","orderId":"valid-uuid","amount":0} 전송 → 0원 결제 거부 여부 확인 · classes 테이블 price 와 대조 여부 확인
  • 4.5: /api/checkout/confirm POST 에 {"paymentKey":"x","orderId":"not-a-uuid","amount":1000} 전송 → 400 응답인지 500 응답인지 확인
G · 운영·출시 품질
  • 11.1 실 발화 기록: 알림 연결 후 테스트 에러 발생 → Slack/Discord 등 수신 확인 → 기록 문서화
  • 11.5 비밀번호 노출 위험: 관리자 생성 스크립트 작성 후 실행 시 echo · 로그에 비밀번호 평문 남는지 확인 (script.sh 2>&1 | grep password)
  • 12.3 실발송: 메일 어댑터 연결 후 주문 → 수신 확인 (스팸함 포함) · 발송 로그 확인

이 서비스에 안 맞은 항목

  • C · 환경·배포·에러·CI·구조 — 7.4 — 백그라운드 잡이 없는 저장소 (검색: queue|job|worker|cron|schedule → 0건) 10.1 — 설계 노트가 없고, README.md:3 에 "샘플용 가상 앱" 으로 명시된 저장소 (확장 예정 없음)

이 리포트가 만들어진 과정

질문지별 소요와 기록
실행10-27 03:13 → 03:40 · 24분
00-map · 저장소 지도3:19
A · 결제·환불2:38
B · 동시성·성능2:13
C · 환경·배포·에러·CI·구조3:40
D · 법규·연동2:49
E · 시크릿·접근 제어2:52
F · 인증·입력 검증2:55
G · 운영·출시 품질3:50
H · 앱스토어 심사
기록4건
10-27 03:41
리포트 공개
10-27 03:40
분석 끝 · 24분
10-27 03:13
신청 · 공개 저장소
10-27 03:13
분석 시작 · 기준 커밋 40d1750

다음

  1. 60분 회의 — 차단/권장을 같이 확정하고 모듈별로 고치기 vs 다시 만들기를 정합니다. 회의 잡기
  2. 외부 의존은 오늘 시작 — 서류 · PG · 법무는 일정이 여러분 손 밖에 있습니다.
  3. 고친 뒤 재진단 — "고친 뒤 다시 진단" 을 누르면 달라진 항목만 따로 보여 줍니다.
  4. 권한 회수 — 비공개 저장소였다면 읽기 권한을 거두셔도 됩니다. 복제본은 지웠습니다.

"통과" 는 코드와 설정을 읽어서 확인한 것입니다. 운영 환경에서의 동작은 "실행해야 확정되는 것" 의 방법으로 닫습니다. 참고 자료이며 법률·세무 자문이 아닙니다.