refactor(platform): 컴포저블 no-op 콜백 디폴트 — 재발 가드·컨벤션 도입 + afternote 잔여 2건 #1388
Copy link
Copy link
Closed
Labels
area:platformCI·빌드·릴리스·저장소 운영 영역CI·빌드·릴리스·저장소 운영 영역refactor동작 변경 없이 코드 구조·책임·경계를 개선하는 작업동작 변경 없이 코드 구조·책임·경계를 개선하는 작업
Description
작업 유형
refactor — 동작 변경 없는 구조·책임·경계 개선
주 담당 모듈
platform — Android 앱·CI·빌드·릴리스·저장소 운영
개요
컴포저블 콜백 파라미터의 no-op 디폴트(onXxx: (...) -> Unit = {})는 배선을 빠뜨려도 컴파일이 통과하고 조용히 no-op 이 되게 한다. 실사고 전례가 #582 · #618 · #722 · #777 로 반복됐다.
2026-08-30 — 담당 모듈별로 분할했다. 이 이슈에는 전 모듈 공통 재발 가드·컨벤션과 afternote 잔여 2건만 남는다. 실제 청소 작업 84건은 아래 자식 이슈가 담당한다.
현행 실측 (origin/develop, 2026-08-30)
git grep -cE "on[A-Z][A-Za-z]*: \(\([^)]*\) -> Unit\) = \{ ?\}" -- "*/src/main/*.kt"
| 모듈 | 0828 최초 실측 | 현행 | 담당 | 추적 |
|---|---|---|---|---|
| mindrecord | 33 | 47 (+14) | @Sadturtleman | #1540 |
| timeletter | 34 | 34 | @koongmai | #1541 |
| home | 3 | 3 | @Sadturtleman | #1540 |
| afternote | 24 | 2 | @1hyok | 이 이슈 |
| receiver | 14 | 0 ✅ | @1hyok | 해소됨 |
| core · app | 0 | 0 | — | — |
| 합계 | 108 | 86 |
afternote 22건과 receiver 14건은 그동안의 개별 PR 로 해소됐다. 이 이슈의 직접 청소 범위는 2건으로 줄었다.
feature/afternote/presentation/.../author/detail/MemorialDetailScreen.kt:93 onEditClick: () -> Unit = {},
feature/afternote/presentation/.../author/detail/MemorialDetailScreen.kt:94 onDeleteConfirm: () -> Unit = {},
🔴 청소만으로는 끝나지 않는다 — 재발이 실측됐다
부모 이슈를 연 지 이틀 만에 mindrecord 가 33 → 47 로 늘었다. 유입은 두 파일에 집중됐고, 주 유입 커밋은 69f63a22f (refactor(mindrecord): 작성 화면의 screenshotTest용 Content 경계를 분리한다) 다.
| 파일 | 0828 | 현행 |
|---|---|---|
DiaryWriteScreen.kt |
3 | 11 |
DailyQuestionWriteScreen.kt |
3 | 9 |
screenshotTest·프리뷰 용으로 Content 경계를 분리하면서 새 컴포저블에 디폴트를 붙이는 것이 현재의 주 유입 경로다. 호출부에서 {} 를 명시하면 되는 자리이므로 선언에 디폴트를 둘 이유가 없다. 이 이슈가 최초에 「청소만 하면 새 코드로 다시 스며든다」 고 적은 우려가 그대로 실측됐고, 가드 도입이 이 이슈의 본체가 됐다.
이 이슈의 범위
- 재발 유입 가드 1종 도입 — lint/ktlint 커스텀 룰이 가능하면 룰로, 아니면 CI 스크립트 카운트 가드(현재 값을 상한으로 고정하고 초과 시 fail)로. 자식 이슈들이 청소를 마치면 상한을 0 으로 내린다.
- 컨벤션 문서화 — 「화면 컴포저블은 required, 리프의 선택적 상호작용은 nullable 핸들러 또는 오버로드 분리」 를
docs/에 명문화. 프리뷰·screenshotTest 는 호출부에서{}명시. - afternote 잔여 2건 —
MemorialDetailScreen.kt:93-94.
처리 방침 (자식 이슈 공통)
- 화면 컴포저블(실호출부가 NavGraph 한 곳): 디폴트 전면 제거, 프리뷰·screenshotTest·unit test 는
{}를 명시한다. refactor(afternote): 에디터 파라미터 봉투 2종 언번들 — AfternoteEditorScreenCallbacks·AfternoteEditorNavigationParams, no-op 디폴트 제거 포함 #602 가 에디터 봉투 2종에서 이미 같은 처분을 했고, refactor(core): 수신자 입력 거절의 서버 원문을 고정 진단 문구로 바꾼다 #934 방침(폴백보다 값 명시·타입으로 강제)과 정합이다. - 다중 호출부 리프 컴포넌트: 건별 판정한다. 전 호출부가 실값을 넘기면 디폴트만 제거. 상호작용이 진짜 선택적이면
= {}로 「눌러도 아무 일 없는 버튼」을 그리는 대신 nullable 핸들러+UI 숨김 또는 오버로드 분리로 재모델링한다. (fix(afternote): 미배선 콜백 4건 — 남기실 말씀 등록·수신 상세 확인하기·홈 NEXT STEP 카드 무동작, no-op 디폴트가 은폐 #777 이 「리프의 정상적 선택 콜백」으로 판정한 다수가 여기 해당 — 재판정이 아니라 모델링 교정이 목적)
완료 조건
- 신규 유입 가드 1종이 CI 에서 동작한다 (초과 시 fail)
- 컨벤션이
docs/에 명문화되고, 프리뷰·screenshotTest 의 처리 방식이 예시로 들어간다 -
MemorialDetailScreen.kt:93-942건 처리 - 자식 이슈 완료 후 가드 상한을 0 으로 내린다
자식 이슈
- refactor(mindrecord): 컴포저블 no-op 콜백 디폴트 50건 청소 — 이틀 만에 14건 신규 유입 (#1388 분할) #1540 — 마음의 기록 47 + 홈 3 (@Sadturtleman)
- refactor(timeletter): 컴포저블 no-op 콜백 디폴트 34건 청소 (#1388 분할) #1541 — 타임레터 34 (@koongmai)
- refactor: 담당 area 의 main 소스셋 @Preview 148건 전량 삭제 (#1388 파생) #1434 — 담당 area 의 main 소스셋 @Preview 삭제 (이 이슈 파생, @1hyok)
참고
- 발단: PR fix(afternote): 추억 노트 상세 기본 상호작용 보완 (#463) #1336 리뷰 중 신설
onVideoClick: (String) -> Unit = {}확인 →e6c37e31d에서 제거 완료 - 작성 하단바 텍스트 설정 버튼 무동작 — onTextStyleClick 미전달 #778 (open) 이
TimeLetterWriteScreen의onTextStyleClick배선 시 디폴트 동반 제거를 예고 — refactor(timeletter): 컴포저블 no-op 콜백 디폴트 34건 청소 (#1388 분할) #1541 과 조정 필요 - 전례: refactor(afternote): 에디터 파라미터 봉투 2종 언번들 — AfternoteEditorScreenCallbacks·AfternoteEditorNavigationParams, no-op 디폴트 제거 포함 #602 · fix(afternote): 미배선 콜백 4건 — 남기실 말씀 등록·수신 상세 확인하기·홈 NEXT STEP 카드 무동작, no-op 디폴트가 은폐 #777 (137건 전수 대조·실결함 적출) · fix(mindrecord): 데일리질문·일기 '수정하기' 무동작 — 편집 경로 미결선 #582 · fix(mindrecord): 수신 마음의 기록 카드 탭 무동작 — 일기·데일리질문 본문 열람 불가 #618 · fix(mindrecord): 작성·탭 상호작용 7건 — 접기 전환·링크 검증·임시저장·텍스트 설정·오라우팅 #722
- 최초 실측 본문(108건 / 37파일 · 모듈 분포)은 이 이슈 히스토리에 보존돼 있다
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
area:platformCI·빌드·릴리스·저장소 운영 영역CI·빌드·릴리스·저장소 운영 영역refactor동작 변경 없이 코드 구조·책임·경계를 개선하는 작업동작 변경 없이 코드 구조·책임·경계를 개선하는 작업
Activity
OnlyReadOneBook commentedon Aug 28, 2026
PR #1336 의 신설분(
MemorialDetailScreen.onVideoClick)은 e6c37e3 에서 디폴트 제거 완료 — 이 이슈의 잔여 카운트에서 제외. 재측정 시 107건 기준.build(konsist): konsist 모듈에 ktlint 를 적용한다
refactor(receiver): 컴포저블 no-op 콜백 디폴트 14건을 걷는다
refactor(receiver): 프리뷰 전용 Noop 상수를 프로덕션에서 걷는다
refactor(receiver): 컴포저블 no-op 콜백 디폴트 14건을 걷는다
refactor(receiver): 프리뷰 전용 Noop 상수를 프로덕션에서 걷는다
refactor(receiver): 컴포저블 no-op 콜백 디폴트 14건을 걷는다
refactor(receiver): 프리뷰 전용 Noop 상수를 프로덕션에서 걷는다
Merge pull request #1414 from Afternote/refactor/1388-receiver-noop-d…
[-]refactor: 컴포저블 no-op 콜백 디폴트 108건 전수 청소 — 화면은 required 로, 리프는 선택성 재모델링 + 재발 가드[/-][+]refactor(platform): 컴포저블 no-op 콜백 디폴트 — 재발 가드·컨벤션 도입 + afternote 잔여 2건[/+]refactor(mindrecord): 상세 화면의 no-op 콜백 디폴트를 걷는다
OnlyReadOneBook commentedon Aug 30, 2026
완료 조건 3종이 전부
origin/developfc8f32cd5에 들어가 있어 닫습니다. 실측 근거입니다.konsist/src/test/kotlin/com/afternote/konsist/NoOpCallbackDefaultKonsistTest.kt— @composable 파라미터 + 클래스 주 생성자 파라미터 양쪽 검사, LEGACY 목록은 관대 판정 + 해소 항목 경고docs/convention/composable-callback-defaults.mdMemorialDetailScreen.kt의onEditClick·onDeleteConfirm이 디폴트 없는 required 파라미터로 바뀜 (PR #1544,dc8641db8)가드의
LEGACY_NO_OP_DEFAULT_FILES에도 afternote·receiver 항목이 남아 있지 않고 home·mindrecord 만 남아 있습니다 — 자식 이슈 몫과 정확히 일치합니다.모듈별 청소는 #1540(Sadturtleman · mindrecord·home) · #1541(koongmai · timeletter) 이 각자 어사인된 채 열려 있어 그쪽에서 추적됩니다.
fix(setting): FAQ 화면을 실제 내비게이션에 연결하고 문자열 이스케이프를 고친다