From 31b4e93bed2a0c69085889c10cbe8805c15ef720 Mon Sep 17 00:00:00 2001 From: klaus Date: Thu, 28 May 2026 00:08:56 +0900 Subject: [PATCH] =?UTF-8?q?docs(banner):=20=EB=B0=B0=EB=84=88=20Phase=203?= =?UTF-8?q?=EA=B3=BC=204=20=EA=B2=80=EC=A6=9D=EC=9D=84=20=EA=B8=B0?= =?UTF-8?q?=EB=A1=9D=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- docs/agent-guides/build-test-style.md | 3 ++- docs/plan-task/20260527_배너컴포넌트.md | 29 ++++++++++++++++--------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/docs/agent-guides/build-test-style.md b/docs/agent-guides/build-test-style.md index e4868144..9a5d218b 100644 --- a/docs/agent-guides/build-test-style.md +++ b/docs/agent-guides/build-test-style.md @@ -61,7 +61,8 @@ ``` 참고: -- Kotlin backtick 테스트명은 한글 문장으로 작성하는 것을 기본으로 한다. +- 신규 Kotlin 테스트 메서드는 backtick 함수명을 사용하고, 테스트명은 한글 문장으로 작성한다. +- 기존 영어 테스트명을 수정하지 않는 최소 변경 상황을 제외하고, 새 테스트명에 영어 문장을 사용하지 않는다. - Kotlin backtick 테스트명은 공백이 포함될 수 있으므로 전체 문자열을 인용한다. - 한글 테스트명을 `--tests`로 실행할 때도 클래스명과 메서드명을 포함한 전체 문자열을 따옴표로 감싼다. - 메서드 매칭이 불안정하면 클래스 단위로 먼저 실행한다. diff --git a/docs/plan-task/20260527_배너컴포넌트.md b/docs/plan-task/20260527_배너컴포넌트.md index 1e7e341a..e3626bd1 100644 --- a/docs/plan-task/20260527_배너컴포넌트.md +++ b/docs/plan-task/20260527_배너컴포넌트.md @@ -140,21 +140,21 @@ ### Phase 3: XML 리소스와 디자인 타임 미리보기 -- [ ] **Task 3.1: counter 배경 drawable 추가** +- [x] **Task 3.1: counter 배경 drawable 추가** - 생성 파일: `app/src/main/res/drawable/bg_banner_counter.xml` - 요구사항: - solid color는 `#B3000000` 또는 동등한 `rgba(0,0,0,0.7)` 표현을 사용한다. - corners radius는 capsule 형태로 충분히 큰 값을 사용한다. - 검증: resource merge 시 drawable이 정상 참조된다. -- [ ] **Task 3.2: preview placeholder drawable 추가 또는 재사용 결정** +- [x] **Task 3.2: preview placeholder drawable 추가 또는 재사용 결정** - 생성 후보: `app/src/main/res/drawable/bg_banner_preview_placeholder.xml` - 요구사항: - XML layout editor에서 이미지 데이터 없이도 배너 영역이 보인다. - 기존 적절한 placeholder drawable이 있으면 새 drawable을 만들지 않고 해당 리소스를 사용한다. - 검증: `item_banner.xml`의 `tools:src` 또는 `android:background`에서 참조 가능하다. -- [ ] **Task 3.3: preview attrs 추가** +- [x] **Task 3.3: preview attrs 추가** - 생성 또는 수정 파일: `app/src/main/res/values/attrs.xml` - 추가 속성: - `bannerPreviewItemCount` format `integer` @@ -162,7 +162,7 @@ - `bannerPreviewImage` format `reference` - 검증: `BannerView`에서 `context.obtainStyledAttributes(attrs, R.styleable.BannerView)`로 읽을 수 있다. -- [ ] **Task 3.4: `item_banner.xml` 추가** +- [x] **Task 3.4: `item_banner.xml` 추가** - 생성 파일: `app/src/main/res/layout/item_banner.xml` - 요구사항: - root는 `FrameLayout`. @@ -170,7 +170,7 @@ - root와 image는 `14dp` radius clip 대상이 될 수 있어야 한다. - 검증: XML preview에서 정사각형 item 내부 이미지 영역이 확인된다. -- [ ] **Task 3.5: `view_banner.xml` 추가** +- [x] **Task 3.5: `view_banner.xml` 추가** - 생성 파일: `app/src/main/res/layout/view_banner.xml` - 요구사항: - root는 `kr.co.vividnext.sodalive.v2.widget.banner.BannerView`. @@ -182,7 +182,7 @@ ### Phase 4: Adapter와 View 구현 -- [ ] **Task 4.1: `BannerAdapter` 구현** +- [x] **Task 4.1: `BannerAdapter` 구현** - 생성 파일: `app/src/main/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerAdapter.kt` - 요구사항: - `RecyclerView.Adapter`로 구현한다. @@ -192,7 +192,7 @@ - item click은 현재 `BannerItem`을 호출부 callback으로 전달한다. - 검증: adapter 단위 또는 view test에서 click callback이 현재 item을 전달한다. -- [ ] **Task 4.2: `BannerView` 기본 구조 구현** +- [x] **Task 4.2: `BannerView` 기본 구조 구현** - 생성 파일: `app/src/main/java/kr/co/vividnext/sodalive/v2/widget/banner/BannerView.kt` - 요구사항: - `@JvmOverloads constructor(context, attrs, defStyleAttr)` 패턴을 사용한다. @@ -202,7 +202,7 @@ - `setOnBindBannerImage(listener: ((ImageView, BannerItem) -> Unit)?)` 또는 동등한 이미지 바인딩 API를 제공한다. - 검증: 빈 목록, 단일 목록, 복수 목록을 설정해 visibility와 counter 상태가 바뀐다. -- [ ] **Task 4.3: layout size와 peek 적용** +- [x] **Task 4.3: layout size와 peek 적용** - 수정 파일: `BannerView.kt`, `BannerAdapter.kt` - 요구사항: - view width를 기준으로 item size를 `width - 40dp`로 계산한다. @@ -211,7 +211,7 @@ - 단일 item은 peek 없이 가운데 정렬한다. - 검증: `BannerLayoutCalculatorTest`와 `BannerViewTest`에서 item size, spacing, counter visibility를 확인한다. -- [ ] **Task 4.4: counter 표시 구현** +- [x] **Task 4.4: counter 표시 구현** - 수정 파일: `BannerView.kt` - 요구사항: - 0개/1개에서는 counter를 숨긴다. @@ -220,7 +220,7 @@ - scroll settle 후 실제 item index에 맞춰 counter를 갱신한다. - 검증: 빠른 scroll 후에도 counter index가 현재 item과 일치한다. -- [ ] **Task 4.5: radius clipping 구현** +- [x] **Task 4.5: radius clipping 구현** - 수정 파일: `BannerView.kt` 또는 item view holder - 요구사항: - 배너 image/root에 `radius_14` outline provider를 적용한다. @@ -334,3 +334,12 @@ - 2026-05-27 RED: `BannerLayoutCalculatorTest`, `BannerCounterFormatterTest`, `BannerStateTest`는 최초 실행 시 `compileDebugUnitTestKotlin`에서 `BannerLayoutCalculator`, `BannerCounterFormatter`, `BannerState`, `BannerDisplayMode` 미해결 참조로 실패했다. - 2026-05-27 GREEN: 순수 Kotlin contract 구현 후 대상 순수 테스트가 통과했다. - 2026-05-27 LSP 진단: `kotlin-lsp`가 설치되어 있지 않아 Phase 2 Kotlin 파일의 LSP diagnostics는 사용할 수 없었다. +- 2026-05-27 Phase 3 리소스 추가: `bg_banner_counter.xml`, `bg_banner_preview_placeholder.xml`, `attrs.xml`, `item_banner.xml`, `view_banner.xml`을 추가했다. 기존 `bg_placeholder.xml`은 큰 vector icon이라 배너 영역 배경으로 재사용하지 않고, `radius_14` 기반 preview placeholder를 별도 생성했다. +- 2026-05-27 Phase 3 counter/view 구성: counter 배경은 `#B3000000` capsule로 만들고, `view_banner.xml`은 `BannerView` root, horizontal `RecyclerView`, 우상단 counter overlay를 포함하도록 구성했다. counter text는 현재 index `white`, separator/total `gray_400` TextView로 분리했다. +- 2026-05-27 Phase 3 warning 조치: `android:clipToOutline`은 minSdk 23 기준 API 31 warning 대상이라 `item_banner.xml`에서 사용하지 않았다. 실제 radius clipping은 계획된 Phase 4.5 Kotlin outline provider 구현에서 처리한다. +- 2026-05-27 Phase 4 RED: `BannerViewTest` 추가 후 최초 실행 시 `view_banner.xml`이 참조하는 `BannerView` production class가 없어 `compileDebugJavaWithJavac`에서 실패함을 확인했다. +- 2026-05-27 Phase 4 구현: `BannerAdapter`는 0/1개 실제 count, 2개 이상 virtual position remap, image bind callback, item click callback, image radius clipping을 구현했다. `BannerView`는 XML child 연결, `RecyclerView + PagerSnapHelper`, `setItems`, click/image bind API, visibility, layout size/padding/spacing, counter 표시를 구현했다. +- 2026-05-27 Phase 4 RED/GREEN: 단일 item spacing 회귀 테스트 `배너 view는 단일 item이면 item 간격을 적용하지 않는다`를 추가해 RED를 확인한 뒤, 단일 item에서는 spacing을 `0`, 복수 item에서는 `8dp`로 적용하도록 수정해 GREEN을 확인했다. +- 2026-05-27 Phase 4 검증: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.banner.*"`와 `./gradlew :app:assembleDebug`를 순차 실행해 모두 `BUILD SUCCESSFUL`을 확인했다. Kotlin LSP는 `kotlin-lsp`가 설치되어 있지 않아 diagnostics를 실행할 수 없었다. +- 2026-05-27 Phase 4 리뷰 수정: 리뷰에서 `BannerView(context)` 실제 사용 경로가 내부 layout을 inflate하지 않는 문제가 지적되어, `view_banner.xml`을 ``로 변경하고 `BannerView` 생성 시 내부 layout을 inflate하도록 수정했다. `배너 view는 코드로 생성해도 내부 layout을 포함한다` 테스트로 RED를 확인한 뒤 GREEN을 확인했다. +- 2026-05-27 Phase 4 리뷰 수정 후 검증: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.widget.banner.*"`와 `./gradlew :app:assembleDebug`를 다시 실행해 모두 `BUILD SUCCESSFUL`을 확인했다.