Skip to content

상세·하위 화면 9종이 재진입 시 미갱신 — load() 가 에러 재시도에만 결선 #703

Closed
1 of 2 issues completed

Description

@1hyok

📜 Overview (Required)

타임레터 상세 3종은 load() 를 에러 상태의 재시도 버튼에만 결선했고, 정상 표시 중에는 갱신 수단이 없다. 설정 하위 화면들은 재로드 진입점 자체가 없다.

실측 (2026-08-03, develop)

화면 ViewModel 상태
타임레터 상세 TimeLetterDetailViewModel.load() TimeLetterDetailScreen.kt:76 에러 재시도 버튼에만 결선
수신 타임레터 목록 RecipientTimeletterViewModel.load() RecipientTimeletterScreen.kt:86 〃
수신 타임레터 상세 RecipientTimeLetterDetailViewModel.load() RecipientTimeLetterDetailScreen.kt:76 〃
타임레터 임시저장 DraftLetterViewModel.loadDrafts() 정의 있음, 화면 재진입 결선 없음
타임레터 수신자 목록 RecipientListViewModel 재로드 진입점 없음
설정 - 계정 연결 ConnectedAccountsViewModel init 1회 로드, 재로드 진입점 없음
설정 - 사후 전달 조건 DeliveryConditionViewModel 〃
설정 - 프로필 수정 ProfileEditViewModel 〃
설정 - 알림 설정 PushNotificationViewModel 〃

가장 확실한 피해 경로 — 타임레터 상세에서 수정하고 돌아오거나, 설정 하위 화면에서 값을 바꾸고 다시 들어와도 이전 값이 남는다. 에러가 나야만 다시 불러올 수 있다는 것은, 성공한 화면일수록 오래된 값을 붙들고 있다는 뜻이다.

대조군 — 같은 모듈의 타임레터 목록과 설정 메인은 결선되어 있다.

  • TimeletterScreen.kt:60-61 — repeatOnLifecycle(STARTED) 로 재진입마다 load()
  • SettingScreen.kt:69 — viewModel.refresh()

상세·하위 화면만 같은 결선이 빠진 상태다.

해야 할 일

  1. 타임레터 상세 3종의 load() 를 화면 재진입 시점에도 결선 — TimeletterScreen 이 쓰는 repeatOnLifecycle 패턴을 그대로 따르면 된다
  2. 설정 하위 4종에 재진입 갱신 결선
  3. 목록성 화면(타임레터 임시저장·수신자 목록)에 당겨서 새로고침을 둘지 결정

📌 Child Issue(Optional)

2026-09-06 담당 범위별로 이슈와 PR을 분리했습니다. 이 이슈는 두 하위 작업을 함께 추적하며, 어느 한쪽 PR의 병합만으로 닫지 않습니다.

📍 Note (Optional)

설정 수신자 목록은 같은 계열이지만 #579 로 이미 등록되어 있어 이 이슈에서 제외했다.

전 앱 62개 화면 중 당겨서 새로고침이 있는 곳은 홈 탭·애프터노트 홈 2곳뿐이고, 재진입 갱신이 결선된 곳은 6곳뿐이다(2026-08-03 실측). 같은 계열을 담당별로 나눠 등록했다 — 애프터노트·수신자 흐름 #701, 마인드레코드 #702, 타임레터·설정 #703, 설정 수신자 목록 #579.

