Skip to content

feat(platform): 알림 목적지 이동을 앱 루트에 결선한다 — #1727 에서 Nav3 재작성분 분리 #1795

Open

Description

@OnlyReadOneBook

작업 유형

enhancement — 신규 기능·기존 기능 개선

주 담당 모듈

platform — Android 앱·CI·빌드·릴리스·저장소 운영

개요

#1727 (PR #1641) 이 세우는 알림 목적지 이동에서 Navigation 3 이관 때 다시 쓰는 앱 루트 결선 을 분리해 받는다 — AppNavigation.kt 의 호출부 8줄(0903 분리)에 더해, 0904 에 NotificationEntryEffect 컴포저블 본체도 PR 에서 걷어 여기로 옮겼다(본체가 AppState.navigateToBottomBarRoute 에 묶여 있어 미참조로 남겨 둘 이유가 없다).

이 결선은 앱 루트 NavHost 에 붙는데, #1702 가 그 루트를 NavDisplay 로 교체하며 startDestination 개념 자체를 없앤다.

범위

대상 Nav2 였다면 Nav3 에서
결선 위치 AppNavigation.kt 의 NavHost 옆 NotificationEntryEffect(...) NavDisplay 를 소유하는 앱 셸
인증 관문 판정 isSignedIn = startDestination == Route.Home startDestination 이 없다 — 백스택 시드 또는 인증 상태를 직접 읽어야 한다
목적지 이동 appState.navigateToBottomBarRoute(...) (내부가 popUpTo·saveState·restoreState) 탭별 로컬 스택 전환 계약
큐 소비 효과 NotificationEntryEffect(appState, isSignedIn) — Activity 의 MainViewModel.pendingNotificationEntry 를 LaunchedEffect(identityKey, isSignedIn) 로 읽어 이동 뒤 consumeNotificationEntry 같은 큐를 앱 셸이 소비 — 이동 프리미티브만 Nav3 계약으로

NotificationDestination.toRoute() 매핑, 인텐트 수신, PendingIntent 빌더 통합은 엔진 무관이라 #1727 에 남는다 — #1111 본문도 「어떤 Navigation 을 쓰든 필요한 인프라」 로 적어 두었다.

보존해야 할 동작

  1. 로그아웃 상태에서 알림을 타면 목적지로 가지 않는다 — 인증 관문을 건너뛰지 않는다.
  2. 로그인 상태면 지정 목적지 탭으로 이동하고, 미지정·해석 실패는 홈으로 떨어진다.
  3. 같은 알림을 두 번 처리하지 않는다.

보존해야 할 판단 (PR #1641 본문에서 옮김)

  • 로그아웃 상태에서는 소비하지 않고 큐에 남긴다. Nav2 에선 startDestination == Route.Home 이 «로그인 확정» 그 자체였다. 로그아웃이면 온보딩이고, 그때 목적지로 보내면 알림이 인증 관문을 건너뛰는 통로가 된다. 남겨 두면 로그인이 확정되는 순간 효과가 다시 돌아 그 목적지로 이어진다.
  • 이동은 바텀바 탭을 누른 것과 같은 백스택 규약을 재사용한다. 목적지가 전부 바텀바 최상위라 별도 이동 규칙을 만들면 같은 화면 조합에 두 벌의 백스택 동작이 생긴다.
  • MainActivity 는 손대지 않는다. 효과가 Activity 와 같은 ViewModelStoreOwner 에서 hiltViewModel() 로 같은 MainViewModel 인스턴스를 받는다(NotificationPermissionEffect 와 같은 방식). 파라미터로 내려보내면 onXxx = {} no-op 디폴트가 필요해지고 그건 NoOpCallbackDefaultKonsistTest 가 막는다(refactor(platform): 컴포저블 no-op 콜백 디폴트 — 재발 가드·컨벤션 도입 + afternote 잔여 2건 #1388).

완료 조건

의존 관계

자식 이슈

없음

참고

Activity

  1. OnlyReadOneBook commented on Sep 7, 2026

    @OnlyReadOneBook
    CollaboratorAuthor

    PR #1641의 최신 Repository Quality 검사에서 NotificationDestination.toRoute()는 프로덕션 소비자가 없고 매핑 테스트만 호출하는 것으로 확인됐습니다. 사용자 요청에 따라 해당 함수/파일과 NotificationDestinationRouteTest 3건, Konsist의 해당 예외를 #1641에서 제거합니다.

    이 이슈(#1795)에서 Nav3 앱 셸의 실제 알림 소비 경로를 연결할 때 목적지 계약값(home/mind_record/time_letter/afternote)을 실제 탭으로 변환하는 구현과 동작 검증을 함께 추가해 주세요. 로그아웃 시 큐 보존, 로그인 후 지정 탭 이동/홈 폴백, 이동 후 occurrence 단회 소비가 검증 범위입니다. #1641에는 목적지 vocabulary, PendingIntent extra 전달, Intent 파싱/폴백, source+occurrence identity 계약이 그대로 남습니다. 테스트만을 위한 프로덕션 선언이나 예외 라벨은 추가하지 않습니다.

  2. OnlyReadOneBook commented on Sep 13, 2026

    @OnlyReadOneBook
    CollaboratorAuthor

    develop 실측으로 본문을 고치는 기록

    origin/develop 7d87aa3 (0913) 기준으로 본문을 재확인했다. 코드 PR 은 0줄이다. 본문이 적어 둔 범위가 0908 에 한 번 더 움직였고, 완료 조건 하나는 가리키는 대상이 사라졌다. 본문만 믿고 착수하면 없는 파일을 찾고 없는 baseline 줄을 지우려 하게 된다.

    지금 develop 에 이미 있는 것

    #1727 이 남긴 부분은 그대로 서 있다. 목적지 계약값 4종(core/common/.../notification/NotificationDestination.kt, home · mind_record · time_letter · afternote), MainActivity.kt:96 의 인텐트 파싱 후 enqueueNotificationEntry 호출, MainViewModel.kt 의 큐(:49 enqueue · :28 pendingNotificationEntry · :60 consumeNotificationEntry), 그리고 NotificationNavigationAndroidTest.kt 의 수신 계측 4건.

    없는 것은 소비 쪽 전부다. 큐를 읽어 이동시키는 코드와, 목적지를 탭으로 옮기는 매핑이 둘 다 develop 에 없다.

    1. 분리는 2건이 아니라 3건이다

    본문이 적은 두 건 뒤에 한 건이 더 있다.

    커밋 날짜 뗀 것
    fd60e6aa1 0903 AppNavigation.kt 결선 8줄
    ea7d65d13 0904 NotificationEntryEffect.kt 본체 42줄
    f282cfc91 0908 NotificationDestinationRoute.kt 24줄, NotificationDestinationRouteTest.kt 37줄, 그리고 ea7d65d13 이 막 올렸던 Konsist baseline 항목 3줄

    세 번째 건은 0907 코멘트가 예고한 제거가 실제로 착지한 것이다. 그 코멘트는 예고였고 여기는 착지 실측이라 커밋과 줄 수를 남긴다.

    2. 본문의 "toRoute 매핑은 #1727 에 남는다" 는 develop 에서 거짓이다

    git grep toRoute -- app/src/main 이 0건이고 파일 자체가 없다. 이 이슈의 범위는 효과 본체뿐 아니라 toRoute 매핑과 그 테스트 3건(목적지 4종이 서로 다른 Route 로 간다, Route 가 바텀바 최상위 안에 있다, 폴백은 홈이다)까지 다시 만드는 것으로 늘었다.

    복원 원본은 지워지기 직전 커밋에 그대로 있다.

    git show f282cfc91^:app/src/main/java/com/afternote/afternote_fe/navigation/NotificationDestinationRoute.kt
    git show f282cfc91^:app/src/test/java/com/afternote/afternote_fe/navigation/NotificationDestinationRouteTest.kt
    git show ea7d65d13^:app/src/main/java/com/afternote/afternote_fe/navigation/NotificationEntryEffect.kt
    

    이 매핑을 지금 미리 넣는 것은 안 된다. 0908 에 "프로덕션 소비자가 없다" 는 이유로 지운 코드라 소비자인 루트 결선 없이 다시 넣으면 같은 상태로 돌아가고, .github/scripts/validate-test-only-production-declarations.mjs (#1895) 가 PR 이 src/main 에 새로 넣은 미참조 선언을 잡아 떨어뜨린다. 결선과 같은 PR 에서 함께 올려야 한다.

    3. 완료 조건 4 는 이미 무효다

    "#1727 이 남긴 미참조 프로덕션 선언이 해소되어 ProductionVisibilityKonsistTest baseline 에서 빠진다" 는 뺄 줄이 없다. konsist/src/test/kotlin/com/afternote/konsist/ProductionVisibilityKonsistTest.kt:380 의 INTENTIONAL_PRODUCTION_CONTRACTS 에 이 이슈로 미룬 항목은 0건이다. 선언을 baseline 에 올려 둔 게 아니라 f282cfc91 이 선언을 통째로 지웠기 때문이다.

    4. 대신 완료 조건 4 를 이 자리로 다시 쓴다

    실제로 남은 미참조 선언은 어느 게이트에도 안 걸리는 곳에 있다. app/src/main/java/com/afternote/afternote_fe/MainViewModel.kt:28 의 pendingNotificationEntry 와 :60 의 consumeNotificationEntry 가 main 소비자 0건이다. MainActivity.kt:96 은 enqueueNotificationEntry 만 부르고, 나머지 참조는 MainViewModelNotificationTest 와 NotificationColdStartAndroidTest 뿐이다.

    이게 안 잡히는 이유는 두 게이트의 사각이 겹쳐서다. ProductionVisibilityKonsistTest 는 최상위 선언만 보고(.github/workflows/repository-quality.yml:229 의 주석이 같은 사각을 적어 둔다), #1895 가드는 PR 이 새로 추가한 선언만 본다. 이미 들어와 있는 멤버 선언은 둘 다 지나간다.

    따라서 완료 조건 4 는 "이 둘에 main 소비자가 생긴다" 로 읽는 편이 맞다. 결선이 붙으면 자연히 충족된다.

    5. 완료 조건 2 의 앵커

    보존 동작 3건을 검증할 자리는 이미 현행 동작 단언으로 박혀 있다. app/src/androidTest/java/com/afternote/afternote_fe/NotificationNavigationAndroidTest.kt:139-140 은 로그인 warm 진입에서 타임레터 탭에 머무는 것을, :165-166 은 background 진입에서 홈 탭에 머무는 것을 단언한다. 둘 다 이 이슈 번호를 적은 주석이 위에 붙어 있다.

    결선 때 이 두 단언을 목적지 탭 단언으로 뒤집는다. 뒷건은 테스트 이름도 backgroundNotification_resumesSameActivityAndKeepsCurrentScreen 에서 이동 단언으로 되돌려야 한다. 앞건 이름은 warmNotificationWhileLoggedIn_isReceivedWithoutRecreatingActivity 라 그대로 둬도 된다.

    6. 블로커 체인 실측

    blocked_by 인 #1702 는 오늘 기준 선행 4건 중 #1698 만 CLOSED 다. #1695 OPEN(1hyok), #1696 OPEN(koongmai), #1697 OPEN(Sadturtleman, 다시 #959 에 막혀 있다). 남은 셋 중 둘이 내 모듈 밖이라 #1702 는 임박하지 않았다. 이 이슈는 당분간 대기가 맞다.

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

Metadata

Metadata

Labels

area:platformCI·빌드·릴리스·저장소 운영 영역enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions