Skip to content

6주차 미션_종이#20

Open
jongheecode wants to merge 6 commits into
mainfrom
Week6
Open

6주차 미션_종이#20
jongheecode wants to merge 6 commits into
mainfrom
Week6

Conversation

@jongheecode

Copy link
Copy Markdown
Collaborator

📝 작업 내용


📸 스크린샷

▎ 구현 결과를 확인할 수 있는 스크린샷을 첨부해주세요.


🙏 리뷰 요구사항 (선택)

  • Repository interface와 Impl 분리 구조가 적절한지 궁금합니다.
  • StateFlow + ProfileUiState 설계 방식에 대한 피드백 부탁드립니다.

jongheecode and others added 6 commits April 4, 2026 19:36
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>
Copilot AI review requested due to automatic review settings May 2, 2026 11:15

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@kimdoyeon1234 kimdoyeon1234 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.

수고하셨습니다!

이번 코드는 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 분리만 다듬어주시면 훨씬 완성도 있는 코드가 될 것 같습니다.
고생 많으셨어요! 😊

Comment on lines +44 to +46
sharedViewModel.buyProducts.collect { products ->
val wishItems = products.filter { it.isFavorite }
productAdapter.updateData(wishItems)

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.

위시리스트 필터링 로직이 Fragment에 있어요! 이런 비즈니스 로직은 ViewModel에서 처리하고
Fragment는 결과만 받아서 표시하도록 수정하면 좋을거 같습니다!

Comment on lines +21 to +23

private val sharedViewModel: SharedViewModel by activityViewModels()

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.

WishlistFragment가 SharedViewModel을 activityViewModels()로 공유해서 사용하고 있습니다! 화면별로 전용 WishlistViewModel을 만들어 viewModels()로 사용하는 게 더 적절한 구조예요! sharedViewModel은 Fragment 간 데이터를 실시간으로 공유해야 할 때만 사용하는 게 좋아요

Comment on lines +1 to +3
package com.example.week6

import android.os.Bundle

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.

이번 미션의 핵심은 패키지 분리입니다! WishlistFragment는 ui/wishlist/ 패키지로 이동시켜주세요!
data/local/은 잘 분리되어 있는데 Fragment들도 동일하게 패키지를 나눠주시면은 좋을거 같습니다!

Comment on lines +25 to +36

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)
}
}

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.

Flow 타입이 List?로 nullable이에요! null 대신 emptyList()를 반환하도록 수정하면
collect 시 null 체크 없이 더 안전하게 사용할 수 있습니다

@jongheecode

Copy link
Copy Markdown
Collaborator Author

넵 감사합니다

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