Skip to content
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-140] 프로필 수정 - 내 직군 정보 #47

Merged
merged 6 commits into from
Nov 24, 2024

Conversation

jisu15-kim
Copy link
Member

@jisu15-kim jisu15-kim commented Nov 24, 2024

구현사항

  • 내 직군 정보 수정 기능 구현

스크린샷(선택)

직군 수정

Summary by CodeRabbit

  • New Features

    • 사용자 프로필 및 꿈 파트너 편집을 위한 새로운 내비게이션 기능 추가.
    • 사용자 정보를 비동기적으로 업데이트하는 새로운 메서드 추가.
    • 프로필 편집 화면에서 직업 선택 기능 추가.
  • 변경 사항

    • 사용자 정보 구조체의 속성을 변경하여 수정 가능하게 조정.
    • 사용자 프로필 편집에 대한 오류 처리 및 비동기 작업 개선.
  • 버그 수정

    • 사용자 정보 가져오기 및 위젯 삭제 요청의 오류 처리 개선.

@jisu15-kim jisu15-kim added the Feature 기능 label Nov 24, 2024
@jisu15-kim jisu15-kim self-assigned this Nov 24, 2024
Copy link
Contributor

coderabbitai bot commented Nov 24, 2024

Walkthrough

이 변경 사항은 OpenApiGenerator/Sources/OpenapiGenerated/Client.swiftOpenApiGenerator/Sources/OpenapiGenerated/Types.swift 파일에서 사용자 정보 업데이트에 사용되는 HTTP 메소드를 PATCH에서 PUT으로 변경하는 것을 포함합니다. 이 변경은 API의 동작 방식에 영향을 미치며, updateMyUserInfo 함수의 메소드 서명과 문서 주석이 업데이트되었습니다. 추가적으로, 사용자 정보 요청을 위한 UpdateMyUserInfoRequest 구조체의 필수 속성이 변경되었습니다. 여러 파일에서 프로필 편집 및 관련 기능을 추가하는 변경 사항도 포함되어 있습니다.

Changes

파일 경로 변경 요약
OpenApiGenerator/Sources/OpenapiGenerated/Client.swift updateMyUserInfo 함수의 HTTP 메소드를 PATCH에서 PUT으로 변경.
OpenApiGenerator/Sources/OpenapiGenerated/Types.swift updateMyUserInfo 함수의 HTTP 메소드를 PATCH에서 PUT으로 변경. UpdateMyUserInfoRequest 구조체의 속성 변경 (필수 속성으로 변경 및 새로운 속성 추가).
OpenApiGenerator/Sources/openapi-generator-cli/3days-oas 서브프로젝트 커밋 참조를 업데이트.
Projects/App/Sources/Navigation/NavigationStack.swift PathType 열거형에 .editProfile.editDreamPartner 케이스 추가.
Projects/Core/CommonKit/Sources/Path/PathTypes.swift PathType 열거형에 editProfileeditDreamPartner 케이스 추가, 새로운 열거형 추가.
Projects/Core/NetworkKit/Sources/ProfileService/ProfileService.swift ProfileServiceProtocolrequestPutUserInfo 메소드 추가.
Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift ProfileServiceMockrequestPutUserInfo 메소드 추가.
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobIntent.swift EditProfileJobIntent 클래스 추가 및 관련 메소드 정의.
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobModel.swift EditProfileJobModel 클래스 추가 및 상태 관리 관련 프로퍼티 정의.
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobView.swift EditProfileJobView 구조체 추가 및 UI 구성.
Projects/Features/Home/Sources/Profile/ProfileIntent.swift onAppearrequestDeleteWidget 메소드 수정.
Projects/Features/Home/Sources/ProfilePannel/ProfilePannelIntent.swift onTapEditJobOccupationIcon 메소드 추가.
Projects/Features/Home/Sources/ProfilePannel/ProfilePannelView.swift horizonIconKeyValueView 메소드에 매개변수 추가.
Projects/Features/Home/UnitTest/EditProfileJobOccupationTest.swift EditProfileJobOccupation 기능에 대한 테스트 추가.
Projects/Features/Home/UnitTest/WidgetUnitTest.swift WidgetWritingIntent의 초기화에 successHandler 클로저 추가.
Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift UserInfo 및 관련 구조체의 프로퍼티를 변경하여 가변 속성으로 수정.

Possibly related PRs

Suggested labels

Design

🐇 "변경된 코드에 기뻐하며,
사용자 정보를 더욱 간편하게,
프로필 편집이 쉬워졌어요,
모두가 함께 웃을 수 있도록!
새로운 기능과 함께 뛰어보아요! 🐾"

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 SwiftLint (0.57.0)
OpenApiGenerator/Sources/OpenapiGenerated/Types.swift

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?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

🧹 Outside diff range and nitpick comments (20)
Projects/Features/Home/UnitTest/EditProfileJobOccupationTest.swift (2)

13-17: 테스트 구조체에 문서화 추가 필요

테스트의 목적과 테스트하는 시나리오에 대한 설명을 추가하면 좋을 것 같습니다.

다음과 같이 문서화를 추가해보세요:

+/// 프로필 직군 정보 수정 기능 테스트를 위한 구조체
+/// - state: 직군 선택 상태를 관리하는 모델
+/// - intent: 사용자 인터랙션을 처리하는 인텐트
 struct EditProfileJobOccupationTests {
     
     let state: EditProfileJobModel
     let intent: EditProfileJobIntent

18-25: 다양한 테스트 케이스 추가 필요

현재는 기본 mock 데이터만 사용하고 있습니다. 다양한 시나리오를 테스트하기 위해 여러 케이스의 mock 데이터를 추가하면 좋을 것 같습니다.

예를 들어, 다음과 같은 케이스들을 추가해보세요:

  • 직군이 선택되지 않은 상태
  • 여러 직군이 선택된 상태
  • 잘못된 직군 데이터가 있는 상태
Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift (1)

31-35: Mock 구현의 테스트 커버리지 개선 필요

현재 구현은 성공 케이스만 처리하고 있습니다. Mock 객체의 완성도를 높이기 위해 다음 사항들을 고려해주세요:

  1. 실패 시나리오 테스트를 위한 에러 케이스 추가
  2. 입력된 UserInfo 데이터 검증
  3. 테스트에서 호출 여부를 확인할 수 있는 프로퍼티 추가

다음과 같은 개선된 구현을 제안드립니다:

 public final class ProfileServiceMock: ProfileServiceProtocol {
+    public var requestPutUserInfoCallCount = 0
+    public var shouldFail = false
+    public var lastUserInfo: UserInfo?
+
     public func requestPutUserInfo(userInfo: UserInfo) async throws {
+        requestPutUserInfoCallCount += 1
+        lastUserInfo = userInfo
+        
+        if shouldFail {
+            throw NSError(domain: "ProfileServiceMock", code: -1, 
+                         userInfo: [NSLocalizedDescriptionKey: "의도된 실패"])
+        }
         print("✅ [ProfileServiceMock] requestPutUserInfo 성공!")
         return
     }
 }
Projects/Features/Home/Sources/ProfilePannel/ProfilePannelIntent.swift (1)

33-33: 문서화 추가 필요

프로토콜 메서드의 목적과 사용 방법을 명확히 하기 위해 문서 주석을 추가하는 것이 좋습니다.

다음과 같이 문서화를 추가해보세요:

+    /// 직군 정보 수정 아이콘을 탭했을 때 호출되는 메서드입니다.
+    /// 사용자를 직군 정보 수정 화면으로 이동시킵니다.
     func onTapEditJobOccupationIcon()
Projects/Features/Home/UnitTest/WidgetUnitTest.swift (1)

Line range hint 1-89: 프로필 정보 업데이트 관련 테스트 케이스 추가 필요

프로필 수정 기능이 추가됨에 따라, 위젯이 업데이트된 프로필 정보와 올바르게 동기화되는지 확인하는 테스트 케이스가 필요합니다.

다음과 같은 테스트 케이스 추가를 제안드립니다:

@Test func updateWidgetAfterProfileChange() async throws {
    // 프로필 정보 업데이트
    let updatedProfile = UserProfile(/* updated profile info */)
    writeIntent.updateProfile(updatedProfile)
    
    // 위젯 상태 검증
    #expect(writeState.isProfileUpdated == true)
    #expect(writeState.widgetContent.contains(updatedProfile.jobInfo))
}
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobModel.swift (2)

17-17: MARK 주석 형식을 수정해주세요

Swift 스타일 가이드에 따라 MARK 주석은 다음과 같은 형식을 따라야 합니다:

  • // MARK: ... 또는
  • // MARK: - ...

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

-    //MARK: Stateful
+    // MARK: - Stateful

-    //MARK: State Properties
+    // MARK: - State Properties

-//MARK: - Actionable
+// MARK: - Actionable

Also applies to: 32-32, 60-60

🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 17-17: Prefer at least one space after slashes for comments

(comment_spacing)


[Warning] 17-17: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)


