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-139] 프로필 정보 수정 기능 구현 #50

Merged
merged 13 commits into from
Nov 24, 2024

Conversation

jisu15-kim
Copy link
Member

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

구현사항

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 사용자 프로필 및 꿈의 파트너 편집 기능을 위한 새로운 내비게이션 케이스 추가.
    • 회사 검색 및 선택 기능을 위한 새로운 UI 및 로직 추가.
    • 사용자 정보를 업데이트하는 새로운 API 메서드 추가.
  • 버그 수정

    • 사용자 정보 업데이트 시 HTTP 메서드 변경으로 인한 API 호출 수정.
  • 문서화

    • 코드 주석 및 문서화 업데이트로 변경된 API 메서드 반영.
  • 리팩토링

    • 여러 모델 및 뷰의 상태 관리 로직 개선.

@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

이 풀 리퀘스트는 사용자 정보 업데이트와 관련된 API 호출의 HTTP 메서드를 PATCH에서 PUT으로 변경하는 주요 변화를 포함합니다. Client 구조체와 APIProtocolupdateMyUserInfo 메서드에 대한 수정이 이루어졌으며, 이와 함께 사용자 프로필 업데이트에 필요한 입력 구조체의 필수 속성이 강화되었습니다. 추가적으로, 여러 새로운 뷰와 인텐트 클래스가 추가되어 사용자 프로필 및 회사 검색 기능을 확장하고 있습니다.

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 케이스 추가; signUp의 서브타입 명칭 변경.
Projects/Core/NetworkKit/Sources/ProfileService/ProfileService.swift ProfileServiceProtocolrequestPutUserInfo 메서드 추가.
Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift ProfileServiceMockrequestPutUserInfo 메서드 추가.
Projects/DesignSystem/DesignCore/Sources/DropDown/DropDownView.swift DropDownPicker의 사용자 상호작용 방식을 버튼에서 제스처로 변경.
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileCompany/EditProfileCompanyIntent.swift EditProfileCompanyIntent 클래스 추가 및 사용자 상호작용 핸들링 메서드 정의.
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileCompany/EditProfileCompanyModel.swift ProfilePannelModel 클래스 이름을 EditProfileCompanyModel로 변경 및 속성 수정.
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileCompany/EditProfileCompanyView.swift EditProfileCompanyView 구조체 추가.
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 구조체 추가.
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileRegion/EditProfileRegionIntent.swift EditProfileRegionIntent 클래스 추가 및 사용자 상호작용 핸들링 메서드 정의.
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileRegion/EditProfileRegionModel.swift EditProfileRegionModel 클래스 추가 및 상태 관리 정의.
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileRegion/EditProfileRegionView.swift EditProfileRegionView 구조체 추가.
Projects/Features/Home/Sources/Profile/ProfileIntent.swift ProfileIntent 클래스의 비동기 처리 및 오류 처리 개선.
Projects/Features/Home/Sources/Profile/ProfileModel.swift Stateful 프로토콜의 userInfoModel 속성을 읽기-쓰기 가능으로 변경.
Projects/Features/Home/Sources/ProfilePannel/ProfilePanelView.swift ProfilePannelView 구조체의 이름 수정 및 초기화 로직 변경.
Projects/Features/Home/Sources/ProfilePannel/ProfilePannelIntent.swift ProfilePannelIntent 클래스 삭제.
Projects/Features/Home/UnitTest/EditProfileJobOccupationTest.swift EditProfileJobOccupationTests 구조체 및 테스트 메서드 추가.
Projects/Features/Home/UnitTest/WidgetUnitTest.swift WidgetUnitTest 구조체 수정 및 성공 핸들러 추가.
Projects/Features/Project.swift .signUp 타겟을 .searchCompany로 변경 및 새로운 유닛 테스트 타겟 추가.
Projects/Features/SearchCompany/Sources/SearchCompanyIntent.swift SearchCompanyIntent 클래스 추가 및 사용자 상호작용 핸들링 메서드 정의.
Projects/Features/SearchCompany/Sources/SearchCompanyModel.swift SearchCompanyModel 클래스 추가 및 상태 관리 정의.
Projects/Features/SearchCompany/Sources/SearchCompanyView.swift SearchCompanyView 구조체 추가 및 사용자 입력 처리 로직 정의.
Projects/Features/SearchCompany/UnitTest/SearchCompanyTest.swift SearchCompanyTest 클래스 추가 및 테스트 메서드 정의.
Projects/Features/SignUp/Sources/AuthSignUp/AuthPhoneInput/AuthPhoneIntent.swift onTapNextButton 메서드의 로딩 상태 관리 개선.
Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyIntent.swift AuthCompanyIntent 클래스의 초기화 및 메서드 수정.
Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyModel.swift AuthCompanyModel 클래스의 상태 관리 구조 변경.
Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyView.swift AuthCompanyView 구조체의 초기화 및 내부 로직 변경.
Projects/Features/SignUp/UnitTest/AuthCompanyTest.swift AuthCompanyTest 클래스 주석 처리.
Projects/Features/SignUp/UnitTest/AuthPhoneInputTests.swift testOnTapNextButton 테스트 메서드 삭제.
Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift UserInfo, UserInfoProfile, DreamPartnerInfo, LocationModel 구조체의 프로토콜 구현 및 속성 변경.
Tuist/ProjectDescriptionHelpers/TargetConfiguration.swift TargetName 열거형에 searchCompany 케이스 추가.
Workspace.swift three-days-UnitTest 스킴에 .searchCompany 타겟 추가.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI
    participant Intent
    participant Model
    participant Service

    User->>UI: Edit Profile
    UI->>Intent: onTapNextButton
    Intent->>Model: update user info
    Model->>Service: requestPutUserInfo
    Service-->>Model: response
    Model-->>Intent: update state
    Intent-->>UI: refresh view
Loading

Possibly related PRs

Poem

🐰
프로필 수정, 새로운 길,
PUT으로 바뀌어, 더 나은 실.
회사 검색, 꿈의 파트너,
모든 변화, 함께하는 여정,
우리 함께, 즐거운 시간,
변화의 순간, 기쁜 마음. 🌟

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 12 minutes and 24 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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.

📥 Commits

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

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
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileCompany/EditProfileCompanyView.swift
Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyView.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: 23

🧹 Outside diff range and nitpick comments (67)
Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyModel.swift (2)

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

SwiftLint에 따르면, MARK 주석은 // MARK: ... 또는 // MARK: - ... 형식이어야 합니다. 또한, 슬래시 뒤에 공백을 추가해주세요.

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

-//MARK: Stateful
+// MARK: - Stateful
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


Line range hint 21-30: 프로토콜 정의를 클래스 외부로 이동하는 것을 고려해보세요.

프로토콜을 클래스 내부에 정의하면 가독성과 유지보수성에 영향을 줄 수 있습니다. 프로토콜을 클래스 외부에 정의하면 코드 구조가 더 명확해지고 재사용성이 높아집니다.

🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)

Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyIntent.swift (2)

60-61: task() 메서드의 구현 필요 여부 확인

현재 task() 메서드가 빈 상태로 있습니다. 구현이 필요한지 확인해 주시기 바랍니다.


16-16: 주석 형식 및 공백 수정 필요

SwiftLint에서 주석의 형식과 공백에 대한 경고가 발생했습니다. 슬래시 다음에 최소 한 칸의 공백을 추가하고, MARK 주석은 올바른 형식으로 작성해야 합니다.

다음과 같이 수정해 주시기 바랍니다:

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

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

Also applies to: 35-35

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

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileCompany/EditProfileCompanyModel.swift (5)

2-3: 파일 헤더 주석 내용 수정 필요

파일의 모듈명이 변경되었으므로, 헤더 주석의 내용을 현재 파일에 맞게 수정하는 것이 좋습니다. // SignUp 주석을 // EditProfileCompany로 변경해주세요.

코드 수정 제안:

-//  SignUp
+//  EditProfileCompany

17-17: MARK 주석 형식 수정 필요

//MARK: Stateful 주석은 // MARK: - Stateful 형식으로 수정하는 것이 좋습니다. 슬래시 뒤에 공백을 추가하고, 가독성을 높이기 위해 하이픈을 사용하는 것이 권장됩니다.

코드 수정 제안:

-//MARK: Stateful
+// MARK: - Stateful
🧰 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)


Line range hint 18-29: 프로토콜 정의 위치 수정 제안

Stateful 프로토콜이 클래스 내부에 정의되어 있습니다. Swift에서는 프로토콜을 전역 범위에서 정의하는 것이 일반적입니다. 프로토콜을 클래스 외부로 이동하는 것을 고려해보세요.

코드 수정 제안:

-final class EditProfileCompanyModel: ObservableObject {
-
-    // MARK: - Stateful
-    protocol Stateful {
-        // content
+// MARK: - Stateful
+protocol Stateful {
+    // content
     var userInfo: UserInfo? { get }
     var searchCompanyState: SearchCompanyModel.Stateful { get }
     var isValidated: Bool { get }
     // default
     var isLoading: Bool { get }
     // error
     var showErrorView: ErrorModel? { get }
     var showErrorAlert: ErrorModel? { get }
 }
+
+final class EditProfileCompanyModel: ObservableObject {
🧰 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)


56-56: MARK 주석 형식 수정 필요

//MARK: - Actionable 주석은 // MARK: - Actionable 형식으로 수정하는 것이 좋습니다. 슬래시 뒤에 공백을 추가해주세요.

코드 수정 제안:

-//MARK: - Actionable
+// MARK: - Actionable
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


Line range hint 57-68: 프로토콜 정의 위치 수정 제안

EditProfileCompanyModelActionable 프로토콜이 클래스 내부에 정의되어 있습니다. Swift에서는 프로토콜을 전역 범위에서 정의하는 것이 일반적입니다. 프로토콜을 클래스 외부로 이동하는 것을 고려해보세요.

코드 수정 제안:

-protocol EditProfileCompanyModelActionable: AnyObject {
-    // content
-    func setUserInfo(userInfo: UserInfo)
-    // default
-    func setLoading(status: Bool)
-    // error
-    func showErrorView(error: ErrorModel)
-    func showErrorAlert(error: ErrorModel)
-    func resetError()
-}
-
-extension EditProfileCompanyModel: EditProfileCompanyModelActionable {
+protocol EditProfileCompanyModelActionable: AnyObject {
+    // content
+    func setUserInfo(userInfo: UserInfo)
+    // default
+    func setLoading(status: Bool)
+    // error
+    func showErrorView(error: ErrorModel)
+    func showErrorAlert(error: ErrorModel)
+    func resetError()
+}
+
+extension EditProfileCompanyModel: EditProfileCompanyModelActionable {
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(comment_spacing)


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

(mark)


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

(mark)

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileCompany/EditProfileCompanyIntent.swift (4)

16-16: 주석 스타일 수정 제안

주석의 슬래시('//') 뒤에 공백을 추가하여 코딩 컨벤션을 준수해주세요.

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


39-39: 주석 스타일 수정 제안

주석의 슬래시('//') 뒤에 공백을 추가하여 코딩 컨벤션을 준수해주세요.

🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


57-57: 주석 스타일 수정 제안

주석의 슬래시('//') 뒤에 공백을 추가하여 코딩 컨벤션을 준수해주세요.

🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


73-85: 로딩 상태 처리 코드 개선

docatch 블록에서 중복된 model?.setLoading(status: false) 호출이 있습니다. defer 구문을 사용하여 로딩 상태 해제 코드를 간소화하고, 코드의 가독성과 유지보수성을 향상시킬 수 있습니다.

제안된 수정 사항:

 func onTapNextButton(
     state: SearchCompanyModel.Stateful
 ) {
     Task {
+        model?.setLoading(status: true)
+        defer {
+            model?.setLoading(status: false)
+        }
-        do {
-            model?.setLoading(status: true)
             let company = state.selectedCompany
             var newUserInfo = input.userInfo
             newUserInfo.profile.companyId = company?.id
             newUserInfo.dreamPartner.allowSameCompany = state.sameCompanyMatchingAvailable
             try await requestPutProfile(newUserInfo: newUserInfo)
             await popView()
         } catch {
-            model?.setLoading(status: false)
+            // 에러 처리 추가 가능
         }
     }
 }
Projects/Features/SearchCompany/Sources/SearchCompanyIntent.swift (3)

16-16: 슬래시 뒤에 공백을 추가하고 MARK 주석 형식을 수정하세요

슬래시('//') 뒤에 공백을 추가하여 주석의 가독성을 높이고, MARK 주석은 '// 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)


37-37: 슬래시 뒤에 공백을 추가하고 MARK 주석 형식을 수정하세요

슬래시('//') 뒤에 공백을 추가하여 주석의 가독성을 높이고, MARK 주석은 '// MARK: - ...' 형식을 따르는 것이 권장됩니다.

적용할 수 있는 수정 사항은 다음과 같습니다:

-//MARK: - Intentable
+// MARK: - Intentable
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


65-65: 슬래시 뒤에 공백을 추가하고 MARK 주석 형식을 수정하세요

슬래시('//') 뒤에 공백을 추가하여 주석의 가독성을 높이고, MARK 주석은 '// MARK: - ...' 형식을 따르는 것이 권장됩니다.

적용할 수 있는 수정 사항은 다음과 같습니다:

-//MARK: - Intentable
+// MARK: - Intentable
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)

Projects/Features/SearchCompany/Sources/SearchCompanyModel.swift (4)

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

//MARK: Stateful 주석에서 슬래시(//) 뒤에 공백이 없고, MARK 형식이 올바르지 않습니다. 올바른 형식은 // MARK: - Stateful입니다.

수정된 코드입니다:

-//MARK: Stateful
+// MARK: - Stateful
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


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

//MARK: State Properties 주석에서 슬래시(//) 뒤에 공백이 없고, MARK 형식이 올바르지 않습니다. 올바른 형식은 // MARK: - State Properties입니다.

수정된 코드입니다:

-//MARK: State Properties
+// MARK: - State Properties
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


86-86: 주석에 슬래시 후 공백을 추가해주세요

//MARK: - Actionable 주석에서 슬래시(//) 뒤에 공백이 필요합니다. 올바른 형식은 // MARK: - Actionable입니다.

수정된 코드입니다:

-//MARK: - Actionable
+// MARK: - Actionable
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


53-54: 옵셔널 변수의 초기화에서 nil을 생략해주세요

옵셔널 변수는 기본 값이 nil이므로 명시적으로 nil로 초기화할 필요가 없습니다.

수정된 코드입니다:

-public var nextSearchKey: String? = nil
+public var nextSearchKey: String?

-@Published public var selectedCompany: CompanySearchResponse? = nil
+@Published public var selectedCompany: CompanySearchResponse?
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(redundant_optional_initialization)


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

(redundant_optional_initialization)

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileCompany/EditProfileCompanyView.swift (3)

90-97: .foregroundStyle(.red)가 적절하지 않은 위치에 있습니다

.foregroundStyle(.red) 수정자가 .onChange 블록에 적용되어 있는데, 이는 의도한 대로 동작하지 않을 수 있습니다. 해당 수정자를 적절한 뷰에 적용하거나 제거하는 것을 고려해보세요.

-                                }
-                            }
-                        }
-                    }
-                }
-                .foregroundStyle(.red)
+                }
+            }
+        }
+    }
+}

