2탄 권3 제0·1장
2탄 권3 — 제0·1장

Day 29 휴식 의식 + Day 30~35 두 탭 UI

사용자가 처음 화면에서 줍줍을 만지는 자리 — E5 [2] 톤 분리 본격

📑 이 챕터에서 다룰 내용
서문 권1·권2에서 권3으로

권1 (Phase 0) 21h + 권2 (Phase 1.0 절반) 63h = 누적 84h. 5파일+ 체계 가동 + 5확장 5/5 운영 사이클 완성. 1탄 v2 메타 원칙 6개 모두 데이터 입증.

이제 권3 — 사용자가 직접 줍줍을 보고 만지는 자리. Day 29~73 (45일).

본질핵심 사건
권1 (Phase 0)5파일+ 사이클E1·E3·E4 등장
권2 (Phase 1.0 절반)DB·인증·E5 [3]R4 자동 회복 + G2 통과
권3 (Phase 1.0 후반·1.1·출시)UI·외부 노출·심사E5 [2] [5] + E1 4자리 + G3·G4·G5

권3 끝 = 앱스토어 심사 통과 + 1순위 커뮤니티 게시 + 첫 100 사용자 + Phase 2 예고.

0-1 Day 29 — 휴식 의식 적용
📘 들어가며 — Day 29의 자리

권2 끝에서 ★ G2 PASSED + git tag v0.1-G2-passed. 누적 84h. Day 28 "Day 29 1일 휴식 의무" 결정.

이 챕터는 휴식 의식 적용 + 권3 45일 구조 안내 + 5확장의 권3 진화 예고입니다.

사전 지식 체크이 장의 목적완료 후 결과물
권1·권2 누적 / G2 PASSED / Day 29 휴식 결정 Day 29 휴식 적용 + 권3 구조 + 권3에서 등장할 5확장 진화 + Day 30 작업 시작 준비 충분한 휴식 + 권3 구조 인지 + 페이스 정상 복귀 (4h/일)
💻 BUILD.md Day 29 entry
## Phase 1.0 Day 29 — ★ G2 통과 후 휴식 의무 ★

[계획]
- 작업 X (의식적 휴식)

[실행]
- 작업 X
- 가족·자유 시간
- 가벼운 활동만 (산책·읽기)
- BUILD.md·CLAUDE.md 노출 X (강제 단절)

[E2 페이스 회복 효과]
- 권1+권2 누적 84h → Day 29 휴식 → 다음 4주 새 시작
- "G2 통과 → 1일 휴식" 의식 (1탄 v2 부록 H-2 본문 일치)
- 다음 4주 평균 R4 60h/4주 트리거 안전 영역 재진입

[6개월 후 동업자 시나리오]
"왜 Day 29에 작업 안 했나?" 펼치면 본 트레이스에 답:
"G2 게이트 통과 의식 = 1일 휴식 의무. 1탄 v2 부록 H-2 R4 본문 그대로.
운영자 보호 = R1~R12 모두 의미 있게 만드는 자리."

[누적] 84h (Day 29 변동 없음)

휴식 후 Day 30 작업 정상 4h/일 복귀 준비.

0-2 권3 구조 안내 — Day 30~73 (45일)
💻 권3 45일 구조
┌──────────────────────────────────────────────────────────────┐
│ 5주차 (Day 30~35) + Day 36 휴식 — G3 첫 주                   │
│   Day 30: 두 탭 메인 (Agent Teams 위임 — 소상공인·시민)      │
│   Day 31: 카테고리 필터·정렬 (★ E5 [2] 톤 분리)              │
│   Day 32: 상세 페이지 (지원금 정보 카드)                     │
│   Day 33: 단계적 기여 — 체크박스 (부담 0)                    │
│   Day 34: 단계적 기여 — 결과 3택 (부담 낮음)                 │
│   Day 35: 자유 후기 폼 + 닉네임 노출 (E5 [3] 적용)           │
│   Day 36: 일요일 회고                                        │
├──────────────────────────────────────────────────────────────┤
│ 6주차 (Day 37~42) — G3 통과                                  │
│   Day 37: 후기 신고 UI (사용자 측, C-4 연결)                 │
│   Day 38: ⚖️ E1 일관 노출 텍스트 (콘텐츠 면책 1차)           │
│   Day 39: 매칭 알고리즘 (사용자 필터 ↔ benefits)             │
│   Day 40: 통합 시뮬 (사용자 1명 줍줍 완료)                   │
│   Day 41: G3 점검                                            │
│   Day 42: ★ G3 PASSED 의식 + 6주 회고                        │
├──────────────────────────────────────────────────────────────┤
│ 7주차 (Day 43~49) — 통계 시각화 + Sentry                     │
│   Day 43: 마이페이지 (내가 줍줍한 총액 — DB 집계)            │
│   Day 44: 통계 차트 (성공률·평균 일수)                       │
│   Day 45: Phase 1 KPI 측정 (E1 [측정 메트릭])                │
│   Day 46~47: Sentry 통합 (Day 56 게이트 조건)                │
│   Day 48: 첫 7일 무장애 관측 시작                            │
│   Day 49: 일요일 회고                                        │
├──────────────────────────────────────────────────────────────┤
│ 8주차 (Day 50~56) — G4: FCM 알림 + 공유 카드                 │
│   Day 50: FCM 마감 D-7 알림 cron                             │
│   Day 51: FCM 신규 매칭 즉시 알림                            │
│   Day 52: 공유 카드 (Satori OG 이미지)                       │
│   Day 53: 1순위 커뮤니티 측정 폼 (어드민)                    │
│   Day 54~55: G4 통합 + 7일 무장애 관측 완료                  │
│   Day 56: ★ G4 PASSED 의식 + 8주 회고                        │
├──────────────────────────────────────────────────────────────┤
│ 9주차 (Day 57~63) — 약관·개인정보·QA                         │
│   Day 57~58: ⚖️ E1 외부 노출 4자리                           │
│            (About + 약관 + 개인정보처리방침 + Footer)        │
│   Day 59: Apple Privacy Manifest 자동 검증 (G-7)             │
│   Day 60: 어드민 마무리 (검수·신고·매칭·통계)                │
│   Day 61: QA 1차 (전체 시나리오)                             │
│   Day 62: QA 2차 (Edge case)                                 │
│   Day 63: 일요일 회고                                        │
├──────────────────────────────────────────────────────────────┤
│ 10주차 (Day 64~73) — ★ G5 FINAL: 심사 + 커뮤니티             │
│   Day 64: EAS Build (iOS·Android)                            │
│   Day 65: 앱스토어 심사 제출 (iOS)                           │
│   Day 66: 플레이스토어 심사 제출 (Android)                   │
│   Day 67~68: 1순위 커뮤니티 게시 준비 + 게시                 │
│   Day 69~71: 심사 결과 대응 (필요 시 재제출)                 │
│   Day 72: 1순위 커뮤니티 반응 수집                           │
│   Day 73: ★ G5 PASSED + Phase 1 종합 회고 + Phase 2 예고     │
└──────────────────────────────────────────────────────────────┘
0-3 권3 5확장 진화 예고
확장권1·권2 진화권3 진화
E1 회색지대SPEC § 두 결정 + CLAUDE.md §3외부 노출 4자리 (Day 57~)
E2 1인 페이스R4 자동 회복 1회휴식 의식 4번 (G3·G4·G5·Phase 1 종합)
E3 두 검토자G-1·G-3·G-4·G-5·G-6G-7 (Apple Privacy Manifest 자동)
E4 LogOnTable39 트레이스+50 트레이스 → 누적 ~90
E5 콘텐츠 SSOT[1] [3] [4] [6] [7][2] 톤 분리 + [5] E1 외부 노출 4자리 일관
0-4 권3에서 가장 가치 있는 두 자리

1. E5 [2] 톤 분리 (Day 30~35)

권1·권2에서 [3] 닉네임 페르소나 풀로 부분 등장. 권3에서 UI 카피 전체 톤 분리입니다.

💻 두 탭 톤 분리 카피
[소상공인 탭 — 사장님 톤]
- 메인 제목: "사장님, 오늘 받을 수 있는 지원금"
- 카테고리: "신청 자격 + 매출 영향"
- 줍줍 버튼: "사업장에 도움 → 줍줍"

[개인 복지 탭 — 시민 톤]
- 메인 제목: "당신에게 맞는 복지 혜택"
- 카테고리: "생애주기 + 가구 상황"
- 줍줍 버튼: "내 상황에 맞아 → 줍줍"
💡 SSOT 시스템의 깊이

같은 "줍줍 버튼"인데 두 탭에서 다른 카피. 사실은 같지만 표현은 다름 — E5 콘텐츠 SSOT 시스템의 핵심입니다.

2. E1 외부 노출 4자리 (Day 57~58)

권1 제3장에서 SPEC § 회색지대 결정 두 결정 박힘. 권3에서 About + 약관 + 개인정보처리방침 + Footer 4자리에 같은 메시지 박힙니다.

💻 E1 외부 노출 4자리 핵심 메시지
[About 페이지]
"줍줍은 정부 지원금 정보를 정리하고, 사용자 후기를 공유하는 미디어입니다.
✓ 약속하는 것: 공식 정보 정리 / 마감·요건 알림 / 후기 공유 / 자유 공간
✗ 약속하지 않는 것: 무조건 받게 X / 신청 대행 X / 요건 우회 X / 정부 공식 X"

[약관 §3 서비스 범위]
"본 서비스는 신청 대행 X, 신청 결과 보장 X, 정부 공식 X."

[개인정보처리방침 §1]
"수집: 카카오 ID, 닉네임 자동, 자발적 필터, jupjups 행위
수집 안 함: IDFA·디바이스 식별자·위치
제3자 제공: X (Phase 3 익명 집계만)"

[Footer 모든 페이지]
"본 서비스는 정보 제공 목적, 결과 보장 X | About | 약관 | 개인정보"
🎉 제0장 정리

핵심 한 줄: 권3 = 45일 (Day 29~73). G3·G4·G5 + E1 4자리 + E5 [2] [5] 본격. ★ G5 FINAL 앱스토어 심사 + 1순위 커뮤니티.

  • Day 29 휴식 의식: 권1+권2 누적 84h → Day 29 작업 X → Day 30 정상 복귀
  • 5~6주차: G3 두 탭 UI + 단계적 기여
  • 7주차: 통계 + Sentry
  • 8주차: G4 알림·공유
  • 9주차: 약관·개인정보·QA
  • 10주차: ★ G5 심사 + 커뮤니티
제1장 사용자 첫 만남의 자리

권2까지 "DB + 인증 + 백엔드". 권3 제1장부터 사용자가 직접 보고 만지는 화면. 5확장 E5 [2] (톤 분리) 본격 등장 자리입니다.

사전 지식 체크이 장의 목적완료 후 결과물
권1·권2 + Day 29 휴식 / CLAUDE.md §5 [2] / G3 통과 조건 Day 30~35 두 탭 UI + 단계적 기여 시스템 + E5 [2] 본격 두 탭 메인·필터·상세 페이지 + 단계적 기여 3 단계 + 첫 사용자 줍줍 시뮬
1-1 Day 30 — 두 탭 메인 (Agent Teams 위임)

작업 (4h — 페이스 정상 복귀)

CLAUDE.md §6 폴더 구조 그대로 두 에이전트에 병렬 위임합니다.

💻 Claude Code — 두 탭 메인 Agent Teams 위임
[Claude Code, Sonnet + medium]
"두 탭 메인 페이지 동시 (Agent Teams):

/delegate

  에이전트 A (담당: src/app/(tabs)/business/index.tsx):
    - 메인 제목: '사장님, 오늘 받을 수 있는 지원금' (E5 [2] 사장님 톤)
    - benefits 목록 (target_business_type 필터)
    - 카드 컴포넌트: 사업단계 + 지원 금액 + 마감 D-N + 줍줍 수
    - 줍줍 버튼 카피: '사업장에 도움 → 줍줍'

  에이전트 B (담당: src/app/(tabs)/individual/index.tsx):
    - 메인 제목: '당신에게 맞는 복지 혜택' (E5 [2] 시민 톤)
    - benefits 목록 (target_age·target_household 필터)
    - 카드 컴포넌트: 생애주기 + 지원 금액 + 마감 D-N + 줍줍 수
    - 줍줍 버튼 카피: '내 상황에 맞아 → 줍줍'

CLAUDE.md §5 [2] Two-Tab 톤 분리 절대 준수.
공통 BenefitCard.tsx 는 components/에 (직접 수정, 톤 prop으로 분기).
E5 [1] SSOT 준수 — 같은 benefit_id 두 탭 노출 시 사실 일치 자동 검증."
💻 BUILD.md Day 30 entry
## Phase 1.0 Day 30

[계획]
- 두 탭 메인 페이지 Agent Teams 위임

[실행]
- /delegate 에이전트 A·B 병렬 (4h 합계, 순차 8h 대비 -50%)
- src/app/(tabs)/business/index.tsx (160줄)
- src/app/(tabs)/individual/index.tsx (155줄)
- src/components/BenefitCard.tsx (110줄, tone prop으로 분기)
- 일관성 테스트 5/5 통과 (E5 [6])

[LogOnTable 트레이스 — BenefitCard tone prop 결정]
> 결정: BenefitCard 단일 컴포넌트 + tone='business'|'individual' prop
> 근거: SSOT 시스템 [1] — 사실 단일 출처 + 톤 분리 [2]. 두 컴포넌트
       복사 X = DRY + E5 [1] 자연 보장.
> 대안: BusinessCard / IndividualCard 분리 — 코드 중복 + 일관성 검증 어려움
> 부작용: tone prop 전환 시 카피만 변경. 다음 톤 추가 시 enum 확장 가능

[E5 [2] 본격 등장]
- 같은 BenefitCard 컴포넌트, tone prop 'business' / 'individual'
- 사실은 같지만 표현은 다름 (SSOT 시스템 깊이)

[누적] 84h + Day 30 (4h) = 88h
1-2 Day 31 — 카테고리 필터·정렬 (E5 [2] 확장)
💻 Claude Code — 두 탭 필터·정렬 Agent Teams
[Claude Code]
"카테고리 필터·정렬 컴포넌트 — 두 탭 톤 분리:

  에이전트 A (담당: src/app/(tabs)/business/filters.tsx):
    - 필터 카테고리 (사장님 톤):
      · '내 사업단계는?' (창업준비/1년미만/3년미만/3년이상/폐업재기)
      · '지원 유형' (자금/공간/컨설팅)
      · '신청 자격' (강조)
    - 정렬:
      · '마감 임박순' / '많이 줍줍한 순' / '내가 받을 가능성 높은 순'

  에이전트 B (담당: src/app/(tabs)/individual/filters.tsx):
    - 필터 카테고리 (시민 톤):
      · '내 가구는?' (1인/부부/한부모/다자녀/노인/장애인)
      · '내 상황' (생애주기)
      · '소득 분위' (선택)
    - 정렬: 동일 3개 (단, 카피 시민 톤)

E5 [1] [2] 절대 준수."
📘 LogOnTable 트레이스 — 카테고리 카피 톤 분기 16개

결정: 같은 기능 (필터 6 + 정렬 3 = 9개) × 두 탭 = 카피 18개 톤 분기

근거: E5 [2] "같은 사실 다른 톤"의 깊이. UI 카피 1개씩 분기.

대안: 같은 카피 사용 — 톤 분리 본질 손상 (사장님이 시민 카피 읽으면 "내 앱이 아닌 듯" 느낌)

부작용: 카피 18개 i18n 매핑 (Phase 1.1 다국어 시 본격), 현재는 static.

누적: 88h + Day 31 (4h) = 92h

1-3 Day 32 — 상세 페이지 (지원금 정보 카드)
💻 Claude Code — 두 탭 상세 페이지 분리
에이전트 A (src/app/(tabs)/business/[benefit_id].tsx):
  - 헤더: benefit name + 지원 금액 + 마감 D-N
  - 사장님 톤 섹션:
    · '신청 자격' / '지원 내용' / '꼭 필요한 서류' / '담당 기관'
  - 후기 영역 (Day 33~35 단계적 기여 컴포넌트 placeholder)
  - 줍줍 버튼: '사업장에 도움 → 줍줍'

에이전트 B (src/app/(tabs)/individual/[benefit_id].tsx):
  - 헤더 동일 (사실 동일 — E5 [1])
  - 시민 톤 섹션:
    · '신청 자격' / '받는 방법' / '필요한 것' / '문의처'
  - 후기 영역 placeholder
  - 줍줍 버튼: '내 상황에 맞아 → 줍줍'
📘 LogOnTable 트레이스 — '담당 기관' vs '문의처'

결정: 사장님 톤 = '담당 기관' / 시민 톤 = '문의처'

근거: 사장님 = "공식 절차 인식 강함" → 기관명 정확히 / 시민 = "친근한 안내" → 문의처 표현 자연

누적: 92h + Day 32 (4h) = 96h

1-4 Day 33 — 단계적 기여: 부담 0 (체크박스)
💻 components/JupjupCheckbox.tsx (약 100줄)
// components/JupjupCheckbox.tsx
import { useState } from 'react';
import { Alert } from 'react-native';
import { jupjupCreate } from '@/lib/jupjups';

interface Props {
  benefitId: string;
  tone: 'business' | 'individual';
  onSuccess?: () => void;  // Day 34 부담 낮음 노출 트리거
}

const COPIES = {
  business: {
    label: '사업장에 도움 → 줍줍',
    success: '줍줍! 다음 단계 어땠나요?',
    duplicate: '이미 줍줍한 지원금입니다',
    rateLimit: '잠시 후 재시도해주세요',
  },
  individual: {
    label: '내 상황에 맞아 → 줍줍',
    success: '줍줍! 다음 단계 어땠나요?',
    duplicate: '이미 줍줍한 지원금입니다',
    rateLimit: '잠시 후 재시도해주세요',
  },
};

export function JupjupCheckbox({ benefitId, tone, onSuccess }: Props) {
  const [pending, setPending] = useState(false);
  const [done, setDone] = useState(false);
  const copy = COPIES[tone];

  const handleClick = async () => {
    if (done || pending) return;
    setPending(true);

    try {
      const result = await jupjupCreate(benefitId);

      if (result.error === 'DUPLICATE') {
        Alert.alert(copy.duplicate);
      } else if (result.error === 'RATE_LIMIT') {
        Alert.alert(copy.rateLimit);
      } else if (result.success) {
        setDone(true);
        onSuccess?.();  // Day 34 부담 낮음 노출
      }
    } finally {
      setPending(false);
    }
  };

  return (
    <Pressable onPress={handleClick} disabled={pending || done}>
      <Text>{done ? copy.success : copy.label}</Text>
      {/* ⚖️ E1 하단 면책 */}
      <Text className="text-xs text-gray-500 mt-1">
        본 서비스는 정보 제공 목적, 신청 결과 보장 X
      </Text>
    </Pressable>
  );
}
📘 LogOnTable 트레이스 — 체크박스 옆 면책 텍스트

결정: 체크박스 컴포넌트 안에 E1 면책 1줄 명시

근거: 권1 제3장 E1 결정 ① + 권3 Day 38 외부 노출 4자리 예정이지만 사용자 행위 시점 (체크박스 누르는 자리) = 가장 강한 자리. "신청 결과 보장 X" 즉시 인지.

누적: 96h + Day 33 (4h) = 100h

1-5 Day 34 — 단계적 기여: 부담 낮음 (결과 3택)
💻 Claude Code — 결과 3택 컴포넌트
요구사항:
1. components/JupjupResultPicker.tsx — 체크박스 후 1초 안에 노출
2. 3택: SUCCESS (받았어요) / FAILED (떨어졌어요) / IN_PROGRESS (진행중)
3. UPDATE jupjups SET result = ?
4. 트리거 자동: benefits.total_jupjups·total_success 갱신
5. E5 [2] 카피 두 탭 분리:
   - business 톤: '받았어요 (대박!) / 떨어졌어요 (다음을 위해) / 진행중'
   - individual 톤: '받았어요! / 떨어졌어요... / 진행중이에요'
📘 LogOnTable 트레이스 — 결과 3택 카피 톤 분기

결정: 'SUCCESS / FAILED / IN_PROGRESS' enum + 두 톤 6 카피

근거: enum 동일 (DB 일관) + UI 카피 분리 (E5 [2] 톤 분리 깊이). 사장님 톤 "대박!" vs 시민 톤 "받았어요!" 감정 표현 차이. 분리가 자연스럽습니다.

누적: 100h + Day 34 (4h) = 104h

1-6 Day 35 — 자유 후기 폼 + 닉네임 노출
💻 Claude Code — 자유 후기 + 닉네임 시스템
1. components/JupjupReviewForm.tsx
   - 결과 입력 후 1초 안에 노출 (선택, "건너뛰기" 버튼)
   - 200자 제한 + 자동 카운트
   - UPDATE jupjups SET review_text, days_taken

2. 자유 후기 노출 시 닉네임 표시:
   - components/UserNicknameBadge.tsx
   - E5 [3] 닉네임 + 신뢰 표시 (총 줍줍 N개·후기 M개)

3. 후기 노출 페이지 (상세 페이지 안):
   - components/ReviewList.tsx
   - 닉네임 + 결과 + 후기 텍스트 + N일 전
   - 신고 버튼 (C-4 연결, Day 37)
📘 LogOnTable 트레이스 — 닉네임 노출 형식

결정: 닉네임 + 신뢰 (총 줍줍·후기 수) 강조 (실명 X)

근거: E1 결정 ② "익명성 유지" + 사용자 신뢰 = 줍줍·후기 수 (실명보다 행위 데이터)

누적: 104h + Day 35 (4h) = 108h

1-7 Day 30~35 (5주차) 진행 점검
💻 5주차 누적 현황
[권1·권2 누적] 84h
[권3 5주차 (Day 30~35)] 24h
[합계 누적] 108h
[5주차 평균] 24h/6일 = 4h/일 (페이스 정상)
[R4 4주 누적 (2~5주차)] 14+14+21+24 = 73h ⚠️ R4 60h 트리거 초과
⚠️ E2 페이스 점검 — 5주차 끝 (Day 35) 시점

4주 누적 73h로 R4 트리거 (60h/4주) 초과. 자동 결정이 발동합니다.

  • Day 36 일요일 추가 휴식 (회고만)
  • 6주차 (Day 37~42) 페이스 25% 축소 (4h/일 → 3h/일)
  • "피곤하다" 신호 부재 — 단, 트리거 초과만으로 자동 보호

📌 권3 제0·1장 정리

  • Day 29 휴식 의식: 권1+권2 누적 84h → 작업 X → Day 30 정상 복귀
  • 5주차 산출물: 두 탭 메인 (315줄) + 필터·정렬 (265줄, 18 카피) + 상세 (290줄) + 단계적 기여 3단계 (340줄) + 닉네임·후기 (150줄) = ~1,360줄
  • E5 [2] 본격 등장: BenefitCard tone prop 분기 + 18 카피 톤 분기. "사실은 같지만 표현은 다름"
  • 단계적 기여 3단계: 부담 0 (체크박스) → 부담 낮음 (3택) → 부담 선택 (200자 후기)
  • 누적: 108h / 4주 누적 73h (R4 트리거 초과 → 6주차 페이스 축소 자동 결정)
  • 다음 장: 권3 제2장 — Day 36~42 (G3 두 탭 마무리 + 단계적 기여 완성 + ★ G3 PASSED)