28-29: 에러 처리 방식에 대한 문서화가 필요합니다

showErrorViewshowErrorAlert의 사용 목적과 차이점을 명확히 하는 문서화가 필요합니다.

각 에러 처리 메서드에 다음과 같이 문서 주석을 추가해주세요:

+    /// 전체 화면 에러 표시가 필요한 경우 사용
     func showErrorView(error: ErrorModel) {
         showErrorView = error
     }
+    /// 팝업 형태의 에러 알림이 필요한 경우 사용
     func showErrorAlert(error: ErrorModel) {
         showErrorAlert = error
     }

Also applies to: 90-95

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobIntent.swift (3)

16-16: MARK 주석 형식을 수정해주세요.

Swift 코딩 컨벤션에 따라 MARK 주석은 다음과 같은 형식을 따라야 합니다:

-//MARK: - Intent
+// MARK: - Intent

Also applies to: 38-38, 57-57

🧰 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)


23-27: 의존성 주입 패턴을 개선해주세요.

현재 ProfileService.shared를 기본값으로 사용하고 있는데, 이는 테스트 용이성을 저해할 수 있습니다. 의존성 주입을 통해 더 유연한 구조로 개선하는 것이 좋습니다.

     init(
         model: EditProfileJobModelActionable,
         input: DataModel,
-        service: ProfileServiceProtocol = ProfileService.shared
+        service: ProfileServiceProtocol
     )

이렇게 수정하고, 실제 사용하는 곳에서 서비스를 주입하도록 변경하면 테스트가 더 용이해집니다.


60-62: 빈 메서드에 대한 설명을 추가해주세요.

onAppear()task() 메서드가 의도적으로 비어있다면, 그 이유를 문서화하는 것이 좋습니다.

+    /// 현재 구현이 필요하지 않은 기본 메서드입니다.
     func onAppear() {}
     
+    /// 현재 구현이 필요하지 않은 기본 메서드입니다.
     func task() async {}
Projects/Features/Home/Sources/Profile/ProfileIntent.swift (2)

Line range hint 98-101: 에러 처리 개선이 필요합니다

현재 구현에서는 refreshMyUserInfo 실패 시 사용자에게 어떠한 피드백도 제공되지 않습니다. 에러 처리를 추가하여 사용자 경험을 개선하는 것이 좋겠습니다.

다음과 같이 개선을 제안드립니다:

 func refreshUserInfo() async {
-    if let userInfo = try? await AppCoordinator.shared.refreshMyUserInfo() {
+    do {
+        let userInfo = try await AppCoordinator.shared.refreshMyUserInfo()
         fetchUserInfo(userInfo)
+    } catch {
+        await MainActor.run {
+            ToastHelper.showErrorMessage("프로필 정보를 불러오는데 실패했습니다")
+        }
     }
 }

Line range hint 116-119: 도달할 수 없는 코드가 존재합니다

throw 구문 이후의 코드는 실행될 수 없습니다. 이는 디버깅 목적으로 추가된 코드로 보이며, 프로덕션 환경에서는 제거되어야 합니다.

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

 func requestDeleteWidget(_ widget: ProfileWidget) async throws {
-    throw NSError(domain: "33", code: 33)
     try await profileService.requestDeleteProfileWidget(widgetType: widget.widgetType.toDto)
 }
Projects/App/Sources/Navigation/NavigationStack.swift (2)

71-81: 프로필 편집 네비게이션 구현 검토

현재 대부분의 서브뷰가 EmptyView()로 구현되어 있습니다. 이는 아직 구현이 완료되지 않았음을 의미하는 것으로 보입니다. 하지만 PR의 목적이 직군 정보 수정이므로, EditProfileJobView만 구현된 것은 적절해 보입니다.

향후 다른 프로필 편집 기능이 구현될 때를 대비하여, TODO 주석을 추가하는 것이 좋을 것 같습니다.

다음과 같이 TODO 주석을 추가하는 것을 제안합니다:

 case .profileImage(let input):
+    // TODO: ProfileImageEditView 구현 예정
     EmptyView()
 case .jobOccupation(let input):
     EditProfileJobView(input)
 case .company(let input):
+    // TODO: CompanyEditView 구현 예정
     EmptyView()
 case .region(let input):
+    // TODO: RegionEditView 구현 예정
     EmptyView()

83-91: 이상형 편집 네비게이션 구조 개선 제안

현재 모든 이상형 편집 관련 뷰가 EmptyView()로 구현되어 있습니다. 이는 현재 PR의 범위를 벗어나는 것으로 보입니다.

향후 유지보수성을 고려하여 다음과 같은 구조적 개선을 제안드립니다:

  1. 이상형 편집 관련 네비게이션 로직을 별도의 파일로 분리
  2. 각 케이스별로 전달되는 userInfo 파라미터의 타입을 명확히 정의
  3. 각 뷰의 구현 우선순위를 주석으로 명시

예시:

// EditDreamPartnerNavigation.swift
enum EditDreamPartnerViewType {
    case ageRange(DreamPartnerAgeInfo)
    case jobOccupation(DreamPartnerJobInfo)
    case distance(DreamPartnerDistanceInfo)
    
    @ViewBuilder
    var view: some View {
        switch self {
        case .ageRange:
            // TODO: [P1] 연령대 설정 뷰 구현
            EmptyView()
        // ... 기타 케이스
        }
    }
}
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobView.swift (3)

22-34: 초기화 로직을 더 간단하게 리팩토링하면 좋을 것 같습니다.

현재 초기화 로직이 다소 복잡해 보입니다. 컨테이너 설정 부분을 별도의 private 메서드로 분리하면 가독성이 향상될 것 같습니다.

다음과 같이 리팩토링을 제안드립니다:

 public init(_ userInfo: UserInfo) {
+    self._container = StateObject(wrappedValue: Self.createContainer(userInfo))
 }
+    
+ private static func createContainer(_ userInfo: UserInfo) -> MVIContainer<EditProfileJobIntent.Intentable, EditProfileJobModel.Stateful> {
     let model = EditProfileJobModel()
     let intent = EditProfileJobIntent(
         model: model,
         input: .init(userInfo: userInfo)
     )
-    let container = MVIContainer(
+    return MVIContainer(
         intent: intent as EditProfileJobIntent.Intentable,
         model: model as EditProfileJobModel.Stateful,
         modelChangePublisher: model.objectWillChange
     )
-    self._container = StateObject(wrappedValue: container)
 }

88-90: pop 네비게이션 로직 검토가 필요합니다.

AppCoordinator.shared를 직접 사용하는 것은 뷰의 재사용성과 테스트 가능성을 저해할 수 있습니다.

네비게이션 로직을 클로저나 콜백으로 전달받는 방식을 고려해보세요:

public struct EditProfileJobView: View {
    var onDismiss: () -> Void
    
    // ... 
    
    .setPopNavigation {
        onDismiss()
    }
}

95-99: 프리뷰를 더 다양한 상태로 테스트할 수 있게 개선하면 좋을 것 같습니다.

현재는 기본 상태만 프리뷰하고 있습니다. 다양한 상태의 프리뷰를 추가하면 UI 테스트에 도움이 될 것 같습니다.

#Preview("기본 상태") {
    NavigationView {
        EditProfileJobView(.mock)
    }
}

#Preview("선택된 상태") {
    NavigationView {
        EditProfileJobView(.mockWithSelectedJob)
    }
}

#Preview("로딩 상태") {
    NavigationView {
        EditProfileJobView(.mockLoading)
    }
}
Projects/Core/CommonKit/Sources/Path/PathTypes.swift (2)

91-104: 들여쓰기 일관성 개선이 필요합니다.

switch 문 내부의 들여쓰기가 일관적이지 않습니다. 가독성 향상을 위해 수정이 필요합니다.

다음과 같이 수정을 제안합니다:

 case .editProfile(let subView):
     switch subView {
-            case .profileImage: return "프로필 이미지 수정"
-            case .jobOccupation: return "직군 수정"
-            case .company: return "직장 수정"
-            case .region: return "활동 지역 수정"
+     case .profileImage: return "프로필 이미지 수정"
+     case .jobOccupation: return "직군 수정"
+     case .company: return "직장 수정"
+     case .region: return "활동 지역 수정"
     }

169-180: 새로운 enum 타입에 대한 개선사항이 있습니다.

  1. Hashable 프로토콜 준수가 필요할 수 있습니다:

    • SignUpSubViewType처럼 컬렉션에서 사용하거나 비교 연산이 필요한 경우를 대비하여 Hashable 프로토콜을 채택하는 것이 좋습니다.
  2. 문서화가 누락되었습니다:

    • 각 enum과 case에 대한 설명을 추가하면 코드의 가독성과 유지보수성이 향상될 것입니다.

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

+/// 프로필 수정 화면의 타입을 정의합니다.
-public enum EditProfileViewType {
+public enum EditProfileViewType: Hashable {
     case profileImage(UserInfo)
     case jobOccupation(UserInfo)
     case company(UserInfo)
     case region(UserInfo)
 }

+/// 이상형 정보 수정 화면의 타입을 정의합니다.
-public enum EditDreamPartnerViewType {
+public enum EditDreamPartnerViewType: Hashable {
     case ageRange(UserInfo)
     case jobOccupation(UserInfo)
     case distance(UserInfo)
 }
Projects/Features/Home/Sources/ProfilePannel/ProfilePannelView.swift (1)

201-209: 편집 아이콘 UI 구현에 대한 개선 제안

현재 구현은 기능적으로는 문제가 없으나, 접근성과 사용자 경험을 개선할 수 있습니다.

다음과 같은 개선을 제안드립니다:

 if showEditIcon {
     DesignCore.Images.pencil1.image
         .resizable()
         .aspectRatio(contentMode: .fit)
         .frame(width: 18, height: 18)
+        .accessibility(label: Text("편집"))
+        .contentShape(Rectangle())
         .onTapGesture {
             editHandler?()
         }
 }

개선 사항:

  1. VoiceOver 사용자를 위한 접근성 레이블 추가
  2. 터치 영역을 명확히 하기 위한 contentShape 추가
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 29cae89 and 23725f1.

📒 Files selected for processing (16)
  • OpenApiGenerator/Sources/OpenapiGenerated/Client.swift (2 hunks)
  • OpenApiGenerator/Sources/OpenapiGenerated/Types.swift (10 hunks)
  • OpenApiGenerator/Sources/openapi-generator-cli/3days-oas (1 hunks)
  • Projects/App/Sources/Navigation/NavigationStack.swift (1 hunks)
  • Projects/Core/CommonKit/Sources/Path/PathTypes.swift (4 hunks)
  • Projects/Core/NetworkKit/Sources/ProfileService/ProfileService.swift (2 hunks)
  • Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift (2 hunks)
  • Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobIntent.swift (1 hunks)
  • Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobModel.swift (1 hunks)
  • Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobView.swift (1 hunks)
  • Projects/Features/Home/Sources/Profile/ProfileIntent.swift (1 hunks)
  • Projects/Features/Home/Sources/ProfilePannel/ProfilePannelIntent.swift (2 hunks)
  • Projects/Features/Home/Sources/ProfilePannel/ProfilePannelView.swift (5 hunks)
  • Projects/Features/Home/UnitTest/EditProfileJobOccupationTest.swift (1 hunks)
  • Projects/Features/Home/UnitTest/WidgetUnitTest.swift (1 hunks)
  • Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • OpenApiGenerator/Sources/openapi-generator-cli/3days-oas
🧰 Additional context used
🪛 SwiftLint (0.57.0)
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobIntent.swift

[Warning] 16-16: Prefer at least one space after slashes for comments

(comment_spacing)


[Warning] 38-38: Prefer at least one space after slashes for comments

(comment_spacing)


[Warning] 57-57: 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] 38-38: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)


[Warning] 57-57: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobModel.swift

[Warning] 17-17: Prefer at least one space after slashes for comments

(comment_spacing)


[Warning] 32-32: Prefer at least one space after slashes for comments

(comment_spacing)


[Warning] 60-60: Prefer at least one space after slashes for comments

(comment_spacing)


[Warning] 17-17: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)


[Warning] 32-32: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)


[Warning] 60-60: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)

🔇 Additional comments (17)
Projects/Features/Home/UnitTest/EditProfileJobOccupationTest.swift (1)

9-11: NetworkKit import의 필요성 검토 필요

현재 테스트 코드에서 NetworkKit을 직접적으로 사용하는 부분이 보이지 않습니다. 불필요한 import인 경우 제거하는 것이 좋습니다.

다음 스크립트를 실행하여 NetworkKit의 사용 여부를 확인해보겠습니다:

Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift (1)

12-12: Model 모듈 import 추가 확인됨

UserInfo 타입 사용을 위한 Model 모듈 import가 적절히 추가되었습니다.

Projects/Core/NetworkKit/Sources/ProfileService/ProfileService.swift (1)

23-24: 프로토콜 메서드 선언이 적절합니다!

비동기 처리와 에러 핸들링을 포함한 메서드 시그니처가 잘 정의되어 있습니다.

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobModel.swift (1)

15-56: 아키텍처 구현이 잘 되었습니다

다음과 같은 점들이 잘 구현되었습니다:

  • ObservableObject를 활용한 MVVM 패턴 구현
  • StatefulActionable 프로토콜을 통한 명확한 책임 분리
  • 상태 관리와 액션 처리의 체계적인 구조화

Also applies to: 61-73

🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 17-17: Prefer at least one space after slashes for comments

(comment_spacing)


[Warning] 32-32: Prefer at least one space after slashes for comments

(comment_spacing)


[Warning] 17-17: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)


[Warning] 32-32: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobIntent.swift (1)

32-34: 🛠️ Refactor suggestion

옵셔널 처리를 개선해주세요.

JobOccupation(rawValue:)가 nil을 반환할 수 있는 상황에서 강제 언래핑을 사용하고 있습니다. 안전한 처리를 위해 guard let 또는 if let을 사용하는 것이 좋습니다.

-        if let job = JobOccupation(rawValue: input.userInfo.profile.jobOccupationRawValue) {
-            model.setSingleSelectedJob(job)
-        }
+        guard let job = JobOccupation(rawValue: input.userInfo.profile.jobOccupationRawValue) else {
+            return
+        }
+        model.setSingleSelectedJob(job)

Likely invalid or redundant comment.

Projects/Features/Home/Sources/Profile/ProfileIntent.swift (1)

92-94: 비동기 처리가 올바르게 구현되었습니다!

Task 래퍼를 사용하여 비동기 작업을 적절하게 처리하고 있습니다.

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobView.swift (1)

9-14: 필요한 프레임워크들이 잘 임포트되어 있습니다!

필요한 모든 의존성이 명확하게 정의되어 있습니다.

Projects/Core/CommonKit/Sources/Path/PathTypes.swift (1)

29-30: 새로운 PathType 케이스가 적절히 추가되었습니다!

프로필 수정과 이상형 수정을 위한 새로운 케이스가 기존 코드 스타일과 일관성있게 추가되었습니다.

Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift (2)

16-17: dreamPartner 속성의 가변성 필요성 검토 필요

프로필의 직군 정보 수정 기능 구현을 위해 profilevar로 변경한 것은 적절해 보입니다. 하지만 dreamPartner를 가변으로 만든 이유가 불분명합니다. 현재 PR의 범위가 직군 정보 수정에 한정되어 있다면, dreamPartner는 불변(let)으로 유지하는 것이 더 안전할 수 있습니다.


66-68: 잘 구현된 jobOccupationDTO computed property

Components.Schemas.JobOccupation으로의 안전한 변환을 제공하는 computed property가 잘 구현되었습니다. 타입 안전성을 보장하면서도 DTO 변환을 깔끔하게 처리하고 있습니다.

Projects/Features/Home/Sources/ProfilePannel/ProfilePannelView.swift (2)

84-88: 직군 정보 수정 기능 구현이 적절합니다.

직군 정보 수정을 위한 편집 아이콘과 핸들러가 잘 구현되어 있습니다. onTapEditJobOccupationIcon()을 통해 적절한 네비게이션 처리가 이루어지고 있습니다.


184-186: 메서드 시그니처 변경이 적절합니다.

horizonIconKeyValueView 메서드에 편집 기능 관련 파라미터가 잘 추가되었습니다. 선택적 매개변수(editHandler)를 사용하여 하위 호환성도 고려했습니다.

OpenApiGenerator/Sources/OpenapiGenerated/Client.swift (1)

Line range hint 662-675: HTTP 메소드 변경이 적절해 보입니다.

PATCH에서 PUT으로의 변경은 사용자 정보를 전체적으로 업데이트하는 현재 구현 방식과 잘 맞습니다. PUT은 리소스의 전체 업데이트를 위한 표준 HTTP 메소드이며, 이는 프로필 수정 기능의 의도와 일치합니다.

다음 스크립트를 실행하여 클라이언트 코드에서 이 엔드포인트의 사용을 확인하겠습니다:

✅ Verification successful

Let me gather more information about the implementation details and the request body structure.


Let me check one more detail about the request schema to understand the complete update structure.


PUT 메소드 변경이 적절하며 구현이 올바릅니다.

사용자 정보 업데이트 엔드포인트의 구현을 검토한 결과:

  • UpdateMyUserInfoRequest 스키마는 사용자 프로필의 전체 정보(이름, 직군, 회사, 활동 지역)를 포함하고 있습니다
  • PATCH에서 PUT으로의 변경은 리소스의 전체 업데이트를 의미하며, 현재 구현된 요청 구조와 일치합니다
  • 다른 PATCH 엔드포인트와의 충돌이 없습니다
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: PUT /users/my 엔드포인트 사용 확인

# Test: 엔드포인트 호출 패턴 검색
rg -A 5 "PUT.*?/users/my"

Length of output: 2672


Script:

#!/bin/bash
# Description: Check the request body structure and related types

# Search for updateMyUserInfo Input/Body type definitions
ast-grep --pattern 'struct Input {
  $$$
}'

# Search for any related documentation or comments
rg -B 2 -A 5 "updateMyUserInfo.*?Body"

Length of output: 4364


Script:

#!/bin/bash
# Search for UpdateMyUserInfoRequest schema definition
rg -B 2 -A 10 "UpdateMyUserInfoRequest"

# Also check if there are any PATCH endpoints that might be affected
rg "PATCH.*?/users"

Length of output: 4859

OpenApiGenerator/Sources/OpenapiGenerated/Types.swift (4)

186-187: [중복 코멘트] HTTP 메서드 변경에 따른 영향 확인 필요

이미 언급된 내용과 같이, 이 부분에서도 updateMyUserInfo 메서드의 HTTP 메서드 변경에 따른 영향 확인이 필요합니다.


Line range hint 2378-2397: HTTP 메서드 변경에 따른 영향 확인 필요

updateMyUserInfo 오퍼레이션의 정의에서 HTTP 메서드가 PATCH에서 PUT으로 변경되었습니다. 이는 API의 동작 방식과 클라이언트 호출에 영향을 줄 수 있으므로, 관련된 모든 부분이 업데이트되었는지 확인해주세요.


53-54: ⚠️ Potential issue

HTTP 메서드 변경에 따른 영향 확인 필요

updateMyUserInfo 메서드의 HTTP 메서드가 PATCH에서 PUT으로 변경되었습니다. 이 변경은 클라이언트 측의 API 호출에도 영향을 미치므로, 모든 클라이언트 구현부가 해당 변경 사항을 반영하도록 업데이트되었는지 확인해주세요.

다음 스크립트를 실행하여 클라이언트 코드에서 updateMyUserInfo 메서드 호출이 올바르게 업데이트되었는지 확인할 수 있습니다:


591-619: ⚠️ Potential issue

필수 필드 변경에 따른 호환성 확인 필요

UpdateMyUserInfoRequest 구조체에서 name, jobOccupation, locationIds 필드가 선택적(Optional)에서 필수적(Non-Optional)으로 변경되었습니다. 이로 인해 해당 구조체를 사용하는 기존 클라이언트 코드에서 컴파일 오류가 발생할 수 있습니다. 또한, 새로운 필드인 allowSameCompany가 추가되었습니다.

다음 스크립트를 실행하여 클라이언트 코드에서 UpdateMyUserInfoRequest 초기화 시 필수 필드들이 모두 포함되었는지 확인할 수 있습니다:

✅ Verification successful

Let me search for actual usage of this struct in the codebase to verify the impact.


Let me search specifically in the ProfileService and AuthService where this request is most likely to be used.


Let me check the ProfileService implementation and any other potential usages.


필수 필드 변경이 안전하게 처리되어 있음을 확인했습니다

UpdateMyUserInfoRequest 구조체의 필수 필드 변경과 관련하여 다음 사항들을 확인했습니다:

  1. ProfileService에서 requestPutUserInfo 메서드를 통해 UpdateMyUserInfoRequest를 생성할 때 필수 필드인 name, jobOccupation, locationIds를 모두 올바르게 제공하고 있습니다.
  2. 실제 사용처는 EditProfileJobIntent에서 프로필 수정 시에만 사용되며, UserInfo 모델을 통해 필수 값들이 안전하게 전달됩니다.
  3. 선택적 필드인 companyIdallowSameCompany는 필요한 경우에만 설정되도록 구현되어 있습니다.

따라서 필수 필드 변경으로 인한 호환성 문제는 발생하지 않을 것으로 판단됩니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 'UpdateMyUserInfoRequest' 초기화 시 누락된 필수 필드 확인

rg "UpdateMyUserInfoRequest" -A 10

Length of output: 4389


Script:

#!/bin/bash
# Search for actual usage/initialization of UpdateMyUserInfoRequest
rg -B 3 -A 3 "UpdateMyUserInfoRequest\(" --type swift

# Also search for any imports of OpenapiGenerated to find client code
rg "import.*OpenapiGenerated" --type swift

Length of output: 1282


Script:

#!/bin/bash
# Search in profile and auth related services
rg -B 5 -A 5 "UpdateMyUserInfoRequest" Projects/Core/NetworkKit/Sources/ProfileService/ Projects/Core/NetworkKit/Sources/AuthService/

# Also check the mock implementations
cat Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift
cat Projects/Core/NetworkKit/Sources/AuthService/AuthServiceMock.swift

Length of output: 3141


Script:

#!/bin/bash
# Check ProfileService implementation
cat Projects/Core/NetworkKit/Sources/ProfileService/ProfileService.swift

# Search for any other potential usages of UpdateMyUserInfoRequest in the codebase
rg -B 5 -A 5 "requestPutUserInfo|UpdateMyUserInfoRequest" --type swift

Length of output: 10889

