Skip to content

[SPM-433] 프로필 수정 및 회원 관리 구현#30

Merged
Sangyoon98 merged 5 commits into
devfrom
SPM-433
Nov 8, 2025
Merged

[SPM-433] 프로필 수정 및 회원 관리 구현#30
Sangyoon98 merged 5 commits into
devfrom
SPM-433

Conversation

@Sangyoon98
Copy link
Copy Markdown
Member

@Sangyoon98 Sangyoon98 commented Nov 7, 2025

📝 Summary

프로필 수정 및 회원 관리 구현

🙏 Question & PR point

📬 Reference

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 직원 목록 조회 및 관리 기능 추가
    • 사용자 프로필 업데이트 기능 강화
    • 회원가입 플로우 개선
  • 개선 사항

    • 설정 화면의 프로필 편집 기능 개선
    • Material Design 3 라이브러리 적용으로 UI 디자인 현대화
    • 사용자 정보 관리 체계 개선

@Sangyoon98 Sangyoon98 changed the base branch from main to dev November 7, 2025 19:20
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 7, 2025

Important

Review skipped

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

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

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

변경 사항 분석

요약

사용자 인증 및 관리 기능을 재구조화하여 User 모델을 auth에서 user 기능 패키지로 이동하고, 직원 목록 관리, 프로필 편집, 대시보드 개선 등 새로운 기능을 추가했습니다. Material3 의존성이 추가되었습니다.

변경 사항

집단 / 파일(들) 변경 요약
의존성 및 버전 관리
app/build.gradle.kts, gradle/libs.versions.toml
Material3 라이브러리 의존성 추가 (1.4.0)
User 모델 이동
app/src/main/java/com/sampoom/android/feature/user/domain/model/User.kt, app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/...UseCase.kt (LoginUseCase, SignUpUseCase)
User 데이터 클래스를 auth.domain에서 user.domain으로 재배치, 모든 관련 임포트 업데이트
인증 API 및 매퍼 리팩토링
app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt, app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt, app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt
GetProfile/UpdateProfile 엔드포인트 제거, SignUp 엔드포인트 추가, 로그인 응답에서 User 직접 생성
User 저장소 및 유스케이스 생성
app/src/main/java/com/sampoom/android/feature/user/domain/repository/UserRepository.kt, app/src/main/java/com/sampoom/android/feature/user/domain/usecase/...UseCase.kt (GetProfile, GetStored, Update, Edit, GetEmployee)
새로운 UserRepository 인터페이스 및 구현, 프로필/직원 관리 유스케이스 추가
User API 및 DTO
app/src/main/java/com/sampoom/android/feature/user/data/remote/api/UserApi.kt, app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/...Dto.kt
프로필, 직원 편집, 직원 목록 조회 엔드포인트 정의, 관련 DTO 추가
직원 관리 기능
app/src/main/java/com/sampoom/android/feature/user/domain/model/Employee.kt, app/src/main/java/com/sampoom/android/feature/user/data/paging/EmployeePagingSource.kt, app/src/main/java/com/sampoom/android/feature/user/ui/EmployeeListScreen.kt, app/src/main/java/com/sampoom/android/feature/user/ui/EmployeeList...
직원 목록 조회, 페이징, 편집 기능 구현 (Employee 도메인 모델, UI 스크린, ViewModel, 이벤트/상태)
프로필 편집 UI
app/src/main/java/com/sampoom/android/feature/user/ui/UpdateProfileBottomSheet.kt, app/src/main/java/com/sampoom/android/feature/user/ui/UpdateProfileViewModel.kt, app/src/main/java/com/sampoom/android/feature/user/ui/EditEmployeeBottomSheet.kt, app/src/main/java/com/sampoom/android/feature/user/ui/EditEmployeeViewModel.kt
사용자명 및 직원 위치 편집을 위한 새로운 바텀 시트 UI 컴포넌트 추가
대시보드 및 설정 개선
app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt, app/src/main/java/com/sampoom/android/feature/dashboard/ui/SettingScreen.kt, app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt, app/src/main/java/com/sampoom/android/feature/dashboard/ui/SettingViewModel.kt
직원 관리 버튼 추가, 프로필 편집 바텀 시트 통합, setting 패키지를 dashboard로 이동, User 역할 기반 권한 확인
인증 흐름 업데이트
app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt, app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt, app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt
GetProfileUseCase 의존성 추가, 로그인/가입 후 프로필 자동 조회, getProfile 메서드 제거
네비게이션 및 핵심 업데이트
app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt, app/src/main/java/com/sampoom/android/core/preferences/AuthPreferences.kt, app/src/main/java/com/sampoom/android/core/util/AuthValidator.kt, app/src/main/java/com/sampoom/android/core/network/TokenRefreshService.kt, app/src/main/java/com/sampoom/android/MainActivityViewModel.kt
직원 관리 경로(ROUTE_EMPLOYEE) 추가, User 임포트 업데이트, AuthValidator 패키지 이동 (auth.domain → core.util), 설정 화면 경로 변경
리소스 및 DI
app/src/main/res/values/strings.xml, app/src/main/java/com/sampoom/android/feature/user/di/UserModules.kt
직원 관리 및 프로필 편집 관련 문자열 리소스 추가, User 기능 DI 모듈 구성

시퀀스 다이어그램

sequenceDiagram
    participant User as 사용자
    participant LoginVM as LoginViewModel
    participant AuthRepo as AuthRepository
    participant UserRepo as UserRepository
    participant ProfileUC as GetProfileUseCase
    participant AuthPrefs as AuthPreferences

    User->>LoginVM: 로그인 시도
    LoginVM->>AuthRepo: signIn(email, password)
    AuthRepo-->>LoginVM: Result<User> (기본 필드)
    LoginVM->>ProfileUC: 프로필 조회 ("AGENCY")
    ProfileUC->>UserRepo: getProfile("AGENCY")
    UserRepo->>AuthPrefs: 저장된 토큰 조회
    UserRepo-->>ProfileUC: Result<User> (완전한 정보)
    ProfileUC-->>LoginVM: Result<User>
    LoginVM->>AuthPrefs: User 저장
    LoginVM-->>User: 로그인 성공
Loading
sequenceDiagram
    participant User as 사용자
    participant DashboardScreen as DashboardScreen
    participant AppNavHost as AppNavHost
    participant EmployeeListScreen as EmployeeListScreen
    participant EmployeeListVM as EmployeeListViewModel
    participant UserRepo as UserRepository

    User->>DashboardScreen: 직원 버튼 클릭
    DashboardScreen->>AppNavHost: onEmployeeClick()
    AppNavHost->>EmployeeListScreen: ROUTE_EMPLOYEE 네비게이션
    EmployeeListScreen->>EmployeeListVM: 로드 시작
    EmployeeListVM->>UserRepo: getEmployeeList() (페이징)
    UserRepo-->>EmployeeListVM: Flow<PagingData<Employee>>
    EmployeeListVM-->>EmployeeListScreen: 직원 목록 표시
    User->>EmployeeListScreen: 직원 편집 클릭
    EmployeeListScreen->>EmployeeListScreen: 바텀 시트 열기 (EditEmployeeBottomSheet)
Loading

예상 코드 리뷰 난이도

🎯 4 (복잡) | ⏱️ ~60분

특별 주의 사항

  • User 모델 이동: auth.domain에서 user.domain으로 광범위한 패키지 이동이 이루어졌으므로, 모든 임포트 경로가 일관되게 업데이트되었는지 확인 필요
  • 인증 흐름 변경: LoginViewModel/SignUpViewModel에서 GetProfileUseCase 호출 추가로 인한 비동기 흐름 변경, 에러 처리 로직 검토 필수
  • SettingScreen 재배치: setting 기능이 dashboard로 통합되었으므로 네비게이션 및 임포트 경로 일관성 확인
  • EmployeePagingSource: 새로운 페이징 구현으로, 에러 처리 및 에이전시 ID 조회 로직 검토 필수
  • 프로필/직원 편집 UI: 새로운 바텀 시트 컴포넌트들(UpdateProfileBottomSheet, EditEmployeeBottomSheet)의 상태 관리 및 콜백 흐름 검증
  • DashboardScreen 권한 체크: 기존 UserPosition 목록 확인에서 user?.role == "ADMIN" 확인으로 변경되었으므로 권한 로직 재검증

관련 PR

  • PR #22: 동일한 auth/프로필 표면에서 User 타입 이름 변경, AuthApi/AuthRepository 로그인/프로필 동작 변경, LoginViewModel/GetProfileUseCase를 통한 프로필 페치/병합 업데이트
  • PR #26: UserPosition 타입 도입/사용, 인증/사용자 모델, 매퍼, UI에서 관련 매핑 업데이트와 동일
  • PR #25: MainActivityViewModel, AppNavHost, AuthPreferences, AuthMappers 변경 및 GetStoredUserUseCase 사용 중복

제안 레이블

ready-to-merge

제안 검토자

  • yangjiseonn
  • vivivim
  • CHOOSLA
  • Lee-Jong-Jin

축하 시

🐰 User를 새 집으로 옮기고,
직원 목록을 쓱 쓱 불러오고,
프로필 편집은 바텀 시트에서 팍!
로그인 흐름은 더욱 똑똑해지고,
권한 체크도 깔끔하게 정리했네요! 🌟

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 변경 사항의 주요 내용을 명확하게 반영합니다. 프로필 수정 및 회원 관리 기능이 광범위하게 구현되었으며, 제목이 이를 정확히 요약합니다.

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

Comment @coderabbitai help to get the list of available commands and usage tips.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt (1)

49-66: login API 응답에 필요한 사용자 정보가 부족합니다. 현재 여러 필드가 빈 문자열과 기본값으로 초기화되고 있습니다.

검증 결과, 리뷰 의견이 정확합니다. LoginResponseDto는 userId, accessToken, refreshToken, expiresIn 4개 필드만 제공하지만, User 모델은 userName, email, role, workspace, branch, agencyId 등 14개 필드를 필요로 합니다. 현재 toModel() 매퍼는 다음과 같이 처리하고 있습니다:

  • userName, email, role, workspace, branch: 빈 문자열 ("")
  • position: 하드코딩된 기본값 (UserPosition.STAFF)
  • agencyId: 0 (유효하지 않은 ID)
  • startedAt, endedAt: null

이는 불완전한 User 객체가 애플리케이션 상태에 저장되도록 하므로, 사용자 관련 기능(역할 기반 접근 제어, 이메일 작업, 프로필 표시 등)이 제대로 작동할 수 없습니다. login API에서 이 정보들을 응답으로 받거나, 로그인 후 별도로 프로필 정보를 조회하여 User 객체를 완성해야 합니다.

app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt (1)

9-23: 로그인 직후 저장되는 User 정보가 비어 있어 후속 요청이 실패합니다.
LoginResponseDto.toModel()에서 workspace, role, branch, agencyId, userName, email 등을 모두 빈 문자열·0·null로 덮어써 버렸습니다. 이후 UserRepository.getProfile(workspace: String) 같은 호출은 저장된 User.workspace 값을 그대로 사용하므로, 현재 구현대로면 빈 workspace로 API를 호출해 400/404를 유발하고 프로필/직원 리스트 기능이 전부 막힙니다. DTO가 제공하는 실제 필드를 그대로 매핑하도록 원래의 구현을 복구하거나 동일한 데이터를 채워 넣어 주세요.

app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt (1)

193-195: 컴파일 오류: 상태 복사 구문이 불완전합니다.
copy(loading = false, ) 구문이 미완성이라 빌드가 실패합니다. 누락된 필드를 명시해 주세요.

-                _state.update {
-                    it.copy(loading = false, )
-                }
+                _state.update {
+                    it.copy(loading = false, success = false)
+                }
🧹 Nitpick comments (4)
app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt (1)

91-105: 하드코딩된 "AGENCY" 문자열을 상수로 추출하세요.

로그인 성공 후 프로필을 가져오는 로직은 올바르게 구현되었습니다. 하지만 "AGENCY" 문자열이 하드코딩되어 있어 유지보수성이 떨어집니다.

다음과 같이 상수로 추출하는 것을 권장합니다:

 @HiltViewModel
 class LoginViewModel @Inject constructor(
     private val messageHandler: GlobalMessageHandler,
     private val singIn: LoginUseCase,
     private val getProfile: GetProfileUseCase,
     private val application: Application
 ) : ViewModel() {
 
     private companion object {
         private const val TAG = "LoginViewModel"
+        private const val DEFAULT_WORKSPACE = "AGENCY"
     }

그리고 사용 부분을 다음과 같이 변경하세요:

-                getProfile("AGENCY")
+                getProfile(DEFAULT_WORKSPACE)
app/src/main/java/com/sampoom/android/feature/user/data/mapper/UserMappers.kt (1)

27-31: 직책 변환 시 로깅 추가를 고려해보세요.

잘못된 직책 값이 전달될 때 자동으로 STAFF로 변환되는데, 디버깅을 위해 이러한 경우를 로깅하면 API 계약 문제를 더 쉽게 파악할 수 있습니다.

다음과 같이 로깅을 추가할 수 있습니다:

 private fun String.toUserPosition(): UserPosition = try {
     UserPosition.valueOf(this.uppercase())
 } catch (_: IllegalArgumentException) {
+    Log.w("UserMappers", "Invalid position value: $this, defaulting to STAFF")
     UserPosition.STAFF
 }
app/src/main/java/com/sampoom/android/feature/user/data/paging/EmployeePagingSource.kt (1)

34-34: 하드코딩된 문자열 상수화 권장

"AGENCY" 문자열이 하드코딩되어 있습니다. 향후 유지보수성을 위해 상수나 enum으로 추출하는 것을 권장합니다.

예시:

companion object {
    private const val WORKSPACE_TYPE_AGENCY = "AGENCY"
}

// 사용:
val response = api.getEmployeeList(WORKSPACE_TYPE_AGENCY, agencyId, page, pageSize)
app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt (1)

67-67: 역할 기반 관리자 체크로 간소화됨

UserPosition 열거형 체크에서 role == "ADMIN" 문자열 비교로 변경되어 로직이 간소화되었습니다. 다만 "ADMIN" 문자열이 하드코딩되어 있습니다.

향후 유지보수를 위해 역할 문자열을 상수로 추출하는 것을 고려해보세요:

private const val ROLE_ADMIN = "ADMIN"
// 사용:
val isManager = user?.role == ROLE_ADMIN

Also applies to: 78-78

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7e2913c and a531f8d.

📒 Files selected for processing (58)
  • app/build.gradle.kts (1 hunks)
  • app/src/main/java/com/sampoom/android/MainActivityViewModel.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt (3 hunks)
  • app/src/main/java/com/sampoom/android/core/network/TokenRefreshService.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/core/preferences/AuthPreferences.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/core/util/AuthValidator.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/UpdateProfileRequestDto.kt (0 hunks)
  • app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/UpdateProfileResponseDto.kt (0 hunks)
  • app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt (2 hunks)
  • app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/GetStoredUserUseCase.kt (0 hunks)
  • app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/LoginUseCase.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignUpUseCase.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt (4 hunks)
  • app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt (4 hunks)
  • app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt (12 hunks)
  • app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt (2 hunks)
  • app/src/main/java/com/sampoom/android/feature/dashboard/ui/SettingScreen.kt (7 hunks)
  • app/src/main/java/com/sampoom/android/feature/dashboard/ui/SettingUiEvent.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/dashboard/ui/SettingUiState.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/dashboard/ui/SettingViewModel.kt (3 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/data/mapper/UserMappers.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/data/paging/EmployeePagingSource.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/data/remote/api/UserApi.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/EditEmployeeRequestDto.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/EditEmployeeResponseDto.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/EmployeeDto.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/EmployeeListDto.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/GetProfileResponseDto.kt (2 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateProfileRequestDto.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateProfileResponseDto.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/data/repository/UserRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/di/UserModules.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/domain/model/Employee.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/domain/model/EmployeeList.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/domain/model/User.kt (2 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/domain/repository/UserRepository.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/domain/usecase/EditEmployeeUseCase.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/domain/usecase/GetEmployeeUseCase.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/domain/usecase/GetProfileUseCase.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/domain/usecase/GetStoredUserUseCase.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/domain/usecase/UpdateProfileUseCase.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/ui/EditEmployeeBottomSheet.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/ui/EditEmployeeUiEvent.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/ui/EditEmployeeUiState.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/ui/EditEmployeeViewModel.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/ui/EmployeeListScreen.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/ui/EmployeeListUiEvent.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/ui/EmployeeListUiState.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/ui/EmployeeListViewModel.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/ui/UpdateProfileBottomSheet.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/ui/UpdateProfileUiEvent.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/ui/UpdateProfileUiState.kt (1 hunks)
  • app/src/main/java/com/sampoom/android/feature/user/ui/UpdateProfileViewModel.kt (1 hunks)
  • app/src/main/res/values/strings.xml (2 hunks)
  • gradle/libs.versions.toml (2 hunks)
💤 Files with no reviewable changes (3)
  • app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/GetStoredUserUseCase.kt
  • app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/UpdateProfileRequestDto.kt
  • app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/UpdateProfileResponseDto.kt
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-10-15T14:15:21.212Z
Learnt from: Sangyoon98
Repo: 33-Auto/Sampoom-Management-Android PR: 15
File: app/src/main/java/com/sampoom/android/feature/auth/domain/AuthValidator.kt:12-15
Timestamp: 2025-10-15T14:15:21.212Z
Learning: The email validation regex pattern in AuthValidator.kt (app/src/main/java/com/sampoom/android/feature/auth/domain/AuthValidator.kt) was decided after consultation with the backend team. The pattern "[a-zA-Z0-9._-]+@[a-z]+\\.+[a-z]+" is intentionally restrictive to match backend requirements.

Applied to files:

  • app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt
  • app/src/main/java/com/sampoom/android/core/util/AuthValidator.kt
📚 Learning: 2025-10-23T12:27:55.160Z
Learnt from: Sangyoon98
Repo: 33-Auto/Sampoom-Management-Android PR: 19
File: app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt:81-81
Timestamp: 2025-10-23T12:27:55.160Z
Learning: In the Sampoom-Management-Android project, PullToRefreshBox's isRefreshing parameter is intentionally set to false across screens (PartListScreen, CartListScreen, OrderDetailScreen, OrderListScreen, OutboundListScreen) while the internal Indicator still uses the loading state from uiState. This is a deliberate pattern where loading state is managed separately and Pull-to-Refresh only activates on user action.

Applied to files:

  • app/src/main/java/com/sampoom/android/feature/dashboard/ui/SettingScreen.kt
  • app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt
🧬 Code graph analysis (11)
app/src/main/java/com/sampoom/android/feature/user/ui/EmployeeListScreen.kt (7)
app/src/main/java/com/sampoom/android/core/ui/component/ErrorContent.kt (1)
  • ErrorContent (17-36)
app/src/main/java/com/sampoom/android/core/ui/component/EmptyContent.kt (1)
  • EmptyContent (11-26)
app/src/main/java/com/sampoom/android/feature/user/ui/EditEmployeeBottomSheet.kt (1)
  • EditEmployeeBottomSheet (32-113)
app/src/main/java/com/sampoom/android/core/ui/theme/Color.kt (3)
  • backgroundCardColor (253-254)
  • textColor (256-257)
  • textSecondaryColor (259-260)
app/src/main/java/com/sampoom/android/core/util/PositionToKorean.kt (1)
  • positionToKorean (5-17)
app/src/main/java/com/sampoom/android/core/util/FormatDate.kt (1)
  • formatDate (5-26)
app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt (1)
  • CommonButton (46-173)
app/src/main/java/com/sampoom/android/feature/user/ui/EditEmployeeViewModel.kt (3)
app/src/main/java/com/sampoom/android/feature/user/data/remote/api/UserApi.kt (1)
  • editEmployee (23-28)
app/src/main/java/com/sampoom/android/feature/user/data/repository/UserRepositoryImpl.kt (1)
  • editEmployee (101-132)
app/src/main/java/com/sampoom/android/feature/user/domain/repository/UserRepository.kt (1)
  • editEmployee (13-13)
app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt (1)
app/src/main/java/com/sampoom/android/core/util/AuthValidator.kt (3)
  • validateEmail (7-18)
  • validatePassword (21-43)
  • validatePasswordCheck (46-56)
app/src/main/java/com/sampoom/android/feature/user/ui/UpdateProfileViewModel.kt (3)
app/src/main/java/com/sampoom/android/feature/user/data/remote/api/UserApi.kt (1)
  • updateProfile (20-21)
app/src/main/java/com/sampoom/android/feature/user/data/repository/UserRepositoryImpl.kt (1)
  • updateProfile (62-92)
app/src/main/java/com/sampoom/android/feature/user/domain/repository/UserRepository.kt (1)
  • updateProfile (11-11)
app/src/main/java/com/sampoom/android/feature/user/ui/UpdateProfileBottomSheet.kt (2)
app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt (1)
  • CommonTextField (28-143)
app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt (1)
  • CommonButton (46-173)
app/src/main/java/com/sampoom/android/feature/dashboard/ui/SettingScreen.kt (1)
app/src/main/java/com/sampoom/android/feature/user/ui/UpdateProfileBottomSheet.kt (1)
  • UpdateProfileBottomSheet (27-84)
app/src/main/java/com/sampoom/android/feature/user/data/repository/UserRepositoryImpl.kt (1)
app/src/main/java/com/sampoom/android/core/util/DelayNetwork.kt (1)
  • retry (7-30)
app/src/main/java/com/sampoom/android/feature/dashboard/ui/SettingViewModel.kt (1)
app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt (1)
  • refreshUser (130-134)
app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt (1)
app/src/main/java/com/sampoom/android/feature/user/ui/EmployeeListScreen.kt (1)
  • EmployeeListScreen (62-251)
app/src/main/java/com/sampoom/android/feature/user/ui/EditEmployeeBottomSheet.kt (3)
app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt (1)
  • CommonTextField (28-143)
app/src/main/java/com/sampoom/android/core/util/PositionToKorean.kt (1)
  • positionToKorean (5-17)
app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt (1)
  • CommonButton (46-173)
app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt (3)
app/src/main/java/com/sampoom/android/feature/user/data/remote/api/UserApi.kt (2)
  • getProfile (16-37)
  • getProfile (17-18)
app/src/main/java/com/sampoom/android/feature/user/data/repository/UserRepositoryImpl.kt (1)
  • getProfile (28-60)
app/src/main/java/com/sampoom/android/feature/user/domain/repository/UserRepository.kt (1)
  • getProfile (10-10)
🪛 detekt (1.23.8)
app/src/main/java/com/sampoom/android/feature/user/data/paging/EmployeePagingSource.kt

[warning] 31-31: A call to the default constructor of an exception was detected. Instead one of the constructor overloads should be called. This allows to provide more meaningful exceptions.

(detekt.exceptions.ThrowingExceptionsWithoutMessageOrCause)

🔇 Additional comments (56)
app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/LoginUseCase.kt (1)

3-3: User 모델 패키지 이동이 전체 코드베이스에서 일관되게 반영되었습니다.

LoginUseCase.kt의 import 변경이 올바르게 적용되었으며, AuthRepository 인터페이스도 동일한 새로운 User 타입을 사용하도록 업데이트되었습니다. 이전 import 경로에 대한 참조는 코드베이스에서 찾을 수 없으며, 모든 타입 시그니처가 일관되게 유지되고 있습니다.

app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt (2)

6-22: 마이그레이션 검증 완료 - 문제 없음

AuthRepository에서 getProfile 메서드가 완전히 제거되었으며, 다음과 같이 올바르게 마이그레이션되었습니다:

  • UserRepository 인터페이스에 getProfile 메서드 정의
  • GetProfileUseCase가 user feature에서 구현
  • SignUpViewModel과 LoginViewModel이 GetProfileUseCase를 사용하도록 업데이트
  • 마이그레이션되지 않은 AuthRepository.getProfile 호출 없음

관심사의 분리가 적절히 수행되었고 모든 호출 지점이 새로운 위치로 마이그레이션되었습니다.


4-4: 마이그레이션이 완료되고 올바르게 구현되었습니다.

검증 결과, User 모델의 패키지 이동이 완전히 완료되었습니다:

  • AuthRepository.kt: 새로운 경로 com.sampoom.android.feature.user.domain.model.User 올바르게 import됨
  • 이전 import 경로 제거됨: com.sampoom.android.feature.auth.domain.model.User에 대한 참조 없음
  • 모든 사용처 업데이트됨: 30개 이상의 파일에서 새로운 import 경로를 일관되게 사용 중
  • 관심사 분리 달성: auth.domain.model은 VendorList와 Vendor만 보유하며, User는 user.domain으로 완전히 이동됨
app/src/main/java/com/sampoom/android/MainActivityViewModel.kt (1)

6-7: LGTM!

User 모델과 GetStoredUserUseCase의 패키지 이동이 올바르게 반영되었습니다.

app/src/main/java/com/sampoom/android/feature/user/domain/usecase/EditEmployeeUseCase.kt (1)

7-11: LGTM!

Use case 구현이 Clean Architecture 패턴을 올바르게 따르고 있으며, 단일 책임 원칙을 준수합니다.

app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateProfileRequestDto.kt (1)

3-5: LGTM!

프로필 업데이트를 위한 간단한 DTO 구조가 적절합니다.

app/src/main/java/com/sampoom/android/core/util/AuthValidator.kt (1)

1-1: LGTM!

AuthValidator를 core.util 패키지로 이동하여 여러 기능 모듈에서 공유할 수 있도록 한 것은 좋은 리팩토링입니다.

app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt (1)

12-12: LGTM!

User 모델이 user 도메인으로 올바르게 이동되었습니다.

app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/EditEmployeeResponseDto.kt (1)

3-8: LGTM!

직원 편집 응답을 위한 DTO 구조가 적절하며, 필드 타입이 올바르게 정의되었습니다.

app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/EditEmployeeRequestDto.kt (1)

3-5: 검증 완료: 직원 식별자는 URL 경로 매개변수로 올바르게 전달됩니다.

EditEmployeeRequestDto는 올바르게 설계되었습니다. 직원 식별자(userId)는 @Path("userId") 매개변수를 통해 URL 경로(/user/profile/{userId})로 전달되며, 요청 본문에는 수정할 필드(position)만 포함됩니다. 이는 표준 REST API 패턴입니다.

app/src/main/java/com/sampoom/android/feature/user/domain/usecase/GetProfileUseCase.kt (1)

7-11: LGTM!

Use case 구현이 올바르며, 클린 아키텍처 패턴을 잘 따르고 있습니다. Repository로의 단순한 위임 패턴이 적절하게 적용되었습니다.

app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt (2)

9-10: LGTM!

Validator 클래스들을 core.util로 이동한 것은 적절한 리팩토링입니다. 공통 유틸리티를 core 패키지에 배치하는 것이 아키텍처 관점에서 올바릅니다.


21-24: LGTM!

GetProfileUseCase 의존성 추가가 적절합니다. 생성자 주입 패턴이 올바르게 적용되었습니다.

app/src/main/res/values/strings.xml (2)

117-126: LGTM!

직원 관리 관련 문자열 리소스가 적절하게 추가되었습니다. 네이밍 컨벤션이 일관성 있게 유지되고 있습니다.


140-141: LGTM!

프로필 수정 관련 문자열 리소스가 적절하게 추가되었습니다.

app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignUpUseCase.kt (1)

3-3: LGTM!

User 모델을 user feature로 이동한 리팩토링이 적절합니다. 도메인 모델을 해당 feature 패키지에 배치하는 것이 아키텍처 관점에서 올바릅니다.

app/src/main/java/com/sampoom/android/core/network/TokenRefreshService.kt (1)

6-6: LGTM!

User 모델 import 경로 변경이 적절합니다. 다른 파일들과 일관성 있게 user feature 패키지를 사용하고 있습니다.

app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt (2)

13-14: LGTM!

User 및 GetStoredUserUseCase를 user feature 패키지로 이동한 import 변경이 적절합니다.


130-134: LGTM!

refreshUser() 메서드 구현이 올바릅니다. 사용자 정보를 갱신하는 명확한 public API를 제공하고 있습니다.

app/src/main/java/com/sampoom/android/feature/dashboard/ui/SettingUiEvent.kt (1)

1-6: EditProfile 이벤트 제거는 안전합니다. 활성 사용 사례가 없습니다.

검증 결과, SettingUiEvent 인터페이스에 정의된 이벤트는 LoadProfile과 NameChanged이며, SettingViewModel의 onEvent() 메서드도 이 두 이벤트만 처리합니다. SettingScreen에서도 SettingUiEvent.LoadProfile만 사용 중입니다. EditProfile 이벤트는 현재 코드베이스 어디에서도 참조되지 않으므로, 제거로 인한 문제는 없습니다.

app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/EmployeeListDto.kt (2)

3-6: 페이징 처리된 직원 목록 응답 구조가 적절합니다.

EmployeeListDto는 직원 목록(users)과 메타데이터(meta)를 포함하는 표준적인 페이징 응답 구조입니다.


8-15: 페이징 메타데이터 구조가 완벽합니다.

EmployeeMetaDto는 페이징 처리에 필요한 모든 정보(현재 페이지, 전체 페이지, 전체 요소 수, 페이지 크기, 다음/이전 페이지 존재 여부)를 포함하고 있습니다.

app/src/main/java/com/sampoom/android/feature/user/domain/model/User.kt (1)

1-19: User 도메인 모델의 패키지 재구성이 적절합니다.

auth 패키지에서 user 패키지로 이동한 것은 도메인 책임의 명확한 분리를 위한 좋은 리팩토링입니다. 데이터 구조는 그대로 유지되어 안전한 변경입니다.

app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateProfileResponseDto.kt (1)

3-6: 프로필 업데이트 응답 DTO 구조가 적절합니다.

업데이트 후 변경된 필드(userId, userName)만 반환하는 간결한 구조입니다.

app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/GetProfileResponseDto.kt (1)

1-14: GetProfileResponseDto의 패키지 재구성이 일관성 있습니다.

User 도메인 모델과 동일하게 user 패키지로 이동하여 관련 타입들이 함께 위치하도록 개선되었습니다.

app/src/main/java/com/sampoom/android/feature/dashboard/ui/SettingUiState.kt (2)

1-1: UI 패키지 재구성이 적절합니다.

setting.ui에서 dashboard.ui로 변경하여 설정 화면이 대시보드의 일부임을 명확히 표현합니다.


3-3: User 모델 import가 올바르게 업데이트되었습니다.

User 도메인 모델의 패키지 변경에 맞춰 import 경로가 정확히 수정되었습니다.

app/src/main/java/com/sampoom/android/feature/user/domain/usecase/UpdateProfileUseCase.kt (1)

7-11: 프로필 업데이트 유스케이스 구현이 적절합니다.

리포지토리와 뷰모델 사이의 추상화 계층을 제공하며, 향후 비즈니스 로직 추가를 위한 확장 지점을 제공합니다.

app/src/main/java/com/sampoom/android/core/preferences/AuthPreferences.kt (1)

10-10: User 모델 import가 올바르게 업데이트되었습니다.

User 도메인 모델의 패키지 변경에 따라 AuthPreferences의 import도 정확히 수정되어 전체 코드베이스의 일관성이 유지됩니다.

app/src/main/java/com/sampoom/android/feature/user/ui/EditEmployeeUiState.kt (1)

5-10: 직원 수정 UI 상태 구조가 적절합니다.

로딩(isLoading), 에러(error), 성공(isSuccess) 상태와 직원 데이터(employee)를 모두 포함한 완전한 UI 상태 관리 구조입니다.

app/src/main/java/com/sampoom/android/feature/user/ui/UpdateProfileUiState.kt (1)

5-10: 깔끔한 UI 상태 모델입니다.

프로필 업데이트 화면의 상태를 명확하게 표현하고 있으며, 로딩/에러/성공 상태를 적절히 관리하고 있습니다.

app/src/main/java/com/sampoom/android/feature/user/domain/usecase/GetEmployeeUseCase.kt (1)

9-13: Use case 구현이 적절합니다.

Paging 데이터를 반환하는 깔끔한 use case 구조입니다.

app/src/main/java/com/sampoom/android/feature/user/ui/EditEmployeeUiEvent.kt (1)

6-10: UI 이벤트 모델이 잘 설계되었습니다.

sealed interface 패턴을 사용하여 타입 안전한 이벤트 처리가 가능합니다.

app/src/main/java/com/sampoom/android/feature/user/ui/EmployeeListUiState.kt (1)

5-10: 직원 목록 UI 상태가 적절합니다.

목록, 로딩, 에러 상태와 함께 선택된 직원 정보를 포함하여 바텀시트 편집 플로우를 지원합니다.

app/src/main/java/com/sampoom/android/feature/user/domain/usecase/GetStoredUserUseCase.kt (1)

7-11: 저장된 사용자 조회 use case가 적절합니다.

suspend 함수를 사용하여 비동기 저장소 접근을 처리하고 있습니다.

app/src/main/java/com/sampoom/android/feature/user/ui/UpdateProfileUiEvent.kt (1)

5-9: 프로필 업데이트 이벤트 모델이 잘 구성되었습니다.

초기화, 업데이트, 닫기 이벤트를 타입 안전하게 처리할 수 있습니다.

app/src/main/java/com/sampoom/android/feature/user/data/mapper/UserMappers.kt (3)

11-25: 프로필 조회 응답 매핑이 적절합니다.

GetProfile API 응답을 User 도메인 모델로 변환하며, 토큰 정보는 별도로 관리되므로 빈 문자열로 설정하는 것이 합리적입니다.


62-73: EmployeeDto 매핑이 깔끔합니다.

모든 필드를 직접 매핑하여 데이터 손실 없이 변환하고 있습니다.


33-47: 리뷰 의견 재평가 완료: 문제 없음

코드 검증 결과, 해당 리뷰 의견은 부정확합니다.

UpdateProfileResponseDto.toModel()UserRepositoryImpl.updateProfile()에서만 호출되며, 반환된 부분적인 User 객체는 직접 사용되지 않습니다. 저장소 계층에서 다음과 같이 처리됩니다:

  • API 응답에서 userId, userName 추출
  • 저장된 사용자 정보(preferences)에서 accessToken, refreshToken 등 토큰 데이터 복원
  • 원본 사용자 객체에서 email, role 등 유지
  • 이 세 가지를 병합하여 완전한 User 객체 생성 후 반환

따라서 프로필 업데이트 후에도 사용자 정보가 손실되지 않으며, UI에서도 빈 필드를 보지 않습니다. API가 변경된 필드만 반환하는 것은 의도된 설계이며, 리포지토리가 이를 적절히 처리하고 있습니다.

Likely an incorrect or invalid review comment.

app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/EmployeeDto.kt (1)

5-16: 직원 DTO 구조가 적절합니다.

모든 필수 필드를 포함하고 있으며, 선택적 날짜 필드에 nullable 타입을 사용하는 것이 적절합니다.

app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt (3)

52-52: 변경사항 확인됨

SettingScreenUser 모델의 import 경로 변경 및 EmployeeListScreen 추가가 도메인 재구성과 일치합니다. 새로운 ROUTE_EMPLOYEE 상수도 기존 네이밍 컨벤션을 따릅니다.

Also applies to: 58-59, 79-79


215-221: 구현 확인됨

직원 목록 화면의 네비게이션 설정이 적절하며, 다른 상세 화면들과 일관된 패턴을 따릅니다.


244-246: 콜백 연결 확인됨

onEmployeeClick 콜백이 적절하게 설정되었으며, parentNavController를 사용하여 하단 네비게이션 외부로 이동하는 패턴이 다른 네비게이션 동작들과 일관됩니다.

app/src/main/java/com/sampoom/android/feature/user/data/paging/EmployeePagingSource.kt (2)

12-20: 의존성 주입 구현 확인됨

AssistedInjectAssistedFactory 패턴이 적절하게 사용되었습니다.


22-27: 페이징 새로고침 로직 확인됨

getRefreshKey 구현이 양방향 페이징의 표준 패턴을 따릅니다.

app/src/main/java/com/sampoom/android/feature/user/ui/UpdateProfileViewModel.kt (3)

15-34: ViewModel 구조 확인됨

Hilt를 사용한 의존성 주입, StateFlow를 통한 상태 노출, 레이블 바인딩 패턴이 모두 적절합니다.


36-58: 이벤트 핸들링 확인됨

이벤트 기반 아키텍처가 잘 구현되었으며, 상태 업데이트가 적절합니다.


60-95: 프로필 업데이트 로직 확인됨

에러 핸들링, 로딩 상태 관리, 불변 객체 업데이트 등이 모두 적절하게 구현되었습니다. 백엔드 메시지 추출 및 폴백 처리도 잘 되어 있습니다.

app/src/main/java/com/sampoom/android/feature/user/data/repository/UserRepositoryImpl.kt (3)

24-26: 구현 확인됨

getStoredUser의 간단한 위임 패턴이 적절합니다.


94-99: 페이징 구현 확인됨

Paging 3 라이브러리의 표준 패턴을 따르며, 페이지 크기 20도 적절합니다.


101-132: 직원 수정 구현 확인됨

API 호출, 예외 처리(메시지 포함), 그리고 takeIf를 사용한 스마트한 병합 로직이 잘 구현되었습니다.

app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt (3)

89-89: 사용자 새로고침 추가 확인됨

Pull-to-refresh 시 사용자 정보를 새로고침하는 것은 적절한 추가입니다.


126-126: 콜백 연결 확인됨

onEmployeeClick 콜백이 컴포넌트 계층(DashboardScreenButtonSectionButtonCard)을 통해 적절하게 전달되고 있으며, ButtonCard의 기본 파라미터를 통해 선택적으로 사용 가능하도록 설계되었습니다.

Also applies to: 154-160, 231-252, 310-310


265-275: 텍스트 포맷팅 개선 확인됨

코드 가독성을 위한 포맷팅 변경과 문자열 리소스 사용이 적절합니다.

Also applies to: 287-298

app/src/main/java/com/sampoom/android/feature/user/ui/EmployeeListViewModel.kt (1)

17-37: ViewModel 구조 및 페이징 설정 확인됨

Hilt를 사용한 의존성 주입과 cachedIn을 통한 페이징 데이터 캐싱이 적절하게 구현되었습니다.

app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt (1)

5-5: API 도메인 분리 개선 확인됨

signUp 엔드포인트가 AuthApi에 추가되었고, 프로필 관련 엔드포인트(getProfile, updateProfile)가 제거되어 UserApi로 이동한 것은 적절한 도메인 분리입니다. 인증 관련 기능과 사용자 프로필 관리를 명확히 구분하여 단일 책임 원칙을 따릅니다.

Also applies to: 10-11, 18-20

Comment thread app/build.gradle.kts Outdated
Comment thread gradle/libs.versions.toml Outdated
Copy link
Copy Markdown

@Lee-Jong-Jin Lee-Jong-Jin left a comment

Choose a reason for hiding this comment

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

승인

@Sangyoon98 Sangyoon98 merged commit 48c65a0 into dev Nov 8, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants