Skip to content

refactor(receiver): 수신자 홈의 afternote 리소스 차용 해소 — 아이콘 core:ui 승격 (#926) - #1061

Merged
1hyok merged 9 commits into
developfrom
refactor/926-receiver-res
Aug 26, 2026
Merged

1hyok merged 9 commits into
developfrom
refactor/926-receiver-res

Conversation

@Sadturtleman

Copy link
Copy Markdown
Collaborator

Closes #926

범위

이슈가 «스택(#917·#919) 머지 후 남는 잔여 정비 하나» 로 좁혀 둔 그 항목이다. 두 PR 모두 오늘 머지됐고(04:24 / 04:35) 위반이 그대로 남아 있는 것을 확인한 뒤 착수했다.

$ grep -rn "afternote.presentation.R" feature/receiver/presentation/src/main/.../home/
ReceiverHomeScreen.kt:46:  import com.afternote.feature.afternote.presentation.R as AfternoteFeatureR
AfternoteSection.kt:29:    import com.afternote.feature.afternote.presentation.R as AfternoteFeatureR

무엇을 했나

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 이 형제 feature 의 res id 를 들고 있었다
.map { AfternoteSourceIcon(drawableResId = getIconResForType(it)) }

// 지금 — 어떤 그림인지는 core:ui 가 안다
.map { it.toSourceIcon() }

ViewModel 이 res id 를 들면 상태가 Android 리소스에 묶여 단위 테스트에서도 리소스가 필요해진다. 종류는 도메인 개념이지만 아이콘 선택은 표현이라는 경계를 지켰다.

AfternoteType 5종 중 홈이 구분하는 3종 외(BUSINESS·ESTATE)는 Other(로고)로 접는다 — 종전 getIconResForType 의 폴백과 같은 결과다.

회귀 가드

ReceiverHomeResourceKonsistTest — 수신자 홈 패키지가 자신이 아닌 feature 의 R 을 import 하면 실패한다. 리소스 차용은 컴파일로도 테스트로도 안 잡히는 종류라 구조 가드를 붙였다.

import 를 되돌려 재도입 → 3 tests completed, 1 failed
  수신자 홈은 다른 feature 의 R 을 참조하지 않는다
원복 → 통과

검증

ktlintCheck · :app:assembleDebug
:feature:receiver:presentation:testDebugUnitTest
:feature:afternote:presentation:testDebugUnitTest
:konsist:test
→ BUILD SUCCESSFUL

실기기 — 옮긴 아이콘을 실제로 쓰는 애프터노트 에디터(종류·서비스명)를 열어 렌더를 확인했고 Resources$NotFoundException 은 없다. 수신자 홈 자체는 delivery-verification APPROVED 가 필요해 진입할 수 없다(#618·#614 와 같은 사정) — 그쪽은 스크린샷 baseline 3종이 커버한다(무변경).

남는 것 (이 PR 밖)

수신자의 다른 화면들은 아직 afternote presentation 을 참조한다 — playlist·afternotelist·deliveryverification. 이슈가 범위를 «수신자 홈» 으로 좁혀 두었고, 그쪽은 PlaylistSongDisplay·AfternoteFailureStage 처럼 리소스가 아니라 모델·계측 재사용이라 성격이 다르다. 필요하면 별도 이슈로 다루는 편이 맞다고 본다.

🤖 Generated with Claude Code

수신자 홈이 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>
@github-actions

Copy link
Copy Markdown
Contributor

❌ Screenshot test fail — baseline 과 CI rendered PNG 차이.

📦 Artifact: https://github.com/Afternote/Afternote-FE/actions/runs/32729612422 (페이지 하단 Artifacts → screenshot-test-results)

🔍 확인 위치 (artifact zip 내부):

  • diff PNG: preview/debug/diffs/...
  • rendered PNG: preview/debug/rendered/... (CI 환경에서 새로 그린 결과)
  • baseline PNG: repo <module>/src/screenshotTestDebug/reference/... (:core:ui · :feature:home:presentation · :feature:receiver:presentation · :feature:onboarding:presentation · :feature:afternote:presentation)

📝 조치 가이드:

  • 의도된 시각 변경 → docker build -t afternote-screenshot:latest -f Dockerfile.screenshot . 후 docker run --rm -v "$PWD":/workspace -w /workspace afternote-screenshot:latest ./gradlew :<module>:updateScreenshotTest 로 baseline 갱신 + commit/push
  • diff 가 anti-aliasing/font 차이로 보이면 docker 환경 변경 여부 (Dockerfile.screenshot) 점검

CI ↔ 로컬 환경 차이는 본 워크플로의 container 단계가 root fix 한다 (README 의 "Compose Preview Screenshot Testing (docker baseline)" 섹션 참조).

@1hyok 1hyok left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

총평

리소스 차용을 «res id 를 통과시키는 것» 이 아니라 표현 타입(enum) 으로 끊은 방향이 맞습니다. AfternoteType → AfternoteSourceIcon 매핑이 when 이라 종류가 늘면 컴파일이 잡아 주고, 재도입을 Konsist 로 막아 둔 것도 좋습니다. Other 폴백이 종전 getIconResForType 과 같은 결과라는 본문 주장도 실측으로 확인했습니다(아래 검증).

다만 타입을 옮기면서 같은 모듈의 screenshotTest 소스셋이 따라오지 않아 그 모듈이 컴파일되지 않습니다. 1번이 blocking 입니다.

지적

  1. [blocking] screenshotTest 2파일이 옛 위치·옛 형태를 그대로 쓴다 — 모듈 컴파일 실패 → core/ui/src/main/kotlin/com/afternote/core/ui/icon/AfternoteSourceIcon.kt:16 인라인.

  2. [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 가 없어 사이클을 못 도시는 상황이면 제가 대신 돌려도 됩니다 — 말씀 주세요.

  3. [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-verification APPROVED 가 필요한 건 #618·#614 와 같은 사정이라 그대로 인정합니다. 옮긴 아이콘을 실제로 쓰는 애프터노트 에디터 쪽을 대신 확인하신 것도 타당한 대체입니다.

* 아니라 이 enum 이다. ViewModel 이 res id 를 들면 상태가 Android 리소스에 묶여
* 단위 테스트에서도 리소스가 필요해진다.
*/
enum class AfternoteSourceIcon(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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(\..*)?$""")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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 은 아니니 후속으로 잡으셔도 됩니다.

Sadturtleman and others added 3 commits August 25, 2026 00:15
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>
@Sadturtleman

Copy link
Copy Markdown
Collaborator Author

지적 3건 모두 반영했습니다.

1. screenshotTest 컴파일 실패 — 타입을 옮기면서 같은 모듈의 screenshotTest 소스셋을 데려오지 않은 게 맞습니다. import 경로와 생성자 호출을 모두 고쳤습니다.

import com.afternote.core.ui.icon.AfternoteSourceIcon
// AfternoteSectionScreenshotTest
AfternoteSourceIcon.SocialNetwork,
AfternoteSourceIcon.GalleryAndFiles,
// ReceiverHomeScreenScreenshotTest
AfternoteSourceIcon.SocialNetwork,

:feature:receiver:presentation:compileDebugScreenshotTestKotlin BUILD SUCCESSFUL 확인했습니다.

2. baseline 3종(실제로는 2종) 재생성 — 말씀이 맞습니다. 「무변경」은 성립하지 않았고, 종류 아이콘 자리에 검색·링크 아이콘이 박혀 있던 baseline 이 이번에 교정됐습니다. docker 로 갱신·검증했습니다.

docker run ... afternote-screenshot:latest ./gradlew :feature:receiver:presentation:updateScreenshotTest
→ receiverHomeScreenSuccessScreenshot_748aa731_0.png
  afternoteSectionScreenshot_748aa731_0.png

docker run ... ./gradlew :feature:receiver:presentation:validateScreenshotTest
→ BUILD SUCCESSFUL in 6m 4s

갱신본에서 아이콘 자리가 검색 돋보기 → 소셜 패턴·갤러리 아이콘으로 바뀐 것을 눈으로도 확인했습니다. 대신 돌려 주겠다는 제안 감사합니다 — Docker 가 살아 있어 직접 돌렸습니다.

3. Konsist 가드가 FQN 을 못 잡는다 — import 검사에 본문 텍스트 검사를 더했습니다.

file.imports.any { import -> FOREIGN_FEATURE_RESOURCE.matches(import.name) } ||
    FOREIGN_FEATURE_RESOURCE_REFERENCE.containsMatchIn(file.text)

가드가 실제로 잡는지 확인했습니다 — 수신자 홈 파일에 com.afternote.feature.afternote.presentation.R.drawable.x 를 FQN 으로 한 줄 심으니 ReceiverHomeResourceKonsistTest ... FAILED, 지우니 다시 통과합니다. 주석·문자열 오탐은 말씀대로 감수하는 쪽으로 뒀습니다.

@1hyok 1hyok left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

지적 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: 필수 체크 중 Ktlint fail, 그로 인해 ci-gate fail. 나머지는 전부 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건. develop 428022ff 기준.
  • 시안 대조 해당 없음 — 리소스 소유 모듈 이동이라 대조할 시각 변경이 없습니다. 프리뷰 렌더 변화는 baseline 이 받았습니다(2번).
  • 실기동 QA — 앞 리뷰와 같습니다. 수신자 홈 진입에 delivery-verification APPROVED 가 필요한 사정을 그대로 인정하고, 애프터노트 에디터 쪽 확인으로 갈음합니다.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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 한 번이면 함께 정리됩니다.

@1hyok
1hyok requested a review from koongmai August 25, 2026 11:24
@Sadturtleman

Copy link
Copy Markdown
Collaborator Author

재리뷰 요청 — 지적 3건은 반영 완료 상태이고, 방금 develop 을 다시 물어 최신으로 맞췄습니다.

  1. screenshotTest 컴파일 실패 — import 경로·생성자 호출을 enum 형태로 고쳤습니다.
  2. baseline 2종 — docker 로 재생성하고 validateScreenshotTest 까지 통과시켰습니다. 종류 아이콘 자리에 검색 돋보기가 박혀 있던 것이 실제 종류 아이콘으로 교정됩니다.
  3. Konsist 가 FQN 을 못 잡는다 — file.text 검사를 더했고, FQN 참조를 심어 실제로 실패하는 것까지 확인했습니다.

방금 로컬 실측입니다 (develop 최신 병합 후).

:app:assembleDebug                                          BUILD SUCCESSFUL
전 모듈 testDebugUnitTest                                    BUILD SUCCESSFUL
:feature:receiver:presentation:compileDebugScreenshotTestKotlin  BUILD SUCCESSFUL
:konsist:test                                               BUILD SUCCESSFUL

@1hyok 1hyok left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

재리뷰 — 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: Ktlint fail → ci-gate fail. 나머지는 전부 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-verification APPROVED 가 필요한 사정도 그대로 인정합니다.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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>
@Sadturtleman

Copy link
Copy Markdown
Collaborator Author

import 두 줄, 고쳤습니다. ktlintFormat 이 정확히 이 두 파일만 건드렸습니다.

-import com.afternote.core.ui.theme.AfternoteTheme
 import com.afternote.core.ui.icon.AfternoteSourceIcon
+import com.afternote.core.ui.theme.AfternoteTheme

지적하신 대로 제 지난 실측에 ktlint 가 빠져 있었습니다 — compileDebugScreenshotTestKotlin 만 돌려서 «컴파일되니 됐다» 로 넘어갔고, 같은 지적을 두 번 받게 만들었습니다. 주신 명령을 그대로 썼습니다.

:feature:receiver:presentation:ktlintFormat
:feature:receiver:presentation:ktlintCheck                      → BUILD SUCCESSFUL
:feature:receiver:presentation:compileDebugScreenshotTestKotlin → BUILD SUCCESSFUL

ktlintFormat 을 앞에 두고 ktlintCheck 를 뒤에 붙이라는 이유(up-to-date 로 조용히 지나갈 수 있다)도 실제로 그랬습니다 — Format 만으로는 이번에도 확신할 수 없었을 자리입니다. 앞으로 이 모듈 작업엔 세 태스크를 묶어 돌리겠습니다.

@1hyok 1hyok left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

재리뷰 — 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.AfternoteTheme

CI 도 따라왔습니다 — 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 정리, screenshotTest CompactDeviceSpec + 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 SUCCESSFUL
    

    AfternoteSourceIcon 의 정의가 병합본에서 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/…/termsDetailScreenScreenshot
    

    receiver 모듈은 한 장도 없고, 이 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-verification APPROVED 가 필요한 사정도 그대로입니다.

세 회차에 걸쳐 지적이 전부 닫혔습니다. 승인합니다.

@1hyok
1hyok merged commit 1a2b5b8 into develop Aug 26, 2026
14 checks passed
@1hyok
1hyok deleted the refactor/926-receiver-res branch August 26, 2026 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(receiver): 수신자 홈의 afternote R 차용 해소 — 소셜 아이콘·getIconResForType core:ui 승격, VM res id 매핑 제거

2 participants