-
Notifications
You must be signed in to change notification settings - Fork 0
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
[WEAV-148] 이상형 프로필 수정 - 선호 연령대 #52
Conversation
Caution Review failedThe pull request is closed. Walkthrough이 변경 사항은 Changes
Possibly related PRs
Suggested labels
Warning Rate limit exceeded@jisu15-kim has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 1 minutes and 31 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
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 and nitpick comments (22)
Projects/DesignSystem/DesignCore/Sources/AgeUpDownView/AgePickerView.swift (3)
11-12
: 바인딩 타입 개선 제안선택된 나이를
String?
대신Int?
로 처리하는 것이 더 타입 안전할 것 같습니다. 문자열 변환 과정에서 발생할 수 있는 오류를 방지할 수 있습니다.public struct AgePickerView: View { - @Binding var selectedValue: String? + @Binding var selectedValue: Int?
14-16
: 공개 API 문서화 필요공개 이니셜라이저에 대한 문서화가 필요합니다. 매개변수의 용도와 사용 방법을 설명하는 문서 주석을 추가해주세요.
+/// 나이 선택기 뷰를 생성합니다. +/// - Parameter selectedValue: 선택된 나이값을 저장하는 바인딩. nil은 "상관없음"을 의미합니다. public init(selectedValue: Binding<String?>) { self._selectedValue = selectedValue }
11-32
: SwiftUI 프리뷰 추가 필요개발 및 디자인 반복 작업을 위해 SwiftUI 프리뷰를 추가하는 것이 좋습니다.
#Preview { AgePickerView(selectedValue: .constant("5")) }Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift (2)
37-40
: 불필요한 return 문을 제거하는 것이 좋습니다함수가 값을 반환하지 않는 경우 Swift에서는 명시적인 return 문이 필요하지 않습니다.
다음과 같이 수정하는 것을 제안합니다:
public func requestPutPartnerInfo(userInfo: UserInfo) async throws { print("✅ [ProfileServiceMock] requestPutPartnerInfo 성공!") - return }
37-40
: 실패 케이스 시뮬레이션 기능 추가를 고려해보세요테스트의 완성도를 높이기 위해 에러 케이스를 시뮬레이션할 수 있는 기능을 추가하는 것이 좋습니다.
다음과 같은 구현을 제안합니다:
+ private var shouldFail: Bool = false + + public func setShouldFail(_ value: Bool) { + shouldFail = value + } + public func requestPutPartnerInfo(userInfo: UserInfo) async throws { + if shouldFail { + throw NetworkError.serverError + } print("✅ [ProfileServiceMock] requestPutPartnerInfo 성공!") }Projects/Features/Home/Sources/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeModel.swift (2)
16-28
: 프로토콜 문서화 및 연령대 유효성 검사 로직 추가 필요프로토콜의 각 프로퍼티에 대한 문서화 주석이 없어 사용 목적을 파악하기 어렵습니다. 또한 연령대 값의 유효성 검사 로직이 누락되어 있습니다.
다음 사항들을 추가해주시면 좋겠습니다:
- 각 프로퍼티에 대한 문서화 주석
- 연령대 범위 검증을 위한 computed 프로퍼티
예시:
/// 선호하는 연령대의 상한값 var upperValue: String? { get } /// 선호하는 연령대의 하한값 var lowerValue: String? { get } /// 입력된 연령대가 유효한지 검증 (예: 하한값이 상한값보다 작은지) var isAgeRangeValid: Bool { get }
15-15
: MARK 주석 형식 수정 필요SwiftLint 분석 결과에 따라 MARK 주석 형식을 수정해야 합니다.
다음과 같이 수정해주세요:
- //MARK: Stateful + // MARK: - Stateful - //MARK: State Properties + // MARK: - State Properties - //MARK: - Actionable + // MARK: - ActionableAlso applies to: 30-30, 47-47
🧰 Tools
🪛 SwiftLint (0.57.0)
[Warning] 15-15: Prefer at least one space after slashes for comments
(comment_spacing)
[Warning] 15-15: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
(mark)
Projects/Features/Home/Sources/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeIntent.swift (2)
17-32
: 문서화 개선이 필요합니다.클래스와 프로퍼티에 대한 문서화 주석을 추가하면 코드의 가독성과 유지보수성이 향상될 것 같습니다.
다음과 같이 문서화를 추가해보세요:
+/// 이상형 프로필의 연령대 수정을 담당하는 Intent 클래스입니다. class EditDateProfileAgeRangeIntent { + /// 연령대 수정 모델에 대한 약한 참조 private weak var model: EditDateProfileAgeRangeModelActionable? + /// 초기 입력 데이터 private let input: DataModel + /// 프로필 서비스 프로토콜 private let profileService: ProfileServiceProtocol
84-92
: 프로필 업데이트 메서드 문서화가 필요합니다.메서드의 목적과 동작을 명확히 하기 위해 문서화를 추가하면 좋을 것 같습니다.
다음과 같이 문서화를 추가해주세요:
+/// 새로운 이상형 정보를 서버에 업데이트합니다. +/// - Parameter newUserInfo: 업데이트할 새로운 사용자 정보 +/// - Throws: 네트워크 요청 실패시 NetworkError func requestUpdatePartnerInfo(newUserInfo: UserInfo) async throws { try await profileService.requestPutPartnerInfo( userInfo: newUserInfo ) } +/// 현재 뷰를 팝하여 이전 화면으로 돌아갑니다. @MainActor func popView() { AppCoordinator.shared.pop() }Projects/App/Sources/Navigation/NavigationStack.swift (1)
EmptyView()
대신 적절한 뷰가 구현되어야 합니다코드베이스 분석 결과,
.jobOccupation
과.distance
케이스는 이미 다른 부분에서 활발하게 사용되고 있습니다:
DateProfilePanelView
에서 선호 직군과 거리 관련 UI가 구현되어 있음ProfileIntent
에서 해당 기능들의 네비게이션 로직이 구현되어 있음- 관련 모델과 도메인 로직이 존재함
하지만
NavigationStack.swift
의 해당 케이스들은 아직EmptyView()
를 반환하고 있어 실제 편집 기능이 동작하지 않을 것입니다. 다음 작업이 필요합니다:
.jobOccupation
케이스에EditDreamPartnerJobView
구현 필요.distance
케이스에EditDreamPartnerDistanceView
구현 필요🔗 Analysis chain
Line range hint
87-90
: 남은 EmptyView() 구현에 대한 계획이 있나요?
.jobOccupation
과.distance
케이스가 아직EmptyView()
를 사용하고 있습니다. 이는 향후 PR에서 구현될 예정인가요?다음 스크립트로 관련 이슈나 PR이 있는지 확인해보겠습니다:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check for related issues or PRs about job occupation and distance implementations gh issue list --search "jobOccupation distance in:title,body" gh pr list --search "jobOccupation distance in:title,body"Length of output: 124
Script:
#!/bin/bash # Let's check the NavigationStack.swift file to understand the context better rg -A 10 -B 10 "case .jobOccupation|case .distance" --type swift # Also check for any TODO comments or related implementation plans rg -i "todo.*(\bjob\b|\bdistance\b|joboccupation)" --type swift # Check for any existing implementations or references to these features rg "jobOccupation|distance" --type swiftLength of output: 23462
Projects/DesignSystem/DesignCore/Sources/AgeUpDownView/AgeUpDownView.swift (3)
36-41
: 색상 상수를 DesignCore.Colors로 이동하는 것을 고려해주세요.현재 borderColor에서 직접 hex 값을 사용하고 있습니다. 다른 색상들처럼 DesignCore.Colors에서 관리하면 일관성 있는 색상 관리가 가능할 것 같습니다.
var borderColor: Color { switch self { - case .up: .init(hex: 0xA1BA91) - case .down: .init(hex: 0xE6B1C4) + case .up: DesignCore.Colors.greenBorder + case .down: DesignCore.Colors.pinkBorder } }
59-69
: 공개 API에 대한 문서화가 필요합니다.공개 초기화 메서드에 대한 문서화 주석을 추가하면 다른 개발자들이 컴포넌트를 더 쉽게 사용할 수 있을 것 같습니다.
+/// 나이 선택 뷰를 초기화합니다. +/// - Parameters: +/// - type: 위/아래 타입을 지정합니다. +/// - upperValue: 위쪽 나이 값 +/// - lowerValue: 아래쪽 나이 값 +/// - showPicker: 피커 표시 여부 public init( type: AgeUpDownType, upperValue: String?, lowerValue: String?, showPicker: Bool )
71-108
: 레이아웃 관련 상수값들을 분리해주세요.뷰에서 사용되는 여러 크기와 패딩값들이 하드코딩되어 있습니다. 이러한 값들을 상수로 분리하면 유지보수가 더 쉬워질 것 같습니다.
+ private enum Layout { + static let cornerRadius: CGFloat = 16 + static let strokeWidth: CGFloat = 10 + static let frameWidth: CGFloat = 92 + static let frameHeight: CGFloat = 62 + static let horizontalPadding: CGFloat = 8 + } public var body: some View { HStack(spacing: 8) { // ... ZStack { - RoundedRectangle(cornerRadius: 16) + RoundedRectangle(cornerRadius: Layout.cornerRadius) .inset(by: 4) .stroke( borderColor(), - lineWidth: 10 + lineWidth: Layout.strokeWidth ) } - .frame(width: 92, height: 62) + .frame(width: Layout.frameWidth, height: Layout.frameHeight) } - .padding(.horizontal, 8) + .padding(.horizontal, Layout.horizontalPadding)Projects/Core/CommonKit/Sources/AppCoordinator.swift (1)
Line range hint
1-146
: 아키텍처 관련 제안사항이상형 프로필 수정 기능을 추가하면서
AppCoordinator
에 관련 네비게이션 로직이 추가될 것으로 예상됩니다. 프로필 관련 네비게이션 로직을 별도의 코디네이터로 분리하는 것을 고려해보시면 좋을 것 같습니다.예를 들어:
- ProfileCoordinator를 만들어서 프로필 관련 화면 전환을 담당
- AppCoordinator는 high-level 네비게이션만 처리
- 각 도메인별 코디네이터가 해당 도메인의 네비게이션을 담당
이렇게 하면 앱이 커질수록 각 도메인의 네비게이션 로직을 더 깔끔하게 관리할 수 있습니다.
Projects/Features/SignUp/Sources/DreamPartnerInput/DreamPartnerAge/DreamPartnerAgeView.swift (2)
91-110
: 상/하한 나이 선택 UI 구현이 잘 되었습니다.상한/하한 나이 선택을 위한
AgeUpDownView
구현이 깔끔하게 되어있습니다. 각각의 뷰가 독립적으로 상태를 관리하며, 탭 제스처 처리도 적절히 구현되어 있습니다.다만 사용자 경험 향상을 위해 다음 사항들을 고려해보시면 좋을 것 같습니다:
- 상한 나이가 하한 나이보다 작아지지 않도록 validation 로직 추가
- 선택된 나이 범위에 대한 시각적 피드백 제공
Line range hint
119-124
: 나이 선택 피커 구현이 효율적입니다.
AgePickerView
구현이 간결하고 효과적입니다. 바텀 시트 형태의 UI와 트랜지션 애니메이션이 자연스럽게 구현되어 있습니다.접근성 향상을 위해 다음 사항을 고려해보시면 좋을 것 같습니다:
- VoiceOver 지원을 위한 accessibility 레이블 추가
- 키보드로도 나이를 입력할 수 있는 대체 수단 제공
Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift (1)
Line range hint
232-246
: Mock 데이터의 연령대 값이 부적절합니다.Mock 데이터에서
upperBirthYear
와lowerBirthYear
가 모두 4로 설정되어 있는데, 이는 실제 출생연도 값으로는 적절하지 않습니다. 실제 사용 사례를 반영하는 값(예: 1990, 2000 등)으로 수정이 필요합니다.다음과 같이 수정을 제안합니다:
public static var mock: DreamPartnerInfo { .init( - upperBirthYear: 4, - lowerBirthYear: 4, + upperBirthYear: 1990, + lowerBirthYear: 2000, jobOccupations: [Projects/Features/Home/Sources/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeView.swift (5)
36-39
:showUpperPicker
와showLowerPicker
상태 관리 개선 제안두 개의
@State
Boolean 변수를 사용하여 picker의 표시 상태를 관리하고 있습니다. 이는 상태 관리가 복잡해질 수 있고, 두 변수가 동시에true
가 될 가능성도 있습니다. 하나의 enum과 단일 상태 변수를 사용하여 현재 활성화된 picker를 관리하면 코드의 명확성과 안정성이 향상됩니다.다음과 같이 수정할 수 있습니다:
@State private var activePicker: ActivePicker? enum ActivePicker { case upper case lower }그리고 picker의 표시 로직과 탭 제스처를 다음과 같이 변경합니다:
// AgeUpDownView 상위 연령 .onTapGesture { activePicker = .upper } // AgeUpDownView 하위 연령 .onTapGesture { activePicker = .lower } // picker 표시 로직 if let activePicker = activePicker { VStack { Spacer() AgePickerView( selectedValue: activePicker == .upper ? $upperValue : $lowerValue ) .padding(.bottom, 90) .frame(height: 300) } .transition(.move(edge: .bottom)) .ignoresSafeArea() }
102-104
:.ignoresSafeArea(.keyboard)
의 적용 위치 조정 필요
.ignoresSafeArea(.keyboard)
를 전체 뷰에 적용하면 키보드로 인해 중요한 UI 요소가 가려질 수 있습니다. 키보드에 의해 가려지지 않도록 스크롤 뷰를 사용하거나, 필요한 뷰에만 선택적으로 적용하는 것이 좋습니다.예를 들어, 스크롤 가능한 콘텐츠를
ScrollView
로 감싸고, 키보드에 의해 콘텐츠가 밀리지 않도록 설정할 수 있습니다.
112-116
: 프리뷰에서NavigationView
대신NavigationStack
사용 권장SwiftUI의 최신 네비게이션 구조를 따르기 위해
NavigationStack
을 사용하는 것이 좋습니다. 향후 호환성을 위해 프리뷰에서도 이를 적용해주세요.#Preview { NavigationStack { EditDateProfileAgeRangeView(userInfo: .mock) } }
70-81
: Picker 표시 로직의 애니메이션 및 전환 효과 검토picker가 나타날 때
.transition(.move(edge: .bottom))
을 사용하고 있으나,if
문 내에서 애니메이션이 제대로 적용되지 않을 수 있습니다.withAnimation
블록을 사용하여 상태 변화에 애니메이션을 적용하는 것을 고려해주세요.예를 들어:
.withAnimation { activePicker = .upper }또는
showUpperPicker
와showLowerPicker
의 상태 변경 시 애니메이션을 추가합니다.
90-95
:onChange
대신Binding
활용 고려
upperValue
와lowerValue
의 변경을 감지하기 위해onChange
를 사용하고 있습니다. 대신Binding
을 활용하여 값이 변경될 때 즉시intent
에 전달할 수 있습니다.예를 들어,
AgePickerView
에 전달하는selectedValue
를 커스텀Binding
으로 만들어 값 변경 시intent
를 호출합니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (12)
Projects/App/Sources/Navigation/NavigationStack.swift
(1 hunks)Projects/Core/CommonKit/Sources/AppCoordinator.swift
(1 hunks)Projects/Core/CoreKit/Sources/AuthState.swift
(0 hunks)Projects/Core/NetworkKit/Sources/ProfileService/ProfileService.swift
(2 hunks)Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift
(1 hunks)Projects/DesignSystem/DesignCore/Sources/AgeUpDownView/AgePickerView.swift
(1 hunks)Projects/DesignSystem/DesignCore/Sources/AgeUpDownView/AgeUpDownView.swift
(1 hunks)Projects/Features/Home/Sources/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeIntent.swift
(1 hunks)Projects/Features/Home/Sources/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeModel.swift
(1 hunks)Projects/Features/Home/Sources/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeView.swift
(1 hunks)Projects/Features/SignUp/Sources/DreamPartnerInput/DreamPartnerAge/DreamPartnerAgeView.swift
(2 hunks)Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift
(1 hunks)
💤 Files with no reviewable changes (1)
- Projects/Core/CoreKit/Sources/AuthState.swift
🧰 Additional context used
🪛 SwiftLint (0.57.0)
Projects/Core/NetworkKit/Sources/ProfileService/ProfileService.swift
[Warning] 82-82: TODOs should be resolved (API 구현)
(todo)
Projects/Features/Home/Sources/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeIntent.swift
[Warning] 16-16: Prefer at least one space after slashes for comments
(comment_spacing)
[Warning] 34-34: Prefer at least one space after slashes for comments
(comment_spacing)
[Warning] 52-52: Prefer at least one space after slashes for comments
(comment_spacing)
[Warning] 16-16: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
(mark)
[Warning] 34-34: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
(mark)
[Warning] 52-52: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
(mark)
Projects/Features/Home/Sources/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeModel.swift
[Warning] 15-15: Prefer at least one space after slashes for comments
(comment_spacing)
[Warning] 30-30: Prefer at least one space after slashes for comments
(comment_spacing)
[Warning] 47-47: Prefer at least one space after slashes for comments
(comment_spacing)
[Warning] 15-15: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
(mark)
[Warning] 30-30: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
(mark)
[Warning] 47-47: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
(mark)
🔇 Additional comments (5)
Projects/Core/NetworkKit/Sources/ProfileService/ProfileService.swift (1)
25-26
: 프로토콜 선언이 잘 되어있습니다!
메서드 시그니처가 기존 패턴과 일관성있게 잘 정의되어 있습니다.
Projects/App/Sources/Navigation/NavigationStack.swift (1)
86-86
: 구현이 PR 목적과 일치합니다!
EmptyView()
를 EditDateProfileAgeRangeView
로 교체한 것이 이상형 프로필의 선호 연령대 수정 기능 구현이라는 PR의 목적과 잘 부합합니다.
Projects/DesignSystem/DesignCore/Sources/AgeUpDownView/AgeUpDownView.swift (1)
51-113
: 전반적으로 잘 구현된 컴포넌트입니다!
SwiftUI 패턴을 잘 따르고 있으며, 타입과 뷰의 책임이 명확하게 분리되어 있습니다. 위에서 제안된 개선사항들을 반영하면 더욱 완성도 높은 컴포넌트가 될 것 같습니다.
Projects/Core/CommonKit/Sources/AppCoordinator.swift (1)
37-38
: 상태 변경 최적화 및 로깅 개선이 확인되었습니다.
불필요한 상태 업데이트를 방지하는 가드문 추가는 좋은 최적화입니다. 상태 변경 로깅도 디버깅에 도움이 될 것 같습니다.
Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift (1)
159-160
: 속성 변경이 요구사항과 잘 부합합니다.
upperBirthYear
와 lowerBirthYear
속성을 가변(var
)으로 변경한 것은 이상형 프로필의 선호 연령대 수정 기능 구현에 적절합니다.
Projects/DesignSystem/DesignCore/Sources/AgeUpDownView/AgePickerView.swift
Show resolved
Hide resolved
.../DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeModel.swift
Show resolved
Hide resolved
var upperValue: String? | ||
var lowerValue: String? | ||
|
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
상태 프로퍼티에 @published 수정자 추가 필요
upperValue
와 lowerValue
는 UI 업데이트를 위해 @Published
수정자가 필요합니다. SwiftUI 뷰가 이 값들의 변경을 감지하고 자동으로 업데이트되도록 하기 위함입니다.
다음과 같이 수정해주세요:
- var upperValue: String?
- var lowerValue: String?
+ @Published var upperValue: String?
+ @Published var lowerValue: String?
📝 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.
var upperValue: String? | |
var lowerValue: String? | |
@Published var upperValue: String? | |
@Published var lowerValue: String? | |
...DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeIntent.swift
Show resolved
Hide resolved
...DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeIntent.swift
Show resolved
Hide resolved
HStack { | ||
Text(type.imoji) | ||
Text("내 나이보다") | ||
Text(type.text) | ||
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
접근성 지원을 개선해주세요.
현재 구현에는 접근성 레이블이 누락되어 있습니다. VoiceOver 사용자를 위해 적절한 접근성 레이블을 추가하면 좋을 것 같습니다.
HStack {
Text(type.imoji)
+ .accessibilityHidden(true)
Text("내 나이보다")
Text(type.text)
Text("로")
}
+.accessibilityElement(children: .combine)
+.accessibilityLabel("내 나이보다 \(type.text)로")
📝 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.
HStack { | |
Text(type.imoji) | |
Text("내 나이보다") | |
Text(type.text) | |
Text("로") | |
} | |
HStack { | |
Text(type.imoji) | |
.accessibilityHidden(true) | |
Text("내 나이보다") | |
Text(type.text) | |
Text("로") | |
} | |
.accessibilityElement(children: .combine) | |
.accessibilityLabel("내 나이보다 \(type.text)로") |
...s/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeView.swift
Show resolved
Hide resolved
...s/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeView.swift
Show resolved
Hide resolved
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: 7
🧹 Outside diff range and nitpick comments (22)
Projects/DesignSystem/DesignCore/Sources/AgeUpDownView/AgePickerView.swift (3)
11-16
: 공개 API에 대한 문서화가 필요합니다공개 API에 대한 문서화가 누락되었습니다. 다른 개발자들의 이해를 돕기 위해 DocC 문서화를 추가해주세요.
+/// 사용자가 나이를 선택할 수 있는 휠 피커 뷰입니다. +/// - Note: 기본값으로 "상관없어요" 옵션을 제공합니다. public struct AgePickerView: View { @Binding var selectedValue: String? + /// AgePickerView를 초기화합니다. + /// - Parameter selectedValue: 선택된 나이값을 저장하는 바인딩 public init(selectedValue: Binding<String?>) { self._selectedValue = selectedValue }
19-19
: 피커 레이블이 모호합니다"숫자 선택"이라는 레이블이 너무 일반적입니다. 컨텍스트에 맞게 "나이 선택"으로 변경하는 것이 좋겠습니다.
- Picker("숫자 선택", selection: $selectedValue) { + Picker("나이 선택", selection: $selectedValue) {
32-32
: SwiftUI 프리뷰가 누락되었습니다개발 및 디자인 반복 작업을 위해 SwiftUI 프리뷰를 추가해주세요.
#Preview { AgePickerView(selectedValue: .constant("25")) }Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift (1)
37-40
: 에러 시나리오 테스트를 위한 기능 추가를 고려해보세요.테스트 시나리오의 완성도를 높이기 위해 에러 상황을 시뮬레이션할 수 있는 기능 추가를 제안드립니다.
다음과 같은 구현을 고려해보세요:
+ private var shouldSimulateError = false + + public func setShouldSimulateError(_ value: Bool) { + shouldSimulateError = value + } + public func requestPutPartnerInfo(userInfo: UserInfo) async throws { + if shouldSimulateError { + throw NetworkError.serverError + } print("✅ [ProfileServiceMock] requestPutPartnerInfo 성공!") return }Projects/Features/Home/Sources/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeModel.swift (3)
48-61
: 프로토콜 문서화 및 유효성 검사 메서드 추가 필요프로토콜 메서드에 대한 문서화가 필요하며, 연령대 범위를 검증하는 메서드도 추가하면 좋겠습니다.
protocol EditDateProfileAgeRangeModelActionable: AnyObject { + /// 상한 연령 설정 func setUpperValue(value: String?) + /// 하한 연령 설정 func setLowerValue(value: String?) + /// 입력값 유효성 상태 설정 func setValidation(value: Bool) + /// 연령대 범위 유효성 검사 + func validateAgeRange() -> Bool // default func setLoading(status: Bool) // error func showErrorView(error: ErrorModel) func showErrorAlert(error: ErrorModel) func resetError() }
15-15
: MARK 주석 형식 수정 필요SwiftLint 경고에 따라 MARK 주석 형식을 수정해주세요.
- //MARK: Stateful + // MARK: - Stateful - //MARK: State Properties + // MARK: - State Properties - //MARK: - Actionable + // MARK: - ActionableAlso applies to: 30-30, 47-47
🧰 Tools
🪛 SwiftLint (0.57.0)
[Warning] 15-15: Prefer at least one space after slashes for comments
(comment_spacing)
[Warning] 15-15: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
(mark)
1-12
: 파일 수준의 문서화 추가 필요이 모델의 목적과 사용 방법에 대한 문서화를 추가하면 좋겠습니다.
// // EditDateProfileAgeRangeModel.swift // Home // // Created by 김지수 on 11/25/24. // Copyright © 2024 com.weave. All rights reserved. // + /// 이상형 프로필의 선호 연령대를 관리하는 모델입니다. + /// - 연령대의 상한값과 하한값을 관리합니다. + /// - ObservableObject를 준수하여 SwiftUI 뷰와 바인딩됩니다.Projects/Features/Home/Sources/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeIntent.swift (5)
16-16
: MARK 주석 형식을 수정해주세요.SwiftLint 규칙에 따라 MARK 주석 형식을 수정해야 합니다.
-//MARK: - Intent +// MARK: - Intent🧰 Tools
🪛 SwiftLint (0.57.0)
[Warning] 16-16: Prefer at least one space after slashes for comments
(comment_spacing)
[Warning] 16-16: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
(mark)
34-34
: MARK 주석 형식을 수정해주세요.SwiftLint 규칙에 따라 MARK 주석 형식을 수정해야 합니다.
-//MARK: - Intentable +// MARK: - Intentable🧰 Tools
🪛 SwiftLint (0.57.0)
[Warning] 34-34: Prefer at least one space after slashes for comments
(comment_spacing)
[Warning] 34-34: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
(mark)
36-45
: 프로토콜 메서드에 문서화 주석이 필요합니다.각 메서드의 목적과 파라미터에 대한 설명을 추가하면 코드의 가독성이 향상될 것 같습니다.
예시:
/// 상한 연령값을 변경합니다. /// - Parameter value: 새로운 상한 연령값 func onChangeUpperValue(value: String?)
52-52
: MARK 주석 형식을 수정해주세요.SwiftLint 규칙에 따라 MARK 주석 형식을 수정해야 합니다.
-//MARK: - Intentable +// MARK: - Intentable🧰 Tools
🪛 SwiftLint (0.57.0)
[Warning] 52-52: Prefer at least one space after slashes for comments
(comment_spacing)
[Warning] 52-52: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
(mark)
78-81
: 오류 메시지를 더 구체적으로 표시해주세요.현재는 일반적인 오류 메시지만 표시되고 있습니다. 사용자가 이해하기 쉽도록 구체적인 오류 메시지를 추가하면 좋을 것 같습니다.
예시:
} catch { model?.setLoading(status: false) let errorMessage = "프로필 수정 중 오류가 발생했습니다. 다시 시도해 주세요." ToastHelper.showErrorMessage(errorMessage) }Projects/App/Sources/Navigation/NavigationStack.swift (1)
jobOccupation
과distance
케이스에 대한 구현이 필요합니다.코드베이스 분석 결과, 이 두 케이스는
EditDreamPartnerViewType
enum의 일부이며, 사용자의 이상형 프로필 편집과 관련된 중요한 기능입니다:
jobOccupation
: 이상형의 직군 설정distance
: 이상형과의 거리 설정이 기능들은 다음과 같은 이유로 구현이 필요합니다:
- 앱의 다른 부분에서 이미 관련 데이터 모델과 서비스가 구현되어 있음
- 사용자 프로필의 필수 정보로 사용되고 있음
- 프로필 패널과 데이트 프로필 패널에서 이 정보들을 표시하고 있음
🔗 Analysis chain
Line range hint
87-90
: 다른 빈 뷰들에 대한 구현 계획을 확인해주세요.
jobOccupation
과distance
케이스에 대해 아직EmptyView()
가 반환되고 있습니다. 이는 향후 구현될 예정인지, 아니면 의도적으로 비워둔 것인지 확인이 필요합니다.다음 스크립트로 관련 이슈나 작업 항목이 있는지 확인해보겠습니다:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check for related issues about jobOccupation and distance implementations gh issue list --search "jobOccupation distance in:title,body" --state openLength of output: 76
Script:
#!/bin/bash # Search for any references to jobOccupation and distance in the codebase rg -A 5 "jobOccupation|distance" --type swift # Also check the enum definition to understand the context better ast-grep --pattern 'enum $_ { $$$ case jobOccupation $$$ case distance $$$ }'Length of output: 50777
Projects/DesignSystem/DesignCore/Sources/AgeUpDownView/AgeUpDownView.swift (2)
51-70
: 문서화 개선 제안공용 API에 대한 문서화가 누락되어 있습니다. 다음 항목들에 대한 문서 주석 추가를 제안드립니다:
AgeUpDownView
구조체- 공개 초기화 메서드
- 각 매개변수의 용도
다음과 같은 문서화를 제안드립니다:
+/// 나이 선택을 위한 상/하한 선택 뷰 +/// 사용자가 자신의 나이를 기준으로 선호하는 나이 범위를 설정할 수 있습니다. public struct AgeUpDownView: View { // ... + /// 나이 선택 뷰를 초기화합니다. + /// - Parameters: + /// - type: 상한 또는 하한 선택 타입 + /// - upperValue: 상한 나이 값 + /// - lowerValue: 하한 나이 값 + /// - showPicker: 선택기 표시 여부 public init( type: AgeUpDownType, upperValue: String?, lowerValue: String?, showPicker: Bool ) {
71-108
: 상수 추출 및 미리보기 추가 제안
- 하드코딩된 수치들을 상수로 추출하면 유지보수성이 향상될 것 같습니다.
- SwiftUI 미리보기를 추가하면 개발 효율성이 향상될 것 같습니다.
다음과 같은 개선을 제안드립니다:
public struct AgeUpDownView: View { + private enum Constants { + static let cornerRadius: CGFloat = 16 + static let strokeWidth: CGFloat = 10 + static let boxWidth: CGFloat = 92 + static let boxHeight: CGFloat = 62 + static let horizontalPadding: CGFloat = 8 + } // ... existing code ... public var body: some View { // ... update usage of constants ... } } +#Preview { + VStack(spacing: 20) { + AgeUpDownView( + type: .up, + upperValue: "25", + lowerValue: nil, + showPicker: true + ) + AgeUpDownView( + type: .down, + upperValue: nil, + lowerValue: "20", + showPicker: false + ) + } + .padding() +}Projects/Features/Home/Sources/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeView.swift (3)
15-34
: 문서화 개선이 필요합니다.뷰의 목적과
userInfo
파라미터의 역할에 대한 문서화가 있으면 좋겠습니다.다음과 같이 문서 주석을 추가하는 것을 제안합니다:
+/// 이상형 프로필의 선호 연령대를 수정하는 뷰입니다. +/// - Parameters: +/// - userInfo: 현재 사용자의 프로필 정보 public struct EditDateProfileAgeRangeView: View {
41-109
: 접근성 개선이 필요합니다.사용자 경험을 향상시키기 위해 다음 개선사항들을 제안합니다:
AgeUpDownView( type: .up, upperValue: upperValue, lowerValue: lowerValue, showPicker: showUpperPicker ) +.accessibilityLabel("상한 연령 선택") +.accessibilityHint("상한 연령을 선택하려면 두 번 탭하세요")또한 피커 값이 변경될 때 햅틱 피드백을 추가하면 좋을 것 같습니다:
.onChange(of: upperValue) { + UIImpactFeedbackGenerator(style: .light).impactOccurred() intent.onChangeUpperValue(value: upperValue) }
112-116
: 프리뷰 케이스를 추가하면 좋겠습니다.다양한 상황에서의 UI를 확인할 수 있도록 프리뷰 케이스를 추가하는 것이 좋겠습니다.
예를 들어:
- 로딩 상태
- 에러 상태
- 다크 모드
- 다양한 기기 크기
Projects/Features/SignUp/Sources/DreamPartnerInput/DreamPartnerAge/DreamPartnerAgeView.swift (2)
91-110
: 상/하한 나이 선택 UI 구현이 개선되었습니다! 👍AgeUpDownView 컴포넌트를 활용한 구현이 깔끔하고 재사용성이 높아 보입니다. 상/하한 나이 선택 UI가 각각 독립적으로 동작하며, 탭 제스처 처리도 적절히 구현되어 있습니다.
다만, 상/하한 나이 선택 시 유효성 검사 로직을 추가하면 좋을 것 같습니다. 예를 들어:
.onChange(of: upperValue) { + guard let upper = Int(upperValue ?? ""), + let lower = Int(lowerValue ?? "") else { return } + if upper < lower { + upperValue = lowerValue + } intent.onChangeUpperValue(value: upperValue) }
Line range hint
119-124
: 피커 뷰 구현이 단순화되었습니다! 🎉기존의 BottomSheetPickerView를 AgePickerView로 대체하여 코드가 더욱 간결해졌습니다. 트랜지션 효과와 레이아웃 처리가 잘 되어있습니다.
접근성 지원을 위해 VoiceOver 레이블을 추가하면 좋을 것 같습니다:
AgePickerView( selectedValue: showUpperPicker ? $upperValue : $lowerValue ) +.accessibilityLabel(showUpperPicker ? "선호하는 상한 나이" : "선호하는 하한 나이") .padding(.bottom, 90)
Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift (2)
159-160
: 속성의 가변성 변경이 적절하나 유효성 검사가 필요합니다.나이 범위 편집 기능을 위해
upperBirthYear
와lowerBirthYear
를var
로 변경한 것은 적절합니다. 하지만 유효한 생년 범위를 보장하기 위한 유효성 검사 로직이 필요해 보입니다.다음과 같은 방식으로 속성 래퍼(Property Wrapper)를 사용하여 유효성 검사를 구현하는 것을 제안드립니다:
@propertyWrapper public struct BirthYearValidated { private var value: Int? public var wrappedValue: Int? { get { value } set { if let year = newValue { // 현재 연도 기준으로 유효한 범위 설정 (예: 18-65세) let currentYear = Calendar.current.component(.year, from: Date()) let minYear = currentYear - 65 let maxYear = currentYear - 18 value = year.clamped(to: minYear...maxYear) } else { value = nil } } } public init(wrappedValue: Int?) { self.value = wrappedValue } } public struct DreamPartnerInfo: Equatable, Hashable { @BirthYearValidated public var upperBirthYear: Int? @BirthYearValidated public var lowerBirthYear: Int? // ... }
Line range hint
232-246
: Mock 데이터의 생년 값이 부적절합니다.Mock 데이터에서
upperBirthYear
와lowerBirthYear
가 모두 4로 설정되어 있습니다. 이는 실제 사용 사례와 맞지 않으며 테스트 시 문제가 될 수 있습니다.다음과 같이 현실적인 값으로 수정하는 것을 제안드립니다:
public static var mock: DreamPartnerInfo { .init( - upperBirthYear: 4, - lowerBirthYear: 4, + upperBirthYear: 1990, + lowerBirthYear: 1995, jobOccupations: [ "MEDIA_ENTERTAINMENT",
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (12)
Projects/App/Sources/Navigation/NavigationStack.swift
(1 hunks)Projects/Core/CommonKit/Sources/AppCoordinator.swift
(1 hunks)Projects/Core/CoreKit/Sources/AuthState.swift
(0 hunks)Projects/Core/NetworkKit/Sources/ProfileService/ProfileService.swift
(2 hunks)Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift
(1 hunks)Projects/DesignSystem/DesignCore/Sources/AgeUpDownView/AgePickerView.swift
(1 hunks)Projects/DesignSystem/DesignCore/Sources/AgeUpDownView/AgeUpDownView.swift
(1 hunks)Projects/Features/Home/Sources/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeIntent.swift
(1 hunks)Projects/Features/Home/Sources/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeModel.swift
(1 hunks)Projects/Features/Home/Sources/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeView.swift
(1 hunks)Projects/Features/SignUp/Sources/DreamPartnerInput/DreamPartnerAge/DreamPartnerAgeView.swift
(2 hunks)Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift
(1 hunks)
💤 Files with no reviewable changes (1)
- Projects/Core/CoreKit/Sources/AuthState.swift
🧰 Additional context used
🪛 SwiftLint (0.57.0)
Projects/Core/NetworkKit/Sources/ProfileService/ProfileService.swift
[Warning] 82-82: TODOs should be resolved (API 구현)
(todo)
Projects/Features/Home/Sources/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeIntent.swift
[Warning] 16-16: Prefer at least one space after slashes for comments
(comment_spacing)
[Warning] 34-34: Prefer at least one space after slashes for comments
(comment_spacing)
[Warning] 52-52: Prefer at least one space after slashes for comments
(comment_spacing)
[Warning] 16-16: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
(mark)
[Warning] 34-34: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
(mark)
[Warning] 52-52: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
(mark)
Projects/Features/Home/Sources/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeModel.swift
[Warning] 15-15: Prefer at least one space after slashes for comments
(comment_spacing)
[Warning] 30-30: Prefer at least one space after slashes for comments
(comment_spacing)
[Warning] 47-47: Prefer at least one space after slashes for comments
(comment_spacing)
[Warning] 15-15: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
(mark)
[Warning] 30-30: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
(mark)
[Warning] 47-47: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
(mark)
🔇 Additional comments (7)
Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift (1)
37-40
: 구현이 적절해 보입니다!
mock 서비스의 기본 구현이 다른 메서드들과 일관성 있게 작성되었습니다.
Projects/Core/NetworkKit/Sources/ProfileService/ProfileService.swift (1)
25-26
: 프로토콜 메서드 선언이 적절합니다.
메서드 시그니처가 기존 프로토콜 메서드들과 일관성있게 설계되었습니다.
Projects/Features/Home/Sources/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeIntent.swift (2)
9-14
: 모듈 임포트가 적절합니다!
필요한 모든 모듈들이 잘 임포트되어 있습니다.
17-31
: 클래스 구조가 잘 설계되었습니다!
- 의존성 주입이 생성자를 통해 적절히 구현되었습니다.
- 메모리 누수 방지를 위해 model을 weak 참조로 선언한 것이 좋습니다.
Projects/App/Sources/Navigation/NavigationStack.swift (1)
86-86
: 구현이 PR 목적과 잘 부합합니다!
EmptyView()
를 EditDateProfileAgeRangeView
로 교체한 것이 이상형 프로필의 선호 연령대 수정 기능 구현이라는 PR의 목적에 잘 부합합니다.
Projects/Core/CommonKit/Sources/AppCoordinator.swift (1)
37-38
: 상태 변경 로직 개선이 확인되었습니다.
불필요한 상태 업데이트를 방지하는 가드문이 추가되어 앱의 성능이 개선되었습니다. 디버깅을 위한 로그도 적절히 추가되었습니다.
다만, 이상형 프로필의 연령대 수정 기능과 관련하여 인증 상태 변경이 정상적으로 처리되는지 확인이 필요합니다.
아래 스크립트로 프로필 수정 관련 인증 처리를 확인해보겠습니다:
Projects/Features/Home/Sources/DateProfilePanel/EditDateProfile/EditDateProfileAgeRange/EditDateProfileAgeRangeView.swift (1)
9-13
: 필요한 모듈들이 적절하게 임포트되었습니다.
SwiftUI 뷰 구현에 필요한 기본 모듈들과 프로젝트의 커스텀 모듈들이 잘 구성되어 있습니다.
구현사항
스크린샷(선택)
Summary by CodeRabbit
새로운 기능
AgePickerView
및AgeUpDownView
컴포넌트 도입.EditDateProfileAgeRangeView
컴포넌트 추가로 사용자 프로필의 나이 범위 편집 기능 강화.버그 수정
문서화
리팩토링
DreamPartnerAgeView
에서 나이 선택 로직 간소화.