feat: 전역 API 에러 안전망 도입 및 개별 훅 에러 처리 정리#311
Conversation
* chore: PR 봇을 Slack 에서 Discord 로 이관 slack-pr-bot.yml 제거 + discord-pr-bot.yml 추가 (서버 PIKI-Server 검증본 기반). 리뷰어 멘션(initial_reviewers + requested_reviewers)·연관 이슈(close #N) 로직 동일. 클라 slack 커밋 이력(#14·#17·#18·#20)을 추적해 서버와 다른 클라 특화를 반영: - 트리거·부모 메시지 조건: ready_for_review → reopened (#17, 기존 slack 봇과 동일). - 요약 파싱 섹션명: Task → 작업 요약 (클라 PR 템플릿이 '## 작업 요약'). 클라 slack 은 두 요약 함수의 섹션명이 '작업 내용'/'작업 요약' 으로 불일치(#20 이 한쪽만 수정)해 부모 메시지 요약이 항상 비던 버그가 있었는데, 이관본은 둘 다 '작업 요약' 으로 통일해 함께 고친다. - 요약에서 중첩 리스트(' -') skip (#18). alert-direct-push job 제외(클라 범위 밖). 배포는 클라가 Vercel 이라 이 이관 범위 밖. secret(DISCORD_BOT_TOKEN 공유·DISCORD_PR_CHANNEL_ID 전용·DISCORD_USER_MAP) 설정 완료. * PR 봇 부모 메시지 라벨을 갱신 메시지와 같은 볼드·대문자 서식으로 통일 부모(최초) 메시지는 '🔥 연관 이슈'·'**branch**' 처럼 볼드 없는 소문자였고 갱신 메시지는 '🔥 **연관 이슈**'·'**Branch**' 로 달라, 첫 갱신 때 라벨 서식이 바뀌어 보였다. 부모 쪽을 갱신 쪽 서식에 맞춰 일치시킨다. * synchronize 알림의 커밋 수·최신 커밋을 페이지네이션에 견고하게 계산 PR 커밋 API 는 30개/페이지(오래된→최신 순)라 첫 페이지만 받아 length 로 세면 31개 이상 PR 에서 커밋 수가 30 으로 잘리고, 첫 페이지 .[-1] 도 최신 커밋이 아니었다. 커밋 수는 이벤트 payload 의 .pull_request.commits 로, 최신 커밋은 마지막 페이지 (per_page=1 & page=총개수)로 집어 정확하게 만든다.
* PR 봇에 상태 리액션·부모 고정·스레드 정리·라벨 표시·헬퍼 공유 반영 이관 이후 서버 봇에 쌓인 개선을 클라 봇에 맞춰 반영한다. - 상태 리액션: 부모 메시지에 열림/작업중/머지/종료를 이모지로 전환 표시(429 rate limit 재시도 포함) - 부모 고정: 열린(리뷰 대기) PR 부모를 채널 상단에 고정, 종료 시 해제 - 스레드 정리: 종료 시 스레드명에 결과 프리픽스(✅/🗑️)+archive+lock - 부모 카드에 라벨 표시(build_label_text) - find_meta 가 메타 주석을 JSON 마커로 정확히 매칭 — 파일명을 언급한 리뷰 코멘트를 집어 THREAD_ID 를 못 읽고 이후 스텝이 전부 skip 되던 버그(머지 알림 누락) 해소 - 헬퍼 4개를 $RUNNER_TEMP 공유 스크립트로 추출해 스텝 간 중복 제거(checkout 불필요) - 커밋 수는 .pull_request.commits 로 정확화 클라 적응: push 트리거·alert-direct-push 잡 제외, ready_for_review→reopened, 작업 요약 섹션 매칭+중첩 불릿 스킵, 부모 카드 라벨 서식을 갱신 카드와 통일. 최신 커밋 메시지는 contents:read 없이 동작하도록 PR commits 엔드포인트로 조회. * 재오픈된 PR 의 부모 재고정·스레드 복구 (reopened 흐름 정상화) reopened 는 메타 주석이 이미 있어 post_parent 스텝이 스킵되는데, 부모 고정·상태 복구가 그 스텝 출력에만 의존해 재오픈 시 깨졌다. reopened 는 서버 봇엔 없고 클라 트리거라, 이 흐름 버그는 클라 전용이다. - 부모 재고정: pin 스텝의 부모 id 를 post_parent → find_meta 로 폴백하고 조건도 find_meta.message_id 를 포함하도록 넓혀, 재오픈 시 상단 고정이 복구되게 한다. - 스레드 복구: 종료 시 archived·locked 로 잠그고 이름에 🗑️ 프리픽스를 다는데, 재오픈 시 되돌리는 경로가 없어 이후 synchronize 답글이 잠긴 스레드라 실패했다. reopened 에 unarchive·unlock + 이름 원복 스텝을 추가한다.
* fix: 게스트 MEMBER_ONLY 접근 시 로그인 무한 루프 수정 회원(MEMBER) 토큰일 때만 로그인 페이지를 건너뛰도록 제한. 게스트는 로그인에 남아 archive↔login 무한 루프 방지. * fix: 게스트 자동 로그인 시 현재 요청부터 token 적용되도록 수정 * refactor: 로그인 약관 안내 문구를 page로 분리 * feat: 게스트 세션 살아있는 경우 게스트 로그인 선택 시 리프레시 진행 * style: 토스트 위치 오류 수정 * feat: 게스트 로그인 redirect path가 /archive인 경우 /home으로 이동 및 안내 토스트 노출 * fix: 앱 부팅 시 refresh cookie 죽는 문제 해결 * fix: proxy에서 앱 auth token 도 처리 가능하도록 수정 * refactor: 앱 token refresh timeout 추가 * fix: 앱 토큰 만료(401) 시 WebView 쿠키도 정리 * fix: 앱 refresh 응답 snake_case 파싱 수정 * chore: proxy.ts refresh 401 임시 안전망 제거 (백엔드 rotation grace 적용) (#295) * chore: proxy.ts refresh 401 임시 안전망 제거 (백엔드 rotation grace 적용) (#295) * fix: iOS 26 Safari 노치 영역이 흰색으로 보이는 문제 수정 (#293) Co-authored-by: Jung Sun A <amber0809@naver.com> * refactor: 로그인 후 리다이렉트 로직 유틸로 추출 - 로그인 성공 후 경로 계산 중복 제거 (getPostLoginRedirectPath) * fix: 공유 위시 등록 시 refresh 401이면 죽은 토큰 정리 Share Extension이 만료된 토큰으로 재시도를 반복하지 않도록 refresh 401 시 clearTokens 호출 --------- Co-authored-by: 조영찬 <tigerbone@naver.com>
* feat: web Sentry 에러 모니터링 도입
* feat: app Sentry 에러 모니터링 도입
* feat: web/app sentry 에러 로깅 규약 추가
- app: @sentry/react-native 셋업(_layout init+wrap, metro, 플러그인, eas 환경별 주입)
- 공용 captureError 유틸(web/app) — 태그/컨텍스트 일관 부착
- API 5xx·네트워크 에러 중앙 수집(axios 인터셉터 / app fetch)
- 유저 식별 setUser(id), 세션 만료 시 해제
- error.tsx 캡처, ignoreErrors 노이즈 필터
- app WebView onError/onHttpError, 백그라운드 FCM 핸들러 수집
* test: 에러 검증용 테스트 페이지 생성
* fix: SENTRY_AUTH_TOKEN turbo passThroughEnv 추가 (소스맵 업로드)
* feat: Session Replay 마스킹 완화 (이메일만 마스킹, 나머지 노출)
* feat: API 에러 리포트 제목을 'API {status} {method} {path}' 형식으로 개선
* Revert "test: 에러 검증용 테스트 페이지 생성"
This reverts commit 87f9e53.
* fix: 소셜 로그인 5xx 응답 JSON 파싱 실패 시 Sentry 수집 누락 수정
* fix: 로그아웃 시 Sentry 유저 컨텍스트 해제
* fix: Session Replay 타이핑 입력창만 마스킹 (maskAllInputs)
* fix: 소셜 로그인 2xx 응답 본문 파싱 실패도 Sentry 수집
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Discord 스레드 연동용 메타데이터입니다. discord-pr-bot 워크플로가 자동 생성하며, 수정·삭제하면 PR 과 Discord 알림 연동이 끊깁니다. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
💤 Files with no reviewable changes (1)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthrough전역 mutation/query 에러 처리와 공통 메시지 변환이 추가되었고, 개별 mutation 훅의 500 전용·빈 에러 처리가 정리되었다. 에러 정책, API 상태 감사, 코드 오너십 문서도 추가되었다. Changes전역 에러 안전망과 개별 훅 정리
에러 정책·감사·오너십 문서
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Mutation as Mutation
participant QueryClient as QueryClient
participant Toast as toast
participant Sentry as Sentry
Mutation->>QueryClient: 에러 전달
QueryClient->>QueryClient: HTTP 상태 및 개별 onError 확인
alt 5xx 또는 네트워크 오류
QueryClient->>Toast: getApiErrorMessage(error) 표시
QueryClient->>Sentry: captureException(error)
else 4xx 및 개별 onError 없음
QueryClient->>Toast: 공통 에러 메시지 표시
QueryClient->>Sentry: captureException(error)
else 4xx 및 개별 onError 있음
QueryClient-->>Mutation: 개별 에러 처리에 위임
end
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/spec/ownership.md`:
- Around line 16-21: 소셜로그인 담당 구분이 두 군데에서 서로 다르게 적혀 있어 라우팅 기준이 혼동됩니다.
ownership.md의 “위시 + 소셜로그인” 범위와 `/login`, `/auth/callback/[provider]`가 포함된 페이지 표를
하나의 기준으로 통일하고, `소영` 또는 `선아/공동 리뷰` 중 실제 담당 원칙에 맞게 한쪽으로 정리해 중복 표기를 제거하세요. `위시 +
소셜로그인`, `/login`, `/auth/callback/[provider]`, `토큰 인프라 · 계정 · 플랫폼 + 공동 리뷰` 항목이
같은 책임 체계를 가리키도록 문구를 맞추면 됩니다.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 7555d5ae-15df-4ef6-aefa-5862c48c69db
📒 Files selected for processing (11)
apps/web/src/app/archive/_hooks/useDeleteWishes.tsapps/web/src/app/archive/wish/[id]/_hooks/useDeleteWish.tsapps/web/src/app/archive/wish/[id]/_hooks/usePatchWish.tsapps/web/src/app/tournament/[id]/_common/_hooks/useDeleteTournamentItem.tsapps/web/src/hooks/useDeleteTournament.tsapps/web/src/hooks/usePostTournamentOCR.tsapps/web/src/utils/getApiErrorMessage.tsapps/web/src/utils/queryClient.tsdocs/spec/api-status-audit.mddocs/spec/error-handling-policy.mddocs/spec/ownership.md
💤 Files with no reviewable changes (5)
- apps/web/src/app/tournament/[id]/_common/_hooks/useDeleteTournamentItem.ts
- apps/web/src/hooks/usePostTournamentOCR.ts
- apps/web/src/hooks/useDeleteTournament.ts
- apps/web/src/app/archive/wish/[id]/_hooks/usePatchWish.ts
- apps/web/src/app/archive/_hooks/useDeleteWishes.ts
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/web/src/app/archive/wish/[id]/_hooks/useDeleteWish.ts (1)
22-37: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win403/404 외 4xx가 처리되지 않아 조용히 삼켜집니다.
onError가 403/404만 토스트를 띄우므로, 400·409·422 등 다른 4xx가 발생하면 로컬도 무시하고,queryClient.ts의 전역mutationCache.onError도mutation.options.onError가 존재한다는 이유만으로 양보(return)합니다. 결과적으로 해당 실패는 사용자에게 전혀 표시되지 않습니다.401은 전역 인터셉터가, 5xx는 전역 mutationCache가 전담하므로, 이 훅에서는 그 외 모든 4xx를 커버하도록 조건을 넓히는 것이 안전합니다.
🐛 제안: 도달 가능한 4xx 전체를 커버
onError: error => { if (!isAxiosError<ApiErrorResponseT>(error) || !error.response) return; const { status, data: { detail }, } = error.response; + /** 401은 전역 인터셉터, 5xx는 전역 mutationCache가 전담 */ + if (status === 401 || status >= 500) return; + const clientErrorMessage = detail ?? '요청을 처리하지 못했습니다.'; - /** - * 403: 위시 삭제 권한 없음 - * 404: 위시 존재하지 않음 - */ - if (status === 403 || status === 404) toast.error(clientErrorMessage); + toast.error(clientErrorMessage); },🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/app/archive/wish/`[id]/_hooks/useDeleteWish.ts around lines 22 - 37, The local error handling in useDeleteWish only surfaces 403 and 404, so other reachable 4xx responses are dropped before the global mutation handler can show anything. Update the onError logic in useDeleteWish to treat all non-401 4xx responses as user-facing errors by broadening the status check (while still letting 401 and 5xx remain handled elsewhere), and keep using the existing clientErrorMessage derived from error.response.data.detail.
🧹 Nitpick comments (1)
apps/web/src/utils/queryClient.ts (1)
34-38: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value쿼리 4xx 에러도 무조건 Sentry로 전송됩니다.
queryCache.onError는 상태코드 구분 없이 모든 쿼리 실패를 캡처합니다. 404 등 예상 가능한 클라이언트 에러까지 Sentry에 누적되면 노이즈가 커질 수 있습니다. 5xx·네트워크 에러만 캡처하도록 제한하는 것을 고려해 보세요.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/utils/queryClient.ts` around lines 34 - 38, The QueryCache onError handler in queryClient is sending every failed query to Sentry, including expected 4xx responses. Update the onError logic in queryCache to inspect the error before calling Sentry.captureException, and only capture 5xx or network-related failures while skipping expected client errors like 404. Use the existing QueryCache setup in queryClient to keep the change localized and preserve all other behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/spec/api-status-audit.md`:
- Around line 18-33: 현재 표의 “무피드백/조용히 삼킴” 분류가 MutationCache.onError 전역 안전망을 반영하지
않아 과장되어 보입니다. `useDeleteTournament.ts`, `useDeleteWishes.ts`,
`usePostWishRefresh.ts`, `usePostRecordMatch`, `usePostGuestLogin`, `getAuthUrl`
사용부, `usePostNotificationsRead`, `useGetNotifications`, `useFcmTokenSync` 등은 전부
“사용자 피드백 완전 부재”가 아니라 “로컬 맞춤 UX 없음”으로 재분류하고, `MutationCache.onError`가 보장하는 최소
토스트가 있는 케이스와 진짜로 전역 처리까지 없는 케이스를 분리해 문구를 정리하세요. 또한 `usePostTournamentStart`,
`usePostCreateTournament`, `usePostWishOCR`, `usePatchWish`,
`usePostTournamentOCR`, `usePatchTournamentItem`의 502 미대응은 별도 항목으로 유지하되, 실제로 전역
onError가 커버하는지 여부에 맞춰 설명을 맞추고, 미구현 엔드포인트와 Dead code는 현재 상태를 그대로 두되 “호출 코드 없음/소비처
없음”으로 구분해 주세요.
In `@docs/spec/error-handling-policy.md`:
- Around line 20-29: Update the fenced example block in error-handling-policy so
it uses an explicit language tag instead of an unlabeled fence, which is
triggering markdownlint MD040. Locate the first fenced block in the document and
change it to a typed fence such as ts or text so the markdown validator
recognizes it consistently. Keep the rest of the content unchanged.
In `@docs/spec/ownership.md`:
- Around line 102-105: The `CODEOWNERS` guidance in the ownership spec describes
behavior incorrectly. Update the wording in the ownership section to state that
`CODEOWNERS` only auto-assigns reviewers, and that approval enforcement comes
from branch protection with “Require review from Code Owners”; also change the
precedence rule to reflect that `CODEOWNERS` uses the last matching pattern, not
the most specific path. Reference the ownership bullets and the `CODEOWNERS`
examples so the text matches actual behavior.
---
Outside diff comments:
In `@apps/web/src/app/archive/wish/`[id]/_hooks/useDeleteWish.ts:
- Around line 22-37: The local error handling in useDeleteWish only surfaces 403
and 404, so other reachable 4xx responses are dropped before the global mutation
handler can show anything. Update the onError logic in useDeleteWish to treat
all non-401 4xx responses as user-facing errors by broadening the status check
(while still letting 401 and 5xx remain handled elsewhere), and keep using the
existing clientErrorMessage derived from error.response.data.detail.
---
Nitpick comments:
In `@apps/web/src/utils/queryClient.ts`:
- Around line 34-38: The QueryCache onError handler in queryClient is sending
every failed query to Sentry, including expected 4xx responses. Update the
onError logic in queryCache to inspect the error before calling
Sentry.captureException, and only capture 5xx or network-related failures while
skipping expected client errors like 404. Use the existing QueryCache setup in
queryClient to keep the change localized and preserve all other behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 443207f9-68b9-437a-b28d-212840fb39e7
📒 Files selected for processing (11)
apps/web/src/app/archive/_hooks/useDeleteWishes.tsapps/web/src/app/archive/wish/[id]/_hooks/useDeleteWish.tsapps/web/src/app/archive/wish/[id]/_hooks/usePatchWish.tsapps/web/src/app/tournament/[id]/_common/_hooks/useDeleteTournamentItem.tsapps/web/src/hooks/useDeleteTournament.tsapps/web/src/hooks/usePostTournamentOCR.tsapps/web/src/utils/getApiErrorMessage.tsapps/web/src/utils/queryClient.tsdocs/spec/api-status-audit.mddocs/spec/error-handling-policy.mddocs/spec/ownership.md
💤 Files with no reviewable changes (5)
- apps/web/src/hooks/usePostTournamentOCR.ts
- apps/web/src/app/archive/_hooks/useDeleteWishes.ts
- apps/web/src/hooks/useDeleteTournament.ts
- apps/web/src/app/archive/wish/[id]/_hooks/usePatchWish.ts
- apps/web/src/app/tournament/[id]/_common/_hooks/useDeleteTournamentItem.ts
* docs: 역할 분배 문서 추가 * docs: 현재 api 에러 대응 현황 문서 추가 * docs: 에러 처리 정책 문서 추가 * feat: 공통 API 에러 메시지 유틸 추가 * feat: 전역 mutation/query 에러 안전망 도입 * refactor: 비어있는 개별 onError 삭제 (전역 안전망 위임) * refactor: 개별 훅 5xx 토스트 분기 제거 (이중 토스트 방지) * PR 봇을 Slack 에서 Discord 로 이관 (#308) * chore: PR 봇을 Slack 에서 Discord 로 이관 slack-pr-bot.yml 제거 + discord-pr-bot.yml 추가 (서버 PIKI-Server 검증본 기반). 리뷰어 멘션(initial_reviewers + requested_reviewers)·연관 이슈(close #N) 로직 동일. 클라 slack 커밋 이력(#14·#17·#18·#20)을 추적해 서버와 다른 클라 특화를 반영: - 트리거·부모 메시지 조건: ready_for_review → reopened (#17, 기존 slack 봇과 동일). - 요약 파싱 섹션명: Task → 작업 요약 (클라 PR 템플릿이 '## 작업 요약'). 클라 slack 은 두 요약 함수의 섹션명이 '작업 내용'/'작업 요약' 으로 불일치(#20 이 한쪽만 수정)해 부모 메시지 요약이 항상 비던 버그가 있었는데, 이관본은 둘 다 '작업 요약' 으로 통일해 함께 고친다. - 요약에서 중첩 리스트(' -') skip (#18). alert-direct-push job 제외(클라 범위 밖). 배포는 클라가 Vercel 이라 이 이관 범위 밖. secret(DISCORD_BOT_TOKEN 공유·DISCORD_PR_CHANNEL_ID 전용·DISCORD_USER_MAP) 설정 완료. * PR 봇 부모 메시지 라벨을 갱신 메시지와 같은 볼드·대문자 서식으로 통일 부모(최초) 메시지는 '🔥 연관 이슈'·'**branch**' 처럼 볼드 없는 소문자였고 갱신 메시지는 '🔥 **연관 이슈**'·'**Branch**' 로 달라, 첫 갱신 때 라벨 서식이 바뀌어 보였다. 부모 쪽을 갱신 쪽 서식에 맞춰 일치시킨다. * synchronize 알림의 커밋 수·최신 커밋을 페이지네이션에 견고하게 계산 PR 커밋 API 는 30개/페이지(오래된→최신 순)라 첫 페이지만 받아 length 로 세면 31개 이상 PR 에서 커밋 수가 30 으로 잘리고, 첫 페이지 .[-1] 도 최신 커밋이 아니었다. 커밋 수는 이벤트 payload 의 .pull_request.commits 로, 최신 커밋은 마지막 페이지 (per_page=1 & page=총개수)로 집어 정확하게 만든다. * PR 봇 서버 개선 반영 (상태 리액션·부모 고정·스레드 정리·라벨·헬퍼 공유) (#310) * PR 봇에 상태 리액션·부모 고정·스레드 정리·라벨 표시·헬퍼 공유 반영 이관 이후 서버 봇에 쌓인 개선을 클라 봇에 맞춰 반영한다. - 상태 리액션: 부모 메시지에 열림/작업중/머지/종료를 이모지로 전환 표시(429 rate limit 재시도 포함) - 부모 고정: 열린(리뷰 대기) PR 부모를 채널 상단에 고정, 종료 시 해제 - 스레드 정리: 종료 시 스레드명에 결과 프리픽스(✅/🗑️)+archive+lock - 부모 카드에 라벨 표시(build_label_text) - find_meta 가 메타 주석을 JSON 마커로 정확히 매칭 — 파일명을 언급한 리뷰 코멘트를 집어 THREAD_ID 를 못 읽고 이후 스텝이 전부 skip 되던 버그(머지 알림 누락) 해소 - 헬퍼 4개를 $RUNNER_TEMP 공유 스크립트로 추출해 스텝 간 중복 제거(checkout 불필요) - 커밋 수는 .pull_request.commits 로 정확화 클라 적응: push 트리거·alert-direct-push 잡 제외, ready_for_review→reopened, 작업 요약 섹션 매칭+중첩 불릿 스킵, 부모 카드 라벨 서식을 갱신 카드와 통일. 최신 커밋 메시지는 contents:read 없이 동작하도록 PR commits 엔드포인트로 조회. * 재오픈된 PR 의 부모 재고정·스레드 복구 (reopened 흐름 정상화) reopened 는 메타 주석이 이미 있어 post_parent 스텝이 스킵되는데, 부모 고정·상태 복구가 그 스텝 출력에만 의존해 재오픈 시 깨졌다. reopened 는 서버 봇엔 없고 클라 트리거라, 이 흐름 버그는 클라 전용이다. - 부모 재고정: pin 스텝의 부모 id 를 post_parent → find_meta 로 폴백하고 조건도 find_meta.message_id 를 포함하도록 넓혀, 재오픈 시 상단 고정이 복구되게 한다. - 스레드 복구: 종료 시 archived·locked 로 잠그고 이름에 🗑️ 프리픽스를 다는데, 재오픈 시 되돌리는 경로가 없어 이후 synchronize 답글이 잠긴 스레드라 실패했다. reopened 에 unarchive·unlock + 이름 원복 스텝을 추가한다. * fix: 게스트 인증 플로우 버그 2건 수정 + 관련 UX 개선 (#291) * fix: 게스트 MEMBER_ONLY 접근 시 로그인 무한 루프 수정 회원(MEMBER) 토큰일 때만 로그인 페이지를 건너뛰도록 제한. 게스트는 로그인에 남아 archive↔login 무한 루프 방지. * fix: 게스트 자동 로그인 시 현재 요청부터 token 적용되도록 수정 * refactor: 로그인 약관 안내 문구를 page로 분리 * feat: 게스트 세션 살아있는 경우 게스트 로그인 선택 시 리프레시 진행 * style: 토스트 위치 오류 수정 * feat: 게스트 로그인 redirect path가 /archive인 경우 /home으로 이동 및 안내 토스트 노출 * fix: 앱 부팅 시 refresh cookie 죽는 문제 해결 * fix: proxy에서 앱 auth token 도 처리 가능하도록 수정 * refactor: 앱 token refresh timeout 추가 * fix: 앱 토큰 만료(401) 시 WebView 쿠키도 정리 * fix: 앱 refresh 응답 snake_case 파싱 수정 * chore: proxy.ts refresh 401 임시 안전망 제거 (백엔드 rotation grace 적용) (#295) * chore: proxy.ts refresh 401 임시 안전망 제거 (백엔드 rotation grace 적용) (#295) * fix: iOS 26 Safari 노치 영역이 흰색으로 보이는 문제 수정 (#293) Co-authored-by: Jung Sun A <amber0809@naver.com> * refactor: 로그인 후 리다이렉트 로직 유틸로 추출 - 로그인 성공 후 경로 계산 중복 제거 (getPostLoginRedirectPath) * fix: 공유 위시 등록 시 refresh 401이면 죽은 토큰 정리 Share Extension이 만료된 토큰으로 재시도를 반복하지 않도록 refresh 401 시 clearTokens 호출 --------- Co-authored-by: 조영찬 <tigerbone@naver.com> * feat: Sentry 에러 모니터링 도입 (#296) * feat: web Sentry 에러 모니터링 도입 * feat: app Sentry 에러 모니터링 도입 * feat: web/app sentry 에러 로깅 규약 추가 - app: @sentry/react-native 셋업(_layout init+wrap, metro, 플러그인, eas 환경별 주입) - 공용 captureError 유틸(web/app) — 태그/컨텍스트 일관 부착 - API 5xx·네트워크 에러 중앙 수집(axios 인터셉터 / app fetch) - 유저 식별 setUser(id), 세션 만료 시 해제 - error.tsx 캡처, ignoreErrors 노이즈 필터 - app WebView onError/onHttpError, 백그라운드 FCM 핸들러 수집 * test: 에러 검증용 테스트 페이지 생성 * fix: SENTRY_AUTH_TOKEN turbo passThroughEnv 추가 (소스맵 업로드) * feat: Session Replay 마스킹 완화 (이메일만 마스킹, 나머지 노출) * feat: API 에러 리포트 제목을 'API {status} {method} {path}' 형식으로 개선 * Revert "test: 에러 검증용 테스트 페이지 생성" This reverts commit 87f9e53. * fix: 소셜 로그인 5xx 응답 JSON 파싱 실패 시 Sentry 수집 누락 수정 * fix: 로그아웃 시 Sentry 유저 컨텍스트 해제 * fix: Session Replay 타이핑 입력창만 마스킹 (maskAllInputs) * fix: 소셜 로그인 2xx 응답 본문 파싱 실패도 Sentry 수집 * feat: mutation 오류 발생 시 Sentry 로깅 추가 * docs: 역할정리 수정 * docs: 역할 관련 문서 업데이트 --------- Co-authored-by: sevineleven <117634128+sevineleven@users.noreply.github.com> Co-authored-by: 조영찬 <tigerbone@naver.com>
* chore: iOS Smart Banner 설정 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: iOS Universal Link 설정 및 딥링크 라우팅 확장 - AASA 파일 추가 (콜백/api 경로는 exclude) - iOS associatedDomains 설정 - Universal Link/Smart Banner app-argument의 https URL을 WebView 경로로 라우팅 * feat: android app link 관련 config 추가 * chore: proxy.ts refresh 401 임시 안전망 제거 (백엔드 rotation grace 적용) (#295) * fix: iOS 26 Safari 노치 영역이 흰색으로 보이는 문제 수정 (#293) Co-authored-by: Jung Sun A <amber0809@naver.com> * PR 봇을 Slack 에서 Discord 로 이관 (#308) * chore: PR 봇을 Slack 에서 Discord 로 이관 slack-pr-bot.yml 제거 + discord-pr-bot.yml 추가 (서버 PIKI-Server 검증본 기반). 리뷰어 멘션(initial_reviewers + requested_reviewers)·연관 이슈(close #N) 로직 동일. 클라 slack 커밋 이력(#14·#17·#18·#20)을 추적해 서버와 다른 클라 특화를 반영: - 트리거·부모 메시지 조건: ready_for_review → reopened (#17, 기존 slack 봇과 동일). - 요약 파싱 섹션명: Task → 작업 요약 (클라 PR 템플릿이 '## 작업 요약'). 클라 slack 은 두 요약 함수의 섹션명이 '작업 내용'/'작업 요약' 으로 불일치(#20 이 한쪽만 수정)해 부모 메시지 요약이 항상 비던 버그가 있었는데, 이관본은 둘 다 '작업 요약' 으로 통일해 함께 고친다. - 요약에서 중첩 리스트(' -') skip (#18). alert-direct-push job 제외(클라 범위 밖). 배포는 클라가 Vercel 이라 이 이관 범위 밖. secret(DISCORD_BOT_TOKEN 공유·DISCORD_PR_CHANNEL_ID 전용·DISCORD_USER_MAP) 설정 완료. * PR 봇 부모 메시지 라벨을 갱신 메시지와 같은 볼드·대문자 서식으로 통일 부모(최초) 메시지는 '🔥 연관 이슈'·'**branch**' 처럼 볼드 없는 소문자였고 갱신 메시지는 '🔥 **연관 이슈**'·'**Branch**' 로 달라, 첫 갱신 때 라벨 서식이 바뀌어 보였다. 부모 쪽을 갱신 쪽 서식에 맞춰 일치시킨다. * synchronize 알림의 커밋 수·최신 커밋을 페이지네이션에 견고하게 계산 PR 커밋 API 는 30개/페이지(오래된→최신 순)라 첫 페이지만 받아 length 로 세면 31개 이상 PR 에서 커밋 수가 30 으로 잘리고, 첫 페이지 .[-1] 도 최신 커밋이 아니었다. 커밋 수는 이벤트 payload 의 .pull_request.commits 로, 최신 커밋은 마지막 페이지 (per_page=1 & page=총개수)로 집어 정확하게 만든다. * PR 봇 서버 개선 반영 (상태 리액션·부모 고정·스레드 정리·라벨·헬퍼 공유) (#310) * PR 봇에 상태 리액션·부모 고정·스레드 정리·라벨 표시·헬퍼 공유 반영 이관 이후 서버 봇에 쌓인 개선을 클라 봇에 맞춰 반영한다. - 상태 리액션: 부모 메시지에 열림/작업중/머지/종료를 이모지로 전환 표시(429 rate limit 재시도 포함) - 부모 고정: 열린(리뷰 대기) PR 부모를 채널 상단에 고정, 종료 시 해제 - 스레드 정리: 종료 시 스레드명에 결과 프리픽스(✅/🗑️)+archive+lock - 부모 카드에 라벨 표시(build_label_text) - find_meta 가 메타 주석을 JSON 마커로 정확히 매칭 — 파일명을 언급한 리뷰 코멘트를 집어 THREAD_ID 를 못 읽고 이후 스텝이 전부 skip 되던 버그(머지 알림 누락) 해소 - 헬퍼 4개를 $RUNNER_TEMP 공유 스크립트로 추출해 스텝 간 중복 제거(checkout 불필요) - 커밋 수는 .pull_request.commits 로 정확화 클라 적응: push 트리거·alert-direct-push 잡 제외, ready_for_review→reopened, 작업 요약 섹션 매칭+중첩 불릿 스킵, 부모 카드 라벨 서식을 갱신 카드와 통일. 최신 커밋 메시지는 contents:read 없이 동작하도록 PR commits 엔드포인트로 조회. * 재오픈된 PR 의 부모 재고정·스레드 복구 (reopened 흐름 정상화) reopened 는 메타 주석이 이미 있어 post_parent 스텝이 스킵되는데, 부모 고정·상태 복구가 그 스텝 출력에만 의존해 재오픈 시 깨졌다. reopened 는 서버 봇엔 없고 클라 트리거라, 이 흐름 버그는 클라 전용이다. - 부모 재고정: pin 스텝의 부모 id 를 post_parent → find_meta 로 폴백하고 조건도 find_meta.message_id 를 포함하도록 넓혀, 재오픈 시 상단 고정이 복구되게 한다. - 스레드 복구: 종료 시 archived·locked 로 잠그고 이름에 🗑️ 프리픽스를 다는데, 재오픈 시 되돌리는 경로가 없어 이후 synchronize 답글이 잠긴 스레드라 실패했다. reopened 에 unarchive·unlock + 이름 원복 스텝을 추가한다. * fix: 게스트 인증 플로우 버그 2건 수정 + 관련 UX 개선 (#291) * fix: 게스트 MEMBER_ONLY 접근 시 로그인 무한 루프 수정 회원(MEMBER) 토큰일 때만 로그인 페이지를 건너뛰도록 제한. 게스트는 로그인에 남아 archive↔login 무한 루프 방지. * fix: 게스트 자동 로그인 시 현재 요청부터 token 적용되도록 수정 * refactor: 로그인 약관 안내 문구를 page로 분리 * feat: 게스트 세션 살아있는 경우 게스트 로그인 선택 시 리프레시 진행 * style: 토스트 위치 오류 수정 * feat: 게스트 로그인 redirect path가 /archive인 경우 /home으로 이동 및 안내 토스트 노출 * fix: 앱 부팅 시 refresh cookie 죽는 문제 해결 * fix: proxy에서 앱 auth token 도 처리 가능하도록 수정 * refactor: 앱 token refresh timeout 추가 * fix: 앱 토큰 만료(401) 시 WebView 쿠키도 정리 * fix: 앱 refresh 응답 snake_case 파싱 수정 * chore: proxy.ts refresh 401 임시 안전망 제거 (백엔드 rotation grace 적용) (#295) * chore: proxy.ts refresh 401 임시 안전망 제거 (백엔드 rotation grace 적용) (#295) * fix: iOS 26 Safari 노치 영역이 흰색으로 보이는 문제 수정 (#293) Co-authored-by: Jung Sun A <amber0809@naver.com> * refactor: 로그인 후 리다이렉트 로직 유틸로 추출 - 로그인 성공 후 경로 계산 중복 제거 (getPostLoginRedirectPath) * fix: 공유 위시 등록 시 refresh 401이면 죽은 토큰 정리 Share Extension이 만료된 토큰으로 재시도를 반복하지 않도록 refresh 401 시 clearTokens 호출 --------- Co-authored-by: 조영찬 <tigerbone@naver.com> * feat: Sentry 에러 모니터링 도입 (#296) * feat: web Sentry 에러 모니터링 도입 * feat: app Sentry 에러 모니터링 도입 * feat: web/app sentry 에러 로깅 규약 추가 - app: @sentry/react-native 셋업(_layout init+wrap, metro, 플러그인, eas 환경별 주입) - 공용 captureError 유틸(web/app) — 태그/컨텍스트 일관 부착 - API 5xx·네트워크 에러 중앙 수집(axios 인터셉터 / app fetch) - 유저 식별 setUser(id), 세션 만료 시 해제 - error.tsx 캡처, ignoreErrors 노이즈 필터 - app WebView onError/onHttpError, 백그라운드 FCM 핸들러 수집 * test: 에러 검증용 테스트 페이지 생성 * fix: SENTRY_AUTH_TOKEN turbo passThroughEnv 추가 (소스맵 업로드) * feat: Session Replay 마스킹 완화 (이메일만 마스킹, 나머지 노출) * feat: API 에러 리포트 제목을 'API {status} {method} {path}' 형식으로 개선 * Revert "test: 에러 검증용 테스트 페이지 생성" This reverts commit 87f9e53. * fix: 소셜 로그인 5xx 응답 JSON 파싱 실패 시 Sentry 수집 누락 수정 * fix: 로그아웃 시 Sentry 유저 컨텍스트 해제 * fix: Session Replay 타이핑 입력창만 마스킹 (maskAllInputs) * fix: 소셜 로그인 2xx 응답 본문 파싱 실패도 Sentry 수집 * fix: 페이지별 토스트 위치 커스터마이즈 (탭바 페이지 토스트 겹침 수정) (#309) * feat: 토스트 offset 페이지별 override 메커니즘 추가 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: 홈 탭바 위로 토스트 위치 조정 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: 보관 페이지 하단 바 위로 토스트 위치 조정 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore: 토스트 offset 수치 조정 * refactor: 토스트 offset zustand 스토어를 CSS :has() 마커 방식으로 대체 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * feat: 딥링크 전환 로딩 오버레이 추가 * feat: 앱 링크 접속시 warm start 기능 추가 * PR 봇 스레드를 팀 전원이 볼 수 있게 (스레드 멤버 자동 추가) (#313) * PR 봇 스레드에 팀원 자동 추가로 팀 전원 사이드바 노출 Discord 공개 스레드는 멤버(생성자·초대·멘션된 사람)만 사이드바에 뜬다. 부모 카드가 작성자만 @멘션해 작성자만 자기 PR 스레드가 보이고 남의 스레드는 안 떴다. - 스레드 생성 직후 DISCORD_USER_MAP 의 팀원 전원을 thread-members 로 추가해 새 PR 스레드가 팀 전원 사이드바에 뜨게 한다(멘션과 달리 조용히 목록에만 올림). - 이 변경 이전 열린 PR 스레드용으로 backfill-thread-members 잡을 추가한다 (workflow_dispatch 수동 실행). notify-discord 는 pull_request 로 가드해 dispatch 시엔 안 돈다. * 연관 이슈 링크의 Discord 임베드 카드 억제 부모 카드의 연관 이슈 링크가 GitHub 임베드 카드로 커지게 떠서 본문(작업 요약 등)을 아래로 밀어냈다. 이슈 URL 을 <> 로 감싸 임베드만 억제하고 클릭 링크는 유지한다. PR 타이틀 링크는 그대로 둬 PR 카드는 계속 뜬다. * 작업 요약 추출이 STAR 의 Task 섹션도 인식 FE 팀 PR 은 ## 작업 요약, 서버 STAR 로 쓴 PR 은 ## Task 를 쓴다. build_summary 가 작업 요약만 찾아 STAR PR 은 '요약 없음'이 됐다. 두 섹션명을 모두 인식하게 해 어느 관례로 쓰든 요약이 채워지게 한다. * 작업 요약의 Task 섹션 인식 제거 FE 팀은 ## 작업 요약을 쓰고 봇이 이미 이를 매칭하므로, STAR 의 ## Task 인식 추가는 불필요해 되돌린다. 요약은 PR 본문에 ## 작업 요약 을 두는 팀 관례로 채운다. * PR 봇 재싱크: 머지 스레드 잠금 해제 + 종합 백필 (서버 #703 반영) (#315) 서버 봇(#703)과 갈라진 두 가지를 클라에도 반영해 동작을 일치시킨다. - 머지 시 close 정리에서 locked 제거(archived 만) — 닫히되 글을 쓸 수 있게(archived 만이라 글을 쓰면 다시 열림). 머지된 PR 스레드가 잠겨 글을 못 쓰던 문제 해소. - 백필 잡을 종합형(backfill-threads)으로 교체: 열린 PR→팀원 추가+열림, 머지 PR→✅+닫힘, 미머지 닫힘→🗑️+닫힘. 기존엔 열린 스레드 팀원 추가만 했다. 과거 find_meta 버그로 안 닫힌 스레드까지 소급 정리(멱등). * refactor: 링크 입력창 모바일 키보드를 일반 텍스트 키보드로 변경 (#325) * feat: 전역 API 에러 안전망 도입 및 개별 훅 에러 처리 정리 (#311) * docs: 역할 분배 문서 추가 * docs: 현재 api 에러 대응 현황 문서 추가 * docs: 에러 처리 정책 문서 추가 * feat: 공통 API 에러 메시지 유틸 추가 * feat: 전역 mutation/query 에러 안전망 도입 * refactor: 비어있는 개별 onError 삭제 (전역 안전망 위임) * refactor: 개별 훅 5xx 토스트 분기 제거 (이중 토스트 방지) * PR 봇을 Slack 에서 Discord 로 이관 (#308) * chore: PR 봇을 Slack 에서 Discord 로 이관 slack-pr-bot.yml 제거 + discord-pr-bot.yml 추가 (서버 PIKI-Server 검증본 기반). 리뷰어 멘션(initial_reviewers + requested_reviewers)·연관 이슈(close #N) 로직 동일. 클라 slack 커밋 이력(#14·#17·#18·#20)을 추적해 서버와 다른 클라 특화를 반영: - 트리거·부모 메시지 조건: ready_for_review → reopened (#17, 기존 slack 봇과 동일). - 요약 파싱 섹션명: Task → 작업 요약 (클라 PR 템플릿이 '## 작업 요약'). 클라 slack 은 두 요약 함수의 섹션명이 '작업 내용'/'작업 요약' 으로 불일치(#20 이 한쪽만 수정)해 부모 메시지 요약이 항상 비던 버그가 있었는데, 이관본은 둘 다 '작업 요약' 으로 통일해 함께 고친다. - 요약에서 중첩 리스트(' -') skip (#18). alert-direct-push job 제외(클라 범위 밖). 배포는 클라가 Vercel 이라 이 이관 범위 밖. secret(DISCORD_BOT_TOKEN 공유·DISCORD_PR_CHANNEL_ID 전용·DISCORD_USER_MAP) 설정 완료. * PR 봇 부모 메시지 라벨을 갱신 메시지와 같은 볼드·대문자 서식으로 통일 부모(최초) 메시지는 '🔥 연관 이슈'·'**branch**' 처럼 볼드 없는 소문자였고 갱신 메시지는 '🔥 **연관 이슈**'·'**Branch**' 로 달라, 첫 갱신 때 라벨 서식이 바뀌어 보였다. 부모 쪽을 갱신 쪽 서식에 맞춰 일치시킨다. * synchronize 알림의 커밋 수·최신 커밋을 페이지네이션에 견고하게 계산 PR 커밋 API 는 30개/페이지(오래된→최신 순)라 첫 페이지만 받아 length 로 세면 31개 이상 PR 에서 커밋 수가 30 으로 잘리고, 첫 페이지 .[-1] 도 최신 커밋이 아니었다. 커밋 수는 이벤트 payload 의 .pull_request.commits 로, 최신 커밋은 마지막 페이지 (per_page=1 & page=총개수)로 집어 정확하게 만든다. * PR 봇 서버 개선 반영 (상태 리액션·부모 고정·스레드 정리·라벨·헬퍼 공유) (#310) * PR 봇에 상태 리액션·부모 고정·스레드 정리·라벨 표시·헬퍼 공유 반영 이관 이후 서버 봇에 쌓인 개선을 클라 봇에 맞춰 반영한다. - 상태 리액션: 부모 메시지에 열림/작업중/머지/종료를 이모지로 전환 표시(429 rate limit 재시도 포함) - 부모 고정: 열린(리뷰 대기) PR 부모를 채널 상단에 고정, 종료 시 해제 - 스레드 정리: 종료 시 스레드명에 결과 프리픽스(✅/🗑️)+archive+lock - 부모 카드에 라벨 표시(build_label_text) - find_meta 가 메타 주석을 JSON 마커로 정확히 매칭 — 파일명을 언급한 리뷰 코멘트를 집어 THREAD_ID 를 못 읽고 이후 스텝이 전부 skip 되던 버그(머지 알림 누락) 해소 - 헬퍼 4개를 $RUNNER_TEMP 공유 스크립트로 추출해 스텝 간 중복 제거(checkout 불필요) - 커밋 수는 .pull_request.commits 로 정확화 클라 적응: push 트리거·alert-direct-push 잡 제외, ready_for_review→reopened, 작업 요약 섹션 매칭+중첩 불릿 스킵, 부모 카드 라벨 서식을 갱신 카드와 통일. 최신 커밋 메시지는 contents:read 없이 동작하도록 PR commits 엔드포인트로 조회. * 재오픈된 PR 의 부모 재고정·스레드 복구 (reopened 흐름 정상화) reopened 는 메타 주석이 이미 있어 post_parent 스텝이 스킵되는데, 부모 고정·상태 복구가 그 스텝 출력에만 의존해 재오픈 시 깨졌다. reopened 는 서버 봇엔 없고 클라 트리거라, 이 흐름 버그는 클라 전용이다. - 부모 재고정: pin 스텝의 부모 id 를 post_parent → find_meta 로 폴백하고 조건도 find_meta.message_id 를 포함하도록 넓혀, 재오픈 시 상단 고정이 복구되게 한다. - 스레드 복구: 종료 시 archived·locked 로 잠그고 이름에 🗑️ 프리픽스를 다는데, 재오픈 시 되돌리는 경로가 없어 이후 synchronize 답글이 잠긴 스레드라 실패했다. reopened 에 unarchive·unlock + 이름 원복 스텝을 추가한다. * fix: 게스트 인증 플로우 버그 2건 수정 + 관련 UX 개선 (#291) * fix: 게스트 MEMBER_ONLY 접근 시 로그인 무한 루프 수정 회원(MEMBER) 토큰일 때만 로그인 페이지를 건너뛰도록 제한. 게스트는 로그인에 남아 archive↔login 무한 루프 방지. * fix: 게스트 자동 로그인 시 현재 요청부터 token 적용되도록 수정 * refactor: 로그인 약관 안내 문구를 page로 분리 * feat: 게스트 세션 살아있는 경우 게스트 로그인 선택 시 리프레시 진행 * style: 토스트 위치 오류 수정 * feat: 게스트 로그인 redirect path가 /archive인 경우 /home으로 이동 및 안내 토스트 노출 * fix: 앱 부팅 시 refresh cookie 죽는 문제 해결 * fix: proxy에서 앱 auth token 도 처리 가능하도록 수정 * refactor: 앱 token refresh timeout 추가 * fix: 앱 토큰 만료(401) 시 WebView 쿠키도 정리 * fix: 앱 refresh 응답 snake_case 파싱 수정 * chore: proxy.ts refresh 401 임시 안전망 제거 (백엔드 rotation grace 적용) (#295) * chore: proxy.ts refresh 401 임시 안전망 제거 (백엔드 rotation grace 적용) (#295) * fix: iOS 26 Safari 노치 영역이 흰색으로 보이는 문제 수정 (#293) Co-authored-by: Jung Sun A <amber0809@naver.com> * refactor: 로그인 후 리다이렉트 로직 유틸로 추출 - 로그인 성공 후 경로 계산 중복 제거 (getPostLoginRedirectPath) * fix: 공유 위시 등록 시 refresh 401이면 죽은 토큰 정리 Share Extension이 만료된 토큰으로 재시도를 반복하지 않도록 refresh 401 시 clearTokens 호출 --------- Co-authored-by: 조영찬 <tigerbone@naver.com> * feat: Sentry 에러 모니터링 도입 (#296) * feat: web Sentry 에러 모니터링 도입 * feat: app Sentry 에러 모니터링 도입 * feat: web/app sentry 에러 로깅 규약 추가 - app: @sentry/react-native 셋업(_layout init+wrap, metro, 플러그인, eas 환경별 주입) - 공용 captureError 유틸(web/app) — 태그/컨텍스트 일관 부착 - API 5xx·네트워크 에러 중앙 수집(axios 인터셉터 / app fetch) - 유저 식별 setUser(id), 세션 만료 시 해제 - error.tsx 캡처, ignoreErrors 노이즈 필터 - app WebView onError/onHttpError, 백그라운드 FCM 핸들러 수집 * test: 에러 검증용 테스트 페이지 생성 * fix: SENTRY_AUTH_TOKEN turbo passThroughEnv 추가 (소스맵 업로드) * feat: Session Replay 마스킹 완화 (이메일만 마스킹, 나머지 노출) * feat: API 에러 리포트 제목을 'API {status} {method} {path}' 형식으로 개선 * Revert "test: 에러 검증용 테스트 페이지 생성" This reverts commit 87f9e53. * fix: 소셜 로그인 5xx 응답 JSON 파싱 실패 시 Sentry 수집 누락 수정 * fix: 로그아웃 시 Sentry 유저 컨텍스트 해제 * fix: Session Replay 타이핑 입력창만 마스킹 (maskAllInputs) * fix: 소셜 로그인 2xx 응답 본문 파싱 실패도 Sentry 수집 * feat: mutation 오류 발생 시 Sentry 로깅 추가 * docs: 역할정리 수정 * docs: 역할 관련 문서 업데이트 --------- Co-authored-by: sevineleven <117634128+sevineleven@users.noreply.github.com> Co-authored-by: 조영찬 <tigerbone@naver.com> * refactor: 게스트 참여 dead code 제거 (#321) * refactor: 게스트 참여 dead code 제거 * refactor: 게스트 참여 dead code 제거 2 --------- Co-authored-by: Jung Sun A <amber0809@naver.com> * chore: update app version * chore: eas config 삭제 * refactor: 링크 입력 시 텍스트에서 URL 자동 추출 (#323) * refactor: 링크 입력 시 텍스트에서 URL 자동 추출 * fix: URL 패턴 anchor 추가로 트레일링 텍스트 제출 방지 * fix: warm start 딥링크 보류 처리 * fix: 앱 내비게이션 타이머 갱신 --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: 조영찬 <tigerbone@naver.com> Co-authored-by: sevineleven <117634128+sevineleven@users.noreply.github.com> Co-authored-by: kanghaeun <145974230+kanghaeun@users.noreply.github.com>
작업 요약
작업 내용
1. 공통 에러 메시지 유틸 추가 —
getApiErrorMessagedetail우선, 없으면 "요청을 처리하지 못했어요."2. 전역 mutation / query 에러 안전망 (
queryClient.ts)MutationCache/QueryCache에 전역onError를 붙여 에러 처리 책임을 정리했습니다.401→ 전역 인터셉터(apis/client.ts)가 refresh·redirect로 처리하므로 양보 (이중 토스트 방지)5xx·네트워크→ 전역이 단독 처리: 공통 토스트 +Sentry.captureException4xx→ 개별onError가 있으면 양보, 없으면 generic fallback 토스트isError가 담당)3. 개별 훅 정리 — 전역 안전망에 위임
onError삭제: 실질 동작 없이 형식만 있던 핸들러 제거 (useDeleteWishes,useDeleteTournament)useDeleteWish,usePostTournamentOCR,usePatchWish,useDeleteTournamentItem) → 4xx 분기만 남김4. 정책 문서 추가 (
docs/spec/)error-handling-policy.md— 4xx 개별 / 5xx 전역, query는 로깅만 등 에러 처리 정책api-status-audit.md— 현재 API 에러 대응 현황 감사ownership.md— 역할 분배정책 요약
연관 이슈
closes #299
Summary by CodeRabbit