90-96: .onChange 수정자의 위치 재고 필요

.onChange(of: showDropDown) 수정자가 Spacer()에 적용되어 있습니다. Spacer()보다는 상위 VStack이나 적절한 뷰에 적용하는 것이 더 적절할 수 있습니다.


25-25: bottomSpacingHeight 계산 방법 개선 제안

Device.height * 0.7와 같은 하드코딩된 값 대신 GeometryReader를 사용하여 동적으로 높이를 계산하는 것이 좋습니다.

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileRegion/EditProfileRegionIntent.swift (8)

16-16: 주석 스타일을 표준 형식으로 수정하세요

주석 슬래시(//) 뒤에 공백을 추가하여 // MARK: - Intent 형식으로 작성해야 합니다.

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


48-48: 주석 스타일을 표준 형식으로 수정하세요

주석 슬래시(//) 뒤에 공백을 추가하여 // MARK: - Intentable 형식으로 작성해야 합니다.

-//MARK: - Intentable
+// MARK: - Intentable
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


69-69: 주석 스타일을 표준 형식으로 수정하세요

주석 슬래시(//) 뒤에 공백을 추가하여 // MARK: - Intentable 형식으로 작성해야 합니다.

-//MARK: - Intentable
+// MARK: - Intentable
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


111-118: 에러 처리 개선 제안

requestMainRegions() 함수에서 에러 발생 시 에러를 단순히 출력하고 빈 배열을 반환하고 있습니다. 에러를 사용자에게 알리거나 로그에 기록하여 적절한 조치를 취할 수 있도록 하는 것이 좋습니다.


124-133: 에러 처리 개선 제안

requestSubRegions(mainRegion:) 함수에서도 에러 발생 시 에러를 단순히 출력하고 빈 배열을 반환하고 있습니다. 에러를 효과적으로 처리하여 사용자 경험을 향상시킬 수 있도록 개선이 필요합니다.


115-115: 에러 로그 개선

print(error)는 디버깅 용도로는 유용하지만, 프로덕션 코드에서는 적절한 로깅 시스템을 사용하여 에러를 기록하는 것이 좋습니다.


130-130: 에러 로그 개선

print(error)를 사용하는 대신, 에러를 로깅 시스템에 기록하거나 사용자에게 알리는 방법을 고려해 보세요.


154-154: 에러 로그 개선

print(error)는 프로덕션 환경에서 사용하지 않는 것이 좋습니다. 이미 ToastHelper를 통해 에러 메시지를 표시하고 있으므로, print(error)는 제거할 수 있습니다.

- print(error)
  ToastHelper.showErrorMessage(error.localizedDescription)
Projects/Features/SearchCompany/Sources/SearchCompanyView.swift (2)

73-73: 키보드 타입 설정 중복을 확인해주세요

TextInputkeyboardType.flatTextFieldOption(keyboardType:)에서 동일한 키보드 타입을 설정하고 있습니다. 중복 설정이 필요한지 확인하고 필요하지 않다면 하나로 통합하여 코드의 간결성을 높여주세요.

Also applies to: 78-78


177-181: #Preview 사용 시 Xcode 및 Swift 버전 호환성을 확인해주세요

#Preview 구문은 최신 버전의 SwiftUI에서 지원됩니다. 프로젝트의 최소 지원 버전 및 팀원들의 개발 환경(Xcode 버전 등)과 호환되는지 확인하여 호환성 문제를 예방해주세요.

Projects/Features/Home/Sources/ProfilePannel/ProfilePanelView.swift (3)

211-216: 'onTapEditIcon' 함수에서 불필요한 'Task'와 'MainActor.run' 제거

onTapEditIcon 함수 내에서 Taskawait MainActor.run을 사용하고 있지만, 이는 불필요해 보입니다. 이미 메인 스레드에서 실행 중이므로 직접 호출해도 됩니다.

다음과 같이 간소화할 수 있습니다:

- func onTapEditIcon(type: EditProfileViewType) {
-     Task {
-         await MainActor.run {
-             AppCoordinator.shared.push(.editProfile(type))
-         }
-     }
- }
+ func onTapEditIcon(type: EditProfileViewType) {
+     AppCoordinator.shared.push(.editProfile(type))
+ }

66-67: 'AppCoordinator.shared.userInfo'의 반복적인 접근 개선

여러 부분에서 AppCoordinator.shared.userInfoguard let으로 안전하게 처리하고 있습니다. 그러나 이를 뷰의 프로퍼티로 전달하거나 상위 계층에서 의존성 주입을 통해 전달하면 코드의 중복을 줄이고 가독성을 높일 수 있습니다.

Also applies to: 82-83, 99-100


118-118: 'Device.width' 사용 시 회전 대응 확인

Device.width를 사용하여 높이를 계산하고 있습니다. 기기 회전에 따른 화면 크기 변화를 올바르게 처리하려면 UIScreen.main.bounds.width를 사용하는 것이 더 적절할 수 있습니다. 회전에 대응하지 못하면 레이아웃 문제가 발생할 수 있으므로 확인이 필요합니다.

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileRegion/EditProfileRegionView.swift (3)

217-224: GeometryReader 내부의 변수 선언을 View 외부로 이동하여 성능 향상

GeometryReader 내부에서 tagModelsselectedTagModels 변수를 선언하고 있습니다. 이러한 변수들은 GeometryReader 외부로 이동하여 성능과 가독성을 향상시킬 수 있습니다.

적용 가능한 경우, 다음과 같이 수정할 수 있습니다:

+        let tagModels = state.subRegions.map {
+            TagModel(id: $0.id, name: $0.subRegion)
+        }
+        let selectedTagModels = state.selectedSubRegions.map {
+            TagModel(id: $0.id, name: $0.subRegion)
+        }
         GeometryReader { geometry in
             ZStack {
-                let tagModels = state.subRegions.map {
-                    TagModel(id: $0.id, name: $0.subRegion)
-                }
-                let selectedTagModels = state.selectedSubRegions.map {
-                    TagModel(id: $0.id, name: $0.subRegion)
-                }

87-93: onAppear에서 불필요한 애니메이션 사용 최소화

각 항목의 onAppear에서 withAnimation을 사용하면 성능에 영향을 줄 수 있습니다. 애니메이션이 꼭 필요한 경우에만 적용하여 성능 최적화를 고려하는 것이 좋습니다.


136-141: 텍스트와 배경 색상의 대비를 높여 접근성 개선

selectedRegionSingleChip에서 텍스트와 배경 색상의 대비를 높이면 사용자들이 내용을 더 쉽게 읽을 수 있습니다. 색상 조합을 재검토하여 접근성을 향상시키는 것을 권장합니다.

Projects/Features/Home/UnitTest/EditProfileJobOccupationTest.swift (1)

18-25: 테스트 초기화 로직 개선 필요

현재 구현은 기본적인 초기화만 수행하고 있습니다. 다음 사항들을 고려해주세요:

  • 테스트 전후로 상태를 초기화하는 setUp/tearDown 메서드 추가
  • 다양한 시나리오 테스트를 위한 mock 데이터 준비
 init() {
     state = EditProfileJobModel()
     intent = EditProfileJobIntent(
         model: state,
         input: .init(userInfo: .mock),
         service: ProfileServiceMock()
     )
 }
+
+func setUp() {
+    state = EditProfileJobModel()
+}
+
+func tearDown() {
+    // 테스트 후 정리 로직
+}
Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift (1)

32-35: Mock 구현체의 테스트 기능 개선이 필요합니다.

현재 구현은 기본적인 성공 케이스만 처리하고 있습니다. 테스트의 신뢰성을 높이기 위해 다음 기능들의 추가를 고려해주세요:

  1. 에러 시나리오 테스트를 위한 에러 시뮬레이션
  2. 실제 구현체와 유사한 검증 로직
  3. 호출 추적을 위한 상태 관리

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

 public final class ProfileServiceMock: ProfileServiceProtocol {
+    public var shouldFail = false
+    public var lastUserInfo: UserInfo?
+    public var callCount = 0
+
     public func requestPutUserInfo(userInfo: UserInfo) async throws {
+        callCount += 1
+        lastUserInfo = userInfo
+        
+        if shouldFail {
+            throw NSError(domain: "ProfileServiceMock", code: -1, 
+                         userInfo: [NSLocalizedDescriptionKey: "모의 에러 발생"])
+        }
+        
         print("✅ [ProfileServiceMock] requestPutUserInfo 성공!")
         return
     }
 }
Projects/Features/SearchCompany/UnitTest/SearchCompanyTest.swift (2)

15-34: setUp에서 onAppear 호출의 영향을 검증하는 것이 좋습니다.

setUp에서 호출되는 onAppear()의 영향을 검증하는 테스트 케이스를 추가하면 좋을 것 같습니다. 또한 CompanyServiceMock이 모든 테스트 시나리오를 커버하는지 확인이 필요합니다.

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

func testInitialState() {
    XCTAssertNotNil(state)
    XCTAssertNotNil(intent)
    // onAppear 호출 후의 초기 상태 검증
    XCTAssertFalse(state.isValidated)
    XCTAssertTrue(state.isTextFieldEnabled)
    XCTAssertNil(state.selectedCompany)
}

68-90: 엣지 케이스에 대한 테스트가 필요합니다.

현재 테스트는 기본 시나리오만 다루고 있습니다. 토글 동작의 다양한 상황에 대한 테스트가 추가되면 좋을 것 같습니다.

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

// 토글 해제 시나리오
func testDisableNotExistMyCompanyToggle() async {
    // 토글 활성화
    intent.onTapNoCompanyToggle()
    XCTAssertFalse(state.isTextFieldEnabled)
    
    // 토글 비활성화
    intent.onTapNoCompanyToggle()
    XCTAssertTrue(state.isTextFieldEnabled)
    XCTAssertTrue(state.isTextFieldFocused)
    XCTAssertFalse(state.isValidated)
}

// 토글 상태에서 검색어 변경 시도
func testPreventTextChangeWhenToggled() async {
    intent.onTapNoCompanyToggle()
    state.textInput = "새로운 검색어"
    XCTAssertEqual(state.textInput, "")
}
Projects/Features/SignUp/Sources/AuthSignUp/AuthPhoneInput/AuthPhoneIntent.swift (2)

58-60: 로딩 상태 관리가 개선되었습니다.

비동기 작업 동안 로딩 상태를 적절히 관리하도록 구현되었습니다. 다만, 에러 발생 시에도 로딩 상태를 해제하는 것이 좋을 것 같습니다.

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

 func onTapNextButton(with phone: String) {
     Task {
         model?.setLoading(status: true)
-        await requestSendSMS(phone: phone)
-        model?.setLoading(status: false)
+        defer { model?.setLoading(status: false) }
+        await requestSendSMS(phone: phone)
     }
 }

Line range hint 29-29: 매개변수 이름을 Swift 네이밍 컨벤션에 맞게 수정해주세요.

프로토콜에 선언된 메서드의 매개변수 이름이 대문자로 시작하고 있습니다. Swift의 네이밍 컨벤션에 따라 소문자로 시작하도록 수정이 필요합니다.

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

- func onTapNextButton(with Phone: String)
+ func onTapNextButton(with phone: String)
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobModel.swift (4)

17-30: MARK 주석 형식을 수정하고 프로토콜 문서화가 필요합니다.

프로토콜의 가독성과 유지보수성을 향상시키기 위해 다음 사항들을 개선해주세요:

-    //MARK: Stateful
+    // MARK: - Stateful
+    /// 프로필 직업 수정 화면의 상태를 관리하는 프로토콜입니다.
+    /// - Properties:
+    ///   - userInfo: 현재 사용자 정보
+    ///   - singleSelectedJob: 선택된 직업
+    ///   - isValidated: 입력값 유효성 상태
+    ///   - isLoading: 로딩 상태
+    ///   - showErrorView: 에러 뷰 표시 상태
+    ///   - showErrorAlert: 에러 알림 표시 상태
     protocol Stateful {
🧰 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
     }

90-99: 에러 처리 메서드에 대한 개선사항이 있습니다.

에러 처리와 관련하여 다음 사항들을 고려해주세요:

  1. 에러 상태 초기화 시점 검토

    • 화면 전환이나 새로운 작업 시작 시 resetError()를 자동으로 호출하는 것이 좋습니다.
  2. 에러 처리 로직 확장

    • 현재는 단순히 에러 모델을 저장만 하고 있습니다.
    • 에러 발생 시 로깅이나 분석을 위한 추가 처리를 고려해보세요.
     func showErrorView(error: ErrorModel) {
+        Logger.error("프로필 수정 에러 발생: \(error)")
         showErrorView = error
     }

1-100: 테스트 케이스 작성이 필요합니다.

모델의 안정성을 보장하기 위해 다음 테스트 케이스들을 추가하는 것을 권장드립니다:

  1. isValidated 속성에 대한 테스트

    • 모든 필드가 비어있는 경우
    • 직업이 변경된 경우
    • 직업이 동일한 경우
  2. 에러 처리 메서드 테스트

    • 에러 표시 및 초기화 검증

테스트 코드 작성에 도움이 필요하시다면 말씀해 주세요.

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

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

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

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

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

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

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

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


32-34: 옵셔널 체이닝을 사용하여 더 안전한 처리가 필요합니다

현재 구현은 JobOccupation 열거형 변환이 실패할 경우에 대한 처리가 없습니다.

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

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

79-82: 더 구체적인 에러 처리가 필요합니다

현재 구현은 모든 에러를 동일한 방식으로 처리하고 있습니다. 에러 타입에 따라 다른 메시지를 보여주는 것이 사용자 경험에 도움이 될 것 같습니다.

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

-} catch {
+} catch let networkError as NetworkError {
+    switch networkError {
+    case .serverError:
+        ToastHelper.showErrorMessage("서버 오류가 발생했습니다. 잠시 후 다시 시도해주세요")
+    case .connectionError:
+        ToastHelper.showErrorMessage("인터넷 연결을 확인해주세요")
+    default:
+        ToastHelper.showErrorMessage("프로필 수정 중 오류가 발생했습니다")
+    }
+} catch {
     ToastHelper.showErrorMessage(error.localizedDescription)
Projects/Features/Home/Sources/Profile/ProfileModel.swift (2)

24-26: 문서화 개선을 제안드립니다.

userInfoModelisValidated 프로퍼티에 대한 문서 주석을 추가하면 좋을 것 같습니다. 특히 isValidated의 사용 목적과 검증 조건을 명시하면 도움이 될 것 같습니다.

예시:

+/// 사용자 프로필 정보를 담고 있는 모델
 var userInfoModel: UserInfo? { get set }
+/// 프로필 정보의 유효성 검증 상태
 var isValidated: Bool { get }

Line range hint 1-116: 아키텍처 개선 제안

현재 구조는 잘 설계되어 있지만, 다음과 같은 개선사항을 고려해보시면 좋을 것 같습니다:

  1. StatefulProfileModelActionable 프로토콜을 별도의 파일로 분리하여 관리
  2. 에러 처리 로직을 별도의 프로토콜로 분리하여 재사용성 향상
  3. 상태 변경에 대한 히스토리 추적을 위한 로깅 메커니즘 추가
Projects/Features/Home/Sources/Profile/ProfileIntent.swift (1)

Line range hint 119-122: 🚨 위젯 삭제 기능이 동작하지 않습니다!

requestDeleteWidget 메서드에 디버그용으로 추가된 것으로 보이는 에러 발생 코드가 남아있습니다. 이로 인해 위젯 삭제 기능이 전혀 동작하지 않습니다.

다음 라인을 제거해주세요:

 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)

71-81: 매개변수 명명 규칙의 일관성 개선이 필요합니다

각 케이스에서 매개변수 이름이 inputuserInfo로 혼용되어 있습니다. 코드의 일관성과 유지보수성을 위해 통일된 명명 규칙을 사용하는 것이 좋습니다.

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

 case .editProfile(let subView):
     switch subView {
     case .profileImage(let input):
         EmptyView()
     case .jobOccupation(let input):
         EditProfileJobView(input)
     case .company(let input):
-        EditProfileCompanyView(userInfo: input)
+        EditProfileCompanyView(input: input)
     case .region(let input):
-        EditProfileRegionView(userInfo: input)
+        EditProfileRegionView(input: input)
     }

또한, .profileImage 케이스가 EmptyView()를 반환하는 것은 아직 구현이 완료되지 않았음을 의미합니다.

프로필 이미지 편집 뷰 구현에 도움이 필요하신가요?

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

28-33: 컨테이너 초기화 로직 개선 제안

MVIContainer 초기화 부분에서 타입 캐스팅을 제거하여 코드를 더 간결하게 만들 수 있습니다.

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

-        let container = MVIContainer(
-            intent: intent as EditProfileJobIntent.Intentable,
-            model: model as EditProfileJobModel.Stateful,
-            modelChangePublisher: model.objectWillChange
-        )
+        let container = MVIContainer(
+            intent: intent,
+            model: model,
+            modelChangePublisher: model.objectWillChange
+        )

50-51: 매직 넘버 제거 필요

패딩 값들을 상수로 정의하여 재사용성과 일관성을 높일 수 있습니다.

파일 상단에 다음과 같은 상수를 정의하고 사용하는 것을 제안합니다:

private enum Layout {
    static let horizontalPadding: CGFloat = 20
    static let verticalPadding: CGFloat = 10
    static let bottomPadding: CGFloat = 90
}

Also applies to: 69-69

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileRegion/EditProfileRegionModel.swift (3)

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

SwiftLint 규칙에 따라 MARK 주석 형식을 수정해야 합니다.

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

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

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

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

Also applies to: 35-35, 59-59

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


60-75: 프로토콜 메서드에 문서화 주석 추가를 권장드립니다.

각 메서드의 역할과 매개변수에 대한 설명을 추가하면 코드의 가독성과 유지보수성이 향상될 것 같습니다.

예시:

/// 사용자 정보를 설정합니다.
/// - Parameter userInfo: 설정할 사용자 정보
func setUserInfo(_ userInfo: UserInfo)

/// 메인 지역 목록을 설정합니다.
/// - Parameter regions: 설정할 지역 목록
func setMainRegions(_ regions: [String])

1-111: 아키텍처 개선 제안

전반적인 구조는 잘 설계되었으나, 다음과 같은 개선사항을 고려해보시면 좋을 것 같습니다:

  1. 상태 변경에 대한 validation 로직을 별도의 ValidationService로 분리
  2. 에러 타입을 열거형으로 정의하여 타입 안전성 강화
  3. 상태 변경 시 로깅 추가를 위한 미들웨어 패턴 도입 고려

이러한 개선사항들이 필요하시다면 구체적인 구현 방안을 제안드릴 수 있습니다.

🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(comment_spacing)


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

(mark)


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

(mark)

Projects/DesignSystem/DesignCore/Sources/DropDown/DropDownView.swift (1)

91-96: 탭 핸들러와 애니메이션이 잘 통합되었습니다.

withAnimation 블록에서 탭 핸들러와 토글을 함께 처리하는 방식이 자연스럽습니다. 하지만 사용자 피드백을 위해 탭 시 시각적 효과를 추가하는 것이 좋을 것 같습니다.

다음과 같이 탭 시 시각적 피드백을 추가해보세요:

 .onTapGesture {
+    withAnimation(.easeInOut(duration: 0.1)) {
+        // 탭 효과를 위한 상태 변수 추가 필요
+        isPressed = true
+        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
+            isPressed = false
+        }
+    }
     withAnimation {
         showDropDown.toggle()
         tapHandler?(index)
     }
 }
+.opacity(isPressed ? 0.7 : 1.0)
Projects/Core/CommonKit/Sources/Path/PathTypes.swift (1)

91-104: 문자열 지역화(Localization) 적용을 고려해주세요.

하드코딩된 한글 문자열을 지역화 시스템을 통해 관리하면 다음과 같은 이점이 있습니다:

  • 다국어 지원이 용이해집니다
  • 문자열 관리가 체계적으로 이루어집니다
  • 재사용성이 향상됩니다

예시 리팩토링:

case .editProfile(let subView):
    switch subView {
-   case .profileImage: return "프로필 이미지 수정"
+   case .profileImage: return LocalizedString.editProfile.profileImage
    // ... 다른 케이스들도 동일하게 적용
    }
Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift (4)

13-21: == 연산자 구현 최적화 제안

현재 구현된 동등성 비교 로직이 각 속성을 개별적으로 비교하고 있습니다. Swift의 표준 라이브러리 기능을 활용하여 더 간단하게 구현할 수 있습니다.

-public static func == (lhs: UserInfo, rhs: UserInfo) -> Bool {
-    if lhs.id != rhs.id { return false }
-    if lhs.name != rhs.name { return false }
-    if lhs.phone != rhs.phone { return false }
-    if lhs.profile != rhs.profile { return false }
-    if lhs.dreamPartner != rhs.dreamPartner { return false }
-    if lhs.profileWidgets != rhs.profileWidgets { return false }
-    return true
-}
+public static func == (lhs: UserInfo, rhs: UserInfo) -> Bool {
+    return lhs.id == rhs.id &&
+           lhs.name == rhs.name &&
+           lhs.phone == rhs.phone &&
+           lhs.profile == rhs.profile &&
+           lhs.dreamPartner == rhs.dreamPartner &&
+           lhs.profileWidgets == rhs.profileWidgets
+}

91-98: companyName의 기본값 상수화 제안

하드코딩된 "새회사" 문자열을 상수로 분리하는 것이 좋습니다. 이는 재사용성과 유지보수성을 향상시킵니다.

+private static let DEFAULT_COMPANY_NAME = "새회사"

public var companyName: String {
    set {
        _companyName = newValue
    }
    get {
-        return _companyName ?? "새회사"
+        return _companyName ?? Self.DEFAULT_COMPANY_NAME
    }
}

69-79: == 연산자 구현 단순화

현재 구현된 동등성 비교 로직을 더 간단하게 개선할 수 있습니다.

-public static func == (lhs: UserInfoProfile, rhs: UserInfoProfile) -> Bool {
-    if lhs.id != rhs.id { return false }
-    if lhs.gender != rhs.gender { return false }
-    if lhs.birthYear != rhs.birthYear { return false }
-    if lhs.companyId != rhs.companyId { return false }
-    if lhs._companyName != rhs._companyName { return false }
-    if lhs.jobOccupation != rhs.jobOccupation { return false }
-    if lhs.jobOccupationRawValue != rhs.jobOccupationRawValue { return false }
-    if lhs.locations != rhs.locations { return false }
-    return true
-}
+public static func == (lhs: UserInfoProfile, rhs: UserInfoProfile) -> Bool {
+    return lhs.id == rhs.id &&
+           lhs.gender == rhs.gender &&
+           lhs.birthYear == rhs.birthYear &&
+           lhs.companyId == rhs.companyId &&
+           lhs._companyName == rhs._companyName &&
+           lhs.jobOccupation == rhs.jobOccupation &&
+           lhs.jobOccupationRawValue == rhs.jobOccupationRawValue &&
+           lhs.locations == rhs.locations
+}

151-158: == 연산자 구현 개선

다른 구조체들과 마찬가지로, 동등성 비교 로직을 더 간단하게 구현할 수 있습니다.

-public static func == (lhs: DreamPartnerInfo, rhs: DreamPartnerInfo) -> Bool {
-    if lhs.upperBirthYear != rhs.upperBirthYear { return false }
-    if lhs.lowerBirthYear != rhs.lowerBirthYear { return false }
-    if lhs.jobOccupations != rhs.jobOccupations { return false }
-    if lhs.distanceType != rhs.distanceType { return false }
-    if lhs.allowSameCompany != rhs.allowSameCompany { return false }
-    return true
-}
+public static func == (lhs: DreamPartnerInfo, rhs: DreamPartnerInfo) -> Bool {
+    return lhs.upperBirthYear == rhs.upperBirthYear &&
+           lhs.lowerBirthYear == rhs.lowerBirthYear &&
+           lhs.jobOccupations == rhs.jobOccupations &&
+           lhs.distanceType == rhs.distanceType &&
+           lhs.allowSameCompany == rhs.allowSameCompany
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

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

📒 Files selected for processing (37)
  • 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/DesignSystem/DesignCore/Sources/DropDown/DropDownView.swift (1 hunks)
  • Projects/Features/Home/Sources/Profile/EditProfile/EditProfileCompany/EditProfileCompanyIntent.swift (1 hunks)
  • Projects/Features/Home/Sources/Profile/EditProfile/EditProfileCompany/EditProfileCompanyModel.swift (3 hunks)
  • Projects/Features/Home/Sources/Profile/EditProfile/EditProfileCompany/EditProfileCompanyView.swift (1 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/EditProfile/EditProfileRegion/EditProfileRegionIntent.swift (1 hunks)
  • Projects/Features/Home/Sources/Profile/EditProfile/EditProfileRegion/EditProfileRegionModel.swift (1 hunks)
  • Projects/Features/Home/Sources/Profile/EditProfile/EditProfileRegion/EditProfileRegionView.swift (1 hunks)
  • Projects/Features/Home/Sources/Profile/ProfileIntent.swift (2 hunks)
  • Projects/Features/Home/Sources/Profile/ProfileModel.swift (1 hunks)
  • Projects/Features/Home/Sources/ProfilePannel/ProfilePanelView.swift (7 hunks)
  • Projects/Features/Home/Sources/ProfilePannel/ProfilePannelIntent.swift (0 hunks)
  • Projects/Features/Home/UnitTest/EditProfileJobOccupationTest.swift (1 hunks)
  • Projects/Features/Home/UnitTest/WidgetUnitTest.swift (1 hunks)
  • Projects/Features/Project.swift (2 hunks)
  • Projects/Features/SearchCompany/Sources/SearchCompanyIntent.swift (1 hunks)
  • Projects/Features/SearchCompany/Sources/SearchCompanyModel.swift (1 hunks)
  • Projects/Features/SearchCompany/Sources/SearchCompanyView.swift (1 hunks)
  • Projects/Features/SearchCompany/UnitTest/SearchCompanyTest.swift (1 hunks)
  • Projects/Features/SignUp/Sources/AuthSignUp/AuthPhoneInput/AuthPhoneIntent.swift (1 hunks)
  • Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyIntent.swift (2 hunks)
  • Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyModel.swift (3 hunks)
  • Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyView.swift (4 hunks)
  • Projects/Features/SignUp/UnitTest/AuthCompanyTest.swift (1 hunks)
  • Projects/Features/SignUp/UnitTest/AuthPhoneInputTests.swift (0 hunks)
  • Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift (6 hunks)
  • Tuist/ProjectDescriptionHelpers/TargetConfiguration.swift (2 hunks)
  • Workspace.swift (1 hunks)
💤 Files with no reviewable changes (2)
  • Projects/Features/Home/Sources/ProfilePannel/ProfilePannelIntent.swift
  • Projects/Features/SignUp/UnitTest/AuthPhoneInputTests.swift
✅ 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/EditProfileCompany/EditProfileCompanyIntent.swift

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

(comment_spacing)


[Warning] 39-39: 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] 39-39: 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/EditProfileCompany/EditProfileCompanyModel.swift

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


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

(comment_spacing)


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

(mark)

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)

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileRegion/EditProfileRegionIntent.swift

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

(comment_spacing)


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

(comment_spacing)


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

(mark)


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

(mark)

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileRegion/EditProfileRegionModel.swift

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

(comment_spacing)


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

(comment_spacing)


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

(mark)


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

(mark)

Projects/Features/SearchCompany/Sources/SearchCompanyIntent.swift

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

(comment_spacing)


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

(comment_spacing)


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

(mark)


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

(mark)

Projects/Features/SearchCompany/Sources/SearchCompanyModel.swift

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

(comment_spacing)


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

(comment_spacing)


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

(comment_spacing)


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

(mark)


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

(mark)


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

(mark)


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

(redundant_optional_initialization)


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

(redundant_optional_initialization)

Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyIntent.swift

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

(comment_spacing)


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

(mark)

Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyModel.swift

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

(comment_spacing)


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

(mark)

Projects/Features/SignUp/UnitTest/AuthCompanyTest.swift

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

(comment_spacing)


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

(comment_spacing)

🔇 Additional comments (40)
Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyIntent.swift (6)

14-14: SearchCompany 모듈 임포트 확인

필요한 모듈인 SearchCompany가 임포트되어 기능 확장에 적절합니다.


21-21: searchCompanyIntent 프로퍼티 추가 및 초기화 확인

searchCompanyIntent 프로퍼티가 추가되고 초기화 메서드에서 적절하게 설정되었습니다.

Also applies to: 27-27, 31-31


38-38: Intentable 프로토콜 업데이트 확인

프로토콜에 searchCompanyIntent 프로퍼티와 새로운 메서드들이 추가되어 기능이 확장되었습니다.

Also applies to: 40-41


55-56: 클로저에서 약한 참조 사용으로 메모리 누수 방지

searchCompanyIntent.setSameCompanyPopupHandler 클로저에서 [weak self]를 사용하여 순환 참조에 의한 메모리 누수를 방지하였습니다.


65-66: showSameCompanyPopup() 메서드 구현 확인

searchCompanyIntent.showSameCompanyPopup()를 호출하여 메서드가 적절하게 구현되었습니다.


Line range hint 69-75: onTapNextButton 메서드의 비동기 처리 적절성 확인

Task를 사용하여 비동기적으로 payload를 업데이트하고 다음 뷰로 이동하는 로직이 구현되었습니다. 비동기 처리가 필요한 경우 적절하지만, pushNextView 메서드가 @MainActor로 선언되어 있으므로 메인 스레드에서 실행됩니다. 비동기 처리가 필요한지 검토해 주시기 바랍니다.

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

Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyView.swift (5)

14-14: 'SearchCompany' 모듈 임포트 확인

'SearchCompany' 모듈이 성공적으로 임포트되었습니다. 의존성 관리가 올바르게 이루어졌는지 확인해주세요.


26-36: 'SearchCompanyModel'과 'SearchCompanyIntent'의 초기화 및 전달

'SearchCompanyModel'과 'SearchCompanyIntent'를 초기화하고 'AuthCompanyModel'과 'AuthCompanyIntent'에 전달하는 과정이 적절하게 구현되었습니다.


91-91: 'isValidated' 상태 사용 적절성 확인

CTA 버튼의 활성화 여부를 결정하는 데 'state.searchCompanyState.isValidated'를 사용하는 것이 적절합니다.


98-98: 'onTapNextButton' 메서드 호출 검토

'intent.onTapNextButton(state: state.searchCompanyState)' 호출이 새로운 시그니처에 맞게 올바르게 사용되었습니다.


94-95: 'isNoCompanyHere' 논리 검토 필요

'if !state.searchCompanyState.isNoCompanyHere' 조건문의 논리가 의도한 대로 동작하는지 확인해주세요. 조건문의 부정 연산자가 올바르게 사용되었는지 검토가 필요합니다.

해당 조건이 원하는 동작을 수행하는지 확인하기 위해 다음 스크립트를 실행해보세요:

✅ Verification successful

Let me gather more context about the usage of isNoCompanyHere and related logic.


논리 검증 완료: 조건문이 올바르게 구현되어 있습니다

isNoCompanyHere 변수의 구현과 사용을 검토한 결과, 현재 조건문의 논리가 의도한 대로 정확하게 동작하고 있습니다:

  • isNoCompanyHere가 false일 때 (즉, 회사가 있을 때) → showSameCompanyPopup() 호출
  • isNoCompanyHere가 true일 때 (즉, "회사 없음" 상태일 때) → 다음 화면으로 이동

이는 코드의 주석과 구현 의도에 부합하며, 부정 연산자(!)의 사용이 적절합니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: 'isNoCompanyHere' 값이 false일 때 'showSameCompanyPopup()'이 호출되는지 확인

# 기대 결과: 'isNoCompanyHere'가 false일 때 'showSameCompanyPopup()'이 호출되어야 합니다.
grep -rn 'if !state.searchCompanyState.isNoCompanyHere' .

Length of output: 375


Script:

#!/bin/bash
# Search for the definition and usage of isNoCompanyHere
rg "isNoCompanyHere" -A 3 -B 3

# Search for showSameCompanyPopup implementation
ast-grep --pattern 'func showSameCompanyPopup() {
  $$$
}'

Length of output: 6641

Projects/Features/SearchCompany/Sources/SearchCompanyIntent.swift (1)

69-88: 코드 구현이 정확하며 로직이 적절합니다

onAppear 메서드에서 Combine을 사용하여 텍스트 입력을 디바운싱하고 비동기적으로 검색을 수행하는 로직이 잘 구현되었습니다.

Projects/Features/Home/Sources/ProfilePannel/ProfilePanelView.swift (1)

95-95: 'value' 파라미터가 nil일 때의 뷰 표시 확인 필요

horizonIconKeyValueViewvaluenil로 전달하고 있습니다. 이 경우 값이 표시되지 않을 수 있으므로, 의도된 동작인지 확인해야 합니다. 만약 값이 없을 때도 특정한 처리가 필요하다면, 그에 맞게 뷰를 조정해야 합니다.

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

9-11: 테스트에 필요한 추가 프레임워크 import 검토 필요

XCTest나 다른 테스트 관련 프레임워크의 import가 누락되었을 수 있습니다. 또한 테스트 실패 시나리오를 위해 XCTFail 등의 기능이 필요할 수 있습니다.


22-23: Mock 데이터 검증 필요

.mock 데이터와 ProfileServiceMock의 구현을 확인해야 합니다. 실제 사용 사례를 충분히 반영하고 있는지 검증이 필요합니다.

✅ Verification successful

Let me gather more information about the mock data structure.


Let me gather more information about the mock implementation of JobOccupation.


Mock 데이터와 ProfileServiceMock의 구현이 적절합니다

ProfileServiceMock은 단순히 성공 응답을 반환하도록 구현되어 있고, UserInfo mock 데이터는 다음과 같은 실제 사용 사례를 잘 반영하고 있습니다:

  • 직업 정보 (jobOccupation)는 서버 API 스펙과 일치하는 enum 값을 사용
  • 프로필 정보는 실제 사용되는 모든 필드를 포함
  • EditProfileJobOccupationTest에서는 직업 변경 로직을 적절히 검증
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Mock 구현 확인
rg -A 10 "ProfileServiceMock" 
# Mock 데이터 구조 확인
ast-grep --pattern 'extension $_ { static var mock: $_ { $$$  } }'

Length of output: 6274


Script:

#!/bin/bash
# UserInfo mock 데이터 구조 확인
rg -A 10 "UserInfo" --type swift

Length of output: 122943


Script:

#!/bin/bash
# JobOccupation 관련 구현 확인
rg -A 10 "JobOccupation" --type swift

Length of output: 66629

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

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

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

Projects/Features/Project.swift (4)

15-20: 새로운 searchCompany 타겟 구성이 적절합니다.

commonKit과 designCore에 대한 의존성이 올바르게 설정되어 있습니다.


21-26: 단위 테스트 타겟 구성이 적절합니다.

searchCompany 기능에 대한 단위 테스트 타겟이 올바르게 추가되었습니다.


45-46: home 타겟의 의존성 업데이트가 적절합니다.

searchCompany 기능을 home 화면에서 사용하기 위한 의존성이 올바르게 추가되었습니다.


27-34: 의존성 순환 여부를 확인해주세요.

signUp 타겟에 searchCompany 의존성이 추가되었습니다. searchCompany 타겟이 signUp에 의존성을 가지고 있지 않은지 확인이 필요합니다.

의존성 순환을 확인하기 위해 다음 스크립트를 실행합니다:

✅ Verification successful

의존성 순환이 없음을 확인했습니다.

Project.swift 파일을 검토한 결과, searchCompany 타겟은 commonKit과 designCore에만 의존성을 가지고 있으며, signUp 타겟에 대한 의존성은 없습니다. 따라서 signUp 타겟이 searchCompany를 의존성으로 추가하는 것은 안전합니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for circular dependencies between signUp and searchCompany targets

# Search for dependencies in searchCompany related files
echo "Checking searchCompany dependencies..."
rg -l "import.*SignUp" Projects/Features/SearchCompany/

# Search for any references to SignUp in searchCompany implementation
echo "Checking for SignUp references in searchCompany..."
rg "SignUp" Projects/Features/SearchCompany/

Length of output: 300


Script:

#!/bin/bash
# Let's check the Project.swift files to understand the dependency structure

# First, find all Project.swift files
echo "Finding all Project.swift files..."
fd "Project.swift$"

# Then check the content of SearchCompany's Project.swift specifically
echo -e "\nChecking SearchCompany's Project.swift for dependencies..."
cat Projects/Features/SearchCompany/Project.swift

# Also check SignUp's Project.swift for comparison
echo -e "\nChecking SignUp's Project.swift for dependencies..."
cat Projects/Features/Project.swift

Length of output: 2129

Tuist/ProjectDescriptionHelpers/TargetConfiguration.swift (2)

22-22: 새로운 Feature 타겟이 올바르게 추가되었습니다.

기존 네이밍 컨벤션을 잘 따르고 있으며, Features 섹션에 적절하게 배치되었습니다.


39-39: 프로젝트 설정 파일들의 일관성 검증이 필요합니다.

새로 추가된 searchCompany 타겟이 다른 프로젝트 설정 파일들과 올바르게 통합되었는지 확인이 필요합니다.

다음 스크립트를 실행하여 관련 설정 파일들을 확인해주세요:

✅ Verification successful

Let me gather more specific information about the configuration.


프로젝트 설정이 올바르게 구성되어 있습니다.

검증 결과, searchCompany 타겟이 다음과 같이 적절하게 구성되어 있음을 확인했습니다:

  • Features 프로젝트에서 필수 의존성(commonKit, designCore)이 올바르게 설정됨
  • 단위 테스트 타겟이 정상적으로 구성됨
  • signUphome 타겟에서 searchCompany 의존성이 올바르게 추가됨
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the integration of searchCompany target across project configuration files

# Check for target references in project configuration files
echo "Checking project configuration files for searchCompany target..."
rg -l "searchCompany" "Projects/Features/Project.swift" || echo "Warning: searchCompany not found in Features project configuration"

# Check for target dependencies
echo "Checking target dependencies..."
rg "searchCompany" "Projects/App/Project.swift" || echo "Warning: searchCompany target might not be linked in main app project"

# Verify test target configuration
echo "Checking test configuration..."
rg "SearchCompany.*UnitTest" "Projects/Features/Project.swift" || echo "Warning: Unit test target might not be configured for searchCompany"

Length of output: 771


Script:

#!/bin/bash
# Check the actual content of searchCompany configuration in Features/Project.swift
echo "Checking searchCompany configuration in Features/Project.swift:"
rg -A 10 "searchCompany" "Projects/Features/Project.swift"

# Check if there are any test targets defined in Features/Project.swift
echo -e "\nChecking test target patterns in Features/Project.swift:"
rg ".*Test.*= Target\(" "Projects/Features/Project.swift"

# Check App dependencies configuration
echo -e "\nChecking App dependencies configuration:"
rg "dependencies:" -A 10 "Projects/App/Project.swift"

Length of output: 2232

Workspace.swift (1)

48-48: 테스트 타겟 추가가 적절해 보입니다.

새로운 .searchCompany 테스트 타겟이 올바르게 추가되었습니다.

타겟의 존재 여부를 확인하기 위해 다음 스크립트를 실행하세요:

✅ Verification successful

Let me analyze the output to verify the target configuration properly.


.searchCompany 타겟이 올바르게 구성되어 있습니다

프로젝트 설정을 확인한 결과:

  • .searchCompany 메인 타겟이 적절한 의존성(commonKit, designCore)과 함께 정의되어 있습니다
  • .searchCompany 테스트 타겟이 올바르게 구성되어 있습니다
  • signUphome 타겟에서도 .searchCompany를 의존성으로 올바르게 참조하고 있습니다
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: SearchCompany 타겟이 프로젝트에 정의되어 있는지 확인

# Projects/Features 디렉토리에서 SearchCompany 관련 설정 확인
fd -t f "Project.swift" "Projects/Features" --exec rg -A 5 "searchCompany"

# 테스트 타겟 설정 확인
fd -t f "Project.swift" "Projects/Features" --exec rg -A 5 "SearchCompanyTests"

Length of output: 852


Script:

#!/bin/bash
# Let's verify the SearchCompany target and its test target definitions more thoroughly

# Check for SearchCompany target definition
ast-grep --pattern 'target: .searchCompany' -l

# Check for test target definition
ast-grep --pattern 'makeUnitTest.*searchCompany' -l

# Find Project.swift files and check their content for SearchCompany
fd "Project.swift" -x cat {} \; | rg -A 10 -B 10 "searchCompany"

Length of output: 1741

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

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

비동기 처리와 에러 핸들링을 포함한 메서드 시그니처가 적절하게 정의되었습니다.

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

37-38: ⚠️ Potential issue

successHandler 구현 필요

현재 successHandler가 비어있어 성공 시나리오에 대한 테스트가 이루어지지 않고 있습니다. 위젯 작성 성공 시의 상태 변화를 검증하는 로직이 필요합니다.

성공 핸들러의 구현 여부를 확인하기 위해 다음 스크립트를 실행합니다:

Projects/Features/SearchCompany/UnitTest/SearchCompanyTest.swift (1)

1-14: LGTM! 파일 구조와 import 문이 적절합니다.

필요한 모든 모듈이 import되어 있으며, 파일 구조가 Swift 컨벤션을 잘 따르고 있습니다.

Projects/Features/Home/Sources/Profile/ProfileModel.swift (2)

24-24: 프로토콜 속성 변경이 적절합니다.

프로필 정보 수정 기능 구현을 위해 userInfoModel 속성을 읽기/쓰기가 가능하도록 변경한 것이 적절합니다. 이는 @Published 프로퍼티와도 일관성이 있습니다.


Line range hint 39-39: 프로토콜 구현의 일관성을 확인했습니다.

ProfileModel 클래스가 Stateful 프로토콜의 모든 요구사항을 올바르게 구현하고 있습니다. @Published 프로퍼티 래퍼를 통해 상태 관리가 적절히 이루어지고 있습니다.

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

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

Task를 사용하여 비동기 작업을 처리하는 방식이 적절합니다.

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

70-91: 새로운 네비게이션 경로의 사용성 검증이 필요합니다

새로 추가된 .editProfile.editDreamPartner 경로가 앱 전체에서 올바르게 사용되고 있는지 확인이 필요합니다.

다음 스크립트를 실행하여 새로운 네비게이션 경로의 사용을 확인해보세요:

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

88-90: 메모리 누수 가능성 확인 필요

AppCoordinator.shared를 직접 참조하는 것은 메모리 누수를 발생시킬 수 있습니다.

다음 스크립트로 AppCoordinator 사용 패턴을 확인해보세요:

의존성 주입을 통해 coordinator를 전달받는 방식으로 변경하는 것을 고려해보세요.

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileRegion/EditProfileRegionModel.swift (3)

9-12: 필요한 모듈들이 적절하게 임포트되었습니다.

기본 Foundation과 함께 CommonKit, CoreKit, Model 모듈이 프로필 편집 기능 구현에 적절하게 임포트되었습니다.


17-33: Stateful 프로토콜이 잘 설계되었습니다.

상태 관리가 content, default, error로 명확하게 구분되어 있어 가독성이 좋습니다.


44-47: isValidated 로직 검증이 필요합니다.

현재 구현에서 몇 가지 고려해야 할 사항이 있습니다:

  1. selectedSubRegions가 비어있지 않은지 확인하는 것은 좋지만, 최대 선택 가능한 개수 제한이 필요할 수 있습니다.
  2. initialState 비교 시 순서에 따라 결과가 달라질 수 있습니다.

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

    var isValidated: Bool {
-        let initialState = userInfo?.profile.locations.map { $0.id } == selectedSubRegions.map { $0.id }
+        let initialLocations = Set(userInfo?.profile.locations.map { $0.id } ?? [])
+        let selectedLocations = Set(selectedSubRegions.map { $0.id })
+        let initialState = initialLocations == selectedLocations
        return selectedMainRegion != nil && selectedSubRegions.isNotEmpty && !initialState
    }
Projects/Core/CommonKit/Sources/Path/PathTypes.swift (1)

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

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

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

231-239: 구현이 깔끔하고 적절합니다

LocationModel의 구현이 간단하고 명확하며, Hashable 프로토콜 준수와 초기화 구현이 적절합니다.

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

Line range hint 662-675: HTTP 메서드 변경에 따른 동작 방식 변경 확인 필요

PATCH에서 PUT으로의 변경은 부분 업데이트에서 전체 리소스 업데이트로의 전환을 의미합니다. 이로 인해 클라이언트 측에서는 항상 전체 사용자 정보를 포함하여 요청해야 합니다.

다음 스크립트를 실행하여 클라이언트 코드에서 이 변경사항이 올바르게 반영되었는지 확인하세요:

✅ Verification successful

Let me analyze the UpdateMyUserInfoRequest schema to verify if it requires all user information fields.


Let me try a different approach to find the schema definition.


HTTP PUT 메서드 변경이 올바르게 구현되어 있음을 확인했습니다

ProfileService의 구현을 보면 updateMyUserInfo 호출 시 사용자의 필수 정보인 이름(name), 직업(jobOccupation), 회사 정보(companyId), 파트너 선호도(allowSameCompany), 활동 지역(locationIds)을 모두 포함하여 요청하고 있습니다. 이는 PUT 메서드의 전체 리소스 업데이트 특성에 부합합니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: updateMyUserInfo 메서드 호출 부분에서 전체 사용자 정보가 포함되어 있는지 확인

# Test: updateMyUserInfo 호출 패턴 검색
rg -p "updateMyUserInfo.*\(" -A 10

Length of output: 3816


Script:

#!/bin/bash
# Find the UpdateMyUserInfoRequest schema definition
ast-grep --pattern 'struct UpdateMyUserInfoRequest'

Length of output: 53


Script:

#!/bin/bash
# Search for UpdateMyUserInfoRequest definition using ripgrep
rg -p "UpdateMyUserInfoRequest" -A 10

Length of output: 2357

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

53-54: HTTP 메서드 변경에 따른 동작 검증 필요

PATCH에서 PUT으로의 변경은 부분 업데이트에서 전체 리소스 업데이트로의 전환을 의미합니다. 클라이언트 측에서 모든 필수 필드를 포함하여 전체 프로필 데이터를 전송하는지 확인이 필요합니다.

Also applies to: 186-187, 2378-2379


591-633: 구조체 필드 요구사항 변경 및 새로운 기능 추가

다음과 같은 변경사항이 있습니다:

  1. 필수 필드화:
    • name
    • jobOccupation
    • locationIds
  2. 새로운 기능:
    • allowSameCompany: 같은 회사 파트너 매칭 허용 여부

이러한 변경은 데이터 일관성을 향상시키고 매칭 기능을 확장합니다.


Line range hint 2383-2397: API 작업 정의가 적절히 업데이트됨

UpdateMyUserInfo 작업이 새로운 요구사항에 맞게 잘 수정되었습니다:

  • PUT 메서드 반영
  • 요청/응답 타입 정의 업데이트
  • 문서화 개선

Comment on lines +82 to +84
} catch {
model?.setLoading(status: false)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

에러 처리 개선 필요

catch 블록에서 로딩 상태를 해제하는 것 외에도, 사용자에게 에러 메시지를 표시하여 실패 원인에 대한 피드백을 제공하는 것이 좋습니다.

Comment on lines +62 to +66
SearchCompanyView(
state: state.searchCompanyState as! SearchCompanyModel,
intent: intent.searchCompanyIntent as! SearchCompanyIntent,
showDropDown: _showDropDown
)
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

강제 캐스팅(as!) 대신 안전한 캐스팅 사용 권장

'SearchCompanyView' 초기화 시 강제 캐스팅인 'as!'를 사용하고 있습니다. 이는 런타임 크래시를 유발할 수 있으므로, 강제 캐스팅을 피하고 안전한 캐스팅 'as?'나 옵셔널 바인딩을 사용하는 것이 좋습니다.

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

 SearchCompanyView(
-    state: state.searchCompanyState as! SearchCompanyModel,
-    intent: intent.searchCompanyIntent as! SearchCompanyIntent,
+    state: state.searchCompanyState as? SearchCompanyModel ?? SearchCompanyModel(),
+    intent: intent.searchCompanyIntent as? SearchCompanyIntent ?? SearchCompanyIntent(
+        model: state.searchCompanyState as? SearchCompanyModel ?? SearchCompanyModel(),
+        input: .init()
+    ),
     showDropDown: _showDropDown
 )
📝 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.

Suggested change
SearchCompanyView(
state: state.searchCompanyState as! SearchCompanyModel,
intent: intent.searchCompanyIntent as! SearchCompanyIntent,
showDropDown: _showDropDown
)
SearchCompanyView(
state: state.searchCompanyState as? SearchCompanyModel ?? SearchCompanyModel(),
intent: intent.searchCompanyIntent as? SearchCompanyIntent ?? SearchCompanyIntent(
model: state.searchCompanyState as? SearchCompanyModel ?? SearchCompanyModel(),
input: .init()
),
showDropDown: _showDropDown
)

Comment on lines +155 to +156
print(error)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

에러 처리 방식을 개선하세요

현재 catch 블록에서 에러를 단순히 print(error)로 출력하고 있습니다. 사용자에게 적절한 에러 메시지를 전달하거나 에러 상태를 모델에 반영하여 UI에서 표시할 수 있도록 개선하는 것이 좋습니다.

적용할 수 있는 수정 사항은 다음과 같습니다:

 } catch {
-    print(error)
+    // 에러를 모델에 전달하여 UI에서 표시하도록 처리
+    model?.setErrorState(error)
 }

또는 에러 로그를 출력하려면 디버깅 용도로 print 대신 os_log 등을 사용하는 것을 고려해보세요.

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

Comment on lines +38 to +63
extension SearchCompanyIntent {
public protocol Intentable {
// content
func onTextChanged(text: String)
func onCompanySelected(company: CompanySearchResponse)
func onTapNoCompanyToggle()
func onChangedFocusState(_ value: Bool)
func onTapSameCompanyMatching(isAgree: Bool)
func needRequestNextPage(
keyword: String,
next: String
)
func showSameCompanyPopup()
func closeSameCompanyPopup()
func onTapNextButton(state: SearchCompanyModel.Stateful)
func setSameCompanyPopupHandler(handler: @escaping (SearchCompanyModel.Stateful) -> Void)

// default
func onAppear()
func task() async
}

public struct DataModel {
public init() {}
}
}
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

extension 내부에 프로토콜 정의를 피하세요

Swift에서는 extension 내부에서 새로운 프로토콜을 정의할 수 없습니다. 프로토콜은 전역 스코프에서 정의해야 합니다. 이 코드는 컴파일 에러를 발생시킬 수 있습니다.

프로토콜 정의를 extension 밖으로 이동시키세요.

적용할 수 있는 수정 사항은 다음과 같습니다:

-public class SearchCompanyIntent {
+public class SearchCompanyIntent {
     // 기존 코드
 }
 
-extension SearchCompanyIntent {
     public protocol Intentable {
         // 프로토콜 내용
     }
     // 기타 코드
-}

+extension SearchCompanyIntent: Intentable {
     // 기존 코드
+}

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

Comment on lines +15 to +23
extension CompanySearchResponse: DropDownFetchable {
public static func == (lhs: CompanySearchResponse, rhs: CompanySearchResponse) -> Bool {
lhs.id == rhs.id
}

public func hash(into hasher: inout Hasher) {
hasher.combine(0)
}
}
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

'hash(into:)' 메서드 구현이 잘못되어 있습니다

CompanySearchResponsehash(into:) 메서드에서 모든 객체가 동일한 해시 값을 가지도록 hasher.combine(0)으로 구현되어 있습니다. 이는 해시 기반 컬렉션에서 예상치 못한 동작을 유발할 수 있습니다. id를 사용하여 해시 값을 계산하도록 수정해야 합니다.

수정된 코드입니다:

 public func hash(into hasher: inout Hasher) {
-    hasher.combine(0)
+    hasher.combine(id)
 }
📝 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.

Suggested change
extension CompanySearchResponse: DropDownFetchable {
public static func == (lhs: CompanySearchResponse, rhs: CompanySearchResponse) -> Bool {
lhs.id == rhs.id
}
public func hash(into hasher: inout Hasher) {
hasher.combine(0)
}
}
extension CompanySearchResponse: DropDownFetchable {
public static func == (lhs: CompanySearchResponse, rhs: CompanySearchResponse) -> Bool {
lhs.id == rhs.id
}
public func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}

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

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

9-11: 적절한 import 구문이지만 문서화가 필요합니다.

필요한 모듈들이 잘 import 되어 있습니다. 하지만 테스트의 목적과 범위를 명확히 하기 위해 파일 상단에 문서화 주석을 추가하면 좋을 것 같습니다.

다음과 같은 문서화 주석을 추가하는 것을 제안합니다:

+/// EditProfileJobOccupationTests는 프로필 직업 선택 기능에 대한 단위 테스트를 포함합니다.
+/// 이 테스트 스위트는 사용자가 직업을 선택할 때의 상태 변화를 검증합니다.
 struct EditProfileJobOccupationTests {

13-26: 구조체와 프로퍼티의 접근 제어가 필요합니다.

테스트 구조와 초기화가 잘 구현되어 있습니다. 하지만 명시적인 접근 제어를 추가하면 좋을 것 같습니다.

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

-struct EditProfileJobOccupationTests {
-    let state: EditProfileJobModel
-    let intent: EditProfileJobIntent
+public struct EditProfileJobOccupationTests {
+    private let state: EditProfileJobModel
+    private let intent: EditProfileJobIntent
Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift (1)

31-35: Mock 구현이 일관성 있게 작성되었습니다.

기존 메서드들과 동일한 패턴으로 구현되어 있으며, 성공 메시지 출력 형식도 일치합니다. 다만 다음 사항들을 고려해보시면 좋겠습니다:

  1. 실패 케이스 테스트를 위한 시나리오 추가
  2. 입력된 userInfo 데이터 검증 로직 추가

다음과 같이 개선해볼 수 있습니다:

+    private var shouldFail = false
+    
+    public func setShouldFail(_ fail: Bool) {
+        self.shouldFail = fail
+    }
+
     public func requestPutUserInfo(userInfo: UserInfo) async throws {
+        if shouldFail {
+            throw NetworkError.serverError
+        }
+        
+        // 데이터 유효성 검증
+        guard !userInfo.name.isEmpty else {
+            throw NetworkError.invalidRequest
+        }
+        
         print("✅ [ProfileServiceMock] requestPutUserInfo 성공!")
         return
     }
Tuist/ProjectDescriptionHelpers/TargetConfiguration.swift (1)

21-24: Features 섹션의 가독성 개선을 위한 제안

Features 섹션의 일관성을 위해 관련 타겟들을 그룹화하는 것이 좋을 것 같습니다.

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

    //MARK: - Features
+   // Auth
    case searchCompany = "SearchCompany"
    case signUp = "SignUp"
+   // Main
    case home = "Home"
+   // Preview
    case designPreview = "DesignPreview"
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)

Workspace.swift (1)

Line range hint 48-52: 테스트 타겟 정렬 개선 제안

가독성과 유지보수를 위해 테스트 타겟을 알파벳 순으로 정렬하는 것이 좋습니다.

다음과 같이 변경을 제안합니다:

                 [
                     .target(.coreKit),
-                    .target(.searchCompany),
                     .target(.designCore),
-                    .target(.signUp),
-                    .target(.home)
+                    .target(.home),
+                    .target(.searchCompany),
+                    .target(.signUp)
                 ]
Projects/Features/Home/UnitTest/WidgetUnitTest.swift (1)

Line range hint 1-95: 테스트 커버리지 개선 필요

현재 테스트는 기본적인 시나리오만 다루고 있습니다. 다음과 같은 추가 테스트 케이스들을 고려해보시기 바랍니다:

  1. 에러 시나리오 테스트
  2. 상태 전환 검증
  3. 경계값 테스트

예시 테스트 케이스:

// 에러 시나리오
@Test func handleServiceError() async throws {
    let errorService = ProfileServiceMock(shouldFail: true)
    let intent = WidgetWritingIntent(
        model: writeState,
        input: .init(widgetType: .body, content: nil, successHandler: {}),
        service: errorService
    )
    
    intent.onTapNextButton(state: writeState)
    try await Task.sleep(for: .seconds(1))
    #expect(writeState.error != nil)
}

// 상태 전환
@Test func validateStateTransitions() async throws {
    writeIntent.onChangedBodyText("test", maxCount: 15)
    #expect(writeState.isValid == true)
    writeIntent.onChangedBodyText("", maxCount: 15)
    #expect(writeState.isValid == false)
}
Projects/Features/SearchCompany/UnitTest/SearchCompanyTest.swift (1)

19-28: setUp에서 에러 처리 추가를 고려해보세요.

CompanyServiceMock 초기화 실패 시나리오에 대한 처리가 없습니다. 테스트의 안정성을 위해 에러 처리를 추가하는 것이 좋습니다.

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

 override func setUp() {
     super.setUp()
+    do {
         state = SearchCompanyModel()
         intent = SearchCompanyIntent(
             model: state,
             input: .init(),
             companyService: CompanyServiceMock()
         )
         intent.onAppear()
+    } catch {
+        XCTFail("Failed to initialize test dependencies: \(error)")
+    }
 }
Projects/Features/SignUp/Sources/AuthSignUp/AuthPhoneInput/AuthPhoneIntent.swift (1)

58-60: 로딩 상태 관리가 잘 구현되었습니다!

비동기 작업 전후로 로딩 상태를 적절히 관리하여 사용자 피드백이 개선되었습니다. 다만 다음과 같은 개선사항을 고려해보시면 좋을 것 같습니다:

  1. 타임아웃 처리 추가
  2. 구조화된 동시성 패턴 적용 (예: async let)

다음과 같이 개선해보시는 건 어떨까요?

 func onTapNextButton(with phone: String) {
     Task {
         model?.setLoading(status: true)
-        await requestSendSMS(phone: phone)
+        try? await withTimeout(seconds: 30) {
+            await requestSendSMS(phone: phone)
+        }
         model?.setLoading(status: false)
     }
 }

+private func withTimeout<T>(seconds: TimeInterval, operation: @escaping () async throws -> T) async throws -> T {
+    try await withThrowingTaskGroup(of: T.self) { group in
+        group.addTask {
+            try await operation()
+        }
+        
+        group.addTask {
+            try await Task.sleep(nanoseconds: UInt64(seconds * 1_000_000_000))
+            throw TimeoutError()
+        }
+        
+        let result = try await group.next()!
+        group.cancelAll()
+        return result
+    }
+}
+
+struct TimeoutError: Error {}
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobModel.swift (5)

9-14: Import 구문을 체계적으로 구성하면 좋겠습니다.

Import 구문을 다음과 같이 그룹화하여 가독성을 높이는 것이 좋습니다:

  1. Foundation과 같은 표준 프레임워크
  2. 내부 프레임워크 (CommonKit, CoreKit 등)
  3. UI 관련 프레임워크 (DesignCore)
  4. 모델 관련 프레임워크
import Foundation

import CommonKit
import CoreKit
import Model

import DesignCore

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

SwiftLint 경고에 따라 MARK 주석 형식을 수정하고, 각 프로퍼티에 대한 문서화를 추가하면 좋겠습니다.

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

또한 각 프로퍼티에 대한 문서화 주석을 추가하는 것이 좋습니다:

/// 사용자 정보를 저장하는 프로퍼티
var userInfo: UserInfo? { get }

/// 선택된 직업 정보를 저장하는 프로퍼티
var singleSelectedJob: JobOccupation? { get }
🧰 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: isValidated 로직을 더 간단하게 개선할 수 있습니다.

현재 구현된 검증 로직을 더 읽기 쉽고 간단하게 리팩토링할 수 있습니다.

    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
    }

54-56: 에러 처리 방식을 더 구체화하면 좋겠습니다.

현재 ErrorModel을 통해 에러를 처리하고 있지만, 다음과 같은 개선사항을 제안드립니다:

  1. 에러 타입을 명확하게 구분
  2. 에러 상황별 처리 방식 문서화
enum ProfileError: Error {
    case invalidJob
    case networkError
    case validationError
    
    var shouldShowInAlert: Bool {
        // 각 에러 타입별로 알맞은 표시 방식 결정
        switch self {
        case .networkError: return true
        default: return false
        }
    }
}

Also applies to: 90-99


77-82: 상태 변경 메서드에 유효성 검사를 추가하면 좋겠습니다.

setUserInfosetSingleSelectedJob 메서드에 기본적인 유효성 검사를 추가하여 데이터 안정성을 높일 수 있습니다.

    func setUserInfo(_ userInfo: UserInfo) {
+        guard userInfo.profile.jobOccupationRawValue.isEmpty == false else {
+            showErrorAlert(error: ErrorModel(message: "직업 정보가 없습니다"))
+            return
+        }
        self.userInfo = userInfo
    }
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileJob/EditProfileJobIntent.swift (3)

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)


40-50: 프로토콜 문서화가 필요합니다

각 메서드의 목적과 사용법을 명확히 하기 위해 문서화를 추가해주세요.

예시:

/// 프로필 작업 관련 인텐트 프로토콜
protocol Intentable {
    /// 직업 선택 시 호출되는 메서드
    /// - Parameter selectedJob: 선택된 직업 정보
    func onTapJobOccupation(selectedJob: JobOccupation)
    
    /// 다음 버튼 탭 시 호출되는 메서드
    /// - Parameter state: 현재 모델의 상태
    func onTapNextButton(state: EditProfileJobModel.Stateful)
    // ...
}

93-96: Coordinator 의존성 주입을 고려해주세요

AppCoordinator.shared를 직접 사용하는 것은 테스트를 어렵게 만들 수 있습니다. 의존성 주입을 통해 테스트 가능성을 향상시키는 것을 추천드립니다.

 class EditProfileJobIntent {
     private weak var model: EditProfileJobModelActionable?
     private let input: DataModel
     private let profileService: ProfileServiceProtocol
+    private let coordinator: AppCoordinatorProtocol
     
     init(
         model: EditProfileJobModelActionable,
         input: DataModel,
-        service: ProfileServiceProtocol = ProfileService.shared
+        service: ProfileServiceProtocol = ProfileService.shared,
+        coordinator: AppCoordinatorProtocol = AppCoordinator.shared
     ) {
         self.input = input
         self.model = model
         self.profileService = service
+        self.coordinator = coordinator
     }
     
     @MainActor
     func popToRoot() {
-        AppCoordinator.shared.pop()
+        coordinator.pop()
     }
 }
Projects/Features/Home/Sources/Profile/ProfileModel.swift (2)

24-24: 프로토콜 속성 변경이 적절하게 이루어졌습니다.

프로필 정보 수정 기능을 위해 userInfoModel 속성을 읽기/쓰기로 변경한 것이 적절해 보입니다. 다만, 속성의 용도와 상태 관리 방식에 대한 문서화를 추가하면 좋을 것 같습니다.

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

+/// 사용자 프로필 정보를 관리하는 속성입니다.
+/// 프로필 수정 시에는 반드시 `setUserInfo` 메서드를 통해 업데이트해야 합니다.
 var userInfoModel: UserInfo? { get set }

24-26: 상태 검증 로직 강화 제안

userInfoModelisValidated 속성이 밀접하게 연관되어 있는데, 상태 변경 시 자동으로 유효성 검사가 이루어지도록 개선하면 좋을 것 같습니다.

다음과 같은 구현을 제안합니다:

 @Published var userInfoModel: UserInfo? {
+    didSet {
+        validateUserInfo()
+    }
 }

+private func validateUserInfo() {
+    isValidated = userInfoModel?.isValid ?? false
+}
Projects/Features/Home/Sources/Profile/ProfileIntent.swift (2)

104-106: @mainactor 사용 권장

DispatchQueue.main.async 대신 Swift Concurrency의 @mainactor를 사용하면 더 안전하고 현대적인 방식으로 메인 스레드 작업을 보장할 수 있습니다.

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

- func fetchUserInfo(_ userInfo: UserInfo) {
-   DispatchQueue.main.async {
-     self.model?.setUserInfo(userInfo)
-   }
- }
+ @MainActor
+ func fetchUserInfo(_ userInfo: UserInfo) {
+   model?.setUserInfo(userInfo)
+ }

Line range hint 119-122: 심각: 위젯 삭제 기능이 동작하지 않음

throw NSError(domain: "33", code: 33) 구문으로 인해 위젯 삭제 API가 호출되지 않습니다. 이는 위젯 삭제 기능을 완전히 차단하는 심각한 버그입니다.

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

  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)

71-91: 네비게이션 패턴의 일관성 검토가 필요합니다.

프로필 편집과 이상적인 파트너 편집 기능이 기존 회원가입 플로우와 유사한 구조를 가지고 있습니다. 하지만 각각의 구현 방식이 다소 다릅니다:

  • 프로필 편집: userInfo 파라미터 사용
  • 이상적인 파트너 편집: 단순 EmptyView 반환

일관된 패턴을 적용하여 유지보수성을 높이는 것이 좋을 것 같습니다.

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

22-34: 초기화 로직에 대한 문서화 개선이 필요합니다.

초기화 메서드와 MVIContainer 설정에 대한 문서화를 추가하면 코드의 유지보수성이 향상될 것 같습니다.

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

+/// 프로필 직군 수정 화면을 초기화합니다.
+/// - Parameter userInfo: 현재 사용자 정보
 public init(_ userInfo: UserInfo) {
     let model = EditProfileJobModel()
     let intent = EditProfileJobIntent(
         model: model,
         input: .init(userInfo: userInfo)
     )
     let container = MVIContainer(
         intent: intent as EditProfileJobIntent.Intentable,
         model: model as EditProfileJobModel.Stateful,
         modelChangePublisher: model.objectWillChange
     )
     self._container = StateObject(wrappedValue: container)
 }

95-99: 프리뷰 구현 개선이 필요합니다.

현재 프리뷰가 단일 상태만 보여주고 있어, 다양한 상황에서의 UI를 확인하기 어렵습니다.

다음과 같이 다양한 상태의 프리뷰를 추가해보세요:

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

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

#Preview("로딩 상태") {
    NavigationView {
        EditProfileJobView(.mockLoading)
    }
}
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileRegion/EditProfileRegionModel.swift (4)

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

