-
Notifications
You must be signed in to change notification settings - Fork 0
feat: 서재UI/UX 개편 (10) - 계층 간 상태 동기화 및 코드 정리 #734
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
ca2cad5
refactor: 기존 2개의 디비를 1개로 통합
s9hn ff9db1f
refactor: DefaultLibraryLocalDataSource를 데이터레이어에서 DB모듈로 마이그레이션
s9hn c8d247e
refactor: 페이징 구현체에서 데이터소스 의존성 분리
s9hn e57c52c
feat: AttractivePoints 일급 컬렉션 구현 및 적용
s9hn b2cf5c1
feat: ReadStatus 일급 컬렉션 구현 및 적용
s9hn 00afbd3
feat: NovelRating 값 객체 생성 및 적용
s9hn 48a1fff
refactor: SortType -> SortCriteria 변경 및 적용
s9hn 5fc55d3
refactor: UI state 수정 및 적용
s9hn e8b1a2d
refactor: 필터 파라미터 수정 및 적용
s9hn 277986d
refactor: 기존 AttractivePointsModel -> AttractivePoints 마이그레이션 및 UI 적용
s9hn e909206
refactor: LibraryFilterType 제거
s9hn 4e27a00
refactor: 불필요한 UI 모델 제거 및 분리
s9hn aa8cfe6
refactor: 의존성 정리
s9hn 0f1a5df
Merge branch 'feat/704' of https://github.com/Team-WSS/WSS-Android in…
s9hn 158e9ff
refactor: viewmodelscope 롤백
s9hn fca72be
refactor: 리뷰 반영
s9hn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 4 additions & 32 deletions
36
core/database/src/main/java/com/into/websoso/core/database/WebsosoDatabase.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,45 +1,17 @@ | ||
| package com.into.websoso.core.database | ||
|
|
||
| import android.content.Context | ||
| import androidx.room.Database | ||
| import androidx.room.Room | ||
| import androidx.room.RoomDatabase | ||
| import androidx.room.TypeConverters | ||
| import com.into.websoso.core.database.dao.FilteredNovelDao | ||
| import com.into.websoso.core.database.dao.NovelDao | ||
| import com.into.websoso.core.database.entity.InDatabaseFilteredNovelEntity | ||
| import com.into.websoso.core.database.entity.InDatabaseNovelEntity | ||
| import dagger.Module | ||
| import dagger.Provides | ||
| import dagger.hilt.InstallIn | ||
| import dagger.hilt.android.qualifiers.ApplicationContext | ||
| import dagger.hilt.components.SingletonComponent | ||
| import javax.inject.Singleton | ||
| import com.into.websoso.core.database.datasource.library.dao.NovelDao | ||
| import com.into.websoso.core.database.datasource.library.entity.InDatabaseNovelEntity | ||
|
|
||
| @Database( | ||
| entities = [InDatabaseNovelEntity::class, InDatabaseFilteredNovelEntity::class], | ||
| version = 4, | ||
| entities = [InDatabaseNovelEntity::class], | ||
| version = 5, | ||
| exportSchema = false, | ||
| ) | ||
| @TypeConverters(Converters::class) | ||
| internal abstract class WebsosoDatabase : RoomDatabase() { | ||
| internal abstract fun novelDao(): NovelDao | ||
|
|
||
| internal abstract fun filteredNovelDao(): FilteredNovelDao | ||
| } | ||
|
|
||
| @Module | ||
| @InstallIn(SingletonComponent::class) | ||
| internal object DatabaseModule { | ||
| @Provides | ||
| @Singleton | ||
| internal fun provideDatabase( | ||
| @ApplicationContext context: Context, | ||
| ): WebsosoDatabase = | ||
| Room | ||
| .databaseBuilder( | ||
| context, | ||
| WebsosoDatabase::class.java, | ||
| "websoso.db", | ||
| ).build() | ||
| } | ||
37 changes: 0 additions & 37 deletions
37
core/database/src/main/java/com/into/websoso/core/database/dao/FilteredNovelDao.kt
This file was deleted.
Oops, something went wrong.
45 changes: 45 additions & 0 deletions
45
...n/java/com/into/websoso/core/database/datasource/library/DefaultLibraryLocalDataSource.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| package com.into.websoso.core.database.datasource.library | ||
|
|
||
| import androidx.paging.PagingSource | ||
| import com.into.websoso.core.database.datasource.library.dao.NovelDao | ||
| import com.into.websoso.core.database.datasource.library.entity.InDatabaseNovelEntity | ||
| import com.into.websoso.core.database.datasource.library.mapper.toData | ||
| import com.into.websoso.core.database.datasource.library.mapper.toNovelDatabase | ||
| import com.into.websoso.core.database.datasource.library.paging.mapValue | ||
| import com.into.websoso.data.library.datasource.LibraryLocalDataSource | ||
| import com.into.websoso.data.library.model.NovelEntity | ||
| import dagger.Binds | ||
| import dagger.Module | ||
| import dagger.hilt.InstallIn | ||
| import dagger.hilt.components.SingletonComponent | ||
| import javax.inject.Inject | ||
| import javax.inject.Singleton | ||
|
|
||
| internal class DefaultLibraryLocalDataSource | ||
| @Inject | ||
| constructor( | ||
| private val novelDao: NovelDao, | ||
| ) : LibraryLocalDataSource { | ||
| override suspend fun insertNovels(novels: List<NovelEntity>) { | ||
| val offset = novelDao.selectNovelsCount() | ||
| novelDao.insertNovels( | ||
| novels.mapIndexed { index, novelEntity -> | ||
| novelEntity.toNovelDatabase(offset + index) | ||
| }, | ||
| ) | ||
| } | ||
|
|
||
| override fun selectAllNovels(): PagingSource<Int, NovelEntity> = novelDao.selectAllNovels().mapValue(InDatabaseNovelEntity::toData) | ||
|
|
||
| override suspend fun deleteAllNovels() { | ||
| novelDao.deleteAllNovels() | ||
| } | ||
| } | ||
|
|
||
| @Module | ||
| @InstallIn(SingletonComponent::class) | ||
| internal interface LibraryDataSourceModule { | ||
| @Binds | ||
| @Singleton | ||
| fun bindLibraryDataSource(defaultLibraryLocalDataSource: DefaultLibraryLocalDataSource): LibraryLocalDataSource | ||
| } |
13 changes: 8 additions & 5 deletions
13
...nto/websoso/core/database/dao/NovelDao.kt → ...tabase/datasource/library/dao/NovelDao.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
...ase/src/main/java/com/into/websoso/core/database/datasource/library/mapper/NovelMapper.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| package com.into.websoso.core.database.datasource.library.mapper | ||
|
|
||
| import com.into.websoso.core.database.datasource.library.entity.InDatabaseNovelEntity | ||
| import com.into.websoso.data.library.model.NovelEntity | ||
|
|
||
| internal fun NovelEntity.toNovelDatabase(index: Int): InDatabaseNovelEntity = | ||
| InDatabaseNovelEntity( | ||
| userNovelId = userNovelId, | ||
| novelId = novelId, | ||
| title = title, | ||
| novelImage = novelImage, | ||
| novelRating = novelRating, | ||
| readStatus = readStatus, | ||
| isInterest = isInterest, | ||
| userNovelRating = userNovelRating, | ||
| attractivePoints = attractivePoints, | ||
| startDate = startDate, | ||
| endDate = endDate, | ||
| keywords = keywords, | ||
| myFeeds = myFeeds, | ||
| sortIndex = index, | ||
| ) | ||
|
|
||
| internal fun InDatabaseNovelEntity.toData(): NovelEntity = | ||
| NovelEntity( | ||
| userNovelId = userNovelId, | ||
| novelId = novelId, | ||
| title = title, | ||
| novelImage = novelImage, | ||
| novelRating = novelRating, | ||
| readStatus = readStatus, | ||
| isInterest = isInterest, | ||
| userNovelRating = userNovelRating, | ||
| attractivePoints = attractivePoints, | ||
| startDate = startDate, | ||
| endDate = endDate, | ||
| keywords = keywords, | ||
| myFeeds = myFeeds, | ||
| ) |
30 changes: 30 additions & 0 deletions
30
...ain/java/com/into/websoso/core/database/datasource/library/paging/MapValuePagingSource.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package com.into.websoso.core.database.datasource.library.paging | ||
|
|
||
| import androidx.paging.PagingSource | ||
| import androidx.paging.PagingState | ||
|
|
||
| internal fun <K : Any, From : Any, To : Any> PagingSource<K, From>.mapValue(mapper: suspend (From) -> To): PagingSource<K, To> = | ||
| MapValuePagingSource(this, mapper) | ||
|
|
||
| internal class MapValuePagingSource<Key : Any, From : Any, To : Any>( | ||
| private val targetSource: PagingSource<Key, From>, | ||
| private val mapper: suspend (From) -> To, | ||
| ) : PagingSource<Key, To>() { | ||
| override suspend fun load(params: LoadParams<Key>): LoadResult<Key, To> = | ||
| when (val result = targetSource.load(params)) { | ||
| is LoadResult.Page -> LoadResult.Page( | ||
| data = result.data.map { mapper(it) }, | ||
| prevKey = result.prevKey, | ||
| nextKey = result.nextKey, | ||
| itemsBefore = result.itemsBefore, | ||
| itemsAfter = result.itemsAfter, | ||
| ) | ||
|
|
||
| is LoadResult.Error -> LoadResult.Error(result.throwable) | ||
| is LoadResult.Invalid -> LoadResult.Invalid() | ||
| } | ||
|
|
||
| override val jumpingSupported: Boolean get() = targetSource.jumpingSupported | ||
|
|
||
| override fun getRefreshKey(state: PagingState<Key, To>): Key? = null | ||
| } |
28 changes: 28 additions & 0 deletions
28
core/database/src/main/java/com/into/websoso/core/database/di/DatabaseModule.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| package com.into.websoso.core.database.di | ||
|
|
||
| import android.content.Context | ||
| import androidx.room.Room | ||
| import com.into.websoso.core.database.WebsosoDatabase | ||
| import dagger.Module | ||
| import dagger.Provides | ||
| import dagger.hilt.InstallIn | ||
| import dagger.hilt.android.qualifiers.ApplicationContext | ||
| import dagger.hilt.components.SingletonComponent | ||
| import javax.inject.Singleton | ||
|
|
||
| @Module | ||
| @InstallIn(SingletonComponent::class) | ||
| internal object DatabaseModule { | ||
| @Provides | ||
| @Singleton | ||
| internal fun provideDatabase( | ||
| @ApplicationContext context: Context, | ||
| ): WebsosoDatabase = | ||
| Room | ||
| .databaseBuilder( | ||
| context, | ||
| WebsosoDatabase::class.java, | ||
| "websoso.db", | ||
| ).fallbackToDestructiveMigration() | ||
| .build() | ||
| } |
22 changes: 0 additions & 22 deletions
22
...base/src/main/java/com/into/websoso/core/database/entity/InDatabaseFilteredNovelEntity.kt
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
❓ Verification inconclusive
데이터베이스 스키마 단순화가 잘 되었습니다.
FilteredNovelEntity제거로 스키마가 단순해졌고, 버전을 5로 증가시킨 것이 적절합니다. 다만 마이그레이션 처리가 필요합니다.다음 스크립트로 마이그레이션 구현을 확인해주세요:
🏁 Script executed:
Length of output: 88
마이그레이션 구현 필요: 버전 4→5 누락 확인
RoomDatabase 버전을 4에서 5로 올리셨지만, 해당 마이그레이션 코드(예:
MIGRATION_4_5)와 이를addMigrations()로 등록하는 부분이 발견되지 않습니다. 스키마 변경 시 데이터 손실을 방지하려면 반드시 마이그레이션을 추가해 주세요.점검 항목:
MIGRATION_4_5객체(또는 함수) 정의 여부 확인Room.databaseBuilder(...).addMigrations(MIGRATION_4_5)호출 여부 확인🤖 Prompt for AI Agents
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
•fallbackToDestructiveMigration()은?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
@s9hn 좋은 지적입니다!
fallbackToDestructiveMigration()을 사용하는 것이 이 경우에는 더 적합할 수 있습니다.fallbackToDestructiveMigration()은 다음과 같은 상황에서 적절한 선택입니다:캐시된 데이터인 경우:
InDatabaseFilteredNovelEntity는 필터링된 소설 데이터를 캐시하는 용도로 보이며, 이는 다시 가져올 수 있는 데이터입니다.PR 목표와 부합: 이번 PR에서 "전체 사용자 서재 데이터를 백그라운드에서 가져오는 무거운 작업을 피하고, 사용자가 명시적으로 요청한 데이터만 캐시"하는 것이 목표라고 하셨는데, 기존 캐시 데이터를 버리고 새로 시작하는 것이 오히려 의도에 맞습니다.
데이터 손실이 허용되는 경우: 사용자의 중요한 데이터가 아닌 성능 최적화를 위한 캐시 데이터이므로 손실되어도 문제없습니다.
따라서
DatabaseModule에서 다음과 같이 설정하는 것을 추천합니다:이렇게 하면 명시적인 마이그레이션 코드 없이도 안전하게 스키마 변경을 처리할 수 있습니다.
🏁 Script executed:
Length of output: 49
현재 코드베이스에서
fallbackToDestructiveMigration()이 사용되지 않고 있습니다. DatabaseModule의 현재 구현을 확인해서 어떻게 설정되어 있는지 보겠습니다.🏁 Script executed:
Length of output: 48
🏁 Script executed:
Length of output: 828
🏁 Script executed:
Length of output: 829
@s9hn 맞습니다! 현재 DatabaseModule을 보니 마이그레이션 처리가 전혀 없는 상태네요.
fallbackToDestructiveMigration()을 사용하는 것이 이 상황에서 가장 적절한 해결책입니다.현재 DatabaseModule을 다음과 같이 수정하시면 됩니다:
이 방법이 적합한 이유:
제거된 엔티티의 성격:
InDatabaseFilteredNovelEntity는 필터링된 소설 데이터를 캐시하는 용도로, 사용자의 핵심 데이터가 아닙니다.PR 목표와 일치: "백그라운드에서 모든 사용자 서재 데이터를 가져오는 무거운 작업을 피하고, 사용자가 명시적으로 요청한 데이터만 캐시"한다는 목표에 부합합니다.
개발 효율성: 복잡한 마이그레이션 로직을 작성할 필요 없이 깔끔하게 스키마 변경을 처리할 수 있습니다.
데이터 특성: 캐시 데이터는 언제든 다시 가져올 수 있으므로 손실되어도 문제없습니다.
명시적 마이그레이션 대신
fallbackToDestructiveMigration()을 사용하는 것이 이번 리팩토링의 의도에 더 적합한 선택인 것 같습니다.