Activity

  1. added
    bugSomething isn't working
    on Aug 3, 2026
  2. added theissue type on Aug 3, 2026
  3. changed the title [-]fix(timeletter,setting): 상세·하위 화면 9종이 재진입 시 미갱신 — load() 가 에러 재시도에만 결선[/-] [+]상세·하위 화면 9종이 재진입 시 미갱신 — load() 가 에러 재시도에만 결선[/+] on Aug 28, 2026
  4. added
    pr-open이 이슈를 구현하는 PR 이 열려 있다 — base 가 기본 브랜치가 아니어도 드러낸다
    on Sep 5, 2026
  5. assigned and unassigned on Sep 6, 2026
  6. removed
    pr-open이 이슈를 구현하는 PR 이 열려 있다 — base 가 기본 브랜치가 아니어도 드러낸다
    on Sep 6, 2026
  7. 1hyok commented on Sep 13, 2026

    @1hyok
    CollaboratorAuthor

    실측 기록: 지금 여기서 뗄 코드 범위는 없고, 대신 남기는 네 가지

    origin/develop 7d87aa3f4 (2026-09-13) 기준으로 본문 실측표를 다시 쟀다. 결론은 이 이슈가 지금 순수 추적용이라는 것이고, 그래서 코드 대신 기록을 남긴다. 본문은 고치지 않았다. 아래가 정정분이다.

    1. 9종 전부 미결선이 맞고, 표의 줄 번호는 밀렸다

    재진입마다 서버 상태를 갱신하도록 결선된 것은 9종 중 0건이다. 타임레터 상세 3종은 여전히 에러 재시도 버튼에만 load() 가 걸려 있다. 결선 상태 자체는 본문 그대로 유효하고, 줄 번호만 어긋난다.

    파일 본문 표 develop 7d87aa3f4
    TimeLetterDetailScreen.kt :76 :84
    RecipientTimeletterScreen.kt :86 :90
    RecipientTimeLetterDetailScreen.kt :76 :84
    TimeletterScreen.kt (대조군) :60-61 :72-74
    SettingScreen.kt (대조군) :69 :69 (그대로)

    설정 4종 VM 은 init 1회 로드에 private 로드 함수뿐이라는 것도 그대로다. ConnectedAccountsViewModel.kt:29·:33, DeliveryConditionViewModel.kt:40·:44, ProfileEditViewModel.kt:27·:31, PushNotificationViewModel.kt:50·:62·:84.

    하위 둘은 모두 열려 있다. #1920 OPEN(1hyok), #1921 OPEN(koongmai), PR #1930 OPEN·MERGEABLE(base handoff/708-setting-1hyok), PR #1905 OPEN·MERGEABLE(base develop, head f0cfec520). 열린 PR 62건의 본문에서 Closes 를 전수 검색해도 이 범위를 무는 것은 #1930(Closes #1920)과 #1905(Closes #1921) 둘뿐이다. #2034 는 Closes #579 로 별건이다. 두 PR 이 들어오기 전까지 여기서 낼 코드가 없다.

    2. 「해야 할 일」 3번은 어느 하위 이슈도 물지 않는다

    당겨서 새로고침 결정(3번)이 #1920 완료 조건에도 #1921 완료 조건에도 없다. 두 하위가 다 닫혀도 3번은 미결로 남는다.

    다만 develop 실코드가 이 항목의 전제를 이미 약화시켰다.

    • 임시저장은 복귀 경로 한정으로 이미 결선돼 있다. TimeLetterNavGraph.kt:97-110·:152-157 의 savedStateHandle 키 timeletter_draft_changed 로, 작성·수정 화면에서 목록으로 돌아오면 DraftLetterScreen.kt:52-57 이 loadDrafts() 를 부른다. 커밋 68ed54514 (2026-08-27), 본문 실측일 8월 3일 이후에 들어왔다. 본문 표의 「정의 있음, 화면 재진입 결선 없음」은 「복귀 경로 한정 결선 있음」으로 읽어야 한다.
    • 수신자 목록은 명시적 refresh 함수가 없는 것은 맞지만 「재로드 진입점 없음」은 오해를 부른다. RecipientListViewModel.kt:20-27 이 SharingStarted.WhileSubscribed(5_000) 로 receiverListFlow 를 구독하고, UserReceiverRepositoryImpl.kt:62-77 의 그 flow 는 콜드라 새 구독마다 서버를 다시 조회한다(UserRepositoryImplTest.kt:151 의 「새 구독은 서버에서 목록을 다시 조회한다」가 고정). 화면이 collectAsStateWithLifecycle 이므로 5초 넘게 벗어났다 돌아오면 이미 자동 재조회된다. 남는 구멍은 5초 이내 재진입뿐이다.

    여기에 #1905 가 두 화면 모두에 ON_RESUME refreshOnReturn() 을 얹는다(fix/703 f0cfec520 기준 DraftLetterScreen.kt:68-70, RecipientListScreen.kt:58-60). 당겨서 새로고침까지 넣으면 같은 화면에 갱신 경로가 셋이 된다. 구독 재개와 resume 가 같은 조회를 두 번 보낸다는 지적은 #1905 의 RecipientListViewModel.kt:41 리뷰 스레드에 아직 열려 있다. 결정 자체는 타임레터 담당(koongmai) 몫으로 남긴다.

    3. 설정 쪽에 표에 없는 10번째 화면이 있다

    PushNotificationViewModel 에는 라우트가 둘 붙어 있다. SettingNavGraph.kt:103-108 의 NotificationRoute(NotificationSettingScreen)와 :110-114 의 PushNotificationRoute(PushNotificationScreen). 본문 표는 이 VM 을 화면 한 개로 셌고, #1920 은 대상에 PushNotificationScreen 만 적었다.

    NotificationSettingScreen 은 develop(:85-87)에서도 #1930 HEAD(handoff/1920-setting-1hyok :90-91)에서도 ON_RESUME 에 기기 알림 권한(로컬값)만 보낸다. 정작 이 화면만 그리는 서버 값인 마케팅 수신 동의 sms·email·push 는 재진입에 갱신되지 않는다. DeviceAlarmOffSection 을 실제로 호출하는 곳은 NotificationSettingScreen.kt:163 하나뿐이고(PushNotificationScreen.kt:12 는 import 만 남아 있다), 그 값을 채우는 loadMarketingConsents() 는 develop :84, #1930 HEAD :206 모두 init 에서만 불린다. #1930 이 추가하는 refreshOnReturn()(HEAD :163-170)도 refreshDeviceAlarmStatus() 와 loadPushSettings() 만 부른다.

    가드로는 드러나지 않는다. RefreshOnReturnWiringKonsistTest 는 refreshOnReturn 을 선언한 VM 에 결선 사이트가 최소 하나 있는지만 보고, KDoc :30-32 에서 스스로 「ON_RESUME 에서 정말 그 ViewModel 의 것을 부르는가」까지는 보지 않는다고 적어 두었다. PushNotificationScreen.kt:27 한 곳만 결선돼도 초록이다.

    여기서 코드로 메우지 않는 이유. develop 의 PushNotificationViewModel 은 아직 MVI 가 아니라서(onIntent 없음, _uiState 직접 갱신) develop 위에서 고치면 #1967 → #1925 → #1930 스택이 들어오는 즉시 Intent 방식으로 다시 쓰게 되고, PushNotificationViewModel.kt 에서 #1930 과 충돌한다. 자리는 새 PR 이 아니라 #1930(이슈 #1920) 범위 확장이다.

    4. Note 의 집계 정정

    「재진입 갱신이 결선된 곳은 6곳뿐이다(2026-08-03 실측)」는 낡았다. 형제 이슈 #702(마인드레코드)가 CLOSED/COMPLETED 로 들어오면서 늘었다. develop 에서 다시 세면 이렇다.

    • refreshOnReturn() 을 선언한 ViewModel 12개, 그 ON_RESUME 결선 파일 12개. AppNavigation.kt:144-150, AfternoteDetailRoute.kt:160, ReceivedAfternoteDetailRoute.kt:45, ReceivedAfternoteNavHost.kt:80, ReceiverHomeEntry.kt:25, HomeTabMindRecordLazyItems.kt:93, ReceiverMindRecordScreen.kt:78, DailyQuestionAnswerListScreen.kt:60, DiaryScreen.kt:77, DraftListScreen.kt:88, WeeklyReportScreen.kt:55, SenderDetailScreen.kt:69.
    • 다른 패턴 둘: SettingScreen.kt:69 의 refresh(), TimeletterScreen.kt:72-74 의 repeatOnLifecycle(STARTED) + load().
    • NotificationSettingScreen.kt:85-87 은 ON_RESUME 이 있으나 기기 알림 권한만 갱신하므로 서버 상태 갱신으로 세지 않는다.

    즉 서버 상태를 재진입에 갱신하는 결선 파일은 14개다. *Screen.kt 파일만 세면 9개인데, 결선이 Route·NavHost·NavGraph·Entry 파일에도 있어서 화면 파일만 세면 실태를 못 잡는다. 「전 앱 62개 화면」도 세는 단위가 무엇이었는지 알 수 없어 확정 오류로 적지 않는다. 다시 잰다면 기준을 같이 적는 편이 낫다. presentation 모듈 main 소스셋의 *Screen.kt 파일은 70개다.

    git ls-tree -r --name-only origin/develop | grep -E '/presentation/src/main/.*Screen\.kt$' | wc -l
    

    당겨서 새로고침이 2곳뿐이라는 것은 그대로 유효하다. HomeTabScreen.kt:139, AfternoteHomeScreen.kt:114.

    한 가지 더. RefreshOnReturnWiringKonsistTest 는 #1930 이 새로 세우는 가드가 아니라 develop 에 이미 있는 가드다(8b9fd0131, 2026-08-31, #701 계열. 963bf304f #1725 로 공유 스코프 진입점을 쓰게 다듬었다). #1930 은 여기에 MVI 의 onIntent(XIntent.RefreshOnReturn) 결선까지 같은 계약으로 검사하도록 확장한다.

  8. 1hyok commented on Sep 20, 2026

    @1hyok
    CollaboratorAuthor

    2026-09-20 하위 이슈·PR 상태를 다시 확인했습니다.

    이 이슈에서 새로 분리해 구현할 잔여 화면은 없습니다. #1920과 #1921의 실제 최종 소비 구현과 병합을 확인해야 하며, 한쪽이 닫혔다는 이유로 전체 완료로 처리하지 않습니다. 목록의 당겨서 새로고침 제공 여부를 아직 확정된 추가 구현으로 간주하지 않습니다.

  9. 1hyok commented on Sep 23, 2026

    @1hyok
    CollaboratorAuthor

    추적을 하위 이슈로 옮기고 닫는다 (2026-09-23)

    이 이슈는 09-06 에 담당별로 나눈 뒤 두 하위를 함께 추적하는 역할만 남아 있었다. 범위를 다 끝내서 닫는 것이 아니다. 추적을 하위 두 이슈로 옮기고 닫는다. 두 하위가 각자의 담당 큐에 서 있어 진행 상황은 하위 자체로 보인다. #928·#945 와 같은 처리다.

    하위 담당 범위 상태
    #1920 1hyok 설정 4종과 NotificationSettingScreen OPEN, #708 에 blocked. 이전 PR #1930 은 미병합으로 닫힘
    #1921 koongmai 타임레터 5종 OPEN, PR #1905 (base develop) 승인

    "한쪽만으로 닫지 않는다"는 조건과의 관계

    본문의 "어느 한쪽 PR의 병합만으로 닫지 않습니다", #1920 본문의 "이 이슈 완료만으로 상위 #703 전체를 닫지 않는다", 09-20 코멘트의 "#1920과 #1921의 실제 최종 소비 구현과 병합을 확인해야 하며"는 한쪽만 끝났을 때 전체를 완료로 처리하지 말라는 조건이다. 이 조건은 #1920 과 #1921 이 각자의 구현이 머지되어 닫히는 것으로 충족된다. 부모를 열어 둔다고 더 확인되는 것은 없다. #1920 본문의 그 줄도 이 처리에 맞춰 고쳤다.

    옮긴 것과 예약하지 않은 것

    • 09-13 코멘트 3번의 10번째 화면(NotificationSettingScreen 의 마케팅 수신 동의가 재진입에 갱신되지 않음)은 이 이슈 코멘트에만 있었다. fix(setting): 설정 하위 화면 4종의 재진입 갱신 (#703 분리) #1920 본문의 대상과 완료 조건에 옮겼다. develop f69332d 에서도 NotificationSettingScreen.kt:83 의 ON_RESUME 은 refreshDeviceAlarmStatus() 만 부르고, loadMarketingConsents() 는 PushNotificationViewModel.kt:53 의 init 에서만 불린다.
    • 본문 "해야 할 일" 3번(목록 화면에 당겨서 새로고침을 둘지)은 기능 제공 여부라 PM 확인 대상이다. 어느 하위의 완료 조건으로도 옮기지 않았다. 제공하기로 결정되면 그때 최신 코드 기준으로 새 이슈를 등록한다.
    • PR fix(timeletter): 타임레터 하위 화면 5종의 재진입 갱신 (#1921) #1905 본문의 Refs #703 은 그대로 둔다.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:setting설정 기능 영역area:timeletter타임레터 기능 영역bugSomething isn't working

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions