Repository navigation
fix(stomp): 북마크·멤버·가계부·채팅을 변경 뒤 서버 조회 기준으로 갱신 - #262
Open
KangShinGyu98 wants to merge 28 commits into
Open
KangShinGyu98 wants to merge 28 commits into
KangShinGyu98 wants to merge 28 commits into
Conversation
- 전체 목록 queryFn이 카테고리별 key에 써 넣던 시딩을 없애고, useRoomBookmarks는 같은 전체 목록 query의 select로 거른다 - 사본이 1벌이 되어 옛 전체 스냅샷이 최신 카테고리 목록을 덮거나 0개가 된 카테고리에 옛 목록이 남지 않는다 - 시딩 때문에만 마운트하던 BookmarkFoldersView·BookmarkFolderDetailView·AddFromBookmarkModal의 useAllRoomBookmarks 줄 정리 - 쓰지 않게 된 카테고리별 key·GET(getRoomBookmarks)·bookmark-bulk-cache 삭제, 재구독 복구는 전체 목록 key만 무효화 - 추가 응답 반영은 전체 목록에만 하고, 목록을 받은 적이 없으면 일부만 든 목록을 만들지 않는다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 타입별로 하나씩 await하던 무효화를 Promise.all로 함께 보낸다(앞 재조회가 끝나야 다음이 출발하던 지연 제거) - 카테고리별 key가 없어져 북마크 변경·카테고리 삭제는 폴더 목록과 전체 북마크 두 key만 무효화한다(invalidateRoomBookmarkLists, 본인 변경도 같이 쓴다) - 기본 refetchType(active)과 같은 옵션은 지운다 - bookmarks-invalidation.test.ts 추가: 타입별 범위, 병렬 출발, 화면 밖 목록 표시만, 다른 방 제외 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 서버는 폴더 안의 북마크도 함께 지우는데, 폴더 목록만 무효화해 지도 핀·전체 북마크에 지운 북마크가 남았다 - 본인 CATEGORY_DELETED는 STOMP에서 버리므로 onSettled(성공·실패 모두)에서 두 목록을 다시 받는다 - 응답 본문이 없어 재조회를 반환해 목록에서 폴더가 빠질 때까지 확인창 진행 표시를 유지한다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- mutationFn이 오류를 결과 객체로 바꿔 삼켜 실패·409(이미 있음) 경로에 재조회가 없었다 - onSettled에서 폴더 목록과 전체 북마크를 무효화한다. 성공 응답은 onSuccess에서 이미 반영해 기다리지 않는다(void) - "목록 캐시도 즉시 무효화" 주석을 실제 동작(응답 반영 → 끝나면 재조회)에 맞게 고친다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- useCreateRoomBookmark는 호출부가 없다. 추가는 useCreateRoomBookmarksInCategories 하나로 한다 - 함께 쓰이지 않게 된 createRoomBookmark API와 RoomBookmarkCreateRequest 타입도 지운다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 폴더 생성·수정, 북마크 이동·삭제에 onSettled(성공·실패 모두) 무효화를 넣는다. 본인 STOMP 반향은 버려 바꾼 탭은 여기서 맞춘다 - 응답이 있는 것은 onSuccess에서 반영하고 재조회는 기다리지 않는다(void): 폴더 생성(새 폴더 추가), 폴더 수정(이름·색만 — 응답 placeCount는 0), 이동(옮긴 북마크로 교체) - 응답이 없는 북마크 삭제는 재조회를 반환해 목록에서 빠질 때까지 확인창 진행 표시를 유지한다 - 폴더 목록을 받은 적이 없으면 새 폴더 한 건짜리 목록을 만들지 않는다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 폴더를 바꿔도 전체 목록을 다시 받지 않고 isPending이 false인지, 폴더별로 걸러지는지 단언한다 - 폴더를 고르기 전(null)에는 요청 없이 '조회 전'으로 두는지 단언한다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 이벤트 detail로 room-members를 고치면 이벤트 전에 출발한 GET이 늦게 와서 덮었다. 무효화로 바꿔 TanStack이 옛 조회를 취소하게 한다 - 내가 나가거나 내보내진 이벤트(또는 대상을 모르는 이벤트)는 다시 받지 않는다. 나간 방의 GET은 403이고, 방 캐시는 나가기·강퇴 처리가 지운다 - 방장 위임은 방장 판정의 세 출처(멤버·방 목록·방 상세)를 모두 무효화한다 — 다른 탭의 이전 방장도 방장 판정이 풀린다 - members-dispatch.test.ts: 무효화·늦은 응답 무시·본인 퇴장 제외·방장 위임 다른 탭 시나리오로 다시 씀 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 접속·해제는 잦아 isOnline 패치를 예외로 남긴다. 사유와 범위(ACTIVE 멤버 isOnline만)를 코드 주석에 적는다 - 멤버 목록을 받는 중이면 그 조회는 접속 변화 전에 출발했을 수 있어, 패치 대신 무효화로 옛 조회를 취소하고 다시 받는다 - 바뀌는 것이 없으면 캐시를 쓰지 않는다 - presence-dispatch.test.ts 추가 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- deprecated 표시 뒤 호출부가 없다. 구독 직후 재동기화는 scheduleRoomMembersResyncAfterSubscribe가 맡는다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 방장 위임: 응답 없이 확정된 결과를 onSuccess에서 세 출처에 반영하고, onSettled(실패 포함)에서 세 출처를 무효화한다. 화면은 기다리지 않는다(void) - 강퇴·입장 승인·거절: 응답 본문이 없어 onSettled 무효화를 반환해 목록에서 빠질 때까지 진행 표시를 유지한다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 나간 방은 접근 권한을 잃어 방 범위 조회가 403을 받는다. onSuccess에서 evictRoomFromClientCaches로 그 방 캐시·가계부 접근을 지운다(AGENTS.md: 권한 상실 시 즉시 제거) - onSettled(실패 포함)에서는 방 목록(ROOMS)만 무효화한다. 나간 방은 이미 목록에서 빠져 기다리지 않는다 - 다른 탭은 STOMP 본인 MEMBER_LEFT(onSelfLeftRoom)가 같은 정리를 한다 - useLeaveRoom.test.tsx 추가 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- useRoomMembers queryFn이 signal을 getRoomMembers에 넘긴다 - 멤버 이벤트·접속 변화로 받는 중인 조회를 TanStack이 취소하면 그 HTTP 요청도 끊긴다(연달아 오는 이벤트에 옛 요청이 끝까지 가지 않게) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 가계부 조회 함수(목록·요약·환산 요약·예산·통화)와 getRoomMembers가 선택 인자 signal을 받아 fetch에 넘긴다 - ExpenseProvider의 조회·readLatest·readLatestBudget queryFn이 signal을 넘겨, TanStack이 옛 조회를 취소하면 HTTP 요청도 끊긴다 - signal이 없으면 지금처럼 init 없이 보낸다 - ExpenseProvider.test: 환산 요약 호출 인자에 signal을 반영, 방 전체 합계 판별을 인자 개수 대신 필터 여부로 바꾼다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 복구가 키마다 cancelQueries 뒤 자체 queryFn으로 fetchQuery하던 것을 invalidateQueries(기본 refetchType active)로 바꾼다. 다시 받는 일은 화면의 ExpenseProvider 조회가 자기 queryFn으로 한다 - 진행 중 조회는 TanStack 기본값대로 취소하고 새로 받는다(cancelRefetch: false 합류 없음). 취소된 HTTP 요청은 signal로 끊긴다 - 변경 알림·본인 저장 뒤에는 데이터가 없어 TanStack이 합류하는 첫 조회도 취소하고 다시 받는다. 입장·연결 복구는 구독 뒤 출발한 첫 조회에 합류해 입장 때 6개 × 2 조회가 6개가 된다 - 같은 틱에 온 요청(중복 프레임·알림 여러 개)은 다음 마이크로태스크에 한 번에 무효화한다 - 상태 기계(pending·refreshing·ready·error·revoked), 403·404 권한 해제, listRevision 펜스, 실패 기억은 그대로 둔다. 더 새 조회로 바뀌어 취소된 조회는 실패로 세지 않는다 - 테스트: observer 없이 6개를 받던 단정을 ExpenseProvider와 같은 조회를 붙인 상태로 고쳐 쓰고, 첫 조회 재시작·본인 저장 반향(요청 2번·앞 요청 중단·반영 1번) 시나리오 추가 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 두 응답에 다른 예산 값을 주고, 늦게 온 옛 응답 뒤에도 캐시가 새 값인지 단언한다(전에는 둘 다 빈 배열이라 덮어써도 통과했다) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 복구: 장부가 맞춰진(ready·refreshing) 상태에서 온 변경 알림·본인 저장 뒤 재조회는 refreshing으로 둔다. 입장·연결 복구·재시도(all)와 아직 맞춰지지 않은 장부는 지금처럼 pending - ExpenseProvider: 복구가 ready일 때 다른 화면의 무효화(일정 변경·멤버 이벤트)로 다시 받는 중이면 pending 대신 refreshing으로 낸다. 처음 데이터가 없으면 pending, 실패는 error 그대로 - 그동안 남은 예산·카테고리 합계가 '—'로 바뀌던 것을 막는다(AGENTS.md 로딩 원칙) - expense-recovery.test: 실제 변경이 pending으로 올리던 단정을 refreshing 유지로 바꾸고, 범위별 상태 시나리오 추가 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 가계부 조회의 staleTime 0을 Infinity로, 멤버 조회의 refetchOnMount "always"를 지운다. 입장·연결 성립 복구와 변경 알림·본인 저장 무효화가 갱신을 맡는다 - 다시 들어올 때 마운트 재조회 6개와 입장 복구 6개가 겹쳐 12번(6번은 취소) 보내던 것이 6번이 된다. 화면 밖에서 무효화된 조회는 다시 붙을 때 받는다 - ExpenseProvider.test: 다시 들어올 때 자원마다 한 번만 읽는 시나리오 추가 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 로딩 UI 원칙에 추가: 아바타·사진은 같은 크기의 스켈레톤, 이름·문장은 보이지 않게 둔다 - (알 수 없음) 같은 대체 문구는 조회가 끝난 뒤에도 값이 없을 때만 쓴다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 메시지(채팅 토픽)와 이름(멤버 목록)이 따로 와서, 새 멤버의 입장 문구·메시지가 이름보다 먼저 그려져 '(알 수 없음)'이 잠깐 보였다 - 수신 콜백에서 메시지가 가리키는 사람(보낸 사람·입장한 사람·새 방장)이 목록에 없으면 멤버 목록을 무효화하고 그 메시지를 기억한다. state는 메시지 추가 한 번뿐이다 - 렌더에서 목록을 처음 받는 중이거나, 기억한 메시지인데 목록을 다시 받는 중이면 그리지 않는다. 목록이 갱신되면 같은 계산으로 제자리에 이름과 함께 보인다 - 다시 받은 목록에도 없거나, 이미 있던 메시지의 사람이 없으면(탈퇴) '(알 수 없음)'으로 둔다 - 무효화는 기본값(진행 중 조회 취소 후 새로) — 받는 중인 조회는 그 사람이 들어오기 전에 출발했을 수 있다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 데이터가 없는 첫 조회에는 무효화가 취소하지 않고 합류해서, 방 입장 직후 들어온 새 멤버가 목록과 채팅 이름에서 빠진 채 남았다 - invalidateAfterChange(query-client)를 두어 받는 중인 첫 조회를 먼저 취소하고 새로 받는다. 데이터가 있는 조회는 무효화가 취소한다 - 멤버 이벤트, 접속 상태의 재조회, 채팅에서 이름 모르는 메시지를 받았을 때 이 함수를 쓴다 - 테스트: 첫 조회 중 변경(공용 함수·멤버 이벤트·채팅) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- "변경 뒤에는 받는 중인 조회를 버리고 새로 받는다"를 invalidateAfterChange 하나로 통일한다 - 북마크: STOMP 이벤트와 본인 변경 뒤 폴더 목록·전체 북마크 재조회에 사용(첫 조회 중 변경도 놓치지 않음) - 가계부: 변경 알림·본인 저장 뒤에 쓰던 '데이터 없는 조회 취소' 코드를 이 함수로 바꾼다. 입장·연결 복구는 지금처럼 첫 조회에 합류한다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 방 페이지의 멤버 조회는 STOMP 연결 뒤에 시작해서, 그 전에는 내 메시지만 보이고 로딩 표시가 없었다 - useChatMessages가 waitingForMembers를 내보내고, ChatPanel은 그동안 목록 자리에 Spinner를 둔다(입력창은 그대로) - 목록은 멤버 목록을 받은 뒤 처음 마운트되어, 읽음 위치 스크롤도 메시지가 다 그려진 뒤에 처리된다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 1번 커밋에서 시딩용으로 보고 지운 useAllRoomBookmarks 두 줄이, 지도(같은 목록을 받음)가 없는 모바일에서는 유일한 미리 받기였다 - 폴더 목록 화면: 폴더를 누를 때 GET·스켈레톤이 생기던 것을 다시 미리 받는다 - 일정 "북마크에서 추가": 폴더 목록을 받은 뒤에야 북마크를 받던 직렬 대기를 없앤다 - 같은 key라 요청 수는 그대로(전체 목록 1번) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- signal을 주면 apiFetch init에 그대로 넘긴다 - signal 없이 부르면 지금처럼 init 없이 보낸다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 강퇴·입장 승인·거절·북마크 삭제는 목록을 다시 받을 때까지 mutateAsync가 끝나지 않는다 - 강퇴·승인·거절·방장 위임·북마크 삭제가 실패해도 관련 key를 무효화한다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # src/hooks/useRooms.ts
- 5·10·20번처럼 건너뛴 번호는 빠진 구간으로 처리돼 메시지가 붙지 않아 단언이 빈 목록과 비교되고 있었다 - 빈 방 다음 1번부터 이어지게 바꾸고, 입장 메시지는 번호를 받는 함수로 바꾼다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



노션
변경 내용
select로 걸러 쓰고(시딩 캐시 제거), STOMP·본인 변경 뒤에는onSettled무효화로 서버 기준에 맞춘다.invalidateAfterChange). 방을 나가면 그 방 캐시를 바로 지운다.staleTime: Infinity로 재마운트 때 겹치던 조회를 없앤다.변경 이유
테스트
npm run lintnpm testnpm run build🤖 Generated with Claude Code