Repository navigation
refactor(afternote): 에디터 파라미터 봉투 2종 언번들 — AfternoteEditorScreenCallbacks·AfternoteEditorNavigationParams, no-op 디폴트 제거 포함 #602
Description
📜 Overview (Required)
#439(콜백/Params grab-bag 언번들)의 감사에서 빠진 파라미터 봉투가 에디터 흐름에 2개 남아 있다. 둘 다 대상 목록에도, 본문의 "제외" 항목(MemorialPlaylistEntryActions·MemorialGuidelineEditorContentParams)에도 없다. 성격과 처분이 같아 한 이슈로 묶어 처리한다.
1. AfternoteEditorScreenCallbacks
묶여 있는 근거가 이미 무효다. KDoc 은 콜백 그룹 (S107: 파라미터 7개 이하 유지) 라고 적고 있는데, #439 가 "≤7(S107) 은 이 repo 미강제(detekt/sonar 없음) 자율규약이라 번들 정당화 근거가 아님"으로 판정한 바로 그 근거다. 현재도 detekt·sonar 설정은 레포에 없다.
디폴트 = {} 도 함께 걷는다. 8개 콜백 전부 = {} 디폴트를 갖고 AfternoteEditorScreen 은 callbacks: AfternoteEditorScreenCallbacks = AfternoteEditorScreenCallbacks() 로 no-arg 인스턴스를 기본값으로 받는다. 그런데 AfternoteEditorScreen 호출처는 AfternoteNavGraphEditor 한 곳뿐이고 거기서 콜백을 모두 채워 넘긴다 — Preview 도 스크린샷 테스트도 이 화면을 직접 호출하지 않아, no-op 디폴트가 실제로 소비되는 자리가 없다. 대가만 남는다: 배선을 빠뜨려도 컴파일이 통과하고 조용히 아무 일도 안 한다. 특히 onThumbnailExtractionFailed 는 텔레메트리 콜백이라 누락돼도 화면에 증상이 없어 침묵으로 끝난다.
2. AfternoteEditorNavigationParams (AfternoteNavGraphEditor.kt:69)
같은 형태다 — 9필드 중 7개가 람다이고, @Composable AfternoteEditorNavigation(params: AfternoteEditorNavigationParams) 에 넘기기만 하는 봉투다.
internal data class AfternoteEditorNavigationParams(
val backStackEntry: NavBackStackEntry,
val liveSongs: List<Song>,
val onReplaceSongs: (List<Song>) -> Unit,
val onClearSongs: () -> Unit,
val onNavigateToSelectReceiver: () -> Unit = {},
val onBottomNavTabSelected: (BottomNavTab) -> Unit = {},
val onPopBackStack: () -> Unit,
val onNavigateToMemorialPlaylist: () -> Unit,
val onSaveSuccessNavigateHome: () -> Unit,
)여기도 no-op 디폴트가 2개(onNavigateToSelectReceiver·onBottomNavTabSelected)인데, 생성처는 AfternoteNavGraph.kt 한 곳뿐이고 거기서 둘 다 채워 넘긴다. 소비되지 않는 디폴트다. 덧붙여 onNavigateToSelectReceiver 는 그 유일한 생성처에서 {} // TODO: 수신인 선택 화면 라우팅 연결 로 비어 있다 — 디폴트가 있어 이 미배선이 컴파일·리뷰 어디에도 안 걸린다.
판단 근거 (공통)
- grab-bag 금지 — compose-component-api-guidelines.md 의 Prefer multiple components over style classes 의
Avoid grab-bag style parameters and classes, akin to ComponentStyle or ComponentConfiguration. DON'T 예시class ButtonStyles(background, border, textColor, shape, contentPadding)와 같은 모양이다. - 묶어도 되는 예외에 해당하지 않음 — compose-api-guidelines.md 의 Hoisted state types 가 허용하는 건 상호의존하는 값을
@Stableinterface 로 묶는 경우다(scrollPosition을scrollRange로 clamp 해야 하는 관계). 두 봉투 모두 필드끼리 서로를 제약하지 않고, 형태도 data class 다. ⚠️ 필드 개수는 근거가 아니다 — 많다고 묶을 이유도, 줄었다고 풀 이유도 되지 않는다. 공식 가이드라인 2종에 파라미터 개수 상한 규칙은 없다(too many·number of parameters·parameter count전수 검색 0건). 같은 판정을 refactor(afternote): MemorialEditorContentParams 언번들 — #439 제외 판정 근거(파라미터 개수) 무효 #677 에 적용했다.- 성능 근거 — 람다를 data class 로 묶으면 recomposition skip 이 깨진다(refactor(afternote): grab-bag 콜백/Params 데이터 클래스 flat 파라미터로 언번들 #439 승계).
flat 파라미터로 풀고 디폴트를 제거하면 배선 누락이 컴파일 타임에 잡힌다.
📌 Child Issue(Optional)
No response
📍 Note (Optional)
-
refactor(afternote): grab-bag 콜백/Params 데이터 클래스 flat 파라미터로 언번들 #439 의 판단 근거(Compose 공식 API 가이드의
Avoid grab-bag style parameters and classes, 람다를 data class 로 묶으면 recomposition skip 이 깨진다는 점)를 그대로 승계한다. -
feat(core): non-fatal 오류 계측 확대 — 홈·애프터노트 흐름의 handled 실패 기록 #544 계측 작업에서
onThumbnailExtractionFailed를AfternoteEditorScreenCallbacks에 추가했다 — 언번들 시 함께 flat 으로 나간다. -
같은 파일의
SaveAfternoteMemorialMedia는 응집된 값객체라 대상 아님. -
두 봉투 모두
AfternoteNavGraphEditor.kt를 경유하므로 함께 푸는 편이 배선 대조가 쉽다. -
같은 근거의 잔여 건은 refactor(afternote): MemorialEditorContentParams 언번들 — #439 제외 판정 근거(파라미터 개수) 무효 #677(
MemorialEditorContentParams). 파일이 겹치지 않아 의존은 없다. -
겹침 (2026-08-02 재실측 — 게이트가 3건에서 5건으로 늘었다): 같은 디렉터리 수준이 아니라 같은 파일이고, 대상 파일 4개 중 3개를 열린 PR 5건이 전부 점유하고 있다.
파일 feat(core): non-fatal 오류 계측 확대 — 홈·애프터노트·수신자 흐름 handled 실패 기록 (closes 544) #605 fix(afternote): 등록 실패 시 서버 원문 대신 일반 문구 폴백 — 5xx 내부 SQL 노출 차단 (closes 511) #621 fix(afternote): 수신자 열람 인증 스낵바 서버 문구 표시를 안내된 4xx 거절로 제한 (closes 651) #655 fix(afternote): 수정 진입 시 기존 수신자 prefill 및 분위기 기능 제거 (closes 566) #679 refactor(afternote): 에디터 폼 상태·갱신 통로 재설계 — 카테고리별 sealed 분리 (closes 675) [base: develop] #682 AfternoteEditorScreenModels.kt(Callbacks 정의)✓ ✓ ✓ ✓ – AfternoteNavGraphEditor.kt(생성처·NavigationParams 정의)✓ ✓ ✓ ✓ ✓ AfternoteEditorScreen.kt(소비·no-op 디폴트)✓ ✓ ✓ ✓ ✓ AfternoteNavGraph.kt(NavigationParams 생성)– – – ✓ – 충돌의 성격이 텍스트가 아니다. feat(core): non-fatal 오류 계측 확대 — 홈·애프터노트·수신자 흐름 handled 실패 기록 (closes 544) #605·fix(afternote): 등록 실패 시 서버 원문 대신 일반 문구 폴백 — 5xx 내부 SQL 노출 차단 (closes 511) #621·fix(afternote): 수신자 열람 인증 스낵바 서버 문구 표시를 안내된 4xx 거절로 제한 (closes 651) #655 는 봉투에 필드를 추가하는 방향으로(feat(core): non-fatal 오류 계측 확대 — 홈·애프터노트·수신자 흐름 handled 실패 기록 (closes 544) #605 의
onThumbnailExtractionFailed가 그 예), fix(afternote): 수정 진입 시 기존 수신자 prefill 및 분위기 기능 제거 (closes 566) #679·refactor(afternote): 에디터 폼 상태·갱신 통로 재설계 — 카테고리별 sealed 분리 (closes 675) [base: develop] #682 는 필드 개명·배선 재작성 방향으로 같은 정의를 고치는 중인데, 이 이슈는 그 봉투 자체를 삭제한다 — "삭제한 클래스에 필드 추가" 형태라 자동 병합으로 풀리지 않는다.5건 전부 머지된 뒤 develop 기준으로 착수한다.
feat/675위에 스택으로 쌓으면 fix(afternote): 수정 진입 시 기존 수신자 prefill 및 분위기 기능 제거 (closes 566) #679·refactor(afternote): 에디터 폼 상태·갱신 통로 재설계 — 카테고리별 sealed 분리 (closes 675) [base: develop] #682 와의 충돌만 피할 수 있고, base 가 develop 인 feat(core): non-fatal 오류 계측 확대 — 홈·애프터노트·수신자 흐름 handled 실패 기록 (closes 544) #605·fix(afternote): 등록 실패 시 서버 원문 대신 일반 문구 폴백 — 5xx 내부 SQL 노출 차단 (closes 511) #621·fix(afternote): 수신자 열람 인증 스낵바 서버 문구 표시를 안내된 4xx 거절로 제한 (closes 651) #655 가 머지되는 순간 스택 전체가 같은 충돌을 다시 겪는다.
Activity
feat: 에디터 에러 보고 추가 및 관련 모델 주석 현행화
[-]refactor(afternote): AfternoteEditorScreenCallbacks 언번들 — #439 감사 누락분, no-op 디폴트 제거 포함[/-][+]refactor(afternote): 에디터 파라미터 봉투 2종 언번들 — AfternoteEditorScreenCallbacks·AfternoteEditorNavigationParams, no-op 디폴트 제거 포함[/+]