Skip to content

[Feature/#77] onboarding, maps api#80

Merged
leeseokchan00 merged 7 commits intodevelopfrom
feature/#77-maps-api
Jul 15, 2025
Merged

[Feature/#77] onboarding, maps api#80
leeseokchan00 merged 7 commits intodevelopfrom
feature/#77-maps-api

Conversation

@leeseokchan00
Copy link
Copy Markdown
Contributor

@leeseokchan00 leeseokchan00 commented Jul 15, 2025

📌 PR 요약

🌱 작업한 내용

  • 온보딩, 지도 api 조금

🌱 PR 포인트

📸 스크린샷

스크린샷
파일첨부바람

📮 관련 이슈

Summary by CodeRabbit

  • 신규 기능

    • 온보딩 과정에서 페르소나 질문을 불러오고 선택할 수 있는 기능이 추가되었습니다.
    • 닉네임 입력 시 중복 및 유효성 검사가 실시간으로 반영되고, 성공 여부에 따라 다음 단계로 진행할 수 있습니다.
    • 이미지(SVG, GIF 포함) 로딩 및 표시 기능이 추가되었습니다.
    • 장소 및 코스 상세 정보, 북마크 추가/삭제, 장소별 코스 목록 조회 등 지도 관련 기능이 개선되었습니다.
  • 기능 개선

    • 장소 및 코스 식별자 타입이 Int에서 Long으로 변경되어 더 많은 데이터를 지원합니다.
    • 이미지 정보, SNS 링크 등 상세 정보 구조가 개선되어 더 풍부한 정보를 제공합니다.
    • 온보딩 상태 관리 및 성공 여부 확인이 명확해졌습니다.
  • 버그 수정

    • 닉네임 입력 및 유효성 검증 로직이 개선되어, 입력 지연 및 불필요한 중복 호출이 제거되었습니다.
    • 페르소나 선택 및 상태 관리가 정확하게 동작하도록 수정되었습니다.
  • 라이브러리/의존성

    • Coil 이미지 라이브러리가 2.7.0으로 업데이트되고, SVG 및 GIF 지원이 추가되었습니다.

@leeseokchan00 leeseokchan00 requested a review from a team July 15, 2025 22:44
@leeseokchan00 leeseokchan00 self-assigned this Jul 15, 2025
@leeseokchan00 leeseokchan00 added the 석찬🍚🦁 이석 찬찬찬찬 찬이야 ~ 완전 찬이야 ~ label Jul 15, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jul 15, 2025

Walkthrough

이번 변경 사항은 지도(Maps) 및 온보딩(OnBoarding) 기능의 전체적인 API 연동, DTO 및 Entity 구조 정비, Flow 기반 검증 로직 도입, Compose UI 파라미터 타입 일관화, 이미지 로딩 유틸 추가, 그리고 의존성 및 라이브러리 버전 갱신을 포함합니다. 또한, 신규 API 엔드포인트와 매퍼, 리포지토리, 데이터소스 구현이 대폭 추가되었습니다.

Changes

파일/경로 요약 변경 내용 요약
core/designsystem/.../SolplyTextField.kt 닉네임 유효성 콜백 추가, 내부 검증 로직 및 의존성 변경, delay 제거
core/ui/build.gradle.kts, gradle/libs.versions.toml Coil SVG/GIF 번들 추가 및 버전 업데이트, Compose 번들 수정
core/ui/.../AdaptationImage.kt SVG/GIF 지원 AdaptationImage 컴포저블 추가
data/maps/.../dto/response/*.kt 코스/장소 상세, 코스 리스트용 DTO 신규 추가
data/maps/.../mapper/*.kt DTO → Entity 매핑 확장 함수 신규 추가
data/maps/.../repository/MapsRepositoryImpl.kt, .../source/MapsRemoteDataSource.kt 하드코딩 제거, 실제 원격 데이터 연동, 북마크/코스 관련 신규 메서드 추가 및 시그니처 변경
domain/maps/.../model/*.kt ID 타입 Int→Long, 썸네일/이미지/링크 필드 타입 및 명칭 정비
domain/maps/.../repository/MapsRepository.kt 메서드 시그니처 및 반환 타입, 파라미터 타입 일괄 Long으로 변경, 신규 메서드 추가/제거
data/onboarding/.../response/GetPersonaQuestionsResponseDto.kt, .../mapper/PersonaEntityMapper.kt 페르소나 관련 DTO, 매퍼 신규 추가
data/onboarding/.../repository/OnBoardingRepositoryImpl.kt, .../source/remote/OnBoardingRemoteDataSource.kt 페르소나 질문 조회 메서드 추가 및 인터페이스 경로 변경
domain/onboarding/.../model/PersonaEntity.kt, .../repository/OnBoardingRepository.kt 페르소나 Entity 및 Repository 메서드 추가
feature/maps/... (다수) ID타입 Int→Long, 필드명 정비, 파라미터/콜백 타입 일관화, 신규 API 연동
feature/onboarding/... (다수) 닉네임 중복 체크 Flow 기반 비동기화, 온보딩 성공 플래그 및 Intent 추가, 페르소나/닉네임/버튼 활성화 로직 개선
remote/maps/.../MapsRemoteDataSourceImpl.kt, .../service/MapsService.kt 기존 saveCourse 제거, 장소/코스/북마크 관련 신규 API 메서드 대거 추가
remote/onboarding/.../OnBoardingRemoteDataSourceImpl.kt, .../service/OnBoardingService.kt 페르소나 질문 조회 API 추가 및 구현
기타 패키지 경로, import, DTO 패키지 위치 일부 정비

Sequence Diagram(s)

sequenceDiagram
    participant UI
    participant ViewModel
    participant Repository
    participant RemoteDataSource
    participant Service

    UI->>ViewModel: getPlaceDetailInfo(placeId: Long)
    ViewModel->>Repository: getPlaceDetail(placeId: Long)
    Repository->>RemoteDataSource: getPlaceDetail(placeId: Long)
    RemoteDataSource->>Service: getPlaceDetail(placeId: Long) [API]
    Service-->>RemoteDataSource: BaseResponse<GetPlaceDetailResponseDto>
    RemoteDataSource-->>Repository: GetPlaceDetailResponseDto
    Repository-->>ViewModel: PlaceDetailEntity (매핑)
    ViewModel-->>UI: State 업데이트
Loading
sequenceDiagram
    participant UI
    participant ViewModel
    participant Repository
    participant RemoteDataSource
    participant Service

    UI->>ViewModel: ChangeInputNickname(nickname)
    ViewModel->>ViewModel: nicknameFlow 업데이트
    ViewModel-->>ViewModel: (debounce 500ms)
    ViewModel->>Repository: checkNicknameDuplicate(nickname)
    Repository->>RemoteDataSource: checkNicknameDuplicate(nickname)
    RemoteDataSource->>Service: checkNicknameDuplicate(nickname) [API]
    Service-->>RemoteDataSource: BaseResponse<Boolean>
    RemoteDataSource-->>Repository: Boolean
    Repository-->>ViewModel: Boolean
    ViewModel-->>UI: isNicknameDuplicate, isOnBoardingSuccess 등 State 업데이트
Loading

Possibly related PRs

  • #76: SolplyTextField.kt의 닉네임 중복 체크 콜백 구조 변경과 관련, 동일 컴포저블 및 검증 로직을 수정함.
  • #30: SolplyTextField.kt의 닉네임 검증 UI/상태 관리 전면 리팩터와 관련, 동일 컴포저블 및 검증 로직을 다룸.

Suggested reviewers

  • ImHyungsuk

Poem

🐰
코스와 장소, 롱으로 통일,
북마크, 페르소나, 모두 API로 빌빌!
닉네임 검증은 Flow로 찰랑,
이미지 로딩은 Coil로 반짝!
토끼는 오늘도 코드를 달려,
SOLPLY의 지도를 완성하려!
🗺️✨

✨ Finishing Touches
  • 📝 Generate Docstrings

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

@leeseokchan00 leeseokchan00 merged commit 1e59b15 into develop Jul 15, 2025
1 check was pending
Copy link
Copy Markdown

@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: 10

🔭 Outside diff range comments (2)
feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/screen/NamingScreen.kt (1)

34-35: 중복된 modifier를 제거하세요.

fillMaxSize() modifier가 두 번 적용되어 있습니다.

modifier = Modifier
    .fillMaxSize()
-    .fillMaxSize()
    .padding(horizontal = 16.dp)
    .addFocusCleaner(focusManager),
feature/maps/src/main/java/com/teamsolply/solply/maps/MapsViewModel.kt (1)

231-241: 하드코딩된 courseId 수정 필요

getCourseDetailInfo() 메서드에서 courseId = 1로 하드코딩되어 있습니다. 실제 코스 ID를 매개변수로 받아야 합니다.

다음과 같이 수정해주세요:

-    fun getCourseDetailInfo() {
+    fun getCourseDetailInfo(courseId: Long) {
         viewModelScope.launch {
-            mapsRepository.getCourseDetail(courseId = 1).onSuccess {
+            mapsRepository.getCourseDetail(courseId = courseId).onSuccess {
🧹 Nitpick comments (7)
core/ui/src/main/java/com/teamsolply/solply/ui/image/AdaptationImage.kt (2)

39-46: 에러 처리 및 로딩 상태 지원 추가 고려

현재 구현에서는 이미지 로딩 실패나 로딩 상태에 대한 처리가 없습니다. 사용자 경험 개선을 위해 에러 처리와 로딩 상태를 지원하는 것을 고려해보세요.

다음과 같은 개선사항을 제안합니다:

 @Composable
 fun AdaptationImage(
     modifier: Modifier = Modifier,
     imageUrl: String,
     contentScale: ContentScale = ContentScale.Fit,
-    contentDescription: String? = null
+    contentDescription: String? = null,
+    placeholder: @Composable (() -> Unit)? = null,
+    error: @Composable (() -> Unit)? = null,
+    onLoading: @Composable (() -> Unit)? = null
 ) {
     // ... existing code ...
     
     AsyncImage(
         model = request,
         imageLoader = imageLoader,
         contentScale = contentScale,
         contentDescription = contentDescription,
+        placeholder = placeholder,
+        error = error,
+        onLoading = onLoading,
         modifier = modifier
     )
 }

27-31: 디코더 추가 로직 개선 필요

현재 when 블록에서 SVG 또는 GIF 중 하나만 처리하고 있습니다. 두 조건이 모두 true인 경우나 둘 다 false인 경우에 대한 처리가 명확하지 않습니다.

더 명확한 로직을 제안합니다:

 .components {
-    when {
-        isSvg -> add(SvgDecoder.Factory())
-        isGif -> add(GifDecoder.Factory())
-    }
+    if (isSvg) add(SvgDecoder.Factory())
+    if (isGif) add(GifDecoder.Factory())
 }
domain/onboarding/src/main/java/com/teamsolply/solply/onboarding/model/PersonaEntity.kt (1)

3-6: 도메인 모델 구조가 적절하나 포매팅을 개선해주세요.

도메인 엔티티 설계는 좋습니다. 다만 클래스 정의에서 불필요한 공백 라인이 있습니다.

 data class PersonaEntity(
     val personaList: List<Persona>
-
 )
feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/OnBoardingViewModel.kt (1)

81-91: 페르소나 질문 조회 시 에러 처리를 추가하는 것이 좋겠습니다.

현재 성공 케이스만 처리하고 있어 실패 시 사용자에게 피드백이 없습니다.

private fun getPersonaQuestions() {
    viewModelScope.launch {
-        onBoardingRepository.getPersonaQuestions().onSuccess {
-            reduce {
-                copy(
-                    personaList = it
-                )
+        onBoardingRepository.getPersonaQuestions()
+            .onSuccess {
+                reduce {
+                    copy(
+                        personaList = it
+                    )
+                }
+            }
+            .onFailure { throwable ->
+                // 에러 로깅 또는 사용자 피드백 처리
+                // 예: postSideEffect(OnBoardingSideEffect.ShowError(throwable.message))
            }
-        }
    }
}
remote/maps/src/main/java/com/teamsolply/solply/maps/service/MapsService.kt (3)

22-32: 메서드명의 일관성을 개선해주세요.

북마크 관리 메서드들이 올바르게 구현되었지만, 메서드명에서 "BookMark"보다는 "Bookmark"가 더 일관된 표기법입니다.

-    suspend fun postPlaceBookMark(
+    suspend fun postPlaceBookmark(
        @Path("placeId") placeId: Long
    ): BaseResponse<Unit>

-    suspend fun deletePlaceBookMark(
+    suspend fun deletePlaceBookmark(
        @Path("placeId") placeId: Long
    ): BaseResponse<Unit>

34-39: 메서드명을 더 명확하게 개선해주세요.

"getAddMyCourse"라는 메서드명이 혼란스럽습니다. "Add"가 포함되어 있어 추가 작업으로 오해될 수 있지만, 실제로는 조회 메서드입니다.

-    suspend fun getAddMyCourse(
+    suspend fun getMyCourses(
        @Query("townId") townId: Long,
        @Query("placeId") placeId: Long
    ): BaseResponse<CoursesResponseDto>

47-47: 불필요한 주석을 제거해주세요.

"// 코스 전체 조회" 주석에 해당하는 메서드가 없습니다. 이는 혼란을 야기할 수 있으므로 제거해주세요.

-    // 코스 전체 조회
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6a6609e and e9a839c.

📒 Files selected for processing (39)
  • core/designsystem/src/main/java/com/teamsolply/solply/designsystem/component/textfield/SolplyTextField.kt (2 hunks)
  • core/ui/build.gradle.kts (1 hunks)
  • core/ui/src/main/java/com/teamsolply/solply/ui/image/AdaptationImage.kt (1 hunks)
  • data/maps/src/main/java/com/teamsolply/solply/maps/dto/SaveCourseRequestDto.kt (1 hunks)
  • data/maps/src/main/java/com/teamsolply/solply/maps/dto/response/GetAddMyCourseResponseDto.kt (1 hunks)
  • data/maps/src/main/java/com/teamsolply/solply/maps/dto/response/GetCourseDetailResponseDto.kt (1 hunks)
  • data/maps/src/main/java/com/teamsolply/solply/maps/dto/response/GetPlaceDetailResponseDto.kt (1 hunks)
  • data/maps/src/main/java/com/teamsolply/solply/maps/mapper/CourseDetailEntityMapper.kt (1 hunks)
  • data/maps/src/main/java/com/teamsolply/solply/maps/mapper/CourseInfoEntityMapper.kt (1 hunks)
  • data/maps/src/main/java/com/teamsolply/solply/maps/mapper/PlaceDetailEntityMapper.kt (1 hunks)
  • data/maps/src/main/java/com/teamsolply/solply/maps/repository/MapsRepositoryImpl.kt (1 hunks)
  • data/maps/src/main/java/com/teamsolply/solply/maps/source/MapsRemoteDataSource.kt (1 hunks)
  • data/onboarding/src/main/java/com/teamsolply/solply/onboarding/dto/response/GetPersonaQuestionsResponseDto.kt (1 hunks)
  • data/onboarding/src/main/java/com/teamsolply/solply/onboarding/mapper/PersonaEntityMapper.kt (1 hunks)
  • data/onboarding/src/main/java/com/teamsolply/solply/onboarding/repository/OnBoardingRepositoryImpl.kt (1 hunks)
  • data/onboarding/src/main/java/com/teamsolply/solply/onboarding/source/remote/OnBoardingRemoteDataSource.kt (1 hunks)
  • domain/maps/src/main/java/com/teamsolply/solply/maps/model/CourseDetailEntity.kt (1 hunks)
  • domain/maps/src/main/java/com/teamsolply/solply/maps/model/CourseInfoEntity.kt (1 hunks)
  • domain/maps/src/main/java/com/teamsolply/solply/maps/model/PlaceDetailEntity.kt (1 hunks)
  • domain/maps/src/main/java/com/teamsolply/solply/maps/repository/MapsRepository.kt (1 hunks)
  • domain/onboarding/src/main/java/com/teamsolply/solply/onboarding/model/PersonaEntity.kt (1 hunks)
  • domain/onboarding/src/main/java/com/teamsolply/solply/onboarding/repository/OnBoardingRepository.kt (1 hunks)
  • feature/maps/src/main/java/com/teamsolply/solply/maps/MapsContract.kt (5 hunks)
  • feature/maps/src/main/java/com/teamsolply/solply/maps/MapsScreen.kt (5 hunks)
  • feature/maps/src/main/java/com/teamsolply/solply/maps/MapsViewModel.kt (4 hunks)
  • feature/maps/src/main/java/com/teamsolply/solply/maps/component/bottomsheet/AddCourseBottomSheet.kt (1 hunks)
  • feature/maps/src/main/java/com/teamsolply/solply/maps/component/bottomsheet/EditCourseBottomSheet.kt (1 hunks)
  • feature/maps/src/main/java/com/teamsolply/solply/maps/component/bottomsheet/PlaceDetailBottomSheet.kt (4 hunks)
  • feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/OnBoardingContract.kt (3 hunks)
  • feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/OnBoardingScreen.kt (4 hunks)
  • feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/OnBoardingViewModel.kt (2 hunks)
  • feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/screen/NamingScreen.kt (4 hunks)
  • feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/screen/SelectPersonaScreen.kt (1 hunks)
  • gradle/libs.versions.toml (7 hunks)
  • remote/maps/src/main/java/com/teamsolply/solply/maps/datasource/MapsRemoteDataSourceImpl.kt (1 hunks)
  • remote/maps/src/main/java/com/teamsolply/solply/maps/service/MapsService.kt (1 hunks)
  • remote/onboarding/src/main/java/com/teamsolply/solply/onboarding/datasource/OnBoardingRemoteDataSourceImpl.kt (1 hunks)
  • remote/onboarding/src/main/java/com/teamsolply/solply/onboarding/di/OnBoardingRemoteDataModule.kt (1 hunks)
  • remote/onboarding/src/main/java/com/teamsolply/solply/onboarding/service/OnBoardingService.kt (2 hunks)
🔇 Additional comments (88)
gradle/libs.versions.toml (3)

89-89: Coil 라이브러리 버전 업데이트 승인

2.7.0 버전으로의 업데이트가 적절해 보입니다. 새로운 SVG 및 GIF 디코더 지원을 위한 버전 업데이트입니다.


189-190: 새로운 Coil 모듈 추가 승인

SVG 및 GIF 지원을 위한 새로운 모듈들이 올바르게 추가되었습니다.


260-260: Coil 번들 구성 승인

관련된 Coil 라이브러리들을 하나의 번들로 묶어 의존성 관리를 효율적으로 개선했습니다.

core/ui/build.gradle.kts (1)

9-11: 의존성 추가 승인

새로운 AdaptationImage 컴포저블을 위한 Coil 번들 의존성이 올바르게 추가되었습니다.

remote/onboarding/src/main/java/com/teamsolply/solply/onboarding/di/OnBoardingRemoteDataModule.kt (1)

4-4: 패키지 구조 개선이 적절합니다.

OnBoardingRemoteDataSource 인터페이스를 source.remote 패키지로 이동시킨 것은 원격 데이터 소스들을 더 명확하게 구분하는 좋은 구조 개선입니다.

domain/onboarding/src/main/java/com/teamsolply/solply/onboarding/repository/OnBoardingRepository.kt (2)

3-3: PersonaEntity 임포트 추가가 적절합니다.

새로 추가된 getPersonaQuestions() 메서드에서 사용할 PersonaEntity 타입의 임포트가 올바르게 추가되었습니다.


7-7: Repository 패턴을 올바르게 따르고 있습니다.

새로 추가된 getPersonaQuestions() 메서드는 다음과 같은 좋은 패턴을 따르고 있습니다:

  • suspend 함수로 비동기 처리
  • Result<T> 타입으로 에러 처리
  • 일관된 네이밍 컨벤션 준수
feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/screen/SelectPersonaScreen.kt (3)

48-48: 데이터 구조 변경에 맞는 올바른 수정입니다.

PersonaEntity 구조 변경에 맞춰 options.personaList.forEach로 수정된 것이 적절합니다. 이제 optionsPersonaEntity 타입이고 실제 리스트는 personaList 프로퍼티에 있습니다.


49-49: 선택된 페르소나 비교 로직이 올바르게 수정되었습니다.

selectedPersona == persona.personaType 비교로 변경된 것이 적절합니다. 이는 selectedPersona가 이제 String 타입(personaType)으로 변경된 것을 반영합니다.


54-54: Intent 파라미터 수정이 새로운 데이터 모델과 일치합니다.

OnBoardingIntent.OnPersonaSelectedpersona.personaType을 전달하는 것이 올바른 변경입니다. 이는 선택된 페르소나를 객체 대신 타입 문자열로 관리하는 새로운 설계와 일치합니다.

remote/onboarding/src/main/java/com/teamsolply/solply/onboarding/service/OnBoardingService.kt (2)

5-5: 새로운 DTO 임포트가 적절히 추가되었습니다.

GetPersonaQuestionsResponseDto 임포트가 새로 추가된 API 메서드에 맞춰 올바르게 추가되었습니다.


15-16: API 엔드포인트 구현이 일관된 패턴을 따르고 있습니다.

새로 추가된 getPersonaQuestions() 메서드는 다음과 같은 좋은 패턴을 따르고 있습니다:

  • @GET 어노테이션과 적절한 엔드포인트 경로
  • 다른 메서드들과 일관된 BaseResponse<T> 래퍼 사용
  • suspend 함수로 비동기 처리
  • 명확한 네이밍 컨벤션
remote/onboarding/src/main/java/com/teamsolply/solply/onboarding/datasource/OnBoardingRemoteDataSourceImpl.kt (3)

4-4: 필요한 DTO 임포트가 올바르게 추가되었습니다.

새로 구현된 getPersonaQuestions() 메서드를 위한 GetPersonaQuestionsResponseDto 임포트가 적절히 추가되었습니다.


8-8: 패키지 구조 변경에 맞는 임포트 경로 수정입니다.

OnBoardingRemoteDataSource 인터페이스의 임포트 경로가 source.remote 패키지로 올바르게 수정되었습니다.


14-15: 일관된 구현 패턴을 따르고 있습니다.

새로 추가된 getPersonaQuestions() 메서드는 클래스 내 다른 메서드들과 동일한 패턴을 따르고 있습니다:

  • 서비스 메서드 호출 후 .data 필드 반환
  • 에러 처리는 서비스 레이어에 위임
  • 간결하고 명확한 구현
data/onboarding/src/main/java/com/teamsolply/solply/onboarding/source/remote/OnBoardingRemoteDataSource.kt (3)

1-1: 패키지 구조 개선이 적절합니다.

패키지명을 remote로 명확히 구분한 것은 데이터 소스의 역할을 명확하게 하는 좋은 변경입니다.


4-4: 새로운 DTO 임포트가 적절합니다.

persona 질문 기능을 위한 DTO 임포트가 올바르게 추가되었습니다.


9-9: 인터페이스 확장이 일관성 있게 구현되었습니다.

새로운 getPersonaQuestions() 메서드가 기존 패턴과 일관성 있게 추가되었습니다. suspend 함수로 비동기 처리가 적절하게 구현되어 있습니다.

domain/onboarding/src/main/java/com/teamsolply/solply/onboarding/model/PersonaEntity.kt (1)

8-11: Persona 엔티티 정의가 적절합니다.

personaTypedescription 필드를 가진 간단하고 명확한 도메인 모델입니다.

data/onboarding/src/main/java/com/teamsolply/solply/onboarding/repository/OnBoardingRepositoryImpl.kt (3)

4-5: 새로운 임포트가 적절하게 추가되었습니다.

mapper 함수와 도메인 엔티티 임포트가 올바르게 추가되었습니다.


7-7: 업데이트된 임포트 경로가 일관성 있습니다.

remote 패키지로 이동한 데이터 소스 임포트가 올바르게 업데이트되었습니다.


13-17: 에러 핸들링과 매핑이 우수합니다.

runCatchingmapCatching을 사용한 에러 핸들링이 적절하고, DTO를 엔티티로 매핑하는 로직이 깔끔하게 구현되어 있습니다. 기존 코드와 일관성 있는 패턴을 따릅니다.

data/onboarding/src/main/java/com/teamsolply/solply/onboarding/mapper/PersonaEntityMapper.kt (3)

1-7: 임포트 및 패키지 구조가 적절합니다.

매퍼 파일의 패키지 구조와 필요한 DTO, 엔티티 클래스들의 임포트가 올바르게 구성되어 있습니다.


8-12: ResponseDto 매퍼 구현이 우수합니다.

GetPersonaQuestionsResponseDtoPersonaEntity로 매핑하는 로직이 깔끔하고 명확합니다. 리스트 매핑에 map 함수를 적절히 사용했습니다.


14-19: 개별 DTO 매퍼가 적절하게 구현되었습니다.

PersonaDtoPersona 엔티티로 매핑하는 로직이 간단하고 명확합니다. 필드 매핑이 직관적입니다.

data/onboarding/src/main/java/com/teamsolply/solply/onboarding/dto/response/GetPersonaQuestionsResponseDto.kt (3)

1-5: 패키지 구조와 직렬화 임포트가 적절합니다.

DTO 패키지 위치와 kotlinx.serialization 임포트가 올바르게 설정되어 있습니다.


6-10: 응답 DTO 구현이 우수합니다.

@Serializable 어노테이션과 @SerialName을 사용한 JSON 필드 매핑이 적절하게 구현되어 있습니다. 필드명 차이(personaList vs personaDtoList)를 명확히 구분한 것이 좋습니다.


12-18: PersonaDto 구현이 적절합니다.

개별 persona 데이터를 위한 DTO 구조가 명확하고, 직렬화 어노테이션이 올바르게 적용되어 있습니다.

feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/screen/NamingScreen.kt (1)

60-75: 키보드 처리 및 검증 로직 개선이 잘 되었습니다!

imePadding() 추가로 키보드가 버튼을 가리지 않게 되었고, isOnBoardingSuccess 상태를 통한 버튼 활성화 로직이 더 명확해졌습니다.

feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/OnBoardingContract.kt (1)

16-22: 상태 관리 구조 개선이 잘 되었습니다.

PersonaEntity로의 변경과 isOnBoardingSuccess 플래그 추가로 온보딩 상태 관리가 더 명확해졌습니다.

core/designsystem/src/main/java/com/teamsolply/solply/designsystem/component/textfield/SolplyTextField.kt (1)

113-172: 닉네임 검증 로직이 개선되었습니다.

외부 콜백을 통한 검증 상태 전달과 지연 제거로 더 반응적인 사용자 경험을 제공합니다.

feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/OnBoardingScreen.kt (1)

74-76: 콜백 전파가 적절하게 구현되었습니다.

checkOnBoardingSuccess 콜백이 컴포넌트 계층을 통해 올바르게 전달되고 있습니다.

Also applies to: 89-90, 188-188

feature/onboarding/src/main/java/com/teamsolply/solply/onboarding/OnBoardingViewModel.kt (2)

24-39: Flow 기반 닉네임 검증이 잘 구현되었습니다.

500ms 디바운스로 불필요한 API 호출을 줄이고, 실패 시 적절히 처리하고 있습니다.


97-109: 안전한 null 처리가 잘 되어 있습니다.

중첩된 let을 사용하여 모든 필수 데이터가 있을 때만 API 호출이 실행됩니다.

data/maps/src/main/java/com/teamsolply/solply/maps/dto/SaveCourseRequestDto.kt (1)

1-1: 패키지 구조 정리 변경사항 승인

DTO 클래스들을 통합된 패키지 구조로 정리한 변경사항입니다. 기능적 변경 없이 단순한 패키지 재구성으로 적절합니다.

domain/maps/src/main/java/com/teamsolply/solply/maps/model/CourseInfoEntity.kt (1)

9-9: 썸네일 이미지 타입 변경 승인

로컬 리소스 ID에서 URL 문자열로 변경된 것은 서버 API 연동을 위한 적절한 변경입니다. 이미지 로딩 로직이 이 변경사항에 맞게 업데이트되었는지 확인이 필요합니다.

domain/maps/src/main/java/com/teamsolply/solply/maps/model/CourseDetailEntity.kt (2)

4-4: 코스 ID 타입 변경 승인

Int에서 Long으로 변경된 것은 더 큰 데이터셋을 처리할 수 있도록 하는 적절한 타입 표준화입니다.


12-12: 장소 ID 타입 변경 승인

Int에서 Long으로 변경된 것은 ID 타입 표준화의 일환으로 적절한 변경입니다.

feature/maps/src/main/java/com/teamsolply/solply/maps/component/bottomsheet/PlaceDetailBottomSheet.kt (3)

39-39: ImageInfo 임포트 추가 승인

더 구조화된 이미지 데이터 모델을 사용하기 위한 적절한 임포트입니다.


51-51: 이미지 URL 파라미터 타입 변경 승인

Int 리소스 ID에서 ImageInfo 객체로 변경된 것은 더 풍부한 이미지 정보를 제공하는 적절한 개선입니다.


265-265: SNS 플랫폼 속성명 변경 승인

도메인 모델의 속성명 변경에 맞춘 적절한 업데이트입니다.

data/maps/src/main/java/com/teamsolply/solply/maps/mapper/CourseInfoEntityMapper.kt (1)

7-17: 매퍼 함수 전체 구조 승인

전반적으로 적절한 매퍼 함수 구조입니다. DTO에서 Entity로의 변환 로직이 명확하게 구현되어 있습니다.

data/maps/src/main/java/com/teamsolply/solply/maps/mapper/CourseDetailEntityMapper.kt (1)

8-16: CourseDetailResponseDto 매퍼 함수가 올바르게 구현되었습니다.

DTO에서 Entity로의 변환 로직이 명확하고 직관적입니다.

feature/maps/src/main/java/com/teamsolply/solply/maps/component/bottomsheet/AddCourseBottomSheet.kt (1)

36-39: ID 타입의 일관성 있는 변경이 잘 적용되었습니다.

selectedPlaceItem과 콜백 함수들의 파라미터 타입을 Int에서 Long으로 변경한 것은 도메인 모델의 ID 타입 표준화와 일치합니다.

data/maps/src/main/java/com/teamsolply/solply/maps/dto/response/GetAddMyCourseResponseDto.kt (2)

6-10: CoursesResponseDto가 올바르게 구현되었습니다.

래퍼 클래스로서의 역할이 명확하고 직렬화 어노테이션이 적절히 적용되었습니다.


12-34: CourseDto 구조가 잘 설계되었습니다.

모든 필드가 적절한 타입으로 정의되어 있고, courseIdLong 타입으로 사용하여 전체 코드베이스의 ID 타입 일관성을 유지했습니다.

data/maps/src/main/java/com/teamsolply/solply/maps/mapper/PlaceDetailEntityMapper.kt (2)

19-19: null 처리가 잘 구현되었습니다.

contactNumber의 null 처리로 빈 문자열을 기본값으로 제공하는 것이 적절합니다.


28-40: ImageInfo와 SnsLink 매퍼가 올바르게 구현되었습니다.

중첩된 DTO 객체들의 변환 로직이 명확하고 직관적입니다.

data/maps/src/main/java/com/teamsolply/solply/maps/dto/response/GetPlaceDetailResponseDto.kt (3)

6-50: GetPlaceDetailResponseDto가 잘 구조화되었습니다.

모든 필드가 적절한 타입으로 정의되어 있고, @SerialName 어노테이션을 통해 JSON 직렬화가 올바르게 설정되었습니다. placeIdLong 타입으로 사용하여 타입 일관성을 유지했습니다.


27-31: 좌표 데이터의 String 타입 선택에 대한 확인이 필요합니다.

latitudelongitudeString 타입으로 정의되어 있는데, 이는 API 응답 형식에 맞춘 것으로 보입니다. 매퍼에서 Double로 변환할 때 예외 처리가 필요할 것입니다.

API 응답에서 좌표 데이터가 실제로 문자열 형식으로 제공되는지 확인해주세요.


52-68: 중첩된 DTO 클래스들이 올바르게 정의되었습니다.

ImageInfoDtoSnsLinkDto가 각각의 역할에 맞게 잘 구조화되어 있고, 직렬화 어노테이션이 적절히 적용되었습니다.

domain/maps/src/main/java/com/teamsolply/solply/maps/model/PlaceDetailEntity.kt (7)

6-6: ID 타입 변경 확인 완료

placeId의 타입이 Int에서 Long으로 변경되었습니다. 이는 더 큰 범위의 식별자를 지원하기 위한 합리적인 변경사항입니다.


9-9: 프로퍼티 이름 변경 확인 완료

descriptionintroduction으로 이름이 변경되었습니다. API 응답과의 일관성을 위한 변경으로 보입니다.


10-10: 이미지 정보 구조 개선

imageInfos의 타입이 List<Int>에서 List<ImageInfo>로 변경되어 더 구조화된 이미지 정보를 담을 수 있게 되었습니다. 이는 표시 순서와 URL 정보를 모두 포함할 수 있는 개선된 구조입니다.


16-16: SNS 링크 프로퍼티 이름 변경 확인

snsLinksnsLinks로 변경되어 복수형으로 더 명확하게 표현되었습니다.


19-19: 기본 장소 ID 타입 변경 확인

placeDefaultIdLong 타입으로 변경되어 다른 ID 필드들과 일관성을 유지합니다.


22-25: 새로운 ImageInfo 데이터 클래스 추가

이미지 정보를 구조화하기 위한 새로운 데이터 클래스가 추가되었습니다. displayOrderurl 필드를 통해 이미지 표시 순서와 URL을 명확하게 관리할 수 있습니다.


28-28: SNS 플랫폼 프로퍼티 이름 변경

SnsLink 데이터 클래스의 platformsnsPlatform으로 변경되어 더 명확한 의미를 전달합니다.

data/maps/src/main/java/com/teamsolply/solply/maps/dto/response/GetCourseDetailResponseDto.kt (3)

6-22: DTO 구조 및 직렬화 어노테이션 확인 완료

CourseDetailResponseDto의 구조가 잘 정의되어 있고, 모든 필드에 @SerialName 어노테이션이 올바르게 적용되어 있습니다. Long 타입의 ID 사용도 적절합니다.


24-58: CoursePlaceDto 구조 확인 완료

CoursePlaceDto의 필드들이 적절하게 정의되어 있고, 직렬화 어노테이션도 올바르게 적용되어 있습니다. 필드명과 타입이 일관성 있게 사용되고 있습니다.


47-51: API 응답 좌표 타입 확인 필요

GetCourseDetailResponseDtoGetPlaceDetailResponseDto에서 latitude/longitude가 모두 String으로 정의되어 있고, 도메인 모델인 CourseDetailEntity도 String을 사용하고 있습니다. 실제 서버 API 스펙에서 좌표가 문자열로 전달되는지 백엔드 팀에 확인해 주세요.
만약 API가 숫자(Double)를 반환한다면 DTO·도메인 모델을 Double로 변경하고, 매퍼에서의 toDouble() 변환을 제거해야 합니다.

– 확인 대상 위치:
• data/maps/src/main/java/com/teamsolply/solply/maps/dto/response/GetCourseDetailResponseDto.kt
• data/maps/src/main/java/com/teamsolply/solply/maps/dto/response/GetPlaceDetailResponseDto.kt
• domain/maps/src/main/java/com/teamsolply/solply/maps/model/CourseDetailEntity.kt
• domain/maps/src/main/java/com/teamsolply/solply/maps/model/PlaceDetailEntity.kt
• data/maps/src/main/java/com/teamsolply/solply/maps/mapper/CourseDetailEntityMapper.kt
• data/maps/src/main/java/com/teamsolply/solply/maps/mapper/PlaceDetailEntityMapper.kt

data/maps/src/main/java/com/teamsolply/solply/maps/source/MapsRemoteDataSource.kt (5)

3-6: 새로운 DTO 임포트 확인

필요한 DTO 클래스들이 적절하게 임포트되어 있습니다. 각 메서드에서 사용할 응답 타입들이 명확하게 정의되어 있습니다.


8-8: 장소 상세 정보 조회 메서드 추가

getPlaceDetail 메서드가 Long 타입 ID를 사용하여 장소 상세 정보를 조회하도록 정의되었습니다. 메서드명과 반환 타입이 명확합니다.


9-10: 북마크 관리 메서드 추가

장소 북마크 저장 및 삭제를 위한 메서드들이 추가되었습니다. 메서드명이 의미를 명확하게 전달하고 있습니다.


12-15: 사용자 코스 조회 메서드 추가

getAddMyCourse 메서드가 추가되어 특정 지역과 장소에 대한 코스 정보를 조회할 수 있습니다. 파라미터 구조가 명확하게 정의되어 있습니다.


17-17: 코스 상세 정보 조회 메서드 추가

getCourseDetail 메서드가 추가되어 코스 상세 정보를 조회할 수 있습니다. 반환 타입이 적절하게 정의되어 있습니다.

feature/maps/src/main/java/com/teamsolply/solply/maps/MapsContract.kt (3)

24-24: 선택된 장소 ID 타입 변경 확인

selectedPlaceInfoId의 타입이 Long?으로 변경되어 다른 ID 필드들과 일관성을 유지합니다.


50-50: Intent 및 SideEffect에서 ID 타입 변경 확인

모든 Intent와 SideEffect에서 placeId 파라미터의 타입이 Long으로 일관되게 변경되었습니다. 이는 도메인 모델과의 일관성을 유지하는 좋은 변경사항입니다.

Also applies to: 54-54, 88-88, 113-113


124-124: 기본 엔티티 프로퍼티 이름 업데이트

defaultPlaceDetailEntity에서 descriptionintroduction으로, snsLinksnsLinks로 변경되어 도메인 모델의 변경사항과 일치합니다.

Also applies to: 128-128

feature/maps/src/main/java/com/teamsolply/solply/maps/component/bottomsheet/EditCourseBottomSheet.kt (1)

58-58: 파라미터 타입 일관성 유지

selectedPlaceItem, singleCoursePlaceBookMarkClick, placeInfoClick, placeDetailClick의 타입이 Long으로 변경되어 전체 maps 모듈의 타입 일관성을 유지합니다. 컴포저블 내부 로직에는 영향을 주지 않는 적절한 타입 변경입니다.

Also applies to: 64-64, 66-66, 71-71

remote/maps/src/main/java/com/teamsolply/solply/maps/datasource/MapsRemoteDataSourceImpl.kt (2)

14-15: 검증 결과: .data 직접 접근은 안전하며 추가 에러 핸들링 불필요

  • GetPlaceDetailResponseDto 등 각 ResponseDto의 data 프로퍼티는 non-nullable로 선언되어 있어, JSON 필드 누락 시에는 직렬화 단계에서 예외가 발생합니다.
  • RemoteDataSource는 예외를 상위 레이어로 전파하는 설계이므로, 여기서 별도 try–catch 처리나 null 체크를 추가할 필요가 없습니다.

Likely an incorrect or invalid review comment.


17-27: 확인 완료: 북마크 메서드 .data 반환 타입은 Unit이 맞습니다
MapsServicepostPlaceBookMarkdeletePlaceBookMark 메서드 시그니처가 BaseResponse<Unit>를 반환하므로, .data의 타입은 Unit으로 구현이 올바릅니다.

feature/maps/src/main/java/com/teamsolply/solply/maps/MapsViewModel.kt (2)

43-65: 북마크 상태 관리 로직 개선됨

북마크 토글 시 UI 상태를 즉시 업데이트하고 비동기적으로 API를 호출하는 방식으로 개선되었습니다. 사용자 경험 측면에서 좋은 접근법입니다.


197-207: 매개변수 타입 변경 확인됨

placeId 매개변수가 Int에서 Long으로 변경되어 도메인 모델 일관성이 개선되었습니다.

feature/maps/src/main/java/com/teamsolply/solply/maps/MapsScreen.kt (4)

84-86: 매개변수 타입 일관성 개선

townIdtargetId 매개변수가 Long 타입으로 변경되어 도메인 모델과 일관성이 개선되었습니다.


106-106: 메서드 호출 업데이트 확인

getAllCourseInfo 메서드 호출이 새로운 매개변수 구조에 맞게 업데이트되었습니다.


285-287: 콜백 시그니처 타입 변경 확인

UI 콜백 함수들의 매개변수 타입이 Long으로 일관되게 변경되었습니다.


561-566: 속성 이름 변경 확인

descriptionintroduction으로, snsLinksnsLinks로 변경되어 도메인 모델 변경사항에 맞게 업데이트되었습니다.

domain/maps/src/main/java/com/teamsolply/solply/maps/repository/MapsRepository.kt (3)

9-11: 북마크 관리 메서드 추가 확인

새로운 북마크 저장 및 삭제 메서드가 추가되었습니다. 메서드 이름과 시그니처가 명확하고 일관됩니다.


13-16: 메서드 시그니처 개선

getAddMyCourse 메서드가 townIdplaceId 매개변수를 받도록 업데이트되어 더 구체적인 코스 조회가 가능합니다.


19-19: 매개변수 타입 일관성 확인

getCourseDetail 메서드의 매개변수가 Long 타입으로 변경되어 일관성이 개선되었습니다.

data/maps/src/main/java/com/teamsolply/solply/maps/repository/MapsRepositoryImpl.kt (4)

15-19: 에러 처리 및 매핑 패턴 개선

runCatchingmapCatching을 활용한 에러 처리 패턴이 잘 구현되었습니다. DTO를 엔티티로 변환하는 매핑 로직도 깔끔합니다.


21-27: 북마크 관리 메서드 구현 확인

북마크 저장 및 삭제 메서드가 원격 데이터소스를 적절히 호출하고 있습니다.


29-36: 코스 리스트 매핑 로직 확인

getAddMyCourse 메서드에서 응답 DTO의 courses 리스트를 엔티티로 매핑하는 로직이 올바르게 구현되었습니다.


39-43: 코스 상세 정보 조회 메서드 구현 확인

getCourseDetail 메서드가 원격 데이터소스 호출과 엔티티 매핑을 적절히 수행하고 있습니다.

remote/maps/src/main/java/com/teamsolply/solply/maps/service/MapsService.kt (3)

3-11: Import 문들이 올바르게 구성되어 있습니다.

새로운 DTO 클래스들과 Retrofit 어노테이션들이 적절하게 import되었습니다.


14-20: 장소 상세 정보 조회 메서드가 올바르게 구현되었습니다.

RESTful 규칙을 따르고 있으며, Long 타입 사용도 일관성 있게 적용되었습니다.


43-46: 코스 상세 정보 조회 메서드가 올바르게 구현되었습니다.

RESTful 규칙을 따르고 있으며, 다른 상세 조회 메서드들과 일관성 있게 구현되었습니다.

Comment on lines +48 to +51
private fun containsExtension(url: String, extension: String): Boolean {
val regex = Regex("\\.$extension(\\?|$)", RegexOption.IGNORE_CASE)
return regex.containsMatchIn(url)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

확장자 검출 로직 개선 필요

현재 정규식 기반 확장자 검출이 모든 URL 형태를 올바르게 처리하지 못할 수 있습니다. 쿼리 매개변수가 있는 복잡한 URL에서 문제가 발생할 수 있습니다.

더 robust한 확장자 검출 로직을 제안합니다:

 private fun containsExtension(url: String, extension: String): Boolean {
-    val regex = Regex("\\.$extension(\\?|$)", RegexOption.IGNORE_CASE)
-    return regex.containsMatchIn(url)
+    return try {
+        val uri = java.net.URI(url)
+        val path = uri.path ?: ""
+        path.substringAfterLast('.', "").equals(extension, ignoreCase = true)
+    } catch (e: Exception) {
+        // Fallback to regex if URI parsing fails
+        val regex = Regex("\\.$extension(\\?|$)", RegexOption.IGNORE_CASE)
+        regex.containsMatchIn(url)
+    }
 }
📝 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
private fun containsExtension(url: String, extension: String): Boolean {
val regex = Regex("\\.$extension(\\?|$)", RegexOption.IGNORE_CASE)
return regex.containsMatchIn(url)
}
private fun containsExtension(url: String, extension: String): Boolean {
return try {
val uri = java.net.URI(url)
val path = uri.path ?: ""
path.substringAfterLast('.', "").equals(extension, ignoreCase = true)
} catch (e: Exception) {
// Fallback to regex if URI parsing fails
val regex = Regex("\\.$extension(\\?|$)", RegexOption.IGNORE_CASE)
regex.containsMatchIn(url)
}
}
🤖 Prompt for AI Agents
In core/ui/src/main/java/com/teamsolply/solply/ui/image/AdaptationImage.kt
around lines 48 to 51, the current regex-based extension detection may fail on
complex URLs with query parameters. Improve the logic by parsing the URL to
extract the path component and then checking if the path ends with the given
extension, ignoring case. This approach avoids false matches in query strings
and ensures more accurate extension detection.

Comment on lines +25 to +32
val imageLoader = ImageLoader.Builder(context)
.components {
when {
isSvg -> add(SvgDecoder.Factory())
isGif -> add(GifDecoder.Factory())
}
}
.build()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

성능 최적화를 위한 ImageLoader 캐싱 필요

현재 ImageLoader가 매번 컴포지션마다 새로 생성되어 성능 문제가 발생할 수 있습니다. ImageLoader를 캐싱하거나 remember를 사용하여 최적화해야 합니다.

다음과 같이 수정하는 것을 권장합니다:

+    val imageLoader = remember(isSvg, isGif) {
+        ImageLoader.Builder(context)
+            .components {
+                when {
+                    isSvg -> add(SvgDecoder.Factory())
+                    isGif -> add(GifDecoder.Factory())
+                }
+            }
+            .build()
+    }
-    val imageLoader = ImageLoader.Builder(context)
-        .components {
-            when {
-                isSvg -> add(SvgDecoder.Factory())
-                isGif -> add(GifDecoder.Factory())
-            }
-        }
-        .build()
🤖 Prompt for AI Agents
In core/ui/src/main/java/com/teamsolply/solply/ui/image/AdaptationImage.kt
around lines 25 to 32, the ImageLoader is being recreated on every composition,
which can degrade performance. To fix this, cache the ImageLoader instance by
using a remember block or another caching mechanism so that it is only created
once and reused across compositions, improving efficiency.

Comment on lines +65 to 66
placeImageUrls.size
3
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

페이저 상태 초기화 검토 필요

placeImageUrls.size와 고정값 3이 모두 있는 것으로 보입니다. 이는 실수일 가능성이 있습니다.

다음과 같이 수정하세요:

-        placeImageUrls.size
-        3
+        placeImageUrls.size
🤖 Prompt for AI Agents
In
feature/maps/src/main/java/com/teamsolply/solply/maps/component/bottomsheet/PlaceDetailBottomSheet.kt
around lines 65 to 66, there is a discrepancy between using placeImageUrls.size
and the fixed value 3. This likely causes inconsistent pager state
initialization. Replace the fixed value 3 with placeImageUrls.size to ensure the
pager state correctly reflects the actual number of images.

title = this.title,
placeCount = this.placeCount,
thumbnailImage = this.thumbnailImage,
mainTag = this.mainTags.map { PlaceType.valueOf(it) },
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

열거형 변환 예외 처리 필요

PlaceType.valueOf(it)는 일치하는 열거형 값이 없을 때 예외를 발생시킬 수 있습니다. 안전한 변환을 위해 예외 처리를 추가하는 것을 고려하세요.

-        mainTag = this.mainTags.map { PlaceType.valueOf(it) },
+        mainTag = this.mainTags.mapNotNull { 
+            try { PlaceType.valueOf(it) } catch (e: IllegalArgumentException) { null }
+        },

또는 서버에서 올바른 열거형 값만 전달되도록 보장하세요.

📝 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
mainTag = this.mainTags.map { PlaceType.valueOf(it) },
mainTag = this.mainTags.mapNotNull {
try { PlaceType.valueOf(it) } catch (e: IllegalArgumentException) { null }
},
🤖 Prompt for AI Agents
In
data/maps/src/main/java/com/teamsolply/solply/maps/mapper/CourseInfoEntityMapper.kt
at line 13, the use of PlaceType.valueOf(it) can throw an exception if the
string does not match any enum constant. To fix this, add exception handling
around the valueOf call or use a safe conversion method that returns a default
or null value when no match is found, ensuring the code does not crash on
invalid input.


fun CourseDto.toEntity(): CourseInfoEntity {
return CourseInfoEntity(
courseId = this.courseId.toInt(),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

타입 변환 안전성 검토 필요

Long에서 Int로의 변환은 데이터 손실 가능성이 있습니다. 도메인 모델에서 courseIdLong으로 변경하는 것을 고려하세요.

-        courseId = this.courseId.toInt(),
+        courseId = this.courseId,

그리고 CourseInfoEntitycourseId 타입을 Long으로 변경하세요.

📝 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
courseId = this.courseId.toInt(),
courseId = this.courseId,
🤖 Prompt for AI Agents
In
data/maps/src/main/java/com/teamsolply/solply/maps/mapper/CourseInfoEntityMapper.kt
at line 9, the code converts courseId from Long to Int, which risks data loss.
To fix this, change the courseId type in the domain model to Long and update the
CourseInfoEntity's courseId type to Long as well, then remove the toInt()
conversion to maintain type consistency and safety.

latitude = latitude,
longitude = longitude,
placeTag = placeType,
placeDefaultId = placeDefaultId.toInt()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

String to Int 변환 시 예외 처리를 고려하세요.

placeDefaultId.toInt() 호출 시 String이 유효한 정수가 아닐 경우 NumberFormatException이 발생할 수 있습니다.

다음과 같이 안전한 변환을 적용하는 것을 권장합니다:

-        placeDefaultId = placeDefaultId.toInt()
+        placeDefaultId = placeDefaultId.toIntOrNull() ?: 0

또는 더 안전한 접근을 위해:

-        placeDefaultId = placeDefaultId.toInt()
+        placeDefaultId = runCatching { placeDefaultId.toInt() }.getOrDefault(0)
📝 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
placeDefaultId = placeDefaultId.toInt()
// before (line 30)
- placeDefaultId = placeDefaultId.toInt()
// after
+ placeDefaultId = placeDefaultId.toIntOrNull() ?: 0
🤖 Prompt for AI Agents
In
data/maps/src/main/java/com/teamsolply/solply/maps/mapper/CourseDetailEntityMapper.kt
at line 30, the direct call to placeDefaultId.toInt() can throw a
NumberFormatException if the string is not a valid integer. To fix this, replace
the direct conversion with a safe parsing method such as toIntOrNull(), and
handle the null case appropriately to avoid exceptions during runtime.

Comment on lines +17 to +18
latitude = latitude.toDouble(),
longitude = longitude.toDouble(),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

좌표 문자열의 Double 변환 시 예외 처리를 고려하세요.

latitude.toDouble()longitude.toDouble() 호출 시 문자열이 유효한 숫자가 아닐 경우 NumberFormatException이 발생할 수 있습니다.

안전한 변환을 위해 다음과 같이 수정하는 것을 권장합니다:

-        latitude = latitude.toDouble(),
-        longitude = longitude.toDouble(),
+        latitude = latitude.toDoubleOrNull() ?: 0.0,
+        longitude = longitude.toDoubleOrNull() ?: 0.0,
📝 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
latitude = latitude.toDouble(),
longitude = longitude.toDouble(),
latitude = latitude.toDoubleOrNull() ?: 0.0,
longitude = longitude.toDoubleOrNull() ?: 0.0,
🤖 Prompt for AI Agents
In
data/maps/src/main/java/com/teamsolply/solply/maps/mapper/PlaceDetailEntityMapper.kt
around lines 17 to 18, the calls to latitude.toDouble() and longitude.toDouble()
can throw NumberFormatException if the strings are not valid numbers. To fix
this, implement safe parsing by catching exceptions or using a safe conversion
method that returns a default value or null when parsing fails, ensuring the
application does not crash due to invalid coordinate strings.

return PlaceDetailEntity(
placeId = placeId,
placeName = placeName,
primaryTag = PlaceType.valueOf(primaryTag),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

PlaceType.valueOf() 호출 시 예외 처리가 필요합니다.

primaryTag 값이 유효한 PlaceType enum 값과 일치하지 않을 경우 IllegalArgumentException이 발생할 수 있습니다.

안전한 변환을 위해 다음과 같이 수정하는 것을 권장합니다:

-        primaryTag = PlaceType.valueOf(primaryTag),
+        primaryTag = PlaceType.entries.find { it.name == primaryTag } ?: PlaceType.EMPTY,

또는 runCatching을 사용하여:

-        primaryTag = PlaceType.valueOf(primaryTag),
+        primaryTag = runCatching { PlaceType.valueOf(primaryTag) }.getOrDefault(PlaceType.EMPTY),
📝 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
primaryTag = PlaceType.valueOf(primaryTag),
primaryTag = PlaceType.entries.find { it.name == primaryTag } ?: PlaceType.EMPTY,
Suggested change
primaryTag = PlaceType.valueOf(primaryTag),
primaryTag = runCatching { PlaceType.valueOf(primaryTag) }
.getOrDefault(PlaceType.EMPTY),
🤖 Prompt for AI Agents
In
data/maps/src/main/java/com/teamsolply/solply/maps/mapper/PlaceDetailEntityMapper.kt
at line 13, the call to PlaceType.valueOf(primaryTag) can throw an
IllegalArgumentException if primaryTag does not match any enum constant. To fix
this, add exception handling around the valueOf call to safely handle invalid
values, such as using a try-catch block or Kotlin's runCatching to catch the
exception and provide a default value or null instead of letting the exception
propagate.

Comment on lines +210 to 228
fun getAllCourseInfo(
townId: Long,
placeId: Long
) {
viewModelScope.launch {
mapsRepository.getAllCourses().onSuccess {
mapsRepository.getAddMyCourse(
townId = townId,
placeId = placeId
).onSuccess {
reduce {
copy(
courses = it.toPersistentList()
)
}
}.onFailure {
Log.d("asdasdasd", it.toString())
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

에러 처리 방식 개선 필요

에러 로깅에서 Log.d("asdasdasd", it.toString())를 사용하고 있습니다. 프로덕션 코드에서는 더 명확한 태그와 구조적인 에러 처리가 필요합니다.

다음과 같이 개선하는 것을 권장합니다:

-            }.onFailure {
-                Log.d("asdasdasd", it.toString())
+            }.onFailure { exception ->
+                Log.e("MapsViewModel", "Failed to get courses: ${exception.message}", exception)
+                // TODO: 사용자에게 에러 상태 알림 처리
🤖 Prompt for AI Agents
In feature/maps/src/main/java/com/teamsolply/solply/maps/MapsViewModel.kt
between lines 210 and 228, the error handling uses a vague log tag "asdasdasd"
and simple Log.d for logging exceptions. Replace this with a clear, descriptive
log tag relevant to the class or function, and use Log.e to log errors with the
throwable to provide structured and meaningful error information suitable for
production. This will improve error traceability and debugging.

Comment on lines +3 to +8
import com.teamsolply.solply.maps.mapper.toEntity
import com.teamsolply.solply.maps.model.CourseDetailEntity
import com.teamsolply.solply.maps.model.CourseInfoEntity
import com.teamsolply.solply.maps.model.NewCourseEntity
import com.teamsolply.solply.maps.model.Place
import com.teamsolply.solply.maps.model.PlaceDetailEntity
import com.teamsolply.solply.maps.model.SnsLink
import com.teamsolply.solply.maps.source.MapsRemoteDataSource
import com.teamsolply.solply.model.PlaceType
import toEntity
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

중복 import 문제

toEntity 함수가 두 번 import되고 있습니다. 8번째 줄의 import toEntity는 불필요해 보입니다.

다음과 같이 수정해주세요:

 import com.teamsolply.solply.maps.mapper.toEntity
 import com.teamsolply.solply.maps.model.CourseDetailEntity
 import com.teamsolply.solply.maps.model.CourseInfoEntity
 import com.teamsolply.solply.maps.model.PlaceDetailEntity
 import com.teamsolply.solply.maps.source.MapsRemoteDataSource
-import toEntity
📝 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
import com.teamsolply.solply.maps.mapper.toEntity
import com.teamsolply.solply.maps.model.CourseDetailEntity
import com.teamsolply.solply.maps.model.CourseInfoEntity
import com.teamsolply.solply.maps.model.NewCourseEntity
import com.teamsolply.solply.maps.model.Place
import com.teamsolply.solply.maps.model.PlaceDetailEntity
import com.teamsolply.solply.maps.model.SnsLink
import com.teamsolply.solply.maps.source.MapsRemoteDataSource
import com.teamsolply.solply.model.PlaceType
import toEntity
import com.teamsolply.solply.maps.mapper.toEntity
import com.teamsolply.solply.maps.model.CourseDetailEntity
import com.teamsolply.solply.maps.model.CourseInfoEntity
import com.teamsolply.solply.maps.model.PlaceDetailEntity
import com.teamsolply.solply.maps.source.MapsRemoteDataSource
🤖 Prompt for AI Agents
In
data/maps/src/main/java/com/teamsolply/solply/maps/repository/MapsRepositoryImpl.kt
around lines 3 to 8, there is a duplicate import of the toEntity function.
Remove the redundant import statement on line 8 that simply says 'import
toEntity' to eliminate the duplicate import issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

석찬🍚🦁 이석 찬찬찬찬 찬이야 ~ 완전 찬이야 ~

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 지도 api

1 participant