SwiftLint 규칙에 따라 MARK 주석은 다음과 같은 형식을 따라야 합니다:

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

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

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

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

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

Also applies to: 35-35, 59-59

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


17-33: 프로토콜 문서화 개선이 필요합니다

각 프로퍼티의 목적과 사용 사례를 명확히 설명하는 문서화가 추가되면 좋겠습니다.

다음과 같은 형식으로 문서화를 추가해주세요:

 protocol Stateful {
+    /// 현재 사용자 정보
     var userInfo: UserInfo? { get }
+    /// 사용 가능한 메인 지역 목록
     var mainRegions: [String] { get }
     // ... 나머지 프로퍼티들에 대해서도 동일하게 적용
 }

31-32: 에러 처리 구분에 대한 문서화가 필요합니다

showErrorViewshowErrorAlert의 사용 목적과 차이점이 명확하지 않습니다. 각각 어떤 상황에서 사용되어야 하는지 문서화가 필요합니다.

에러 처리 로직에 다음과 같은 문서화를 추가해주세요:

 // error
+/// 화면 전체에 표시되는 에러 뷰
+/// - 네트워크 오류나 심각한 시스템 오류 시 사용
 @Published var showErrorView: ErrorModel?
+
+/// 팝업으로 표시되는 에러 알림
+/// - 사용자 입력 오류나 경미한 오류 시 사용
 @Published var showErrorAlert: ErrorModel?

Also applies to: 53-54, 101-106


14-111: 단위 테스트 추가가 필요합니다

상태 관리와 프로토콜 기반 설계가 잘 되어있지만, 이를 검증하는 단위 테스트가 없습니다. 특히 다음 사항들에 대한 테스트가 필요합니다:

  • isValidated 로직
  • 상태 변경 메서드들
  • 에러 처리 시나리오

단위 테스트 코드 생성을 도와드릴까요?

🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(comment_spacing)


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

(mark)


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

(mark)

Projects/DesignSystem/DesignCore/Sources/DropDown/DropDownView.swift (2)

91-96: 탭 제스처 처리 방식 개선에 대한 제안

onTapGesture를 사용한 상호작용 처리는 좋은 접근이지만, 접근성(Accessibility) 지원을 위해 다음과 같은 개선을 제안드립니다.

 .containerShape(Rectangle())
 .onTapGesture {
     withAnimation {
         showDropDown.toggle()
         tapHandler?(index)
     }
 }
+.accessibilityElement(children: .ignore)
+.accessibilityLabel("\(item.name) 선택")
+.accessibilityAddTraits(.isButton)

79-96: 성능 최적화 제안

현재 구현에서는 모든 아이템이 즉시 렌더링됩니다. 데이터가 많을 경우를 대비하여 다음과 같은 최적화를 고려해보시기 바랍니다:

  1. LazyVStack의 최대 표시 항목 수를 제한하는 것을 고려해보세요.
  2. 스크롤 성능 향상을 위해 ScrollViewReader 사용을 검토해보세요.
  3. 큰 데이터셋의 경우 페이지네이션 구현을 고려해보세요.
Projects/Core/CommonKit/Sources/Path/PathTypes.swift (1)

Line range hint 69-89: 들여쓰기 일관성 개선이 필요합니다.

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

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

 case .signUp(let subView):
     switch subView {
-    case .authPhoneInput: return "전화번호 입력"
-    case .authPhoneVerify: return "전화번호 인증"
-    case .authAgreement: return "이용 약관"
+        case .authPhoneInput: return "전화번호 입력"
+        case .authPhoneVerify: return "전화번호 인증"
+        case .authAgreement: return "이용 약관"
Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift (2)

12-21: Equatable 구현 최적화 제안

현재 구현된 equality 비교 로직이 다소 복잡합니다. == 연산자를 더 간단하게 구현할 수 있습니다.

다음과 같이 리팩토링하는 것을 제안합니다:

-public static func == (lhs: UserInfo, rhs: UserInfo) -> Bool {
-    if lhs.id != rhs.id { return false }
-    if lhs.name != rhs.name { return false }
-    if lhs.phone != rhs.phone { return false }
-    if lhs.profile != rhs.profile { return false }
-    if lhs.dreamPartner != rhs.dreamPartner { return false }
-    if lhs.profileWidgets != rhs.profileWidgets { return false }
-    return true
-}
+public static func == (lhs: UserInfo, rhs: UserInfo) -> Bool {
+    return lhs.id == rhs.id &&
+           lhs.name == rhs.name &&
+           lhs.phone == rhs.phone &&
+           lhs.profile == rhs.profile &&
+           lhs.dreamPartner == rhs.dreamPartner &&
+           lhs.profileWidgets == rhs.profileWidgets
+}

150-158: 일관성을 위한 Equatable 구현 개선

UserInfo 구조체와 동일한 패턴으로 구현되어 있습니다. 코드베이스의 일관성을 위해 동일한 방식으로 리팩토링이 필요합니다.

다음과 같이 리팩토링하는 것을 제안합니다:

-public static func == (lhs: DreamPartnerInfo, rhs: DreamPartnerInfo) -> Bool {
-    if lhs.upperBirthYear != rhs.upperBirthYear { return false }
-    if lhs.lowerBirthYear != rhs.lowerBirthYear { return false }
-    if lhs.jobOccupations != rhs.jobOccupations { return false }
-    if lhs.distanceType != rhs.distanceType { return false }
-    if lhs.allowSameCompany != rhs.allowSameCompany { return false }
-    return true
-}
+public static func == (lhs: DreamPartnerInfo, rhs: DreamPartnerInfo) -> Bool {
+    return lhs.upperBirthYear == rhs.upperBirthYear &&
+           lhs.lowerBirthYear == rhs.lowerBirthYear &&
+           lhs.jobOccupations == rhs.jobOccupations &&
+           lhs.distanceType == rhs.distanceType &&
+           lhs.allowSameCompany == rhs.allowSameCompany
+}
Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyModel.swift (2)

18-18: 주석 형식 수정 필요

주석의 형식은 '// MARK: - ...'와 같이 작성하는 것이 좋습니다. 슬래시 뒤에 공백을 추가하고, 'MARK:' 뒤에도 공백을 추가하세요.

🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


Line range hint 21-28: 프로토콜 선언 위치 수정 필요

Swift에서는 프로토콜을 클래스 내부가 아닌 전역 범위에서 선언하는 것이 권장됩니다. 'Stateful' 프로토콜을 클래스 밖으로 이동하는 것을 제안합니다.

다음과 같이 프로토콜을 클래스 밖으로 이동할 수 있습니다:

+ protocol Stateful {
+     // content
+     var searchCompanyState: SearchCompanyModel.Stateful { get }
+     // default
+     var isLoading: Bool { get }
+     // error
+     var showErrorView: ErrorModel? { get }
+     var showErrorAlert: ErrorModel? { get }
+ }

  final class AuthCompanyModel: ObservableObject {

-     //MARK: Stateful
-     protocol Stateful {
-         // content
-         var searchCompanyState: SearchCompanyModel.Stateful { get }
-         // default
-         var isLoading: Bool { get }
-         // error
-         var showErrorView: ErrorModel? { get }
-         var showErrorAlert: ErrorModel? { get }
-     }

      // 나머지 코드...
  }
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)

Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyIntent.swift (2)

