Skip to content

[Fix] FCM 토큰이 바뀌어도 서버에 반영하지 않는 문제 수정 - #567

Merged
edv-Shin merged 4 commits into
devfrom
fix/fcm-token-sync-565
Aug 16, 2026
Merged

[Fix] FCM 토큰이 바뀌어도 서버에 반영하지 않는 문제 수정#567
edv-Shin merged 4 commits into
devfrom
fix/fcm-token-sync-565

Conversation

@edv-Shin

Copy link
Copy Markdown
Contributor

#️⃣연관된 이슈

ex) #이슈번호, #이슈번호

Closes#565

📝작업 내용

이번 PR에서 작업한 내용을 간략히 설명해주세요(이미지 첨부 가능)

FCM 토큰이 갱신돼도 다음 앱 진입까지 서버에 올라가지 않던 경로를 끊었습니다. onNewToken()에서 저장한 뒤 WorkManager로 전송을 예약합니다.

FcmTokenSyncWorker 추가

  • NetworkType.CONNECTED 제약으로 연결이 잡힌 뒤에 실행
  • BackoffPolicy.EXPONENTIAL, 초기 지연 30초, 총 5회까지 시도
  • enqueueUniqueWork("fcm_token_sync", REPLACE)로 중복 예약 방지
  • 대기 중 토큰이 다시 갱신되면 REPLACE로 백오프를 처음부터 다시 셈
  • 재시도 판단은 FcmTokenSyncPolicy로 분리해 JVM 테스트로 검증

FcmService.onNewToken()은 저장 후 워커만 예약

  • 백그라운드나 프로세스 기동 직후에도 불려 네트워크와 로그인 상태를 확신할 수 없으므로 API를 직접 부르지 않음

SyncFcmTokenUseCase 추가

  • 회원ID가 없으면 SKIPPED로 끝내고 전송하지 않음
  • 저장된 토큰을 호출 시점에 읽어 예약과 실행 사이의 재갱신을 흡수
  • 토큰 전용 엔드포인트가 없어 당분간 POST /login을 씀

FcmTokenProvider의 메모리 캐시 제거

  • 캐시가 남아 있으면 갱신 이후에도 옛 토큰이 X-Fcm-Token에 실림
  • 호출할 때마다 저장소를 읽어 인터셉터가 항상 마지막 토큰을 보냄

토큰 없는 POST /login을 실패로 반환

  • AuthRepositoryImpl.login()에서 선확인 후 NO_FCM_TOKEN 에러 반환
  • 서버는 헤더 없는 요청을 LOGIN_SUCCESS로 돌려주므로 그대로 두면 재시도 경로가 닫힘
  • MainViewModel.serverLoginPending이 닫히지 않아 재연결 재시도가 살아남

Hilt Worker 설정

  • ApplicationClass가 Configuration.Provider 구현, HiltWorkerFactory 주입
  • 매니페스트에서 WorkManagerInitializer 제거
  • androidx.work:work-runtime-ktx:2.9.1, androidx.hilt:hilt-work:1.2.0 추가

테스트

SyncFcmTokenUseCaseTest

  • 로그인 전이면 전송하지 않고 SKIPPED
  • 저장된 토큰이 없으면 전송하지 않고 SKIPPED
  • 전송 성공 / 실패 분기
  • 토큰이 없어 로그인이 막히면 FAILURE
  • 대기 중 갱신 대비. 호출할 때마다 저장소를 다시 읽음

FcmTokenSyncPolicyTest

  • 상한 전까지 재시도, 상한에 닿으면 재시도하지 않음

MainViewModelTest

  • 토큰이 없어 실패하면 대기가 닫히지 않고 재연결 때 재시도

스크린샷 (선택)

💬리뷰 요구사항(선택)

리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요

ex) 메서드 XXX의 이름을 더 잘 짓고 싶은데 혹시 좋은 명칭이 있을까요?

ExistingWorkPolicy를 REPLACE로 뒀습니다. 실행 중인 워커가 있으면 취소되고 새로 시작합니다. 워커가 실행 시점에 최신 토큰을 읽으므로 KEEP도 동작하지만, 백오프 대기가 긴 상태에서 새 토큰이 오면 그대로 기다리게 됩니다. KEEP이 나을지 봐주세요.

재시도 상한을 5회로 뒀습니다. 30초 지수 백오프 기준 마지막 시도까지 약 8분입니다.

워커의 로그인 상태 확인은 회원ID 유무로 판단합니다. clearSession()이 인증 상태와 회원ID를 함께 지우고, MainViewModel의 진입 라우팅도 같은 기준을 씁니다.

이름 정리는 후속 PR로 분리했습니다. AuthRepository.login()을 FcmRepository.registerToken()으로 옮기는 작업입니다.

이번 범위 밖으로 남긴 것이 있습니다. 별도 이슈로 올릴 예정입니다.

  • 앱 진입의 ensureFcmRegistration()과 워커가 같은 일을 두 경로로 합니다. 진입 직후 토큰이 갱신되면 등록 요청이 두 번 나갈 수 있습니다
  • 진입 경로에는 백오프가 없어 재연결이 반복되면 요청이 연달아 나갑니다
  • 진입 경로를 워커로 합치려면 워커가 먼저 토큰을 갱신할 수 있어야 합니다. @AccessTokenWithFcmApi는 TokenAuthenticator의 401 자동 갱신을 건너뜁니다
  • 로그아웃 시 예약된 워커를 취소하지 않습니다. memberId가 지워져 SKIPPED로 끝나므로 동작은 안전합니다

@edv-Shinedv-Shin self-assigned this Aug 16, 2026
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@edv-Shin
edv-Shin merged commit 99f1e98 into devAug 16, 2026
1 check passed
Sign up for freeto 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.

[Fix] FCM 토큰이 바뀌어도 서버에 반영하지 않는 문제 수정

1 participant

@edv-Shin