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-138] Profile Image 업로드 기능 구현 #56

Merged
merged 4 commits into from
Dec 7, 2024

Conversation

jisu15-kim
Copy link
Member

@jisu15-kim jisu15-kim commented Dec 7, 2024

구현사항

  • Profile Image 업로드 기능
  • Presigned URL 방식을 통한 업로드
  • PHPickerViewController 활용

Summary by CodeRabbit

  • 신규 기능

    • 프로필 이미지 업로드를 위한 URL 생성 및 업로드 완료 처리를 지원하는 메서드 추가.
    • 사용자가 사진을 선택하고 미리 볼 수 있는 새로운 SwiftUI 컴포넌트 추가.
    • 프로필 관리 기능 향상을 위한 여러 상태 변수 및 UI 요소 추가.
  • 버그 수정

    • 프로필 관련 데이터 처리 및 오류 처리를 개선.
  • 문서화

    • 사진 라이브러리 접근에 대한 설명 추가로 개인정보 보호 설정 강화.
  • 스타일

    • 프로필 패널 레이아웃 및 효과 조정.

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

coderabbitai bot commented Dec 7, 2024

Walkthrough

이 풀 리퀘스트는 Client 구조체에 두 개의 새로운 공개 메서드인 getProfileImageUploadUrlcompleteProfileImageUpload를 추가합니다. 이 메서드들은 프로필 이미지 업로드를 위한 URL을 생성하고 업로드 완료를 등록하는 기능을 제공합니다. 또한, APIProtocol에 관련 메서드와 데이터 구조가 추가되어 프로필 이미지 관리 기능을 향상시킵니다. 이외에도 여러 파일에서 UI 및 데이터 모델에 대한 변경이 포함되어 있습니다.

Changes

파일 경로 변경 요약
OpenApiGenerator/Sources/OpenapiGenerated/Client.swift - 메서드 추가: getProfileImageUploadUrlcompleteProfileImageUpload
OpenApiGenerator/Sources/OpenapiGenerated/Types.swift - 메서드 추가: getProfileImageUploadUrlcompleteProfileImageUpload
- 구조체 추가: GetProfileImageUploadUrlResponse, CompleteProfileImageUploadRequest
OpenApiGenerator/Sources/openapi-generator-cli/3days-oas - 하위 프로젝트 커밋 해시 업데이트
Projects/App/Project.swift - infoPlist"NSPhotoLibraryUsageDescription" 키 추가
Projects/Core/CommonKit/Sources/Path/PathTypes.swift - SignUpSubViewTypeauthPhoneVerify 케이스 추가
- 해시 및 동등성 메서드 업데이트
Projects/Core/NetworkKit/Sources/ProfileService/ProfileService.swift - 메서드 추가: requestUploadImage
- 여러 비공식 메서드 추가
Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift - 메서드 추가: requestUploadImage
Projects/DesignSystem/DesignCore/Resources/Images/Images.xcassets/Profile/camera_circle_fill.imageset/Contents.json - 새 JSON 파일 생성: Contents.json
Projects/DesignSystem/DesignCore/Sources/PhotoPicker/PhotoPickerView.swift - 새 구조체 추가: PhotoPickerView 및 관련 메서드들
Projects/DesignSystem/DesignCore/Sources/PhotoPicker/PhotoPreviewView.swift - 새 구조체 추가: PhotoPreviewView 및 초기화 메서드 추가
Projects/Features/Home/Sources/Profile/ProfileIntent.swift - DataModel 구조체에 userInfo 속성 추가
Projects/Features/Home/Sources/Profile/ProfileView.swift - 초기화 메서드 업데이트: userInfo 매개변수 추가
Projects/Features/Home/Sources/ProfilePannel/ProfilePanelView.swift - 여러 상태 변수 추가 및 UI 업데이트
Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift - UserInfoProfileprofileImageUrl 속성 추가

Possibly related PRs

Suggested labels

Design

🐰 "변경된 프로필, 사진을 올려요,
새 URL로, 업로드를 시작해요.
사진 선택, 미리보기까지,
모두 함께, 즐거운 시간이지!
더 나은 프로필, 함께 만들어가요!" 🐇


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

🧹 Outside diff range and nitpick comments (10)
Projects/DesignSystem/DesignCore/Sources/PhotoPicker/PhotoPreviewView.swift (3)

46-46: 코드와 주석의 불일치 수정 필요

주석에서는 10%씩 크기 감소라고 되어 있으나, 코드에서는 scale 값이 0.7로 설정되어 실제로는 약 30%씩 감소하고 있습니다. 주석이나 코드를 수정하여 일관성을 맞춰주세요.

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

- let scale = CGFloat(0.7)  // 10% 씩 크기 감소
+ let scale = CGFloat(0.7)  // 30%씩 크기 감소

50-50: 디버그용 print 문 제거 권장

프로덕션 코드에서 print 문은 성능에 영향을 줄 수 있고, 불필요한 콘솔 출력을 발생시킬 수 있습니다. 필요 시 로그 라이브러리를 사용하거나 해당 구문을 제거하는 것이 좋습니다.

- print(whileCount)

98-98: 강제 언래핑 대신 nil 병합 연산자 사용 제안

navigationTitle == nil ? "" : navigationTitle! 대신에 navigationTitle ?? ""를 사용하여 강제 언래핑을 피하고 코드를 간결하게 만들 수 있습니다.

- .navigationTitle(navigationTitle == nil ? "" : navigationTitle!)
+ .navigationTitle(navigationTitle ?? "")
Projects/Core/NetworkKit/Sources/ProfileService/ProfileService.swift (2)

122-125: 변수 이름 중복으로 인한 가독성 저하

매개변수 url과 내부 변수 url의 이름이 동일하여 가독성이 떨어질 수 있습니다. 변수 이름을 명확하게 구분하여 코드의 이해도를 높이는 것이 좋습니다.

