Repository navigation
refactor(receiver): 수신자 홈의 afternote 리소스 차용 해소 — 아이콘 core:ui 승격 (#926) - #1061
Conversation
수신자 홈이 feature:afternote:presentation 의 R 을 직접 import 해 아이콘을 그렸다. 리소스는 모듈 경계를 가장 조용히 넘는 의존이다 — 컴파일도 되고 그림도 뜨지만, 다른 모듈이 리소스를 지우거나 이름을 바꿀 때에야 드러난다. 종류 아이콘 4개를 core:ui 로 승격하고, 화면 사이에 오가는 값을 res id 대신 AfternoteSourceIcon enum 으로 바꾼다. ViewModel 이 res id 를 들면 상태가 Android 리소스에 묶여 단위 테스트에서도 리소스가 필요해진다. ReceiverHomeResourceKonsistTest 로 되살아남을 막는다 — import 를 되돌리면 잡힌다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
❌ Screenshot test fail — baseline 과 CI rendered PNG 차이. 📦 Artifact: https://github.com/Afternote/Afternote-FE/actions/runs/32729612422 (페이지 하단 Artifacts → 🔍 확인 위치 (artifact zip 내부):
📝 조치 가이드:
CI ↔ 로컬 환경 차이는 본 워크플로의 container 단계가 root fix 한다 (README 의 "Compose Preview Screenshot Testing (docker baseline)" 섹션 참조). |
1hyok
left a comment
There was a problem hiding this comment.
총평
리소스 차용을 «res id 를 통과시키는 것» 이 아니라 표현 타입(enum) 으로 끊은 방향이 맞습니다. AfternoteType → AfternoteSourceIcon 매핑이 when 이라 종류가 늘면 컴파일이 잡아 주고, 재도입을 Konsist 로 막아 둔 것도 좋습니다. Other 폴백이 종전 getIconResForType 과 같은 결과라는 본문 주장도 실측으로 확인했습니다(아래 검증).
다만 타입을 옮기면서 같은 모듈의 screenshotTest 소스셋이 따라오지 않아 그 모듈이 컴파일되지 않습니다. 1번이 blocking 입니다.
지적
-
[blocking] screenshotTest 2파일이 옛 위치·옛 형태를 그대로 쓴다 — 모듈 컴파일 실패 →
core/ui/src/main/kotlin/com/afternote/core/ui/icon/AfternoteSourceIcon.kt:16인라인. -
[blocking] 1번을 고치면 baseline 3종이 반드시 바뀐다 — 본문의 «무변경» 은 성립하지 않습니다. 앵커할 diff 줄이 없어 본문에 적습니다.
지금 screenshotTest 가 넘기는 아이콘은 종류 아이콘이 아니라 손에 잡히는 아무 아이콘입니다.
// ReceiverHomeScreenScreenshotTest.kt:53 AfternoteSourceIcon(drawableResId = com.afternote.core.ui.R.drawable.core_ui_ic_tabler_search) // AfternoteSectionScreenshotTest.kt:21-22 AfternoteSourceIcon(drawableResId = com.afternote.core.ui.R.drawable.core_ui_ic_tabler_search) AfternoteSourceIcon(drawableResId = com.afternote.core.ui.R.drawable.core_ui_ic_link)
이걸
AfternoteSourceIcon.SocialNetwork류로 바꾸면 그려지는 그림 자체가 달라지므로 픽셀이 변합니다. 즉 «수신자 홈은 스크린샷 baseline 3종이 커버한다(무변경)» 는 이 PR 에서는 성립할 수 없고, 컴파일을 고친 다음 baseline 재생성이 한 번 더 필요합니다. 검색 아이콘이 종류 아이콘 자리에 박혀 있던 baseline 이 이번에 실제 그림으로 교정되는 셈이라, 오히려 이 PR 이 마땅히 가져가야 할 변경입니다.Docker 가 없어 사이클을 못 도시는 상황이면 제가 대신 돌려도 됩니다 — 말씀 주세요.
-
[normal] Konsist 가드가 fully-qualified 참조는 못 잡는다 →
konsist/src/test/kotlin/com/afternote/konsist/ReceiverHomeResourceKonsistTest.kt:33인라인.
검증
Other폴백이 회귀인지 실측 — 회귀 아님(본문 주장 확인).AfternoteService전수에typeKey = "BUSINESS"·"ESTATE"항목이 없어 종전에도fromTypeKeyOrNull이 null → 로고 폴백이었습니다.BUSINESS, ESTATE -> Other는 같은 결과입니다.$ git grep -nE 'typeKey = "(BUSINESS|ESTATE)"' origin/refactor/926-receiver-res (0건)- 옮긴 리소스의 옛 이름 잔재 0건.
feature_afternote_ic_social_pattern·ic_gallery_pattern·ic_memorial_guideline·img_logo를 브랜치 전수 검색해 남은 참조가 없음을 확인했습니다. 참조 4파일 정리는 빠짐없이 됐습니다. - CI 실측:
:feature:receiver:presentation:compileDebugScreenshotTestKotlin FAILED—Unresolved reference 'AfternoteSourceIcon'5건(run 32729612422). 1번의 근거가 이 로그입니다. 그 외 체크는 전부 green. - 시안 대조: 해당 없음. 리소스의 소유 모듈만 옮기는 변경이라 대조할 시각 변경이 없습니다. 다만 위 2번대로 프리뷰 렌더는 바뀝니다 — 그건 시안이 아니라 baseline 이 받아야 할 몫입니다.
- 실기동 QA: 본문 사정 수용. 수신자 홈 진입에
delivery-verificationAPPROVED 가 필요한 건 #618·#614 와 같은 사정이라 그대로 인정합니다. 옮긴 아이콘을 실제로 쓰는 애프터노트 에디터 쪽을 대신 확인하신 것도 타당한 대체입니다.
| * 아니라 이 enum 이다. ViewModel 이 res id 를 들면 상태가 Android 리소스에 묶여 | ||
| * 단위 테스트에서도 리소스가 필요해진다. | ||
| */ | ||
| enum class AfternoteSourceIcon( |
There was a problem hiding this comment.
[blocking] 이 타입이 feature:receiver:presentation 의 home.model 에서 여기로 올라오면서 같은 모듈의 screenshotTest 소스셋이 따라오지 않았습니다. data class(drawableResId) → enum 이라 import 경로뿐 아니라 생성자 호출도 함께 바뀌어야 하는데, 그쪽은 옛 형태 그대로입니다.
e: .../screenshotTest/.../home/ReceiverHomeScreenScreenshotTest.kt:6:63 Unresolved reference 'AfternoteSourceIcon'.
e: .../screenshotTest/.../home/ReceiverHomeScreenScreenshotTest.kt:53:29 Unresolved reference 'AfternoteSourceIcon'.
e: .../screenshotTest/.../home/component/AfternoteSectionScreenshotTest.kt:9:63 Unresolved reference 'AfternoteSourceIcon'.
e: .../screenshotTest/.../home/component/AfternoteSectionScreenshotTest.kt:21:21 Unresolved reference 'AfternoteSourceIcon'.
e: .../screenshotTest/.../home/component/AfternoteSectionScreenshotTest.kt:22:21 Unresolved reference 'AfternoteSourceIcon'.
> Task :feature:receiver:presentation:compileDebugScreenshotTestKotlin FAILED
본문 검증 목록이 assembleDebug·testDebugUnitTest·konsist:test 로 끝나 screenshotTest 소스셋만 컴파일 범위 밖에 있었던 것으로 보입니다. 이 모듈은 enableScreenshotTest 가 켜져 있어 소스셋이 하나 더 있습니다 — 타입을 옮길 때는 :feature:receiver:presentation:compileDebugScreenshotTestKotlin 까지 걸어 두시면 같은 누락이 다시 안 납니다.
| private companion object { | ||
| /** 수신자 자신이 아닌 feature 의 `R` (또는 그 하위 참조). */ | ||
| val FOREIGN_FEATURE_RESOURCE = | ||
| Regex("""^com\.afternote\.feature\.(?!receiver\.)[a-z]+\.presentation\.R(\..*)?$""") |
There was a problem hiding this comment.
[normal] 가드가 import 문만 봅니다(file.imports.any { … }). 그래서 fully-qualified 로 쓰면 그대로 통과합니다.
// 이건 잡힌다
import com.afternote.feature.afternote.presentation.R as AfternoteFeatureR
// 이건 안 잡힌다 — import 가 없다
painterResource(com.afternote.feature.afternote.presentation.R.drawable.feature_afternote_img_logo)가정이 아니라 이 모듈에 이미 있는 코드 습관입니다 — 같은 패키지의 screenshotTest 두 파일이 지금도 com.afternote.core.ui.R.drawable.… 를 FQN 으로 씁니다. 그 손버릇으로 형제 feature 의 R 을 쓰면 가드가 침묵합니다.
file.text 에 같은 정규식을 한 번 더 걸거나(주석·문자열 오탐은 감수), import 검사에 더해 참조 텍스트까지 보는 쪽으로 좁혀 두면 구멍이 막힙니다. 지금 범위에서 blocking 은 아니니 후속으로 잡으셔도 됩니다.
AfternoteSourceIcon 을 data class(resId) → enum 으로 올리면서 같은 모듈의 screenshotTest 소스셋이 따라오지 않아 compileDebugScreenshotTestKotlin 이 깨졌다. 종류 아이콘 자리에 검색·링크 아이콘이 박혀 있던 것도 실제 종류 아이콘으로 고친다. Konsist 가드는 import 만 봐서 FQN 참조가 빠져나갔다 — 본문 텍스트도 함께 본다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
screenshotTest 가 종류 아이콘 자리에 검색·링크 아이콘을 넘기고 있어 baseline 에 엉뚱한 그림이 박혀 있었다. 실제 종류 아이콘으로 바꾼 렌더로 docker 에서 재생성한다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
지적 3건 모두 반영했습니다. 1. screenshotTest 컴파일 실패 — 타입을 옮기면서 같은 모듈의 screenshotTest 소스셋을 데려오지 않은 게 맞습니다. import 경로와 생성자 호출을 모두 고쳤습니다. import com.afternote.core.ui.icon.AfternoteSourceIcon
// AfternoteSectionScreenshotTest
AfternoteSourceIcon.SocialNetwork,
AfternoteSourceIcon.GalleryAndFiles,
// ReceiverHomeScreenScreenshotTest
AfternoteSourceIcon.SocialNetwork,
2. baseline 3종(실제로는 2종) 재생성 — 말씀이 맞습니다. 「무변경」은 성립하지 않았고, 종류 아이콘 자리에 검색·링크 아이콘이 박혀 있던 baseline 이 이번에 교정됐습니다. docker 로 갱신·검증했습니다. 갱신본에서 아이콘 자리가 검색 돋보기 → 소셜 패턴·갤러리 아이콘으로 바뀐 것을 눈으로도 확인했습니다. 대신 돌려 주겠다는 제안 감사합니다 — Docker 가 살아 있어 직접 돌렸습니다. 3. Konsist 가드가 FQN 을 못 잡는다 — import 검사에 본문 텍스트 검사를 더했습니다. file.imports.any { import -> FOREIGN_FEATURE_RESOURCE.matches(import.name) } ||
FOREIGN_FEATURE_RESOURCE_REFERENCE.containsMatchIn(file.text)가드가 실제로 잡는지 확인했습니다 — 수신자 홈 파일에 |
1hyok
left a comment
There was a problem hiding this comment.
지적 3건 중 2·3 은 닫혔고, 1 은 컴파일이 풀린 대신 같은 커밋이 새 red 를 만들었습니다. 고칠 것은 import 두 줄뿐입니다.
지적 처리
| # | 지적 | 처리 |
|---|---|---|
| 1 | [blocking] screenshotTest 2파일이 옛 형태 — 모듈 컴파일 실패 | 컴파일은 닫힘, 그러나 아래 4번(새 blocking) |
| 2 | [blocking] baseline 3종이 반드시 바뀐다 — 본문의 «무변경» 불성립 | 닫힘 — 2종 갱신, 스크린샷 CI green |
| 3 | [normal] Konsist 가드가 FQN 을 못 잡는다 | 닫힘 — 본문 텍스트 검사 추가 |
| 4 | [blocking] 새로 넣은 import 가 ktlint 정렬을 깬다 | → 인라인 2건 |
2번 — Screenshot / Validate Compose Preview Screenshots 가 green 입니다. baseline 2종(receiverHomeScreenSuccessScreenshot_748aa731_0.png·afternoteSectionScreenshot_748aa731_0.png)이 갱신됐고, 검색 돋보기가 종류 아이콘 자리에 박혀 있던 것이 실제 그림으로 교정됐습니다. docker 사이클을 직접 돌려 주신 것도 확인했습니다.
3번 — file.imports 검사에 FOREIGN_FEATURE_RESOURCE_REFERENCE.containsMatchIn(file.text) 를 더해 FQN 경로가 막혔습니다. 심어 보고 FAILED → 지우고 통과까지 확인하신 절차가 정확합니다 — 가드는 «막는 것을 실제로 막는가» 를 한 번 태워 보지 않으면 통과만 하고 아무것도 안 하는 상태로 남기 쉽습니다. 정규식의 (?!receiver\.) 로 자기 모듈을 빼 둔 것도 맞고, 스캔 범위가 withPackage("…home..") 라 이 테스트 파일 자신은 대상이 아니라 자기 정규식에 걸리는 자충수도 없습니다.
4번 — 새 blocking (CI red 의 원인)
Static Analysis / Check Code Quality (Ktlint) 가 red 이고, 실패 스텝은 5번 Run Ktlint 입니다(6번 Summarize 는 성공 — 인프라 문제가 아니라 코드에서 나온 위반입니다).
> Task :feature:receiver:presentation:ktlintScreenshotTestSourceSetCheck FAILED
AfternoteSectionScreenshotTest.kt:3:1 Imports must be ordered in lexicographic order … (standard:import-ordering)
ReceiverHomeScreenScreenshotTest.kt:3:1 (같은 위반)
둘 다 이번 수정 커밋 84480a33 에서 갈아 낀 import 가 theme 뒤에 놓여 사전순을 깬 것입니다. 각 파일 인라인에 적었습니다.
ktlintScreenshotTestSourceSetCheck 는 앞 리뷰에서 지적한 compileDebugScreenshotTestKotlin 과 또 다른 태스크라, 컴파일만 확인하면 이번처럼 한 칸 옆으로 새어 나갑니다. 아래 한 줄이면 둘 다 덮습니다.
./gradlew :feature:receiver:presentation:ktlintFormat :feature:receiver:presentation:compileDebugScreenshotTestKotlin(ktlintFormat 은 up-to-date 로 조용히 지나갈 수 있으니, 고친 뒤 ktlintCheck 로 한 번 더 확인하시는 편이 안전합니다.)
검증
- CI: 필수 체크 중
Ktlintfail, 그로 인해ci-gatefail. 나머지는 전부 green — 특히Screenshot / Validate Compose Preview Screenshots와Unit Test / Run Unit Tests(Konsist 가드 포함)가 통과라, 2·3 번이 실제로 닫힌 것이 CI 로 실증됩니다. - develop 병합 실측:
git merge-tree --write-tree origin/develop <head>→ 충돌 0건. develop428022ff기준. - 시안 대조 해당 없음 — 리소스 소유 모듈 이동이라 대조할 시각 변경이 없습니다. 프리뷰 렌더 변화는 baseline 이 받았습니다(2번).
- 실기동 QA — 앞 리뷰와 같습니다. 수신자 홈 진입에
delivery-verificationAPPROVED 가 필요한 사정을 그대로 인정하고, 애프터노트 에디터 쪽 확인으로 갈음합니다.
import 두 줄만 정리하면 green 이 됩니다.
| import androidx.compose.ui.unit.dp | ||
| import com.afternote.core.ui.theme.AfternoteTheme | ||
| import com.afternote.feature.receiver.presentation.home.model.AfternoteSourceIcon | ||
| import com.afternote.core.ui.icon.AfternoteSourceIcon |
There was a problem hiding this comment.
[blocking] 이 import 가 standard:import-ordering 을 깨서 CI 의 Ktlint 가 red 입니다.
AfternoteSectionScreenshotTest.kt:3:1 Imports must be ordered in lexicographic order without any
empty lines in-between with "java", "javax", "kotlin" and aliases in the end (standard:import-ordering)
> Task :feature:receiver:presentation:ktlintScreenshotTestSourceSetCheck FAILED
core.ui.icon 이 core.ui.theme 보다 앞이라 두 줄을 맞바꾸면 끝납니다.
import com.afternote.core.ui.icon.AfternoteSourceIcon
import com.afternote.core.ui.theme.AfternoteTheme(위반 위치가 3:1 로 보고되는 것은 ktlint 가 import 블록 전체를 첫 줄에 앵커하기 때문이고, 실제로 순서를 깨는 것은 이 줄입니다.)
| import androidx.compose.ui.tooling.preview.Preview | ||
| import com.afternote.core.ui.theme.AfternoteTheme | ||
| import com.afternote.feature.receiver.presentation.home.model.AfternoteSourceIcon | ||
| import com.afternote.core.ui.icon.AfternoteSourceIcon |
There was a problem hiding this comment.
[blocking] 같은 위반이 이 파일에도 있습니다 — core.ui.icon 이 core.ui.theme 뒤에 놓였습니다.
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import com.afternote.core.ui.icon.AfternoteSourceIcon
import com.afternote.core.ui.theme.AfternoteTheme
import com.afternote.feature.receiver.presentation.home.model.MindRecordSummary두 파일 다 ktlintFormat 한 번이면 함께 정리됩니다.
|
재리뷰 요청 — 지적 3건은 반영 완료 상태이고, 방금 develop 을 다시 물어 최신으로 맞췄습니다.
방금 로컬 실측입니다 (develop 최신 병합 후). |
…refactor/926-receiver-res
1hyok
left a comment
There was a problem hiding this comment.
재리뷰 — 1·2·3 은 이미 닫혀 있었습니다. 남은 blocking 은 4번이고, 그대로입니다
재리뷰 요청에 적어 주신 3건은 직전 리뷰(08-25 08:25)에서 이미 닫힌 것으로 확인했습니다. 그 리뷰에서 새로 세운 것이 4번 — 1번을 고친 커밋 84480a33 이 갈아 낀 import 가 standard:import-ordering 을 깬 건입니다. 현재 head 4627becf 에서도 두 파일 다 그대로이고, CI 도 여전히 red 입니다.
$ gh api .../actions/jobs/97820937597 --jq '.steps[]'
5 Run Ktlint → failure ← 인프라가 아니라 코드 위반
6 Summarize ktlint violations → success
> Task :feature:receiver:presentation:ktlintScreenshotTestSourceSetCheck FAILED
AfternoteSectionScreenshotTest.kt:3:1 Imports must be ordered in lexicographic order …
ReceiverHomeScreenScreenshotTest.kt:3:1 (같은 위반)
두 줄 맞바꾸면 끝납니다 — 각 파일 인라인에 현재 head 기준으로 다시 적었습니다.
적어 주신 로컬 실측에 compileDebugScreenshotTestKotlin 은 있는데 ktlint 가 없습니다. 지난 리뷰에서 짚은 «컴파일과 ktlint 는 다른 태스크» 가 그대로 재현된 자리입니다. 아래 한 줄이면 둘 다 덮습니다.
./gradlew :feature:receiver:presentation:ktlintFormat :feature:receiver:presentation:ktlintCheck :feature:receiver:presentation:compileDebugScreenshotTestKotlin(ktlintFormat 은 up-to-date 로 조용히 지나갈 수 있어 ktlintCheck 를 뒤에 붙였습니다.)
검증
- CI:
Ktlintfail →ci-gatefail. 나머지는 전부 green(Screenshot / Validate Compose Preview Screenshots·Unit Test·Android Lint포함)이라, 1·2·3 이 닫힌 상태가 유지되는 것도 함께 실증됩니다. - 실패 원인 귀속: 실패 스텝이 5번
Run Ktlint이고 6번 Summarize 는 성공입니다 — reviewdog 쪽 인프라 실패가 아니라 코드에서 나온 위반입니다. - develop 병합 실측:
git merge-tree --write-tree origin/develop <head>→ 충돌 0건. 방금 물려 두신 develop 최신화로 이 접점은 깨끗합니다. - 시안 대조 · 실기동 QA: 직전 리뷰와 동일 — 리소스 소유 모듈 이동이라 대조할 시각 변경이 없고, 프리뷰 렌더 변화는 baseline 2종이 이미 받았습니다. 수신자 홈 진입에
delivery-verificationAPPROVED 가 필요한 사정도 그대로 인정합니다.
import 두 줄이면 green 입니다.
| import androidx.compose.ui.tooling.preview.Preview | ||
| import com.afternote.core.ui.theme.AfternoteTheme | ||
| import com.afternote.feature.receiver.presentation.home.model.AfternoteSourceIcon | ||
| import com.afternote.core.ui.icon.AfternoteSourceIcon |
There was a problem hiding this comment.
[blocking] (직전 리뷰 4번 — 아직 그대로입니다) core.ui.icon 이 core.ui.theme 뒤에 놓여 standard:import-ordering 을 깹니다. 이 줄과 바로 위 theme 줄을 맞바꾸면 끝납니다.
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import com.afternote.core.ui.icon.AfternoteSourceIcon
import com.afternote.core.ui.theme.AfternoteTheme
import com.afternote.feature.receiver.presentation.home.model.MindRecordSummary| import com.afternote.core.ui.theme.AfternoteTheme | ||
| import com.afternote.feature.receiver.presentation.home.model.AfternoteSourceIcon | ||
| import com.afternote.core.ui.icon.AfternoteSourceIcon | ||
| import com.android.tools.screenshot.PreviewTest |
There was a problem hiding this comment.
[blocking] (직전 리뷰 4번 — 아직 그대로입니다) 같은 위반이 이 파일에도 남아 있습니다. icon 을 theme 앞으로 올리면 됩니다.
import androidx.compose.ui.unit.dp
import com.afternote.core.ui.icon.AfternoteSourceIcon
import com.afternote.core.ui.theme.AfternoteTheme
import com.android.tools.screenshot.PreviewTest(ktlint 가 위반 위치를 3:1 로 보고하는 것은 import 블록 전체를 첫 줄에 앵커하기 때문이고, 실제로 순서를 깨는 것은 이 줄입니다.)
#926 의 아이콘 core:ui 승격으로 갈아 낀 import 가 standard:import-ordering 을 깼다. 컴파일은 통과하지만 ktlintScreenshotTestSourceSetCheck 가 잡는 자리라 CI 가 red 였다 — 컴파일과 ktlint 는 다른 태스크다. ktlintCheck · compileDebugScreenshotTestKotlin 둘 다 BUILD SUCCESSFUL. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
import 두 줄, 고쳤습니다. -import com.afternote.core.ui.theme.AfternoteTheme
import com.afternote.core.ui.icon.AfternoteSourceIcon
+import com.afternote.core.ui.theme.AfternoteTheme지적하신 대로 제 지난 실측에 ktlint 가 빠져 있었습니다 —
|
1hyok
left a comment
There was a problem hiding this comment.
재리뷰 — import 두 줄로 닫혔습니다. 승인합니다
지난 회차에서 남은 blocking 은 4번 하나(standard:import-ordering)였고, 3b11d3b14 가 그 두 줄을 바로잡았습니다. 지적대로 ktlintFormat 이 정확히 그 두 파일만 건드렸고, 다른 것이 딸려 오지 않았습니다.
// ReceiverHomeScreenScreenshotTest.kt · AfternoteSectionScreenshotTest.kt
-import com.afternote.core.ui.theme.AfternoteTheme
import com.afternote.core.ui.icon.AfternoteSourceIcon
+import com.afternote.core.ui.theme.AfternoteThemeCI 도 따라왔습니다 — Static Analysis / Check Code Quality (Ktlint) pass, ci-gate pass. 1·2·3 이 닫힌 상태가 유지되는 것도 같은 run 의 Screenshot · Unit Test · Android Lint green 으로 함께 실증됩니다.
konsist 가드가 실제로 서는지 되돌려 확인했습니다
이 PR 의 값어치는 아이콘을 옮긴 것보다 다시 빌려 쓰면 빨개지게 만든 것에 있습니다. 그 가드가 «통과만 하는 테스트» 가 아닌지 위반을 심어 봤습니다.
// ReceiverHomeScreen.kt — 형제 feature 의 R 을 다시 끌어온다
+import com.afternote.feature.afternote.presentation.R as ForeignR$ ./gradlew :konsist:test --tests '*ReceiverHomeResourceKonsistTest*'
ReceiverHomeResourceKonsistTest > 수신자 홈은 다른 feature 의 R 을 참조하지 않는다 FAILED
BUILD FAILED
as 별칭을 준 import 도 잡습니다(import.name 이 FQN 이라). 본문 정규식을 함께 둔 판단 — «이 패키지의 screenshotTest 가 FQN 을 쓰는 손버릇이 있다» — 도 근거가 코드에 실재하는 이야기라 과한 방어가 아닙니다.
검증
-
CI: head
3b11d3b14전 체크 green. -
develop 접점 — 실제로 병합해 빌드했습니다. develop(
71679cd23)이 그 사이 receiver 모듈을 크게 건드렸습니다(#1177 DTO 정리, screenshotTestCompactDeviceSpec+ baseline 25장 신규,SenderMessageHeroCard·HeroCard·AfternoteTypography변경).merge-tree충돌 0건에 더해 병합본(64af74726)에서:./gradlew :feature:receiver:presentation:ktlintCheck \ :feature:receiver:presentation:compileDebugKotlin \ :feature:receiver:presentation:compileDebugUnitTestKotlin \ :feature:receiver:presentation:compileDebugScreenshotTestKotlin \ :core:ui:ktlintCheck :konsist:test \ :app:compileDebugAndroidTestKotlin → BUILD SUCCESSFULAfternoteSourceIcon의 정의가 병합본에서core:ui하나로 유지되고, 참조 6곳이 전부com.afternote.core.ui.icon을 물고 있는 것도 확인했습니다. -
develop 의 줄바꿈 변경이 이 PR 의 baseline 2장을 건드리는가 — 아닙니다. develop 에 한글 어절 줄바꿈(
LineBreak.Paragraph+WordBreak.Phrase+ko-KR)이 들어와 렌더가 바뀔 수 있는 자리라 확인했습니다. 그 커밋(372b433b8)이 함께 갱신한 baseline 은 4장이고 전부 home·onboarding 입니다.home/…/homeTabScreenLoadingScreenshot · homeTabScreenSuccessScreenshot home/…/weeklySummaryGridScreenshot onboarding/…/termsDetailScreenScreenshotreceiver 모듈은 한 장도 없고, 이 PR 이 갈아 끼운 두 장(
receiverHomeScreenSuccessScreenshot·afternoteSectionScreenshot)은 develop 쪽에서 merge-base 이후 손대지 않은 파일입니다. 즉 두 변경이 같은 픽셀을 두고 다투지 않습니다. -
머지 직전에 한 번 더 돌 것: 현재 head 는 최신 develop 을 아직 물지 않았고(
merge-base --is-ancestor→ false), 마지막 run(08-26 07:28)은 develop 최신(08-26 08:58)보다 앞섭니다. 위 로컬 실측으로 접점은 확인했지만 픽셀 판정은 CI 몫이라, 머지 큐에서 재실행되는 Screenshot 결과를 그대로 신뢰하면 됩니다. -
시안 대조 · 실기동 QA — 직전 회차와 동일. 리소스 소유 모듈 이동이라 대조할 시각 변경이 없고, 아이콘 교정으로 인한 렌더 변화는 baseline 2종이 이미 받았습니다. 수신자 홈 진입에
delivery-verificationAPPROVED 가 필요한 사정도 그대로입니다.
세 회차에 걸쳐 지적이 전부 닫혔습니다. 승인합니다.
Closes #926
범위
이슈가 «스택(#917·#919) 머지 후 남는 잔여 정비 하나» 로 좁혀 둔 그 항목이다. 두 PR 모두 오늘 머지됐고(04:24 / 04:35) 위반이 그대로 남아 있는 것을 확인한 뒤 착수했다.
무엇을 했나
1. 종류 아이콘 4개를
core:ui로 승격 —social_pattern·gallery_pattern·memorial_guideline·logo.git mv라 히스토리가 이어진다. 원 소유 모듈(feature:afternote:presentation)의 참조 4파일도core:ui로 돌렸다.2. 화면 사이에 오가는 값을 res id → enum —
AfternoteSourceIcon을core:ui에 두고, 수신자 홈 ViewModel 은 종류만 옮긴다.ViewModel 이 res id 를 들면 상태가 Android 리소스에 묶여 단위 테스트에서도 리소스가 필요해진다. 종류는 도메인 개념이지만 아이콘 선택은 표현이라는 경계를 지켰다.
AfternoteType5종 중 홈이 구분하는 3종 외(BUSINESS·ESTATE)는Other(로고)로 접는다 — 종전getIconResForType의 폴백과 같은 결과다.회귀 가드
ReceiverHomeResourceKonsistTest— 수신자 홈 패키지가 자신이 아닌 feature 의R을 import 하면 실패한다. 리소스 차용은 컴파일로도 테스트로도 안 잡히는 종류라 구조 가드를 붙였다.검증
실기기 — 옮긴 아이콘을 실제로 쓰는 애프터노트 에디터(종류·서비스명)를 열어 렌더를 확인했고
Resources$NotFoundException은 없다. 수신자 홈 자체는delivery-verificationAPPROVED 가 필요해 진입할 수 없다(#618·#614 와 같은 사정) — 그쪽은 스크린샷 baseline 3종이 커버한다(무변경).남는 것 (이 PR 밖)
수신자의 다른 화면들은 아직 afternote presentation 을 참조한다 —
playlist·afternotelist·deliveryverification. 이슈가 범위를 «수신자 홈» 으로 좁혀 두었고, 그쪽은PlaylistSongDisplay·AfternoteFailureStage처럼 리소스가 아니라 모델·계측 재사용이라 성격이 다르다. 필요하면 별도 이슈로 다루는 편이 맞다고 본다.🤖 Generated with Claude Code