Conversation
Made-with: Cursor
Made-with: Cursor
There was a problem hiding this comment.
Pull request overview
홈/구매하기/위시리스트의 상품 데이터를 DataStore(JSON) 기반으로 전환하고, 구매하기 하트 토글이 위시리스트에 반영되며 앱 재실행 후에도 유지되도록 구성한 PR입니다. 또한 구매하기 화면에 탭(전체 / Tops & T-shirts / sale)을 추가하고, 일부 탭은 플레이스홀더 Fragment로 처리했습니다.
Changes:
- 상품 더미 데이터를
DataStore(Preferences) + JSON(Gson)으로 시딩/조회/갱신하도록 구현 - 구매하기 하트 토글 ↔ 위시리스트 동기화 및 위시리스트 화면 표시
- BottomNavigation + Shop 탭 UI/Fragment 구성 추가
Reviewed changes
Copilot reviewed 60 out of 89 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| Week04/LinLin/settings.gradle.kts | Gradle 설정/리포지토리 및 모듈 포함 구성 추가 |
| Week04/LinLin/build.gradle.kts | 루트 Gradle 플러그인 alias 구성 |
| Week04/LinLin/gradle.properties | Gradle 전역 옵션 추가 |
| Week04/LinLin/gradlew | Gradle wrapper 실행 스크립트(POSIX) 추가 |
| Week04/LinLin/gradlew.bat | Gradle wrapper 실행 스크립트(Windows) 추가 |
| Week04/LinLin/gradle/gradle-daemon-jvm.properties | Toolchain/daemon JVM 설정 파일 추가 |
| Week04/LinLin/gradle/libs.versions.toml | 버전 카탈로그(라이브러리/플러그인) 추가 |
| Week04/LinLin/gradle/wrapper/gradle-wrapper.properties | Gradle 배포 URL/해시 등 wrapper 설정 추가 |
| Week04/LinLin/gradle/wrapper/gradle-wrapper.jar | Gradle wrapper jar 추가 |
| Week04/LinLin/app/build.gradle.kts | Android 앱 모듈 빌드 설정/의존성 추가 |
| Week04/LinLin/app/proguard-rules.pro | ProGuard 기본 규칙 파일 추가 |
| Week04/LinLin/app/src/main/AndroidManifest.xml | 앱/액티비티 선언 및 테마/아이콘 설정 추가 |
| Week04/LinLin/app/src/main/java/com/example/week02/MainActivity.kt | BottomNavigation 기반 Fragment 전환 및 주문 버튼 이벤트 처리 |
| Week04/LinLin/app/src/main/java/com/example/week02/data/ProductItem.kt | 상품 UI 모델 정의 |
| Week04/LinLin/app/src/main/java/com/example/week02/data/ProductDummyData.kt | 홈/구매하기 더미 상품 데이터 제공 |
| Week04/LinLin/app/src/main/java/com/example/week02/data/ProductPreferencesRepository.kt | DataStore(JSON) 시딩/조회/하트 토글/위시리스트 동기화 |
| Week04/LinLin/app/src/main/java/com/example/week02/ui/home/HomeFragment.kt | 홈 화면 + 날짜 표시 + 가로 상품 리스트 바인딩 |
| Week04/LinLin/app/src/main/java/com/example/week02/ui/home/HomeNewProductAdapter.kt | 홈 가로 상품 RecyclerView 어댑터 |
| Week04/LinLin/app/src/main/java/com/example/week02/ui/shop/ShopFragment.kt | 구매하기 탭 구성 및 탭별 child fragment 교체 |
| Week04/LinLin/app/src/main/java/com/example/week02/ui/shop/ShopGridFragment.kt | 구매하기 전체 탭 그리드 + 하트 토글 연동 |
| Week04/LinLin/app/src/main/java/com/example/week02/ui/shop/ShopProductAdapter.kt | 구매하기/위시리스트 공용 상품 그리드 어댑터(하트 포함) |
| Week04/LinLin/app/src/main/java/com/example/week02/ui/shop/ShopTabPlaceholderFragment.kt | 구매하기 빈 탭용 플레이스홀더 Fragment |
| Week04/LinLin/app/src/main/java/com/example/week02/ui/wishlist/WishlistFragment.kt | 위시리스트 그리드 표시(DataStore Flow 수집) |
| Week04/LinLin/app/src/main/java/com/example/week02/ui/cart/CartFragment.kt | 장바구니 화면 및 주문하기 버튼 이벤트 전달 |
| Week04/LinLin/app/src/main/java/com/example/week02/ui/cart/OnCartOrderListener.kt | CartFragment → Activity 이벤트 전달 인터페이스 |
| Week04/LinLin/app/src/main/java/com/example/week02/ui/profile/ProfileFragment.kt | 프로필 화면 및 수정 화면 이동 |
| Week04/LinLin/app/src/main/java/com/example/week02/ui/profile/ProfileEditFragment.kt | 프로필 수정 화면(기본 UI) |
| Week04/LinLin/app/src/main/res/layout/activity_main.xml | 메인 컨테이너 + BottomNavigation 레이아웃 |
| Week04/LinLin/app/src/main/res/layout/fragment_home.xml | 홈 UI(배너, 날짜, 가로 리스트) |
| Week04/LinLin/app/src/main/res/layout/fragment_shop.xml | 구매하기 탭 + child container 레이아웃 |
| Week04/LinLin/app/src/main/res/layout/fragment_shop_grid.xml | 구매하기 그리드 RecyclerView 레이아웃 |
| Week04/LinLin/app/src/main/res/layout/fragment_shop_tab_placeholder.xml | 구매하기 빈 탭 플레이스홀더 레이아웃 |
| Week04/LinLin/app/src/main/res/layout/fragment_wishlist.xml | 위시리스트 RecyclerView 레이아웃 |
| Week04/LinLin/app/src/main/res/layout/fragment_cart.xml | 장바구니 빈 상태 UI + 주문하기 버튼 |
| Week04/LinLin/app/src/main/res/layout/fragment_profile.xml | 프로필 화면 UI |
| Week04/LinLin/app/src/main/res/layout/fragment_profile_edit.xml | 프로필 수정 화면 UI |
| Week04/LinLin/app/src/main/res/layout/item_home_new_product.xml | 홈 가로 리스트 아이템 레이아웃 |
| Week04/LinLin/app/src/main/res/layout/item_shop_product.xml | 구매하기/위시리스트 상품 카드 아이템 레이아웃 |
| Week04/LinLin/app/src/main/res/menu/bottom_nav_menu.xml | 하단 네비게이션 메뉴 정의 |
| Week04/LinLin/app/src/main/res/values/strings.xml | 앱 이름 문자열 추가 |
| Week04/LinLin/app/src/main/res/values/colors.xml | 기본 색상 리소스 추가 |
| Week04/LinLin/app/src/main/res/values/themes.xml | 앱 테마 정의 |
| Week04/LinLin/app/src/main/res/values/styles.xml | BottomNav 스타일(ActiveIndicator) 추가 |
| Week04/LinLin/app/src/main/res/color/nav_item_color.xml | BottomNav 선택/비선택 색 selector 추가 |
| Week04/LinLin/app/src/main/res/xml/backup_rules.xml | 백업 규칙 파일 추가 |
| Week04/LinLin/app/src/main/res/xml/data_extraction_rules.xml | 데이터 추출 규칙 파일 추가 |
| Week04/LinLin/app/src/main/res/drawable/bg_tab_transparent.xml | TabLayout 배경 shape 추가 |
| Week04/LinLin/app/src/main/res/drawable/bg_product_placeholder.xml | 상품 이미지 플레이스홀더 shape 추가 |
| Week04/LinLin/app/src/main/res/drawable/ic_home.xml | 홈 아이콘 벡터 추가 |
| Week04/LinLin/app/src/main/res/drawable/ic_shop.xml | 구매하기 아이콘 벡터 추가 |
| Week04/LinLin/app/src/main/res/drawable/ic_wishlist.xml | 위시리스트 아이콘 벡터 추가 |
| Week04/LinLin/app/src/main/res/drawable/ic_profile.xml | 프로필 아이콘 벡터 추가 |
| Week04/LinLin/app/src/main/res/drawable/ic_search.xml | 검색 아이콘 벡터 추가 |
| Week04/LinLin/app/src/main/res/drawable/ic_cart.xml | 장바구니(원형) 아이콘 벡터 추가 |
| Week04/LinLin/app/src/main/res/drawable/ic_cart_empty.xml | 장바구니 아이콘(24dp) 벡터 추가 |
| Week04/LinLin/app/src/main/res/drawable/ic_heart_outline.xml | 하트 아웃라인 벡터 추가 |
| Week04/LinLin/app/src/main/res/drawable/ic_heart_filled.xml | 하트 채움 벡터 추가 |
| Week04/LinLin/app/src/main/res/drawable/ic_launcher_background.xml | 런처 아이콘 배경 벡터 추가 |
| Week04/LinLin/app/src/main/res/drawable/ic_launcher_foreground.xml | 런처 아이콘 전경 벡터 추가 |
| Week04/LinLin/app/src/main/res/drawable/img_home_banner.png | 홈 배너 이미지 리소스 추가 |
| Week04/LinLin/app/src/main/res/drawable/img_air_jordan_xxxvi.png | 상품 이미지 리소스 추가 |
| Week04/LinLin/app/src/main/res/drawable/img_nike_air_force_1_07.png | 상품 이미지 리소스 추가 |
| Week04/LinLin/app/src/main/res/drawable/img_jordan_nike_af1_07_essentials.png | 상품 이미지 리소스 추가 |
| Week04/LinLin/app/src/main/res/drawable/img_nike_elite_crew.png | 상품 이미지 리소스 추가 |
| Week04/LinLin/app/src/main/res/drawable/img_nike_everyday_plus_cushioned.png | 상품 이미지 리소스 추가 |
| Week04/LinLin/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml | 적응형 런처 아이콘 정의 추가 |
| Week04/LinLin/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml | 적응형 라운드 런처 아이콘 정의 추가 |
| Week04/LinLin/app/src/main/res/mipmap-mdpi/ic_launcher.webp | 런처 아이콘(webp) 추가 |
| Week04/LinLin/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp | 라운드 런처 아이콘(webp) 추가 |
| Week04/LinLin/app/src/main/res/mipmap-hdpi/ic_launcher.webp | 런처 아이콘(webp) 추가 |
| Week04/LinLin/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp | 라운드 런처 아이콘(webp) 추가 |
| Week04/LinLin/app/src/main/res/mipmap-xhdpi/ic_launcher.webp | 런처 아이콘(webp) 추가 |
| Week04/LinLin/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp | 라운드 런처 아이콘(webp) 추가 |
| Week04/LinLin/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp | 런처 아이콘(webp) 추가 |
| Week04/LinLin/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp | 라운드 런처 아이콘(webp) 추가 |
| Week04/LinLin/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp | 런처 아이콘(webp) 추가 |
| Week04/LinLin/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp | 라운드 런처 아이콘(webp) 추가 |
| Week04/LinLin/.idea/AndroidProjectSystem.xml | IDE 프로젝트 시스템 설정 파일 추가 |
| Week04/LinLin/.idea/assetWizardSettings.xml | IDE 에셋 위저드 설정 파일 추가 |
| Week04/LinLin/.idea/compiler.xml | IDE 컴파일러 설정 추가 |
| Week04/LinLin/.idea/deploymentTargetSelector.xml | IDE 배포 타겟 선택 설정 추가 |
| Week04/LinLin/.idea/deviceManager.xml | IDE 디바이스 매니저 설정 추가 |
| Week04/LinLin/.idea/gradle.xml | IDE Gradle 연동 설정 추가 |
| Week04/LinLin/.idea/misc.xml | IDE 프로젝트 JDK/루트 설정 추가 |
| Week04/LinLin/.idea/runConfigurations.xml | IDE 런 구성 무시 프로듀서 설정 추가 |
| Week04/LinLin/.idea/runConfigurations/app.xml | IDE 앱 런 구성 추가 |
| Week04/LinLin/.idea/vcs.xml | IDE VCS 매핑 설정 추가 |
| Week04/LinLin/.idea/workspace.xml | IDE 워크스페이스(개인 설정) 파일 추가 |
| Week04/LinLin/.idea/caches/deviceStreaming.xml | IDE 캐시/디바이스 스트리밍 설정 파일 추가 |
Files not reviewed (12)
- Week04/LinLin/.idea/AndroidProjectSystem.xml: Language not supported
- Week04/LinLin/.idea/assetWizardSettings.xml: Language not supported
- Week04/LinLin/.idea/caches/deviceStreaming.xml: Language not supported
- Week04/LinLin/.idea/compiler.xml: Language not supported
- Week04/LinLin/.idea/deploymentTargetSelector.xml: Language not supported
- Week04/LinLin/.idea/deviceManager.xml: Language not supported
- Week04/LinLin/.idea/gradle.xml: Language not supported
- Week04/LinLin/.idea/misc.xml: Language not supported
- Week04/LinLin/.idea/runConfigurations.xml: Language not supported
- Week04/LinLin/.idea/runConfigurations/app.xml: Language not supported
- Week04/LinLin/.idea/vcs.xml: Language not supported
- Week04/LinLin/.idea/workspace.xml: Language not supported
|
|
||
| CLASSPATH="\\\"\\\"" | ||
|
|
There was a problem hiding this comment.
CLASSPATH 값이 "\\\"\\\""로 설정되어 있어 정상적인 Gradle Wrapper 실행에 문제를 만들 수 있습니다. 일반적으로는 gradle/wrapper/gradle-wrapper.jar 경로를 가리키도록 설정되거나, -jar 옵션만 쓸 경우 -classpath 인자를 제거하는 형태가 됩니다. Gradle에서 생성한 기본 wrapper 스크립트로 재생성/교체하는 쪽을 권장합니다.
| @rem Setup the command line | ||
|
|
||
| set CLASSPATH= | ||
|
|
||
|
|
||
| @rem Execute Gradle | ||
| "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* |
There was a problem hiding this comment.
Windows용 wrapper에서도 set CLASSPATH=로 비어 있는데, 아래 실행 커맨드에서 -classpath "%CLASSPATH%"를 전달하고 있습니다. -jar를 사용할 거라면 -classpath를 제거하거나, 사용할 거면 CLASSPATH를 wrapper jar 경로로 채우는 등 스크립트를 표준 형태로 맞춰 주세요(현재 상태는 환경에 따라 실행 실패/오동작 위험이 있습니다).
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <project version="4"> | ||
| <component name="AndroidLayouts"> | ||
| <shared> | ||
| <config /> | ||
| </shared> |
There was a problem hiding this comment.
사용자 로컬 환경에 종속적인 .idea/workspace.xml이 커밋에 포함되어 있습니다. 다른 개발자 환경/CI에 불필요한 충돌을 유발하므로 저장소에서 제거하고, **/.idea/workspace.xml 등 하위 프로젝트까지 무시하도록 ignore 패턴을 보완하는 것을 권장합니다.
| import android.util.Log | ||
| import android.view.MenuItem | ||
| import androidx.activity.enableEdgeToEdge | ||
| import androidx.appcompat.app.AppCompatActivity | ||
| import androidx.core.view.ViewCompat | ||
| import androidx.core.view.WindowInsetsCompat | ||
| import androidx.fragment.app.Fragment | ||
| import com.example.week02.databinding.ActivityMainBinding |
There was a problem hiding this comment.
PR 체크리스트에 '불필요한 Log 제거'가 있는데, MainActivity에 생명주기 Log.d가 다수 남아 있습니다. 디버그 용도라면 BuildConfig.DEBUG 가드로 감싸거나 제거해 주세요. 또한 MenuItem, Fragment import는 현재 코드에서 사용되지 않아 정리하는 게 좋습니다.
| <ImageView | ||
| android:id="@+id/iv_heart" | ||
| android:layout_width="28dp" | ||
| android:layout_height="28dp" | ||
| android:layout_marginTop="8dp" | ||
| android:layout_marginEnd="8dp" | ||
| android:contentDescription="@null" | ||
| android:padding="2dp" | ||
| app:layout_constraintEnd_toEndOf="@id/iv_product" | ||
| app:layout_constraintTop_toTopOf="@id/iv_product" | ||
| tools:src="@drawable/ic_heart_outline" /> |
There was a problem hiding this comment.
클릭 가능한 하트 아이콘(iv_heart)의 contentDescription이 @null로 되어 있어 스크린리더에서 의미가 전달되지 않습니다. 접근성을 위해 '위시리스트 추가/삭제'처럼 상태에 맞는 설명을 제공하고(가능하면 string 리소스 사용), 토글 시 함께 업데이트해 주세요.
| <item android:id="@+id/homeFragment" android:title="홈" android:icon="@drawable/ic_home" /> | ||
| <item android:id="@+id/shopFragment" android:title="구매하기" android:icon="@drawable/ic_shop" /> | ||
| <item android:id="@+id/wishlistFragment" android:title="위시리스트" android:icon="@drawable/ic_wishlist" /> | ||
| <item android:id="@+id/cartFragment" android:title="장바구니" android:icon="@drawable/ic_cart" /> | ||
| <item android:id="@+id/profileFragment" android:title="프로필" android:icon="@drawable/ic_profile" /> |
There was a problem hiding this comment.
BottomNavigation 메뉴의 android:title이 문자열 리소스가 아닌 하드코딩 문자열로 들어가 있습니다. 다국어/일관된 관리 관점에서 @string/...으로 분리해 주세요.
| <application | ||
| android:allowBackup="true" | ||
| android:icon="@mipmap/ic_launcher" | ||
| android:label="@string/app_name" | ||
| android:roundIcon="@mipmap/ic_launcher_round" | ||
| android:supportsRtl="true" | ||
| android:theme="@style/Theme.Week02"> |
There was a problem hiding this comment.
backup_rules.xml/data_extraction_rules.xml을 추가했지만 AndroidManifest.xml의 <application>에 android:fullBackupContent / android:dataExtractionRules 속성으로 연결되어 있지 않아 현재는 적용되지 않습니다. 실제로 백업/복구 정책을 의도했다면 manifest에 해당 속성을 추가해 주세요.
| private fun parseList(json: String?): List<ProductItem> { | ||
| if (json.isNullOrBlank()) return emptyList() | ||
| return gson.fromJson(json, listType) ?: emptyList() | ||
| } |
There was a problem hiding this comment.
DataStore에 저장된 JSON이 깨졌거나 스키마가 바뀐 경우 gson.fromJson에서 예외가 발생해 Flow 수집 시 앱이 크래시날 수 있습니다. parseList에서 try/catch로 JsonSyntaxException 등을 처리해 빈 리스트로 폴백하거나, 시드를 재생성하는 방식으로 복구 로직을 넣는 것이 안전합니다.
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <project version="4"> | ||
| <component name="DeviceStreaming"> | ||
| <option name="deviceSelectionList"> | ||
| <list> |
There was a problem hiding this comment.
.idea/caches/deviceStreaming.xml은 Android Studio가 생성하는 캐시/로컬 디바이스 스트리밍 설정 파일로, 사용자 환경에 종속적이고 용량도 커서 버전 관리에 포함하지 않는 것이 일반적입니다. 저장소에서 제거하고 **/.idea/caches/를 무시하도록 ignore 패턴을 추가하는 것을 권장합니다.
| plugins { | ||
| alias(libs.plugins.android.application) | ||
| } |
There was a problem hiding this comment.
프로젝트가 Kotlin 소스(.kt)를 포함하고 있는데 app/build.gradle.kts에 Kotlin Android 플러그인(예: org.jetbrains.kotlin.android) 적용이 보이지 않습니다. 이 상태에서는 Kotlin 컴파일 태스크가 구성되지 않아 빌드가 실패할 가능성이 큽니다. 버전 카탈로그에 Kotlin 플러그인을 추가하고 plugins 블록에 함께 적용해 주세요.
|
안녕하세요! 4주차 과제 수행하시느라 고생 많으셨습니다💚 총평ShopProductAdapter를 구매하기(하트 토글 필요)와 위시리스트(표시 위주)에서 함께 쓸 수 있도록, showHeart와 onHeartClick(옵션 콜백)을 조합해 설계하신 점이 좋습니다. 1. 어댑터 생성자 설계(재사용성)onHeartClick을 nullable + 기본값 null로 둬서, ShopGrid에서는 onHeartClick을 넘겨 DataStore 토글을 외부에서 처리할 수 있고, 2. ViewBinding 기반 바인딩(RecyclerView 기본기)ViewBinding을 사용해 onBindViewHolder에서 각 UI를 채우는 흐름이 정석입니다. 3. 화면별 UI 제어(showHeart)showHeart로 하트 표시 여부를 명확하게 제어하고, 하트를 숨길 때는 클릭 리스너도 제거해서 불필요한 이벤트를 방지했습니다. 4. 하트 아이콘 상태 렌더링(heartFilled)heartFilled에 따라 아이콘을 바꾸는 방식이 직관적이며, UI 요구사항과도 잘 맞습니다. 5. 클릭 처리 방식(콜백 우선 + fallback)bindingAdapterPosition + NO_POSITION 방어를 넣어 클릭 안정성이 좋습니다. 6. (선택 개선) 콜백 파라미터를 position 대신 id로현재 onHeartClick이 (position: Int) -> Unit인데, 구조적으로는: onHeartClick: (productId: Int) -> Unit 처럼 id 기반으로 넘기는 편이 더 안전합니다. 마무리이 ShopProductAdapter는
코드 리뷰 확인해보시고 궁금한 점 있으면 언제든지 말씀해주세요! |
📝 미션 번호
4주차 Misson 1,2
📋 구현 사항
📎 스크린샷
umc_week04.mp4
✅ 체크리스트
🤔 질문 사항