- func requestUploadImage(image: Data, url: String) async throws {
-     guard let url = URL(string: url) else { return }
+ func requestUploadImage(image: Data, urlString: String) async throws {
+     guard let url = URL(string: urlString) else { throw URLError(.badURL) }

123-135: 프로덕션 코드에서 debugPrint 사용 최소화 권장

debugPrint 문은 디버깅 용도로 사용되며, 프로덕션 환경에서는 불필요한 로그를 발생시킬 수 있습니다. 로그 레벨을 설정할 수 있는 로깅 프레임워크를 사용하거나 해당 구문을 제거하는 것이 좋습니다.

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

2750-3118: 불필요한 주석 제거 및 코드 간결화 권장

생성된 코드에 불필요한 주석과 빈 줄이 많아 전체적인 가독성이 떨어집니다. 주석은 필요한 부분에만 포함하고, 코드 스타일을 정리하여 유지보수성을 높이는 것이 좋습니다.

Projects/DesignSystem/DesignCore/Sources/PhotoPicker/PhotoPickerView.swift (1)

76-88: View 확장 메서드의 매개변수 개선이 필요합니다.

현재 구현은 기본 필터와 선택 제한을 커스터마이즈할 수 없습니다.

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

 public extension View {
     func photoPicker(
         isPresented: Binding<Bool>,
+        filter: PHPickerFilter = .images,
+        selectionLimit: Int = 1,
         imageHandler: @escaping ([UIImage]) -> Void
     ) -> some View {
         fullScreenCover(isPresented: isPresented, content: {
-            PhotoPickerView { images in
+            PhotoPickerView(
+                filter: filter,
+                limit: selectionLimit
+            ) { images in
                 imageHandler(images)
             }
         })
     }
 }
Projects/App/Project.swift (1)

19-19: 사진 라이브러리 사용 설명의 현지화가 필요합니다.

현재 설명이 한국어로만 되어 있어, 다국어 지원이 필요할 수 있습니다.

InfoPlist.strings 파일을 생성하여 다음과 같이 현지화를 구현하는 것을 제안합니다:

- "NSPhotoLibraryUsageDescription": "프로필 사진 변경에 활용됩니다."
+ "NSPhotoLibraryUsageDescription": "${PHOTO_LIBRARY_USAGE_DESCRIPTION}"

그리고 각 언어별 InfoPlist.strings 파일에 다음과 같이 추가:

// ko.lproj/InfoPlist.strings
"PHOTO_LIBRARY_USAGE_DESCRIPTION" = "프로필 사진 변경에 활용됩니다.";

// en.lproj/InfoPlist.strings
"PHOTO_LIBRARY_USAGE_DESCRIPTION" = "Used for changing profile pictures.";
Projects/Features/Home/Sources/Profile/ProfileIntent.swift (1)

Line range hint 143-146: 위젯 삭제 요청 메서드의 에러 처리가 잘못되었습니다.

현재 구현은 항상 에러를 발생시키고 실제 삭제 요청은 실행되지 않습니다.

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

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

924-1037: 이미지 업로드 완료 콜백 구현이 적절합니다.

타임아웃 메커니즘을 통한 미완료 이미지 정리 로직이 잘 구현되어 있습니다. 다만, 문서에 구체적인 타임아웃 시간을 명시하면 좋을 것 같습니다.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 82c64aa and a95f5ae.

⛔ Files ignored due to path filters (3)
  • Projects/DesignSystem/DesignCore/Resources/Images/Images.xcassets/Profile/camera_circle_fill.imageset/camera_circle_fill.png is excluded by !**/*.png
  • Projects/DesignSystem/DesignCore/Resources/Images/Images.xcassets/Profile/camera_circle_fill.imageset/[email protected] is excluded by !**/*.png
  • Projects/DesignSystem/DesignCore/Resources/Images/Images.xcassets/Profile/camera_circle_fill.imageset/[email protected] is excluded by !**/*.png
📒 Files selected for processing (14)
  • OpenApiGenerator/Sources/OpenapiGenerated/Client.swift (1 hunks)
  • OpenApiGenerator/Sources/OpenapiGenerated/Types.swift (6 hunks)
  • OpenApiGenerator/Sources/openapi-generator-cli/3days-oas (1 hunks)
  • Projects/App/Project.swift (1 hunks)
  • Projects/Core/CommonKit/Sources/Path/PathTypes.swift (1 hunks)
  • Projects/Core/NetworkKit/Sources/ProfileService/ProfileService.swift (2 hunks)
  • Projects/Core/NetworkKit/Sources/ProfileService/ProfileServiceMock.swift (1 hunks)
  • Projects/DesignSystem/DesignCore/Resources/Images/Images.xcassets/Profile/camera_circle_fill.imageset/Contents.json (1 hunks)
  • Projects/DesignSystem/DesignCore/Sources/PhotoPicker/PhotoPickerView.swift (1 hunks)
  • Projects/DesignSystem/DesignCore/Sources/PhotoPicker/PhotoPreviewView.swift (1 hunks)
  • Projects/Features/Home/Sources/Profile/ProfileIntent.swift (2 hunks)
  • Projects/Features/Home/Sources/Profile/ProfileView.swift (2 hunks)
  • Projects/Features/Home/Sources/ProfilePannel/ProfilePanelView.swift (3 hunks)
  • Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift (5 hunks)
✅ Files skipped from review due to trivial changes (2)
  • Projects/DesignSystem/DesignCore/Resources/Images/Images.xcassets/Profile/camera_circle_fill.imageset/Contents.json
  • OpenApiGenerator/Sources/openapi-generator-cli/3days-oas
👮 Files not reviewed due to content moderation or server errors (3)
  • Projects/Core/CommonKit/Sources/Path/PathTypes.swift
  • Projects/Model/Model/Sources/Auth/Domain/UserInfo.swift
  • Projects/Features/Home/Sources/Profile/ProfileView.swift
🔇 Additional comments (5)
Projects/DesignSystem/DesignCore/Sources/PhotoPicker/PhotoPreviewView.swift (1)

63-65: 반복문의 종료 조건 검토 필요

현재 종료 조건이 newSize.width < 200 || newSize.height < 200로 설정되어 있습니다. 이로 인해 너비나 높이 중 하나만 200보다 작아져도 반복문이 종료됩니다. 원하는 동작이 모두의 크기가 최소한의 크기에 도달하는 것이라면 조건을 &&로 변경하는 것이 좋습니다.

- if newSize.width < 200 || newSize.height < 200 {
+ if newSize.width < 200 && newSize.height < 200 {
Projects/Core/NetworkKit/Sources/ProfileService/ProfileService.swift (1)

127-128: 업로드된 이미지의 공개 접근 권한 검토 필요

x-amz-acl 헤더에 "public-read"를 설정하면 업로드된 이미지가 공개적으로 접근 가능해집니다. 보안 및 개인정보 보호 측면에서 이러한 설정이 의도된 것인지 확인이 필요합니다.

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

112-115: 조기 반환 로직이 적절합니다.

userInfo가 이미 있는 경우 불필요한 네트워크 호출을 방지하는 최적화가 잘 되어있습니다.

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

792-923: 프로필 이미지 업로드 URL 생성 구현이 적절합니다.

Presigned URL을 사용한 이미지 업로드 방식이 보안적으로 안전하며, 표준 에러 처리도 잘 구현되어 있습니다.


792-1037: 이미지 업로드 프로세스 검증이 필요합니다.

두 엔드포인트가 연계되어 동작하는 프로세스에 대한 검증이 필요합니다:

  1. URL 생성
  2. 이미지 업로드 (클라이언트 측)
  3. 완료 콜백
✅ Verification successful

이미지 업로드 프로세스가 적절히 구현되어 있습니다

코드 분석 결과, 이미지 업로드 프로세스가 다음과 같이 명확하게 구현되어 있습니다:

  1. getProfileImageUploadUrl API를 통해 업로드 URL을 획득
  2. 클라이언트에서 해당 URL로 이미지 업로드 수행
  3. completeProfileImageUpload API를 통해 업로드 완료 콜백 처리

특히 다음 안전장치들이 확인됩니다:

  • 업로드 URL 생성 시 이미지 확장자 검증
  • 콜백 미수신 시 이미지 자동 삭제 메커니즘
  • 400, 401, 500 등 다양한 에러 상황에 대한 처리
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation of image upload process in the client code

# Check for proper error handling in image upload process
rg -A 5 "uploadImage|handleImageUpload" 

# Check for timeout handling implementation
rg -A 5 "timeout.*upload|upload.*timeout"

Length of output: 85


Script:

#!/bin/bash
# Let's search for any implementation related to profile image upload
rg -A 5 "profile.*image.*upload" --type swift

# Search for any documentation or comments about image upload process
rg -A 5 "이미지.*업로드" --type swift

# Search for any error handling related to image upload
rg -A 5 "ErrorResponse.*image" --type swift

# Look for any test cases related to image upload
fd "test.*\.swift" --exec rg -l "profile.*image.*upload|이미지.*업로드"

Length of output: 24853


Script:

#!/bin/bash
# Let's check for the schema definitions related to profile image upload
ast-grep --pattern 'struct GetProfileImageUploadUrlResponse {
  $$$
}'

# Check for timeout or expiry related configurations
ast-grep --pattern 'struct CompleteProfileImageUploadRequest {
  $$$
}'

# Look for any error handling related to timeouts
rg "일정시간|timeout|expire" --type swift

Length of output: 2107

@jisu15-kim jisu15-kim merged commit 5933517 into develop Dec 7, 2024
2 checks passed
@jisu15-kim jisu15-kim deleted the feature/WEAV-138 branch December 7, 2024 14:09
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