Repository navigation
refactor(afternote): 에디터 폼 갱신 통로 updateForm 을 개별 콜백으로 분리 — 파사드 19개 지점 #674
Description
📜 Overview (Required)
에디터 폼 갱신이 updateForm 이라는 상태 변환 람다 하나를 통로로 쓴다. UI 파사드가 (EditorFormState) -> EditorFormState 를 받아 ViewModel 이 소유한 폼 SSOT 를 임의로 변환하는 구조다.
// AfternoteEditorViewModel.kt:204
fun updateForm(block: (EditorFormState) -> EditorFormState) {
internalState.update { prev -> prev.copy(form = block(prev.form)) }
persistFormSnapshot(internalState.value.form)
}파사드 AfternoteEditorState 가 이 통로를 19곳에서 쓴다 — syncMemorialPlaylistSongs(71) · resetMemorialPlaylistFormSnapshot(76) · selectCategory(90, private — onCategorySelected·selectCategoryByNavKey 가 호출) · onServiceSelected(104) · onMemorialPhotoSelected(109) · onFuneralVideoSelected(113) · onFuneralThumbnailDataUrlReady(117) · onAddCustomService(130) · onAddAfternoteEditorReceiver(140) · onAfternoteEditorReceiverDelete(155) · addReceiverFromSelection(168) · replaceReceiversIfEmpty(182) · addEditorMessage(190) · removeEditorMessage(200) · persistEditorMessagesFromTyping(233) · applyFormPrefill(248) · addProcessingMethod(268) · deleteProcessingMethod(279) · editProcessingMethod(288).
공식 가이드가 권장하는 형태는 개별 콜백이다. State holders 는 "If the shorter-lived state holder needs certain information from a higher-scoped state holder, pass only the information it needs as a parameter instead of passing the state holder instance." 라고 적고, 예제에서 private val doSomething: () -> Unit 처럼 필요한 동작만 개별로 받는 형태를 보여 준다. UI layer 의 "Only sources or owners of data should be responsible for updating the data they expose." 도 같은 방향이다.
작업: 파사드 19개 지점이 updateForm { ... } 대신 각자 대응하는 ViewModel 콜백을 호출하도록 바꾸고, 실제 copy(...) 는 ViewModel 안에서 수행한다. 파사드의 공개 메서드 이름·시그니처는 유지되므로 컴포저블 호출부는 영향이 없다.
📍 Note (Optional)
- 2026-05-02 에 "reducer 유지" 로 결정했던 건을 2026-08-02 에 뒤집은 것이다. 당시 근거로 기록돼 있던 사용자 발언 인용이 실제 발언이 아니었고, 공식 문서를 대조한 뒤 전환하기로 확정했다.
AfternoteEditorUiHolder는 대상이 아니다 — 탭·다이얼로그·드롭다운·TextFieldState만 들고 ViewModel 참조가 없어 State holders 문서의 UI logic state holder 정의에 정확히 부합한다.- refactor(afternote): 에디터 폼 상태·갱신 통로 재설계 — EditorFormState 카테고리별 sealed 분리 + updateForm 개별 콜백화 #675 와 합본한다. refactor(afternote): 에디터 폼 상태·갱신 통로 재설계 — EditorFormState 카테고리별 sealed 분리 + updateForm 개별 콜백화 #675(EditorFormState sealed 분리)가 같은 19블록의
copy(...)를 카테고리별when으로 재작성하므로, 나눠 진행하면 뒤엣것이 앞엣것을 통째로 다시 쓴다. 같은 브랜치에서 refactor(afternote): 에디터 폼 갱신 통로 updateForm 을 개별 콜백으로 분리 — 파사드 19개 지점 #674 → refactor(afternote): 에디터 폼 상태·갱신 통로 재설계 — EditorFormState 카테고리별 sealed 분리 + updateForm 개별 콜백화 #675 순으로 처리한다 — 이 작업이 끝나면copy(...)가 ViewModel 한곳에 모여 refactor(afternote): 에디터 폼 상태·갱신 통로 재설계 — EditorFormState 카테고리별 sealed 분리 + updateForm 개별 콜백화 #675 의 분기 작성 지점이 파사드 19곳에서 ViewModel 로 줄어든다. - base 브랜치는
develop이 아니라feat/566(fix(afternote): 수정 진입 시 기존 수신자 prefill 및 분위기 기능 제거 (closes 566) #679)이다. 본문의 지점 수·라인 번호는 fix(afternote): 수정 진입 시 기존 수신자 prefill 및 분위기 기능 제거 (closes 566) #679 기준으로 현행화했다(develop 기준으로는 20곳 —selectedLastWish갱신 1곳이 fix(afternote): 수정 진입 시 기존 수신자 prefill 및 분위기 기능 제거 (closes 566) #679 에서 기능째 제거됐다). develop 은 feat/566 의 순수 조상이다(rev-list --left-right --count origin/develop...origin/feat/566=0 7). - feat(core): non-fatal 오류 계측 확대 — 홈·애프터노트·수신자 흐름 handled 실패 기록 (closes 544) #605·fix(afternote): 등록 실패 시 서버 원문 대신 일반 문구 폴백 — 5xx 내부 SQL 노출 차단 (closes 511) #621·fix(afternote): 수신자 열람 인증 스낵바 서버 문구 표시를 안내된 4xx 거절로 제한 (closes 651) #655 와의 겹침은
AfternoteEditorViewModel.kt의 import·catch 지점뿐이라(세 PR 모두AfternoteEditorState.kt미포함) 착수 차단 요인이 아니다. - 함께 유지되는 분리선(별건): ViewModel 에
Context주입 금지 / Compose UI 객체 소유 금지.
Activity
[-]refactor(afternote): 에디터 폼 갱신 통로 updateForm 을 개별 콜백으로 분리 — 파사드 20개 함수[/-][+]refactor(afternote): 에디터 폼 갱신 통로 updateForm 을 개별 콜백으로 분리 — 파사드 19개 지점[/+]OnlyReadOneBook commentedon Aug 2, 2026
#675 로 합본한다.
두 작업이
AfternoteEditorState의 같은 19개updateForm { it.copy(...) }블록을 각자 재작성해서, 나눠 진행하면 뒤엣것이 앞엣것을 통째로 다시 쓴다. 이 이슈의 내용(공식 문서 근거·2026-05-02 "reducer 유지" 결정 역전 기록·대상 19개 지점 목록)은 #675 본문으로 옮겼다.작업 자체가 취소된 것이 아니라 #675 에서 함께 처리된다.