#945 의 `feature/timeletter/presentation` 실행분이다. **38개 파일**을 타입별 묶음에서 기능별 묶음으로 옮긴다. 실측 기준: `4e0a648e` (origin/develop) 현재 최상위 폴더 — `component/` · `navigation/` · `screen/` · `viewmodel/` 화면 하나를 고치려면 이 폴더들을 오가야 한다. 가장 큰 모듈인 `feature/afternote/presentation`(117개)과 `feature/onboarding/presentation`(27개)은 이미 기능별이라, 소수를 다수에 맞추는 게 아니라 그 반대다. ## 순서 — 파일럿이다 #945 가 이 모듈을 **파일럿**으로 지목했다. 38개로 가장 작아서 기능 폴더 경계를 잡는 시행착오 비용이 가장 싸다. 여기서 정한 폴더 경계·`shared/` 기준을 나머지 모듈이 따른다. ## 충돌면 (`4e0a648e` 실측) 이 모듈의 presentation 을 건드리는 **열린 PR 3건 — #440 · #767 · #771**. 파일 이동은 리네임 충돌을 그대로 일으키므로, 착수 전에 이것들을 정리하거나 머지된 뒤에 시작하는 편이 낫다. ## 목표 구조 (#945 정본) ``` feature/timeletter/presentation/ <기능1>/ # Screen · ViewModel · UiState 를 한자리에 component/ # 이 기능 전용 컴포넌트 <기능2>/ shared/ # 2개 이상 기능이 쓰는 것만 navigation/ ``` ### 지킬 것 - **깊이는 2단계까지.** 기능 폴더 안에 `component/` 정도까지만 판다 - **진짜 공용만 `shared/`** — 여러 화면이 쓰는 것을 전부 기능 폴더로 밀어넣으면 사본이 생긴다. `feature/afternote/presentation/shared/` 가 참고 사례 - **State 위치 규칙** — 화면 상태(`*UiState`)는 기능 폴더 안, 여러 화면이 공유하는 UI 모델만 `shared/model` - **파일 이동 외 변경을 섞지 않는다.** 리뷰 가능성을 지키기 위해서다. 이름 변경·로직 수정은 별건 ## 완료 조건 - 이 모듈의 `component/` · `viewmodel/` · `screen/` 타입별 폴더가 사라지고 기능 폴더로 접힌다 - `:feature:timeletter:presentation:compileDebugUnitTestKotlin` · `:app:compileDebugAndroidTestKotlin` · `:konsist:test` · `ktlintCheck` 통과 - 시각 변경 0 — 파일 이동만이므로 screenshotTest baseline 재생성이 필요 없다 ## 참고 - #945 — 총괄. 목표 구조·깊이 제한·`shared/` 기준의 정본이 여기 있다
Activity
[-]refactor(timeletter): presentation 을 기능별 묶음으로 이관 — 38개 파일, 타입별 4폴더 (#945 파일럿)[/-][+]presentation 을 기능별 묶음으로 이관 — 38개 파일, 타입별 4폴더 (#945 파일럿)[/+]