[feature] cover image 업로드 및 삭제 기능 구현#537
Conversation
|
Warning Rate limit exceeded@PororoAndFriends has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 19 minutes and 30 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (2)
""" Walkthrough클럽의 커버 이미지 관리 기능이 추가되었습니다. 클럽 엔티티와 DTO에 커버 이미지 필드가 도입되었으며, 커버 이미지 업로드 및 삭제를 위한 API 엔드포인트와 서비스 메서드가 구현되었습니다. 기존 Google Cloud/Drive 관련 서비스는 전체 주석 처리되어 비활성화되었습니다. AWS SDK 관련 Gradle 의존성이 최신 버전으로 명시적으로 변경되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant ClubImageController
participant ClubImageService
participant Club
participant Repository
Client->>ClubImageController: POST /{clubId}/cover (multipart file)
ClubImageController->>ClubImageService: uploadCover(clubId, file)
ClubImageService->>Repository: findById(clubId)
Repository-->>ClubImageService: Club
ClubImageService->>Club: updateCover(newCoverPath)
ClubImageService->>Repository: save(Club)
ClubImageService-->>ClubImageController: newCoverUrl
ClubImageController-->>Client: 응답(newCoverUrl)
Client->>ClubImageController: DELETE /{clubId}/cover
ClubImageController->>ClubImageService: deleteCover(clubId)
ClubImageService->>Repository: findById(clubId)
Repository-->>ClubImageService: Club
ClubImageService->>Club: updateCover(null)
ClubImageService->>Repository: save(Club)
ClubImageService-->>ClubImageController: 완료
ClubImageController-->>Client: 성공 메시지
Possibly related PRs
Suggested labels
Suggested reviewers
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Test Results75 tests 75 ✅ 2s ⏱️ Results for commit c3b59c2. ♻️ This comment has been updated with latest results. |
There was a problem hiding this comment.
Actionable comments posted: 2
🔭 Outside diff range comments (1)
backend/src/main/java/moadong/media/service/GcsClubImageService.java (1)
1-161: GCS 마이그레이션 후 주석 처리된 코드 및 관련 설정·의존성 정리 필요현재 전체 서비스 클래스가 주석 처리되어 있지만, GCS 관련 의존성은 여전히 남아 있습니다. 마이그레이션 상태에 따라 다음을 검토해 주세요:
- backend/src/main/java/moadong/media/service/GcsClubImageService.java
• 마이그레이션이 완료되었다면 파일을 삭제하거나 별도 브랜치로 이동
• 롤백 가능성을 위해 보관이 필요하다면 TODO 주석이나 이슈 링크로 제거 계획 명시- backend/build.gradle
• implementation 'com.google.cloud:spring-cloud-gcp-storage:5.8.0' → 더 이상 사용되지 않는다면 제거- application.properties/application.yml
• google.cloud.storage.bucket.name 설정 여부 확인 후 미사용 시 제거위 항목을 정리하여 코드 가독성과 유지보수성을 확보하세요.
🧹 Nitpick comments (2)
backend/build.gradle (1)
59-59: 주석 처리된 의존성의 필요성을 명확히 하세요.
netty-nio-client의존성이 주석 처리되어 있는 이유와 향후 필요성에 대해 명확히 문서화하거나 완전히 제거하는 것이 좋겠습니다.backend/src/main/java/moadong/media/service/GoogleDriveClubImageService.java (1)
1-173: 전체 서비스 구현체가 주석 처리됨Google Drive 기반 이미지 서비스 전체가 주석 처리되어 비활성화되었습니다. Cloudflare 기반 서비스로의 완전한 전환이 확정되었다면, 주석 처리된 코드를 제거하는 것을 고려해 보세요.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
backend/build.gradle(1 hunks)backend/src/main/java/moadong/club/entity/Club.java(1 hunks)backend/src/main/java/moadong/club/entity/ClubRecruitmentInformation.java(2 hunks)backend/src/main/java/moadong/club/payload/dto/ClubDetailedResult.java(2 hunks)backend/src/main/java/moadong/media/controller/ClubImageController.java(1 hunks)backend/src/main/java/moadong/media/domain/FileType.java(1 hunks)backend/src/main/java/moadong/media/service/CloudflareImageService.java(1 hunks)backend/src/main/java/moadong/media/service/ClubImageService.java(1 hunks)backend/src/main/java/moadong/media/service/GcsClubImageService.java(1 hunks)backend/src/main/java/moadong/media/service/GoogleDriveClubImageService.java(1 hunks)backend/src/main/java/moadong/media/util/GoogleDriveConfig.java(0 hunks)backend/src/main/java/moadong/media/util/S3Config.java(1 hunks)backend/src/main/java/moadong/user/controller/UserController.java(0 hunks)
💤 Files with no reviewable changes (2)
- backend/src/main/java/moadong/user/controller/UserController.java
- backend/src/main/java/moadong/media/util/GoogleDriveConfig.java
🧰 Additional context used
🧠 Learnings (8)
backend/src/main/java/moadong/club/entity/Club.java (1)
Learnt from: lepitaaar
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/service/ClubApplyService.java:34-38
Timestamp: 2025-05-19T05:45:52.957Z
Learning: The code duplication between createClubApplication and editClubApplication methods in ClubApplyService.java is acknowledged but will be addressed in a future refactoring, as per the developer's plan.
backend/src/main/java/moadong/media/service/GoogleDriveClubImageService.java (1)
Learnt from: lepitaaar
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/service/ClubApplyService.java:34-38
Timestamp: 2025-05-19T05:45:52.957Z
Learning: The code duplication between createClubApplication and editClubApplication methods in ClubApplyService.java is acknowledged but will be addressed in a future refactoring, as per the developer's plan.
backend/src/main/java/moadong/club/payload/dto/ClubDetailedResult.java (1)
Learnt from: lepitaaar
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/service/ClubApplyService.java:34-38
Timestamp: 2025-05-19T05:45:52.957Z
Learning: The code duplication between createClubApplication and editClubApplication methods in ClubApplyService.java is acknowledged but will be addressed in a future refactoring, as per the developer's plan.
backend/src/main/java/moadong/media/service/CloudflareImageService.java (1)
Learnt from: lepitaaar
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/service/ClubApplyService.java:34-38
Timestamp: 2025-05-19T05:45:52.957Z
Learning: The code duplication between createClubApplication and editClubApplication methods in ClubApplyService.java is acknowledged but will be addressed in a future refactoring, as per the developer's plan.
backend/src/main/java/moadong/club/entity/ClubRecruitmentInformation.java (1)
Learnt from: lepitaaar
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/service/ClubApplyService.java:34-38
Timestamp: 2025-05-19T05:45:52.957Z
Learning: The code duplication between createClubApplication and editClubApplication methods in ClubApplyService.java is acknowledged but will be addressed in a future refactoring, as per the developer's plan.
backend/src/main/java/moadong/media/service/GcsClubImageService.java (1)
Learnt from: lepitaaar
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/service/ClubApplyService.java:34-38
Timestamp: 2025-05-19T05:45:52.957Z
Learning: The code duplication between createClubApplication and editClubApplication methods in ClubApplyService.java is acknowledged but will be addressed in a future refactoring, as per the developer's plan.
backend/src/main/java/moadong/media/controller/ClubImageController.java (1)
Learnt from: lepitaaar
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/service/ClubApplyService.java:34-38
Timestamp: 2025-05-19T05:45:52.957Z
Learning: The code duplication between createClubApplication and editClubApplication methods in ClubApplyService.java is acknowledged but will be addressed in a future refactoring, as per the developer's plan.
backend/src/main/java/moadong/media/service/ClubImageService.java (1)
Learnt from: lepitaaar
PR: Moadong/moadong#406
File: backend/src/main/java/moadong/club/service/ClubApplyService.java:34-38
Timestamp: 2025-05-19T05:45:52.957Z
Learning: The code duplication between createClubApplication and editClubApplication methods in ClubApplyService.java is acknowledged but will be addressed in a future refactoring, as per the developer's plan.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (11)
backend/src/main/java/moadong/media/util/S3Config.java (1)
30-30: 코드 정리 변경사항 승인.불필요한 import 제거와 주석 정리로 코드가 더 깔끔해졌습니다.
backend/src/main/java/moadong/club/entity/Club.java (1)
118-121: 일관된 패턴으로 구현된 메서드입니다.기존
updateLogo메서드와 동일한 패턴으로 구현되어 코드 일관성이 유지되었습니다.backend/src/main/java/moadong/media/domain/FileType.java (1)
8-9: enum 확장이 올바르게 구현되었습니다.기존 패턴과 일관되게
COVER타입이 추가되어 커버 이미지 기능을 지원합니다.backend/src/main/java/moadong/club/entity/ClubRecruitmentInformation.java (2)
34-36: @unique 어노테이션 사용의 적절성 검토 필요커버 이미지 필드에
@Unique어노테이션이 적용되어 있습니다. 만약 여러 클럽이 동일한 커버 이미지 URL을 공유할 가능성이 있다면, 이 제약 조건이 문제가 될 수 있습니다. 커버 이미지 URL이 클럽별로 고유해야 하는지 확인해 주세요.
116-118: LGTM!
updateCover메서드가 기존 업데이트 메서드들과 일관된 패턴으로 구현되어 있습니다.backend/src/main/java/moadong/media/service/ClubImageService.java (1)
19-21: LGTM!커버 이미지 업로드 및 삭제를 위한 새로운 인터페이스 메서드들이 기존 메서드들과 일관된 패턴으로 잘 정의되어 있습니다.
backend/src/main/java/moadong/club/payload/dto/ClubDetailedResult.java (2)
15-15: LGTM!DTO에 커버 이미지 필드가 올바르게 추가되었습니다.
44-45: LGTM!커버 이미지 필드 초기화 로직이 기존 필드들과 일관된 null 체크 패턴을 따르고 있습니다.
backend/src/main/java/moadong/media/service/CloudflareImageService.java (2)
123-135: LGTM!
uploadCover메서드가 기존uploadLogo메서드와 동일한 패턴으로 구현되어 있으며, 기존uploadFile메서드를 재사용하여 코드 중복을 방지했습니다.
137-146: LGTM!
deleteCover메서드가 기존deleteLogo메서드와 일관된 패턴으로 구현되어 있습니다. 기존deleteFile메서드를 재사용하여 코드 일관성을 유지했습니다.backend/src/main/java/moadong/media/controller/ClubImageController.java (1)
71-76: 깔끔한 구현입니다.DELETE 엔드포인트가 기존 패턴과 일관성 있게 구현되었습니다. 서비스 레이어에 적절히 위임하고 있습니다.
| implementation 'software.amazon.awssdk:s3:2.26.0' | ||
| implementation 'software.amazon.awssdk:auth:2.26.0' | ||
| // implementation 'software.amazon.awssdk:netty-nio-client:2.26.0' |
There was a problem hiding this comment.
🛠️ Refactor suggestion
의존성 관리 방식을 재검토하세요.
AWS SDK 의존성을 platform BOM에서 명시적 버전으로 변경하는 것은 다음과 같은 문제를 야기할 수 있습니다:
- 각 모듈 간 버전 일관성 관리가 어려워짐
- 의존성 충돌 가능성 증가
- 향후 업그레이드 시 각 모듈을 개별적으로 관리해야 함
기존 platform BOM 방식을 유지하면서 필요한 경우에만 특정 모듈의 버전을 재정의하는 것을 권장합니다.
- implementation 'software.amazon.awssdk:s3:2.26.0'
- implementation 'software.amazon.awssdk:auth:2.26.0'
-// implementation 'software.amazon.awssdk:netty-nio-client:2.26.0'
+ implementation platform('software.amazon.awssdk:bom:2.26.0')
+ implementation 'software.amazon.awssdk:s3'
+ implementation 'software.amazon.awssdk:auth'
+// implementation 'software.amazon.awssdk:netty-nio-client'🤖 Prompt for AI Agents
In backend/build.gradle around lines 57 to 59, the AWS SDK dependencies are
specified with explicit versions instead of using the platform BOM. This can
cause version inconsistency and dependency conflicts. To fix this, revert to
using the platform BOM for AWS SDK dependencies to manage versions centrally,
and only override specific module versions if absolutely necessary by specifying
them separately without changing the overall BOM approach.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
backend/src/test/java/moadong/media/service/CloudflareClubImageServiceLogoTest.java (2)
14-14: 사용되지 않는 import를 제거하세요.Google Drive API 관련 import가 더 이상 사용되지 않습니다. Cloudflare로 마이그레이션하면서 불필요해진 import를 제거해주세요.
-import com.google.api.services.drive.Drive;
64-65: 주석 처리된 코드를 제거하세요.마이그레이션 과정에서 주석 처리된 기존 Google Drive 관련 코드가 남아있습니다. 더 이상 필요하지 않다면 제거하는 것이 좋겠습니다.
-// doReturn( "https://drive.google.com/file/d/" + club.getId() + "/LOGO/" + mockFile.getOriginalFilename() + "/view" ) -// .when(clubImageService).uploadFile(any(), eq(mockFile), eq(FileType.LOGO));backend/src/test/java/moadong/media/service/CloudflareClubImageServiceFeedTest.java (1)
11-11: 사용되지 않는 import를 제거하세요.Google Drive API 관련 import가 더 이상 사용되지 않습니다. Cloudflare로 마이그레이션하면서 불필요해진 import를 제거해주세요.
-import com.google.api.services.drive.Drive;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
backend/src/main/java/moadong/media/controller/ClubImageController.java(1 hunks)backend/src/test/java/moadong/media/service/CloudflareClubImageServiceFeedTest.java(1 hunks)backend/src/test/java/moadong/media/service/CloudflareClubImageServiceLogoTest.java(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- backend/src/main/java/moadong/media/controller/ClubImageController.java
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (4)
backend/src/test/java/moadong/media/service/CloudflareClubImageServiceLogoTest.java (2)
34-34: 클래스명 변경이 적절합니다.Google Drive에서 Cloudflare로의 마이그레이션을 반영하여 클래스명이 적절하게 변경되었습니다.
38-38: 서비스 타입 변경이 적절합니다.테스트 대상 서비스가
CloudflareImageService로 올바르게 변경되어 마이그레이션을 정확히 반영하고 있습니다.backend/src/test/java/moadong/media/service/CloudflareClubImageServiceFeedTest.java (2)
35-35: 클래스명 변경이 적절합니다.Google Drive에서 Cloudflare로의 마이그레이션을 반영하여 클래스명이 적절하게 변경되었습니다.
39-39: 서비스 타입 변경이 적절합니다.테스트 대상 서비스가
CloudflareImageService로 올바르게 변경되어 마이그레이션을 정확히 반영하고 있습니다.
lepitaaar
left a comment
There was a problem hiding this comment.
좋네요 !!. 클라우드 플레어 이전 기대됩니다
| //package moadong.media.service; | ||
| // | ||
| //import static moadong.media.util.ClubImageUtil.containsInvalidChars; | ||
| // | ||
| //import com.google.api.client.http.FileContent; | ||
| //import com.google.api.services.drive.Drive; | ||
| //import com.google.api.services.drive.model.File; | ||
| //import com.google.api.services.drive.model.Permission; | ||
| //import java.io.IOException; | ||
| //import java.util.Collections; | ||
| //import java.util.List; | ||
| //import lombok.RequiredArgsConstructor; | ||
| //import moadong.club.entity.Club; | ||
| //import moadong.club.repository.ClubRepository; | ||
| //import moadong.global.exception.ErrorCode; | ||
| //import moadong.global.exception.RestApiException; | ||
| //import moadong.global.util.ObjectIdConverter; | ||
| //import moadong.global.util.RandomStringUtil; | ||
| //import moadong.media.domain.FileType; | ||
| //import org.bson.types.ObjectId; | ||
| //import org.springframework.beans.factory.annotation.Value; | ||
| //import org.springframework.stereotype.Service; | ||
| //import org.springframework.web.multipart.MultipartFile; | ||
| // | ||
| //@Service("googleDrive") | ||
| //@RequiredArgsConstructor | ||
| //public class GoogleDriveClubImageService implements ClubImageService { | ||
| // | ||
| // @Value("${google.drive.share-file-id}") | ||
| // String shareFileId; | ||
| // @Value("${server.feed.max-count}") | ||
| // private int MAX_FEED_COUNT; | ||
| // | ||
| // private final Drive googleDrive; | ||
| // private final ClubRepository clubRepository; | ||
| // | ||
| // private final String PREFIX = "https://drive.google.com/file/d/"; | ||
| // private final String SUFFIX = "/view"; | ||
| // | ||
| // @Override | ||
| // public String uploadLogo(String clubId, MultipartFile file) { | ||
| // ObjectId objectId = ObjectIdConverter.convertString(clubId); | ||
| // Club club = clubRepository.findClubById(objectId) | ||
| // .orElseThrow(() -> new RestApiException(ErrorCode.CLUB_NOT_FOUND)); | ||
| // | ||
| // if (club.getClubRecruitmentInformation().getLogo() != null) { | ||
| // deleteFile(club, club.getClubRecruitmentInformation().getLogo()); | ||
| // } | ||
| // | ||
| // String filePath = uploadFile(clubId, file, FileType.LOGO); | ||
| // club.updateLogo(filePath); | ||
| // clubRepository.save(club); | ||
| // return filePath; | ||
| // } | ||
| // | ||
| // @Override | ||
| // public void deleteLogo(String clubId) { | ||
| // ObjectId objectId = ObjectIdConverter.convertString(clubId); | ||
| // Club club = clubRepository.findClubById(objectId) | ||
| // .orElseThrow(() -> new RestApiException(ErrorCode.CLUB_NOT_FOUND)); | ||
| // | ||
| // if (club.getClubRecruitmentInformation().getLogo() != null) { | ||
| // deleteFile(club, club.getClubRecruitmentInformation().getLogo()); | ||
| // } | ||
| // club.updateLogo(null); | ||
| // clubRepository.save(club); | ||
| // } | ||
| // | ||
| // @Override | ||
| // public String uploadFeed(String clubId, MultipartFile file) { | ||
| // ObjectId objectId = ObjectIdConverter.convertString(clubId); | ||
| // int feedImagesCount = clubRepository.findClubById(objectId) | ||
| // .orElseThrow(() -> new RestApiException(ErrorCode.CLUB_NOT_FOUND)) | ||
| // .getClubRecruitmentInformation().getFeedImages().size(); | ||
| // | ||
| // if (feedImagesCount + 1 > MAX_FEED_COUNT) { | ||
| // throw new RestApiException(ErrorCode.TOO_MANY_FILES); | ||
| // } | ||
| // return uploadFile(clubId, file, FileType.FEED); | ||
| // } | ||
| // | ||
| // @Override | ||
| // public void updateFeeds(String clubId, List<String> newFeedImageList) { | ||
| // ObjectId objectId = ObjectIdConverter.convertString(clubId); | ||
| // Club club = clubRepository.findClubById(objectId) | ||
| // .orElseThrow(() -> new RestApiException(ErrorCode.CLUB_NOT_FOUND)); | ||
| // | ||
| // if (newFeedImageList.size() > MAX_FEED_COUNT) { | ||
| // throw new RestApiException(ErrorCode.TOO_MANY_FILES); | ||
| // } | ||
| // | ||
| // List<String> feedImages = club.getClubRecruitmentInformation().getFeedImages(); | ||
| // if (feedImages != null && !feedImages.isEmpty()) { | ||
| // deleteFeedImages(club, feedImages, newFeedImageList); | ||
| // } | ||
| // club.updateFeedImages(newFeedImageList); | ||
| // clubRepository.save(club); | ||
| // } | ||
| // | ||
| // private void deleteFeedImages(Club club, List<String> feedImages, List<String> newFeedImages) { | ||
| // for (String feedsImage : feedImages) { | ||
| // if (!newFeedImages.contains(feedsImage)) { | ||
| // deleteFile(club, feedsImage); | ||
| // } | ||
| // } | ||
| // } | ||
| // | ||
| // @Override | ||
| // public void deleteFile(Club club, String filePath) { | ||
| // //"https://drive.google.com/file/d/{fileId}/view" -> {fileId} | ||
| // String fileId = filePath.split("/")[5]; | ||
| // try { | ||
| // googleDrive.files() | ||
| // .delete(fileId) | ||
| // .setSupportsAllDrives(true) // 공유 드라이브(Shared Drive)도 지원할 경우 | ||
| // .execute(); | ||
| // } catch (IOException e) { | ||
| // throw new RestApiException(ErrorCode.IMAGE_DELETE_FAILED); | ||
| // } | ||
| // } | ||
| // | ||
| // private String uploadFile(String clubId, MultipartFile file, FileType fileType) { | ||
| // if (file == null) { | ||
| // throw new RestApiException(ErrorCode.FILE_NOT_FOUND); | ||
| // } | ||
| // // MultipartFile → java.io.File 변환 | ||
| // java.io.File tempFile; | ||
| // try { | ||
| // tempFile = java.io.File.createTempFile("upload-", file.getOriginalFilename()); | ||
| // file.transferTo(tempFile); | ||
| // } catch (IOException e) { | ||
| // throw new RestApiException(ErrorCode.FILE_TRANSFER_ERROR); | ||
| // } | ||
| // | ||
| // // 메타데이터 생성 | ||
| // File fileMetadata = new File(); | ||
| // String fileName = file.getOriginalFilename(); | ||
| // if (containsInvalidChars(fileName)) { | ||
| // fileName = RandomStringUtil.generateRandomString(10); | ||
| // } | ||
| // | ||
| // fileMetadata.setName(clubId + "/" + fileType + "/" + fileName); | ||
| // fileMetadata.setMimeType(file.getContentType()); | ||
| // // 공유 ID 설정 | ||
| // fileMetadata.setParents(Collections.singletonList(shareFileId)); | ||
| // | ||
| // // 파일 업로드 | ||
| // FileContent mediaContent = new FileContent(file.getContentType(), tempFile); | ||
| // // 전체 공개 권한 설정 | ||
| // Permission publicPermission = new Permission() | ||
| // .setType("anyone") // 누구나 | ||
| // .setRole("reader"); // 읽기 권한 | ||
| // | ||
| // File uploadedFile; | ||
| // try { | ||
| // uploadedFile= googleDrive.files().create(fileMetadata, mediaContent) | ||
| // .setFields("id") | ||
| // .execute(); | ||
| // | ||
| // googleDrive.permissions().create(uploadedFile.getId(), publicPermission) | ||
| // .setFields("id") | ||
| // .execute(); | ||
| // } catch (Exception e) { | ||
| // throw new RestApiException(ErrorCode.IMAGE_UPLOAD_FAILED); | ||
| // }finally { | ||
| // // 임시 파일 삭제 | ||
| // tempFile.delete(); | ||
| // } | ||
| // // 공유 링크 반환 | ||
| // return PREFIX + uploadedFile.getId() + SUFFIX; | ||
| // } | ||
| // | ||
| //} |
#️⃣연관된 이슈
📝작업 내용
Summary by CodeRabbit
신규 기능
버그 수정
리팩터
기타