Skip to content

Comments

[REFAC] 직급 Enum 변경#21

Merged
Sangyoon98 merged 1 commit intodevfrom
SPM-396
Nov 6, 2025
Merged

[REFAC] 직급 Enum 변경#21
Sangyoon98 merged 1 commit intodevfrom
SPM-396

Conversation

@Sangyoon98
Copy link
Member

@Sangyoon98 Sangyoon98 commented Nov 5, 2025

📝 Summary

직급 Enum 변경

🙏 Question & PR point

📬 Reference

Summary by CodeRabbit

릴리스 노트

  • 새 기능

    • 가입 시 직급 선택이 드롭다운 메뉴로 개선되었습니다.
  • 개선사항

    • 프로필에 표시되는 직급 정보가 한국어로 변경되었습니다.
    • 프로필 로딩 안정성이 향상되었습니다.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 5, 2025

개요

사용자 직급 관리 시스템을 문자열에서 강타입 UserPosition 열거형으로 전환하고, 프로필 조회에 지수 백오프 재시도 로직을 추가하며, UI에서 위치 선택기를 드롭다운 메뉴로 변경했습니다.

변경 사항

기능군 / 파일 변경 요약
UserPosition 열거형 도입
SampoomManagement/Features/Auth/Domain/Models/UserPosition.swift
직급 데이터를 위한 새로운 UserPosition 열거형 추가. String, CaseIterable, Codable, Equatable, Hashable 준수. staff부터 chairman까지 10개 사례 정의, 각 사례에 대한 한국어 displayNameKo 계산 속성 포함
도메인 모델 업데이트
SampoomManagement/Features/Auth/Domain/Models/User.swift
User 구조체의 position 속성을 String에서 UserPosition으로 변경
로컬 저장소 및 매핑 레이어
SampoomManagement/Features/Auth/Data/Local/Preferences/AuthPreferences.swift,
SampoomManagement/Features/Auth/Data/Mappers/AuthMappers.swift
AuthPreferences에서 position의 rawValue를 저장/로드; AuthMappers에서 UserPosition(rawValue:) 변환 추가, 기본값으로 .staff 폴백
재시도 로직 추가
SampoomManagement/Features/Auth/Data/Repository/AuthRepositoryImpl.swift
signIn 중 프로필 조회에 지수 백오프 재시도 추가 (최대 5회, 초기 지연 300ms, 최대 지연 1500ms, 1.8배 백오프 계수); 실패 시 토큰 롤백 처리
UI 상태 및 뷰 업데이트
SampoomManagement/Features/Auth/UI/SignUpUiState.swift,
SampoomManagement/Features/Auth/UI/SignUpView.swift
workspace 기본값을 "대리점"에서 "AGENCY"로 변경; 위치 입력을 Menu 기반 드롭다운 선택기로 변경, UserPosition 열거형 사용
설정 화면 표시 업데이트
SampoomManagement/Features/Setting/UI/SettingView.swift
user.position을 user.position.displayNameKo로 변경하여 한국어 직급명 표시

시퀀스 다이어그램

sequenceDiagram
    participant View as SignUp View
    participant ViewModel as ViewModel
    participant Repo as Repository
    participant Remote as Remote API
    participant Local as Local Storage

    View->>ViewModel: signUp(user)
    ViewModel->>Repo: authenticate(email, password)
    Repo->>Remote: login(credentials)
    Remote-->>Repo: token + profile
    Repo->>Repo: retry block (up to 5 times,<br/>exponential backoff)
    Repo->>Remote: getProfile()
    alt Success
        Remote-->>Repo: profileDTO
        Repo->>Repo: toModel() - convert to User
        Repo->>Local: saveUser(user)
        Repo-->>ViewModel: success
    else Retry Exhausted
        Repo->>Local: clearTokens()
        Repo-->>ViewModel: error
    end
Loading
sequenceDiagram
    participant User as User selects position
    participant View as SignUpView
    participant State as selectedPosition state
    participant ViewModel as ViewModel

    User->>View: tap Menu dropdown
    View->>View: show UserPosition cases<br/>with displayNameKo
    User->>View: select position
    View->>State: selectedPosition = UserPosition
    View->>ViewModel: updatePosition(pos.rawValue)
    View->>View: move focus to email field
Loading

예상 코드 리뷰 노력

🎯 3 (보통) | ⏱️ ~20분

  • 재시도 로직 검증: AuthRepositoryImpl의 지수 백오프 구현이 정상 작동하는지 확인 필요 (재시도 횟수, 지연 시간, 백오프 계수)
  • 타입 변환 완전성: 모든 레이어(Local, Mapper, Repository, UI)에서 String↔UserPosition 변환이 일관되게 처리되었는지 검토
  • 기본값 및 폴백: AuthPreferences와 AuthMappers에서 .staff 폴백이 모든 엣지 케이스를 올바르게 처리하는지 확인
  • UI 상호작용: SignUpView의 Menu 선택기에서 포커스 이동 및 폼 제출 흐름이 의도대로 작동하는지 테스트 필요

🐰 직급이 번역되니 얼마나 예쁜지!
한글 이름으로 반짝이는 UI,
재시도와 폴백으로 더욱 튼튼해진 네트워크,
이제 우리 앱은 정말 멋진 형태지요!
🎉✨

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목 '[REFAC] 직급 Enum 변경'은 변경 사항의 핵심을 명확하게 설명하고 있습니다. 여러 파일에서 String 타입의 position을 UserPosition enum으로 변경하는 리팩토링의 주요 목표를 정확히 반영합니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch SPM-396

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

@taemin3 taemin3 left a comment

Choose a reason for hiding this comment

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

확인했습니다

Copy link
Contributor

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

🧹 Nitpick comments (3)
SampoomManagement/Features/Auth/Data/Repository/AuthRepositoryImpl.swift (1)

59-65: 재시도 가능한 오류만 필터링하는 것을 고려하세요.

현재 구현은 모든 오류에 대해 재시도를 수행하는데, 이는 유효성 검사 실패나 404와 같은 재시도 불가능한 오류에도 최대 5번까지 재시도하여 불필요한 지연을 발생시킬 수 있습니다.

다음과 같이 재시도 가능한 오류만 필터링하도록 개선할 수 있습니다:

-            profileUser = try await retry(times: 5, initialDelayMs: 300, maxDelayMs: 1500, factor: 1.8) {
+            profileUser = try await retry(
+                times: 5, 
+                initialDelayMs: 300, 
+                maxDelayMs: 1500, 
+                factor: 1.8,
+                shouldRetry: { error in
+                    // 네트워크 오류나 일시적 서버 오류만 재시도
+                    if let authError = error as? AuthError {
+                        return authError == .invalidResponse
+                    }
+                    return true // 기타 네트워크 오류는 재시도
+                }
+            ) {
                 let profileResponse = try await self.api.getProfile()
                 guard let profileDto = profileResponse.data else {
                     throw AuthError.invalidResponse
                 }
                 return profileDto.toModel()
             }

그리고 retry 함수의 시그니처를 다음과 같이 수정:

 private func retry<T>(
     times: Int = 5,
     initialDelayMs: UInt64 = 300,
     maxDelayMs: UInt64 = 1500,
     factor: Double = 1.8,
+    shouldRetry: ((Error) -> Bool)? = nil,
     _ block: @escaping () async throws -> T
 ) async throws -> T {
     precondition(times >= 1)
     var currentDelayMs = initialDelayMs
     for attempt in 1..<(times) {
         do {
             return try await block()
         } catch {
+            if let shouldRetry = shouldRetry, !shouldRetry(error) {
+                throw error
+            }
             let ns = currentDelayMs * 1_000_000
             try? await Task.sleep(nanoseconds: ns)
             let next = UInt64(Double(currentDelayMs) * factor)
             currentDelayMs = min(next, maxDelayMs)
         }
     }
     return try await block()
 }
SampoomManagement/Features/Auth/Domain/Models/User.swift (1)

10-26: UserRole과 UserPosition 간의 중복을 검토하세요.

UserRole enum에 staff, seniorStaff, assistantManager 등의 케이스가 포함되어 있는데, 이는 새로 추가된 UserPosition enum과 중복됩니다. UserRole은 권한 수준(admin, user, manager)을 나타내고 UserPosition은 조직 내 직급을 나타내야 하는데, 현재 두 개념이 혼재되어 있어 혼란을 야기할 수 있습니다.

향후 UserRole을 실제 역할(권한)만 포함하도록 정리하는 것을 고려하세요:

enum UserRole: String, Codable, Equatable {
    case admin = "ADMIN"
    case user = "USER"
    case manager = "MANAGER"
    
    var isAdmin: Bool { self == .admin }
}
SampoomManagement/Features/Auth/UI/SignUpView.swift (1)

16-16: 중복된 nil 초기화를 제거하세요.

Optional 변수는 기본적으로 nil로 초기화되므로 명시적인 = nil은 불필요합니다.

다음과 같이 수정:

-@State private var selectedPosition: UserPosition? = nil
+@State private var selectedPosition: UserPosition?
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9de3e18 and 4f65013.

📒 Files selected for processing (8)
  • SampoomManagement/Features/Auth/Data/Local/Preferences/AuthPreferences.swift (3 hunks)
  • SampoomManagement/Features/Auth/Data/Mappers/AuthMappers.swift (2 hunks)
  • SampoomManagement/Features/Auth/Data/Repository/AuthRepositoryImpl.swift (2 hunks)
  • SampoomManagement/Features/Auth/Domain/Models/User.swift (1 hunks)
  • SampoomManagement/Features/Auth/Domain/Models/UserPosition.swift (1 hunks)
  • SampoomManagement/Features/Auth/UI/SignUpUiState.swift (1 hunks)
  • SampoomManagement/Features/Auth/UI/SignUpView.swift (2 hunks)
  • SampoomManagement/Features/Setting/UI/SettingView.swift (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
SampoomManagement/Features/Auth/UI/SignUpView.swift (1)
SampoomManagement/Features/Auth/UI/SignUpViewModel.swift (1)
  • updatePosition (35-38)
SampoomManagement/Features/Auth/Data/Local/Preferences/AuthPreferences.swift (1)
SampoomManagement/Features/Auth/Data/Local/Preferences/KeychainManager.swift (2)
  • save (24-43)
  • get (45-71)
SampoomManagement/Features/Auth/Data/Repository/AuthRepositoryImpl.swift (3)
SampoomManagement/Core/Network/AuthRequestInterceptor.swift (1)
  • retry (56-80)
SampoomManagement/Features/Auth/Data/Remote/API/AuthAPI.swift (1)
  • getProfile (98-105)
SampoomManagement/Features/Auth/Data/Mappers/AuthMappers.swift (2)
  • toModel (11-27)
  • toModel (31-47)
🪛 SwiftLint (0.57.0)
SampoomManagement/Features/Auth/UI/SignUpView.swift

[Warning] 16-16: Initializing an optional variable with nil is redundant

(redundant_optional_initialization)

🔇 Additional comments (8)
SampoomManagement/Features/Auth/Data/Repository/AuthRepositoryImpl.swift (1)

158-180: 재사용 가능한 재시도 헬퍼 구현이 우수합니다.

지수 백오프 재시도 로직이 잘 구현되어 있고, 제네릭으로 재사용 가능하도록 설계되었습니다.

SampoomManagement/Features/Setting/UI/SettingView.swift (1)

61-61: 한글 직급명 표시가 올바르게 적용되었습니다.

UserPosition enum의 displayNameKo 속성을 활용하여 한글 직급명을 표시하도록 변경된 것이 적절합니다.

SampoomManagement/Features/Auth/Data/Local/Preferences/AuthPreferences.swift (1)

38-38: Enum 직렬화가 올바르게 구현되었습니다.

rawValue를 사용한 저장 및 복원 로직이 적절하며, 기존 사용자 데이터에 대한 마이그레이션도 .staff 폴백을 통해 안전하게 처리됩니다.

Also applies to: 89-89, 105-105

SampoomManagement/Features/Auth/Domain/Models/User.swift (1)

37-37: Position의 타입 변경이 올바르게 적용되었습니다.

String에서 UserPosition enum으로의 변경은 타입 안정성과 한글 표시를 제공합니다.

SampoomManagement/Features/Auth/Data/Mappers/AuthMappers.swift (1)

20-20: 매핑 로직이 새로운 enum 타입과 일관되게 업데이트되었습니다.

LoginResponseDTO는 임시 .staff 값을 사용하고, GetProfileResponseDTO는 rawValue로 안전하게 변환하며 폴백을 제공합니다.

Also applies to: 40-40

SampoomManagement/Features/Auth/UI/SignUpUiState.swift (1)

33-33: 기본값을 API 상수와 일치하도록 변경한 것이 적절합니다.

한글 문자열 "대리점"에서 영문 상수 "AGENCY"로 변경하여 API와의 일관성을 확보했습니다.

SampoomManagement/Features/Auth/Domain/Models/UserPosition.swift (1)

10-36: UserPosition enum 구현이 우수합니다.

타입 안정성, 로컬라이제이션, UI 반복을 위한 적절한 프로토콜 준수가 잘 구현되어 있습니다. rawValue는 서버 API와의 호환성을 보장하고, displayNameKo는 UI 표시를 간소화합니다.

SampoomManagement/Features/Auth/UI/SignUpView.swift (1)

86-121: Menu 기반 직급 선택 UI가 잘 구현되었습니다.

TextField를 Menu picker로 교체하여 사전 정의된 직급 선택에 더 적합한 UX를 제공합니다. UserPosition.allCases를 활용한 반복, rawValue 저장, 에러 표시, 포커스 관리가 모두 올바르게 처리되었습니다.

@Sangyoon98 Sangyoon98 merged commit 12d571f into dev Nov 6, 2025
6 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