Oracle3
Oracle3: 예측시장 거래 엔진·MCP 서버
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
가족·부부·커플·룸메이트 등 원하는 단위로 그룹을 만들어 지출을 함께 관리하는 공유 가계부 — 영수증을 사진 한 장으로 기록하고, 아낀 만큼 저금통 펫이 자라는 앱. • 타깃 사용자: 대학생, 부부, 커플 • 겪는 문제 1. 지출 출처를 알 수 없는 지출이 나온다 (예: 토스로 결제하면 "토스페이 지출"로만 뜸) 2. 카카오톡·메시지로 오는 전자 영수증을 캡쳐해서 등록하는 것이 번거롭다 3. 내 돈이 어느 순간 사라진 것처럼 느낀다 4. 그룹원끼리 쓴 내역을 직접 다 더해서 정산해야 한다 5. 그룹원끼리 각자 다른 방식(수기·단톡방·개별 앱)으로 기록해 한곳에서 보기 어렵다 6. 그룹 성격이 "가족"으로 고정돼 있어 커플·룸메이트 등 다른 관계에는 맞지 않는다 • 우리의 해결: 그룹의 성격을 앱이 정해주지 않고 사용자가 만들 때 직접 고르게 하고(가족/부부/커플/친구/모임·동아리/기타), 영수증은 촬영 한 번으로 OCR 자동 입력, 기록은 그룹 피드 한곳에 모은다. 목적은 세 가지 — 투명성 · 신뢰성 · 정산 편의.README 전문 보기 ↗
가족·부부·커플·룸메이트 등 원하는 단위로 그룹을 만들어 지출을 함께 관리하는 공유 가계부 — 영수증을 사진 한 장으로 기록하고, 아낀 만큼 저금통 펫이 자라는 앱.
| 항목 | 내용 |
|---|---|
| 팀명 | ShooT |
| 팀원 | 이종민(형상관리자), 황하윤(리서쳐), 신아림(PM) |
| 기간 | 2026.08.26 ~ 2026.09.22 |
| 배포 링크 | https://module1-two.vercel.app/ |
| 피그마 | 사용하지 않음 (디자인은 Claude Design으로 대체) |
| Claude Design | https://claude.ai/design/p/d96d3213-5f1e-437d-aeee-2a78011034a2?file=ShooT+%ED%95%98%EC%9C%A4.dc.html&via=share |
| 저장소 | https://github.com/SHY-wanted/module1 |
팀이 직접 확인한 유사 서비스: 카카오페이·토스·뱅크샐러드 — 셋 다 자동 기록은 되지만 실물 영수증 촬영 등록과 "가족 외 그룹" 단위 공유가 없다는 점을 차별점으로 잡았다.
| 우선순위 | 기능 | 상태 |
|---|---|---|
| 최상 | F1~F3 그룹 생성·초대코드 발급·참여 | 완료 |
| 최상 | F5·F6 지출 기록·목록 조회 | 완료 |
| 최상 | F8·F10·F11 영수증 촬영 OCR 자동 입력 + 인식 실패 항목 후수정 | 완료 |
| 최상 | F12·F13 그룹 공유 토글 · 그룹 피드 | 완료 |
| 최상 | F14 본인 지출만 수정·삭제(권한 제약) | 완료 |
| 상 | F7 메모 · F19·F20 저금 등록 · F21 캘린더 | 완료 |
| 중 | F18 그룹장 위임 | 완료 (v2 범위였으나 구현) |
| — | F22 그룹 반려 캐릭터 · F23 피드 이모지 반응 (v2 통합) | 완료 |
| — | 저금통 펫(P1·P2·P3·P5·P8), 월별 목표(P7'·P4), 출석체크, 개인 랭킹, 카카오 로그인, 회원 탈퇴 | 완료 |
| 하 | F17 월별 리포트 | 일부 (월별 목표 리포트로 대체) |
MVP를 끝낸 뒤 더 붙인 것 (9/199/22, PR #17#23과 main 직접 커밋)
| 기능 | 무엇인가 |
|---|---|
| 정기 지출 | 매달 같은 날 자동으로 기록되는 템플릿(월세·구독료 등). 화면을 열 때 이번 달 것을 만든다 — 별도 배치 서버 없음 |
| 그룹 예산 | 그룹장이 카테고리별 이번 달 예산을 정하고, 그룹 상세에서 쓴 만큼 비교해 보여준다 |
| 그룹원 지출 비교표 | 정산 자동계산 대신 "누가 이번 달 얼마나 썼는지"만 나란히 보여준다 |
| 지출 페이스 경고 · 저녁 리마인더 · 메모 검색 | 이 속도면 목표를 넘는다는 경고, 오후 8시까지 기록이 없으면 알림, 메모로 지출 찾기 |
| 온보딩 투어 · 카테고리 도넛 차트 · 지출 정렬 | 첫 실행 안내, 홈의 카테고리 비중 시각화, 목록 정렬 옵션 |
| 펫 경제 개편 | 단계별 필요 XP 증가, 밥값 5코인, 지출 기록 코인(하루 한 번), 그룹원이 각자 하루 한 번 그룹 펫 먹이기(XP는 인원수로 나눠 형평성 유지) |
| 그룹 펫 꾸미기 | 그룹 펫도 색을 바꿀 수 있다. 그룹원 누구나 바꾸고 모두에게 같이 보인다 |
| 실시간 동기화 | 그룹원이 무엇을 하든(참여·탈퇴·지출·저금·이모지·펫 꾸미기·예산 변경·닉네임 변경) 새로고침 없이 내 화면에 반영된다 |
| 보안 강화 | REST/RPC를 직접 호출해 코인·XP를 무한정 채우거나 아무 그룹의 그룹장을 자가 임명할 수 있던 구멍을 막았다. 보상 계산을 클라이언트에서 서버 RPC로 옮기고, pets의 경제 컬럼은 컬럼 단위 권한으로 잠갔다 |
| 회원가입 비밀번호 검증 | 입력칸에 "8자 이상"이라고 써 있는데 실제로 검사하는 코드가 없어 7자로도 가입됐다 — 이메일 형식과 같은 인라인 오류로 막았다 |
| 상황 | 사용자에게 보이는 것 | 다음 행동 | 구현 여부 |
|---|---|---|---|
| 필수 입력이 비어 있음 (P1) | "이메일과 비밀번호를 입력해주세요" / "그룹 이름을 입력해주세요" | 입력 후 재시도 | ✅ |
| 데이터가 하나도 없음(빈 상태) | "아직 지출 내역이 없어요" · "아직 속한 그룹이 없어요" · "이번 달 설정한 목표가 아직 없어요" + 첫 행동 유도 버튼 | 추가하기 | ✅ |
| OCR 인식 실패 (P7·F11) | 저장은 항상 성공하고 category="확인 필요" 배지로 표시 | 항목을 눌러 수정(F10) | ✅ |
| 본인 지출이 아닌 것을 수정 시도 (P6) | "본인 지출만 수정할 수 있어요" (RLS가 서버에서도 차단) | 조회만 가능 | ✅ |
| 그룹 멤버가 아닌 그룹 피드 조회 (P5) | "그룹 멤버만 볼 수 있어요" | 초대 코드로 참여 | ✅ |
| 이미 참여한 그룹에 다시 참여 (P3) | "이미 참여한 그룹입니다" | 그룹 목록으로 | ✅ |
| 그룹장이 위임 없이 나가기 (P10) | "새 그룹장을 먼저 지정해주세요" (혼자면 그룹·지출 함께 삭제) | 10a-1에서 위임 | ✅ |
| 그룹에 속하지 않아 공유 대상이 없음 (P8) | 공유 select가 아예 표시되지 않음 (오류 아님) | 개인 지출로 저장 | ✅ |
| 저장·불러오기 실패(네트워크·권한) | "지출을 저장하지 못했어요" 등 원인별 한국어 문구 | 다시 시도 | ✅ |
| 카메라를 쓸 수 없음 | "카메라를 사용할 수 없어요. 갤러리에서 사진을 선택해주세요" | 갤러리 선택 | ✅ |
문서는 문제에서 화면까지 한 줄로 이어지도록 번호 순으로 썼다. 앞 문서의 결론이 뒷 문서의 입력이 되고, 각 항목에 ID(R·F·P·E)를 붙여 서로를 참조한다 — 예를 들어 "본인 지출만 수정" 규칙은 요구 R14 → 기능 F14 → 정책 P6 → 데이터 E4 → 화면 7로 추적된다.
01 문제 정의 → 02 업무 분석 → 03 요구사항(R) → 04 기능(F) → 05 정책(P) → 06 데이터(E) → 07 화면
↘ PRD (전부 요약한 종합본)
| 문서 | 무엇이 들어 있나 | 분량 |
|---|---|---|
| 01. 문제 정의 | 팀이 이 주제를 고른 기록, 목적 3가지(투명성·신뢰성·정산 편의), 문제/대상/현재해법/불편 4요소 표, 팀이 모은 불편 6개, 유사 서비스 3개(카카오페이·토스·뱅크샐러드) 직접 접속 조사와 차별점 | 71줄 |
| 02. 업무 분석 | 행위자 4명(그룹원·그룹장·신규 초대 멤버·정산 상대)과 각자 지금 쓰는 도구, 지출 기록의 As-Is → To-Be 단계표(그룹 생성 → 지출 발생 → 출처 확인 → OCR 등록 → 인식 실패 수정 → 공유 → 정산), 단계별 감정·불편 | 62줄 |
| 03. 요구사항 | R1~R21. 각 요구의 우선순위(최상/상/중/하)와 그 근거, 어느 목적과 연결되는지. 목적에 연결되지 않은 요구는 지우지 않고 "연결 안 됨"으로 표시만 해 남겼다 | 87줄 |
| 04. 기능 | F1~F23. R을 기능으로 옮긴 것으로, 기능마다 어느 R에서 나왔는지 출처를 달았다. 중요도 × 난이도 2축으로 우선순위를 다시 매겼고, 에이전트가 던진 발산 질문의 채택·거절 결과와 MVP 이후 추가된 기능도 여기 있다 | 114줄 |
| 05. 정책 | P1~P17. "누가 / 언제 / 무엇을 할 수 없다 / 위반하면 화면에 뭐가 보이는가" 네 칸으로 쓴 규칙표. 상태값 2개(그룹장 위임, 지출 인식 상태)와 서비스 정책 SP1~SP4(범위 밖 명시). 이 표가 그대로 Supabase RLS 정책이 됐다 | 69줄 |
| 06. 데이터 | 엔티티 16개(E1 | 305줄 |
| 07. 화면 | (디자인 초안 23개 + 나중에 추가된 비밀번호 찾기·정기 지출 관리 등)의 ID·이름·관련 R·F·진입 경로·다음 화면, 화면별 상세, (탭은 120ms 크로스페이드, 스택은 280ms 세로 슬라이드). 마지막에 목록을 따로 남겼다 |
계획과 실제가 갈라진 곳도 지우지 않고 남겼다. PRD 7절 기술 스택은 오래
React + Vite로 적혀 있었지만 실제로는 Next.js로 만들었다 — 셋업에서 바꾸고 문서에 반영하지 않았던 것을 2026-09-21에 현행화하면서, 값을 덮어쓰는 대신 "계획 / 실제" 2열 표로 바꿔 무엇이 언제 갈라졌는지 보이게 했다. 펫 명세(08)도 같은 방식으로 맨 뒤에 「이 문서와 실제 구현이 달라진 곳」 절을 뒀다 — 주간 예산·주간 정산 배치처럼 제안됐다가 폐기된 것이 왜 사라졌는지 추적된다.
문서 공통 표기 규약 — 이 프로젝트 기획 문서의 핵심 장치다.
| 표기 | 뜻 |
|---|---|
[?] | 팀이 아직 모르는 것. 짐작해서 채우지 않고 물음표로 남긴다 |
[제안] | 에이전트가 보탠 후보. 근거 한 줄을 함께 적고, 팀이 채택하면 태그를 지운다 |
| 「검토했으나 제외」 | 각 문서 끝에 두는 표. 거절한 후보를 이유와 함께 남겨 같은 논의를 두 번 하지 않는다 |
즉 문서 어느 줄을 봐도 그게 팀이 정한 것인지, 에이전트가 제안한 것인지, 아직 모르는 것인지 구분된다.
| 도구 | 어느 단계에 썼나 | 원본 여부 |
|---|---|---|
| 피그마 | 사용하지 않음 | — |
| Claude Design | 색·타이포·컴포넌트 정의부터 화면 생성까지 (ShooT 하윤.dc.html). 초안 23종으로 시작해 최종본 36종 — 구현하면서 추가된 화면(펫·배지·월별 목표·그룹장 위임·정기 지출 관리 등)을 디자인에 역으로 반영했다 | 원본 |
app/globals.css | Claude Design의 값을 CSS 변수(디자인 토큰)로 옮겨 코드의 단일 기준으로 삼음 | 구현 기준 |
| 구분 | 정의 | 피그마 | Claude Design |
|---|---|---|---|
| 색상(라이트) | Accent #6a5ecf, Background #f6f5fc, Surface #ffffff, Surface-alt #f0eeff, Border #e8e4f4, Text #2d2a3e, Muted #6b6980 | ✗ | ✅ |
| 색상(다크) | Accent #9b8cff, Background #15131f, Surface #201d2e, Text #f1eefa | ✗ | ✅ |
| 타이포 | 본문·제목 모두 Geist Sans (next/font), 코드 Geist Mono · 강조는 크기(11~30px)와 두께(600/700/800)로만 구분 | ✗ | ✅ |
| 아이콘 | Lucide (stroke 2px, round cap/join, 24×24 viewBox) — components/icons.tsx에 직접 이식해 외부 의존성 0 | ✗ | ✅ |
색은 전부
var(--shoot-*)토큰으로만 쓴다. 다크모드는.shoot-app-root[data-dark="true"]에서 토큰 값만 바꾸면 앱 전체가 따라 바뀌도록 설계했다.
cursor: 71efault) / Kakao(브랜드 고정색 #FEE500)borderRadius: 20, 1px solid var(--shoot-border), 항목 간 간격 10·16px 두 단계borderRadius: 14, 2px 테두리(오류 시 #E8B4B4, 포커스 시 accent)피그마를 쓰지 않았으므로 Claude Design 원본 ↔ 실제 배포 화면 2단 비교다.
Claude Design (ShooT 하윤.dc.html) | 실제 배포 화면 |
|---|---|
로그인 화면 — 아이콘 타일·제목·입력칸 radius·"로그인 상태 유지" 토글·카카오로 계속하기까지 그대로다. 남은 차이는 하나 — 실제 화면은 비밀번호 칸 아래에 비밀번호를 잊으셨나요? 링크를 인라인으로 뒀는데, 디자인은 이를 별도 화면(2a-1 비밀번호 재설정)으로 그렸다.
홈 화면 — 출석체크 배너, 수입 카드, 보라색 지출 카드(전월 대비 + 도넛 차트), 이번 달 목표 설정하기, 점선 "그룹 만들기", 최근 지출까지 순서와 구성이 같다. 남은 차이는 원본 맨 아래의 월 캘린더 — 실제 앱은 이를 홈에서 빼고 별도 화면으로 옮겼다.
실제 화면 더 보기(로그인 후):
flowchart LR
T["팀 3인"] -->|"인터뷰 답변"| PP["planning-partner<br/>기획 파트너"]
PP -->|"docs/ 기획 문서 초안"| PC["product-planner<br/>기획 코치"]
PC -->|"빠진 것·모호한 문장 질문"| T
T -->|"확정된 PRD + Claude Design"| PB["product-builder<br/>구현 에이전트"]
PB -->|화면 구현| T
T -->|CLAUDE.md + 스킬 문서| PB
| Agent | 역할 | 입력 | 출력 | 제약 |
|---|---|---|---|---|
| planning-partner | 기획 인터뷰를 한 번에 한 질문씩 진행하고 답을 문서 양식에 받아 적음. 발산 질문으로 후보를 [제안]으로 보탬 | 팀의 구두 답변, 앞 문서(01→05) | docs/0N-*.md 초안·종합 문서 | 팀 대신 결정하지 않음 · 모르면 [?] · docs/ 아래만 수정 (Read/Write/Edit) |
| product-planner | 기획 문서를 읽고 빈칸과 모호한 문장을 질문으로 되돌려줌. F↔R↔P ID 참조 검사(고아 ID 탐지) | docs/ 기획 문서 | 질문 목록·참조 검사 결과 | 문서를 대신 쓰지 않음 · 답을 정해주지 않음 (Read 전용) |
| product-builder | PRD와 Claude Design 화면을 입력으로 실제 화면 구현 | docs/PRD.md, 디자인 파일 | 화면 코드 | 첨부에 없는 화면을 지어내지 않음 · 서버/새 폴더가 필요하면 만들지 말고 되물음 |
| 스킬 문서 5종 | UI / CHARACTER / ANIMATION / ASSET_PIPELINE / DESIGN_SYSTEM — 작업 종류별로 반드시 먼저 읽는 규칙집 | — | — | CLAUDE.md가 "작업 시작 전 확인 필수"로 지정 |
[planning-partner]
팀이 말한 것은 그대로 적는다. 말을 매끄럽게 고치지 않는다. 팀의 단어를 쓴다.
네가 보탠 것에는 반드시 [제안]을 붙인다. [제안]마다 근거 한 줄.
대신 정하지 않는다. "이걸로 하자"고 쓰지 않는다.
모르면 [?]. 짐작해서 채우지 않는다.
질문은 한 번에 하나만 한다.
[product-planner]
기획 문서를 대신 써 주지 않는다. 빈칸을 찾아 질문으로 돌려준다.
"편리하다·좋다·귀찮다"처럼 확인할 수 없는 문장은 원문을 인용하고 왜 확인할 수 없는지 적는다.
기능 문장의 주어가 앱이거나, 정책에 기술 단어(DB·API)가 들어 있으면 지적한다.
[제안] 태그와 [?] 규칙을 넣어 출처가 팀인지 에이전트인지 항상 구분되게 바꿨다.product-planner 를 따로 만들어 질문만 하게 분리했다.CLAUDE.md에 Golden Asset 보호 · 최소 변경 · 원인 확인 전 수정 금지 조항을 넣고, 작업 종류별 스킬 문서 5종을 추가했다.CLAUDE.md는 44개 조항의 최상위 작업 규칙이다. 특히 중요한 것:
app/(라우트·API) · components/screens/(화면 컴포넌트 43개) · lib/(store·selectors·순수 로직) · docs/(기획) · supabase/(SQL 32개) · scripts/(마스크 생성·검증) · .claude/agents/(에이전트·스킬 문서)public/stage_*.png 원본 캐릭터 이미지는 덮어쓰기·재생성·크롭 금지. 색 변경은 런타임 마스크 합성으로만| 이름 | 하는 일 | 사용 |
|---|---|---|
DESIGN_SYSTEM.md | 임의 색·폰트·radius·그림자 추가 금지, 화면마다 새 버튼 스타일 금지 | UI 작업 전 상시 |
UI.md | 화면 구조·간격·상태 표시 규칙 | UI 작업 전 상시 |
CHARACTER.md | 부위 마스크·고정 색(코인 금색, 입) 보호 규칙 | 캐릭터 작업 12회+ |
ASSET_PIPELINE.md | 마스크 생성·검증 스크립트 규약 | 마스크 재생성 시 |
ANIMATION.md | 둥둥 뜨기·깜빡임·그림자 등 모션 원칙 | 애니메이션 작업 시 |
planning-partner / product-planner / product-builder | 위 3절 참고 | 기획 전 구간 |
매 변경마다 아래 3단계를 순서대로 통과시킨다.
| 명령 | 무엇을 잡나 |
|---|---|
npx tsc --noEmit | 타입이 안 맞는 실수. --noEmit은 "파일은 만들지 말고 검사만 해라"는 뜻 — 숫자 자리에 문자를 넣었거나 없는 값을 참조한 경우를 여기서 잡는다 |
npx eslint <변경 파일> | 코드 스타일과 흔한 버그 패턴. 안 쓰는 변수, React 의존성 빠뜨림 등. 실제로 고친 파일 경로를 넣는다 |
npx next build --webpack | 진짜 배포 가능한지. 앞 둘을 통과해도 빌드가 깨지는 경우가 있다(서버 전용 코드를 클라이언트에 섞는 등) |
캐릭터·마스크 작업은 node scripts/verify-character-masks.js로 13개 항목 자동 검증 + 실제 렌더 이미지를 눈으로 확인한다.
화면 동작은 로컬 HTTPS 서버(npm run 62ev:https)를 띄우고 실제 계정으로 로그인해 확인한다. 서버 로그([account], [receipt-ocr] 등)에 원인 진단용 로그를 남겨 실패 지점을 특정한다. 또는 vercel의 각각 브랜치 도메인 링크를 통해서 직접 확인.
잘못되면 덧붙여 고치지 않고 git status / git log로 마지막 정상 커밋을 확인해 되돌린다 (CLAUDE.md 29조).
실제 사례 1 — 캐릭터 부위 경계의 보라색 윤곽선 에이전트가 마스크를 "색 범위(밝기·색조 임계값)"로 나눴더니, 부위 경계마다 어느 마스크에도 속하지 않는 픽셀이 남아 색을 바꿀 때 보라색 테두리로 드러났다. 200% 확대 QA에서 발견 → 판정 기준을 "실제 오브젝트 경계(연결된 덩어리)"로 전면 재작성하고, 검증 스크립트로 "임자 없는 픽셀 0개"를 자동 확인하게 했다.
실제 사례 2 — 출석체크 연속일수가 매번 1일차
"어제 날짜"를 new Date(...).setDate(-1) 후 toISOString()으로 구했는데, 한국(UTC+9)에서는 이 변환이 날짜를 하루 더 밀어 어제 기록을 못 찾았다. 사용자 제보 → 로그로 재현 → 타임존 안전한 shiftDateKST()로 교체하고 순수 함수 단위로 검증했다.
실제 사례 3 — 그림자 마스크가 다리를 타고 올라감 알파 페이드를 그림자로 판정하다 보니 다리 실루엣을 따라 3~4px 흔적이 남았다. 사용자가 다크 배경 스크린샷으로 제보 → 형태학적 opening(침식→팽창)으로 얇은 돌기만 제거하도록 고쳤다.
gitGraph
commit id: "기획 문서"
branch yaru
commit id: "기획 초안 01~03"
checkout main
merge yaru tag: "PR #1"
branch petbranch
commit id: "저금통 펫"
checkout main
merge petbranch tag: "PR #8"
branch shooTbranch
commit id: "월별 목표"
checkout main
merge shooTbranch tag: "PR #10"
branch feature-income-account
commit id: "수입·회원탈퇴"
checkout main
merge feature-income-account tag: "PR #12"
branch shooTbranch2
commit id: "정기지출·그룹예산"
checkout main
merge shooTbranch2 tag: "PR #17"
branch feature-group-compare
commit id: "비교표·도넛차트"
checkout main
merge feature-group-compare tag: "PR #18"
commit id: "실시간 동기화" type: HIGHLIGHT
다이어그램의 브랜치 이름은
/를 뺀 축약형이고,shooTbranch2는 같은 브랜치를 두 번째로 쓴 것을 구분한 표기다(실제로는 같은shooTbranch). 실제 이름 예:feature/income-avatar-account-deletion,feature/group-compare-onboarding-donut-sort. 맨 끝실시간 동기화는 PR 없이 main에 직접 병합한 구간이다.
main(배포용) / 개인 작업 브랜치(mg, hybran~hybran7, hybranch, petbranch, shooTbranch, yaru, teamshy) / 기능·수정 브랜치(feature/<기능명>, fix/<버그>, docs/<문서>, draft/<문서>)mg, hybranch)으로 쓰다가, 후반에 작업 내용 기반(feature/income-avatar-account-deletion, draft/hy-ledger-planning-01-03)으로 옮겨갔다.main을 먼저 merge해 충돌을 자기 브랜치에서 해소 → PR 생성 → main 병합별도 이슈를 하나도 만들지 않았다. GitHub Issues 탭에 뜨는 숫자는 전부 열려 있는 PR이고 순수 이슈는 0건이다. 이슈 템플릿·PR 템플릿(.github/)도 쓰지 않았다. 작업 단위는 브랜치명과 커밋 메시지로 나눴고, 결정 사항은 docs/ 문서에 날짜와 함께 남기는 방식으로 대체했다. → 이 선택의 대가는 7. 회고에 적었다.
총 PR 23개 (병합 19 · 열린 PR 없음). 계정명은 Lezo-Jong=이종민, hhy0123=황하윤, arim0317-dot=신아림.
| PR | 내용 | 브랜치 | 상태 |
|---|---|---|---|
| #1 | 기획 초안 01-problem·02-workflow·03-requirements | yaru | 병합 |
| #2 · #3 | 팀/개인 기획 문서 저장 | teamshy, draft/hy-... | 열림 |
| #4 · #6 | 캐릭터 에셋·마스크 파이프라인 1차 | mg | 병합 |
| #5 | 반려 캐릭터(다마고치)·이모지 반응 | hybranch | 열림 |
| #7 · #10 | 월별 목표 설정/삭제, 홈 카테고리 % 실제 계산 | shooTbranch | 병합 |
| #8 | 성년기 코인 재작업, 눈 흰자·가방 끈 번짐 근본 수정 | petbranch | 병합 |
| #9 | 출석체크 — 7일 연속 시 코인 2배 | hybran | 병합 |
| #11 | 로그인 빈 칸 한국어 안내, 목표 금액 입력칸 강조 | hybran2 | 병합 |
| #12 | 수입 DB 연동, 프로필 사진 저장, 회원 탈퇴 | feature/income-avatar-account-deletion | 병합 |
| #13 | 지출 페이스 경고 · 저녁 리마인더 · 메모 검색 | feature/pace-warning-... | 병합 |
| #14 | 날짜/시간대 버그 3건 수정 | fix/date-timezone-bugs | 병합 |
| #15 · #20 · #21 | 펫 경제 개편, 밥 관련 버그, 시무룩 그림 재조정 | hybran3, hybran4, hybran5 | 병합 |
| #16 | README 스크린샷·기록 정정 | docs/readme-images | 열림 |
| #17 | 정기 지출 · 그룹 예산 · 영수증 원본 재확인 | shooTbranch | 병합 |
| #18 | 그룹 지출 비교표 · 온보딩 투어 · 도넛 차트 · 정렬 | feature/group-compare-... | 병합 |
| #19 | 개인 펫 밥주기 하루 1회 제한 복원 | fix/pet-feed-daily-limit | 병합 |
| #22 | 정기 지출 빈 목록 아이콘 수정 | hybran7 | 병합 |
| #23 | 개인 펫 코인·XP 지급을 원자적 RPC로 통일, 목표 정산 버그 수정 | hybran9 | 병합 |
| 팀원 | 담당 영역 | 주요 작업 | 커밋 |
|---|---|---|---|
| 이종민 (형상관리자) | 캐릭터 에셋 파이프라인 · 외부 연동 · 하네스 규칙 · 실시간 | 마스크 생성/검증 스크립트, PNG+마스크 렌더러, 네이버 CLOVA OCR 영수증 인식, 카카오 로그인, 개인 랭킹, 그룹 펫 꾸미기, 13개 테이블 실시간 동기화, CLAUDE.md·스킬 문서 5종 | 85 |
| 신아림 (PM) | 기획 종합 · 목표(퀘스트) · 그룹 예산 | 01~03 기획 초안, 월별 목표 설정/삭제, 홈 캘린더 날짜 선택 바, 비밀번호 찾기, 정기 지출, 그룹 예산, 그룹장 배지, 기획 문서 현행화 | 23 |
| 황하윤 (리서쳐) | 리서치 · 디자인 원본 · 참여 유도 · 펫 경제 | ShooT 하윤.dc.html 디자인 원본, 출석체크(7일 연속 보너스), 반려 캐릭터·이모지 반응, 수입 DB 연동, 회원 탈퇴, 펫 경제 개편, 그룹 지출 비교표·온보딩 투어·도넛 차트 | 23 |
components/screens/*.tsx)을 맡아 서로 다른 파일을 건드리게 해서 충돌 면적을 줄였다.lib/store.tsx)은 함수 단위로 나눠서 추가만 하고 기존 함수는 건드리지 않는 규칙을 뒀다.009_ ~ 020_, 총 20개)만 추가하는 방식으로 서로의 스키마 작업이 겹치지 않게 했다. 프로젝트 내내 스키마 충돌이 한 번도 없었다.main 병합 시 같은 줄이 충돌 → 나중 PR(#11)에서 한쪽을 되돌리고 하나로 합치는 커밋("목표 금액 입력칸 테두리 강조 되돌리기")을 따로 만들어 정리했다.mg·hybranch·shooTbranch가 각자 다른 펫 스펙(성장 5단계 vs 4단계, 종 선택 vs 색상 커스텀, 주간 예산 vs 월별 목표)을 구현해 충돌했다. 코드로 먼저 합치지 않고 충돌 지점 4개를 사용자에게 직접 질문해 결정한 뒤 합쳤고, 결정 내용을 docs/07-screens.md·PRD.md에 날짜와 함께 기록했다.실행 방법
npm install
npm run 87ev # http://localhost:3000
npm run 114ev:https # https://localhost:3000 (카메라 기능 테스트용 — getUserMedia는 HTTPS 필수)
.env.local): NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY, SUPABASE_SERVICE_ROLE_KEY, CLOVA_OCR_INVOKE_URL, CLOVA_OCR_SECRET_KEY, KAKAO_ADMIN_KEYsupabase/schema.sql → 002 ~ 032 순서대로 SQL Editor에서 실행 (fix_group_members_recursion.sql은 schema.sql만 실행해 둔 기존 프로젝트를 고치는 용도라 새로 세팅할 땐 건너뛴다. 033은 시연 전용이라 아래 별도 설명 참고)
019·020을 빠뜨리면 앱은 정상 동작하지만 실시간 반영만 꺼진다 — 조용히 아무 일도 안 일어나서 알아채기 어렵다. 확인 방법:select tablename from pg_publication_tables where pubname = 'supabase_realtime' and schemaname = 'public';결과가 13줄이어야 한다.
025~031은 보안 강화(REST/RPC 직접 호출로 코인·XP·그룹 권한을 조작할 수 있던 구멍 차단),032는 그 과정에서 생긴 출석체크 버그 수정이다 —032를 빠뜨리면 "출석하기"를 눌러도 코인이 들어오지 않는다.
시연에 쓰는 실제 계정과 분리된 테스트 계정이다. 비밀번호는 셋 다 공통 test123.
이 앱은 이메일로 로그인한다(별도 아이디 체계가 없다). 그래서 요청하신 아이디
test123·test1234·test12345를 그대로 쓰되 뒤에@test.com을 붙인 형태다 — 로그인 화면에는 아래 이메일을 그대로 입력하면 된다.
| 계정 | 이메일 | 권한 | 이 계정으로 확인할 수 있는 것 |
|---|---|---|---|
| 팀장(그룹장) | [email protected] | 그룹장(OWNER) | 그룹 예산 설정·수정, 그룹 이름 변경, 그룹장 위임 |
| 팀원(그룹원) | [email protected] | 그룹원(MEMBER) | 그룹 피드 조회, 본인 지출만 수정·삭제. 그룹 예산은 읽기 전용 |
| 일반 사용자 | [email protected] | 그룹 미소속 | 그룹이 없을 때의 화면 — 공유 select가 아예 안 보임(P8) |
세 계정 모두 로그인 후 바로 볼 내용이 있도록 데이터를 넣어 뒀다 — 그룹장·그룹원 계정은 강사 평가용 그룹(초대 코드 TEST01)에 함께 속해 있고 공유 지출 3건과 그룹 예산 2건이 있다.
관리자 계정은 없습니다. 이 앱의 권한은
member_roleenum의 OWNER / MEMBER 두 가지, 즉 "그룹 안에서의 역할"만 존재합니다(06-data.md E3). 앱 전체를 관리하는 관리자 개념은 기획 단계부터 범위에 없었습니다. 위 세 계정이 이 앱에서 구분 가능한 권한의 전부입니다.
권한이 서버에서 실제로 막히는지 확인한 결과 — 화면에서 숨기는 것이 아니라 Supabase RLS가 차단합니다.
| 그룹원 계정으로 시도 | 결과 |
|---|---|
| 남이 쓴 지출 수정 (P6) | 차단 |
| 본인 지출 수정 | 허용 |
| 그룹 예산 생성 (P14) | 차단 (42501) |
| 그룹 이름 변경 (P2) | 차단 |
계정 관리 스크립트 — scripts/seed-instructor-accounts.mjs. .env.local의 서비스 롤 키를 쓰므로 그 파일이 있는 PC에서만 동작한다.
| 명령 | 하는 일 |
|---|---|
node scripts/seed-instructor-accounts.mjs | 계정·그룹·샘플 데이터 생성. 여러 번 실행해도 안전하고, 이미 있으면 비밀번호만 다시 맞춘다 |
… --demo-reset | 리허설을 다시 돌릴 때. 오늘의 출석체크·밥주기 기록을 지우고 코인을 100개로 채우고 온보딩 투어가 다시 뜨게 한다. 계정·그룹·지출은 건드리지 않는다 |
… --delete | 계정·그룹·지출 전부 삭제(평가 종료 후 정리) |
돌린 뒤에는 브라우저를 새로고침해야 한다. 앱이 이 값들을 로그인·페이지 로드 시점에 읽기 때문에, 열려 있는 화면에는 바로 반영되지 않는다.
시연용 예외 — 팀장 계정만 밥주기 무제한
밥주기는 서버에서 하루 1회로 막혀 있다(pet_feedings의 (pet_id, user_id, fed_date) 유니크 제약). 그런데 발표에서 성장 4단계(알 → 유년기 → 청소년기 → 성체)를 그 자리에서 보여주려면 연속으로 먹여야 한다. 그래서 팀장 계정 하나에만 예외를 두는 SQL을 따로 준비했다.
| 파일 | 언제 실행 |
|---|---|
033_demo_unlimited_feed.sql | 발표 전 — 예외 열기 |
033_revert_demo_unlimited_feed.sql | 발표 후 — 원상복구 |
feed_pet() 안에서 그 계정(uuid 하나)일 때만 오늘 기록을 지우고 다시 넣는다.025~031 보안 강화가 막아둔 경제 조작에 예외를 일부러 하나 여는 것이다. 그래서 되돌리는 파일을 함께 뒀고, 평가가 끝나면 닫는 것을 전제로 한다.시연 순서
[?](팀이 모름)와 [제안](에이전트가 보탬)을 구분해 적었더니, 나중에 "이거 누가 정한 거였지?"로 되돌아가는 일이 없었다. 거절한 후보도 「검토했으나 제외」 표에 이유와 함께 남겨서 같은 논의를 두 번 하지 않았다.docs/06-data.md·07-screens.md·PRD.md에 날짜와 함께 남았다.| 무엇이 실패했나 | 왜 | 어떻게 고쳤나 |
|---|---|---|
| 캐릭터 색 변경 시 부위 경계에 보라색 선이 남음 | 마스크를 색 범위로 나눠 경계 픽셀이 어느 마스크에도 안 들어감 | 판정 기준을 실제 오브젝트 경계로 재작성 + "임자 없는 픽셀 0개" 자동 검증 |
| Vercel 배포가 계속 실패 | .env.local은 git에 안 올라가는데 Vercel에 환경변수를 등록하지 않음 | 4개 변수를 Production/Preview/Development 전부 체크해 등록 후 재배포(기존 배포엔 소급 적용 안 됨) |
카카오 로그인 후 localhost로 튕김 | Supabase의 Site URL이 http://localhost:3000이라, 배포 주소에서 로그인해도 거기로 돌려보냄 | Site URL을 배포 주소로 바꾸고 Redirect URLs에 https://module1-*.vercel.app/** 와일드카드 추가 |
| 월별 목표 삭제 버튼이 눌러도 안 됨 | category_goals 테이블에 DELETE RLS 정책만 빠져 있었음(RLS는 정책 없으면 기본 차단) | 010_category_goals_delete_policy.sql 추가 |
| 영수증 OCR이 자꾸 인식 실패 | 무료 커스텀 템플릿 방식은 좌표로 판정해서, 영수증이 조금만 기울거나 잘려도 매칭 실패 | 안정적인 종이 영수증만 지원 범위로 좁히고, 간편결제 캡쳐는 범위에서 제외. 인식 실패 시 수동 수정 경로를 보장 |
| 회원 탈퇴 후 카카오로 다시 로그인하면 동의 화면이 안 뜸 | 우리 DB의 계정만 지우고 카카오 쪽 연결은 안 끊었음 | 탈퇴 시 카카오 unlink API도 함께 호출(실패해도 탈퇴 자체는 진행) |
| 화면에는 규칙이 써 있는데 검사하는 코드가 없었다 — 회원가입 비밀번호 칸에 "8자 이상"이라고 적혀 있었지만 7자로도 가입됐다 | 화면 문구를 먼저 만들고 검증은 나중에 붙이려다 잊었다. 서버(Supabase) 기본 최소 길이가 6자라 서버도 안 막았고, 화면 문구만 보고 "되는 줄" 알았다 | 이메일 형식 검사와 같은 인라인 오류로 막았다. 07-screens.md에 [?]로 남아 있던 자리를 그제서야 채운 셈이다 |
| 보안 수정이 멀쩡하던 기능을 조용히 깨뜨렸다 — 출석체크를 눌러도 코인이 안 들어왔다 | 보상 계산을 서버 RPC로 옮기면서 함수 반환 컬럼 이름(checkin_date)이 테이블 컬럼과 겹쳤다. 마이그레이션 실행은 성공하고 호출할 때만 실패해서, 적용 직후엔 아무도 몰랐다 | 테이블 참조에 별칭을 붙여 고쳤다(032). 이후 임시 계정으로 주요 기능 15개를 실제로 호출해 다른 곳은 멀쩡한지 확인했다 |
| 같은 입력칸을 세 명이 같은 시각에 고침 — 9/18 14:08에 세 사람이 각자 "목표 금액 입력칸"을 수정한 커밋을 올렸다 | 브랜치는 나눴지만 화면 담당자를 정하지 않았다. "금액 입력칸이 눈에 안 띈다"는 같은 피드백을 세 명이 각자 받아 각자 고쳤다 | 21분 뒤 한 명이 되돌리는 커밋(14:29)으로 하나로 합쳤다. 이후로는 같은 화면을 한 사람이 맡도록 나눴다 |
| 타임존 버그가 1차 점검을 통과했다 — 출석 연속일수·저녁 리마인더·페이스 경고가 각각 다른 증상으로 어긋났다 | "오늘 날짜"를 모듈을 불러올 때 한 번만 고정하는 패턴이 세 곳에 복사돼 있었다. 증상이 제각각이라 처음엔 서로 다른 버그로 보였다 | 2차 점검을 따로 돌려 3건을 한 번에 찾았고, 날짜를 쓸 때마다 다시 계산하도록 통일했다 |
| 기획이 구현 중에 바뀌었다 — 모임 유형 "룸메이트"→"친구", 성장 5단계→4단계, 주간 예산→월별 목표 | 세 브랜치가 서로 다르다는 게 드러났다. 기획 문서에 적히기 전에 코드가 먼저 나간 부분이 있었다 |
CLAUDE.md나 스킬 문서에 조항으로 넣는다.console.error("[account] ...") 같은 태그 로그를 먼저 심고 재현시키면, 추측 없이 원인을 특정할 수 있다.tsc → eslint → build 통과 결과를 항상 같이 보고하게 했다.mg, hybran, hybran2)는 나중에 어떤 작업인지 추적하기 어려웠다.| 271줄 |
| PRD (종합) | 위 문서를 한 곳에 요약 — 제품 개요, 핵심 사용자 흐름, MVP/v2 기능 범위, 화면·데이터·정책 요약, 기술 스택(계획 / 실제 2열), 7일 마일스톤, 그리고 열린 이슈를 착수 우선순위로 재배열한 목록 | 204줄 |
| 저금통 펫 명세 | 펫 기능만 따로 뗀 화면·기능 명세(2026-09-15 제안 시점). 전체 개념, 펫 선택·상세·먹이주기 팝업·절약 리포트·배지·그룹 랭킹, 백엔드 참고사항, 확인 후 결정된 것과 남은 [?], 그리고 이 문서와 실제 구현이 달라진 곳 정리 | 137줄 |
| 충돌 지점 4개를 코드로 합치기 전에 팀에 물어 결정하고, 정한 내용을 날짜와 함께 기획 문서에 반영한 뒤 병합했다 |
| 공유 가계부인데 새로고침을 해야 서로가 보였다 — 초대를 받아 들어가도 멤버 목록에 자기 혼자였다 | 데이터를 로그인 직후 한 번만 읽는 구조였다. 실시간은 지출 알림 하나에만 걸려 있었고, 그마저 토스트만 띄우고 목록에는 넣지 않았다 | 참여 직후 그룹 멤버 전체를 다시 읽게 고치고, 화면이 읽는 13개 테이블을 전부 Realtime으로 구독하도록 바꿨다(019·020 마이그레이션) |