Comment on lines +59 to +75
public func requestPutUserInfo(userInfo: UserInfo) async throws {
guard let jobOccupation = userInfo.profile.jobOccupationDTO else {
return
}
let result = try await client.updateMyUserInfo(
.init(
body: .json(
.init(
name: userInfo.name,
jobOccupation: jobOccupation,
locationIds: userInfo.profile.locations.map { $0.id }
)
)
)
)
_ = try result.ok
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

에러 처리 및 유효성 검사가 필요합니다.

현재 구현에서 몇 가지 개선이 필요한 부분이 있습니다:

  1. jobOccupation이 nil일 때 조용히 리턴하는 것은 호출하는 쪽에서 실패 여부를 알 수 없습니다.
  2. name이나 locations 같은 필수 필드에 대한 유효성 검사가 없습니다.

다음과 같이 개선하는 것을 제안드립니다:

 public func requestPutUserInfo(userInfo: UserInfo) async throws {
     guard let jobOccupation = userInfo.profile.jobOccupationDTO else {
-        return
+        throw ProfileServiceError.invalidJobOccupation
     }
+    
+    guard !userInfo.name.isEmpty else {
+        throw ProfileServiceError.invalidName
+    }
+    
     let result = try await client.updateMyUserInfo(
         .init(
             body: .json(

추가로 다음 에러 타입도 정의가 필요합니다:

public enum ProfileServiceError: Error {
    case invalidJobOccupation
    case invalidName
}

Comment on lines +29 to +30
case editProfile(EditProfileViewType)
case editDreamPartner(EditDreamPartnerViewType)
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

네비게이션 스택에서 일부 화면이 EmptyView()로 구현되어 있습니다

네비게이션 스택에서 새로운 경로들이 모두 처리되고 있지만, 다음 화면들이 아직 EmptyView()로만 구현되어 있습니다:

  • editProfile: profileImage 화면
  • editDreamPartner: ageRange, jobOccupation 화면

이 화면들의 구현이 필요합니다.

🔗 Analysis chain

새로운 네비게이션 경로의 처리 여부를 확인해주세요.

새로 추가된 프로필 수정 관련 화면들이 네비게이션 스택에서 올바르게 처리되는지 확인이 필요합니다.

Also applies to: 169-180

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# NavigationStack에서 새로운 PathType 케이스들의 처리 여부 확인

# NavigationStack 파일에서 새로운 케이스 처리 확인
rg -A 5 "case [.]editProfile|case [.]editDreamPartner" --type swift

Length of output: 2299

Comment on lines +61 to +64
public var companyName: String?
public let jobOccupation: String
public let jobOccupationRawValue: String
public let locations: [LocationModel]
public var jobOccupationRawValue: String
public var locations: [LocationModel]
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

jobOccupationjobOccupationRawValue 간의 일관성 보장 필요

jobOccupationlet으로 유지되는 반면 jobOccupationRawValuevar로 변경되었습니다. 이로 인해 두 속성 간의 불일치가 발생할 수 있습니다. 다음 두 가지 해결 방안을 고려해보세요:

  1. jobOccupation을 computed property로 변경
  2. jobOccupationRawValue 수정 시 jobOccupation도 함께 업데이트하는 로직 추가

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

🧹 Outside diff range and nitpick comments (15)
Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift (1)

31-35: Mock 구현이 일관된 패턴을 따르고 있습니다.

다음 사항들이 적절하게 구현되었습니다:

  • 기존 메서드들과 동일한 형식의 성공 메시지 출력
  • ProfileServiceProtocol 요구사항 준수
  • async/throws 키워드의 올바른 사용

하나의 개선사항을 제안드립니다:

실제 서비스에서 발생할 수 있는 다양한 시나리오 테스트를 위해 에러 케이스도 추가하는 것이 좋을 것 같습니다. 다음과 같은 구현을 고려해보세요:

 public func requestPutUserInfo(userInfo: UserInfo) async throws {
+    // 테스트를 위한 에러 케이스 추가
+    guard userInfo.occupation != "invalid_occupation" else {
+        throw NetworkError.invalidRequest
+    }
     print("✅ [ProfileServiceMock] requestPutUserInfo 성공!")
     return
 }
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobModel.swift (4)

17-17: MARK 주석 형식을 수정해주세요

Swift 스타일 가이드라인에 따라 MARK 주석 형식을 수정해야 합니다.

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

-    //MARK: Stateful
+    // MARK: - Stateful

-    //MARK: State Properties
+    // MARK: - State Properties

-//MARK: - Actionable
+// MARK: - Actionable

Also applies to: 32-32, 60-60

🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 17-17: Prefer at least one space after slashes for comments

(comment_spacing)


[Warning] 17-17: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)


37-48: 검증 로직을 단순화할 수 있습니다

현재 검증 로직이 중첩된 조건문으로 인해 복잡해 보입니다. 가독성을 높이기 위해 로직을 단순화하는 것이 좋겠습니다.

다음과 같이 수정하는 것을 제안합니다:

    var isValidated: Bool {
-        if let userInfo,
-           let singleSelectedJob {
-            if userInfo.profile.jobOccupationRawValue == singleSelectedJob.rawValue {
-                return false
-            }
-        } else {
-            return false
-        }
-        
-        return true
+        guard let userInfo = userInfo,
+              let singleSelectedJob = singleSelectedJob else {
+            return false
+        }
+        return userInfo.profile.jobOccupationRawValue != singleSelectedJob.rawValue
    }

28-29: 에러 처리 방식에 대한 문서화가 필요합니다

showErrorViewshowErrorAlert의 사용 목적과 차이점을 명확히 하는 문서화가 필요합니다.

각 에러 처리 방식에 대해 다음과 같이 문서 주석을 추가해주세요:

    // error
+   /// 화면 전체에 표시되는 에러 뷰를 위한 에러 모델
    var showErrorView: ErrorModel? { get }
+   /// 팝업 형태로 표시되는 에러 알럿을 위한 에러 모델
    var showErrorAlert: ErrorModel? { get }

Also applies to: 90-99


15-56: 단위 테스트 추가를 권장합니다

상태 관리와 검증 로직이 잘 구현되어 있습니다. 하지만 이러한 비즈니스 로직의 신뢰성을 보장하기 위해 단위 테스트가 필요합니다.

다음 사항들에 대한 테스트 케이스 작성을 권장드립니다:

  • isValidated 속성의 다양한 조건에 대한 테스트
  • 에러 상태 관리에 대한 테스트
  • 직군 선택 상태 변경에 대한 테스트

테스트 코드 작성을 도와드릴까요?

🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 17-17: Prefer at least one space after slashes for comments

(comment_spacing)


[Warning] 32-32: Prefer at least one space after slashes for comments

(comment_spacing)


[Warning] 17-17: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)


[Warning] 32-32: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobIntent.swift (2)

16-16: MARK 주석 형식을 수정해주세요

Swift 스타일 가이드라인에 따라 MARK 주석 형식을 수정해야 합니다.

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

-//MARK: - Intent
+// MARK: - Intent

-//MARK: - Intentable
+// MARK: - Intentable

Also applies to: 38-38, 57-57

🧰 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)


86-91: 프로필 업데이트 전 유효성 검증을 추가해주세요

프로필 정보 업데이트 전에 필수 필드에 대한 유효성 검증이 필요합니다.

다음과 같은 개선을 제안드립니다:

 func requestEditProfile(newUserInfo: UserInfo) async throws {
-    
+    // 필수 필드 유효성 검증
+    guard !newUserInfo.profile.jobOccupationRawValue.isEmpty else {
+        throw ProfileError.invalidJobOccupation
+    }
+    
     try await profileService.requestPutUserInfo(
         userInfo: newUserInfo
     )
 }
Projects/Features/Home/Sources/Profile/ProfileIntent.swift (1)

Line range hint 124-127: 심각: 위젯 삭제 기능이 동작하지 않습니다.

현재 구현에서 다음과 같은 문제점이 있습니다:

  1. 하드코딩된 에러가 항상 발생하여 실제 API 호출이 실행되지 않습니다.
  2. 에러의 domain과 code가 의미 없는 값으로 설정되어 있습니다.

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

func requestDeleteWidget(_ widget: ProfileWidget) async throws {
-    throw NSError(domain: "33", code: 33)
    try await profileService.requestDeleteProfileWidget(widgetType: widget.widgetType.toDto)
}
Projects/App/Sources/Navigation/NavigationStack.swift (1)

83-91: 이상적인 파트너 편집 기능이 구현되지 않았습니다.

모든 서브뷰가 EmptyView()를 반환하고 있습니다. 이는 아직 구현되지 않은 상태를 나타냅니다. PR의 목적이 프로필 수정 기능 구현이므로, 이상적인 파트너 편집 기능은 별도의 PR로 분리하는 것이 좋을 것 같습니다.

현재 PR의 범위를 프로필 수정으로 한정하고, 이상적인 파트너 편집 기능은 새로운 PR로 분리하는 것을 제안드립니다.

Projects/Core/CommonKit/Sources/Path/PathTypes.swift (1)

91-104: 문자열 관리 개선을 고려해보세요.

'수정'이라는 단어가 여러 번 반복되고 있습니다. 문자열을 상수로 분리하거나 지역화 파일로 관리하는 것을 고려해보세요.

예시 리팩토링:

+ private enum LocalizedString {
+     static let edit = "수정"
+ }

  case .editProfile(let subView):
      switch subView {
-     case .profileImage: return "프로필 이미지 수정"
-     case .jobOccupation: return "직군 수정"
+     case .profileImage: return "프로필 이미지 \(LocalizedString.edit)"
+     case .jobOccupation: return "직군 \(LocalizedString.edit)"
      // ... 나머지 케이스들도 동일하게 적용
Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift (2)

61-61: 프로필 수정 관련 프로퍼티 변경 승인

직무 정보 수정 기능 구현을 위한 적절한 프로퍼티 변경입니다. 다만, 프로퍼티들의 업데이트 로직을 명확히 하기 위해 다음과 같은 개선을 제안드립니다:

public struct UserInfoProfile {
+    // MARK: - Mutable Properties for Profile Update
     public var companyName: String?
     public var jobOccupationRawValue: String
     public var locations: [LocationModel]

Also applies to: 63-64


66-68: jobOccupationDTO 계산 프로퍼티 개선 제안

계산 프로퍼티의 구현이 간단하고 명확하나, 다음과 같은 개선사항을 고려해보시기 바랍니다:

  1. 실패 가능한 변환에 대한 로깅 추가
  2. 잘못된 rawValue 처리를 위한 에러 핸들링
 public var jobOccupationDTO: Components.Schemas.JobOccupation? {
+    // TODO: Add logging for debugging purposes
     return .init(rawValue: jobOccupationRawValue)
 }
Projects/Features/Home/Sources/ProfilePannel/ProfilePannelView.swift (1)

201-209: 접근성 개선을 위한 제안사항이 있습니다.

현재 구현은 기능적으로는 문제가 없으나, 다음과 같은 개선사항을 고려해보시면 좋겠습니다:

  1. DesignCore.Images.pencil1 대신 SF Symbols의 pencil 아이콘 사용을 고려해보세요.
  2. 고정된 프레임 크기 대신 Dynamic Type을 지원하는 방식으로 수정하면 좋겠습니다.
-DesignCore.Images.pencil1.image
-    .resizable()
-    .aspectRatio(contentMode: .fit)
-    .frame(width: 18, height: 18)
+Image(systemName: "pencil")
+    .imageScale(.medium)
+    .font(.body)
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobView.swift (2)

41-41: 하드코딩된 문자열을 로컬라이즈하세요

사용자 인터페이스에 표시되는 문자열은 로컬라이제이션을 통해 관리되어야 합니다. 이를 통해 다국어 지원과 유지 보수성을 향상시킬 수 있습니다.

Also applies to: 73-73, 86-86


85-85: 키보드로 인한 안전 영역을 무시하지 않는 것이 좋습니다

.ignoresSafeArea(.keyboard)를 사용하면 키보드로 인해 중요한 UI 요소가 가려질 수 있습니다. 키보드 나타남에 따라 뷰를 자동으로 조정하도록 구현하는 것이 사용자 경험 측면에서 더 좋습니다.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 29cae89 and 23725f1.

📒 Files selected for processing (16)
  • OpenApiGenerator/Sources/OpenapiGenerated/Client.swift (2 hunks)
  • OpenApiGenerator/Sources/OpenapiGenerated/Types.swift (10 hunks)
  • OpenApiGenerator/Sources/openapi-generator-cli/3days-oas (1 hunks)
  • Projects/App/Sources/Navigation/NavigationStack.swift (1 hunks)
  • Projects/Core/CommonKit/Sources/Path/PathTypes.swift (4 hunks)
  • Projects/Core/NetworkKit/Sources/ProfileService/ProfileService.swift (2 hunks)
  • Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift (2 hunks)
  • Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobIntent.swift (1 hunks)
  • Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobModel.swift (1 hunks)
  • Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobView.swift (1 hunks)
  • Projects/Features/Home/Sources/Profile/ProfileIntent.swift (1 hunks)
  • Projects/Features/Home/Sources/ProfilePannel/ProfilePannelIntent.swift (2 hunks)
  • Projects/Features/Home/Sources/ProfilePannel/ProfilePannelView.swift (5 hunks)
  • Projects/Features/Home/UnitTest/EditProfileJobOccupationTest.swift (1 hunks)
  • Projects/Features/Home/UnitTest/WidgetUnitTest.swift (1 hunks)
  • Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • OpenApiGenerator/Sources/openapi-generator-cli/3days-oas
🧰 Additional context used
🪛 SwiftLint (0.57.0)
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobIntent.swift

[Warning] 16-16: Prefer at least one space after slashes for comments

(comment_spacing)


[Warning] 38-38: Prefer at least one space after slashes for comments

(comment_spacing)


[Warning] 57-57: 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] 38-38: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)


[Warning] 57-57: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobModel.swift

[Warning] 17-17: Prefer at least one space after slashes for comments

(comment_spacing)


[Warning] 32-32: Prefer at least one space after slashes for comments

(comment_spacing)


[Warning] 60-60: Prefer at least one space after slashes for comments

(comment_spacing)


[Warning] 17-17: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)


[Warning] 32-32: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)


[Warning] 60-60: MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'

(mark)

🔇 Additional comments (16)
Projects/Features/Home/UnitTest/EditProfileJobOccupationTest.swift (1)

9-11: 테스트에 필요한 모듈이 모두 import 되었는지 확인이 필요합니다.

현재 Testing, Home, NetworkKit만 import되어 있습니다. 테스트에서 사용되는 모든 타입들이 이 모듈들에 포함되어 있는지 확인해주세요.

✅ Verification successful

현재 import된 모듈들로 충분합니다.

검증 결과, 테스트에서 사용되는 모든 타입들이 현재 import된 모듈들을 통해 접근 가능합니다:

  • EditProfileJobModel, EditProfileJobIntent@testable import Home을 통해 접근 가능합니다 (Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/ 경로에서 확인)
  • ProfileServiceMock은 테스트 파일 내에서 정의되거나 Testing 모듈에서 제공되는 것으로 보입니다
  • NetworkKit은 서비스 관련 기능을 위해 필요합니다
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if all required types are available in imported modules

# Search for all custom types used in the test file
rg -o --no-filename '(\w+Model|\w+Intent|\w+Service|\w+Mock)' Projects/Features/Home/UnitTest/EditProfileJobOccupationTest.swift | sort -u | while read type; do
  echo "Searching for type: $type"
  rg "class $type|struct $type|protocol $type" 
done

Length of output: 347


Script:

#!/bin/bash
# Let's check the content of the test file first to understand the types being used
cat Projects/Features/Home/UnitTest/EditProfileJobOccupationTest.swift

# Then search for the implementation of these types in the Home module
echo "Searching for related types in Home module..."
fd . Projects/Features/Home -e swift -E "*Test.swift" --exec rg -l "class|struct|protocol.*(?:EditProfileJob|Intent|Model)"

Length of output: 2347

Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift (1)

12-12: Model 모듈 import 추가가 적절합니다.

UserInfo 타입을 사용하기 위해 필요한 import문이 올바르게 추가되었습니다.

Projects/Features/Home/Sources/ProfilePannel/ProfilePannelIntent.swift (2)

33-33: 프로토콜 메서드 선언이 적절합니다.

프로토콜에 직군 정보 수정 아이콘 탭 이벤트를 처리하는 메서드가 잘 정의되어 있습니다.


58-72: 🛠️ Refactor suggestion

직군 정보 수정 화면 전환 로직 개선이 필요합니다.

현재 구현에서 몇 가지 개선이 필요한 부분이 있습니다:

  1. userInfo가 없는 경우에 대한 처리가 누락되어 있습니다.
  2. Task와 MainActor의 중첩 사용이 불필요해 보입니다.

다음과 같이 개선하는 것을 제안드립니다:

 func onTapEditJobOccupationIcon() {
-    Task {
-        await MainActor.run {
-            if let userInfo = AppCoordinator.shared.userInfo {
-                AppCoordinator.shared.push(
-                    .editProfile(
-                        .jobOccupation(
-                            userInfo
-                        )
-                    )
-                )
-            }
-        }
+    guard let userInfo = AppCoordinator.shared.userInfo else {
+        // TODO: 사용자 정보가 없는 경우 에러 처리
+        return
     }
+    
+    AppCoordinator.shared.push(
+        .editProfile(
+            .jobOccupation(
+                userInfo
+            )
+        )
+    )
 }

또한, 다음 사항들도 검토해 주시기 바랍니다:

  1. 화면 전환 전에 사용자 정보 유효성 검증이 필요한지
  2. 에러 상황에 대한 사용자 피드백 처리 방안
Projects/Core/NetworkKit/Sources/ProfileService/ProfileService.swift (1)

23-24: 프로토콜 메서드 선언이 명확합니다!

비동기 처리와 에러 핸들링이 적절하게 구현되어 있습니다.

Projects/Features/Home/UnitTest/WidgetUnitTest.swift (2)

36-36: 초기 content 값이 nil인 이유에 대한 검증 필요

content: nil로 초기화하는 것이 의도된 것인지 확인이 필요합니다. 이는 잠재적인 null 참조 문제를 야기할 수 있습니다.

다음 사항들을 확인해주세요:

  1. nil 상태에서의 위젯 동작 검증
  2. content가 nil일 때의 예외 처리 로직 검증

36-38: 🛠️ Refactor suggestion

성공 핸들러에 대한 테스트 케이스 추가 필요

successHandler가 비어있는 상태로 구현되어 있습니다. 성공 시나리오에 대한 테스트 커버리지가 누락되어 있을 수 있습니다.

다음과 같은 테스트 케이스 추가를 제안드립니다:

  • 성공 핸들러 호출 여부 검증
  • 성공 시나리오에서의 상태 변화 검증

예시 구현:

 @Test func onTapNextButton() async throws {
     writeIntent.onTapNextButton(state: writeState)
-    // 3초 후 실행
     try await Task.sleep(for: .seconds(1))
     #expect(writeState.isModalPresented == false)
+    // 성공 핸들러 호출 검증
+    var successHandlerCalled = false
+    writeIntent.input.successHandler = {
+        successHandlerCalled = true
+    }
+    #expect(successHandlerCalled == true)
 }
Projects/Features/Home/Sources/Profile/ProfileIntent.swift (1)

92-94: 비동기 처리가 올바르게 구현되었습니다! 👍

Task를 사용하여 비동기 작업을 적절하게 처리하고 있습니다.

Projects/App/Sources/Navigation/NavigationStack.swift (1)

71-81: 프로필 편집 기능 구현이 완료되지 않았습니다.

현재 EditProfileJobView만 구현되어 있고 나머지 뷰들은 EmptyView()를 반환하고 있습니다. 프로필 이미지, 회사, 지역 정보 수정 기능의 구현 계획을 명확히 해주시기 바랍니다.

구현이 필요한 나머지 뷰들에 대한 기본 구조를 제공해드릴까요?

Projects/Core/CommonKit/Sources/Path/PathTypes.swift (1)

29-30: 새로운 PathType 케이스가 적절히 추가되었습니다!

프로필 수정과 이상형 수정을 위한 새로운 케이스가 기존 코드 스타일을 잘 따르고 있습니다.

Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift (1)

16-17: 불변성(Immutability) 변경에 대한 안전성 검토 필요

핵심 사용자 정보를 담고 있는 profiledreamPartner 프로퍼티를 가변(var)으로 변경하는 것은 프로필 수정 기능을 위해 필요하지만, 예기치 않은 상태 변경의 위험이 있습니다.

다음 사항들을 확인해주세요:

  • 상태 변경이 일어나는 시점이 명확한지
  • 동시성 관련 이슈는 없는지
  • 상태 변경 후 적절한 validation이 이루어지는지
Projects/Features/Home/Sources/ProfilePannel/ProfilePannelView.swift (2)

84-88: 직군 수정 기능이 적절하게 구현되었습니다!

MVI 패턴을 잘 따르고 있으며, 사용자 인터랙션 처리가 깔끔하게 구현되었습니다.


184-186: 메서드 시그니처가 적절하게 확장되었습니다!

새로운 파라미터들이 잘 정의되어 있으며, 옵셔널 핸들러의 기본값 처리가 적절합니다.

OpenApiGenerator/Sources/OpenapiGenerated/Client.swift (1)

662-663: HTTP 메소드 변경에 대한 설계 검토

PATCH에서 PUT으로의 변경이 RESTful 설계 원칙에 부합하는지 확인이 필요합니다. PUT은 리소스의 전체 교체를 의미하므로, 부분 업데이트가 필요한 경우 PATCH가 더 적절할 수 있습니다.

Also applies to: 675-675

✅ Verification successful

Let me gather more information about the API specification and implementation to better understand the HTTP method change.


PUT 메소드 사용이 적절함을 확인

OpenAPI 생성 코드와 ProfileService의 구현을 검토한 결과, PUT 메소드로의 변경이 적절합니다. 해당 엔드포인트는 사용자 정보의 전체 업데이트를 위한 것으로 보이며, 일관되게 PUT으로 구현되어 있습니다.

  • ProfileService에서 updateMyUserInfo는 PUT 메소드를 사용하여 구현됨
  • OpenAPI 스펙에서도 /users/my 엔드포인트가 PUT으로 정의됨
  • 전체 코드베이스에서 이 엔드포인트에 대한 PATCH 사용 사례가 발견되지 않음
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: PUT 메소드가 일관되게 사용되는지 확인
# 다른 파일에서 동일한 엔드포인트를 호출하는 부분 검색

# API 호출 패턴 검색
rg -A 3 "users/my.*PATCH|users/my.*PUT" --type swift

# ProfileService 클래스에서 관련 메소드 검색
ast-grep --pattern 'class ProfileService {
  $$$
  func $_(userInfo: UserInfo) {
    $$$
  }
  $$$
}'

Length of output: 2173


Script:

#!/bin/bash
# Check OpenAPI specification files for the endpoint definition
fd -e yaml -e json . | xargs rg -A 5 "/users/my"

# Look for any related test files or documentation
rg -g "!*.generated.*" -g "!*.gen.*" "updateMyUserInfo" --type swift

Length of output: 4490

OpenApiGenerator/Sources/OpenapiGenerated/Types.swift (2)

Line range hint 2383-2514: 작업 구조 변경 검토 완료

updateMyUserInfo 작업의 구조가 PUT 메소드에 맞게 적절히 업데이트되었으며, 에러 처리도 기존과 동일하게 잘 유지되어 있습니다.


53-54: HTTP 메소드 변경에 따른 주의사항

PATCH에서 PUT으로의 변경은 클라이언트 측에서 부분 업데이트가 아닌 전체 리소스 상태를 전송해야 함을 의미합니다. 클라이언트 코드가 이 변경사항을 올바르게 처리하는지 확인이 필요합니다.

Also applies to: 186-187, 2378-2379

✅ Verification successful

PUT 메소드 변경은 적절하게 구현되어 있습니다

코드 검토 결과, PUT 메소드로의 변경이 다음과 같은 이유로 적절하게 구현되어 있음을 확인했습니다:

  • 필수 필드인 name, jobOccupation, locationIds가 명확하게 정의되어 있습니다
  • 선택적 필드인 companyIdallowSameCompany가 옵셔널로 올바르게 처리되어 있습니다
  • API 문서에 프로필 정보 전체를 수정하는 엔드포인트임이 명시되어 있습니다
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify if there are any remaining PATCH references in the codebase

# Check for PATCH references in Swift files
rg -l "PATCH.*?/users/my" --type swift

# Check for PATCH references in API documentation or configuration files
rg -l "PATCH.*?/users/my" --type yaml --type json

Length of output: 92


Script:

#!/bin/bash
# Let's verify the HTTP method change more thoroughly

# Check for any PUT references to /users/my
echo "=== Checking PUT /users/my references ==="
rg "PUT.*?/users/my" --type swift -A 2 -B 2

# Check for any method references to /users/my in yaml/json files
echo "=== Checking API specs for /users/my endpoint ==="
rg "/users/my" --type yaml --type json -A 5 -B 5

# Look for UpdateMyUserInfo related code
echo "=== Checking UpdateMyUserInfo implementation ==="
ast-grep --pattern 'struct UpdateMyUserInfoRequest'

Length of output: 2591


Script:

#!/bin/bash
# Let's check the UpdateMyUserInfoRequest structure to understand the required fields

echo "=== Checking UpdateMyUserInfoRequest structure ==="
rg "struct UpdateMyUserInfoRequest" --type swift -A 20

echo "=== Checking for any documentation about required fields ==="
rg "UpdateMyUserInfoRequest" --type swift -B 5 -A 1 | grep -E "(///|//)"

Length of output: 4843

Comment on lines +169 to +180
public enum EditProfileViewType {
case profileImage(UserInfo)
case jobOccupation(UserInfo)
case company(UserInfo)
case region(UserInfo)
}

public enum EditDreamPartnerViewType {
case ageRange(UserInfo)
case jobOccupation(UserInfo)
case distance(UserInfo)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

새로운 enum들에 Hashable 프로토콜 준수가 필요합니다.

EditProfileViewTypeEditDreamPartnerViewType이 다른 enum들처럼 Hashable을 준수하도록 수정이 필요합니다. 이는 향후 이 타입들을 컬렉션이나 비교 연산에서 사용할 때 필요할 수 있습니다.

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

- public enum EditProfileViewType {
+ public enum EditProfileViewType: Hashable {
     case profileImage(UserInfo)
     case jobOccupation(UserInfo)
     case company(UserInfo)
     case region(UserInfo)
 }

- public enum EditDreamPartnerViewType {
+ public enum EditDreamPartnerViewType: Hashable {
     case ageRange(UserInfo)
     case jobOccupation(UserInfo)
     case distance(UserInfo)
 }

Committable suggestion skipped: line range outside the PR's diff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature 기능
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant