Skip to content

fix(setting): 수신자 등록이 BE 가 지운 POST users/receivers 를 아직 부른다 #2078

Closed

Description

@1hyok

작업 유형

bug — 버그·오동작

주 담당 모듈

setting — 설정

개요

수신자 등록 화면에서 저장을 누르면 서버에 없는 엔드포인트를 부른다. BE 가 2026-09-08 에 지운 경로다.

FE 호출 경로는 ReceiverRegisterViewModel.kt:59 → UserReceiverRepositoryImpl.kt:115 → UserApiService.kt:39 의 @POST("users/receivers") 다. 그런데 Afternote-BE main(3593aa3)의 UserController 매핑을 전수로 보면 /receivers 아래에 @GetMapping, @GetMapping("/{receiverId}"), @PatchMapping("/{receiverId}"), @PatchMapping("/{receiverId}/message"), @PatchMapping("/{receiverId}/relation"), @DeleteMapping("/{receiverId}") 는 있고 @PostMapping 만 없다. BE PR #289(2026-09-08T05:57:54Z 머지)가 핸들러와 UserCreateReceiverRequest·UserCreateReceiverResponse·UserServiceCreateReceiverTest 를 함께 삭제했다.

즉 FE 의 수신자 엔드포인트 5개 중 등록 하나만 죽었다. 목록·상세·수정·메시지 수정은 그대로 동작한다.

대체 경로는 초대 발급이다. POST /api/v1/receiver-invitations 가 초대를 만들고, GET /api/v1/receiver-invitations/{token} 으로 조회하며, POST /api/v1/receiver-invitations/{token}/accept 로 수락한다. 등록 시점에는 수신자가 생기지 않고 상대가 수락해야 생긴다. 그래서 등록 직후 receiverId 가 없다.

BE 가 안드로이드 연동 가이드를 노션에 써 두었다. 커스텀 스킴, 토큰 임시 보관과 가입 후 재개 분기, 오류별 처리, QA 체크리스트, 배포 전 공유값 목록이 들어 있다. Deferred Deep Link 는 백엔드 범위 밖이라고 선언돼 있다.

부수로 확인된 것 하나. BE 에 새로 생긴 PATCH /users/receivers/{receiverId}/relation 이 FE UserApiService 에 없다. 초대 수락 시 관계와 메시지가 null 로 저장되므로 나중에 채우는 경로로 보인다.

참고

Activity

  1. github-actions commented on Sep 13, 2026

    @github-actions
    Contributor

    bug 이슈는 사이드바 Fields > Priority 로 심각도를 지정해야 합니다. 판정 기준:

    • Urgent: 치명 — 크래시·데이터 소실·보안 무력화·핵심 경로 차단·가짜 성공
    • High: 심각 — 실패·틀린 값의 정상 위장, 핵심 기능 무동작
    • Medium: 불편 — 우회로가 있는 오동작·틀린 표시, 핵심 흐름은 유지
    • Low: 경미 — 문구·정렬·마감 품질 흠, 기능 영향 없음

    값이 비어 있어도 이슈를 닫지는 않습니다. 이 안내는 이슈당 한 번만 답니다.

  2. 1hyok commented on Sep 13, 2026

    @1hyok
    CollaboratorAuthor

    이 이슈에서 지금 코드로 뗄 독립 범위가 없다고 판정했다. 전환과 화면 배선은 #1948 의 계약 확정과 #944 의 소유라 통째로 막혀 있다. 남은 후보 둘도 값이 없었다. 405 를 별도 분기로 잡아 안내 문구를 고치는 것은, 그 분기의 유일한 생산자가 지금 죽은 POST 하나뿐이라 전환이 POST 를 지우는 순간 분기와 문자열이 같이 지워진다. PATCH /users/receivers/{receiverId}/relation 을 UserApiService 에 미리 넣는 것은 소비처인 초대 수락 흐름이 저장소에 통째로 없어서 죽은 계약이 된다.

    대신 다음 착수자가 바로 쓸 실측을 남긴다. 기준 커밋은 origin/develop 7d87aa3 다.

    1. 죽은 호출이 재시도 안내로 둔갑한다

    core/data/.../UserReceiverRepositoryImpl.kt:203-212 의 mapReceiverRequestFailure 가 208 줄에서 error.status in setOf(400, 409) && !serverMessage.isNullOrBlank() 일 때만 ReceiverRequestRejectedException 으로 바꾼다. 405 는 raw ApiException 으로 그대로 통과한다.

    그걸 ReceiverRegisterViewModel.kt:68-71 의 onFailure 가 받아 toReceiverFailureMessage(R.string.receiver_register_failed) 를 부르고, ReceiverFailureMessage.kt:16-23 이 타입이 ReceiverRequestRejectedException 이 아니면 fallback 가지로 접는다. 최종 문구는 feature/setting/presentation/src/main/res/values/strings.xml:163 의 "수신자 등록에 실패했습니다. 잠시 후 다시 시도해주세요." 다.

    405 나 코드 1005 를 다루는 분기는 저장소 *.kt 전체에 0건이다(git grep -w). 그리고 70 줄이 isLoading 만 false 로 되돌리고 같은 폼에 errorMessage 를 세우므로, 영구 실패와 일시 실패가 화면에서 구분되지 않는다. 사용자는 다시 눌러도 되는 것으로 안내받는다.

    2. 죽은 화면으로 들어가는 살아 있는 진입이 두 곳이다

    설정 홈 메뉴가 하나다. SettingScreen.kt:199-202 의 settings_recipient_register 항목이 SettingNavGraph.kt:50 을 거쳐 SettingNavGraph.kt:137-141 의 ReceiverRegisterScreen 으로 간다.

    홈의 수신인 지정 칩이 나머지 하나다. GetHomeSummaryUseCase.kt:64 가 isRecipientDesignated = receivers.isNotEmpty() 로 정하고, false 면 HomeTabScreen.kt:167-171 이 RecipientDesignationBadgeState.Incomplete 에 onClick 을 걸며, AppNavigationActions.kt:304-311 이 SettingRoute.RecipientRegisterRoute 로 보낸다.

    즉 수신자가 하나도 없는 사용자는 홈에서 전원 이 죽은 폼으로 간다. 비어 있는 Priority 필드를 정할 때 쓸 근거다.

    3. 같은 자리를 물고 있는 열린 PR

    경로 이동도 하나 걸려 있다. #2053 (base refactor/1064-setting-unused)이 ReceiverRegisterViewModel.kt, ReceiverFailureMessage.kt, ReceiverRegisterScreen.kt 를 presentation/viewmodel, presentation/screen 에서 presentation/receiver 로 rename 하고 #2055 가 그 위에 스택돼 있다. #1967 (base codex/1695-setting-nav3)은 ReceiverRegisterViewModel 을 MVI 계약으로 갈아엎는다. 위 줄 번호는 전부 develop 기준이니, 이 스택들이 들어온 뒤에는 경로가 아니라 심볼명으로 다시 찾아야 한다.

    4. 지금 코드를 안 대는 근거

    #944 본문은 "기존 이메일 흐름을 미리 삭제하거나 임시 초대 화면으로 대체하지 않는다" 고 적는다. #1948 본문은 "현행 등록 실패 처리나 목록 표시 개선까지 일괄 중단하는 의미는 아니다" 라고 적는다. 그러니 문구 수준 처방 자체가 금지된 것은 아니다. 다만 1번의 405 경로는 생산자가 전환과 함께 사라지므로, 지금 넣으면 되돌릴 임시 구현이 된다. 먼저 고치겠다면 전환 PR 에서 같이 지우는 것을 전제로 잡아야 한다.

    남은 것과 풀려야 하는 순서

    남은 것은 전환 전체다. 순서는 #1948 의 초대 계약 확정이 먼저고 그 뒤에 #944 의 화면, 공유, 상태 배선이다. #1586 과 #709 는 POST 가 사라지면 전제가 함께 사라진다.

    본문의 부재 사실은 재확인 시점에도 그대로다. receiver-invitations, inviteToken, ShareClient 는 저장소에 0건이고, gradle/libs.versions.toml 에는 v2-user 와 v2-auth 만 있고 v2-share 가 없다.

  3. 1hyok commented on Sep 19, 2026

    @1hyok
    CollaboratorAuthor

    2026-09-19 정리로 닫는다. 이 이슈의 완료 조건은 PM의 결정에 달려 있어 결정 전에는 FE 가 무엇을 만들지 쓸 수 없다. 그런 이슈는 FE 저장소에 열어 두지 않고 결정이 나면 그때 새 이슈로 다시 연다.

    기다리는 결정: 이메일 등록 버튼과 폼 값의 처리(#1948 질문).

    PM 질문은 창구가 정해지는 대로 보낸다(일혁이 목록 보관).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:setting설정 기능 영역bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions