[FEAT] 검색, 모임방 메인 스크린 네비게이션 연결#60
Conversation
Walkthrough이 변경사항은 그룹(모임방) 및 검색 관련 주요 화면에 대한 네비게이션 구조를 대대적으로 확장하고, 각종 뷰모델과 데이터 구조를 리팩터링하여 동적 데이터 로딩과 화면 간 이동을 지원합니다. 또한, 알림(Alarm) 화면과 관련 네비게이션이 추가되고, 최근 검색어의 영속화, 데이터 클래스의 ID 필드 추가, Gradle 및 라이브러리 버전 조정이 포함됩니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant GroupScreen
participant NavController
participant GroupViewModel
participant GroupRepository
User->>GroupScreen: 버튼 클릭 (예: 완료된 모임방)
GroupScreen->>NavController: onNavigateToGroupDone()
NavController->>GroupDoneScreen: 화면 이동
GroupDoneScreen->>GroupViewModel: doneGroups 상태 구독
GroupViewModel->>GroupRepository: getDoneGroups() suspend 호출
GroupRepository-->>GroupViewModel: 데이터 반환
GroupViewModel-->>GroupDoneScreen: StateFlow로 데이터 전달
GroupDoneScreen-->>User: UI 렌더링
sequenceDiagram
participant User
participant GroupSearchScreen
participant SharedPreferences
User->>GroupSearchScreen: 검색어 입력 후 검색
GroupSearchScreen->>SharedPreferences: 최근 검색어 저장 (JSON 직렬화)
SharedPreferences-->>GroupSearchScreen: 저장 성공/실패
GroupSearchScreen-->>User: UI 갱신
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Possibly related PRs
Suggested reviewers
Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
✨ Finishing Touches🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (5)
app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt (1)
112-116: Preview의 하드코딩된 문자열을 StringResource로 추출하는 것을 고려해보세요.Preview 함수에서 "피드", "모임", "내 글을 좋아합니다" 등의 하드코딩된 한국어 문자열들이 사용되고 있습니다. 유지보수성과 다국어 지원을 위해 이들을
strings.xml로 추출하는 것을 고려해보세요.AlarmItem(1, "피드", "내 글을 좋아합니다.", "user123님이 내 글에 좋아요를 눌렀어요.", "2", false), AlarmItem(2, "모임", "같이 읽기를 시작했어요!", "모임방에서 20분 동안 같이 읽기가 시작되었어요!", "7", false),이런 문자열들을 StringResource로 추출할 수 있습니다.
app/src/main/java/com/texthip/thip/ui/common/alarmpage/viewmodel/AlarmViewModel.kt (2)
14-21: 하드코딩된 문자열을 StringResource로 추출하는 것을 고려해보세요.모크 데이터의 한국어 문자열들("피드", "모임", "내 글을 좋아합니다" 등)이 하드코딩되어 있습니다. 유지보수성과 다국어 지원을 위해
strings.xml로 추출하는 것을 권장합니다.예시:
AlarmItem(1, context.getString(R.string.alarm_feed), context.getString(R.string.alarm_like_title), ...)
24-26: TODO 구현 지원을 제공할 수 있습니다.알림 카드 클릭 처리가 아직 구현되지 않았습니다. 이 기능 구현에 도움이 필요하시면 알려주세요.
일반적으로 알림 카드 클릭 시 해당 알림을 읽음 상태로 변경하고 관련 화면으로 네비게이션하는 로직이 필요할 것입니다.
app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt (1)
158-158: 사용자 상태에 따른 버튼 타입 결정 로직이 필요합니다.현재
GroupBottomButtonType.JOIN이 하드코딩되어 있습니다. 주석에 따르면 실제로는 사용자 상태에 따라 결정되어야 합니다.ViewModel에서 사용자의 참여 상태를 확인하는 로직을 추가하시겠습니까?
app/src/main/java/com/texthip/thip/ui/group/viewmodel/GroupViewModel.kt (1)
95-117: 목 데이터를 별도의 클래스로 분리하는 것을 고려해보세요.현재 ViewModel의 init 블록에 많은 양의 목 데이터가 하드코딩되어 있습니다. 이를 별도의 MockDataProvider나 Repository로 분리하면 테스트와 유지보수가 더 쉬워집니다.
다음과 같은 구조를 제안합니다:
// GroupMockDataProvider.kt object GroupMockDataProvider { fun getDoneGroups(): List<GroupCardItemRoomData> = listOf(...) fun getMyRoomGroups(): List<GroupCardItemRoomData> = listOf(...) fun getSearchGroups(): List<GroupCardItemRoomData> = listOf(...) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (24)
app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt(2 hunks)app/src/main/java/com/texthip/thip/ui/common/alarmpage/viewmodel/AlarmViewModel.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/common/forms/SearchBookTextField.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupDeadlineRoomSection.kt(12 hunks)app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupSearchTextField.kt(3 hunks)app/src/main/java/com/texthip/thip/ui/group/myroom/mock/GroupCardItemRoomData.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/group/myroom/mock/GroupRoomData.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/group/myroom/screen/GroupMyScreen.kt(14 hunks)app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomRecruitScreen.kt(14 hunks)app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt(2 hunks)app/src/main/java/com/texthip/thip/ui/group/screen/GroupDoneScreen.kt(3 hunks)app/src/main/java/com/texthip/thip/ui/group/screen/GroupScreen.kt(3 hunks)app/src/main/java/com/texthip/thip/ui/group/search/component/GroupFilteredSearchResult.kt(4 hunks)app/src/main/java/com/texthip/thip/ui/group/search/component/GroupLiveSearchResult.kt(5 hunks)app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt(8 hunks)app/src/main/java/com/texthip/thip/ui/group/viewmodel/GroupViewModel.kt(4 hunks)app/src/main/java/com/texthip/thip/ui/navigator/MainNavHost.kt(2 hunks)app/src/main/java/com/texthip/thip/ui/navigator/extensions/GroupNavigationExtensions.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/navigator/navigations/CommonNavigation.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt(3 hunks)app/src/main/java/com/texthip/thip/ui/navigator/routes/CommonRoutes.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/navigator/routes/GroupRoutes.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookGroupScreen.kt(8 hunks)app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookScreen.kt(4 hunks)
🧰 Additional context used
🧠 Learnings (10)
📓 Common learnings
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
app/src/main/java/com/texthip/thip/ui/common/forms/SearchBookTextField.kt (1)
Learnt from: rbqks529
PR: #30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
app/src/main/java/com/texthip/thip/ui/common/alarmpage/viewmodel/AlarmViewModel.kt (1)
Learnt from: rbqks529
PR: #30
File: app/src/main/java/com/texthip/thip/ui/myPage/groupPage/GroupPageScreen.kt:34-37
Timestamp: 2025-07-01T07:19:01.239Z
Learning: GroupPageScreen의 MyPageViewModel은 임시 ViewModel로, 현재는 프로토타입 단계이므로 오류 처리 등의 추가 기능은 나중에 구현 예정입니다.
app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupSearchTextField.kt (1)
Learnt from: rbqks529
PR: #30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt (1)
Learnt from: rbqks529
PR: #30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookScreen.kt (1)
Learnt from: rbqks529
PR: #30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt (1)
Learnt from: rbqks529
PR: #30
File: app/src/main/java/com/texthip/thip/ui/myPage/groupPage/GroupPageScreen.kt:34-37
Timestamp: 2025-07-01T07:19:01.239Z
Learning: GroupPageScreen의 MyPageViewModel은 임시 ViewModel로, 현재는 프로토타입 단계이므로 오류 처리 등의 추가 기능은 나중에 구현 예정입니다.
app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt (1)
Learnt from: rbqks529
PR: #30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
app/src/main/java/com/texthip/thip/ui/group/screen/GroupScreen.kt (1)
Learnt from: rbqks529
PR: #30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
app/src/main/java/com/texthip/thip/ui/group/screen/GroupDoneScreen.kt (1)
Learnt from: rbqks529
PR: #30
File: app/src/main/java/com/texthip/thip/ui/myPage/groupPage/GroupPageScreen.kt:34-37
Timestamp: 2025-07-01T07:19:01.239Z
Learning: GroupPageScreen의 MyPageViewModel은 임시 ViewModel로, 현재는 프로토타입 단계이므로 오류 처리 등의 추가 기능은 나중에 구현 예정입니다.
🧬 Code Graph Analysis (6)
app/src/main/java/com/texthip/thip/ui/navigator/MainNavHost.kt (1)
app/src/main/java/com/texthip/thip/ui/navigator/navigations/CommonNavigation.kt (1)
commonNavigation(15-29)
app/src/main/java/com/texthip/thip/ui/navigator/navigations/CommonNavigation.kt (1)
app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt (1)
AlarmScreen(32-103)
app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookScreen.kt (1)
app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt (1)
saveRecentSearches(60-65)
app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt (1)
app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookScreen.kt (1)
saveRecentSearches(58-63)
app/src/main/java/com/texthip/thip/ui/group/screen/GroupScreen.kt (2)
app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupSearchTextField.kt (1)
GroupSearchTextField(27-68)app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupMySectionHeader.kt (1)
GroupMySectionHeader(21-44)
app/src/main/java/com/texthip/thip/ui/group/screen/GroupDoneScreen.kt (1)
app/src/main/java/com/texthip/thip/ui/theme/Theme.kt (1)
ThipTheme(41-69)
🔇 Additional comments (46)
app/src/main/java/com/texthip/thip/ui/common/forms/SearchBookTextField.kt (1)
56-56: 배경색 변경이 적절합니다.
DarkGrey02에서DarkGrey로의 배경색 변경이 디자인 시스템과 일관성을 유지합니다.app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookGroupScreen.kt (1)
148-218: 프리뷰 데이터에 ID 필드 추가가 일관성 있게 적용되었습니다.각
GroupCardItemRoomData인스턴스에 순차적이고 고유한 ID 값(1-8)이 올바르게 할당되었습니다. 이는 데이터 클래스 변경사항과 일치합니다.app/src/main/java/com/texthip/thip/ui/group/myroom/mock/GroupRoomData.kt (1)
4-4: 데이터 클래스에 ID 필드 추가가 적절합니다.고유 식별을 위한
id필드 추가는 네비게이션과 상태 관리를 위한 좋은 개선사항입니다. 첫 번째 매개변수로 배치된 것도 적절합니다.app/src/main/java/com/texthip/thip/ui/group/myroom/mock/GroupCardItemRoomData.kt (1)
6-6: 일관성 있는 ID 필드 추가입니다.
GroupRoomData와 동일한 패턴으로 ID 필드가 추가되어 데이터 모델 간 일관성이 유지됩니다. 네비게이션 구현에 필요한 변경사항입니다.app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupDeadlineRoomSection.kt (2)
192-298: 프리뷰 데이터의 ID 필드 업데이트가 체계적으로 완료되었습니다.모든
GroupCardItemRoomData인스턴스에 순차적이고 고유한 ID가 할당되었습니다. 마감 임박(1-5), 인기(6-8), 인플루언서(9-11) 카테고리별로 논리적으로 구분된 ID 범위가 적절합니다.
334-334: 빈 장르 프리뷰의 ID 할당이 적절합니다.다른 프리뷰 데이터와 중복되지 않는 고유한 ID(12)가 할당되어 일관성이 유지됩니다.
app/src/main/java/com/texthip/thip/ui/navigator/MainNavHost.kt (1)
11-11: 네비게이션 통합이 올바르게 구현되었습니다.
commonNavigation임포트와 함수 호출이 기존 패턴과 일관성 있게 추가되어 알림 기능이 메인 네비게이션 그래프에 적절히 통합되었습니다.Also applies to: 21-21
app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt (1)
42-44: 뒤로가기 네비게이션 콜백이 적절히 추가되었습니다.하드코딩된 빈 람다를 구성 가능한
onBackClick매개변수로 교체하여 외부에서 뒤로가기 동작을 제어할 수 있게 되었습니다. 기본값을 제공하여 하위 호환성도 유지됩니다.Also applies to: 103-103
app/src/main/java/com/texthip/thip/ui/navigator/routes/CommonRoutes.kt (1)
1-9: 공통 라우트 정의가 깔끔하게 구현되었습니다.
CommonRoutessealed class가 적절한 직렬화 어노테이션과 함께 올바르게 정의되었으며,Alarm라우트가 명확하게 선언되었습니다. 네비게이션 패턴과 일관성을 유지합니다.app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt (1)
34-36: 네비게이션 콜백과 매개변수가 적절히 추가되었습니다.
onNavigateBack콜백이 추가되어 외부에서 뒤로가기 동작을 제어할 수 있게 되었고,alarmItems와onCardClick매개변수로 데이터와 이벤트 처리를 외부에서 관리할 수 있습니다.Also applies to: 53-53
app/src/main/java/com/texthip/thip/ui/common/alarmpage/viewmodel/AlarmViewModel.kt (1)
9-12: StateFlow 패턴이 올바르게 구현되었습니다.private mutable StateFlow와 public immutable StateFlow를 적절히 사용하여 반응형 UI 업데이트를 지원하는 좋은 패턴입니다.
app/src/main/java/com/texthip/thip/ui/group/search/component/GroupLiveSearchResult.kt (3)
24-25: 네비게이션 콜백 추가가 적절합니다.
onRoomClick콜백 파라미터 추가로 룸 카드 클릭 시 외부에서 네비게이션을 처리할 수 있게 되었습니다. 기본값으로 빈 람다를 제공하여 선택적 사용이 가능하도록 구현되었습니다.
36-37:isSecret속성과 클릭 콜백 연결이 올바릅니다.
CardItemRoomSmall컴포넌트에isSecret속성이 추가되고,onClick콜백이 외부onRoomClick함수와 연결되어 있습니다. 룸 데이터가 올바르게 전달되고 있습니다.
63-85: 프리뷰 데이터에 ID 추가가 일관성 있게 처리되었습니다.각
GroupCardItemRoomData인스턴스에 고유한id값(1, 2, 3)이 추가되어 데이터 식별이 가능해졌습니다. 이는 다른 그룹 관련 컴포넌트들과 일관성을 유지하는 변경사항입니다.app/src/main/java/com/texthip/thip/ui/navigator/navigations/CommonNavigation.kt (1)
15-29: 네비게이션 그래프 구현이 잘 구조화되어 있습니다.
commonNavigation함수가 Jetpack Compose Navigation 패턴을 올바르게 따르고 있습니다:
AlarmViewModel을 통한 적절한 상태 관리collectAsState()를 사용한 반응형 상태 수집- 네비게이션 콜백 처리가 명확하게 분리됨
MVVM 패턴이 잘 적용되어 있고, 의존성 분리도 적절합니다.
app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookScreen.kt (4)
45-55: SharedPreferences를 통한 검색어 영속화가 올바르게 구현되었습니다.
SharedPreferences를 사용하여 최근 검색어를 영구 저장하는 방식이 적절합니다:
- Context를 통한 SharedPreferences 인스턴스 생성
- 앱 재시작 시에도 검색어가 유지되도록 구현
remember를 사용하여 컴포지션 간 상태 유지GroupSearchScreen과 일관된 패턴을 따르고 있어 코드베이스 전반의 일관성을 유지합니다.
58-63: 검색어 저장 함수가 효율적으로 구현되었습니다.
saveRecentSearches함수가 다음과 같이 올바르게 구현되었습니다:
apply()를 사용한 비동기 저장으로 UI 블로킹 방지- 로컬 상태와 저장소 동기화
- 함수 시그니처가 GroupSearchScreen과 일치하여 일관성 유지
128-129: 최근 검색어 관리 로직이 효율적입니다.새로운 검색어를 목록 앞에 추가하고 최대 9개까지만 유지하여 총 10개로 제한하는 로직이 적절합니다. 중복 검색어 방지도 잘 구현되어 있습니다.
147-149: 검색어 삭제 처리가 올바릅니다.
filterNot을 사용하여 특정 검색어를 제거하고saveRecentSearches를 호출하여 상태와 저장소를 동기화하는 방식이 적절합니다.app/src/main/java/com/texthip/thip/ui/group/screen/GroupDoneScreen.kt (3)
30-32: 네비게이션 콜백 파라미터 추가가 적절합니다.
onCardClick과onNavigateBack콜백을 추가하여 외부에서 네비게이션을 제어할 수 있도록 개선되었습니다. 기본값으로 빈 람다를 제공하여 선택적 사용이 가능합니다.
43-43: TopAppBar 네비게이션 연결이 올바릅니다.
DefaultTopAppBar의onLeftClick에onNavigateBack콜백이 정확히 연결되어 뒤로가기 기능이 외부에서 처리될 수 있습니다.
91-131: 프리뷰 데이터 ID 추가가 일관성 있게 처리되었습니다.모든
GroupCardItemRoomData인스턴스에 고유한id값(1-6)이 추가되어 데이터 식별과 관리가 개선되었습니다. 다른 그룹 관련 컴포넌트들과 일관된 패턴을 따르고 있습니다.app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomRecruitScreen.kt (3)
439-475: JOIN 프리뷰의 ID 추가가 적절합니다.각
GroupCardItemRoomData추천 항목에 고유한id값(1-5)이 추가되고, 메인GroupRoomData에도id: 1이 할당되었습니다. 데이터 식별과 네비게이션 지원이 개선되었습니다.Also applies to: 494-494
526-544: CANCEL 프리뷰의 ID 추가가 일관성 있게 처리되었습니다.추천 항목들에 고유한
id값(6-8)이 할당되고, 메인 데이터에는id: 2가 할당되어 JOIN 프리뷰와 중복되지 않도록 구현되었습니다.Also applies to: 563-563
595-613: CLOSE 프리뷰의 ID 추가가 올바릅니다.추천 항목들에 고유한
id값(9-11)이 할당되고, 메인 데이터에는id: 3이 할당되어 전체 프리뷰 함수들 간의 ID 충돌이 방지되었습니다.Also applies to: 632-632
app/src/main/java/com/texthip/thip/ui/group/search/component/GroupFilteredSearchResult.kt (3)
39-40: 네비게이션 콜백 패턴이 잘 구현되었습니다.
onRoomClick매개변수가 적절히 추가되어 외부에서 룸 클릭 이벤트를 처리할 수 있도록 하였고, 기본값으로 빈 람다를 제공하여 하위 호환성을 유지했습니다.
83-84: 클릭 이벤트 연결이 올바르게 구현되었습니다.
CardItemRoomSmall의onClick에onRoomClick(room)을 전달하여 룸 데이터와 함께 콜백을 호출하는 구조가 적절합니다.
118-128: 프리뷰 데이터에 ID가 명시적으로 추가되었습니다.데이터 모델 변경에 맞춰
GroupCardItemRoomData에id속성이 명시적으로 설정되어 일관성이 유지되었습니다.app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupSearchTextField.kt (2)
28-31: 컴포넌트 역할이 네비게이션 트리거로 명확하게 변경되었습니다.편집 가능한 텍스트 필드에서 클릭 가능한 검색 트리거로 변경된 것이 적절합니다. 실제 검색 기능은 전용 검색 화면에서 처리하는 아키텍처가 더 명확합니다.
36-67: UI 구현이 간결하고 명확합니다.정적 플레이스홀더 텍스트와 검색 아이콘을 클릭 가능한
Box로 구성한 것이 사용자 경험 측면에서 직관적입니다.app/src/main/java/com/texthip/thip/ui/navigator/extensions/GroupNavigationExtensions.kt (3)
6-6: CommonRoutes 임포트가 적절히 추가되었습니다.알람 기능을 위한
CommonRoutes임포트가 모듈 간 통합을 잘 보여줍니다.
18-32: 새로운 네비게이션 확장 함수들이 일관된 패턴으로 구현되었습니다.
navigateToGroupDone,navigateToGroupSearch,navigateToGroupMy,navigateToAlarm함수들이 기존 패턴과 일치하며 명명 규칙이 명확합니다.
34-40: 매개변수가 있는 네비게이션 함수가 적절히 구현되었습니다.
roomId매개변수를 받는navigateToGroupRecruit와navigateToGroupRoom함수가 특정 룸으로의 네비게이션을 위해 잘 설계되었습니다.app/src/main/java/com/texthip/thip/ui/group/myroom/screen/GroupMyScreen.kt (3)
36-37: 네비게이션 콜백이 적절히 추가되었습니다.
onNavigateBack매개변수 추가로 외부에서 뒤로가기 동작을 제어할 수 있게 되어 네비게이션 아키텍처가 일관성을 갖습니다.
53-66: UI 레이아웃이 개선되었습니다.배경색과
fillMaxSize모디파이어 추가로 화면 전체를 적절히 채우며, 일관된 스타일링이 적용되었습니다.
129-235: 프리뷰 데이터의 ID가 명시적으로 설정되었습니다.모든
GroupCardItemRoomData인스턴스에 고유한 ID(1-12)가 할당되어 데이터 모델 변경사항과 일치합니다.app/src/main/java/com/texthip/thip/ui/navigator/routes/GroupRoutes.kt (1)
10-23: 새로운 라우트 정의가 잘 구조화되었습니다.매개변수가 없는 라우트는
data object로, 매개변수가 있는 라우트는data class로 적절히 구분하여 정의했습니다.roomId: Int매개변수를 통한 특정 룸 네비게이션 지원이 적절합니다.app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt (3)
47-57: SharedPreferences 초기화가 적절합니다!
remember를 사용하여 SharedPreferences 인스턴스를 한 번만 생성하도록 한 점이 좋습니다. MODE_PRIVATE 사용도 보안상 적절합니다.
149-152: 최근 검색어 관리 로직이 잘 구현되었습니다!중복 검사, 최대 10개 유지, 새 검색어를 앞에 추가하는 로직이 모두 적절합니다.
233-239: 프리뷰 데이터가 올바르게 업데이트되었습니다!새로운 ID 필드가 모든 GroupCardItemRoomData 인스턴스에 추가되어 데이터 모델 변경사항과 일치합니다.
app/src/main/java/com/texthip/thip/ui/group/screen/GroupScreen.kt (2)
36-41: 네비게이션 콜백 구조가 잘 설계되었습니다!각 화면으로의 네비게이션이 명확하게 분리되어 있고, roomId 파라미터가 필요한 화면들은 적절히 처리되었습니다.
95-101: ViewModel과 UI의 책임 분리가 잘 되어있습니다!ViewModel이 모임방 상태에 따른 네비게이션 로직을 처리하고, UI는 실제 네비게이션 액션만 제공하는 구조가 좋습니다.
app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt (2)
39-56: GroupScreen 네비게이션 연결이 완벽합니다!모든 네비게이션 콜백이 올바른 확장 함수와 연결되어 있고, 파라미터 전달도 정확합니다.
175-178: 적절한 에러 처리입니다!모임방 데이터를 찾을 수 없는 경우 즉시 뒤로 이동하는 방어적 프로그래밍이 잘 적용되었습니다.
app/src/main/java/com/texthip/thip/ui/group/viewmodel/GroupViewModel.kt (2)
21-22: 임시 유저 이름을 실제 사용자 데이터로 교체해야 합니다.현재 하드코딩된 "규빈"은 실제 사용자 인증 정보나 프로필에서 가져와야 합니다.
사용자 정보를 관리하는 UserRepository나 AuthService가 이미 구현되어 있는지 확인이 필요합니다.
124-135: 모임방 클릭 네비게이션 로직이 깔끔합니다!
isRecruiting플래그에 따라 적절한 화면으로 네비게이션하는 로직이 명확하게 구현되었습니다.
app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
app/src/main/java/com/texthip/thip/ui/group/viewmodel/GroupViewModel.kt (1)
142-169: 모임방 상세 데이터 초기화 메서드 구현 양호기본 모임방 데이터를 상세 데이터로 변환하는 로직이 잘 구현되어 있습니다. 현재는 더미 책 데이터를 사용하고 있지만, 프로토타입 단계에서는 적절합니다.
추후 실제 책 데이터로 교체 시 고려사항:
-val bookData = GroupBookData( - title = "심장보다 단단한 토마토 한 알", - author = "고선지", - publisher = "푸른출판사", - description = "${room.title}에서 읽는 책입니다. 감동적인 이야기로 가득한 작품입니다.", - imageRes = room.imageRes ?: R.drawable.bookcover_sample -) +val bookData = repository.getBookDataForRoom(room.id) ?: getDefaultBookData()app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt (1)
137-187: 매개변수가 있는 목적지 화면들의 구현 우수roomId 매개변수 추출과 데이터 유효성 검사, 그리고 데이터가 없을 경우 즉시 뒤로 이동하는 오류 처리 패턴이 잘 구현되었습니다.
오류 처리를 더 명확하게 하려면 로깅 추가를 고려해볼 수 있습니다:
} else { + // Log.w("GroupNavigation", "Room data not found for ID: $roomId") // 데이터를 찾을 수 없는 경우 바로 뒤로 이동 navController.navigateBack() }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
app/src/main/java/com/texthip/thip/ui/group/myroom/mock/GroupCardData.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/group/screen/GroupDoneScreen.kt(4 hunks)app/src/main/java/com/texthip/thip/ui/group/screen/GroupScreen.kt(3 hunks)app/src/main/java/com/texthip/thip/ui/group/viewmodel/GroupViewModel.kt(3 hunks)app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt(3 hunks)
✅ Files skipped from review due to trivial changes (1)
- app/src/main/java/com/texthip/thip/ui/group/myroom/mock/GroupCardData.kt
🚧 Files skipped from review as they are similar to previous changes (2)
- app/src/main/java/com/texthip/thip/ui/group/screen/GroupScreen.kt
- app/src/main/java/com/texthip/thip/ui/group/screen/GroupDoneScreen.kt
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt (1)
Learnt from: rbqks529
PR: #30
File: app/src/main/java/com/texthip/thip/ui/myPage/groupPage/GroupPageScreen.kt:34-37
Timestamp: 2025-07-01T07:19:01.239Z
Learning: GroupPageScreen의 MyPageViewModel은 임시 ViewModel로, 현재는 프로토타입 단계이므로 오류 처리 등의 추가 기능은 나중에 구현 예정입니다.
🔇 Additional comments (10)
app/src/main/java/com/texthip/thip/ui/group/viewmodel/GroupViewModel.kt (6)
8-9: 새로운 데이터 모델 import 추가 확인됨GroupRoomData와 GroupBookData import가 추가되어 상세 모임방 데이터 관리 기능을 지원합니다.
24-31: 새로운 StateFlow 속성들이 올바르게 구현됨완료된 모임방, 내 모임방, 검색용 모임방을 위한 StateFlow들이 적절한 패턴으로 구현되었습니다.
36-37: ID 기반 모임방 데이터 조회를 위한 맵 추가모임방 상세 정보를 ID로 빠르게 조회할 수 있는 맵이 적절히 추가되었습니다.
42-117: 데이터 초기화 구조 개선됨모든 모임방 데이터에 명시적 ID가 추가되고, 다양한 화면 타입별로 데이터가 체계적으로 구성되었습니다. 검색용 데이터를 기존 리스트들을 조합하여 생성하는 방식도 효율적입니다.
120-139: 네비게이션 콜백 패턴이 올바르게 구현됨ViewModel이 비즈니스 로직(모집 상태에 따른 네비게이션 분기)을 처리하고, 실제 네비게이션은 호출자에게 위임하는 좋은 관심사 분리가 구현되었습니다.
172-179: 추천 로직 및 상세 정보 조회 메서드 구현 적절간단하지만 효과적인 추천 로직과 명확한 상세 정보 조회 메서드가 구현되었습니다. 프로토타입 단계에서 필요한 기능을 잘 제공합니다.
app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt (4)
7-29: 네비게이션 확장을 위한 import 추가 확인됨새로운 화면들과 네비게이션 기능을 지원하기 위한 필요한 import들이 적절히 추가되었습니다.
35-57: GroupScreen 네비게이션 콜백 패턴 잘 구현됨각 화면으로의 네비게이션을 위한 콜백들이 명확하게 정의되고, 일관된 패턴으로 구현되었습니다. UI와 네비게이션 로직의 분리가 적절합니다.
74-135: 단순 목적지 화면들이 일관된 패턴으로 구현됨GroupDone, GroupMy, GroupSearch 화면들이 ViewModel 생성, 상태 수집, 네비게이션 콜백 연결의 일관된 패턴으로 잘 구현되었습니다.
177-182: 잘못된 리뷰 지적: GroupRoomScreen에 roomDetail 매개변수 없음현재 GroupRoomScreen 함수( app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt:42 ) 시그니처에는 onBackClick만 정의되어 있어, roomDetail을 전달할 수 없습니다.
- 함수 정의
fun GroupRoomScreen( onBackClick: () -> Unit = {} ) { … }- 호출부
if (roomDetail != null) { GroupRoomScreen( onBackClick = { navController.navigateBack() } ) }roomDetail 데이터를 화면에 사용해야 한다면 GroupRoomScreen 함수 시그니처를 roomDetail: RoomDetail 같은 형태로 확장해주세요.
그렇지 않다면 이 코멘트는 무시해주시면 됩니다.Likely an incorrect or invalid review comment.
| private val _userName = MutableStateFlow("규빈") // 임시 유저 이름 | ||
| val userName: StateFlow<String> = _userName |
There was a problem hiding this comment.
🛠️ Refactor suggestion
하드코딩된 사용자명 개선 필요
임시로 하드코딩된 사용자명이 있습니다. 추후 실제 사용자 데이터로 교체가 필요합니다.
-private val _userName = MutableStateFlow("규빈") // 임시 유저 이름
+private val _userName = MutableStateFlow("") // Repository에서 실제 사용자명 로드 예정📝 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.
| private val _userName = MutableStateFlow("규빈") // 임시 유저 이름 | |
| val userName: StateFlow<String> = _userName | |
| private val _userName = MutableStateFlow("") // Repository에서 실제 사용자명 로드 예정 | |
| val userName: StateFlow<String> = _userName |
🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/ui/group/viewmodel/GroupViewModel.kt at
lines 21-22, the userName is currently hardcoded as a temporary value. Replace
this hardcoded string with a mechanism to fetch or receive the actual user name
from the user data source or repository to ensure dynamic and accurate user
information.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt (2)
48-62: JSON 직렬화 방식으로 순서 보존 문제를 해결했습니다.이전 리뷰에서 지적된 Set 변환으로 인한 순서 손실 문제가 JSON 직렬화를 통해 올바르게 해결되었습니다. 하지만 예외 처리 시 로깅을 추가하면 디버깅에 도움이 될 것입니다.
예외 로깅을 추가하는 것을 고려해보세요:
} catch (e: Exception) { + android.util.Log.w("GroupSearchScreen", "Failed to load recent searches", e) emptyList() }
64-74: 일관된 저장 패턴을 사용하고 있습니다.SearchBookScreen.kt와 동일한 JSON 직렬화 패턴을 사용하여 코드베이스 전반의 일관성을 유지하고 있습니다. 다만 예외 처리 시 로깅을 추가하면 좋겠습니다.
예외 로깅을 추가하는 것을 고려해보세요:
} catch (e: Exception) { + android.util.Log.w("GroupSearchScreen", "Failed to save recent searches", e) recentSearches = emptyList() }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt(9 hunks)app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookScreen.kt(5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookScreen.kt
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt (1)
Learnt from: rbqks529
PR: #30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
🧬 Code Graph Analysis (1)
app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt (1)
app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookScreen.kt (1)
saveRecentSearches(62-72)
🪛 detekt (1.23.8)
app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt
[warning] 56-56: The caught exception is swallowed. The original exception could be lost.
(detekt.exceptions.SwallowedException)
[warning] 69-69: The caught exception is swallowed. The original exception could be lost.
(detekt.exceptions.SwallowedException)
🔇 Additional comments (6)
app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt (6)
3-3: 필요한 의존성 추가가 적절합니다.SharedPreferences 및 JSON 직렬화를 위한 필수 import들이 올바르게 추가되었습니다.
Also applies to: 24-24, 39-39
44-46: 네비게이션 콜백 추가가 적절합니다.화면 간 네비게이션과 방 아이템 상호작용을 위한 콜백 매개변수들이 올바르게 추가되어 전체 네비게이션 프레임워크와 일치합니다.
159-162: 검색어 관리 로직이 올바르게 구현되었습니다.새 검색어 추가 시 중복 방지, 최대 10개 제한, 그리고 검색어 삭제 시 목록 업데이트가 모두 적절하게 처리되고 있습니다.
Also applies to: 186-188
139-139: 뒤로가기 네비게이션이 올바르게 연결되었습니다.이전의 빈 람다 대신 onNavigateBack 콜백을 사용하여 적절한 뒤로가기 기능을 제공합니다.
200-202: 하위 컴포넌트에 방 클릭 콜백이 올바르게 전달되었습니다.GroupLiveSearchResult와 GroupFilteredSearchResult 컴포넌트에 onRoomClick 콜백을 전달하여 방 아이템 클릭 시 적절한 네비게이션이 가능합니다.
Also applies to: 213-213
242-248: 프리뷰 데이터가 새 데이터 모델에 맞게 업데이트되었습니다.GroupCardItemRoomData에 추가된 id 매개변수가 모든 프리뷰 인스턴스에 올바르게 포함되어 데이터 모델 변경사항과 일치합니다.
There was a problem hiding this comment.
ViewModel 데이터는 다 화면 이동시 UI를 보여주려고 임시로 넣어뒀습니다
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt (1)
200-229: 로딩 상태와 에러 처리 개선이 필요합니다데이터 로딩 중 빈 화면이 표시되고 에러 처리가 없습니다. 사용자 경험 개선을 위해 로딩 인디케이터와 에러 처리를 추가해주세요.
roomDetail?.let { detail -> GroupRoomRecruitScreen( // ... existing parameters ) } ?: run { - // 로딩 중이거나 데이터를 찾을 수 없는 경우 + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } }또한 에러 처리를 위해 다음과 같은 개선을 고려해주세요:
var roomDetail by remember { mutableStateOf<GroupRoomData?>(null) } var isLoading by remember { mutableStateOf(true) } var error by remember { mutableStateOf<String?>(null) } LaunchedEffect(roomId) { isLoading = true try { roomDetail = groupViewModel.getRoomDetail(roomId) if (roomDetail == null) { error = "방을 찾을 수 없습니다" } } catch (e: Exception) { error = "데이터를 불러오는 중 오류가 발생했습니다" } finally { isLoading = false } }Also applies to: 248-263
🧹 Nitpick comments (4)
app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookScreen.kt (2)
54-63: 예외 처리 시 로그를 남기는 것이 좋습니다JSON 디코딩 실패 시 예외가 조용히 무시되고 있습니다. 개발 중에는 문제 파악을 위해 로그를 남기는 것이 좋습니다.
var recentSearches by remember { mutableStateOf( try { val jsonString = sharedPrefs.getString("recent_book_searches", "[]") ?: "[]" Json.decodeFromString<List<String>>(jsonString) } catch (e: Exception) { + // 디버깅을 위한 로그 추가 + Log.w("SearchBookScreen", "Failed to decode recent searches", e) emptyList() } ) }
65-75: 저장 실패 시에도 로그를 남기는 것이 좋습니다검색어 저장 실패 시 예외가 조용히 무시되고 있습니다. 사용자 경험 개선을 위해 로그를 남기는 것이 좋습니다.
fun saveRecentSearches(searches: List<String>) { try { val jsonString = Json.encodeToString(ListSerializer(String.serializer()), searches) sharedPrefs.edit { putString("recent_book_searches", jsonString) } recentSearches = searches } catch (e: Exception) { + Log.e("SearchBookScreen", "Failed to save recent searches", e) recentSearches = emptyList() } }app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt (1)
56-65: 예외 처리 시 로그를 남기는 것이 좋습니다JSON 처리 실패 시 예외가 조용히 무시되고 있습니다. 개발 및 디버깅을 위해 로그를 남기는 것이 좋습니다.
var recentSearches by remember { mutableStateOf( try { val jsonString = sharedPrefs.getString("recent_searches", "[]") ?: "[]" Json.decodeFromString<List<String>>(jsonString) } catch (e: Exception) { + Log.w("GroupSearchScreen", "Failed to decode recent searches", e) emptyList() } ) } fun saveRecentSearches(searches: List<String>) { try { val jsonString = Json.encodeToString(ListSerializer(String.serializer()), searches) sharedPrefs.edit { putString("recent_searches", jsonString) } recentSearches = searches } catch (e: Exception) { + Log.e("GroupSearchScreen", "Failed to save recent searches", e) recentSearches = emptyList() } }Also applies to: 67-77
app/src/main/java/com/texthip/thip/ui/group/data/repository/GroupRepositoryImpl.kt (1)
16-16: 하드코딩된 문자열을 상수나 리소스로 관리하는 것이 좋습니다장르 목록이 하드코딩되어 있습니다. 유지보수와 현지화를 위해 상수나 enum으로 관리하는 것을 고려해보세요.
-private val genres = listOf("문학", "과학·IT", "사회과학", "인문학", "예술") +companion object { + private val GENRE_LITERATURE = "문학" + private val GENRE_SCIENCE_IT = "과학·IT" + private val GENRE_SOCIAL_SCIENCE = "사회과학" + private val GENRE_HUMANITIES = "인문학" + private val GENRE_ART = "예술" + + private val genres = listOf( + GENRE_LITERATURE, + GENRE_SCIENCE_IT, + GENRE_SOCIAL_SCIENCE, + GENRE_HUMANITIES, + GENRE_ART + ) +}또는 enum class를 사용하는 방법도 있습니다:
enum class Genre(val displayName: String) { LITERATURE("문학"), SCIENCE_IT("과학·IT"), SOCIAL_SCIENCE("사회과학"), HUMANITIES("인문학"), ART("예술") }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
app/src/main/java/com/texthip/thip/ui/group/data/repository/GroupRepositoryImpl.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt(9 hunks)app/src/main/java/com/texthip/thip/ui/navigator/extensions/CommonNavigationExtensions.kt(2 hunks)app/src/main/java/com/texthip/thip/ui/navigator/extensions/GroupNavigationExtensions.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt(2 hunks)app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookScreen.kt(5 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- app/src/main/java/com/texthip/thip/ui/navigator/extensions/CommonNavigationExtensions.kt
- app/src/main/java/com/texthip/thip/ui/navigator/extensions/GroupNavigationExtensions.kt
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt (1)
Learnt from: rbqks529
PR: #30
File: app/src/main/java/com/texthip/thip/ui/myPage/groupPage/GroupPageScreen.kt:34-37
Timestamp: 2025-07-01T07:19:01.239Z
Learning: GroupPageScreen의 MyPageViewModel은 임시 ViewModel로, 현재는 프로토타입 단계이므로 오류 처리 등의 추가 기능은 나중에 구현 예정입니다.
app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt (1)
Learnt from: rbqks529
PR: #30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookScreen.kt (1)
Learnt from: rbqks529
PR: #30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
🧬 Code Graph Analysis (3)
app/src/main/java/com/texthip/thip/ui/group/data/repository/GroupRepositoryImpl.kt (1)
app/src/main/java/com/texthip/thip/ui/group/data/repository/GroupRepository.kt (2)
getRoomSections(18-18)getSearchGroups(27-27)
app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt (1)
app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookScreen.kt (1)
saveRecentSearches(65-75)
app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookScreen.kt (1)
app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt (1)
saveRecentSearches(67-77)
🪛 detekt (1.23.8)
app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt
[warning] 61-61: The caught exception is swallowed. The original exception could be lost.
(detekt.exceptions.SwallowedException)
[warning] 74-74: The caught exception is swallowed. The original exception could be lost.
(detekt.exceptions.SwallowedException)
app/src/main/java/com/texthip/thip/ui/search/screen/SearchBookScreen.kt
[warning] 59-59: The caught exception is swallowed. The original exception could be lost.
(detekt.exceptions.SwallowedException)
[warning] 72-72: The caught exception is swallowed. The original exception could be lost.
(detekt.exceptions.SwallowedException)
🔇 Additional comments (3)
app/src/main/java/com/texthip/thip/ui/group/search/screen/GroupSearchScreen.kt (1)
48-49: 네비게이션 콜백 구현이 잘 되었습니다!뒤로가기와 룸 클릭 핸들러가 적절히 추가되고 하위 컴포넌트로 전달되었습니다.
Also applies to: 142-142, 203-204, 216-216
app/src/main/java/com/texthip/thip/ui/group/data/repository/GroupRepositoryImpl.kt (1)
11-13: 임시 구현이 잘 구조화되어 있습니다실제 API 통합 전 mock 데이터를 제공하는 repository가 잘 구현되었습니다. Result 타입을 통한 일관된 에러 처리와 suspend 함수 사용이 적절합니다.
app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt (1)
43-45: ViewModel 공유 패턴이 잘 구현되었습니다Group 네비게이션 전체에서 상태를 유지하기 위한 ViewModel 공유가 적절히 구현되었습니다. try-catch를 통한 폴백 처리도 견고합니다.
Also applies to: 89-100, 115-126, 149-161, 187-198, 234-246
| fun refresh() { | ||
| loadInitialData() | ||
| } |
There was a problem hiding this comment.
private이 아닌 함수인데 함수 명이 너무 포괄적이라서 refreshGroupDatas와 같이 명확하게 수정하는건 어떨까요?
| fun onMyGroupCardClick( | ||
| data: GroupCardData, | ||
| onNavigateToRoom: (Int) -> Unit | ||
| ) { | ||
| onNavigateToRoom(data.id) | ||
| } | ||
|
|
||
| fun onRoomCardClick( | ||
| data: GroupCardItemRoomData, | ||
| onNavigateToRecruit: (Int) -> Unit, | ||
| onNavigateToRoom: (Int) -> Unit | ||
| ) { | ||
| if (data.isRecruiting) { | ||
| onNavigateToRecruit(data.id) | ||
| } else { | ||
| onNavigateToRoom(data.id) | ||
| } | ||
| } |
There was a problem hiding this comment.
얘네는 viewModel보다는 composable이 있는 곳에서 분기처리 하는게 나을 것 같은데 viewModel에 만든 이유가 있나요?
There was a problem hiding this comment.
그렇게 한번 수정해볼게요 단순하게 함수 하나로 처리해보려고 했습니다
| suspend fun getRoomDetail(roomId: Int): GroupRoomData? { | ||
| return repository.getRoomDetail(roomId).getOrNull() | ||
| } |
There was a problem hiding this comment.
이 함수도 viewModel보다는 Repository에 만드는게 어떨까요?
There was a problem hiding this comment.
이거 GroupRoom 또는 GroupRecruitRoom으로 이동할 때 더미 넣는 용도였는데 GroupRoom보면 하드코딩 되어있어서 따로 조치하시면 될거 같아요 예시용으로 만들어 둔거 였어요
또 레포지토리에 구현해뒀다고 생각했는데 수정할 점이 있을까요?
There was a problem hiding this comment.
아 화긴했습니닷 repository에 만들라는 거는 이런 함수는 repository 폴더를 만들어서 GroupRepository폴더 안에 넣어달라는 뜻이었는데 그쪽 코드가 숨겨져있어서 못봤네욧 화긴했습니닷 ! 나중에 hilt 적용하면서 수정하면 좋을 것 같아요
| val context = LocalContext.current | ||
| val sharedPrefs = remember { | ||
| context.getSharedPreferences("group_search_prefs", Context.MODE_PRIVATE) | ||
| } | ||
|
|
||
| var recentSearches by remember { | ||
| mutableStateOf( | ||
| try { | ||
| val jsonString = sharedPrefs.getString("recent_searches", "[]") ?: "[]" | ||
| Json.decodeFromString<List<String>>(jsonString) | ||
| } catch (e: Exception) { | ||
| emptyList() | ||
| } | ||
| ) | ||
| } | ||
|
|
||
| fun saveRecentSearches(searches: List<String>) { | ||
| try { | ||
| val jsonString = Json.encodeToString(ListSerializer(String.serializer()), searches) | ||
| sharedPrefs.edit { | ||
| putString("recent_searches", jsonString) | ||
| } | ||
| recentSearches = searches | ||
| } catch (e: Exception) { | ||
| recentSearches = emptyList() | ||
| } | ||
| } |
There was a problem hiding this comment.
이 코드는 최근 검색어를 shared preference를 사용해서 로컬에 저장하는 코드로 보이는데, 최근 검색어도 서버에서 받아오는걸로 알고있는데 테스트 용으로 설정해놓은 코드인가요?
There was a problem hiding this comment.
어 그런가요? 몰랐는데 프론트에서 처리하는 줄 알았네요 나중에 API연결할 때 수정할게요
There was a problem hiding this comment.
넵 ~ 이쪽 말고 밑에 최근검색어 하나 더 있던데 그거도 같이 수정하면 좋겠네용
| onSearch = { query -> | ||
| if (query.isNotBlank() && !recentSearches.contains(query)) { | ||
| recentSearches = listOf(query) + recentSearches | ||
| val newSearches = listOf(query) + recentSearches.take(9) // 최대 10개 유지 |
| val parentEntry = remember(navController) { | ||
| try { | ||
| navController.getBackStackEntry(MainTabRoutes.Group) | ||
| } catch (e: Exception) { | ||
| null | ||
| } | ||
| } | ||
| val groupViewModel: GroupViewModel = if (parentEntry != null) { | ||
| viewModel(viewModelStoreOwner = parentEntry) | ||
| } else { | ||
| viewModel() | ||
| } |
There was a problem hiding this comment.
이 코드가 아래에서도 계속 반복되는 것 같은데 함수로 분리하면 어떨까요?
There was a problem hiding this comment.
나중에 Hilt 적용하면 뺄거 같아요
| onNavigateBack = { | ||
| navController.navigateBack() | ||
| } |
There was a problem hiding this comment.
navController.navigateBack()와 같이 navController에 직접 의존하기보다는 대신 외부에서 주입받은 콜백을 사용하는 게 좋을 것 같습니닷 ..!
There was a problem hiding this comment.
네비게이션 코드에서 사용하는데 따로 주입을 받는게 좋을까요?
There was a problem hiding this comment.
MainNavHost쪽에서 navigateBack을 navigateBack = navController::navigateUp, 이런식으로 받고 각 navigation 파일에서는 이걸 호출하면 어떨까 했는데 지금 저희 mainnavhost는 navcontroller만 주입하는 방식이라 같이 고민해보면 좋긴 할거가타요
rbqks529
left a comment
There was a problem hiding this comment.
궁금한점이나 답변 다 완료했고 수정 필요해보이는 부분은 수정하겠습니다!
There was a problem hiding this comment.
기존에 있던 텍스트 필드인데 누르면 화면 이동만 되던 컴포넌트여서 이렇게 수정했습니다
There was a problem hiding this comment.
이 화면은 뒤로가기 네비게이션만 추가했습니다
| val parentEntry = remember(navController) { | ||
| try { | ||
| navController.getBackStackEntry(MainTabRoutes.Group) | ||
| } catch (e: Exception) { | ||
| null | ||
| } | ||
| } | ||
| val groupViewModel: GroupViewModel = if (parentEntry != null) { | ||
| viewModel(viewModelStoreOwner = parentEntry) | ||
| } else { | ||
| viewModel() | ||
| } |
There was a problem hiding this comment.
나중에 Hilt 적용하면 뺄거 같아요
| fun onMyGroupCardClick( | ||
| data: GroupCardData, | ||
| onNavigateToRoom: (Int) -> Unit | ||
| ) { | ||
| onNavigateToRoom(data.id) | ||
| } | ||
|
|
||
| fun onRoomCardClick( | ||
| data: GroupCardItemRoomData, | ||
| onNavigateToRecruit: (Int) -> Unit, | ||
| onNavigateToRoom: (Int) -> Unit | ||
| ) { | ||
| if (data.isRecruiting) { | ||
| onNavigateToRecruit(data.id) | ||
| } else { | ||
| onNavigateToRoom(data.id) | ||
| } | ||
| } |
There was a problem hiding this comment.
그렇게 한번 수정해볼게요 단순하게 함수 하나로 처리해보려고 했습니다
| val context = LocalContext.current | ||
| val sharedPrefs = remember { | ||
| context.getSharedPreferences("group_search_prefs", Context.MODE_PRIVATE) | ||
| } | ||
|
|
||
| var recentSearches by remember { | ||
| mutableStateOf( | ||
| try { | ||
| val jsonString = sharedPrefs.getString("recent_searches", "[]") ?: "[]" | ||
| Json.decodeFromString<List<String>>(jsonString) | ||
| } catch (e: Exception) { | ||
| emptyList() | ||
| } | ||
| ) | ||
| } | ||
|
|
||
| fun saveRecentSearches(searches: List<String>) { | ||
| try { | ||
| val jsonString = Json.encodeToString(ListSerializer(String.serializer()), searches) | ||
| sharedPrefs.edit { | ||
| putString("recent_searches", jsonString) | ||
| } | ||
| recentSearches = searches | ||
| } catch (e: Exception) { | ||
| recentSearches = emptyList() | ||
| } | ||
| } |
There was a problem hiding this comment.
어 그런가요? 몰랐는데 프론트에서 처리하는 줄 알았네요 나중에 API연결할 때 수정할게요
| suspend fun getRoomDetail(roomId: Int): GroupRoomData? { | ||
| return repository.getRoomDetail(roomId).getOrNull() | ||
| } |
There was a problem hiding this comment.
이거 GroupRoom 또는 GroupRecruitRoom으로 이동할 때 더미 넣는 용도였는데 GroupRoom보면 하드코딩 되어있어서 따로 조치하시면 될거 같아요 예시용으로 만들어 둔거 였어요
또 레포지토리에 구현해뒀다고 생각했는데 수정할 점이 있을까요?
| onNavigateBack = { | ||
| navController.navigateBack() | ||
| } |
There was a problem hiding this comment.
네비게이션 코드에서 사용하는데 따로 주입을 받는게 좋을까요?
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (2)
app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt (2)
194-223: 비동기 데이터 로딩 시 로딩 상태 및 에러 처리 개선 필요과거 리뷰에서 지적된 것처럼 현재 구현은 데이터 로딩 중 빈 화면을 보여주어 사용자 경험이 좋지 않습니다. 로딩 인디케이터와 에러 처리 로직을 추가해주세요.
var roomDetail by remember { mutableStateOf<GroupRoomData?>(null) } +var isLoading by remember { mutableStateOf(true) } +var error by remember { mutableStateOf<String?>(null) } LaunchedEffect(roomId) { + isLoading = true + error = null try { roomDetail = groupViewModel.getRoomDetail(roomId) + } catch (e: Exception) { + error = e.message + } finally { + isLoading = false } } -roomDetail?.let { detail -> +when { + isLoading -> { + // 로딩 인디케이터 표시 + CircularProgressIndicator() + } + error != null -> { + // 에러 메시지 및 재시도 버튼 표시 + } + roomDetail != null -> { GroupRoomRecruitScreen( - detail = detail, + detail = roomDetail!!, // ... 기존 코드 ) -} ?: run { - // 로딩 중이거나 데이터를 찾을 수 없는 경우 + } }
242-257: roomDetail 데이터 미사용 문제과거 리뷰에서 지적된 것처럼
roomDetail을 로드하지만GroupRoomScreen에 전달하지 않고 있습니다. 데이터가 필요하다면 파라미터로 전달하고, 불필요하다면 로딩 로직을 제거해주세요.다음 스크립트로
GroupRoomScreen이 roomDetail 데이터를 필요로 하는지 확인해주세요:#!/bin/bash # GroupRoomScreen의 파라미터 확인 ast-grep --pattern 'fun GroupRoomScreen($$$) { $$$ }'
🧹 Nitpick comments (3)
app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt (3)
38-38: SuppressLint 사용보다는 근본적인 문제 해결 권장
UnrememberedGetBackStackEntry경고를 억제하는 대신,remember블록 내에서 적절한 예외 처리를 통해 안전하게 처리하는 것이 좋습니다. 현재 코드에서는 이미 try-catch로 처리하고 있으므로 SuppressLint가 불필요할 수 있습니다.-@SuppressLint("UnrememberedGetBackStackEntry") fun NavGraphBuilder.groupNavigation( navController: NavHostController, navigateBack: () -> Unit ) {
91-102: ViewModel 공유 패턴 중복 - 함수 추출 고려동일한 ViewModel 공유 패턴이 여러 화면에서 반복됩니다. Hilt 적용 전까지 임시로 사용한다고 하셨지만, 가독성과 유지보수를 위해 공통 함수로 추출하는 것을 고려해보세요.
private fun getSharedGroupViewModel( navController: NavHostController, currentEntry: NavBackStackEntry ): GroupViewModel { val parentEntry = remember(navController) { try { navController.getBackStackEntry(MainTabRoutes.Group) } catch (e: Exception) { null } } return if (parentEntry != null) { viewModel(viewModelStoreOwner = parentEntry) } else { viewModel() } }
39-42: navController 직접 사용에 대한 아키텍처 고려사항과거 리뷰에서 navController 직접 의존성보다 콜백 주입을 선호한다는 의견이 있었습니다. 네비게이션 그래프에서는 직접 사용이 일반적이지만, 테스트 가능성과 결합도를 고려할 때 콜백 방식도 장점이 있습니다. 현재 구조에서는
navigateBack콜백을 이미 사용하고 있어 일관성 있는 접근을 보여줍니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
app/src/main/java/com/texthip/thip/ui/group/data/viewmodel/GroupViewModel.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/group/screen/GroupScreen.kt(3 hunks)app/src/main/java/com/texthip/thip/ui/navigator/MainNavHost.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/navigator/extensions/CommonNavigationExtensions.kt(2 hunks)app/src/main/java/com/texthip/thip/ui/navigator/navigations/CommonNavigation.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- app/src/main/java/com/texthip/thip/ui/navigator/extensions/CommonNavigationExtensions.kt
- app/src/main/java/com/texthip/thip/ui/navigator/MainNavHost.kt
- app/src/main/java/com/texthip/thip/ui/navigator/navigations/CommonNavigation.kt
- app/src/main/java/com/texthip/thip/ui/group/data/viewmodel/GroupViewModel.kt
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
app/src/main/java/com/texthip/thip/ui/group/screen/GroupScreen.kt (2)
Learnt from: rbqks529
PR: #30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
Learnt from: rbqks529
PR: #30
File: app/src/main/java/com/texthip/thip/ui/myPage/groupPage/GroupPageScreen.kt:34-37
Timestamp: 2025-07-01T07:19:01.239Z
Learning: GroupPageScreen의 MyPageViewModel은 임시 ViewModel로, 현재는 프로토타입 단계이므로 오류 처리 등의 추가 기능은 나중에 구현 예정입니다.
app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt (1)
Learnt from: rbqks529
PR: #30
File: app/src/main/java/com/texthip/thip/ui/myPage/groupPage/GroupPageScreen.kt:34-37
Timestamp: 2025-07-01T07:19:01.239Z
Learning: GroupPageScreen의 MyPageViewModel은 임시 ViewModel로, 현재는 프로토타입 단계이므로 오류 처리 등의 추가 기능은 나중에 구현 예정입니다.
🔇 Additional comments (11)
app/src/main/java/com/texthip/thip/ui/group/screen/GroupScreen.kt (8)
29-29: LGTM: ViewModel 구조 변경에 따른 import 경로 업데이트GroupViewModel이 데이터 레이어로 이동하여 리포지토리 패턴을 사용하도록 개선된 것에 맞춰 import 경로가 적절히 업데이트되었습니다.
36-41: 훌륭한 네비게이션 콜백 구조PR 목표에 맞춰 다양한 그룹 관련 화면으로의 네비게이션 콜백이 적절히 추가되었습니다. 파라미터 명명과 주석이 명확하고, roomId를 받는 콜백들도 적절히 구현되어 있습니다.
49-49: LGTM: 컴포넌트 유연성 개선Box의 modifier를 외부에서 전달받은 modifier를 직접 사용하도록 변경하여 컴포넌트의 유연성이 향상되었습니다.
60-61: 적절한 네비게이션 콜백 사용LogoTopAppBar에서 완료된 그룹과 알림 화면으로의 네비게이션이 콜백을 통해 적절히 처리되고 있습니다.
67-67: 검색 화면 네비게이션 구현 완료GroupSearchTextField에서 검색 화면으로의 네비게이션이 적절히 구현되었습니다.
72-72: 내 모임방 네비게이션 구현 완료GroupMySectionHeader에서 내 모임방 화면으로의 네비게이션이 적절히 구현되었습니다.
78-80: 그룹 카드 클릭 네비게이션 구현 완료GroupPager에서 카드 클릭 시 그룹 룸 화면으로의 네비게이션이 groupCard.id를 사용하여 적절히 구현되었습니다.
95-101: 조건부 네비게이션 로직 구현 완료PR 설명에서 언급된
isRecruiting속성에 기반한 조건부 네비게이션 로직이 적절히 구현되었습니다. 모집 중인 방은 모집 화면으로, 진행 중인 방은 기록장 화면으로 이동하는 로직이 사용자 경험 관점에서 합리적입니다.app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt (3)
44-73: 메인 GroupScreen 네비게이션 구현 완료PR 목표에 맞춰 모든 필요한 네비게이션 콜백이 적절히 구현되었습니다. ViewModel을 backStackEntry에 스코핑하여 네비게이션 그래프 전체에서 상태를 공유하는 방식도 올바릅니다.
133-138: 일관된 조건부 네비게이션 로직GroupScreen과 동일한 조건부 네비게이션 로직이 일관되게 적용되어 사용자 경험의 일관성을 보장합니다.
39-42: 훌륭한 네비게이션 아키텍처 구현PR 목표에 맞춰 메인 모임방 화면에서 다양한 화면으로의 네비게이션이 포괄적으로 구현되었습니다. 네비게이션 콜백과 공유 ViewModel을 사용한 접근 방식이 아키텍처적으로 우수합니다.
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (2)
app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt (2)
249-249: roomDetail 데이터 미사용
roomDetail을 로드했지만GroupRoomScreen에 전달하지 않고 있습니다.
91-102: 중복된 ViewModel 획득 로직동일한 패턴의 코드가 5번 반복되고 있습니다. 과거 리뷰에서도 언급되었듯이 함수로 추출하면 좋겠습니다.
Also applies to: 117-128, 147-158, 181-192, 229-240
🧹 Nitpick comments (5)
app/src/main/java/com/texthip/thip/data/group/repository/GroupRepository.kt (4)
11-13: 임시 코드임을 명시해주셔서 감사합니다실제 API 연동 시 쉽게 교체할 수 있도록 Repository 인터페이스를 따로 정의하는 것을 고려해보세요. 이렇게 하면 테스트와 실제 구현을 쉽게 전환할 수 있습니다.
+interface GroupRepository { + suspend fun getUserName(): Result<String> + suspend fun getMyGroups(): Result<List<GroupCardData>> + suspend fun getRoomSections(): Result<List<GroupRoomSectionData>> + // ... 다른 메서드들 +} + -class GroupRepository { +class MockGroupRepository : GroupRepository {
21-21: 하드코딩된 사용자 이름임시 구현이라고 하셨지만, 테스트나 데모 목적으로도 설정 가능한 값으로 만들면 더 유용할 것 같습니다.
+ private val mockUserName = "규빈" + suspend fun getUserName(): Result<String> { return try { - Result.success("규빈") // 임시 이름 + Result.success(mockUserName) // 임시 이름
278-323: 과도한 하드코딩된 추천 데이터46개의 하드코딩된 추천 데이터는 유지보수가 어렵습니다. 데이터 생성 로직을 단순화하거나 외부 파일로 분리하는 것을 고려해보세요.
- val recommendationPool = listOf( - // 문학 관련 추천 - GroupCardItemRoomData(1001, "한국 근현대 소설 읽기", 18, 25, true, 3, R.drawable.bookcover_sample, 0), - // ... 46개의 항목 - ) + val recommendationPool = generateMockRecommendations() + + private fun generateMockRecommendations(): List<GroupCardItemRoomData> { + return (1001..1046).map { id -> + GroupCardItemRoomData( + id = id, + title = mockTitles[id % mockTitles.size], + participants = (10..30).random(), + maxParticipants = (15..35).random(), + isRecruiting = true, + endDate = (1..10).random(), + imageRes = R.drawable.bookcover_sample, + genreIndex = (0..4).random(), + isSecret = id % 5 == 0 + ) + } + }
29-29: 일관되지 않은 딜레이 시간네트워크 지연을 시뮬레이션하는 딜레이 시간이 메서드마다 다릅니다 (50ms, 150ms, 200ms). 일관성을 위해 상수로 정의하는 것이 좋겠습니다.
+ companion object { + private const val MOCK_NETWORK_DELAY = 100L + } + suspend fun getMyGroups(): Result<List<GroupCardData>> { return try { - delay(200) + delay(MOCK_NETWORK_DELAY)Also applies to: 191-191
app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt (1)
220-222: 로딩 및 에러 상태 UI 구현 필요현재 데이터 로딩 중이거나 에러 발생 시 빈 화면이 표시됩니다. 사용자 경험 개선을 위해 적절한 UI를 추가해주세요.
} ?: run { // 로딩 중이거나 데이터를 찾을 수 없는 경우 Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { CircularProgressIndicator() } }로딩 상태와 에러 상태를 구분하여 처리하는 완전한 구현을 생성해드릴까요?
Also applies to: 254-256
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
app/build.gradle.kts(2 hunks)app/src/main/java/com/texthip/thip/data/group/repository/GroupRepository.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/group/screen/GroupScreen.kt(3 hunks)app/src/main/java/com/texthip/thip/ui/group/viewmodel/GroupViewModel.kt(1 hunks)app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt(2 hunks)build.gradle.kts(1 hunks)gradle/libs.versions.toml(2 hunks)gradle/wrapper/gradle-wrapper.properties(1 hunks)
✅ Files skipped from review due to trivial changes (2)
- gradle/wrapper/gradle-wrapper.properties
- build.gradle.kts
🚧 Files skipped from review as they are similar to previous changes (2)
- app/src/main/java/com/texthip/thip/ui/group/screen/GroupScreen.kt
- app/src/main/java/com/texthip/thip/ui/group/viewmodel/GroupViewModel.kt
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/myPage/groupPage/GroupPageScreen.kt:34-37
Timestamp: 2025-07-01T07:19:01.239Z
Learning: GroupPageScreen의 MyPageViewModel은 임시 ViewModel로, 현재는 프로토타입 단계이므로 오류 처리 등의 추가 기능은 나중에 구현 예정입니다.
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.
📚 Learning: grouppagescreen의 mypageviewmodel은 임시 viewmodel로, 현재는 프로토타입 단계이므로 오류 처리 등의 추가 기능은 나중에 구현 예정입니다....
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/myPage/groupPage/GroupPageScreen.kt:34-37
Timestamp: 2025-07-01T07:19:01.239Z
Learning: GroupPageScreen의 MyPageViewModel은 임시 ViewModel로, 현재는 프로토타입 단계이므로 오류 처리 등의 추가 기능은 나중에 구현 예정입니다.
Applied to files:
app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt
🪛 detekt (1.23.8)
app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt
[warning] 94-94: The caught exception is swallowed. The original exception could be lost.
(detekt.exceptions.SwallowedException)
[warning] 120-120: The caught exception is swallowed. The original exception could be lost.
(detekt.exceptions.SwallowedException)
[warning] 151-151: The caught exception is swallowed. The original exception could be lost.
(detekt.exceptions.SwallowedException)
[warning] 184-184: The caught exception is swallowed. The original exception could be lost.
(detekt.exceptions.SwallowedException)
[warning] 232-232: The caught exception is swallowed. The original exception could be lost.
(detekt.exceptions.SwallowedException)
🔇 Additional comments (2)
app/build.gradle.kts (1)
8-9: Hilt 의존성 추가가 적절합니다Hilt를 통한 의존성 주입 설정이 올바르게 구성되었습니다. KSP 플러그인과 함께 필요한 모든 Hilt 의존성이 추가되었네요.
Also applies to: 72-74
gradle/libs.versions.toml (1)
3-3: Kotlin 및 연관 라이브러리 버전 호환성 검증 필요현재 gradle/libs.versions.toml에서 주요 의존성들이 아래와 같이 다운그레이드/변경되었습니다:
- Kotlin: 2.2.0 → 2.0.21
- Navigation 라이브러리 (라인 11–14)
- Serialization 라이브러리 (라인 17)
- Hilt/KSP 플러그인 신규 도입 및 버전 정렬
공식 자료 기준으로 Hilt 2.51.1은 Kotlin 1.9.x~2.0.x 계열에서 검증되었으나, Kotlin 2.2.0 호환성 사례는 아직 제한적입니다. 특히 Jetpack Compose Compiler, KSP, AGP 등 주변 의존성과 함께 전체 빌드 환경에서 테스트하지 않을 경우 예기치 않은 빌드 오류가 발생할 수 있습니다.
아래 사항들을 확인해주세요:
- Kotlin 2.0.21 선택이 Hilt·KSP 호환성 확보를 위한 의도인지
- Kotlin 2.2.0으로 업그레이드 시 Compose/KSP/AGP 빌드 통과 여부
- Navigation·Serialization 라이브러리 다운그레이드로 인한 기능 또는 버그 수정 누락 여부
| class GroupRepository { | ||
|
|
||
| private val genres = listOf("문학", "과학·IT", "사회과학", "인문학", "예술") | ||
| private val roomDetailsCache = mutableMapOf<Int, GroupRoomData>() |
There was a problem hiding this comment.
캐시 관리 개선 필요
roomDetailsCache가 계속 증가할 수 있습니다. 메모리 누수를 방지하기 위해 LRU 캐시나 크기 제한을 고려해보세요.
- private val roomDetailsCache = mutableMapOf<Int, GroupRoomData>()
+ private val roomDetailsCache = androidx.collection.LruCache<Int, GroupRoomData>(50)Also applies to: 225-225
🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/data/group/repository/GroupRepository.kt
at line 17 and also line 225, the current mutableMap used for roomDetailsCache
can grow indefinitely causing potential memory leaks. Replace this with an LRU
cache implementation or add a size limit to the cache to automatically evict the
least recently used entries when the cache exceeds a defined capacity, ensuring
controlled memory usage.
| val parentEntry = remember(navController) { | ||
| try { | ||
| navController.getBackStackEntry(MainTabRoutes.Group) | ||
| } catch (e: Exception) { |
There was a problem hiding this comment.
예외 처리 시 로깅 추가 필요
예외가 발생할 때 조용히 무시되고 있습니다. 디버깅을 위해 최소한 로그를 남기는 것이 좋겠습니다.
} catch (e: Exception) {
+ // 부모 백스택 엔트리를 찾을 수 없는 경우 - 정상적인 상황일 수 있음
+ android.util.Log.d("GroupNavigation", "Parent back stack entry not found: ${e.message}")
null
}Also applies to: 120-120, 151-151, 184-184, 232-232
🧰 Tools
🪛 detekt (1.23.8)
[warning] 94-94: The caught exception is swallowed. The original exception could be lost.
(detekt.exceptions.SwallowedException)
🤖 Prompt for AI Agents
In
app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt
at lines 94, 120, 151, 184, and 232, the catch blocks currently swallow
exceptions silently without logging. Modify each catch block to log the caught
exception using an appropriate logging mechanism to ensure that errors are
recorded for debugging purposes.
| roomDetail?.let { detail -> | ||
| GroupRoomRecruitScreen( | ||
| detail = detail, | ||
| buttonType = GroupBottomButtonType.JOIN, // 기본값, 실제로는 사용자 상태에 따라 결정 |
There was a problem hiding this comment.
🛠️ Refactor suggestion
하드코딩된 버튼 타입
GroupBottomButtonType.JOIN이 하드코딩되어 있습니다. 주석에도 나와있듯이 실제 사용자 상태에 따라 결정되어야 합니다.
- buttonType = GroupBottomButtonType.JOIN, // 기본값, 실제로는 사용자 상태에 따라 결정
+ buttonType = when {
+ detail.isOwner -> GroupBottomButtonType.CLOSE_RECRUITMENT
+ detail.isParticipant -> GroupBottomButtonType.CANCEL
+ else -> GroupBottomButtonType.JOIN
+ },📝 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.
| buttonType = GroupBottomButtonType.JOIN, // 기본값, 실제로는 사용자 상태에 따라 결정 | |
| buttonType = when { | |
| detail.isOwner -> GroupBottomButtonType.CLOSE_RECRUITMENT | |
| detail.isParticipant -> GroupBottomButtonType.CANCEL | |
| else -> GroupBottomButtonType.JOIN | |
| }, |
🤖 Prompt for AI Agents
In
app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt
at line 203, the buttonType is hardcoded to GroupBottomButtonType.JOIN, but it
should be dynamically determined based on the user's current state. Modify the
code to evaluate the user's status and assign buttonType accordingly instead of
using a fixed value.
➕ 이슈 링크
🔎 작업 내용
📸 스크린샷
😢 해결하지 못한 과제
[] 검색 화면은 아직 구현하지 않았습니다
📢 리뷰어들에게
Summary by CodeRabbit
신규 기능
기능 개선
버그 수정
기타