Skip to content

Create Week4 Mission1, 2#25

Open
chldnjswo wants to merge 3 commits intomainfrom
Week04/Deku
Open

Create Week4 Mission1, 2#25
chldnjswo wants to merge 3 commits intomainfrom
Week04/Deku

Conversation

@chldnjswo
Copy link
Copy Markdown
Contributor

📝 미션 번호

4주차 Mission 1, 2

📋 구현 사항

  • 하트 이모티콘 클릭 시 위시리스트에 리사이클러뷰로 된 ui 구현
  • datastore을 사용하여 상품 목록 및 상품 상태를 로컬에 저장하도록 구현
  • 리포지터리를 통해 viewmodel이 직접 datastore을 다루지 않도록 구현

📎 스크린샷

스크린샷 2026-04-05 오후 4 11 37 스크린샷 2026-04-05 오후 4 11 49

✅ 체크리스트

  • Merge 하려는 브랜치가 올바르게 설정되어 있나요?
  • 에뮬레이터 또는 실제 기기에서 정상 동작하나요?
  • 불필요한 주석 및 Log가 제거되었나요?

🤔 질문 사항

@chldnjswo chldnjswo requested a review from Dawon-Y April 5, 2026 07:12
@chldnjswo chldnjswo self-assigned this Apr 5, 2026
@Dawon-Y Dawon-Y requested a review from Copilot April 9, 2026 07:55
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

위시리스트(하트 토글) 기능을 DataStore로 로컬 영속화하고, Repository를 통해 ViewModel이 직접 저장소를 다루지 않도록 구조화한 Android 앱(Week04/Week03 Deku)을 추가/구현하는 PR입니다.

Changes:

  • 하트 토글 ↔ 위시리스트 화면(RecyclerView Grid) 및 상세 화면 연동 구현
  • Preferences DataStore + Gson 기반으로 상품 목록/위시 상태 로컬 저장 및 Repository 레이어 추가
  • Navigation/BottomNavigation + Shop 탭(ViewPager2/TabLayout) UI 구성 및 스플래시/메인 화면 추가

Reviewed changes

Copilot reviewed 142 out of 201 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
Week04/Deku/settings.gradle.kts Gradle 설정/프로젝트 이름
Week04/Deku/gradlew.bat Gradle Wrapper(Windows)
Week04/Deku/gradle/wrapper/gradle-wrapper.properties Gradle 배포 설정
Week04/Deku/gradle/libs.versions.toml 버전 카탈로그 정의
Week04/Deku/gradle.properties Gradle 공통 속성
Week04/Deku/build.gradle.kts 루트 build 설정
Week04/Deku/app/build.gradle.kts 앱 모듈 의존성/SDK 설정
Week04/Deku/app/proguard-rules.pro Proguard 규칙
Week04/Deku/app/.gitignore 모듈 빌드 산출물 ignore
Week04/Deku/app/src/main/AndroidManifest.xml 액티비티/런처 설정
Week04/Deku/app/src/test/java/com/example/week02/ExampleUnitTest.kt 기본 유닛 테스트 템플릿
Week04/Deku/app/src/androidTest/java/com/example/week02/ExampleInstrumentedTest.kt 기본 계측 테스트 템플릿
Week04/Deku/app/src/main/java/com/example/week02/MainActivity.kt NavHost + BottomNav 연결
Week04/Deku/app/src/main/java/com/example/week02/SplashActivity.kt 스플래시 화면/전환
Week04/Deku/app/src/main/java/com/example/week02/home/HomeFragment.kt 홈(최신 상품/날짜)
Week04/Deku/app/src/main/java/com/example/week02/home/HomeProductAdapter.kt 홈 상품 어댑터
Week04/Deku/app/src/main/java/com/example/week02/shop/ShopFragment.kt Shop 탭/페이지 연결
Week04/Deku/app/src/main/java/com/example/week02/shop/ShopPagerAdapter.kt ViewPager2 어댑터
Week04/Deku/app/src/main/java/com/example/week02/shop/AllFragment.kt 전체 상품 그리드
Week04/Deku/app/src/main/java/com/example/week02/shop/TopsFragment.kt Tops 카테고리
Week04/Deku/app/src/main/java/com/example/week02/shop/ShoesFragment.kt Shoes 카테고리
Week04/Deku/app/src/main/java/com/example/week02/shop/DetailFragment.kt 상품 상세/위시 토글
Week04/Deku/app/src/main/java/com/example/week02/shop/ShopProductAdapter.kt 상품 그리드 어댑터
Week04/Deku/app/src/main/java/com/example/week02/shop/ProductViewModel.kt DataStore 기반 VM
Week04/Deku/app/src/main/java/com/example/week02/wishList/WishListFragment.kt 위시리스트 화면
Week04/Deku/app/src/main/java/com/example/week02/cart/CartFragment.kt 장바구니 화면
Week04/Deku/app/src/main/java/com/example/week02/profile/ProfileFragment.kt 프로필(템플릿)
Week04/Deku/app/src/main/java/com/example/week02/data/ItemList.kt 상품 모델
Week04/Deku/app/src/main/java/com/example/week02/data/ItemData.kt 더미 상품 데이터
Week04/Deku/app/src/main/java/com/example/week02/data/ProductRepository.kt Repository 레이어
Week04/Deku/app/src/main/java/com/example/week02/data/ProductDataStore.kt DataStore 저장/토글
Week04/Deku/app/src/main/res/navigation/nava_graph.xml Navigation 그래프
Week04/Deku/app/src/main/res/menu/menu_bottom_navigation.xml BottomNav 메뉴
Week04/Deku/app/src/main/res/layout/activity_main.xml 메인 레이아웃
Week04/Deku/app/src/main/res/layout/activity_splash.xml 스플래시 레이아웃
Week04/Deku/app/src/main/res/layout/fragment_home.xml 홈 레이아웃
Week04/Deku/app/src/main/res/layout/fragment_shop.xml Shop 레이아웃
Week04/Deku/app/src/main/res/layout/fragment_product_list.xml 상품 리스트 공용
Week04/Deku/app/src/main/res/layout/item_home_product.xml 홈 아이템 뷰
Week04/Deku/app/src/main/res/layout/item_shop_product.xml Shop 아이템 뷰
Week04/Deku/app/src/main/res/layout/fragment_detail.xml 상세 레이아웃
Week04/Deku/app/src/main/res/layout/fragment_wish_list.xml 위시리스트 레이아웃
Week04/Deku/app/src/main/res/layout/fragment_cart.xml 장바구니 레이아웃
Week04/Deku/app/src/main/res/layout/fragment_profile.xml 프로필 레이아웃
Week04/Deku/app/src/main/res/layout/fragment_all.xml All 컨테이너
Week04/Deku/app/src/main/res/layout/fragment_tops.xml Tops 컨테이너
Week04/Deku/app/src/main/res/layout/fragment_shoes.xml Shoes 컨테이너
Week04/Deku/app/src/main/res/values/strings.xml 문자열 리소스
Week04/Deku/app/src/main/res/values/colors.xml 색상 리소스
Week04/Deku/app/src/main/res/values/styles.xml 위젯 스타일
Week04/Deku/app/src/main/res/values/themes.xml 테마(라이트)
Week04/Deku/app/src/main/res/values-night/themes.xml 테마(나이트)
Week04/Deku/app/src/main/res/color/color_bottom_navigation.xml BottomNav 컬러 셀렉터
Week04/Deku/app/src/main/res/xml/backup_rules.xml 백업 규칙
Week04/Deku/app/src/main/res/xml/data_extraction_rules.xml 데이터 추출 규칙
Week04/Deku/app/src/main/res/drawable/home.xml 아이콘(홈)
Week04/Deku/app/src/main/res/drawable/shop.xml 아이콘(샵)
Week04/Deku/app/src/main/res/drawable/heart.xml 아이콘(하트)
Week04/Deku/app/src/main/res/drawable/heart_filled.xml 아이콘(하트 채움)
Week04/Deku/app/src/main/res/drawable/cart.xml 아이콘(카트)
Week04/Deku/app/src/main/res/drawable/profile.xml 아이콘(프로필)
Week04/Deku/app/src/main/res/drawable/ic_arrow_back.xml 아이콘(뒤로)
Week04/Deku/app/src/main/res/drawable/bg_heart_circle.xml 하트 배경
Week04/Deku/app/src/main/res/drawable/bg_detail_secondary_button.xml 버튼 배경(보조)
Week04/Deku/app/src/main/res/drawable/bg_detail_size_button.xml 버튼 배경(사이즈)
Week04/Deku/app/src/main/res/drawable/ic_launcher_foreground.xml 런처 포그라운드
Week04/Deku/app/src/main/res/drawable/splash_logo.png 스플래시 로고
Week04/Deku/app/src/main/res/drawable/nike_logo.png 브랜드 로고
Week04/Deku/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml 런처 adaptive icon
Week04/Deku/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml 런처 adaptive(round)
Week04/Deku/app/src/main/res/mipmap-mdpi/ic_launcher.webp 런처 아이콘(mdpi)
Week04/Deku/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp 런처 아이콘 round(mdpi)
Week04/Deku/app/src/main/res/mipmap-hdpi/ic_launcher.webp 런처 아이콘(hdpi)
Week04/Deku/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp 런처 아이콘 round(hdpi)
Week04/Deku/app/src/main/res/mipmap-xhdpi/ic_launcher.webp 런처 아이콘(xhdpi)
Week04/Deku/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp 런처 아이콘(xxhdpi)
Week04/Deku/.idea/.name IDE 프로젝트 이름
Week04/Deku/.idea/.gitignore IDE ignore
Week04/Deku/.idea/AndroidProjectSystem.xml IDE 설정
Week04/Deku/.idea/compiler.xml IDE 컴파일러 설정
Week04/Deku/.idea/deploymentTargetSelector.xml IDE 디바이스 선택
Week04/Deku/.idea/gradle.xml IDE Gradle 설정
Week04/Deku/.idea/markdown.xml IDE Markdown 설정
Week04/Deku/.idea/migrations.xml IDE 마이그레이션
Week04/Deku/.idea/misc.xml IDE JDK 등 설정
Week04/Deku/.idea/runConfigurations.xml IDE 실행 설정
Week04/Deku/.idea/vcs.xml VCS 매핑
Week03/Deku/settings.gradle.kts Week03 Gradle 설정
Week03/Deku/gradlew.bat Week03 Gradle Wrapper(Windows)
Week03/Deku/gradle/wrapper/gradle-wrapper.properties Week03 Gradle 배포 설정
Week03/Deku/gradle/libs.versions.toml Week03 버전 카탈로그
Week03/Deku/gradle.properties Week03 Gradle 속성
Week03/Deku/build.gradle.kts Week03 루트 build
Week03/Deku/app/build.gradle.kts Week03 앱 모듈 build
Week03/Deku/app/proguard-rules.pro Week03 Proguard
Week03/Deku/app/.gitignore Week03 모듈 ignore
Week03/Deku/app/src/main/AndroidManifest.xml Week03 Manifest
Week03/Deku/app/src/test/java/com/example/week02/ExampleUnitTest.kt Week03 유닛 테스트 템플릿
Week03/Deku/app/src/androidTest/java/com/example/week02/ExampleInstrumentedTest.kt Week03 계측 테스트 템플릿
Week03/Deku/app/src/main/java/com/example/week02/MainActivity.kt Week03 MainActivity
Week03/Deku/app/src/main/java/com/example/week02/SplashActivity.kt Week03 SplashActivity
Week03/Deku/app/src/main/java/com/example/week02/home/HomeFragment.kt Week03 HomeFragment
Week03/Deku/app/src/main/java/com/example/week02/home/HomeProductAdapter.kt Week03 홈 어댑터
Week03/Deku/app/src/main/java/com/example/week02/shop/ProductViewModel.kt Week03 VM(메모리)
Week03/Deku/app/src/main/java/com/example/week02/shop/ShopFragment.kt Week03 ShopFragment
Week03/Deku/app/src/main/java/com/example/week02/shop/ShopPagerAdapter.kt Week03 PagerAdapter
Week03/Deku/app/src/main/java/com/example/week02/shop/AllFragment.kt Week03 AllFragment
Week03/Deku/app/src/main/java/com/example/week02/shop/TopsFragment.kt Week03 TopsFragment
Week03/Deku/app/src/main/java/com/example/week02/shop/ShoesFragment.kt Week03 ShoesFragment
Week03/Deku/app/src/main/java/com/example/week02/shop/DetailFragment.kt Week03 DetailFragment
Week03/Deku/app/src/main/java/com/example/week02/shop/ShopProductAdapter.kt Week03 상품 어댑터
Week03/Deku/app/src/main/java/com/example/week02/wishList/WishListFragment.kt Week03 위시리스트
Week03/Deku/app/src/main/java/com/example/week02/cart/CartFragment.kt Week03 장바구니
Week03/Deku/app/src/main/java/com/example/week02/profile/ProfileFragment.kt Week03 프로필(템플릿)
Week03/Deku/app/src/main/java/com/example/week02/data/ItemList.kt Week03 모델
Week03/Deku/app/src/main/java/com/example/week02/data/ItemData.kt Week03 더미 데이터
Week03/Deku/app/src/main/res/navigation/nava_graph.xml Week03 Navigation
Week03/Deku/app/src/main/res/menu/menu_bottom_navigation.xml Week03 BottomNav 메뉴
Week03/Deku/app/src/main/res/layout/activity_main.xml Week03 메인 레이아웃
Week03/Deku/app/src/main/res/layout/activity_splash.xml Week03 스플래시 레이아웃
Week03/Deku/app/src/main/res/layout/fragment_home.xml Week03 홈 레이아웃
Week03/Deku/app/src/main/res/layout/fragment_shop.xml Week03 Shop 레이아웃
Week03/Deku/app/src/main/res/layout/fragment_product_list.xml Week03 리스트 레이아웃
Week03/Deku/app/src/main/res/layout/item_home_product.xml Week03 홈 아이템
Week03/Deku/app/src/main/res/layout/item_shop_product.xml Week03 Shop 아이템
Week03/Deku/app/src/main/res/layout/fragment_detail.xml Week03 상세
Week03/Deku/app/src/main/res/layout/fragment_wish_list.xml Week03 위시
Week03/Deku/app/src/main/res/layout/fragment_cart.xml Week03 카트
Week03/Deku/app/src/main/res/layout/fragment_profile.xml Week03 프로필
Week03/Deku/app/src/main/res/layout/fragment_all.xml Week03 All 컨테이너
Week03/Deku/app/src/main/res/layout/fragment_tops.xml Week03 Tops 컨테이너
Week03/Deku/app/src/main/res/layout/fragment_shoes.xml Week03 Shoes 컨테이너
Week03/Deku/app/src/main/res/values/strings.xml Week03 문자열
Week03/Deku/app/src/main/res/values/colors.xml Week03 색상
Week03/Deku/app/src/main/res/values/styles.xml Week03 스타일
Week03/Deku/app/src/main/res/values/themes.xml Week03 테마
Week03/Deku/app/src/main/res/values-night/themes.xml Week03 나이트 테마
Week03/Deku/app/src/main/res/color/color_bottom_navigation.xml Week03 컬러 셀렉터
Week03/Deku/app/src/main/res/xml/backup_rules.xml Week03 백업 규칙
Week03/Deku/app/src/main/res/xml/data_extraction_rules.xml Week03 추출 규칙
Week03/Deku/app/src/main/res/drawable/home.xml Week03 홈 아이콘
Week03/Deku/app/src/main/res/drawable/shop.xml Week03 샵 아이콘
Week03/Deku/app/src/main/res/drawable/heart.xml Week03 하트
Week03/Deku/app/src/main/res/drawable/heart_filled.xml Week03 하트 채움
Week03/Deku/app/src/main/res/drawable/cart.xml Week03 카트
Week03/Deku/app/src/main/res/drawable/profile.xml Week03 프로필
Week03/Deku/app/src/main/res/drawable/ic_arrow_back.xml Week03 뒤로
Week03/Deku/app/src/main/res/drawable/bg_heart_circle.xml Week03 하트 배경
Week03/Deku/app/src/main/res/drawable/bg_detail_secondary_button.xml Week03 버튼 배경
Week03/Deku/app/src/main/res/drawable/bg_detail_size_button.xml Week03 버튼 배경
Week03/Deku/app/src/main/res/drawable/ic_launcher_foreground.xml Week03 런처 포그라운드
Week03/Deku/app/src/main/res/drawable/splash_logo.png Week03 스플래시 로고
Week03/Deku/app/src/main/res/drawable/nike_logo.png Week03 로고
Week03/Deku/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml Week03 adaptive icon
Week03/Deku/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml Week03 adaptive(round)
Week03/Deku/app/src/main/res/mipmap-mdpi/ic_launcher.webp Week03 런처(mdpi)
Week03/Deku/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Week03 런처 round(mdpi)
Week03/Deku/app/src/main/res/mipmap-hdpi/ic_launcher.webp Week03 런처(hdpi)
Week03/Deku/app/src/main/res/mipmap-xhdpi/ic_launcher.webp Week03 런처(xhdpi)
Week03/Deku/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Week03 런처(xxhdpi)
Week03/Deku/.idea/.name Week03 IDE 이름
Week03/Deku/.idea/.gitignore Week03 IDE ignore
Week03/Deku/.idea/AndroidProjectSystem.xml Week03 IDE 설정
Week03/Deku/.idea/compiler.xml Week03 IDE 컴파일러
Week03/Deku/.idea/deploymentTargetSelector.xml Week03 IDE 디바이스
Week03/Deku/.idea/gradle.xml Week03 IDE Gradle
Week03/Deku/.idea/migrations.xml Week03 IDE 마이그레이션
Week03/Deku/.idea/misc.xml Week03 IDE misc
Week03/Deku/.idea/runConfigurations.xml Week03 IDE 실행 설정
Week03/Deku/.idea/vcs.xml Week03 VCS 매핑
Files not reviewed (21)
  • Week03/Deku/.idea/.gitignore: Language not supported
  • Week03/Deku/.idea/.name: Language not supported
  • Week03/Deku/.idea/AndroidProjectSystem.xml: Language not supported
  • Week03/Deku/.idea/compiler.xml: Language not supported
  • Week03/Deku/.idea/deploymentTargetSelector.xml: Language not supported
  • Week03/Deku/.idea/gradle.xml: Language not supported
  • Week03/Deku/.idea/migrations.xml: Language not supported
  • Week03/Deku/.idea/misc.xml: Language not supported
  • Week03/Deku/.idea/runConfigurations.xml: Language not supported
  • Week03/Deku/.idea/vcs.xml: Language not supported
  • Week04/Deku/.idea/.gitignore: Language not supported
  • Week04/Deku/.idea/.name: Language not supported
  • Week04/Deku/.idea/AndroidProjectSystem.xml: Language not supported
  • Week04/Deku/.idea/compiler.xml: Language not supported
  • Week04/Deku/.idea/deploymentTargetSelector.xml: Language not supported
  • Week04/Deku/.idea/gradle.xml: Language not supported
  • Week04/Deku/.idea/markdown.xml: Language not supported
  • Week04/Deku/.idea/migrations.xml: Language not supported
  • Week04/Deku/.idea/misc.xml: Language not supported
  • Week04/Deku/.idea/runConfigurations.xml: Language not supported
  • Week04/Deku/.idea/vcs.xml: Language not supported

Comment on lines +33 to +34
binding.tvDate.text = LocalDate.now()
.format(DateTimeFormatter.ofPattern("M월 d일 EEEE", Locale.KOREAN))
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

minSdk가 24인데 java.time.LocalDate/DateTimeFormatter를 그대로 사용하고 있어 API 24~25에서 NoClassDefFoundError로 크래시가 날 수 있습니다. coreLibraryDesugaring을 활성화(compileOptions + desugar_jdk_libs 추가)하거나, API 26 미만에서는 다른 날짜 API로 대체/분기 처리해 주세요.

Copilot uses AI. Check for mistakes.
Comment on lines +32 to +33
binding.tvDate.text = LocalDate.now()
.format(DateTimeFormatter.ofPattern("M월 d일 EEEE", Locale.KOREAN))
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

minSdk가 24인데 java.time.LocalDate/DateTimeFormatter 사용으로 API 24~25에서 런타임 크래시 가능성이 있습니다. coreLibraryDesugaring을 활성화하거나(API desugaring 의존성/옵션 추가), API 26 미만에서는 다른 구현으로 분기 처리해 주세요.

Copilot uses AI. Check for mistakes.
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.8.7")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7")
implementation("com.google.code.gson:gson:2.10.1")
implementation("com.google.android.material:material:1.12.0")
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