Line range hint 38-47: 프로토콜과 구조체를 최상위 수준으로 이동 필요

protocol Intentablestruct DataModelAuthCompanyIntent의 extension 내부에 선언되어 있습니다. Swift에서는 프로토콜과 구조체를 파일의 최상위 수준에서 선언하는 것이 일반적이며, 중첩 선언을 피하는 것이 좋습니다. 이는 코드의 가독성과 유지보수성을 향상시킵니다.

다음과 같이 수정할 수 있습니다:

+protocol AuthCompanyIntentIntentable {
+    var searchCompanyIntent: SearchCompanyIntent.Intentable { get }
+    // content
+    func onTapNextButton(state: SearchCompanyModel.Stateful)
+    func showSameCompanyPopup()
+    // default
+    func onAppear()
+    func task() async
+}
+
+struct DataModel {
+    let input: SignUpFormDomain
+}

 extension AuthCompanyIntent: AuthCompanyIntentIntentable {
     // 기존 코드 유지
 }
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


60-63: task() 함수에 대한 처리 필요

현재 func task() async 함수가 비어 있습니다. 이 함수가 필요하지 않다면 제거하고, 추후 구현 예정이라면 명확한 주석이나 TODO를 추가하여 의도를 알려주세요.

가능한 수정 예시는 다음과 같습니다:

 func task() async {
-    
+    // TODO: Implement task functionality
 }
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileCompany/EditProfileCompanyModel.swift (2)

