Skip to content

fix(stomp): 재연결 때 놓친 일정·채팅 복구와 재연결 백오프 적용 - #247

Merged
minbros merged 19 commits into
devfrom
fix/stomp-sync-recovery
Oct 28, 2026
Merged

minbros merged 19 commits into
devfrom
fix/stomp-sync-recovery

Conversation

@KangShinGyu98

@KangShinGyu98 KangShinGyu98 commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

노션

변경 내용

  • 재연결: 수동 루프를 없애고 stompjs 지수 백오프(시작 12초, 2배씩, 상한 30초)에 맡김. 끊긴 뒤 7번째 재연결까지 실패하면 재연결을 멈추고 배너를 띄움(끊긴 뒤 약 1분 30초2분). 세션 확인은 beforeConnect에서 하고, 백엔드 장애(503)로는 로그아웃하지 않음
  • 다시 시작: 배너의 '다시 시도', 또는 인터넷이 완전히 끊겼다 돌아올 때(online 이벤트) 횟수를 처음부터 다시 셈. 클릭·화면 전환으로는 다시 시작하지 않음 — 무한 재시도가 되고, 다른 호출은 멀쩡한데 ws만 막힌 한정적인 상황이라 '다시 시도'에 맡김
  • 방 데이터: 방 토픽을 구독할 때마다(첫 연결·재연결·/home 복귀) 일정·북마크·안읽음 수를 다시 받고, 재조회가 실패해도 보이던 목록은 유지. 끊긴 동안 권한을 잃은 방은 재연결 뒤 퇴장
  • 일정 드래그: 끊긴 동안과 놓친 변경을 다시 받는 동안 드래그를 막음. 전체 재조회를 하나로 모아 늦은 응답이 새 일정을 덮지 않게 하고, 같은 일차 이동은 드래그한 항목 id로 저장
  • 채팅: sequence 커서로 실시간 메시지를 이어 붙이고, 빈 번호·재연결·재진입 때 afterSequence로 끝까지 따라잡음. 첫 기록 로딩 중 받은 채팅을 유지하고, 재연결로 붙은 메시지 앞에 구분선을 두고 스크롤

변경 이유

  • STOMP가 끊긴 동안(절전·네트워크·/home 이동) 놓친 변경을 복구하지 않아, 옛 일정 기준 드래그로 잘못된 순서가 저장되고 채팅이 사라지거나 15개를 넘으면 누락됨
  • 웹소켓만 실패하고 세션 API는 200이면 재연결이 지연 없이 무한 반복돼 백엔드 장애를 키움

테스트

  • npm run lint
  • npm test
  • npm run build
  • 화면 확인: pc-chrome
  • 그 외 수동 검증:
    • DevTools로 /ws/* 차단 → 7번째 재연결 실패 뒤 재연결이 멈추고 배너 표시
    • 로컬 크롬 같은 계정 두 탭(Claude 조작): 백엔드 재시작 중 세션 503·로그아웃 없음 / 끊긴 탭만 드래그 잠금 / 재연결·/home 복귀 때 일정 조회 1번으로 다른 탭 변경 반영 / 끊긴 동안 받은 채팅을 재연결 직후 표시 / 첫 기록 응답을 늦춰도 그 사이 받은 채팅 유지 / 연달아 보낸 채팅이 보낸 순서대로 표시
    • PC + 모바일로 일정 동시 수정 테스트

🤖 Generated with Claude Code

KangShinGyu98 and others added 16 commits October 25, 2026 18:11
- 백엔드 도달 실패·5xx·429는 503, 인증 실패가 확정된 경우만 401
- refresh 직후 재확인이 장애로 실패해도 새 쿠키 전달
- proxy의 세션 판정은 그대로 유지

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- reconnectDelay·EXPONENTIAL·maxReconnectDelay(5초)로 재시도 간격 위임
- 재연결 직전 세션 확인을 beforeConnect로 옮기고 401이면 재연결 중단 후 로그아웃
- 연결 문제 배너는 끊긴 지 45초가 지나면 표시하고 연결되면 해제
- 다시 시도는 연결 시도 중이 아닐 때만 바로 재연결

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 브라우저 online 이벤트에서 다시 시도와 같은 경로로 즉시 재연결

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 구독 오류(ERROR)를 받으면 방 접근을 HTTP로 확인해 거부면 퇴장 처리
- 구독 오류로 연결이 닫히면 5초 뒤 다시 연결해 1초 간격 반복 방지

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- refetchOnMount: false 제거, staleTime: Infinity는 유지해 무효화된 경우에만 조회

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 취소된 일정 조회는 캐시에 쓰지 않고, 미리보기를 기다린 뒤 한 번에 쓰기
- 본인 일차 변경·여행 날짜 변경·ROOM_SCHEDULES_RESYNCED는 room-schedules 조회를 거쳐 재조회
- 일차 목록을 고치는 동안 전체 재조회가 진행 중이면 다시 시작
- 재조회로 순서가 바뀐 일차는 이웃이 바뀐 구간 경로만 무효화

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 첫 구독·재연결·/home 복귀·방 전환 때 일정·북마크·안읽음 배지를 무효화
- 개인 큐를 구독할 때 놓친 입장 요청 목록을 무효화
- 화면에 있는 조회만 바로 다시 받고, 준비물·가계부·채팅 목록은 대상에서 제외

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 모바일 일정·경로 카드·북마크 폴더·폴더 상세·북마크에서 추가 모달은 처음 불러오기에 실패했을 때만 오류 화면
- 경로 카드는 재조회 실패 뒤에도 받아 둔 일정으로 장소 목록을 계속 읽음

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 무효화된 멤버 목록에는 이벤트를 패치하지 않아 다음 마운트 때 재조회 유지
- 멤버 목록을 받은 적이 없으면 한 명짜리 목록을 만들지 않음

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 데스크톱 같은 일차·다른 일차, 모바일, 일차 이동 모두 드래그 시작 때 순서와 놓을 때 순서를 비교
- 같은 일차 이동은 드롭 시점 목록 대신 드래그한 항목 id로 요청

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 데스크톱·모바일·일차 이동 손잡이는 기존 비활성 표시를 쓰고 목록은 그대로 보임
- 드래그 중에 끊기면 놓아도 저장하지 않고 알림

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- STOMP client·연결 상태를 보낼 때 ref로 읽어 markMessagesRead가 연결마다 새로 만들어지지 않게 함
- 이 함수에 기대는 채팅 최초 기록 조회가 재연결 때마다 다시 시작되던 원인을 없앰

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 기록 조회·최신으로 이동·아래 페이지·따라잡기 중 받은 메시지를 모았다가 결과 반영 뒤 같은 규칙으로 처리(로딩 중 받은 일반 채팅 유실 수정)
- 커서+1만 목록 끝에 붙이고, 번호가 비면 afterSequence로 200개씩 끝까지 받음
- 재연결·다른 방에서 돌아올 때 놓친 메시지를 따라잡고, 재연결로 새로 붙은 메시지 앞에 구분선을 두고 그 자리로 스크롤
- 중간 창에서는 새 메시지를 붙이지 않고 같은 id만 갱신, AI 요청은 대기 상태로 되돌리지 않음
- 빈 방은 afterSequence=0 대신 최신 페이지를 받고, 400·403·404는 다시 보내지 않음(네트워크·5xx는 1·2·4초 간격 재시도)
- 최초 기록 조회가 재연결로 멈추지 않게 하고, 끝내 실패했으면 재연결 때 다시 받음
- 목록을 sequence 순으로 정렬하고, 최신으로 이동은 목록을 비우지 않고 한 번에 교체
- 메시지·읽음 위치 조회 API가 HttpError를 던지게 함

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 서버는 저장 충돌을 재시도한 순서로 sequence를 매겨, 번호 순 정렬이면 1~4가 3·4·1·2로 보였음
- 목록은 작성 시각 순으로 되돌리고, sequence 순서는 빈 번호 판단에만 사용
- 최초 기록·최신으로 이동 결과도 작성 시각 순으로 정렬

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 드래그 시작과 놓을 때의 순서 비교, "일정이 바뀌어서 옮기지 않았어요" 알림 제거(데스크톱·모바일·일차 이동)
- 같은 일차 이동은 계속 드래그한 항목 id로 요청
- 연결이 끊긴 동안과 다시 받는 동안의 드래그 잠금은 유지

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

vercel Bot commented Oct 26, 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 Oct 28, 2026 8:06am UTC

Request Review

KangShinGyu98 and others added 3 commits October 28, 2026 16:39
- 재연결 간격 상한을 5초에서 30초로 늘림(1~2초 시작, 2배씩)
- 끊긴 뒤 7번째 재연결까지 실패하면 재연결을 멈추고 연결 문제 배너를 띄움
- 45초 타이머 배너를 없앰
- 배너의 '다시 시도'는 횟수를 처음부터 다시 셈. 멈춘 뒤 online 이벤트로는 다시 시작하지 않음

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 7회 실패로 재연결을 멈춘 뒤 online 이벤트가 오면 횟수를 처음부터 다시 세며 재연결
- 다시 온라인이 됐다는 것은 인터넷이 완전히 끊겼다가 돌아온 경우를 말하고, 클릭이나 화면 전환은 포함하지 않음
- 화면 전환·클릭에 재시도를 걸면 무한히 재시도하게 되고, 이 상황은 다른 호출은 멀쩡하고 ws만 막힌 한정적인 경우라서 '다시 시도' 버튼에 맡김

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

Copy link
Copy Markdown

@minbros
minbros merged commit 4f7d9fc into dev Oct 28, 2026
2 checks passed
minbros added a commit that referenced this pull request Nov 1, 2026
* fix(places): 사진 조회 실패 시 반복 요청하지 않도록 재시도 규칙 변경

- 전역 재시도를 일시적 네트워크 오류 1회로 제한 (429·4xx·5xx는 재시도하지 않음)
- 장소 API 실패를 status가 담긴 HttpError로 던짐
- 사진 retry 2·미리보기 retry 1 개별 설정 제거

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

* feat(places): 사진 카드를 batch로 조회하고 실패한 장만 한 번 더 조회

- 같은 커밋에 보이는 사진 2장 이상은 batch, 1장은 단건 API로 보냄
- batch 항목 실패는 실패한 장만 한 번 더 보내고 그래도 실패하면 끝냄
- 요청 자체가 실패하면 단건으로 나눠 보내지 않음
- 쓰이지 않던 사진 batch 시딩 코드 제거

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

* feat(places): 지도 북마크 핀·북마크 미리보기를 batch로 조회

- 같은 커밋에 마운트된 미리보기는 batch로 모으고 실패한 곳만 한 번 더 조회
- 지도 핀이 batch를 먼저 보낸 뒤 실패하면 전부 단건으로 다시 받던 단계 제거

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

* fix(route): 경로 batch의 경로 없음 답을 단건으로 다시 묻지 않음

- NO_ROUTE·LAST_ITEM·SCHEDULE_ITEM_NOT_FOUND 구간은 경로 없음(null)으로 시딩

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

* fix(schedule): 일정 불러오기에서 같은 장소 미리보기를 반복 조회하지 않도록 수정

- 모든 일차 장소를 batch 한 번으로 받고 실패한 곳만 batch로 한 번 더 조회, 단건 조회 제거
- 일차 블록은 일정 불러오기가 끝난 뒤 켜서 같은 장소를 다시 받지 않음
- 자리표시자가 남은 일차는 다시 들어올 때 그 장소만 batch로 다시 조회
- 미리보기 batch가 실패해도 일정 전체를 실패로 만들지 않고 자리표시자로 표시

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

* fix(schedule): 일정 불러오는 동안 일차에 빈 상태 대신 스켈레톤 표시

- 일차 쿼리를 일정 불러오기 중에도 켜고, 진행 중인 불러오기를 기다려 그 결과를 사용
- 같은 진입 안에서 장소 미리보기를 다시 받지 않음

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

* fix(places): 100곳이 넘을 때 뒤 묶음이 실패해도 앞 묶음에서 받은 장소는 쓰도록 수정

- 로더가 서버 한도(100곳)씩 나눠 차례로 보내고, 받은 묶음은 바로 씀
- 요청이 실패하면 그 묶음과 남은 묶음은 그 에러로 끝내고, 실패 항목도 다시 보내지 않음(요청 수는 이전과 같음)
- 마지막 묶음이 1곳이면 단건 API로 보냄

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

* fix(schedule): 기다리던 일정 불러오기가 취소되면 새 불러오기를 기다리도록 수정

- 취소된 불러오기를 기다리던 일차 조회가 '조회 중'으로 멈춰 그 일차 경로를 받지 않던 문제 방지
- 진행 중인 일정 불러오기를 취소하고 다시 받는 변경(#247)과 함께 쓰일 때를 대비

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

* fix(places): 사진 batch 응답 id 형식이 달라도 같은 장소로 맞추도록 수정

- 응답 id의 `places/` 접두를 떼고 요청 id 기준으로 결과를 돌려줌
- id가 빈 항목이 있어도 batch 전체를 실패로 처리하지 않음

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

* fix(places): status 없는 미리보기 batch 항목도 id·이름이 있으면 사용

- 레거시 응답(status 없음)을 예전처럼 받아 일정·북마크 핀이 자리표시자로 남지 않게 함

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

* fix(bookmark): 미리보기를 받지 못하면 내부 에러 문구 대신 안내 문구 표시

- 요청 id·API 오류 코드가 담긴 에러 메시지를 화면에 그대로 보여 주지 않음

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

* fix(plan): 사진을 다시 받아도 불러오지 못하면 일정 카드에 깨진 이미지 대신 회색 칸 표시

- 사진 오류 처리에 다시 받기까지 실패했을 때 알리는 `onPhotoUnavailable` 추가
- 못 불러온 사진 주소는 그리지 않는 `useVisiblePlacePhotoUrl` 추가(주소가 바뀌면 다시 그림)

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

* fix(places): 북마크·채팅·장소 상세 사진도 불러오지 못하면 사진 없음 모양 표시

- 북마크·채팅 장소 카드는 지도 핀 아이콘, 장소 상세는 회색 칸으로 둠

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

* refactor(places): 사진 조회 옵션을 함수로 빼고 테스트가 훅 대신 쓰게 함

- 훅이 아닌 함수에서 훅을 부르던 테스트의 lint 오류(react-hooks/rules-of-hooks) 수정
- 조회 키·queryFn·캐시 설정은 그대로

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

* test(places): 사진 없음 처리 훅 테스트가 렌더 중 바깥 변수를 바꾸지 않게 수정

- lint 오류(react-hooks/globals) 수정

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

* fix(route): 경로를 다시 받다가 실패해도 마지막 답이 경로 없음이면 오류 대신 그대로 표시

- 순서 변경 등으로 다시 받던 "경로 없음" 구간이 429를 받으면 "경로 조회 오류"로 바뀌던 문제 수정
- 받은 답 없이 실패하면 지금처럼 오류 표시

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

* fix(route): 지도가 방금 실패한 경로 구간을 다시 요청하지 않도록 수정

- 목록 요청이 429 등으로 실패한 구간을 지도가 fetchQuery로 한 번 더 보내던 문제 수정
- 진행 중인 요청에 합류하고, 받은 적 없는 구간은 지금처럼 받음

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

* fix(schedule): 미리보기 실패 상태에서 다시 들어와도 지운 장소가 되살아나지 않도록 수정

- 일차 목록이 있으면 room-schedules의 장소 목록으로 다시 만들지 않고 자리표시자 장소의 미리보기만 다시 받아 채움
- room-schedules의 장소 목록은 장소 추가·삭제·수정을 따라가지 않아, 다시 만들면 지운 장소가 되살아났음

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: minbros <realminbros@gmail.com>

This branch was successfully deployed

1 active deployment
Preview — 5eab860e Deployed Oct 28, 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