libs.material(버전 카탈로그)과 com.google.android.material:material:1.12.0를 동시에 선언하고 있어 중복/버전 충돌 소지가 있습니다. 한 쪽만 사용하도록 정리하고(권장: 버전 카탈로그로 일원화), 필요하면 다른 라이브러리들도 버전 카탈로그로 옮겨 일관성을 맞춰주세요.

Copilot uses AI. Check for mistakes.
Comment on lines +52 to +54
implementation("com.google.android.material:material:1.12.0")
implementation("com.airbnb.android:lottie:6.4.0")
implementation("com.google.android.material:material:1.12.0")
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

동일한 com.google.android.material:material:1.12.0 의존성이 중복으로 선언되어 있습니다(또한 libs.material도 이미 포함). 중복 라인을 제거하고, 가능하면 버전 카탈로그(libs.material)로 의존성 버전을 일원화해 주세요.

Copilot uses AI. Check for mistakes.
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="장바구니가 비어있습니다\n제품을 추가면 여기에 표시됩니다."
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

문장 오타로 보입니다. "제품을 추가면" → "제품을 추가하면" 으로 수정해 주세요.

Copilot uses AI. Check for mistakes.
super.onViewCreated(view, savedInstanceState)
_binding = FragmentDetailBinding.bind(view)

val productId = requireArguments().getInt(ARG_PRODUCT_ID)
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

requireArguments().getInt(ARG_PRODUCT_ID)는 인자가 없을 때 즉시 크래시가 납니다. 현재 nav graph에 detailFragment의 argument 정의가 없어서(그리고 다른 경로로 진입할 가능성을 배제하기 어려워서) 안전하지 않습니다. navigation graph에 productId argument를 명시하거나, 인자 누락 시 안전하게 처리(기본값/에러 처리)하도록 변경해 주세요.

Copilot uses AI. Check for mistakes.
_binding = null
}

/// 다른 화면에서 id를 쉽게 담아서 넘거는 함수
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

주석에 오타가 있습니다. "넘거는" → "넘기는" 으로 수정해 주세요.

Copilot uses AI. Check for mistakes.
Comment on lines +54 to +57
fun updateItems(newItems: List<ItemList>) {
items.clear()
items.addAll(newItems)
notifyDataSetChanged()
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

notifyDataSetChanged()는 매번 전체 아이템을 리바인딩해서 아이템 수가 늘면 스크롤/렌더링 성능에 영향을 줄 수 있습니다. ListAdapter + DiffUtil로 변경하거나, 최소한 DiffUtil.calculateDiff를 적용해 변경분만 갱신하도록 개선해 주세요.

Copilot uses AI. Check for mistakes.
Comment on lines +22 to +23
rootProject.name = "week02"
include(":app")
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

Week04 미션 PR인데 rootProject.nameweek02로 설정되어 있어 프로젝트 식별이 혼동될 수 있습니다. 폴더/주차에 맞는 이름(예: week04 또는 Deku)으로 조정하는 것을 권장합니다.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +3
pluginManagement {
repositories {
google {
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

PR 설명은 4주차 미션인데 Week03/Deku 프로젝트가 함께 추가되어 있습니다. 의도된 포함이 아니라면 Week03 관련 파일들은 PR에서 제외(또는 별도 PR로 분리)해 변경 범위를 줄여주세요.

Copilot uses AI. Check for mistakes.
@Dawon-Y
Copy link
Copy Markdown
Contributor

Dawon-Y commented Apr 12, 2026

안녕하세요! 4주차 과제 수행하시느라 고생 많으셨습니다💚
작성해주신 코드에 대한 리뷰를 정리했으니 참고하시면 좋을 것 같습니다.


총평

ProductViewModel에서 init { seedIfNeeded() }를 호출해 앱 최초 진입 시 DataStore를 자동 초기화하는 흐름이 완성되어 있습니다.
즉, Week04 요구사항인 “더미 데이터 → DataStore(JSON) 대체 + 비동기 처리 + 하트 상태 유지”의 전체 파이프라인이 DataStore → Repository → ViewModel → UI(Fragments/Adapter)로 잘 연결되어 있습니다.

1. ViewModel 구조 선택(AndroidViewModel)

class ProductViewModel(application: Application) : AndroidViewModel(application)

ProductDataStore(application.applicationContext)처럼 Context가 필요한 DataStore를 ViewModel에서 만들기 위해 AndroidViewModel을 선택한 점은 논리적으로 맞습니다.
여러 Fragment에서 activityViewModels()로 공유할 때도 구조가 자연스럽습니다.

2. seedIfNeeded() 호출 위치

init {
    viewModelScope.launch {
        repository.seedIfNeeded()
    }
}

ViewModel 생성 시점에 DataStore가 비어있으면 더미 데이터를 채우도록 해서 앱 첫 실행에서도 리스트가 즉시 보이고
이후에는 DataStore 값이 유지되도록 만드는 흐름이 명확합니다.
viewModelScope.launch로 비동기 처리한 점도 요구사항(비동기 처리)에 맞습니다.

3. LiveData 변환(asLiveData)

val products: LiveData<List<ItemList>> = repository.products.asLiveData()
val wishlistProducts: LiveData<List<ItemList>> = repository.wishlistProducts.asLiveData()

또한 최신 상품만 보여주는 요구도:

val latestProducts = repository.products.map { it.take(5) }.asLiveData()

처럼 “원본 → 가공(파생) → 노출” 구조로 깔끔하게 처리했습니다.

4. 카테고리 필터링(productsByCategory)

fun productsByCategory(category: String?): List<ItemList> {
    val currentProducts = products.value.orEmpty()
    return if (category == null) currentProducts else currentProducts.filter { it.category == category }
}

현재 구조는 “observe가 한 번 돌고 난 이후”에는 잘 동작합니다.
다만 아주 처음에 products.value가 아직 null인 타이밍이면 빈 리스트가 나올 수 있습니다.
그런데 각 탭 Fragment에서:

productViewModel.products.observe(viewLifecycleOwner) {
    adapter.updateItems(productViewModel.productsByCategory("Shoes"))
}

처럼 observe 안에서 호출하고 있어서, 실제로는 데이터가 들어온 뒤 실행되므로 실사용에서는 안정적입니다. (구현 방식이 괜찮습니다)

5. 하트 토글(toggleWish)

fun toggleWish(productId: Int) {
    viewModelScope.launch {
        repository.toggleWish(productId)
    }
}

클릭 이벤트가 UI에서 오면 ViewModel이 비동기로 저장 작업을 수행하고, DataStore의 Flow가 갱신되며,
wishlistProducts와 products가 다시 방출 → UI가 갱신이라는 흐름이 성립합니다.
이 구조면 앱 종료 후 재실행해도 isWish 값이 DataStore에 남아서 유지됩니다.

6. productById

fun productById(productId: Int): ItemList? =
    products.value.orEmpty().find { it.id == productId }

상세 화면에서 id로 찾는 기능을 ViewModel에 둔 것도 적절합니다.

(선택 개선)
이 함수도 “초기 로딩 전”에는 null이 나올 수 있으니, 디테일 화면에서는 null 처리(UI placeholder 등)를 해주면 더 안전합니다.


마무리

ProductViewModel까지 포함해서 보면,

  • DataStore(JSON)로 더미 데이터 대체
  • 비동기 처리(Flow + viewModelScope)
  • 토글 상태 영구 저장
  • 홈/구매/위시리스트 화면에 동일 데이터가 일관되게 반영
    으로 요구사항을 구조적으로 아주 깔끔하게 달성했습니다.

코드 리뷰 확인해보시고 궁금한 점 있으면 언제든지 말씀해주세요!

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.

3 participants