You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
refactor(platform): 최종 앱 루트 책임 판정과 MVI 전환 종료 검사 (#1809 분리) #2022
여러 모듈 전환 뒤 수행해야 하는 MainViewModel의 최종 책임 판정과 MVI 전환 종료 검사만 #1809에서 분리한다. 알림 권한 ViewModel과 직접 Effect 전환은 독립 이슈 #1809에 남겼고 여기의 구현 범위에서 제외한다.
대상
MainViewModel. 앱 진입·라우팅 판정을 들고 있어 화면 ViewModel 과 성격이 다르다. MviViewModel 이 맞는지 먼저 판정하고, 아니면 전환하지 않는 근거를 이 이슈에 남긴 뒤 konsist allowlist 에 영구 예외로 등재한다.
전환 종료 처리
실제로 완료된 모듈 전환 산출물을 대조한 뒤 이 이슈에서 마무리한다. NOT_PLANNED로 닫힌 #1803은 전환 완료에 포함하지 않으며, 해당 수신자 흐름의 MVI 구현을 이 이슈에서 다시 예약하지 않는다.
Konsist allowlist를 실제 선언과 대조한다. 존재하지 않는 com.afternote.feature.receiver.presentation.home.ReceiverHomeViewModel 항목은 제거하고, 철회된 구 수신자 흐름의 현존 예외는 유지한다. 유효한 예외가 모두 없어졌을 때만 규칙 B의 예외 분기를 제거한다.
설정의 수신자 등록 화면(ReceiverRegisterViewModel)은 BE 에서 삭제된 POST users/receivers 를 부르는 화면이라 여기서 전환하지 않는다. 초대 흐름 전환과 함께 수신자 등록 카톡 초대 전환 — 이메일 등록·인증 대체 #944 에서 MVI 로 다시 만들고, 그 전까지는 남은 ViewModel 로 센다(2026-10-04 판정).
MviViewModel 을 상속하지 않는 ViewModel 이 남아 있다면, 각각 그 이유가 문서나 allowlist 주석에 적혀 있다
docs/convention/mvi.md 가 전환 완료 시점의 실제 코드와 일치한다
자식 이슈
No response
참고
MainViewModel 은 앱 시작 경로에 있다. release 전용 R8 크래시는 런타임 게이트가 전부 debug 라 잡지 못한 전례가 있다(0903 nav enum). 전환 시 minified 빌드로 앱 진입을 한 번 확인한다.
네비게이션은 이 전환 범위 밖이다. app 모듈은 #1698(소관 그래프 Nav3 이관)과 #1795(알림 목적지 결선)가 열려 있다. MainViewModel 이 라우팅 판정을 들고 있어 겹친다.
분리 근거
#1809의 알림 권한은 현재 확정 계약으로 독립 완료한다. 이 이슈는 기존 모듈 전환의 최종 산출물을 기다리는 종료 검사이며, MainViewModel 라우팅 책임이 #1702에서 바뀌므로 지금 임시 MVI 구현을 예약하지 않는다. 실제 최종 코드로 전환 필요성을 다시 판정한다.
2026-10-04 분리
체크리스트 첫 항목(allowlist 의 존재하지 않는 FQN 제거)과 같은 파일·mvi.md 의 낡은 개수·담당 문구 정리는 선행을 기다리지 않아 #2246 으로 뗐다. 규칙 B 예외 분기 제거와 MainViewModel 판정은 여기 남는다.
changed the title [-]refactor(platform): 알림 권한 ViewModel과 Effect를 MVI로 전환 (#1809 분리)[/-][+]refactor(platform): 최종 앱 루트 책임 판정과 MVI 전환 종료 검사 (#1809 분리)[/+]on Sep 13, 2026
실측 기록: 본문의 konsist 처방은 실행되지 않고, 종료 검사 2항의 기준 수치는 낡았다
기준 리비전은 origin/develop7d87aa3f4 (2026-09-13) 다. 이 이슈로 지금 쓸 코드는 0줄이다. 다음 착수자가 죽은 처방을 따라가거나 낡은 기준으로 종료 검사를 통과시키지 않도록 실측만 남긴다. 본문과 라벨은 건드리지 않았다.
1. "konsist allowlist 에 영구 예외로 등재한다" 는 지금 코드에서 실행되지 않는다
MainViewModel 은 규칙 B 의 후보 집합에 애초에 들어오지 않는다. konsist/src/test/kotlin/com/afternote/konsist/MviContractKonsistTest.kt:259 가 후보를 FEATURE_PRESENTATION_MAIN (:358, 정규식 feature/[^/]+/presentation/src/main/) 으로 거르는데, MainViewModel 은 app/src/main/java/com/afternote/afternote_fe/MainViewModel.kt 에 있다.
그래서 등재해도 세 군데가 어긋난다.
PENDING_MVI_MIGRATION 은 후보 집합에서 빼는 용도다 (:64 의 unmigratedViewModels(...) - PENDING_MVI_MIGRATION). 후보가 아닌 항목을 넣으면 빼 줄 것이 없다.
해소된 항목은 경고로 알린다 테스트 (:79-94) 는 PENDING_MVI_MIGRATION - unmigratedViewModels(...) 를 stale 로 출력한다. MainViewModel 항목은 영구 stale 경고가 된다.
이 이슈 완료 조건 1과 충돌한다. 목록이 비어야 규칙 B 의 예외 분기를 지우는데, 영구 예외를 넣으면 그 목록은 영원히 비지 않는다.
develop 은 이미 세 자리에 app 이 규칙 B 밖이라고 적어 뒀다. MviContractKonsistTest.kt:466-469 의 KDoc, 같은 파일 :174-186 의 규칙 B fixture 단언 (app/src/main/kotlin/app/AppViewModel.kt 를 넣고도 위반 0건을 단언한다), docs/convention/mvi.md:126.
경험적 확인도 있다. #1809 의 PR #2033 은 app 모듈의 NotificationPermissionViewModel 을 MVI 로 전환하면서 MviContractKonsistTest.kt 를 한 줄도 고치지 않았다. 그 PR 이 고친 konsist 파일은 ProductionVisibilityKonsistTest.kt 하나다. #1809 본문의 "konsist 임시 예외에서는 이 ViewModel만 제거한다" 도 같은 이유로 지울 항목이 없다.
따라서 최종 판정이 "전환하지 않는다" 로 나오더라도 근거를 남길 자리는 allowlist 가 아니다. MainViewModel 의 KDoc 이거나 문서이거나, 규칙 B 스코프를 app 까지 넓히는 별도 결정이다. 뒤쪽을 고르면 MainViewModel 이 그 순간 위반이 되어 완료 조건 1이 요구하는 빈 목록과 다시 충돌하므로, 그 결정에는 완료 조건 1의 개정이 딸려 온다.
위 세 자리의 문구는 분리 이후로 낡기도 했다. 셋 다 app 의 ViewModel 2개를 #1809 가 처리한다고 적는데, MainViewModel 판정은 이 이슈로 떨어져 나왔다.
2. 종료 검사 2항의 기준 수치 갱신
본문은 "현재 11개 VM · 참조 77곳" 인데 origin/develop7d87aa3f4 실측은 이렇다.
선언 22건의 모듈별 분해는 onboarding 11 (ViewModel 4개) · afternote 6 (ViewModel 3개) · receiver 5 (ViewModel 5개) 이고, app 모듈은 0건이다. 즉 이 항목에는 app 쪽으로 떼어낼 조각이 없다.
참조 112줄을 셀 때 주의할 것이 둘 있다. main 84줄 중 2줄은 core/ui 의 문서 주석 (mvi/MviContract.kt:21, mvi/ObserveSignal.kt:25) 이고, 3줄은 timeletter 의 컴포저블 파라미터 (TimeLetterNavGraph.kt:106, DraftLetterScreen.kt:45 와 :54) 라 ViewModel 선언과 무관하다. 종료 조건은 선언 0건이므로 22건 쪽을 보면 된다.
완료 조건 1의 allowlist 수치도 어긋나 있다. PENDING_MVI_MIGRATION 의 합집합은 지금 51개 (MviContractKonsistTest.kt:471) 인데 :466 KDoc 과 docs/convention/mvi.md:126 은 49개로 적는다. 모듈별 임자 분해는 #1813 코멘트에 있다.
#2038 (#1810) 은 docs/convention/mvi.md 에 네비게이션 경계 절을 새로 넣는다. 그 절이 세우는 경계는 피처 entry·host 소관이라 앱 루트 MainViewModel 을 다루지 않고 (그 PR 의 diff 에 MainViewModel 0건), 규칙 B 문장은 :126 에서 :165 로 밀릴 뿐 내용이 그대로다. 근거를 문서에 적는 선택을 하더라도 이 PR 이 들어간 뒤가 맞다.
다음 착수자가 볼 것
이 이슈로 지금 낼 코드 변경은 없다. 착수 시점은 blocked_by 10건이 닫힌 뒤다.
Activity
[-]refactor(platform): 알림 권한 ViewModel과 Effect를 MVI로 전환 (#1809 분리)[/-][+]refactor(platform): 최종 앱 루트 책임 판정과 MVI 전환 종료 검사 (#1809 분리)[/+]OnlyReadOneBook commentedon Sep 13, 2026
실측 기록: 본문의 konsist 처방은 실행되지 않고, 종료 검사 2항의 기준 수치는 낡았다
기준 리비전은
origin/develop7d87aa3f4(2026-09-13) 다. 이 이슈로 지금 쓸 코드는 0줄이다. 다음 착수자가 죽은 처방을 따라가거나 낡은 기준으로 종료 검사를 통과시키지 않도록 실측만 남긴다. 본문과 라벨은 건드리지 않았다.1. "konsist allowlist 에 영구 예외로 등재한다" 는 지금 코드에서 실행되지 않는다
MainViewModel은 규칙 B 의 후보 집합에 애초에 들어오지 않는다.konsist/src/test/kotlin/com/afternote/konsist/MviContractKonsistTest.kt:259가 후보를FEATURE_PRESENTATION_MAIN(:358, 정규식feature/[^/]+/presentation/src/main/) 으로 거르는데,MainViewModel은app/src/main/java/com/afternote/afternote_fe/MainViewModel.kt에 있다.그래서 등재해도 세 군데가 어긋난다.
PENDING_MVI_MIGRATION은 후보 집합에서 빼는 용도다 (:64의unmigratedViewModels(...) - PENDING_MVI_MIGRATION). 후보가 아닌 항목을 넣으면 빼 줄 것이 없다.해소된 항목은 경고로 알린다테스트 (:79-94) 는PENDING_MVI_MIGRATION - unmigratedViewModels(...)를 stale 로 출력한다.MainViewModel항목은 영구 stale 경고가 된다.develop 은 이미 세 자리에 app 이 규칙 B 밖이라고 적어 뒀다.
MviContractKonsistTest.kt:466-469의 KDoc, 같은 파일:174-186의 규칙 B fixture 단언 (app/src/main/kotlin/app/AppViewModel.kt를 넣고도 위반 0건을 단언한다),docs/convention/mvi.md:126.경험적 확인도 있다. #1809 의 PR #2033 은 app 모듈의
NotificationPermissionViewModel을 MVI 로 전환하면서MviContractKonsistTest.kt를 한 줄도 고치지 않았다. 그 PR 이 고친 konsist 파일은ProductionVisibilityKonsistTest.kt하나다. #1809 본문의 "konsist 임시 예외에서는 이 ViewModel만 제거한다" 도 같은 이유로 지울 항목이 없다.따라서 최종 판정이 "전환하지 않는다" 로 나오더라도 근거를 남길 자리는 allowlist 가 아니다.
MainViewModel의 KDoc 이거나 문서이거나, 규칙 B 스코프를 app 까지 넓히는 별도 결정이다. 뒤쪽을 고르면MainViewModel이 그 순간 위반이 되어 완료 조건 1이 요구하는 빈 목록과 다시 충돌하므로, 그 결정에는 완료 조건 1의 개정이 딸려 온다.위 세 자리의 문구는 분리 이후로 낡기도 했다. 셋 다 app 의 ViewModel 2개를 #1809 가 처리한다고 적는데,
MainViewModel판정은 이 이슈로 떨어져 나왔다.2. 종료 검사 2항의 기준 수치 갱신
본문은 "현재 11개 VM · 참조 77곳" 인데
origin/develop7d87aa3f4실측은 이렇다.onXxxConsumed()를 가진 ViewModel선언 22건의 모듈별 분해는 onboarding 11 (ViewModel 4개) · afternote 6 (ViewModel 3개) · receiver 5 (ViewModel 5개) 이고, app 모듈은 0건이다. 즉 이 항목에는 app 쪽으로 떼어낼 조각이 없다.
참조 112줄을 셀 때 주의할 것이 둘 있다. main 84줄 중 2줄은
core/ui의 문서 주석 (mvi/MviContract.kt:21,mvi/ObserveSignal.kt:25) 이고, 3줄은 timeletter 의 컴포저블 파라미터 (TimeLetterNavGraph.kt:106,DraftLetterScreen.kt:45와:54) 라 ViewModel 선언과 무관하다. 종료 조건은 선언 0건이므로 22건 쪽을 보면 된다.완료 조건 1의 allowlist 수치도 어긋나 있다.
PENDING_MVI_MIGRATION의 합집합은 지금 51개 (MviContractKonsistTest.kt:471) 인데:466KDoc 과docs/convention/mvi.md:126은 49개로 적는다. 모듈별 임자 분해는 #1813 코멘트에 있다.3. 판정을 지금 못 하는 이유
MainViewModel은 69줄이고 하는 일이 둘인데, 둘 다 열린 이슈 소유다.startRoute(:35-43). refactor(platform): 앱 루트를 Navigation 3 NavDisplay로 전환 #1702 가 앱 루트를NavDisplay로 바꾸면서startDestination개념 자체를 없앤다. feat(platform): 알림 목적지 이동을 앱 루트에 결선한다 — #1727 에서 Nav3 재작성분 분리 #1795 본문 13행과 대조표 20행에 명시돼 있다.pendingNotificationEntry:28,enqueueNotificationEntry:49,consumeNotificationEntry:60). feat(platform): 알림 목적지 이동을 앱 루트에 결선한다 — #1727 에서 Nav3 재작성분 분리 #1795 가 큐 소비를 앱 셸로 옮긴다. feat(platform): 알림 목적지 이동을 앱 루트에 결선한다 — #1727 에서 Nav3 재작성분 분리 #1795 는 blocked_by refactor(platform): 앱 루트를 Navigation 3 NavDisplay로 전환 #1702 다.지금 MVI 로 전환하면 #1702 와 #1795 가 다시 쓸 임시 구현이 된다. 이 큐 멤버들의 main 소비자가 0건인 상태와 그 사각지대는 #1795 코멘트 4절에 이미 실측해 뒀으니 여기서 반복하지 않는다.
대기 상태는
gh api repos/Afternote/Afternote-FE/issues/2022/dependencies/blocked_by로 확인했다. 등록된 blocked_by 10건이 전부 OPEN 이다. #1702 #1802 #1803 #1804 #1805 #1806 #1807 #1808 #1809 #2037. 본문 참고란이 열려 있다고 적은 #1698 은 지금 CLOSED 다.4. 지금 코드를 붙일 파일이 전부 열린 스택 안에 있다
MainViewModel.kt를 고치는 열린 PR 은 0건이지만, 이 이슈가 손댈 나머지 파일에는 임자가 있다. 열린 PR 62건 기준이다.konsist/.../MviContractKonsistTest.ktdocs/convention/mvi.mdapp/.../navigation/AppNavigation.kt#2038 (#1810) 은
docs/convention/mvi.md에 네비게이션 경계 절을 새로 넣는다. 그 절이 세우는 경계는 피처 entry·host 소관이라 앱 루트MainViewModel을 다루지 않고 (그 PR 의 diff 에MainViewModel0건), 규칙 B 문장은:126에서:165로 밀릴 뿐 내용이 그대로다. 근거를 문서에 적는 선택을 하더라도 이 PR 이 들어간 뒤가 맞다.다음 착수자가 볼 것
MainViewModel이지 지금 것이 아니다. refactor(platform): 앱 루트를 Navigation 3 NavDisplay로 전환 #1702 와 feat(platform): 알림 목적지 이동을 앱 루트에 결선한다 — #1727 에서 Nav3 재작성분 분리 #1795 가 두 책임을 모두 가져가면 판정할 코드 자체가 남지 않을 수 있다.