-
Notifications
You must be signed in to change notification settings - Fork 1
Feature/온보딩 프로필 #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Feature/온보딩 프로필 #28
The head ref may contain hidden characters: "feature/\uC628\uBCF4\uB529-\uD504\uB85C\uD544"
Conversation
백업용 입니다. 빌드 불가. 에러 투성이 입니다.
백업용 입니다. 빌드 불가. 에러 투성이 입니다.
hilt 부분에서 오류 발생, build 불가
Walkthrough닉네임 중복 확인 기능을 추가했다. Retrofit 서비스(NicknameService), 응답 모델(NicknameResponse, NicknameData), 리포지토리 인터페이스/구현(NicknameRepository, NicknameRepositoryImpl)을 도입하고 DI 모듈(ServiceModule, RepositoryModule)에 제공 메서드를 등록했다. UI에는 닉네임 변경 BottomSheet(ChangeNicknamePopup)와 ViewModel(ChangeNicknameViewModel)을 추가하여 프로필 화면에서 닉네임 변경 흐름을 연결했고, fragment_profile 레이아웃을 대대적으로 개편했다. ChatRoomFragment의 문법 오류를 수정했고, 신규 드로어블과 닉네임 팝업 레이아웃을 추가했다. Sequence Diagram(s)sequenceDiagram
participant UI as ChangeNicknamePopup
participant VM as ChangeNicknameViewModel
participant Repo as NicknameRepository
participant Impl as NicknameRepositoryImpl
participant Svc as NicknameService
participant API as Server
UI->>VM: checkNickname(nickname, onResult)
VM->>Repo: isNicknameDuplicated(nickname)
Repo->>Impl: isNicknameDuplicated(nickname)
Impl->>Svc: GET auth/check-nickname/{nickname}
Svc->>API: Request
API-->>Svc: NicknameResponse(success, data.available)
Svc-->>Impl: NicknameResponse
Impl-->>Repo: !data.available
Repo-->>VM: Boolean isDuplicated
VM-->>UI: onResult(isDuplicated)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes ✨ 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. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 14
🔭 Outside diff range comments (2)
app/src/main/java/umc/onairmate/ui/profile/ProfileFragment.kt (2)
94-99: PopupWindow 위치 계산 버그: 측정되지 않은 measuredWidth 사용
popupView.measuredWidth는 측정 전이므로 0이 되어 위치 계산이 틀어집니다. 표시 전 명시적으로 측정하세요.아래처럼 측정 후 좌표를 계산하는 방식을 권장합니다:
// 표시 전 반드시 측정 popupView.measure( View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) ) val popupWidth = popupView.measuredWidth val x = anchorX - popupWidth / 2 + anchorView.width / 2 val y = anchorY - anchorView.height - 20 popupWindow.showAtLocation(anchorView, Gravity.NO_GRAVITY, x, y)
101-103: 클릭 리스너 이중 등록 제거
onViewCreated에서ivTooltip에 토스트 리스너를 등록했고,showTooltip내부에서 다시ivTooltip.setOnClickListener를 설정하고 있습니다. 클릭 핸들러는 한 곳(보통 onViewCreated)에서만 설정하고, 그 핸들러에서showTooltip을 호출하도록 정리하세요.권장 형태:
// onViewCreated binding.ivTooltip.setOnClickListener { showTooltip(it, "추천 및 제재에 따라 인기도가 조정됩니다.") } // showTooltip 내부의 setOnClickListener 재등록 코드는 삭제
🧹 Nitpick comments (12)
app/src/main/res/drawable/bg_btn_edit.xml (3)
2-2: 색상 리소스 네이밍/의도 불일치 가능성 확인 필요 (@color/disable).리소스명이 “disable”이라 이 배경이 비활성(Disabled) 상태용인지, 일반 버튼 배경인지 혼동될 수 있습니다. 일반 상태용이라면 색상 리소스 혹은 파일명을 의도에 맞게 조정하는 것이 좋습니다(예: bg_btn_edit_disabled.xml 또는 @color/btn_edit_bg). 반대로 실제로 Disabled 전용이라면 사용처에서 상태 셀렉터를 통해 enabled/disabled를 구분해 주세요.
3-3: 하드코딩된 dp 대신 공용 dimen 리소스 사용 권장.여러 곳에서 동일 코너 값 재사용/일관성 확보를 위해 @Dimen으로 추출하는 것이 좋습니다.
다음 변경을 제안합니다:
- <corners android:radius="8dp"/> + <corners android:radius="@dimen/radius_8"/>그리고 values/dimens.xml에 다음을 추가해 주세요(파일이 없다면 새로 생성):
<resources> <dimen name="radius_8">8dp</dimen> </resources>
1-4: 버튼 상태(pressed/disabled) 및 리플 효과 고려.현재는 단일 상태 배경이라 터치 피드백/접근성이 부족할 수 있습니다. 셀렉터로 상태별 배경을 분리하거나(MaterialButton 사용 시 기본 리플 제공) RippleDrawable 적용을 권장합니다.
옵션 1) 셀렉터로 상태 분기(pressed/disabled):
-<shape xmlns:android="http://schemas.android.com/apk/res/android"> - <solid android:color="@color/disable" /> - <corners android:radius="8dp"/> -</shape> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- disabled --> + <item android:state_enabled="false"> + <shape> + <solid android:color="@color/disable"/> + <corners android:radius="@dimen/radius_8"/> + </shape> + </item> + <!-- pressed --> + <item android:state_pressed="true"> + <shape> + <!-- 적절한 눌림 색상 리소스로 교체 --> + <solid android:color="@color/btn_edit_pressed"/> + <corners android:radius="@dimen/radius_8"/> + </shape> + </item> + <!-- enabled (default) --> + <item> + <shape> + <!-- 기본 배경 색상 리소스로 교체 --> + <solid android:color="@color/btn_edit_enabled"/> + <corners android:radius="@dimen/radius_8"/> + </shape> + </item> +</selector>옵션 2) API 21+에서 리플 적용(drawable-v21에 별도 파일로 권장):
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?attr/colorControlHighlight"> <item> <shape> <solid android:color="@color/btn_edit_enabled"/> <corners android:radius="@dimen/radius_8"/> </shape> </item> </ripple>MaterialComponents를 쓰고 있다면, 가능하면 MaterialButton 스타일로 대체하는 것도 유지보수/일관성 측면에서 유리합니다.
app/src/main/java/umc/OnAirMate/ui/chat_room/ChatRoomFragment.kt (1)
86-90: onReady 시그니처 정리는 문제없습니다. 기본 videoId 매직 문자열은 상수로 추출을 권장합니다.하드코딩된 기본 videoId("CgCVZdcKcqY")는 상수로 추출해 재사용성과 가독성을 높이는 편이 좋습니다.
변경 예시(파일 외부 보조 코드):
companion object { private const val DEFAULT_VIDEO_ID = "CgCVZdcKcqY" }그리고 사용부:
val videoId = roomData.videoId ?: DEFAULT_VIDEO_IDapp/src/main/res/drawable/bg_input_edit_text.xml (1)
1-5: EditText 테두리 두께 0.2dp는 디바이스 해상도에 따라 거의 보이지 않을 수 있습니다.시각적 일관성을 위해 1dp로 상향 조정하거나, 디자인 가이드의 아웃라인 컬러(테마 속성)를 사용하는 것을 권장합니다.
예시 변경(diff):
- <stroke android:color="@color/black" android:width="0.2dp"/> + <stroke android:color="@color/black" android:width="1dp"/>app/src/main/res/layout/popup_change_nickname.xml (2)
23-31: LinearLayout에 ConstraintLayout 속성이 남아 있습니다. 제거하세요.
app:layout_constraint*속성은 LinearLayout에서 무의미합니다. 노이즈이므로 삭제를 권장합니다.적용(diff):
android:layout_marginTop="17dp" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/title_image"> + >
15-21: 텍스트 뷰 높이 고정(17dp)은 폰트 스케일에서 잘릴 수 있습니다. wrap_content로 변경 권장.하드 코딩된 높이는 접근성과 폰트 스케일 대응에 취약합니다.
적용(diff):
- android:layout_height="17dp" + android:layout_height="wrap_content"app/src/main/java/umc/onairmate/ui/profile/ProfileFragment.kt (1)
50-56: 주석 처리된 참여한 방 클릭 리스너: 의도 확인 필요프로덕션 릴리스 전까지 이 동작이 비활성화되어도 되는지 확인 부탁드립니다. 당장 비활성화가 필요하다면 TODO 주석과 이슈를 남겨 추후 복원을 추적하는 것이 좋습니다.
app/src/main/java/umc/OnAirMate/data/model/response/NicknameResponse.kt (1)
6-12: data class로 전환하여 가독성과 유틸리티 향상응답 DTO는 값 객체 성격이 강하므로
data class가 더 적합합니다(toString/equals/copy 제공).다음과 같이 변경을 제안합니다:
-class NicknameResponse ( +data class NicknameResponse( @SerializedName("success") val success: Boolean, @SerializedName("data") val data: NicknameData )app/src/main/java/umc/OnAirMate/data/api/NicknameService.kt (1)
11-15: API 설계 제안: 에러 응답 처리 강화서버가 4xx/5xx를 반환할 때 예외로 흐르는 대신 응답 본문을 점검하려면
Response<NicknameResponse>를 반환하는 형태가 유리합니다. 필요 시 Repository 레이어에서 성공/실패를 분기해 도메인 결과 타입으로 감싸는 패턴을 권장합니다.예:
@GET("auth/check-nickname/{nickname}") suspend fun checkNickname( @Path("nickname") nickname: String ): Response<NicknameResponse>app/src/main/java/umc/OnAirMate/ui/pop_up/ChangeNicknamePopup.kt (1)
65-78: 주석 처리된 중복 확인 로직 활성화 권장현재 닉네임 중복 확인 로직이 주석 처리되어 있어 기능이 동작하지 않습니다. Hilt 바인딩 이슈가 해결되면 이 코드를 활성화해야 합니다.
Hilt 바인딩 이슈가 해결되면 다음과 같이 코드를 활성화할 수 있습니다:
+ // Hilt 바인딩 이슈 해결 후 주석 해제 binding.checkNickname.setOnClickListener { val nickname = binding.editNickname.text.toString() if (nickname.length !in 3..10) { Toast.makeText(requireContext(), "닉네임은 3자 이상 10자 이하여야 합니다.", Toast.LENGTH_SHORT).show() return@setOnClickListener } -// viewLifecycleOwner.lifecycleScope.launch { -// val isDuplicated = withContext(Dispatchers.IO) { -// repository.isNicknameDuplicated(nickname) -// } -// -// if (isDuplicated) { -// Toast.makeText(requireContext(), "이미 사용 중인 닉네임입니다.", Toast.LENGTH_SHORT).show() -// binding.editNickname.text.clear() -// binding.checkNickname.setBackgroundResource(R.drawable.bg_btn_disabled) -// binding.checkNickname.isEnabled = false -// } else { -// Toast.makeText(requireContext(), "사용 가능한 닉네임입니다!", Toast.LENGTH_SHORT).show() -// } -// } + viewLifecycleOwner.lifecycleScope.launch { + val isDuplicated = withContext(Dispatchers.IO) { + repository.isNicknameDuplicated(nickname) + } + + if (isDuplicated) { + Toast.makeText(requireContext(), "이미 사용 중인 닉네임입니다.", Toast.LENGTH_SHORT).show() + binding.editNickname.text.clear() + binding.checkNickname.setBackgroundResource(R.drawable.bg_btn_disabled) + binding.checkNickname.isEnabled = false + } else { + Toast.makeText(requireContext(), "사용 가능한 닉네임입니다!", Toast.LENGTH_SHORT).show() + } + } }app/src/main/res/layout/fragment_profile.xml (1)
109-109: 하드코딩된 margin 값들의 일관성 검토여러 곳에서
layout_marginLeft를 사용하고 있는데, 일관성을 위해layout_marginStart를 사용하는 것이 좋습니다. 또한 하드코딩된 픽셀 값들이 다양한 화면 크기에서 일관된 레이아웃을 제공하는지 검토가 필요합니다.다음과 같이 개선할 수 있습니다:
- android:layout_marginLeft="214dp" + android:layout_marginStart="214dp" - android:layout_marginLeft="38dp" + android:layout_marginStart="38dp" - android:layout_marginLeft="38dp" + android:layout_marginStart="38dp" - android:layout_marginLeft="85dp" + android:layout_marginStart="85dp"그리고 반복되는 margin 값들을 dimens.xml에서 관리하는 것을 권장합니다.
Also applies to: 135-135, 159-159, 175-175
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (16)
app/src/main/java/umc/OnAirMate/data/api/NicknameService.kt(1 hunks)app/src/main/java/umc/OnAirMate/data/model/entity/NicknameData.kt(1 hunks)app/src/main/java/umc/OnAirMate/data/model/response/NicknameResponse.kt(1 hunks)app/src/main/java/umc/OnAirMate/data/repository/repository/NicknameRepository.kt(1 hunks)app/src/main/java/umc/OnAirMate/data/repository/repositoryImpl/NicknameRepositoryImpl.kt(1 hunks)app/src/main/java/umc/OnAirMate/ui/chat_room/ChatRoomFragment.kt(1 hunks)app/src/main/java/umc/OnAirMate/ui/pop_up/ChangeNicknamePopup.kt(1 hunks)app/src/main/java/umc/OnAirMate/ui/pop_up/ChangeNicknameViewModel.kt(1 hunks)app/src/main/java/umc/onairmate/module/RepositoryModule.kt(2 hunks)app/src/main/java/umc/onairmate/module/ServiceModule.kt(2 hunks)app/src/main/java/umc/onairmate/ui/profile/ProfileFragment.kt(1 hunks)app/src/main/res/drawable/bg_btn_edit.xml(1 hunks)app/src/main/res/drawable/bg_input_edit_text.xml(1 hunks)app/src/main/res/drawable/btn_logout_outline.xml(1 hunks)app/src/main/res/layout/fragment_profile.xml(4 hunks)app/src/main/res/layout/popup_change_nickname.xml(1 hunks)
🧰 Additional context used
🪛 detekt (1.23.8)
app/src/main/java/umc/OnAirMate/ui/pop_up/ChangeNicknamePopup.kt
[warning] 53-53: This empty block of code can be removed.
(detekt.empty-blocks.EmptyFunctionBlock)
[warning] 54-54: This empty block of code can be removed.
(detekt.empty-blocks.EmptyFunctionBlock)
app/src/main/java/umc/OnAirMate/ui/pop_up/ChangeNicknameViewModel.kt
[warning] 24-24: The caught exception is swallowed. The original exception could be lost.
(detekt.exceptions.SwallowedException)
🔇 Additional comments (7)
app/src/main/res/drawable/bg_btn_edit.xml (1)
1-4: 기본 구조는 올바릅니다.XML 문법/구성에 문제 없고, 단색 배경 + 8dp 라운드 처리도 정상입니다.
app/src/main/java/umc/OnAirMate/data/repository/repository/NicknameRepository.kt (1)
1-5: RepositoryModule을 SingletonComponent로 이동하고 리포지토리 범위를 Singleton으로 변경하세요.현재
app/src/main/java/umc/onairmate/module/RepositoryModule.kt가 ViewModelComponent에만 설치되어 있어, ViewModel 외부(예: 팝업, Activity 등)에서 NicknameRepository를 바로 주입하려 할 때 바인딩을 찾을 수 없습니다. 또한, 일반적으로 Repository는 앱 전역에서 재사용되므로 SingletonComponent에 바인딩하는 것이 권장됩니다.수정 사항:
- 파일:
app/src/main/java/umc/onairmate/module/RepositoryModule.kt
@InstallIn(ViewModelComponent::class)→@InstallIn(SingletonComponent::class)- 각
@Provides메서드에@Singleton애노테이션 추가- 선택사항:
@Binds+@Singleton조합의 추상 모듈로 전환하면 구현체 변경 시 편리합니다.예시 변경안 (추상 모듈 + Binds 활용):
- @Module - @InstallIn(ViewModelComponent::class) - object RepositoryModule { - @ViewModelScoped - @Provides - fun providesNicknameRepository( - nicknameService: NicknameService - ): NicknameRepository = NicknameRepositoryImpl(nicknameService) - } + @Module + @InstallIn(SingletonComponent::class) + abstract class RepositoryModule { + @Binds + @Singleton + abstract fun bindNicknameRepository( + impl: NicknameRepositoryImpl + ): NicknameRepository + + // FriendRepository, HomeRepository, ChatRoomRepository, TestRepository도 동일하게 추가 + }Likely an incorrect or invalid review comment.
app/src/main/res/drawable/btn_logout_outline.xml (1)
1-10: LGTM — 아웃라인 버튼 드로어블 정의가 명확합니다.투명 배경 + 1dp 스트로크 + 6dp 라운드 처리 적절합니다. 재사용성도 좋습니다.
app/src/main/java/umc/onairmate/module/ServiceModule.kt (1)
49-53: LGTM: NicknameService DI 바인딩 추가 적절
@Provides @Singleton+@NetworkModule.BaseRetrofit사용 패턴이 기존 서비스들과 일관되고, 재사용 가능한buildService<T>()확장 함수 활용도 좋습니다.app/src/main/java/umc/OnAirMate/data/model/entity/NicknameData.kt (1)
5-11: LGTM: 응답 엔티티 정의 적절필드명과
@SerializedName매핑이 명확하고,Boolean/String타입 선택도 합리적입니다.app/src/main/java/umc/onairmate/module/RepositoryModule.kt (1)
52-56: 닉네임 리포지토리 DI 설정 정상 구현
NicknameRepository에 대한 DI 바인딩이 올바르게 구성되었습니다. ViewModelComponent에 설치되어 ViewModel에서 주입 가능하며, 스코프도 적절히 설정되었습니다.app/src/main/res/layout/fragment_profile.xml (1)
299-303: 로고 크기 검토 필요하단 로고의 크기가
470dp x 89.26dp로 매우 크게 설정되어 있습니다. 대부분의 모바일 화면에서 이 크기가 적절한지 확인이 필요합니다.다양한 화면 크기에서 레이아웃이 올바르게 표시되는지 테스트해보시기 바랍니다. 특히 작은 화면에서 로고가 화면을 벗어나지 않는지 확인하세요.
| @@ -0,0 +1,16 @@ | |||
| package umc.onairmate.data.api | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
패키지-디렉터리 대소문자 불일치: OnAirMate vs onairmate
서비스 인터페이스 파일 경로 또한 umc/OnAirMate/...로 보입니다. 패키지 선언(umc.onairmate...)과 일치하도록 디렉터리를 umc/onairmate/...로 이동해 주세요.
아래 스크립트를 실행하여 실제 디렉터리 명칭이 패키지 선언과 일치하는지 확인해주세요.
🏁 Script executed:
#!/bin/bash
# NicknameService.kt 파일 위치 확인
echo "🔍 NicknameService.kt 위치:"
find app/src/main/java -type f -name "NicknameService.kt"
echo ""
# umc 디렉터리 하위 구조 및 대소문자 확인
echo "📂 app/src/main/java/umc 하위 디렉터리 목록:"
find app/src/main/java/umc -maxdepth 3 -type d | sortLength of output: 1528
파일 경로 대소문자 불일치 수정 필요
현재 app/src/main/java/umc/OnAirMate/data/api/NicknameService.kt 파일의 패키지 선언은
package umc.onairmate.data.api로, 디렉터리 이름(OnAirMate)과 맞지 않습니다.
- 이동 대상 파일
• 기존 경로:app/src/main/java/umc/OnAirMate/data/api/NicknameService.kt
• 수정 경로:app/src/main/java/umc/onairmate/data/api/NicknameService.kt
위와 같이 디렉터리 이름을 모두 소문자(onairmate)로 변경해 패키지 선언과 일치하도록 조치해주세요.
🤖 Prompt for AI Agents
In app/src/main/java/umc/OnAirMate/data/api/NicknameService.kt around line 1,
the package declaration uses all-lowercase "umc.onairmate.data.api" but the
directory is named "OnAirMate"; rename the filesystem directory
app/src/main/java/umc/OnAirMate to app/src/main/java/umc/onairmate (or move the
file into that all-lowercase path) so the package declaration and directory
structure match, then verify imports/build run; do not change the package line
if you perform the directory rename.
| @@ -0,0 +1,11 @@ | |||
| package umc.onairmate.data.model.entity | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
패키지-디렉터리 대소문자 불일치: OnAirMate vs onairmate
현재 파일 경로가 app/src/main/java/umc/OnAirMate/... 형태인데, 패키지는 umc.onairmate...입니다. 대소문자 불일치가 CI/리눅스(대소문자 구분 파일시스템)에서 컴파일 실패, 중복 패키지 생성, IDE 인덱싱 문제를 야기합니다. 동일한 소스셋 내 모든 경로를 umc/onairmate/...로 통일해 주세요(필요 시 git mv로 경로 정정).
다음 스크립트를 실행하여 디렉터리 경로와 패키지 선언의 대소문자 불일치 여부를 확인해 주세요.
🏁 Script executed:
#!/bin/bash
# umc 디렉터리 하위 구조 확인
find app/src/main/java/umc -maxdepth 4 -type d
echo "-----"
# 해당 파일의 패키지 선언 확인
head -n 5 app/src/main/java/umc/OnAirMate/data/model/entity/NicknameData.kt || trueLength of output: 2598
패키지 경로 대소문자 통일 필요
app/src/main/java/umc/OnAirMate/... 디렉터리 구조가 패키지 선언(umc.onairmate…)과 불일치하여 CI/리눅스 환경에서 컴파일 오류를 유발합니다. 모든 소스셋 경로를 소문자 umc/onairmate/...로 변경해야 합니다.
수정 안내:
- 현재 위치:
- app/src/main/java/umc/OnAirMate/...
- package 선언:
umc.onairmate…
- 변경 대상:
- 디렉터리명
OnAirMate→onairmate - 하위 모든 경로(
data,ui,module등)
- 디렉터리명
- 작업 예시:
git mv app/src/main/java/umc/OnAirMate app/src/main/java/umc/onairmate
- 변경 후, IDE나 빌드 스크립트에서 import 경로가 모두 소문자 패키지로 참조되는지 확인 바랍니다.
🤖 Prompt for AI Agents
app/src/main/java/umc/OnAirMate around lines 1-1: the filesystem path uses
"OnAirMate" while the package declaration is "umc.onairmate", causing
case-mismatch compile errors on CI/Linux; rename the top-level directory to
lowercase (onairmate) and apply the same lowercase change recursively to all
subdirectories (data, ui, module, etc.), update any affected import/package
references in source files and build scripts/IDE settings if necessary, refresh
the project/IDE and run a build to confirm fixes, then commit the renamed paths.
| @@ -0,0 +1,12 @@ | |||
| package umc.onairmate.data.model.response | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
패키지-디렉터리 대소문자 불일치: OnAirMate vs onairmate
이 파일도 경로가 umc/OnAirMate/...로 올라와 있습니다. 패키지와 디렉터리 경로를 모두 umc/onairmate/...로 정렬하지 않으면 플랫폼에 따라 빌드가 깨질 수 있습니다.
아래 스크립트를 실행해서 app/src/main/java/umc 하위 디렉터리 구조 및 NicknameResponse.kt 파일 경로를 확인해주세요.
🏁 Script executed:
#!/bin/bash
echo "📂 app/src/main/java/umc 하위 디렉터리 리스트:"
find app/src/main/java/umc -type d | sed 's/^/ - /'
echo ""
echo "📄 NicknameResponse.kt 위치 확인:"
find app/src/main/java/umc -type f -name "NicknameResponse.kt" -printLength of output: 2852
경로·패키지 대소문자 불일치 수정 필요
Linux 등 대소문자를 구분하는 파일시스템에서 빌드가 깨질 수 있습니다.
아래 작업을 통해 디렉터리 경로와 package 선언을 모두 소문자(umc/onairmate/...)로統一하세요.
• 디렉터리명 변경
app/src/main/java/umc/OnAirMate/…→app/src/main/java/umc/onairmate/…
• Kotlin 파일 위치 이동app/src/main/java/umc/OnAirMate/data/model/response/NicknameResponse.kt
→app/src/main/java/umc/onairmate/data/model/response/NicknameResponse.kt
•package선언 및 임포트 경로 수정
- package umc.onairmate.data.model.response
+ package umc.onairmate.data.model.response(이외 관련된 모든 파일의 경로 및 패키지 선언도 함께 정렬)
위 변경 후 반드시 전체 빌드 및 의존 관계를 확인해주세요.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In app/src/main/java/umc/OnAirMate/data/model/response/NicknameResponse.kt
around line 1, the package path uses mixed case ("umc.OnAirMate") which will
break builds on case-sensitive filesystems; rename the directory
app/src/main/java/umc/OnAirMate to app/src/main/java/umc/onairmate, move this
Kotlin file to the new lowercase path, update the package declaration at the top
of the file to "package umc.onairmate.data.model.response", and update any
import statements and other files referencing the old package to the new
lowercase package; after changes run a full clean build to verify and fix any
remaining references.
| package umc.onairmate.data.repository | ||
|
|
||
| interface NicknameRepository { | ||
| suspend fun isNicknameDuplicated(nickname: String): Boolean | ||
| } No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
패키지/디렉터리 구조 불일치 가능성(가독성 및 유지보수 관점).
파일 경로가 .../OnAirMate/.../repository/repository/NicknameRepository.kt처럼 보이는데, 패키지는 umc.onairmate.data.repository입니다. 디렉터리 대소문자/중복(segment: repository/repository) 불일치는 IDE 네비게이션과 팀 컨벤션 면에서 혼란을 야기할 수 있습니다. 패키지 구조와 폴더 구조를 일치시키는 것을 권장합니다.
검증 스크립트:
🏁 Script executed:
#!/bin/bash
# Kotlin 소스의 패키지 선언과 실제 디렉토리 구조 불일치 의심 지점 탐색
echo "== Package declarations vs path hints =="
fd -e kt | rg -n 'package\\s+umc\\.onairmate\\.' -NLength of output: 144
🏁 Script executed:
#!/bin/bash
echo "== NicknameRepository.kt 파일 위치 확인 =="
fd -e kt NicknameRepository.kt
echo ""
echo "== 패키지 선언 확인 (파일 상단 5줄) =="
fd -e kt NicknameRepository.kt -x sed -n '1,5p' {}
echo ""
echo "== 디렉터리 구조 확인 =="
fd -e kt NicknameRepository.kt -x dirname {}Length of output: 622
패키지 경로와 디렉터리 구조 불일치 수정 필요
현재 app/src/main/java/umc/OnAirMate/data/repository/repository/NicknameRepository.kt 경로가
package umc.onairmate.data.repository 선언과 맞지 않습니다. Java/Kotlin 패키지 네이밍 컨벤션에 따라:
- 디렉터리명은 모두 소문자여야 합니다 (
OnAirMate→onairmate). - 중복된
repository디렉터리를 제거해 패키지 구조를 일치시켜야 합니다.
수정 제안:
app/src/main/java/umc/OnAirMate폴더명 →app/src/main/java/umc/onairmate.../repository/repository/NicknameRepository.kt파일을.../repository/NicknameRepository.kt로 이동
🤖 Prompt for AI Agents
In
app/src/main/java/umc/OnAirMate/data/repository/repository/NicknameRepository.kt
(lines 1-5) the declared package "umc.onairmate.data.repository" does not match
the filesystem path (contains "OnAirMate" with uppercase and a duplicated
"repository" directory); move the file to
app/src/main/java/umc/onairmate/data/repository/NicknameRepository.kt (rename
the OnAirMate folder to onairmate and remove the extra repository directory) so
the directory structure matches the package declaration, and verify the package
line remains "package umc.onairmate.data.repository" after the move.
| } catch (e: Exception) { | ||
| Log.e("NicknameRepository", "닉네임 중복 검사 실패", e) | ||
| // 실패 시 기본값 false 또는 true 선택 가능 (보통 실패는 중복 아님 false로 처리) | ||
| false | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
예외 처리 로직 검토 필요
네트워크 오류나 서버 응답 파싱 실패 시 false를 반환하여 "중복 아님"으로 처리하는 것은 보안상 위험할 수 있습니다. 사용자가 이미 사용 중인 닉네임을 사용할 수 있게 되는 경우가 발생할 수 있습니다.
다음과 같이 예외를 상위로 전파하거나 명확한 오류 상태를 반환하는 것을 권장합니다:
override suspend fun isNicknameDuplicated(nickname: String): Boolean {
- return try {
+ try {
val response = api.checkNickname(nickname)
// available == true 면 사용 가능한 닉네임, 중복 아님 → 따라서 중복 여부는 반대(!)
- !response.data.available
+ return !response.data.available
} catch (e: Exception) {
Log.e("NicknameRepository", "닉네임 중복 검사 실패", e)
- // 실패 시 기본값 false 또는 true 선택 가능 (보통 실패는 중복 아님 false로 처리)
- false
+ throw e // 상위에서 처리하도록 전파
}
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| } catch (e: Exception) { | |
| Log.e("NicknameRepository", "닉네임 중복 검사 실패", e) | |
| // 실패 시 기본값 false 또는 true 선택 가능 (보통 실패는 중복 아님 false로 처리) | |
| false | |
| } | |
| override suspend fun isNicknameDuplicated(nickname: String): Boolean { | |
| try { | |
| val response = api.checkNickname(nickname) | |
| // available == true 면 사용 가능한 닉네임, 중복 아님 → 따라서 중복 여부는 반대(!) | |
| return !response.data.available | |
| } catch (e: Exception) { | |
| Log.e("NicknameRepository", "닉네임 중복 검사 실패", e) | |
| throw e // 상위에서 처리하도록 전파 | |
| } | |
| } |
| <shape xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| <solid android:color="@color/disable" /> | ||
| <corners android:radius="8dp"/> | ||
| </shape> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
다크 모드 지원 및 명암 대비(접근성) 확인 요청.
@color/disable가 values-night에 Night 변형을 갖지 않으면 다크 모드에서 대비가 무너질 수 있습니다. 버튼 내부 텍스트/아이콘과의 대비(AA/AAA)도 점검을 권장합니다.
다음 스크립트로 색상 정의와 night 변형 존재 여부를 확인해 주세요:
🏁 Script executed:
#!/bin/bash
# colors.xml 파일 위치 탐색
fd -a colors.xml
# disable 색상 정의 검색
rg -n '<color[^>]*name="disable"' -A 2
# values-night 디렉터리 내 disable 색상 정의 검색
rg -n '<color[^>]*name="disable"' app | rg 'values-night' -n -A 2 || trueLength of output: 417
다크 모드용 disable 색상 오버라이드 및 접근성 대비 보강 필요
현재 app/src/main/res/values/colors.xml에 정의된 disable 색상(#9FA4A9)이 values-night 디렉터리에서 오버라이드되지 않아 다크 모드 시 대비가 부족할 수 있습니다. 버튼 텍스트/아이콘과의 대비(AA/AAA) 충족을 위해 아래 조치를 적용해주세요:
- app/src/main/res/values-night/colors.xml 파일 생성 또는 수정
•<color name="disable">#<적절한 다크 모드 색상></color>추가 - 버튼 내부 텍스트/아이콘과 함께 WCAG AA/AAA 대비비율 확인
🤖 Prompt for AI Agents
In app/src/main/res/drawable/bg_btn_edit.xml lines 1-4, the background uses the
color named "disable" which is only defined in values (light) resources and not
overridden for dark mode; create or update
app/src/main/res/values-night/colors.xml to add a <color name="disable"> with a
darker/appropriate hex value for night mode, then verify and adjust that color
so the button text/icons meet WCAG AA/AAA contrast ratios against this
background (use a contrast checker and tweak the hex until the required ratio is
met).
| <TextView | ||
| android:layout_width="278dp" | ||
| android:layout_height="17dp" | ||
| android:text="닉네임 수정" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
하드코딩된 문자열을 strings.xml로 추출하세요.
국제화, 접근성, 일관된 관리 차원에서 문자열 리소스로 이동이 필요합니다.
예시(strings.xml 추가):
<string name="title_edit_nickname">닉네임 수정</string>
<string name="label_nickname">닉네임</string>
<string name="guide_nickname_length">(3~10자 이내로 입력해주세요)</string>
<string name="action_check_duplication">중복 확인</string>
<string name="desc_nickname_shop">*최소 1회 무료\n추가 변경권은 M:Shop 에서 구매 가능</string>
<string name="action_done">완료</string>
<string name="hint_nickname">닉네임을 입력하세요</string>해당 레이아웃의 텍스트를 위 리소스로 교체해 주세요(예: android:text="@string/title_edit_nickname" 등).
Also applies to: 38-39, 60-61, 72-73, 90-90, 101-101
🤖 Prompt for AI Agents
In app/src/main/res/layout/popup_change_nickname.xml around line 18 (and also
lines 38-39, 60-61, 72-73, 90, 101), several UI strings are hardcoded; extract
each literal into res/values/strings.xml using meaningful resource names (e.g.,
title_edit_nickname, label_nickname, guide_nickname_length,
action_check_duplication, desc_nickname_shop, action_done, hint_nickname), add
the corresponding <string> entries, and replace the android:text attributes in
the layout with references like @string/title_edit_nickname (do the same for any
other hardcoded text in the listed lines). Ensure existing line-specific texts
map to appropriately named keys and update any newline or formatting to use \n
in the string resource.
| <EditText | ||
| android:id="@+id/edit_nickname" | ||
| android:layout_width="180dp" | ||
| android:layout_height="20dp" | ||
| android:background="@drawable/bg_input_edit_text" | ||
| android:maxLines="1" | ||
| android:textSize="14sp" | ||
| android:layout_marginLeft="3dp"/> | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
EditText 접근성/사용성 개선: 높이, 패딩, inputType, 길이 제한, 힌트 추가를 권장합니다.
현재 높이 20dp는 터치/가독성에 부족합니다. 또한 패딩과 inputType, maxLength가 없어 UX가 떨어집니다.
적용(diff):
<EditText
android:id="@+id/edit_nickname"
android:layout_width="180dp"
- android:layout_height="20dp"
+ android:layout_height="wrap_content"
android:background="@drawable/bg_input_edit_text"
- android:maxLines="1"
- android:textSize="14sp"
- android:layout_marginLeft="3dp"/>
+ android:maxLines="1"
+ android:singleLine="true"
+ android:inputType="textPersonName"
+ android:imeOptions="actionDone"
+ android:maxLength="10"
+ android:textSize="14sp"
+ android:paddingStart="12dp"
+ android:paddingEnd="12dp"
+ android:layout_marginStart="3dp"
+ android:hint="@string/hint_nickname"/>참고: @string/hint_nickname 추가가 필요합니다(아래 별도 코멘트 참조).
📝 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.
| <EditText | |
| android:id="@+id/edit_nickname" | |
| android:layout_width="180dp" | |
| android:layout_height="20dp" | |
| android:background="@drawable/bg_input_edit_text" | |
| android:maxLines="1" | |
| android:textSize="14sp" | |
| android:layout_marginLeft="3dp"/> | |
| <EditText | |
| android:id="@+id/edit_nickname" | |
| android:layout_width="180dp" | |
| android:layout_height="wrap_content" | |
| android:background="@drawable/bg_input_edit_text" | |
| android:maxLines="1" | |
| android:singleLine="true" | |
| android:inputType="textPersonName" | |
| android:imeOptions="actionDone" | |
| android:maxLength="10" | |
| android:textSize="14sp" | |
| android:paddingStart="12dp" | |
| android:paddingEnd="12dp" | |
| android:layout_marginStart="3dp" | |
| android:hint="@string/hint_nickname"/> |
| android:background="@drawable/bg_input_edit_text" | ||
| android:maxLines="1" | ||
| android:textSize="14sp" | ||
| android:layout_marginLeft="3dp"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
RTL 대응: left 대신 start 속성을 사용하세요.
layout_marginLeft는 RTL 환경에서 올바르게 동작하지 않습니다. layout_marginStart로 교체를 권장합니다.
적용(diff):
- android:layout_marginLeft="3dp"/>
+ android:layout_marginStart="3dp"/>- android:layout_marginLeft="3dp"/>
+ android:layout_marginStart="3dp"/>- android:layout_marginLeft="5dp"/>
+ android:layout_marginStart="5dp"/>Also applies to: 63-63, 76-76
🤖 Prompt for AI Agents
In app/src/main/res/layout/popup_change_nickname.xml around lines 54, 63 and 76,
replace the RTL-unsafe attribute android:layout_marginLeft with
android:layout_marginStart so margins respect RTL layouts; update each
occurrence to use layout_marginStart (keeping the same value) and remove the
layout_marginLeft attribute.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (2)
app/src/main/res/layout/fragment_profile.xml (1)
293-293: 중복 코멘트: 레이아웃 참조 오류Line 293에서
android:layout_marginStart="16dp"로 올바른 치수값을 사용하고 있어 이전 리뷰 코멘트의 문제는 해결되었습니다.app/src/main/java/umc/OnAirMate/ui/pop_up/ChangeNicknamePopup.kt (1)
30-31: [중복 코멘트] NicknameRepository 주입 복원 필요현재
NicknameRepository주입이 주석 처리되어 있어 실제 중복 확인 API 호출이 불가능합니다. 이는 PR 목표에서 언급된 Hilt 바인딩 오류와 관련이 있을 수 있습니다.-// @Inject -// lateinit var repository: NicknameRepository + @Inject + lateinit var repository: NicknameRepository
🧹 Nitpick comments (3)
app/src/main/java/umc/onairmate/ui/profile/ProfileFragment.kt (2)
9-9: 불필요한 import 제거 필요
androidx.core.content.ContentProviderCompat.requireContext는 사용되지 않는 import입니다.-import androidx.core.content.ContentProviderCompat.requireContext
37-38: SharedPreferences 기본값 처리 개선 권장닉네임을 가져올 때 기본값으로 "user"를 사용하고 있지만, null 안전성을 위해 더 명확한 처리를 권장합니다.
-nickname = spf.getString("nickname","user")!! +nickname = spf.getString("nickname", "user") ?: "user"app/src/main/java/umc/OnAirMate/ui/pop_up/ChangeNicknamePopup.kt (1)
81-97: 중복된 주석 코드 정리 필요동일한 repository 기반 중복 확인 로직이 두 번 주석 처리되어 있습니다. 코드 가독성을 위해 중복 제거를 권장합니다.
- /* - viewLifecycleOwner.lifecycleScope.launch { - val isDuplicated = withContext(Dispatchers.IO) { - repository.isNicknameDuplicated(nickname) - } - - if (isDuplicated) { - Toast.makeText(requireContext(), "이미 사용 중인 닉네임입니다.", Toast.LENGTH_SHORT).show() - binding.editNickname.text.clear() - binding.checkNickname.setBackgroundResource(R.drawable.bg_btn_disabled) - binding.checkNickname.isEnabled = false - } else { - Toast.makeText(requireContext(), "사용 가능한 닉네임입니다!", Toast.LENGTH_SHORT).show() - } - } - */ - -// viewLifecycleOwner.lifecycleScope.launch { -// val isDuplicated = withContext(Dispatchers.IO) { -// repository.isNicknameDuplicated(nickname) -// } -// -// if (isDuplicated) { -// Toast.makeText(requireContext(), "이미 사용 중인 닉네임입니다.", Toast.LENGTH_SHORT).show() -// binding.editNickname.text.clear() -// binding.checkNickname.setBackgroundResource(R.drawable.bg_btn_disabled) -// binding.checkNickname.isEnabled = false -// } else { -// Toast.makeText(requireContext(), "사용 가능한 닉네임입니다!", Toast.LENGTH_SHORT).show() -// } -// }Also applies to: 98-112
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
app/src/main/java/umc/OnAirMate/ui/pop_up/ChangeNicknamePopup.kt(1 hunks)app/src/main/java/umc/onairmate/ui/profile/ProfileFragment.kt(2 hunks)app/src/main/res/layout/fragment_profile.xml(4 hunks)
🔇 Additional comments (11)
app/src/main/res/layout/fragment_profile.xml (6)
7-9: 프로필 화면 루트 레이아웃 개선 완료배경색, 상단 마진, ID 추가로 레이아웃 구조가 명확해졌습니다.
19-19: 폰트 패밀리 업데이트 적용 완료Pretendard Bold 폰트로 일관성 있는 타이포그래피를 구현했습니다.
70-82: 프로필 이미지 영역 마진 조정 완료프로필 이미지와 변경 버튼의 상단 마진이 적절히 증가되어 시각적 여백이 개선되었습니다.
84-177: 개인정보 섹션 구조화 완료개인정보 영역을 별도 컨테이너로 분리하고 닉네임과 인기도 요소를 체계적으로 구성했습니다. 닉네임 편집 기능과의 연동을 위한 레이아웃 구조가 잘 준비되었습니다.
179-283: 나의 활동 섹션 신규 추가 완료참여한 방, 차단 리스트, 의견 보내기, 좋아한 컬렉션 등의 기능들이 일관성 있는 레이아웃으로 구성되었습니다. 각 항목마다 화살표 아이콘과 적절한 클릭 영역이 제공됩니다.
285-317: 하단 로고 영역 레이아웃 개선로그아웃 버튼 추가와 함께 하단 영역이 vertical 방향으로 재구성되어 사용자 경험이 향상되었습니다.
app/src/main/java/umc/onairmate/ui/profile/ProfileFragment.kt (2)
27-28: ViewModel 의존성 주입 구현 완료ChangeNicknameViewModel이 올바르게 주입되어 닉네임 중복 확인 기능을 지원합니다.
46-62: 닉네임 편집 플로우 구현 완료닉네임 레이아웃 클릭 시 ChangeNicknamePopup을 표시하고, 콜백을 통해 ViewModel의 중복 확인 기능과 연결하는 구조가 잘 구현되었습니다.
app/src/main/java/umc/OnAirMate/ui/pop_up/ChangeNicknamePopup.kt (3)
45-59: 입력 검증 및 UI 상태 관리 로직 완료TextWatcher를 통한 실시간 입력 검증과 버튼 상태 업데이트가 잘 구현되었습니다.
61-80: 콜백 기반 중복 확인 로직 구현 완료외부 콜백을 통한 중복 확인과 결과 처리 로직이 적절히 구현되어 있습니다. UI 상태 업데이트도 올바르게 처리됩니다.
115-118: 메모리 누수 방지 처리 완료onDestroyView에서 바인딩을 적절히 해제하여 메모리 누수를 방지합니다.
체크리스트
📝작업 내용
이번 PR에서 작업한 내용을 간략히 설명해주세요
닉네임 변경, 닉네임 중복 확인 관련하여 작업 중 문제 발생
스크린샷
작업한 화면기능의 스크린샷을 첨부해 주세요
(ui상 변화가 없으면 생략가능)
💬리뷰 요구사항(선택)
리뷰어가 특별히 봐주었으면 하는 부분이나 함께 고민해봐야할 부분이 있다면 작성해주세요
hilt 부분에서 오류가 나는 것 같습니다.
clean project > rebuild project
Invalid caches > sync > clean project > rebuild projec 를 해도 같은 오류 발생
오류 문구 아래와 같음
/Users/jisun/Documents/Android/app/build/generated/hilt/component_sources/debug/umc/onairmate/OnAirMateApplication_HiltComponents.java:165: error: [Dagger/MissingBinding] umc.onairmate.data.repository.NicknameRepository cannot be provided without an @Provides-annotated method.
public abstract static class SingletonC implements FragmentGetContextFix.FragmentGetContextFixEntryPoint,
^
Note: A binding for umc.onairmate.data.repository.NicknameRepository exists in umc.onairmate.OnAirMateApplication_HiltComponents.ViewModelC:
umc.onairmate.data.repository.NicknameRepository is injected at
[umc.onairmate.OnAirMateApplication_HiltComponents.FragmentC] umc.onairmate.ui.pop_up.ChangeNicknamePopup.repository
umc.onairmate.ui.pop_up.ChangeNicknamePopup is injected at
[umc.onairmate.OnAirMateApplication_HiltComponents.FragmentC] umc.onairmate.ui.pop_up.ChangeNicknamePopup_GeneratedInjector.injectChangeNicknamePopup(umc.onairmate.ui.pop_up.ChangeNicknamePopup) [umc.onairmate.OnAirMateApplication_HiltComponents.SingletonC → umc.onairmate.OnAirMateApplication_HiltComponents.ActivityRetainedC → umc.onairmate.OnAirMateApplication_HiltComponents.ActivityC → umc.onairmate.OnAirMateApplication_HiltComponents.FragmentC]
Summary by CodeRabbit
New Features
UI/Style
Changes
Bug Fixes