Skip to content

fix(schedule): 일정 실시간 이벤트 응답 순서 보장 및 장소 목록을 서버 조회 기준으로 갱신 - #250

Merged
minbros merged 26 commits into
devfrom
fix/stomp-event-order
Nov 8, 2026
Merged

minbros merged 26 commits into
devfrom
fix/stomp-event-order

Conversation

@KangShinGyu98

@KangShinGyu98 KangShinGyu98 commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

노션

변경 내용

  • 최신 dev를 병합하며 사용자 입력 시간·이동수단 없음 처리와 기존 실시간 무효화 흐름을 함께 보존하도록 충돌을 해결했습니다.
  • 최신 dev 충돌을 해결하고 preview 복구·서버 재조회 흐름을 함께 보존. Sonar 중첩 조건식·순차 조회 경고 2건 해소
  • 일차 장소 목록을 서버(GET …/items)에서 받는 queryFn으로 바꾸고, 일정 화면과 지도가 같은 조회 옵션(schedulePlanPlacesQueryOptions)을 쓴다
  • STOMP 이벤트를 받거나 본인 변경이 끝나면(onSettled) 그 일차를 무효화한다. 받는 중이던 옛 조회는 TanStack이 취소해, 늦게 온 응답이 최신 목록을 덮지 않는다
  • 본인 변경은 응답을 setQueryData로 반영하고, 본인 시간·메모 변경의 반향은 진행 중인 조회에 합류한다. 일정 전체 응답은 요청 뒤에 바뀐 일차 목록을 덮지 않는다
  • 이동수단 선택·모바일 편집 드래그·순서 변경 대기에 쓰던 useState를 mutation variables·isPending으로 바꿨다
  • AGENTS.md 데이터 원칙의 본인 수정 항목을 "서버 상태를 Source Of Truth로 두고 제한적인 경우에만 캐시를 쓴다"로 바꿨다

변경 이유

  • 비활성 일차의 무효화 표시를 늦은 전체 조회가 지우는 캐시 경합은 이번 충돌 해결 범위에서 수정하지 않았습니다. 해당 검증은 별도로 남아 있습니다.
  • 병합 보류: 같은 계정의 다른 탭에서 메모 변경 전 GET에 합류해 이전 메모가 남는 기존 P2 결함은 이번 Sonar·충돌 수정 범위에서 고치지 않음
  • 일차 목록 queryFn이 서버를 부르지 않고 STOMP 처리 코드가 목록을 직접 받아 썼다. 그래서 연달아 바뀔 때 늦게 온 응답이 최신 목록을 덮거나 지운 장소가 되살아났다

테스트

  • npm run lint
  • npm test — 충돌 해결본 213개 파일 / 1,716개 테스트 통과
  • npm run build 및 npx tsc --noEmit — 로컬 테스트 설정으로 검증
  • 화면 확인: 이번 변경의 브라우저 실행 없음. 기존 메모 race 재현은 과거 head의 증거이며 새 head PASS로 간주하지 않음
  • 충돌 해결 후 새 head의 Vercel·SonarCloud 검사 성공
  • 기존 작성자의 수정 전 수동 검증 기록: 아이폰 시뮬레이터 Safari에서 바꾸고 PC 크롬에서 반영 확인(직접), PC 크롬 동작 확인(Claude가 localhost에서 확인) — 이동수단 변경, 순서 변경, 장소 추가·삭제, 시간 변경, 같은 계정의 다른 탭에 시간 변경 반영

🤖 Generated with Claude Code

KangShinGyu98 and others added 5 commits October 30, 2026 20:16
- 일차 목록 queryFn이 캐시만 읽던 것을 서버(GET …/items)에서 받도록 변경. 지도 등 같은 키를 읽는 곳도 같은 조회 옵션을 써서 무효화하면 항상 서버에서 받음
- STOMP 이벤트는 목록을 직접 받아 쓰지 않고 무효화. 같은 일차를 받는 중이면 TanStack이 옛 조회를 취소하고 그 응답을 버림
- 일정 전체 응답은 요청을 보낸 뒤 바뀐 일차 목록을 덮지 않음

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 장소 추가·시간·메모·이동수단·삭제·순서 변경은 응답을 setQueryData로 반영하고 onSettled에서 그 일차를 무효화
- 장소 추가는 mutationFn에서 요청만 하고 캐시 반영은 onSuccess로 옮김
- 본인 시간·메모 변경의 STOMP 반향(UPDATED)은 진행 중인 조회에 합류하고, 다른 사람 변경이 섞이면 새로 받음
- 손으로 넣었던 분기 삭제: 쓸 때마다 일정 전체 재조회, 못 찾으면 무효화, 실패 시 직접 GET

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 이동수단 선택: 서버 값을 useState로 복사·되돌리던 것을, 저장 중에는 고른 수단(variables), 끝나면 서버 값을 보여 주도록 변경
- 모바일 편집 목록의 순서 변경·일차 이동: pending useState 대신 variables·isPending으로 새 자리를 그림
- 순서 변경의 연쇄 PATCH 대기 useState 삭제. onSuccess가 끝날 때까지 isPending이 이어짐

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 늦게 온 옛 조회 응답, 다시 받는 중 본인 삭제, 일정 전체 응답이 더 새 일차 목록을 덮는지 확인
- 바뀐 함수 모양(공용 조회 옵션, 장소 추가 응답, 모바일 드래그 표시)에 맞춰 기존 테스트 수정

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
frontend-server Ready Ready Preview Nov 8, 2026 11:31am UTC

Request Review

KangShinGyu98 and others added 15 commits November 3, 2026 23:20
- 경로 key를 (방, 일차, 출발 항목, 도착 장소, 이동수단)으로 바꾼다 — 목록·지도·batch 시딩이 다음 장소의 googlePlaceId를 넘긴다
- 순서가 바뀐 구간은 key가 달라져 옛 도착지의 거리·선을 보여 주지 않는다
- 도착 장소가 없는 구간은 조회하지 않는다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 순서 변경·장소 추가·삭제·일차 간 이동·이동수단 변경(본인·STOMP)과 일정 전체 재조회 뒤의 구간 경로 무효화를 지운다 — 바뀐 구간은 새 key로 받는다
- 구간 계산·무효화 모듈(scheduleStompRouteScope.ts)과 STOMP 경로 무효화 디바운스 삭제
- 장소 삭제는 응답으로 일차 목록에서 그 장소만 빼고, 일차 삭제 뒤의 경로 무효화도 지운다
- 지도 에폭 증가 호출 삭제 (지도 key 정리는 다음 커밋)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 지도 선 key는 (방, 일차, 출발 항목, 출발·도착 장소, 이동수단)만 쓴다 — 도착 장소가 바뀌면 key가 달라져 새 선을 그린다
- 에폭 스토어(plan-map-directions-epoch-store) 삭제
- 선의 React key도 에폭 대신 도착 장소로 구분한다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- batch가 받아 둔 구간 경로를 목록 칸(다음 장소 googlePlaceId)과 지도(지도 구간 계산)가 단건 요청 없이 쓰는지 본다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 서버가 그 순간의 순서로 다음 항목을 고르던 단건 GET에 destinationItemId를 보낸다 — 요청한 구간과 응답 구간이 항상 같다
- 경로 key·지도 선 key·sessionStorage key의 도착 값을 다음 장소의 itemId로 바꾼다
- 서버에 이 파라미터가 배포되기 전에는 서버가 무시하고 지금처럼 다음 항목으로 계산한다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- batch 응답의 toItemId(서버가 계산한 구간의 도착 항목)로 경로 key를 만든다 — 요청 때 목록에서 짐작하지 않는다
- 응답을 기다리는 사이 순서가 바뀌면 결과를 통째로 버리던 일정 지문 비교를 지운다
- 마지막 항목·항목 없음 답은 도착 항목이 없어 저장하지 않고, 그 칸이 도착 항목을 지정한 단건 조회로 받는다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 탭마다 한 번 만드는 getTabId 추가(모듈 변수, randomUUID 없으면 getRandomValues로 v4)
- 이미 preflight를 하는 PATCH·PUT·DELETE·JSON POST에만 헤더를 붙임
- 백엔드가 이 값을 STOMP payload originTabId로 돌려줘 이 탭의 반향을 가려낼 수 있게 함

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 이벤트 originTabId가 이 탭 ID와 같을 때만 반향으로 보고 건너뜀(isOwnEcho)
- originTabId가 없는 옛 이벤트는 지금처럼 actorUserId로 판정해 배포 순서와 무관
- SCHEDULE_ITEM_UPDATED: 이 탭 반향은 건너뛰고, 다른 탭 변경은 진행 중인 조회에 합류하지 않고 다시 받음

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- bookmarks 이벤트도 isOwnEcho로 판정(originTabId 같을 때만 건너뜀, 없으면 actorUserId)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- isOwnEcho는 originTabId가 이 탭 ID와 같을 때만 반향으로 판정(계정 판정 제거)
- 탭 ID를 못 만든 탭의 변경도 같은 계정의 다른 탭이 놓치지 않게 함
- SCHEDULE_ITEM_UPDATED의 본인 반향 합류(joinInFlight) 분기 제거

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- case마다 반복하던 isOwnEcho를 한 번만 둬 새 이벤트 종류에서 빠뜨리지 않게 함

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 반향은 originTabId가 이 탭이고 actorUserId도 나일 때만으로 판정
- 탭 ID는 방 멤버 모두에게 보이므로 서버가 인증으로 정한 actorUserId를 함께 봄

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 캐시 갱신 흐름과 사용자 지정 시간·이동수단 보존 변경 결합
- 일차 이동 순서와 시간 보존 회귀 테스트 유지
- 도착 항목 경로 키와 미선택 이동수단 처리 결합
- 사용자 지정 시간과 기존 요약 회귀 테스트 보존
- 검증된 경로 캐시 부모 브랜치 병합
- 탭별 본인 변경 반향 처리와 시간 보존 동작 유지
fix(stomp): 같은 계정 다른 탭에도 일정·북마크 변경을 탭 ID로 구분해 반영
fix(route): 경로를 출발·도착 항목 단위로 캐시해 순서를 되돌리면 다시 요청하지 않도록 수정
@sonarqubecloud

sonarqubecloud Bot commented Nov 8, 2026

Copy link
Copy Markdown

@minbros
minbros merged commit a0ff188 into dev Nov 8, 2026
3 checks passed

This branch was successfully deployed

1 active deployment
Preview — bf461b37 Deployed Nov 8, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants