Skip to content

에디터 수신자 지정 불가 — 선택 화면 라우팅 미연결 + AuthorReceiverRepository 죽은 구현 (전 카테고리 신규 등록 차단) #540

Closed

Description

@OnlyReadOneBook

📜 Overview (Required)

애프터노트 에디터의 "수신자 추가" + 버튼이 무동작이다. AfternoteNavGraph.kt:74 에서 onNavigateToSelectReceiver = {} 로 비어 있고 주석이 // TODO: 수신인 선택 화면 라우팅 연결 이다. 애프터노트용 수신자 선택 화면 자체가 레포에 없다(마인드레코드 ReceiverSelectBottomSheet·타임레터 RecipientListScreen 은 각 기능 전용).

영향 카테고리 = 구현된 4종 전부(MEMORIAL·SOCIAL·BUSINESS·GALLERY). 갤러리는 원래 별도 다이얼로그 경로였으나 #680 수정(PR #774 머지)으로 그 경로가 폐기되고 같은 onNavigateToSelectReceiver 에 합류했다.

수신자는 서버 계약상 필수(등록 시 최소 1명, 미지정 시 400 code 1615 "수신자(receivers)는 최소 1명 이상 필요합니다" — 라이브 실측)라, 진입점이 죽어 있으면 해당 카테고리는 등록 자체가 불가능하다. 즉 #501 이 섹션을 노출시켜도 이 라우팅이 연결되기 전까지 등록 데드엔드는 남는다.

⚠️ 위 한 문단은 2026-08-03 이후로 사실이 아니다 — 아래 「등록 차단 논거 정정」 참조. 진입점이 죽어 있다는 진단 자체는 유효하다.

에뮬레이터 런타임 실측(2026-07-27): 소셜 에디터에서 수신자 +(y=1452) 탭 → 화면 전환·다이얼로그 없음, logcat 무반응.

📌 Child Issue(Optional)

No response

📍 Note (Optional)

  • ✅ 수신자 선택 화면 시안은 존재한다 — 디자인 게이트 해소(2026-08-08 Figma REST 실측). 이 이슈가 "시안 유무 확인 필요" 로 달아 둔 blocked: 디자인 은 미확인 상태에서 붙인 것이었고, 확인 결과 3벌이 있다: 115:15841 · 2249:14101 · 3631:24820. 셋 다 검색 필드 + 초성 인덱스(ㄱ~ㅎ) 구조이고, 가장 최근 것(3631:24820)에는 타이틀 "수신자 선택" 과 하단 "수신자 선택 완료하기" 버튼이 명시돼 있다.
  • ⏳ PM 논의 진행 중 — 진입 흐름 확장분(디자인 게이트 아님). 전건호 역질문(2026-08-06)에 대해 제안한 흐름은 "수신자 추가하기" → "수신자 선택" 개명 → 기존 수신자 시트 → 시트 하단 "+ 새 수신자 등록" → 설정>수신자 등록 화면 → 복귀 시 방금 등록한 수신자가 선택된 상태. 서버 영향은 0으로 확인됐다(ReceiverRequest 가 receiverId 단일 필드, 신규 등록 API 가 이미 receiverId 를 응답). "기존 목록에서 고르기" 본체는 어느 안이든 동일하므로 이 이슈의 라우팅 연결은 결론과 무관하게 착수 가능하고, "+ 새 수신자 등록" 진입만 결론 후 추가된다.
  • 기능적으로는 "이미 등록된 수신자 목록에서 고르기"가 맞다(서버가 기존 receiverId 를 요구하므로, 신규 생성 다이얼로그로는 유효한 id 를 만들 수 없다).
  • GET /users/receivers 로 사용자의 등록 수신자 목록을 받을 수 있다.
  • QA 근거: 노션 2차 QA(2026-07-28) 23번.

🔁 #935 흡수 (2026-08-24) — 원인은 둘이다

같은 데드엔드를 리포지토리 축에서 다시 진단한 #935 를 이 이슈로 흡수한다. 라우팅만 연결해도 수신자 지정은 여전히 동작하지 않는다 — 죽은 리포지토리가 두 번째 원인이기 때문이다. 아래는 origin/develop 실측(기준 6123a68a, 관련 파일은 #935 의 기준 커밋 104462fd 와 바이트 동일).

원인 A — 라우팅 미연결 (이 이슈의 원래 진단)

AfternoteNavGraph.kt:73 onNavigateToSelectReceiver = {}, // TODO: 수신인 선택 화면 라우팅 연결
→ 애프터노트용 수신자 선택 화면이 레포에 없다. 추가 확인: 선택 결과를 돌려받는 키 SELECTED_RECEIVER_ID_KEY 는 읽는 코드만 있고 쓰는 코드가 레포에 없다(NavigationKeys.kt:4 정의, AfternoteNavGraphEditor.kt:33-34 읽기·삭제).

원인 B — AuthorReceiverRepository 가 죽은 구현

AuthorReceiverRepositoryImpl 은 모든 메서드가 빈 값 또는 실패를 반환한다.

메서드 실제 반환
currentAuthorUserId() (L27) 항상 null (TODO)
refreshReceivers() (L29-38) 항상 실패 — userId 가 null 이라 fetchReceiversForUser 에 도달 불가
observeReceivers() (L22) 항상 emptyList() — 아무도 채우지 않는 in-memory MutableStateFlow
currentReceivers() (L24) 항상 emptyList()

에디터가 이걸 프로덕션 경로에서 소비한다 — AfternoteEditorViewModel L277 observeReceivers() · L312 refreshReceivers() · L558 getReceiverById().

폼에 수신자가 들어가는 경로 3개 중 2개가 이것 때문에 죽어 있다.

경로 상태
replaceReceiversIfEmpty(uiState.authorReceivers) — 신규 작성 시 (AfternoteNavGraphEditor.kt:131-133) ❌ authorReceivers 가 항상 빈 리스트
tryApplyReceiverSelectionFromSavedState → getReceiverById(id) ❌ currentReceivers() 가 비어 항상 null → early return (원인 A 로 애초에 호출도 안 됨)
applyPrefill — 수정 모드 (#566) ✅ 상세 응답에서 채워짐

즉 신규 작성 한정으로 수신자 지정이 불가능하고, 수정 모드는 prefill 덕에 살아 있다.

이미 동작하는 대체재가 있다 — UserRepository

core:domain 의 UserRepository 가 같은 기능을 하고, 수신자 목록 소비처 7곳이 이미 이것을 쓴다 — GetHomeSummaryUseCase:35 · TimeletterViewModel:63 · TimeLetterDetailViewModel:51 · TimeLetterWriteViewModel:60 · DiaryWriteViewModel:150 · ReceiverListViewModel:21 · RecipientListViewModel:21.

interface UserRepository {
    val receiverListFlow: Flow<List<Receiver>>   // observeReceivers() 의 역할을 커버
    suspend fun getReceivers(): List<Receiver>   // 파라미터 없음
}

AuthorReceiverRepository 는 이것의 죽은 병렬 구현이다.

currentAuthorUserId 는 애초에 불필요하다

  • GET users/receivers(UserApiService.kt:30) 는 파라미터가 없다 — 서버가 액세스 토큰으로 호출자를 식별한다
  • 실제로 userId 는 코드베이스 어디에도 저장되지 않는다. main 소스 전체에서 userId 는 8곳뿐이고 전부 회원가입 응답 경로(AuthDto → AccountRegistration → AuthMapper)와 이 죽은 Impl 이다. TokenDataSource·UserProfileDataSource 모두 userId 를 갖고 있지 않다
  • TODO 가 오래 안 풀린 것은 채울 소스가 없어서가 아니라 채울 필요가 없어서다

"userId 를 core 에서 관리하자" 가 아니라 "userId 개념 자체를 폐기" 가 맞다.


✅ 작업

A. 수신자 선택 화면 + 라우팅 (확정 사양: 위 Note 의 전건호 08-06 답글, 시안 3631:24820)

B. 죽은 리포지토리 제거 (#935 에서 흡수)

  • AfternoteEditorViewModel 을 UserRepository 로 전환 — observeReceivers() → receiverListFlow, refreshReceivers() → getReceivers(), getReceiverById(id) 를 Receiver 기준으로 재작성
  • AuthorReceiverEntry → core:model 의 Receiver(receiverId·name·relation) 로 통합, AuthorReceiverMapping.kt 갱신 또는 삭제
  • AuthorReceiverRepository·AuthorReceiverRepositoryImpl·AuthorReceiverEntry.kt 삭제
  • AfternoteAuthorRepositoryModule 의 bindAuthorReceiverRepository 삭제
  • androidTest 3파일의 Fake 구현 정리 — AfternoteAuthorAndroidTest:206 · AfternoteAuthorExtendedAndroidTest:521 · AfternoteAuthorImplementedCoverageAndroidTest:315 (PR androidTest 도메인 API 드리프트 44건+런타임 7건 수정, PR 컴파일 게이트 추가 #949 와 충돌 주의)

⚠️ 전환 시 주의

  • receiverListFlow 는 수신인 조회 실패가 receiverListFlow 미처리 예외로 전파 — 소비 화면 앱 크래시 #884(OPEN) 미해소 — 조회 실패가 미처리 예외로 전파돼 소비 화면이 크래시한다. 에디터를 여기 물리면 크래시 대상이 하나 늘어난다
  • 신규 작성 경로의 replaceReceiversIfEmpty(authorReceivers) 는 "등록된 수신자 전원 자동 지정"이다. B 만 하면 475 는 우회되지만 시안의 "골라서 지정" 의도와 어긋나므로, A 와 함께 이 자동 채움을 유지할지 판단이 필요하다
  • 기존 feat/540 브랜치(2026-08-14, c6a94702)는 AfternoteNavActions 스텁만 추가하고 getReceiverById 를 지운 채 호출처(AfternoteNavGraphEditor.kt:35)를 안 고쳐 컴파일이 깨진 미완성 상태다. 시그니처만 참고하고 develop 에서 새로 시작한다

🔧 등록 차단 논거 정정 (2026-08-29) — 심각도가 내려간다

이 이슈의 「서버가 수신자 최소 1명을 요구하므로 진입점이 죽으면 등록 자체가 불가능」 논거는 진단 시점(2026-07-27 라이브 실측)에는 사실이었으나 2026-08-03 이후로는 성립하지 않는다.

근거 — BE e7f073d(2026-08-03, hwanggyuun) 「fix: 애프터노트 생성 시 receivers·actions를 선택 필드로 완화」

문서만 맞추지 않고, 수신자·체크리스트 없이도 등록할 수 있게 생성 검증을 변경한다. SOCIAL credentials·PLAYLIST songs 등 카테고리 고유 필수는 유지한다.

BE origin/main(aba24df, 2026-08-27) 재실측 결과:

  • AfternoteValidationCommons.validateRequiredReceivers 는 정의만 남고 호출처 0건이다.
  • ErrorCode.RECEIVERS_REQUIRED(1615) 자체는 살아 있으나 애프터노트 생성 경로가 아니라 타임레터 SCHEDULED(TimeLetterService)와 수신자 서비스(ReceivedService·MindRecordReceiverService)에서만 던진다.

따라서 이 이슈가 푸는 것은 「전 카테고리 등록 차단(치명)」이 아니라 「신규 작성에서 수신자를 지정할 수단 부재(기능 결손)」다. 수신자 없이도 등록은 된다. 수정 모드는 prefill 로 살아 있으므로 영향은 신규 작성 경로에 한정된다.

제목의 「전 카테고리 신규 등록 차단」도 같은 이유로 과장이다. 이력 보존을 위해 제목은 두되 판정은 이 절을 따른다.

관련: 에디터의 필수 표시·검증 기준은 서버 계약을 따른다는 0829 확정에 따라, FE 쪽 수신자·처리방법 필수 취급도 #1334 에서 제거됐다.

Activity

  1. OnlyReadOneBook commented on Jul 28, 2026

    @OnlyReadOneBook
    CollaboratorAuthor

    2026-07-28 13:16 에뮬 런타임 재현 확인.

    노트 탭 → 작성 → 종류 = 소셜네트워크에서 "수신자 추가" 의 + 를 탭해도 화면 변화가 없습니다(UI 트리 변화 0). 같은 세션에서 종류를 "갤러리 및 파일" 로 바꾸면 같은 자리에서 수신자 입력 다이얼로그가 정상적으로 뜹니다.

    수신자는 등록 필수값이라(수신자를 한 명 이상 선택해 주세요. 검증) 소셜네트워크는 등록까지 진행할 수 없습니다.

  2. OnlyReadOneBook commented on Jul 28, 2026

    @OnlyReadOneBook
    CollaboratorAuthor

    최신 develop(18d65f84) 빌드에서도 그대로 재현됩니다. 2026-07-28 18:45 실측.

    노트 탭 → FAB → 소셜네트워크 에디터 → "수신자 추가" + 탭 → 화면 변화 0, 바텀시트·라우팅 없음. 애프터노트 등록 완주가 여전히 막혀 있습니다(수신자 최소 1명이 서버 필수값이라 등록 자체가 불가).

  3. OnlyReadOneBook commented on Jul 30, 2026

    @OnlyReadOneBook
    CollaboratorAuthor

    재현 확인 (2026-07-30, develop a3623e4b)

    소셜 에디터에서 "수신자 추가" + 버튼을 눌러도 화면 전환 없음 · 네트워크 호출 0건(logcat OkHttp). 두 번 탭해도 동일하다.

    같은 화면의 "처리 방법 리스트" + 버튼은 정상 동작한다 — 탭하면 "처리 방법을 입력해 주세요" 입력 행이 추가된다. 무동작인 것은 수신자 쪽 진입점뿐이다.

    수신자는 서버 필수값(code 1615)이라, 이 상태에서는 앱만으로 SOCIAL 애프터노트를 등록할 수 없다. 이번 QA 에서 애프터노트 데이터를 curl 로 만들어야 했던 이유이기도 하다.

  4. OnlyReadOneBook commented on Aug 8, 2026

    @OnlyReadOneBook
    CollaboratorAuthor

    갱신: #680 수정(feat/680, PR 예정)으로 갤러리 다이얼로그 경로가 폐기되고 GALLERY 도 onNavigateToSelectReceiver 로 통일된다. 그 머지 후에는 본문의 "갤러리만 별도 다이얼로그 경로라 동작한다" 서술이 낡고, 이 라우팅 미연결의 영향 카테고리는 4종 전부(MEMORIAL·SOCIAL·BUSINESS·GALLERY) 가 된다. 이 이슈 해소 시 갤러리 진입점도 함께 살아난다.

  5. OnlyReadOneBook commented on Aug 8, 2026

    @OnlyReadOneBook
    CollaboratorAuthor

    라우팅 목적지 사양이 확정됐습니다 — 갤러리 에디터 프레임 700-38183 의 핀 스레드, 전건호 08-06 답글(댓글 1873986804):

    • 작성 화면 버튼 문구 "수신자 선택" → 탭하면 기존 수신자 목록 시트
    • 시트 하단 "+ 새 수신자 등록" → 설정 > 수신자 등록 화면으로 이동
    • 등록 완료 후 작성 화면 복귀 — 방금 등록한 수신자가 선택된 상태, 작성 중 내용 유지
    • 애프터노트·타임레터·마음의 기록 전 제품 통일 방향(타 제품 반영은 각 담당 몫)

    #680 (PR 예정) 머지 시 GALLERY 도 본 이슈의 라우팅 미연결 그룹에 합류해 해소 범위가 4개 카테고리 전부가 됩니다. 선택 결과 수신 배선은 tryApplyReceiverSelectionFromSavedState(SELECTED_RECEIVER_ID_KEY)가 이미 준비돼 있습니다.

  6. OnlyReadOneBook commented on Aug 21, 2026

    @OnlyReadOneBook
    CollaboratorAuthor

    2026-08-21 배포 후보 직접 QA — GALLERY까지 범위 확대 재현

    배포 기준 보정 후 대상인 cc725f47d0704e2b05cab65726ae66b4812c9337(PR #802 merge SHA, 현재 앱 트리와 동일)에서 에뮬레이터로 재현했습니다.

    재현

    1. 애프터노트 신규 작성 진입
    2. 종류를 갤러리 및 파일로 변경
    3. 수신자 추가의 + 탭
    4. 화면 이동·다이얼로그·수신자 선택 UI가 모두 발생하지 않고 에디터에 그대로 머묾

    접근성 트리상 버튼은 clickable=true, bounds [478,838][604,964]였고 탭 후에도 화면에는 갤러리 및 파일, 수신자 추가, 처리 방법 리스트가 그대로 남았습니다.

    현재 원인 지점

    • AfternoteEditorContent.kt: GALLERY의 onAddClick = onNavigateToSelectReceiver
    • AfternoteNavGraph.kt: onNavigateToSelectReceiver = {} // TODO: 수신인 선택 화면 라우팅 연결

    #680에서 GALLERY의 잘못된 직접입력/임시 ID 경로는 제거됐지만, 그 결과 GALLERY도 이 미연결 콜백을 사용하게 됐습니다. 따라서 현재 영향 범위는 기존 본문의 MEMORIAL·SOCIAL·BUSINESS가 아니라 GALLERY를 포함한 구현 카테고리 전부입니다.

    담당은 현재 assignee(1hyok)와 blame(80783a49e, 해당 TODO 배선) 기준이 일치해 유지합니다.

  7. changed the title [-]fix(afternote): 에디터 수신자 추가 진입점 무동작 — 수신인 선택 화면 라우팅 미연결 (MEMORIAL·SOCIAL·BUSINESS 등록 차단)[/-] [+]fix(afternote): 에디터 수신자 지정 불가 — 선택 화면 라우팅 미연결 + AuthorReceiverRepository 죽은 구현 (전 카테고리 신규 등록 차단)[/+] on Aug 23, 2026
  8. changed the title [-]fix(afternote): 에디터 수신자 지정 불가 — 선택 화면 라우팅 미연결 + AuthorReceiverRepository 죽은 구현 (전 카테고리 신규 등록 차단)[/-] [+]에디터 수신자 지정 불가 — 선택 화면 라우팅 미연결 + AuthorReceiverRepository 죽은 구현 (전 카테고리 신규 등록 차단)[/+] on Aug 28, 2026
  9. OnlyReadOneBook commented on Aug 28, 2026

    @OnlyReadOneBook
    CollaboratorAuthor

    라우팅 연결·수신자 선택 화면·SELECTED_RECEIVER_ID_KEY 결과 반환은 PR #1372 로 반영됐다(원인 B 의 죽은 리포지토리는 현 develop 에서 이미 해소돼 있어 원인 A 만 남아 있었음). 이 이슈는 #791(수신자 선택 공용 컴포넌트 추출)에 blocked 로 걸려 있어 #791 결론 후 공용 전환 여부를 정리하면서 닫는다. «+ 새 수신자 등록» 진입 확장은 PM 결론 대기로 계속 범위 밖.

  10. OnlyReadOneBook commented on Aug 29, 2026

    @OnlyReadOneBook
    CollaboratorAuthor

    ✅ 완료 — 닫는다 (2026-08-30 실측)

    원인 A·B 가 모두 해소돼 이 이슈에 남은 작업이 없다.

    원인 상태 근거
    A. 라우팅 미연결 ✅ 해소 PR #1372 (2026-08-29 머지) — 수신자 선택 화면 신설 + AfternoteNavGraph.kt:63 onNavigateToSelectReceiver = actions::navigateToSelectReceiver
    A-2. SELECTED_RECEIVER_ID_KEY 쓰는 코드 0건 ✅ 해소 AppNavigationActions.kt:478 이 쓰고, AfternoteNavGraphEditor.kt:50-51 이 읽고 지운다
    B. AuthorReceiverRepository 죽은 구현 ✅ 해소 0828 코멘트대로 현 develop 에서 이미 해소돼 있었음
    blocked_by #791 (공용 컴포넌트 추출) ✅ CLOSED/COMPLETED —

    origin/develop 실측으로 author/editor/receiver/select/SelectReceiverViewModel.kt · author/navigation/AfternoteNavGraphSelectReceiver.kt 존재를 확인했다.

    이 이슈에서 갈라져 나간 갈래 — 전부 열린 이슈가 추적 중

    이슈 담당 내용
    #1405 1hyok 목록 로드 실패 시 선택이 조용히 소실 — PR #1529 진행 중
    #1426 1hyok 1회 1명 제한 — 반환 채널만 단일, 폼·서버는 복수 지원
    #1427 1hyok 수신자 0건 화면에 등록 진입 CTA 부재 (「+ 새 수신자 등록」 확장분)
    #872 koongmai 같은 흐름의 타임레터 몫

    「+ 새 수신자 등록」 PM 논의 대기분은 #1427 이 이어받았으므로 이 이슈를 대기 상태로 열어 둘 이유가 없다.

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

Metadata

Metadata

Labels

area:afternote애프터노트 기능 영역bugSomething isn't working

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions