Skip to content

Conversation

@s9hn
Copy link
Member

@s9hn s9hn commented Jul 30, 2025

📌𝘐𝘴𝘴𝘶𝘦𝘴

📎𝘞𝘰𝘳𝘬 𝘋𝘦𝘴𝘤𝘳𝘪𝘱𝘵𝘪𝘰𝘯

  • 내 서재/ 유저 서재를 추상화하는 FilterRepository가 추가되었습니다.
  • 내 서재/ 유저 서재를 추상화하는 LibraryRepository가 추가되었습니다.

💬𝘛𝘰 𝘙𝘦𝘷𝘪𝘦𝘸𝘦𝘳𝘴

기존 코드를 굉장히 잘 설계했다고 생각했는데, 아주아주 크나큰 오산이었습니다 ^^.
UDF 패턴은 잘 지켰으나, '내서재'라는 기능에 너무 강하게 결합해버린 탓에 타유저 서재 분기처리 구현으로 확장이 매우 힘든...
아주 OCP를 위배해버린 구조였기에 구조를 뜯어 고쳤습니다.

우선 기능 요구 사항은 다음과 같습니다.

  • 내 서재 , 내 필터 -> 로컬 캐싱 기능 필요, 로컬 저장소로부터 자신의 userId를 조회
  • 유저 서재, 유저 필터 -> 캐싱 없이 1회성, Intent 혹은 Bundle로 넘어온 userId로 조회

성격별로 구현 요구사항이 다르기때문에, 인터페이스로 공통 책임과 상태값을 추상화했습니다.
내서재/유저서재 어느쪽에서든 재사용되는 library 피처 모듈은 굳이 '내서재'와 '유저서재' 를 식별할 필요 없이 서재 및 필터 CRUD 만
수행하면 되므로 추상화된 인터페이스에만 의존하도록 구현했습니다.

단, 어떤 구현체를 사용할지 분기처리를 구현해야 하므로, userId 유무에 따라 인스턴스 구분 및 주입했습니다.

@coderabbitai
Copy link

coderabbitai bot commented Jul 30, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

라이브러리(서재) 관련 데이터 구조와 리포지토리, 필터링, 페이징, DI 모듈, 뷰모델, UI 등 전체적인 구조가 대대적으로 리팩토링되었습니다. 기존의 MyLibrary/타유저 분기, 필터링 로직, 페이징, 뷰모델 분리가 새롭게 통합·정비되었으며, DI 및 네이밍도 일관성 있게 정리되었습니다.

Changes

Cohort / File(s) Change Summary
Navigator 및 DI 범위 조정
app/src/main/java/com/into/websoso/core/common/util/navigator/WebsosoNavigator.kt, core/auth-kakao/src/main/java/com/into/websoso/core/auth_kakao/KakaoAuthClient.kt, app/src/main/java/com/into/websoso/core/common/util/sessionManager/WebsosoAuthSessionManager.kt, core/datastore/src/main/java/com/into/websoso/core/datastore/datasource/account/DefaultAccountDataSource.kt, core/network/src/main/java/com/into/websoso/core/network/datasource/account/DefaultAccountDataSource.kt, core/network/src/main/java/com/into/websoso/core/network/datasource/library/DefaultLibraryDataSource.kt, data/library/src/main/java/com/into/websoso/data/library/datasource/LibraryLocalDataSource.kt
DI 범위 지정 어노테이션(@Singleton, @ActivityScoped) 추가 및 DI 바인딩 메서드에서 어노테이션 제거.
Navigator 및 UserStorageActivity 인텐트 변경
app/src/main/java/com/into/websoso/core/common/util/navigator/WebsosoNavigator.kt, app/src/main/java/com/into/websoso/ui/otherUserPage/otherUserLibrary/OtherUserLibraryFragment.kt, app/src/main/java/com/into/websoso/ui/userStorage/UserStorageActivity.kt, core/common/src/main/java/com/into/websoso/core/common/navigator/NavigatorProvider.kt
navigateToUserStorageActivityuserId 파라미터 추가, 인텐트 생성 시 userId 전달, 관련 인터페이스 시그니처 변경.
필터/라이브러리 데이터 구조 및 네이밍 일괄 변경
core/datastore/src/main/java/com/into/websoso/core/datastore/datasource/library/DefaultLibraryFilterDataSource.kt, core/datastore/src/main/java/com/into/websoso/core/datastore/datasource/library/mapper/LibraryFilterMapper.kt, core/datastore/src/main/java/com/into/websoso/core/datastore/datasource/library/model/LibraryFilterPreferences.kt, core/datastore/src/main/java/com/into/websoso/core/datastore/di/DataStoreModule.kt, core/datastore/src/main/java/com/into/websoso/core/datastore/di/DataStoreQualifier.kt
MyLibraryFilter → LibraryFilter로 네이밍 일괄 변경, 관련 데이터/매퍼/모듈/어노테이션/메서드명 전면 수정, 파라미터 타입 변경, 매핑 함수 신규 추가.
필터/라이브러리 도메인 및 데이터 계층 신규 도입 및 리팩토링
data/library/src/main/java/com/into/websoso/data/filter/FilterRepository.kt, data/library/src/main/java/com/into/websoso/data/filter/datasource/LibraryFilterLocalDataSource.kt, data/library/src/main/java/com/into/websoso/data/filter/di/FilterRepositoryModule.kt, data/library/src/main/java/com/into/websoso/data/filter/model/LibraryFilter.kt, data/library/src/main/java/com/into/websoso/data/filter/repository/MyLibraryFilterRepository.kt, data/library/src/main/java/com/into/websoso/data/filter/repository/UserLibraryFilterRepository.kt, data/library/src/main/java/com/into/websoso/data/library/LibraryRepository.kt, data/library/src/main/java/com/into/websoso/data/library/di/LibraryRepositoryModule.kt, data/library/src/main/java/com/into/websoso/data/library/repository/MyLibraryRepository.kt, data/library/src/main/java/com/into/websoso/data/library/repository/UserLibraryRepository.kt, data/library/src/main/java/com/into/websoso/data/library/paging/LibraryPagingSource.kt, data/library/src/main/java/com/into/websoso/data/library/paging/LibraryRemoteMediator.kt
도메인/데이터 계층 분리, 필터/라이브러리 관련 인터페이스 및 구현 신규 도입, PagingSource/RemoteMediator 신규 작성, 기존 Mediator/Params/Enum 등 삭제, 분기처리/필터링/페이징 로직 재구성.
기존 데이터/도메인/뷰모델/파일 삭제
data/library/src/main/java/com/into/websoso/data/library/datasource/MyLibraryFilterLocalDataSource.kt, data/library/src/main/java/com/into/websoso/data/library/mediator/NovelRemoteMediator.kt, data/library/src/main/java/com/into/websoso/data/library/model/LibraryFilterParams.kt, data/library/src/main/java/com/into/websoso/data/library/model/LibraryReadStatus.kt, domain/library/src/main/java/com/into/websoso/domain/library/GetLibraryUseCase.kt, feature/library/src/main/java/com/into/websoso/feature/library/filter/LibraryFilterViewModel.kt
기존 MyLibraryFilter, Mediator, Params, Enum, UseCase, FilterViewModel 등 삭제.
UI/뷰모델 리팩토링 및 분기처리
feature/library/src/main/java/com/into/websoso/feature/library/LibraryScreen.kt, feature/library/src/main/java/com/into/websoso/feature/library/LibraryViewModel.kt, feature/library/src/main/java/com/into/websoso/feature/library/filter/LibraryFilterBottomSheetScreen.kt
필터 뷰모델 제거, LibraryViewModel에서 필터 상태/이벤트 직접 관리, UI에서 필터 관련 콜백 및 상태 분리, 타유저/내서재 분기처리, paging flow 및 필터 flow 연동.
DB DAO 변경
core/database/src/main/java/com/into/websoso/core/database/dao/FilteredNovelDao.kt
전체 소설 개수 반환하는 selectNovelsCount 메서드 추가, 인덱스 관리 개선.
FilteredLibraryLocalDataSource 인덱스 개선
data/library/src/main/java/com/into/websoso/data/library/datasource/FilteredLibraryLocalDataSource.kt
소설 인서트 시 기존 개수만큼 인덱스 offset 적용.

Sequence Diagram(s)

sequenceDiagram
actor User
participant LibraryScreen
participant LibraryViewModel
participant FilterRepository
participant LibraryRepository
participant PagingSource/RemoteMediator

User->>LibraryScreen: 필터/정렬/관심 등 UI 상호작용
LibraryScreen->>LibraryViewModel: onAttractivePointClick, onReadStatusClick 등 콜백
LibraryViewModel->>FilterRepository: updateFilter(), filterFlow 변경
FilterRepository-->>LibraryViewModel: filterFlow emit
LibraryViewModel->>LibraryRepository: libraryFlow(필터 반영)
LibraryRepository->>PagingSource/RemoteMediator: 페이징 쿼리 및 데이터 fetch
PagingSource/RemoteMediator-->>LibraryRepository: PagingData<NovelEntity>
LibraryRepository-->>LibraryViewModel: PagingData emit
LibraryViewModel-->>LibraryScreen: novels flow collect
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Assessment against linked issues

Objective Addressed Explanation
타유저 서재 분기처리 및 관련 UI/UX 개편 (#699)
필터/정렬/관심/평점 등 필터링 로직 통합 및 구조 개선 (#699)
Paging 및 데이터 흐름 개선, 분기처리 반영 (#699)
기존 MyLibrary/타유저 분기, Mediator, Params 등 레거시 코드 제거 (#699)

Assessment against linked issues: Out-of-scope changes

(해당 변경사항에는 명확히 범위를 벗어난 코드 변경이 발견되지 않았습니다.)

Possibly related PRs

Suggested reviewers

  • junseo511
  • yeonjeen
  • m6z1

Poem

🐰
필터도 새 옷 입고, 분기도 척척!
내 서재, 네 서재, 이제는 똑똑
페이징도 술술, 뷰모델도 산뜻
토끼는 깡총, 코드도 깔끔
라이브러리 탐험, 이젠 더 즐겁쥐!
🥕✨

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/699

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@s9hn s9hn changed the title Feat/699 feat: 서재UI/UX 개편 (5) - 타유저 서재 분기처리 Jul 30, 2025
@github-actions github-actions bot requested review from junseo511, m6z1 and yeonjeen July 30, 2025 07:58
@s9hn s9hn added 🍯 [FEAT] 새로운 기능을 개발합니다. ⚖️ 재상 세훈 전지적 세훈 시점 labels Jul 30, 2025
@s9hn
Copy link
Member Author

s9hn commented Jul 30, 2025

@coderabbitai code review plz

@coderabbitai
Copy link

coderabbitai bot commented Jul 30, 2025

@s9hn I'll review the changes in this PR for the library UI/UX redesign focusing on other user library branching functionality.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🔭 Outside diff range comments (1)
feature/library/src/main/java/com/into/websoso/feature/library/LibraryViewModel.kt (1)

51-73: 필터 업데이트 로직에 오류 처리 추가 권장

ReadStatus.from()AttractivePoints.from() 메서드가 유효하지 않은 키로 인해 예외를 발생시킬 수 있습니다. 안정성을 위해 try-catch 블록을 추가하는 것을 고려해보세요.

 private fun updateLibraryFilter() {
     viewModelScope.launch {
-        filterRepository.filterFlow.collect { filter ->
-            _uiState.update { uiState ->
-                uiState.copy(
-                    libraryFilterUiState = uiState.libraryFilterUiState.copy(
-                        selectedSortType = SortTypeUiModel.valueOf(filter.sortCriteria),
-                        isInterested = filter.isInterested,
-                        readStatuses = filter.readStatuses
-                            .mapKeys {
-                                ReadStatus.from(it.key)
-                            }.ifEmpty { uiState.libraryFilterUiState.readStatuses },
-                        attractivePoints = filter.attractivePoints
-                            .mapKeys {
-                                AttractivePoints.from(it.key)
-                            }.ifEmpty { uiState.libraryFilterUiState.attractivePoints },
-                        novelRating = filter.novelRating,
-                    ),
-                )
+        filterRepository.filterFlow.collect { filter ->
+            try {
+                _uiState.update { uiState ->
+                    uiState.copy(
+                        libraryFilterUiState = uiState.libraryFilterUiState.copy(
+                            selectedSortType = SortTypeUiModel.valueOf(filter.sortCriteria),
+                            isInterested = filter.isInterested,
+                            readStatuses = filter.readStatuses
+                                .mapKeys {
+                                    ReadStatus.from(it.key)
+                                }.ifEmpty { uiState.libraryFilterUiState.readStatuses },
+                            attractivePoints = filter.attractivePoints
+                                .mapKeys {
+                                    AttractivePoints.from(it.key)
+                                }.ifEmpty { uiState.libraryFilterUiState.attractivePoints },
+                            novelRating = filter.novelRating,
+                        ),
+                    )
+                }
+            } catch (e: Exception) {
+                // 로깅 또는 기본값으로 폴백
             }
         }
     }
 }
🧹 Nitpick comments (8)
core/database/src/main/java/com/into/websoso/core/database/dao/FilteredNovelDao.kt (1)

27-28: COUNT 결과 타입 Long 사용 고려
SELECT COUNT(*)는 최대값이 Int 범위를 넘어설 수 있습니다. 안전성을 위해 Long 반환으로 선언해 두면 향후 확장에 대비할 수 있습니다.

data/library/src/main/java/com/into/websoso/data/filter/FilterRepository.kt (1)

6-16: 필터 리포지토리 인터페이스 설계를 승인하며 개선 사항을 제안합니다.

Flow를 활용한 반응형 상태 관리와 명확한 추상화가 잘 구현되어 있습니다. 다만 updateFilter 메서드의 다수 선택적 매개변수는 향후 유지보수성을 위해 데이터 클래스 매개변수 사용을 고려해볼 수 있습니다.

선택적 개선안: 데이터 클래스 매개변수 활용

+data class FilterUpdateParams(
+    val readStatuses: Map<String, Boolean>? = null,
+    val attractivePoints: Map<String, Boolean>? = null,
+    val novelRating: Float? = null,
+    val isInterested: Boolean? = null,
+    val sortCriteria: String? = null,
+)

 suspend fun updateFilter(
-    readStatuses: Map<String, Boolean>? = null,
-    attractivePoints: Map<String, Boolean>? = null,
-    novelRating: Float? = null,
-    isInterested: Boolean? = null,
-    sortCriteria: String? = null,
+    params: FilterUpdateParams = FilterUpdateParams(),
 )
data/library/src/main/java/com/into/websoso/data/filter/di/FilterRepositoryModule.kt (1)

24-24: 하드코딩된 문자열을 상수로 추출하세요

"USER_ID" 문자열이 하드코딩되어 있습니다. 유지보수성과 일관성을 위해 상수로 추출하는 것이 좋겠습니다.

+    private const val KEY_USER_ID = "USER_ID"
+
     @Provides
     @ViewModelScoped
     fun provideFilterRepository(
         savedStateHandle: SavedStateHandle,
         myFilterRepository: Provider<MyLibraryFilterRepository>,
         userFilterRepository: Provider<UserLibraryFilterRepository>,
     ): FilterRepository {
-        val userId: Long? = savedStateHandle["USER_ID"]
+        val userId: Long? = savedStateHandle[KEY_USER_ID]
         return if (userId == null) myFilterRepository.get() else userFilterRepository.get()
     }
data/library/src/main/java/com/into/websoso/data/library/di/LibraryRepositoryModule.kt (1)

17-26: 사용자 컨텍스트 기반 저장소 분기 로직이 잘 구현되었습니다.

SavedStateHandle에서 USER_ID의 존재 여부에 따라 적절한 저장소를 제공하는 조건부 로직이 정확합니다. 이는 PR 제목에서 언급한 "타유저 서재 분기처리"의 핵심 구현체입니다.

하드코딩된 키 상수화를 고려해보세요:

+    companion object {
+        private const val USER_ID_KEY = "USER_ID"
+    }
+
     fun provideLibraryRepository(
         savedStateHandle: SavedStateHandle,
         myLibraryRepository: Provider<MyLibraryRepository>,
         userLibraryRepository: Provider<UserLibraryRepository.Factory>
     ): LibraryRepository {
-        val userId: Long? = savedStateHandle["USER_ID"]
+        val userId: Long? = savedStateHandle[USER_ID_KEY]
         return if (userId == null) myLibraryRepository.get() else userLibraryRepository.get().create(userId)
     }
data/library/src/main/java/com/into/websoso/data/filter/model/LibraryFilter.kt (1)

3-24: 통합된 필터 모델 설계가 훌륭합니다.

여러 개별 파라미터를 하나의 데이터 클래스로 통합한 것은 뛰어난 리팩토링입니다. 특히 다음 요소들이 우수합니다:

  • 파생 속성(readStatusKeys, attractivePointKeys)을 통한 편리한 데이터 접근
  • 재사용 가능한 제네릭 확장 함수 toSelectedKeyList
  • 적절한 기본값 설정으로 사용성 향상

확장 함수의 타입 파라미터 제약을 더 명확하게 할 수 있습니다:

-    private fun <K> Map<K, Boolean>.toSelectedKeyList(toSelectedKeyName: (K) -> String): List<String> =
+    private fun <K : Any> Map<K, Boolean>.toSelectedKeyList(toSelectedKeyName: (K) -> String): List<String> =

이렇게 하면 null 키에 대한 잠재적 문제를 방지할 수 있습니다.

data/library/src/main/java/com/into/websoso/data/library/repository/UserLibraryRepository.kt (1)

19-30: 클래스 문서화 추가 권장

이 클래스는 타유저의 서재 데이터를 관리하는 중요한 역할을 담당합니다. 클래스의 목적과 MyLibraryRepository와의 차이점을 명확히 하는 KDoc 주석을 추가하면 좋겠습니다.

+/**
+ * 타유저의 서재 데이터를 관리하는 Repository
+ * 
+ * @param filterRepository 필터 상태를 관리하는 Repository
+ * @param userId 조회할 유저의 ID
+ * @param libraryRemoteDataSource 서재 데이터를 원격에서 가져오는 DataSource
+ */
internal class UserLibraryRepository
data/library/src/main/java/com/into/websoso/data/library/repository/MyLibraryRepository.kt (1)

24-31: 클래스 문서화 추가 권장

현재 사용자의 서재 데이터를 관리하며 로컬 캐싱을 지원하는 Repository입니다. UserLibraryRepository와의 차이점을 명확히 하는 문서를 추가하면 좋겠습니다.

+/**
+ * 현재 로그인한 사용자의 서재 데이터를 관리하는 Repository
+ * RemoteMediator를 사용하여 로컬 캐싱을 지원함
+ * 
+ * @param filterRepository 필터 상태를 관리하는 Repository
+ * @param accountRepository 계정 정보를 관리하는 Repository
+ * @param libraryRemoteDataSource 서재 데이터를 원격에서 가져오는 DataSource
+ * @param filteredLibraryLocalDataSource 필터링된 서재 데이터를 로컬에서 관리하는 DataSource
+ */
internal class MyLibraryRepository
feature/library/src/main/java/com/into/websoso/feature/library/LibraryViewModel.kt (1)

111-115: 함수명을 더 명확하게 변경하는 것을 고려해보세요

updateMyLibraryFilter보다는 initializeTempFilterState 또는 prepareFilterForEditing 같은 이름이 함수의 목적을 더 명확하게 표현할 수 있습니다.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4d73e7d and f3b0126.

📒 Files selected for processing (38)
  • app/src/main/java/com/into/websoso/core/common/util/navigator/WebsosoNavigator.kt (2 hunks)
  • app/src/main/java/com/into/websoso/core/common/util/sessionManager/WebsosoAuthSessionManager.kt (1 hunks)
  • app/src/main/java/com/into/websoso/ui/otherUserPage/otherUserLibrary/OtherUserLibraryFragment.kt (2 hunks)
  • app/src/main/java/com/into/websoso/ui/userStorage/UserStorageActivity.kt (1 hunks)
  • core/auth-kakao/src/main/java/com/into/websoso/core/auth_kakao/KakaoAuthClient.kt (1 hunks)
  • core/common/src/main/java/com/into/websoso/core/common/navigator/NavigatorProvider.kt (1 hunks)
  • core/database/src/main/java/com/into/websoso/core/database/dao/FilteredNovelDao.kt (1 hunks)
  • core/datastore/src/main/java/com/into/websoso/core/datastore/datasource/account/DefaultAccountDataSource.kt (1 hunks)
  • core/datastore/src/main/java/com/into/websoso/core/datastore/datasource/library/DefaultLibraryFilterDataSource.kt (4 hunks)
  • core/datastore/src/main/java/com/into/websoso/core/datastore/datasource/library/mapper/LibraryFilterMapper.kt (1 hunks)
  • core/datastore/src/main/java/com/into/websoso/core/datastore/datasource/library/model/LibraryFilterPreferences.kt (1 hunks)
  • core/datastore/src/main/java/com/into/websoso/core/datastore/di/DataStoreModule.kt (2 hunks)
  • core/datastore/src/main/java/com/into/websoso/core/datastore/di/DataStoreQualifier.kt (1 hunks)
  • core/network/src/main/java/com/into/websoso/core/network/datasource/account/DefaultAccountDataSource.kt (1 hunks)
  • core/network/src/main/java/com/into/websoso/core/network/datasource/library/DefaultLibraryDataSource.kt (1 hunks)
  • data/library/src/main/java/com/into/websoso/data/filter/FilterRepository.kt (1 hunks)
  • data/library/src/main/java/com/into/websoso/data/filter/datasource/LibraryFilterLocalDataSource.kt (1 hunks)
  • data/library/src/main/java/com/into/websoso/data/filter/di/FilterRepositoryModule.kt (1 hunks)
  • data/library/src/main/java/com/into/websoso/data/filter/model/LibraryFilter.kt (1 hunks)
  • data/library/src/main/java/com/into/websoso/data/filter/repository/MyLibraryFilterRepository.kt (1 hunks)
  • data/library/src/main/java/com/into/websoso/data/filter/repository/UserLibraryFilterRepository.kt (1 hunks)
  • data/library/src/main/java/com/into/websoso/data/library/LibraryRepository.kt (1 hunks)
  • data/library/src/main/java/com/into/websoso/data/library/datasource/FilteredLibraryLocalDataSource.kt (1 hunks)
  • data/library/src/main/java/com/into/websoso/data/library/datasource/LibraryLocalDataSource.kt (1 hunks)
  • data/library/src/main/java/com/into/websoso/data/library/datasource/MyLibraryFilterLocalDataSource.kt (0 hunks)
  • data/library/src/main/java/com/into/websoso/data/library/di/LibraryRepositoryModule.kt (1 hunks)
  • data/library/src/main/java/com/into/websoso/data/library/mediator/NovelRemoteMediator.kt (0 hunks)
  • data/library/src/main/java/com/into/websoso/data/library/model/LibraryFilterParams.kt (0 hunks)
  • data/library/src/main/java/com/into/websoso/data/library/model/LibraryReadStatus.kt (0 hunks)
  • data/library/src/main/java/com/into/websoso/data/library/paging/LibraryPagingSource.kt (1 hunks)
  • data/library/src/main/java/com/into/websoso/data/library/paging/LibraryRemoteMediator.kt (3 hunks)
  • data/library/src/main/java/com/into/websoso/data/library/repository/MyLibraryRepository.kt (1 hunks)
  • data/library/src/main/java/com/into/websoso/data/library/repository/UserLibraryRepository.kt (1 hunks)
  • domain/library/src/main/java/com/into/websoso/domain/library/GetLibraryUseCase.kt (0 hunks)
  • feature/library/src/main/java/com/into/websoso/feature/library/LibraryScreen.kt (10 hunks)
  • feature/library/src/main/java/com/into/websoso/feature/library/LibraryViewModel.kt (4 hunks)
  • feature/library/src/main/java/com/into/websoso/feature/library/filter/LibraryFilterBottomSheetScreen.kt (2 hunks)
  • feature/library/src/main/java/com/into/websoso/feature/library/filter/LibraryFilterViewModel.kt (0 hunks)
💤 Files with no reviewable changes (6)
  • data/library/src/main/java/com/into/websoso/data/library/datasource/MyLibraryFilterLocalDataSource.kt
  • data/library/src/main/java/com/into/websoso/data/library/model/LibraryReadStatus.kt
  • data/library/src/main/java/com/into/websoso/data/library/model/LibraryFilterParams.kt
  • data/library/src/main/java/com/into/websoso/data/library/mediator/NovelRemoteMediator.kt
  • feature/library/src/main/java/com/into/websoso/feature/library/filter/LibraryFilterViewModel.kt
  • domain/library/src/main/java/com/into/websoso/domain/library/GetLibraryUseCase.kt
🧰 Additional context used
🧠 Learnings (4)
core/datastore/src/main/java/com/into/websoso/core/datastore/di/DataStoreModule.kt (1)

Learnt from: s9hn
PR: #676
File: core/network/src/main/java/com/into/websoso/core/network/interceptor/AuthorizationInterceptor.kt:27-34
Timestamp: 2025-05-14T07:41:05.706Z
Learning: Accessing DataStore via runBlocking in OkHttp interceptors can block network threads and cause performance issues. Consider using in-memory caching with background updates instead to achieve thread safety without blocking OkHttp threads.

feature/library/src/main/java/com/into/websoso/feature/library/filter/LibraryFilterBottomSheetScreen.kt (1)

Learnt from: s9hn
PR: #728
File: feature/library/src/main/java/com/into/websoso/feature/library/LibraryScreen.kt:77-84
Timestamp: 2025-07-24T09:02:01.000Z
Learning: bottomSheetState.show()는 바텀시트 애니메이션이 완료될 때까지 suspend하는 함수이므로, invokeOnCompletion에서 실행되는 코드는 바텀시트가 완전히 표시된 후에 실행된다.

feature/library/src/main/java/com/into/websoso/feature/library/LibraryScreen.kt (1)

Learnt from: s9hn
PR: #728
File: feature/library/src/main/java/com/into/websoso/feature/library/LibraryScreen.kt:77-84
Timestamp: 2025-07-24T09:02:01.000Z
Learning: bottomSheetState.show()는 바텀시트 애니메이션이 완료될 때까지 suspend하는 함수이므로, invokeOnCompletion에서 실행되는 코드는 바텀시트가 완전히 표시된 후에 실행된다.

core/datastore/src/main/java/com/into/websoso/core/datastore/datasource/library/DefaultLibraryFilterDataSource.kt (1)

Learnt from: s9hn
PR: #676
File: core/network/src/main/java/com/into/websoso/core/network/interceptor/AuthorizationInterceptor.kt:27-34
Timestamp: 2025-05-14T07:41:05.706Z
Learning: Accessing DataStore via runBlocking in OkHttp interceptors can block network threads and cause performance issues. Consider using in-memory caching with background updates instead to achieve thread safety without blocking OkHttp threads.

🔇 Additional comments (40)
app/src/main/java/com/into/websoso/core/common/util/sessionManager/WebsosoAuthSessionManager.kt (1)

14-17: 싱글톤 주입 구조 정리 👍
클래스에 직접 @Singleton을 부여해 스코프가 명확해졌습니다. 별다른 문제 없습니다.

core/datastore/src/main/java/com/into/websoso/core/datastore/di/DataStoreQualifier.kt (1)

11-11: Qualifier 네이밍 일관성 확보
MyLibraryLibrary로 변경되어 모듈 전반의 명칭이 통일되었습니다. 이상 없습니다.

core/auth-kakao/src/main/java/com/into/websoso/core/auth_kakao/KakaoAuthClient.kt (1)

18-23: 스코프 적절성 확인 필요
@ActivityScoped로 변경되어 Activity 수명 주기로 제한됩니다.
이 클래스를 Fragment / ViewModel 등 Activity 외부 스코프에서 주입하지 않는지 한번 더 확인해 주세요.

app/src/main/java/com/into/websoso/ui/userStorage/UserStorageActivity.kt (2)

44-51: 사용자 ID 전달 로직이 올바르게 구현되었습니다.

Intent에 USER_ID를 추가하는 로직이 정확하게 구현되어 있습니다.


24-41: 사용자 ID 전달 확인 필요

Activity에서 Intent로 전달받은 USER_ID를 추출하여 LibraryViewModel에 전달하지 않고 있어, 사용자별 라이브러리 구분이 누락될 수 있습니다.

확인 대상:

  • app/src/main/java/com/into/websoso/ui/userStorage/UserStorageActivity.kt onCreate 내부에서 intent.get…Extra("USER_ID") 호출 여부
  • LibraryViewModel 생성자 또는 팩토리 메서드가 userId 파라미터를 수신하도록 정의되어 있는지

예시 변경안:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    val userId = intent.getStringExtra("USER_ID")
        ?: error("USER_ID가 필요합니다")

    // userId를 파라미터로 받아들이도록 ViewModel 초기화
    val libraryViewModel = LibraryViewModel(userId)

    enableEdgeToEdge()
    setContent {
        WebsosoTheme {
            LibraryScreen(
                libraryViewModel = libraryViewModel,
                ...
            )
        }
    }
}
data/library/src/main/java/com/into/websoso/data/library/datasource/LibraryLocalDataSource.kt (1)

22-22: 싱글톤 스코프 선언을 구현 클래스로 이동한 변경사항이 적절합니다.

@singleton 어노테이션을 바인딩 메서드에서 구현 클래스로 이동하는 것은 DI 모범 사례에 부합하며, 프로젝트 전반의 일관성을 높입니다.

core/datastore/src/main/java/com/into/websoso/core/datastore/datasource/account/DefaultAccountDataSource.kt (1)

18-18: 일관된 싱글톤 어노테이션 리팩토링입니다.

다른 데이터 소스들과 동일한 패턴으로 @singleton 어노테이션을 구현 클래스에 직접 적용하여 일관성을 유지했습니다.

app/src/main/java/com/into/websoso/ui/otherUserPage/otherUserLibrary/OtherUserLibraryFragment.kt (3)

43-43: 사용자 ID 캐싱이 효율적으로 구현되었습니다.

lazy 프로퍼티를 사용하여 fragment arguments에서 userId를 한 번만 추출하고 재사용하는 방식이 효율적입니다.


66-68: 캐시된 userId 사용이 올바릅니다.

updateUserId 메서드에서 캐시된 userId를 사용하여 중복 추출을 방지했습니다.


224-226: 사용자별 네비게이션이 올바르게 구현되었습니다.

navigateToUserStorageActivity 호출 시 userId를 전달하여 사용자별 라이브러리 접근을 지원합니다.

core/common/src/main/java/com/into/websoso/core/common/navigator/NavigatorProvider.kt (1)

18-21: 사용자별 네비게이션을 위한 인터페이스 업데이트가 적절합니다.

navigateToUserStorageActivity 메서드에 userId 매개변수를 추가하여 사용자별 라이브러리 접근을 지원하도록 인터페이스를 개선했습니다.

core/network/src/main/java/com/into/websoso/core/network/datasource/library/DefaultLibraryDataSource.kt (1)

12-12: 의존성 주입 스코프 선언 개선을 승인합니다.

@Singleton 어노테이션을 구현 클래스에 직접 선언하여 스코프를 명확하게 하고 일관성을 높였습니다. 이는 의존성 주입 모범 사례를 따르는 좋은 변경사항입니다.

core/network/src/main/java/com/into/websoso/core/network/datasource/account/DefaultAccountDataSource.kt (1)

18-18: 의존성 주입 스코프 일관성 개선을 승인합니다.

이전 파일과 동일한 패턴으로 @Singleton 어노테이션을 구현 클래스로 이동하여 코드베이스 전반의 일관성을 높였습니다.

data/library/src/main/java/com/into/websoso/data/filter/datasource/LibraryFilterLocalDataSource.kt (1)

6-12: 잘 설계된 로컬 데이터 소스 인터페이스입니다.

반응형 프로그래밍을 위한 Flow 사용, 명확한 관심사 분리, 비동기 작업을 위한 suspend 함수 활용 등 좋은 아키텍처 패턴을 따르고 있습니다. 인터페이스 설계가 일관성 있고 명확합니다.

core/datastore/src/main/java/com/into/websoso/core/datastore/di/DataStoreModule.kt (2)

20-23: 네이밍 일반화를 통한 아키텍처 개선을 승인합니다.

"MY_LIBRARY_FILTER_DATASTORE"에서 "LIBRARY_FILTER_DATASTORE"로의 네이밍 변경은 내 서재와 타 유저 서재를 모두 지원하는 새로운 아키텍처 목표에 부합합니다.


34-37: 의존성 주입 프로바이더 네이밍 일관성을 승인합니다.

프로바이더 함수명과 한정자 어노테이션의 네이밍 변경이 일관성 있게 적용되어 코드베이스 전반의 통일성을 높였습니다.

core/datastore/src/main/java/com/into/websoso/core/datastore/datasource/library/model/LibraryFilterPreferences.kt (1)

1-12: 변경사항이 적절합니다

LibraryFilterParams와의 변환 함수 제거가 새로운 LibraryFilter 모델 도입과 일관성 있게 진행되었습니다. 데이터 클래스 구조는 깔끔하게 유지되고 있습니다.

core/datastore/src/main/java/com/into/websoso/core/datastore/datasource/library/mapper/LibraryFilterMapper.kt (1)

6-22: 매퍼 구현이 깔끔합니다

LibraryFilterLibraryFilterPreferences 간의 양방향 변환이 명확하게 구현되었습니다. internal 가시성 설정도 적절합니다.

data/library/src/main/java/com/into/websoso/data/filter/di/FilterRepositoryModule.kt (1)

19-26: 조건부 리포지토리 주입 로직이 적절합니다

SavedStateHandle을 통한 userId 확인과 그에 따른 리포지토리 선택 로직이 명확합니다. Provider 사용으로 순환 의존성 문제도 방지했습니다.

data/library/src/main/java/com/into/websoso/data/library/LibraryRepository.kt (1)

7-13: 인터페이스 설계가 깔끔합니다

구체적인 구현체에서 인터페이스로의 리팩토링이 잘 이루어졌습니다. 단일 책임 원칙을 따르며, PAGE_SIZE 상수를 companion object에 둔 것도 적절합니다.

app/src/main/java/com/into/websoso/core/common/util/navigator/WebsosoNavigator.kt (2)

20-20: 싱글톤 스코프 선언이 명확해졌습니다

클래스 레벨에 @Singleton 어노테이션을 추가하여 스코프가 더 명확해졌습니다.


50-56: userId 파라미터 전달이 올바르게 구현되었습니다

navigateToUserStorageActivity 메서드가 userId를 받아서 제대로 전달하도록 수정되었습니다. 타유저 서재 분기 처리에 필수적인 변경사항입니다.

data/library/src/main/java/com/into/websoso/data/library/paging/LibraryRemoteMediator.kt (2)

19-23: 생성자 파라미터 단순화가 잘 되었습니다.

여러 개의 개별 필터 파라미터를 LibraryFilter 객체 하나로 통합한 것은 좋은 리팩토링입니다. 코드의 가독성과 유지보수성이 향상되었습니다.


40-48: 필터 매핑 로직이 올바르게 구현되었습니다.

LibraryFilter 객체의 속성들을 API 파라미터로 변환하는 로직이 정확합니다. 특히 빈 리스트와 기본값에 대한 null 처리가 적절하게 되어있습니다.

data/library/src/main/java/com/into/websoso/data/filter/repository/UserLibraryFilterRepository.kt (1)

12-36: 다른 사용자 서재 필터 저장소 구현이 적절합니다.

인메모리 상태 관리를 사용한 구현이 올바릅니다. MutableStateFlow를 통한 반응형 상태 관리와 null 체크를 통한 부분 업데이트 로직이 정확히 구현되어 있습니다.

다른 사용자의 서재를 볼 때는 필터 상태를 영구 저장하지 않는 것이 합리적인 설계 결정으로 보입니다.

data/library/src/main/java/com/into/websoso/data/filter/repository/MyLibraryFilterRepository.kt (1)

12-40: 내 서재 필터 저장소 구현이 우수합니다.

로컬 데이터소스를 통한 필터 상태 영구 저장과 반응형 플로우 관리가 잘 구현되어 있습니다.

특히 다음 요소들이 좋습니다:

  • distinctUntilChanged()를 통한 불필요한 방출 방지
  • null 안전성을 위한 기본값 매핑
  • 부분 업데이트를 지원하는 유연한 updateFilter 구현

내 서재와 다른 사용자 서재의 필터 저장 방식을 다르게 처리한 아키텍처 결정이 합리적입니다.

data/library/src/main/java/com/into/websoso/data/library/repository/UserLibraryRepository.kt (1)

31-32: flatMapLatest가 여전히 실험적 API로 남아 있어 @OptIn(ExperimentalCoroutinesApi::class) 유지 필요

  • 파일: data/library/src/main/java/com/into/websoso/data/library/repository/UserLibraryRepository.kt (31–32행)
  • 확인 내용: 2025년 7월 기준 공식 문서에 따르면 flatMapLatest는 여전히 @ExperimentalCoroutinesApi로 표시되어 있습니다.
  • 제안: 현재 적용된 @OptIn(ExperimentalCoroutinesApi::class) 어노테이션을 유지하고, 향후 Kotlin Coroutines 버전 업그레이드 시 해당 API의 안정화 여부를 재검토하세요.
data/library/src/main/java/com/into/websoso/data/library/repository/MyLibraryRepository.kt (1)

38-44: RemoteMediator 패턴 구현이 적절합니다

오프라인 지원을 위한 RemoteMediator 패턴이 잘 구현되어 있습니다. 원격 데이터를 로컬에 캐싱하고, 필터링된 데이터를 제공하는 구조가 좋습니다.

feature/library/src/main/java/com/into/websoso/feature/library/filter/LibraryFilterBottomSheetScreen.kt (2)

34-56: 필터 UI의 상태 관리 개선

ViewModel 의존성을 제거하고 상태와 콜백을 파라미터로 받도록 리팩토링한 것이 좋습니다. 이를 통해 테스트 가능성과 재사용성이 향상되었습니다.


124-127: 필터 검색 시 dismiss 순서 확인

onDismissRequest()를 먼저 호출하고 onFilterSearchClick()을 호출하는 순서가 적절한지 확인이 필요합니다. 필터 적용 로직이 바텀시트가 닫힌 후에 실행되어야 한다면 문제가 없지만, 순서에 민감한 경우 고려가 필요합니다.

data/library/src/main/java/com/into/websoso/data/library/paging/LibraryPagingSource.kt (1)

15-48: 페이징 로직 구현이 적절합니다

필터 파라미터를 올바르게 적용하고, 페이징 키를 적절히 관리하며, 에러 처리도 포함되어 있습니다. 전반적으로 잘 구현되었습니다.

feature/library/src/main/java/com/into/websoso/feature/library/LibraryScreen.kt (3)

62-117: ViewModel 통합 및 상태 관리 개선

필터 관련 상태와 이벤트 핸들링을 LibraryViewModel로 통합한 것이 좋습니다. 이를 통해 상태 관리가 단순해지고 데이터 흐름이 명확해졌습니다.


98-104: 바텀시트 애니메이션 처리가 적절합니다

이전 학습 내용대로 bottomSheetState.show()가 애니메이션 완료까지 suspend되므로, invokeOnCompletion에서 필터 업데이트를 처리하는 것이 적절합니다.


169-176: 필터링된 빈 상태 처리 추가

필터가 적용된 상태에서 결과가 없을 때와 전체 서재가 비어있을 때를 구분하여 처리하는 것이 좋은 UX입니다.

core/datastore/src/main/java/com/into/websoso/core/datastore/datasource/library/DefaultLibraryFilterDataSource.kt (3)

29-35: 구현이 적절합니다!

의존성 주입과 싱글톤 패턴이 올바르게 적용되었으며, 코루틴 디스패처를 주입받아 테스트 가능성도 확보했습니다.


36-44: Flow 구현이 효율적입니다!

JSON 역직렬화를 위한 withContext 사용과 distinctUntilChanged()를 통한 중복 방출 방지가 적절하게 구현되었습니다.


69-74: Dagger 모듈 구현이 올바릅니다!

구현체에 @Singleton 스코프가 적용되어 있으므로 바인딩 메서드에는 별도의 스코프 어노테이션이 필요하지 않습니다.

feature/library/src/main/java/com/into/websoso/feature/library/LibraryViewModel.kt (3)

28-46: ViewModel 구조가 잘 설계되었습니다!

Repository 분리, 상태 관리, 그리고 페이징 데이터 캐싱이 적절하게 구현되었습니다. 임시 필터 상태를 별도로 관리하는 것도 좋은 UX 패턴입니다.


81-85: 스크롤 위치 리셋 구현이 적절합니다!

Channel을 통한 일회성 이벤트 전달 패턴이 올바르게 구현되었습니다.


117-135: 필터 업데이트 함수들이 잘 구현되었습니다!

토글 로직이 간결하고 함수형 프로그래밍 패턴을 잘 활용했습니다.

Comment on lines +46 to 56
override suspend fun updateLibraryFilter(params: LibraryFilter) {
val encodedJsonString = withContext(dispatcher) {
Json.encodeToString(
params.toPreferences(),
)
}

myLibraryFilterDataStore.edit { prefs ->
libraryFilterDataStore.edit { prefs ->
prefs[LIBRARY_FILTER_PARAMS_KEY] = encodedJsonString
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

JSON 인코딩 및 DataStore 작업에 대한 오류 처리 추가 필요

JSON 인코딩이나 DataStore 쓰기 작업이 실패할 경우를 대비한 try-catch 블록 추가를 고려해보세요.

 override suspend fun updateLibraryFilter(params: LibraryFilter) {
-    val encodedJsonString = withContext(dispatcher) {
-        Json.encodeToString(
-            params.toPreferences(),
-        )
-    }
-
-    libraryFilterDataStore.edit { prefs ->
-        prefs[LIBRARY_FILTER_PARAMS_KEY] = encodedJsonString
+    try {
+        val encodedJsonString = withContext(dispatcher) {
+            Json.encodeToString(
+                params.toPreferences(),
+            )
+        }
+
+        libraryFilterDataStore.edit { prefs ->
+            prefs[LIBRARY_FILTER_PARAMS_KEY] = encodedJsonString
+        }
+    } catch (e: Exception) {
+        // 로깅 또는 에러 전파
+        throw e
     }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
override suspend fun updateLibraryFilter(params: LibraryFilter) {
val encodedJsonString = withContext(dispatcher) {
Json.encodeToString(
params.toPreferences(),
)
}
myLibraryFilterDataStore.edit { prefs ->
libraryFilterDataStore.edit { prefs ->
prefs[LIBRARY_FILTER_PARAMS_KEY] = encodedJsonString
}
}
override suspend fun updateLibraryFilter(params: LibraryFilter) {
try {
val encodedJsonString = withContext(dispatcher) {
Json.encodeToString(
params.toPreferences(),
)
}
libraryFilterDataStore.edit { prefs ->
prefs[LIBRARY_FILTER_PARAMS_KEY] = encodedJsonString
}
} catch (e: Exception) {
// 로깅 또는 에러 전파
throw e
}
}
🤖 Prompt for AI Agents
In
core/datastore/src/main/java/com/into/websoso/core/datastore/datasource/library/DefaultLibraryFilterDataSource.kt
around lines 46 to 56, the current implementation lacks error handling for JSON
encoding and DataStore editing operations. Wrap the JSON encoding and DataStore
edit calls inside a try-catch block to catch any exceptions that may occur
during these operations. In the catch block, handle or log the error
appropriately to ensure failures are managed gracefully.

Comment on lines +28 to 32
val offset = filteredNovelDao.selectNovelsCount()
filteredNovelDao.insertFilteredNovels(
novels.mapIndexed { index, novelEntity ->
novelEntity.toFilteredNovelDatabase(index)
novelEntity.toFilteredNovelDatabase(offset + index)
},
Copy link

@coderabbitai coderabbitai bot Jul 30, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

오프셋 계산과 삽입을 트랜잭션으로 묶어야 함
selectNovelsCount() 호출과 insertFilteredNovels() 사이가 분리되어 있어, 다른 코루틴이 동시에 삽입하면 중복 sortIndex가 발생할 수 있습니다. 두 동작을 하나의 Room @Transaction 블록으로 감싸거나 DAO에 “INSERT … SELECT COUNT(*) …” 형태로 일괄 처리하도록 리팩터링을 권장합니다.

🤖 Prompt for AI Agents
In
data/library/src/main/java/com/into/websoso/data/library/datasource/FilteredLibraryLocalDataSource.kt
around lines 28 to 32, the offset calculation using selectNovelsCount() and the
subsequent insertFilteredNovels() call are not atomic, risking duplicate
sortIndex if concurrent insertions occur. To fix this, wrap both operations in a
single Room @Transaction method to ensure atomicity, or refactor the DAO to
perform the insert with an SQL statement that calculates the offset internally
using INSERT ... SELECT COUNT(*) ... so that the offset and insert happen in one
atomic database operation.

Copy link
Member Author

Choose a reason for hiding this comment

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

다음 룸 최적화 이슈에서 작업 예정

Copy link

Choose a reason for hiding this comment

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

@s9hn 좋은 접근입니다! 룸 최적화 이슈에서 함께 처리하는 것이 더 효율적이겠네요. 혹시 이 이슈를 추적하기 위한 GitHub 이슈를 생성해드릴까요?

Comment on lines +151 to 159
fun searchFilteredNovels() {
viewModelScope.launch {
filterRepository.updateFilter(
readStatuses = _tempFilterUiState.value.readStatuses.mapKeys { it.key.key },
attractivePoints = _tempFilterUiState.value.attractivePoints.mapKeys { it.key.key },
novelRating = _tempFilterUiState.value.novelRating,
)
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

필터 적용 시 오류 처리 및 사용자 피드백 고려

Repository 업데이트가 실패할 경우를 대비한 오류 처리와 사용자에게 성공/실패 피드백을 제공하는 것을 고려해보세요.

 fun searchFilteredNovels() {
     viewModelScope.launch {
-        filterRepository.updateFilter(
-            readStatuses = _tempFilterUiState.value.readStatuses.mapKeys { it.key.key },
-            attractivePoints = _tempFilterUiState.value.attractivePoints.mapKeys { it.key.key },
-            novelRating = _tempFilterUiState.value.novelRating,
-        )
+        try {
+            filterRepository.updateFilter(
+                readStatuses = _tempFilterUiState.value.readStatuses.mapKeys { it.key.key },
+                attractivePoints = _tempFilterUiState.value.attractivePoints.mapKeys { it.key.key },
+                novelRating = _tempFilterUiState.value.novelRating,
+            )
+            // 성공 시 바텀시트 닫기 등의 이벤트 전송 고려
+        } catch (e: Exception) {
+            // 오류 처리 - 로깅, 사용자 알림 등
+        }
     }
 }
🤖 Prompt for AI Agents
In
feature/library/src/main/java/com/into/websoso/feature/library/LibraryViewModel.kt
around lines 151 to 159, the searchFilteredNovels function lacks error handling
and user feedback when updating the filter repository. Modify the coroutine to
catch exceptions from filterRepository.updateFilter, handle errors
appropriately, and provide user feedback on success or failure, such as updating
UI state or showing messages.

@Team-WSS Team-WSS deleted a comment from coderabbitai bot Jul 30, 2025
@s9hn s9hn merged commit f235f82 into feat/704 Jul 31, 2025
1 check passed
@m6z1 m6z1 deleted the feat/699 branch August 11, 2025 15:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚖️ 재상 세훈 전지적 세훈 시점 🍯 [FEAT] 새로운 기능을 개발합니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants