6주차 미션_종이#20
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Hilt 의존성 주입 설정 (MyApplication, @HiltAndroidApp) - NetworkModule: Retrofit/OkHttp DI 모듈 - RepositoryModule: Interface-Impl 바인딩 - ProductRepository / ProfileRepository 인터페이스 분리 - ProductLocalDataSource: DataStore 로컬 데이터 소스 분리 - ProductRepositoryImpl: LocalDataSource 주입 (Remote/Local 분리) - ProfileRepositoryImpl: ReqResService 주입 - SharedViewModel: @hiltviewmodel, AndroidViewModel → ViewModel - ProfileViewModel: @hiltviewmodel, LiveData → StateFlow + ProfileUiState - ProfileFragment: observe → repeatOnLifecycle + collect 변환 - 전체 Activity/Fragment: @androidentrypoint 적용 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
kimdoyeon1234
left a comment
There was a problem hiding this comment.
수고하셨습니다!
이번 코드는 data/local/ 패키지를 만들어 ProductLocalDataSource를
분리한 점, repeatOnLifecycle(STARTED) 패턴을 올바르게 적용한 점이 좋았어요!
다만 이번 미션의 핵심은 패키지 분리입니다!
WishlistFragment를 포함한 Fragment들이 루트 패키지에 몰려있어요! ui/home/, ui/wishlist/, ui/profile/ 처럼 화면별로 패키지를 나눠주세요
추가로 WishlistFragment에서 products.filter { it.isFavorite } 같은
비즈니스 로직은 ViewModel로 옮겨주시고,
SharedViewModel을 activityViewModels()로 공유하는 것보다
화면별 전용 ViewModel을 만들어 viewModels()로 사용하는 게 더 좋은 구조예요.
Flow의 반환 타입도 nullable 대신 emptyList()를 기본값으로 사용해주세요!
아래처럼 역할에 맞게 패키지를 나눠주세요 :)
com.example.week6
├── data/
│ ├── local/
│ │ └── ProductLocalDataSource.kt
│ ├── model/
│ │ └── Product.kt
│ └── repository/
│ └── ProductRepositoryImpl.kt
├── domain/
│ └── repository/
│ └── ProductRepository.kt (interface)
├── di/
│ ├── NetworkModule.kt
│ └── RepositoryModule.kt
└── ui/
├── home/
│ ├── HomeFragment.kt
│ └── HomeViewModel.kt
├── wishlist/
│ ├── WishlistFragment.kt
│ └── WishlistViewModel.kt
├── profile/
│ ├── ProfileFragment.kt
│ └── ProfileViewModel.kt
└── common/
└── ProductAdapter.kt
전반적으로 DataSource 분리와 Lifecycle 패턴은 잘 적용하셨으니
패키지 구조와 ViewModel 분리만 다듬어주시면 훨씬 완성도 있는 코드가 될 것 같습니다.
고생 많으셨어요! 😊
| sharedViewModel.buyProducts.collect { products -> | ||
| val wishItems = products.filter { it.isFavorite } | ||
| productAdapter.updateData(wishItems) |
There was a problem hiding this comment.
위시리스트 필터링 로직이 Fragment에 있어요! 이런 비즈니스 로직은 ViewModel에서 처리하고
Fragment는 결과만 받아서 표시하도록 수정하면 좋을거 같습니다!
|
|
||
| private val sharedViewModel: SharedViewModel by activityViewModels() | ||
|
|
There was a problem hiding this comment.
WishlistFragment가 SharedViewModel을 activityViewModels()로 공유해서 사용하고 있습니다! 화면별로 전용 WishlistViewModel을 만들어 viewModels()로 사용하는 게 더 적절한 구조예요! sharedViewModel은 Fragment 간 데이터를 실시간으로 공유해야 할 때만 사용하는 게 좋아요
| package com.example.week6 | ||
|
|
||
| import android.os.Bundle |
There was a problem hiding this comment.
이번 미션의 핵심은 패키지 분리입니다! WishlistFragment는 ui/wishlist/ 패키지로 이동시켜주세요!
data/local/은 잘 분리되어 있는데 Fragment들도 동일하게 패키지를 나눠주시면은 좋을거 같습니다!
|
|
||
| val homeProductsFlow: Flow<List<Product>?> = context.dataStore.data.map { prefs -> | ||
| prefs[HOME_KEY]?.let { json -> | ||
| gson.fromJson(json, object : TypeToken<List<Product>>() {}.type) | ||
| } | ||
| } | ||
|
|
||
| val buyProductsFlow: Flow<List<Product>?> = context.dataStore.data.map { prefs -> | ||
| prefs[BUY_KEY]?.let { json -> | ||
| gson.fromJson(json, object : TypeToken<List<Product>>() {}.type) | ||
| } | ||
| } |
There was a problem hiding this comment.
Flow 타입이 List?로 nullable이에요! null 대신 emptyList()를 반환하도록 수정하면
collect 시 null 체크 없이 더 안전하게 사용할 수 있습니다
|
넵 감사합니다 |
📝 작업 내용
📸 스크린샷
▎ 구현 결과를 확인할 수 있는 스크린샷을 첨부해주세요.
🙏 리뷰 요구사항 (선택)