17-17: 주석 형식 수정 필요

SwiftLint 분석 결과, 주석 뒤에 최소 하나의 공백을 추가해야 합니다. 또한 MARK 주석은 '// MARK: ...' 또는 '// MARK: - ...' 형식이어야 합니다. 따라서 다음과 같이 수정해 주세요.

-//MARK: Stateful
+// MARK: - Stateful
🧰 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)


56-56: 주석 형식 수정 필요

SwiftLint 분석 결과, 주석 뒤에 최소 하나의 공백을 추가해야 합니다. 또한 MARK 주석은 '// MARK: ...' 또는 '// MARK: - ...' 형식이어야 합니다. 따라서 다음과 같이 수정해 주세요.

-//MARK: - Actionable
+// MARK: - Actionable
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileCompany/EditProfileCompanyIntent.swift (1)

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

현재 MARK 주석에서 '//' 뒤에 공백이 없으며, SwiftLint에서 권장하는 형태인 '// MARK: - ...' 형식을 따르고 있지 않습니다. 코드의 가독성과 일관성을 위해 MARK 주석을 다음과 같이 수정하는 것을 권장합니다.

다음의 diff를 적용하여 수정할 수 있습니다:

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

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

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

Also applies to: 39-39, 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)

Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyView.swift (2)

91-98: 불리언 변수 네이밍 개선으로 코드 가독성 향상

'state.searchCompanyState.isNoCompanyHere'와 같이 이중 부정 형태의 변수명은 이해하기 어려울 수 있습니다. 변수명을 'hasCompany' 또는 'isCompanyPresent'와 같이 긍정형으로 변경하면 코드의 가독성이 향상됩니다.


Line range hint 78-78: 불필요한 스타일링 제거

'Spacer()'에 '.foregroundStyle(.red)' 스타일이 적용되어 있습니다. 'Spacer()'는 화면에 표시되지 않는 요소이므로 스타일 적용이 불필요합니다. 해당 스타일을 제거하는 것을 권장합니다.

 Spacer()
     .frame(height: bottomSpacingHeight)
     .id(1)
     .onChange(of: showDropDown) {
         if showDropDown {
             withAnimation {
                 proxy.scrollTo(1)
             }
         }
     }
-    .foregroundStyle(.red)
Projects/Features/SearchCompany/Sources/SearchCompanyIntent.swift (3)

16-16: 주석 포맷 수정 필요

//MARK: - ... 주석은 슬래시 뒤에 공백을 추가하여 // MARK: - ... 형태로 작성해야 합니다. SwiftLint 경고를 해결하기 위해 주석 형식을 수정해주세요.

Also applies to: 37-37, 65-65

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


114-121: 접근 제어자 추가 권장

searchCompanyDatarequestCompanyList 함수는 클래스 내부에서만 사용되므로 private 접근 제어자를 명시하여 외부에서의 접근을 제한하는 것이 좋습니다. 이를 통해 클래스의 캡슐화를 강화할 수 있습니다.

Also applies to: 138-157


38-63: 프로토콜 및 구조체의 선언 위치 재고 필요

Intentable 프로토콜과 DataModel 구조체가 SearchCompanyIntent의 extension 내부에 선언되어 있습니다. 이러한 타입들이 모듈 외부에서도 사용될 예정이라면, extension 밖으로 이동시켜 코드를 더욱 명확하게 구성하는 것이 좋습니다.

Projects/Features/SearchCompany/Sources/SearchCompanyModel.swift (7)

27-27: 주석 형식 수정 필요

//MARK: Stateful 주석은 올바른 형식을 따라야 합니다. MARK 뒤에 최소 한 개의 공백을 추가하고 콜론(:)을 포함하는 것이 권장됩니다.

수정을 위해 다음과 같이 변경하세요:

-//MARK: Stateful
+// MARK: - Stateful
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


50-50: 주석 형식 수정 필요

//MARK: State Properties 주석은 올바른 형식을 따라야 합니다. MARK 뒤에 공백과 콜론(:)을 추가하세요.

수정을 위해 다음과 같이 변경하세요:

-//MARK: State Properties
+// MARK: - State Properties
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


86-86: 주석 형식 수정 필요

//MARK: - Actionable 주석은 올바른 형식을 따라야 합니다. MARK 뒤에 공백을 추가하세요.

수정을 위해 다음과 같이 변경하세요:

-//MARK: - Actionable
+// MARK: - Actionable
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


53-54: 불필요한 옵셔널 초기화 제거

옵셔널 변수를 nil로 초기화하는 것은 불필요합니다. Swift에서는 옵셔널 변수 선언 시 기본값이 nil로 설정됩니다.

수정을 위해 다음과 같이 변경하세요:

-@Published public var nextSearchKey: String? = nil
+@Published public var nextSearchKey: String?
-@Published public var selectedCompany: CompanySearchResponse? = nil
+@Published public var selectedCompany: CompanySearchResponse?
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(redundant_optional_initialization)


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

(redundant_optional_initialization)


27-27: 주석 공백 추가 필요

주석 슬래시(//) 이후에 최소한 한 칸의 공백을 추가하는 것이 권장됩니다.

수정을 위해 다음과 같이 변경하세요:

-//MARK: Stateful
+// MARK: Stateful
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


50-50: 주석 공백 추가 필요

주석 슬래시(//) 이후에 최소한 한 칸의 공백을 추가하는 것이 권장됩니다.

수정을 위해 다음과 같이 변경하세요:

-//MARK: State Properties
+// MARK: State Properties
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


86-86: 주석 공백 추가 필요

주석 슬래시(//) 이후에 최소한 한 칸의 공백을 추가하는 것이 권장됩니다.

수정을 위해 다음과 같이 변경하세요:

-//MARK: - Actionable
+// MARK: - Actionable
🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileCompany/EditProfileCompanyView.swift (2)

97-97: Spacer()에 적용된 불필요한 .foregroundStyle(.red) 모디파이어 제거

Spacer()는 화면에 빈 공간을 제공하는 역할을 하므로, .foregroundStyle(.red) 모디파이어는 효과가 없습니다. 해당 모디파이어를 제거하여 코드의 가독성을 높이는 것을 권장합니다.


137-140: Preview에서 NavigationView 대신 NavigationStack 사용 고려

SwiftUI에서는 iOS 16부터 NavigationView 대신 NavigationStack을 권장합니다. 최신 API를 사용하여 호환성을 높이기 위해 Preview에서도 NavigationStack으로 변경하는 것을 제안합니다.

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileRegion/EditProfileRegionIntent.swift (7)

16-16: '//MARK:' 주석 형식 및 공백 수정 필요

주석 스타일 가이드에 따라 '//' 뒤에 공백을 추가하고, 'MARK' 주석은 '// 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)


48-48: '//MARK:' 주석 형식 및 공백 수정 필요

주석 스타일 가이드에 따라 '//' 뒤에 공백을 추가하고, 'MARK' 주석은 '// MARK: - Intentable' 형식으로 작성해 주세요.

🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


69-69: '//MARK:' 주석 형식 및 공백 수정 필요

주석 스타일 가이드에 따라 '//' 뒤에 공백을 추가하고, 'MARK' 주석은 '// MARK: - Intentable' 형식으로 작성해 주세요.

🧰 Tools
🪛 SwiftLint (0.57.0)

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

(comment_spacing)


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

(mark)


50-67: 'Intentable' 프로토콜과 'DataModel' 구조체 최상위 수준으로 이동 권장

코드의 가독성과 유지 보수를 높이기 위해 'Intentable' 프로토콜과 'DataModel' 구조체를 클래스 외부의 최상위 수준에서 선언하는 것이 좋습니다.


114-117: 'print' 대신 적절한 로깅 메커니즘 사용 권장

오류 처리를 위해 'print(error)' 대신 로그 시스템을 사용하여 오류를 기록하는 것이 좋습니다.


129-133: 'print' 대신 적절한 로깅 메커니즘 사용 권장

오류 처리를 위해 'print(error)' 대신 로그 시스템을 사용하여 오류를 기록하는 것이 좋습니다.


154-154: 불필요한 콘솔 출력 제거 또는 로깅 사용 권장

사용자에게 이미 오류 메시지를 표시하고 있으므로 'print(error)'를 제거하거나 로그 시스템을 통해 오류를 기록하는 것이 좋습니다.

Projects/Features/SearchCompany/Sources/SearchCompanyView.swift (3)

87-87: 생산 코드에서 print 문 제거 필요

생산 환경에서는 print 문 사용을 지양해야 합니다. 디버깅 후에는 해당 구문을 제거하거나 적절한 로깅으로 대체해주세요.

적용 가능한 변경사항:

- print("\(nextSearchKey)로 호출")

101-101: 생산 코드에서 print 문 제거 필요

생산 환경에서는 print 문 사용을 지양해야 합니다. 디버깅 후에는 해당 구문을 제거하거나 적절한 로깅으로 대체해주세요.

적용 가능한 변경사항:

- print(state.textInput)

156-159: 중복 코드 리팩토링 제안

두 버튼의 액션 클로저에서 동일한 코드가 반복되고 있습니다. 중복을 제거하고 코드의 재사용성을 향상시키기 위해 공통 함수를 도입하는 것을 권장합니다.

추가할 수 있는 함수:

선택된 라인 외부에 다음 함수를 추가하세요:

private func handleSameCompanySelection(isAgree: Bool) {
    intent.onTapSameCompanyMatching(isAgree: isAgree)
    intent.closeSameCompanyPopup()
    intent.onTapNextButton(state: state)
}

그리고 버튼의 액션 클로저를 다음과 같이 수정합니다:

// 첫 번째 버튼
- {
-    intent.onTapSameCompanyMatching(isAgree: false)
-    intent.closeSameCompanyPopup()
-    intent.onTapNextButton(state: state)
- }
+ {
+    handleSameCompanySelection(isAgree: false)
+ }

// 두 번째 버튼
- {
-    intent.onTapSameCompanyMatching(isAgree: true)
-    intent.closeSameCompanyPopup()
-    intent.onTapNextButton(state: state)
- }
+ {
+    handleSameCompanySelection(isAgree: true)
+ }

Also applies to: 166-169

Projects/Features/Home/Sources/ProfilePannel/ProfilePanelView.swift (1)

211-216: 불필요한 TaskMainActor 사용 제거 제안

onTapEditIcon 함수에서 Taskawait MainActor.run을 사용하고 있습니다. UI 이벤트는 기본적으로 메인 스레드에서 실행되므로, 이러한 비동기 처리는 필요하지 않습니다. 코드를 간소화하여 가독성과 유지보수성을 높일 수 있습니다.

수정 제안:

-    func onTapEditIcon(type: EditProfileViewType) {
-        Task {
-            await MainActor.run {
-                AppCoordinator.shared.push(.editProfile(type))
-            }
-        }
-    }
+    func onTapEditIcon(type: EditProfileViewType) {
+        AppCoordinator.shared.push(.editProfile(type))
+    }
Projects/Features/Home/Sources/Profile/EditProfile/EditProfileRegion/EditProfileRegionView.swift (3)

28-32: 불필요한 형 변환 제거 권장

MVIContainer 초기화 시 intentmodel에 대한 불필요한 형 변환(as)이 사용되고 있습니다. 이미 타입이 명확하므로 형 변환을 제거하여 코드의 간결성을 높일 수 있습니다.

다음과 같이 수정할 수 있습니다:

let container = MVIContainer(
    intent: intent,
    model: model,
    modelChangePublisher: model.objectWillChange
)

274-275: 배경 색상 설정 시 'fill' 수식어 사용 권장

RoundedRectangle에 배경 색상을 적용할 때 현재 foregroundStyle을 사용하고 있습니다. 그러나 도형의 배경을 채우기 위해서는 fill 수식어를 사용하는 것이 더 적절합니다.

다음과 같이 수정할 수 있습니다:

-RoundedRectangle(cornerRadius: 12)
-    .foregroundStyle(isSelected ? DesignCore.Colors.blue500 : Color(hex: 0xD3D3D3))
+RoundedRectangle(cornerRadius: 12)
+    .fill(isSelected ? DesignCore.Colors.blue500 : Color(hex: 0xD3D3D3))

77-94: ForEach에서 인덱스 기반 반복 대신 직접 요소 반복 권장

현재 ForEach에서 인덱스를 사용하여 반복하고 있습니다. SwiftUI에서는 가능한 직접 요소를 반복하는 것이 가독성과 안전성 면에서 좋습니다.

다음과 같이 수정할 수 있습니다:

ForEach(state.selectedSubRegions) { subRegion in
    selectedRegionSingleChip(text: subRegion.subRegion)
        .id(subRegion.id)
        .onTapGesture {
            intent.onTapSubRegion(
                totalSubRegions: state.selectedSubRegions,
                selectedSubRegion: subRegion
            )
        }
        .onAppear {
            if subRegion == state.selectedSubRegions.last {
                withAnimation {
                    reader.scrollTo(subRegion.id)
                }
            }
        }
}

이렇게 하면 코드의 명확성이 향상되고, 요소의 변경에도 안정적으로 동작합니다.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

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

📒 Files selected for processing (37)
  • 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/DesignSystem/DesignCore/Sources/DropDown/DropDownView.swift (1 hunks)
  • Projects/Features/Home/Sources/Profile/EditProfile/EditProfileCompany/EditProfileCompanyIntent.swift (1 hunks)
  • Projects/Features/Home/Sources/Profile/EditProfile/EditProfileCompany/EditProfileCompanyModel.swift (3 hunks)
  • Projects/Features/Home/Sources/Profile/EditProfile/EditProfileCompany/EditProfileCompanyView.swift (1 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/EditProfile/EditProfileRegion/EditProfileRegionIntent.swift (1 hunks)
  • Projects/Features/Home/Sources/Profile/EditProfile/EditProfileRegion/EditProfileRegionModel.swift (1 hunks)
  • Projects/Features/Home/Sources/Profile/EditProfile/EditProfileRegion/EditProfileRegionView.swift (1 hunks)
  • Projects/Features/Home/Sources/Profile/ProfileIntent.swift (2 hunks)
  • Projects/Features/Home/Sources/Profile/ProfileModel.swift (1 hunks)
  • Projects/Features/Home/Sources/ProfilePannel/ProfilePanelView.swift (7 hunks)
  • Projects/Features/Home/Sources/ProfilePannel/ProfilePannelIntent.swift (0 hunks)
  • Projects/Features/Home/UnitTest/EditProfileJobOccupationTest.swift (1 hunks)
  • Projects/Features/Home/UnitTest/WidgetUnitTest.swift (1 hunks)
  • Projects/Features/Project.swift (2 hunks)
  • Projects/Features/SearchCompany/Sources/SearchCompanyIntent.swift (1 hunks)
  • Projects/Features/SearchCompany/Sources/SearchCompanyModel.swift (1 hunks)
  • Projects/Features/SearchCompany/Sources/SearchCompanyView.swift (1 hunks)
  • Projects/Features/SearchCompany/UnitTest/SearchCompanyTest.swift (1 hunks)
  • Projects/Features/SignUp/Sources/AuthSignUp/AuthPhoneInput/AuthPhoneIntent.swift (1 hunks)
  • Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyIntent.swift (2 hunks)
  • Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyModel.swift (3 hunks)
  • Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyView.swift (4 hunks)
  • Projects/Features/SignUp/UnitTest/AuthCompanyTest.swift (1 hunks)
  • Projects/Features/SignUp/UnitTest/AuthPhoneInputTests.swift (0 hunks)
  • Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift (6 hunks)
  • Tuist/ProjectDescriptionHelpers/TargetConfiguration.swift (2 hunks)
  • Workspace.swift (1 hunks)
💤 Files with no reviewable changes (2)
  • Projects/Features/Home/Sources/ProfilePannel/ProfilePannelIntent.swift
  • Projects/Features/SignUp/UnitTest/AuthPhoneInputTests.swift
✅ 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/EditProfileCompany/EditProfileCompanyIntent.swift

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

(comment_spacing)


[Warning] 39-39: 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] 39-39: 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/EditProfileCompany/EditProfileCompanyModel.swift

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


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

(comment_spacing)


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

(mark)

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)

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileRegion/EditProfileRegionIntent.swift

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

(comment_spacing)


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

(comment_spacing)


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

(mark)


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

(mark)

Projects/Features/Home/Sources/Profile/EditProfile/EditProfileRegion/EditProfileRegionModel.swift

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

(comment_spacing)


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

(comment_spacing)


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

(mark)


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

(mark)

Projects/Features/SearchCompany/Sources/SearchCompanyIntent.swift

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

(comment_spacing)


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

(comment_spacing)


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

(mark)


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

(mark)

Projects/Features/SearchCompany/Sources/SearchCompanyModel.swift

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

(comment_spacing)


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

(comment_spacing)


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

(comment_spacing)


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

(mark)


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

(mark)


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

(mark)


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

(redundant_optional_initialization)


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

(redundant_optional_initialization)

Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyIntent.swift

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

(comment_spacing)


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

(mark)

Projects/Features/SignUp/Sources/ProfileInput/AuthCompany/AuthCompanyModel.swift

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

(comment_spacing)


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

(mark)

Projects/Features/SignUp/UnitTest/AuthCompanyTest.swift

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

(comment_spacing)


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

(comment_spacing)

🔇 Additional comments (22)
Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift (1)

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

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

Projects/Features/Project.swift (3)

15-20: 새로운 searchCompany 타겟이 적절하게 구성되었습니다.

기본적인 의존성(commonKit, designCore)이 올바르게 설정되어 있습니다.


21-26: 단위 테스트 타겟이 적절하게 구성되었습니다.

searchCompany 타겟에 대한 단위 테스트 설정이 프로젝트 규칙을 잘 따르고 있습니다.


27-34: 의존성 그래프 검증이 필요합니다.

signUp과 home 타겟에 searchCompany 의존성이 추가되었습니다. 순환 참조가 발생하지 않는지 확인이 필요합니다.

Also applies to: 44-47

✅ Verification successful

순환 참조 문제가 없음을 확인했습니다.

검증 결과, searchCompany 타겟은 signUp이나 home 타겟을 의존성으로 가지고 있지 않으며, 단순히 commonKit과 designCore에만 의존하고 있습니다. 따라서 signUp과 home 타겟이 searchCompany를 의존성으로 추가하더라도 순환 참조가 발생하지 않습니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: 프로젝트 의존성 순환 참조 검사

# searchCompany 타겟이 signUp이나 home을 참조하는지 확인
echo "Checking for circular dependencies..."
rg -A 5 "target: .searchCompany.*dependencies:" Projects/Features/Project.swift

Length of output: 166


Script:

#!/bin/bash
# searchCompany 타겟의 의존성 확인을 위한 패턴 수정
echo "Checking searchCompany target dependencies..."
rg "target: .searchCompany" -A 10 Projects/Features/Project.swift

# signUp과 home 타겟의 의존성도 함께 확인
echo -e "\nChecking signUp and home target dependencies..."
rg "target: .(signUp|home)" -A 10 Projects/Features/Project.swift

Length of output: 2102

Tuist/ProjectDescriptionHelpers/TargetConfiguration.swift (2)

22-22: 새로운 SearchCompany 타겟이 올바르게 추가되었습니다.

타겟 이름과 값이 기존 컨벤션을 잘 따르고 있으며, Features 섹션에 적절하게 위치해 있습니다.


39-39: 프로젝트 경로가 올바르게 설정되었습니다.

새로운 searchCompany 타겟이 다른 feature 타겟들과 함께 적절하게 그룹화되어 있습니다.

Workspace.swift (1)

Line range hint 48-52: 테스트 타겟의 중복 및 불일치 확인 필요

AI 요약에 따르면 .signUp 타겟이 .searchCompany로 이름이 변경되었다고 하는데, 현재 두 타겟이 모두 테스트 타겟 목록에 존재합니다. 이는 잠재적인 문제를 일으킬 수 있습니다.

다음 스크립트를 실행하여 프로젝트 설정에서 타겟 이름의 실제 상태를 확인하세요:

✅ Verification successful

Let me analyze the dependencies and references between these targets before making a final conclusion.


.signUp.searchCompany 타겟이 별도의 독립적인 기능임이 확인됨

Projects/Features/Project.swift 파일을 확인한 결과, .signUp.searchCompany는 서로 다른 독립적인 기능 모듈임이 확인되었습니다. 특히:

  • .searchCompany는 회사 검색 기능을 담당하는 독립적인 모듈
  • .signUp 모듈은 .searchCompany를 의존성으로 사용하는 회원가입 기능 모듈

따라서 Workspace.swift의 테스트 타겟 구성은 정상적이며, 두 모듈의 단위 테스트가 모두 필요합니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: 프로젝트 설정에서 signUp과 searchCompany 타겟의 존재 여부 확인

echo "Projects/Features 디렉토리의 프로젝트 설정 확인:"
cat Projects/Features/Project.swift

Length of output: 1569


Script:

#!/bin/bash
# Check for any references to signUp and searchCompany in the entire codebase
echo "Checking references to signUp and searchCompany:"
rg -l "signUp|searchCompany" --type swift

# Check the workspace configuration
echo -e "\nChecking Workspace.swift content:"
find . -name "Workspace.swift" -exec cat {} \;

Length of output: 4330

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

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

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


63-75: API 요청 구조에 대한 검토가 필요합니다.

클라이언트 업데이트 메서드에 전달되는 파라미터들의 안전성을 확인해야 합니다.

다음 스크립트로 API 스펙과 일치하는지 확인해주세요:

✅ Verification successful

API 요청 구조가 OpenAPI 스펙과 일치하여 안전합니다.

OpenAPI 생성 코드를 검토한 결과, UpdateMyUserInfoRequest 구조체의 모든 필드가 올바르게 매핑되어 있습니다:

  • name
  • jobOccupation
  • companyId
  • allowSameCompany
  • locationIds

현재 구현된 API 요청 구조가 생성된 타입과 정확히 일치하므로 안전성이 검증되었습니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# API 스펙에서 필수 필드 확인
rg -A 10 "updateMyUserInfo.*body.*json" 

Length of output: 41


Script:

#!/bin/bash
# Search for API client definition and updateMyUserInfo method
ast-grep --pattern 'func updateMyUserInfo'

# Search for related request/response types
rg -g '*.swift' -A 5 'struct.*UpdateMyUserInfo'

# Search for any API documentation or comments
rg -g '*.swift' -B 2 'updateMyUserInfo'

Length of output: 8916

Projects/Features/SearchCompany/UnitTest/SearchCompanyTest.swift (1)

9-13: 필요한 모듈들이 올바르게 임포트되었습니다!

테스트에 필요한 모든 모듈들이 적절하게 임포트되어 있습니다.

Projects/DesignSystem/DesignCore/Sources/DropDown/DropDownView.swift (1)

80-89: UI 구현이 개선되었습니다.

HStack을 사용한 레이아웃 구성이 더 명확하고 간결해졌습니다. 타이포그래피와 스타일링이 일관성있게 적용되어 있습니다.

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

29-30: 새로운 PathType 케이스 추가가 적절합니다!

프로필 수정과 이상형 수정을 위한 새로운 케이스가 기존 네비게이션 패턴과 일관성있게 구현되었습니다.


91-104: 새로운 화면 이름이 명확하게 정의되었습니다!

프로필 수정과 이상형 수정 관련 화면들의 이름이 사용자 친화적으로 잘 정의되었습니다.

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

231-238: 구현이 적절합니다

LocationModel의 구현이 간단하고 명확합니다. Hashable 프로토콜 준수와 초기화 구현이 적절합니다.

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

662-663: HTTP 메서드 변경이 올바르게 구현되었습니다.

API 명세에 따라 updateMyUserInfo 메서드의 HTTP 메서드가 PATCH에서 PUT으로 변경되었으며, 문서와 구현이 일관되게 수정되었습니다.

Also applies to: 675-675


Line range hint 662-675: HTTP 메서드 변경에 따른 영향도를 확인해주세요.

PATCH에서 PUT으로의 HTTP 메서드 변경이 클라이언트 코드에 미치는 영향을 확인해야 합니다.

다음 스크립트를 실행하여 클라이언트 코드의 사용 패턴을 확인하세요:

✅ Verification successful

Let's gather more information about the specific usage of these HTTP methods in the found files.


Let's check the OpenAPI configuration and any recent changes to understand the HTTP method change better.


Based on the gathered information, I can now provide the final response:

HTTP 메서드 변경이 일관되게 적용되었습니다

  • OpenApiGenerator에서 자동 생성된 코드에서 /users/my 엔드포인트가 PUT 메서드로 통일되어 있습니다.
  • 클라이언트 코드와 타입 정의 모두에서 동일한 HTTP PUT 메서드를 사용하고 있습니다.
  • 이전 PATCH 메서드 사용 흔적이 있으나, 현재 코드베이스에서는 모두 PUT으로 마이그레이션되었습니다.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: updateMyUserInfo 메서드의 HTTP 메서드 사용 패턴 확인

# 클라이언트 코드에서 PATCH 메서드로 호출하는 부분이 있는지 확인
rg -l "PATCH.*?/users/my"

# PUT 메서드로 업데이트된 호출 확인
rg -l "PUT.*?/users/my"

Length of output: 162


Script:

#!/bin/bash
# Description: HTTP 메서드 사용 상세 확인

# Client.swift와 Types.swift에서 /users/my 관련 PUT 메서드 컨텍스트 확인
echo "=== PUT /users/my 사용 컨텍스트 ==="
rg -B 2 -A 2 "PUT.*?/users/my" OpenApiGenerator/Sources/OpenapiGenerated/Client.swift OpenApiGenerator/Sources/OpenapiGenerated/Types.swift

echo -e "\n=== PATCH /users/my 히스토리 확인 ==="
# Git 히스토리에서 PATCH 메서드 관련 변경사항 확인
git grep -l "PATCH.*?/users/my" $(git rev-list --all)

# OpenAPI 스펙 파일 찾기
echo -e "\n=== OpenAPI 스펙 파일 검색 ==="
fd -e yaml -e json openapi

Length of output: 3224


Script:

#!/bin/bash
# OpenAPI 설정 파일 내용 확인
echo "=== OpenAPI 설정 파일 내용 ==="
cat OpenApiGenerator/Sources/openapi-generator-cli/openapi-generator-config.yaml

# 최근 변경사항 확인
echo -e "\n=== Client.swift 최근 변경사항 ==="
git log -p -1 OpenApiGenerator/Sources/OpenapiGenerated/Client.swift | grep -A 5 "@@"

# OpenAPI 스펙 관련 파일 추가 검색
echo -e "\n=== API 스펙 관련 파일 검색 ==="
fd -e yml -e yaml -e json api

Length of output: 440

Projects/Features/SearchCompany/Sources/SearchCompanyIntent.swift (1)

21-21: 메모리 누수 가능성 확인 필요

sameCompanyPopupHandler 클로저를 저장할 때, 클로저 내부에서 self를 강하게 참조하면 순환 참조로 인해 메모리 누수가 발생할 수 있습니다. 클로저를 설정하는 부분에서 [weak self]를 사용하여 약한 참조로 캡처하도록 검토해주세요.

Also applies to: 159-161

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

53-54: HTTP 메서드 변경 확인

updateMyUserInfo 메서드의 HTTP 메서드가 PATCH에서 PUT으로 변경되었습니다. 관련 주석과 문서가 일관성 있게 업데이트되었음을 확인했습니다.


186-187: HTTP 메서드 변경 확인

동일한 변경 사항이 여기에 반영되었습니다. 주석과 문서가 일관성을 유지하고 있습니다.


591-601: UpdateMyUserInfoRequest 구조체의 필드 업데이트

name, jobOccupation, locationIds 필드가 옵셔널에서 필수로 변경되었으며, 새로운 필드 allowSameCompany가 추가되었습니다. 이 변경은 사용자 프로필 업데이트 시 필수 정보를 명시적으로 요구하여 데이터의 무결성을 강화하고 기능을 확장하는 데에 도움이 됩니다.


615-619: UpdateMyUserInfoRequest 구조체 이니셜라이저 업데이트

이니셜라이저에서 변경된 필수 필드들이 올바르게 반영되었는지 확인했습니다. 모든 필수 매개변수가 포함되어 있어 객체 생성 시 오류가 발생하지 않을 것입니다.


624-631: 코딩 키 업데이트 확인

CodingKeys 열거형에 새로 추가된 allowSameCompany와 필수 필드들이 올바르게 포함되어 직렬화 및 역직렬화 시 문제가 없을 것으로 판단됩니다.

@jisu15-kim
Copy link
Member Author

@coderabbitai resolve

@jisu15-kim jisu15-kim merged commit 314517e into develop Nov 24, 2024
2 checks passed
@jisu15-kim jisu15-kim deleted the feature/WEAV-139 branch November 24, 2024 17:22
Copy link
Contributor

coderabbitai bot commented Nov 24, 2024

✅ Actions performed

Comments resolved.

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