From a1104364a3ffad31915d43766838a16a02c76d76 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Tue, 18 Nov 2025 02:11:48 +0900 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20Media=20=ED=8C=8C=EC=9D=BC=EC=9D=84?= =?UTF-8?q?=20=EC=9E=84=EC=8B=9C=20=EA=B2=BD=EB=A1=9C=EC=97=90=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20=ED=9B=84=20/originals=20S3=EB=A1=9C=20=EB=B3=B5?= =?UTF-8?q?=EC=82=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../media/domain/service/MediaS3Service.java | 37 +++++++++++++++++++ .../domain/service/S3PresignedUrlService.java | 34 ++++++++++++++++- 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 src/main/java/leets/leenk/domain/media/domain/service/MediaS3Service.java diff --git a/src/main/java/leets/leenk/domain/media/domain/service/MediaS3Service.java b/src/main/java/leets/leenk/domain/media/domain/service/MediaS3Service.java new file mode 100644 index 00000000..eefa8939 --- /dev/null +++ b/src/main/java/leets/leenk/domain/media/domain/service/MediaS3Service.java @@ -0,0 +1,37 @@ +package leets.leenk.domain.media.domain.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.net.URI; +import java.util.List; + +@Service +@RequiredArgsConstructor +public class MediaS3Service { + + private final S3PresignedUrlService s3PresignedUrlService; + + public String moveToOriginals(String tempUrl) { + if (tempUrl == null || tempUrl.isBlank()) { + return tempUrl; + } + + if (tempUrl.contains("/originals/")) { + return tempUrl; + } + + String tempKey = extractKeyFromUrl(tempUrl); + String originalsKey = tempKey.replace("temp/", "originals/"); + + s3PresignedUrlService.copyObject(tempKey, originalsKey); + s3PresignedUrlService.deleteObject(tempKey); + + return s3PresignedUrlService.getUrl(originalsKey); + } + + private String extractKeyFromUrl(String url) { + URI uri = URI.create(url); + return uri.getPath().substring(1); + } +} diff --git a/src/main/java/leets/leenk/domain/media/domain/service/S3PresignedUrlService.java b/src/main/java/leets/leenk/domain/media/domain/service/S3PresignedUrlService.java index 2b57385d..6526a467 100644 --- a/src/main/java/leets/leenk/domain/media/domain/service/S3PresignedUrlService.java +++ b/src/main/java/leets/leenk/domain/media/domain/service/S3PresignedUrlService.java @@ -5,6 +5,9 @@ import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.CopyObjectRequest; +import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.services.s3.presigner.model.PresignedPutObjectRequest; @@ -21,9 +24,14 @@ public class S3PresignedUrlService { private final S3Presigner s3Presigner; + private final S3Client s3Client; + @Value("${cloud.aws.s3.bucket}") private String bucket; + @Value("${cloud.aws.region.static}") + private String region; + public List generateUrlList(DomainType domainType, List fileNames) { return IntStream.range(0, fileNames.size()) @@ -61,8 +69,32 @@ private String generateKey(DomainType domainType, String fileName, int index) { String typePath = domainType.name().toLowerCase(); String prefix = (index == 0) ? "thumbnail_" : ""; - return String.format("originals/%s/%s%s", typePath, prefix, filename); + return String.format("temp/%s/%s%s", typePath, prefix, filename); } + public void copyObject(String sourceKey, String destinationKey) { + CopyObjectRequest copyRequest = CopyObjectRequest.builder() + .sourceBucket(bucket) + .sourceKey(sourceKey) + .destinationBucket(bucket) + .destinationKey(destinationKey) + .build(); + + s3Client.copyObject(copyRequest); + } + + public void deleteObject(String key) { + DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder() + .bucket(bucket) + .key(key) + .build(); + + s3Client.deleteObject(deleteRequest); + } + + public String getUrl(String key) { + return String.format("https://%s.s3.%s.amazonaws.com/%s", + bucket, region, key); + } } From d47555d568e1547649e3c2a3dba6f0d4f94bec06 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Tue, 18 Nov 2025 02:13:20 +0900 Subject: [PATCH 2/8] =?UTF-8?q?feat:=20S3=20=ED=81=B4=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EC=96=B8=ED=8A=B8=EC=97=90=20copy,=20delete=20=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=20=EB=B6=80=EC=97=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/leets/leenk/global/config/AwsS3Config.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/leets/leenk/global/config/AwsS3Config.java b/src/main/java/leets/leenk/global/config/AwsS3Config.java index 13d09ff8..c5b239ad 100644 --- a/src/main/java/leets/leenk/global/config/AwsS3Config.java +++ b/src/main/java/leets/leenk/global/config/AwsS3Config.java @@ -7,6 +7,7 @@ import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.presigner.S3Presigner; @Configuration @@ -31,4 +32,14 @@ public S3Presigner s3Presigner() { .credentialsProvider(StaticCredentialsProvider.create(credentials)) .build(); } + + @Bean + public S3Client s3Client() { + AwsBasicCredentials credentials = AwsBasicCredentials.create(accessKey, accessSecret); + + return S3Client.builder() + .region(Region.of(region)) + .credentialsProvider(StaticCredentialsProvider.create(credentials)) + .build(); + } } From c8bb66d6ad413590f4d65360a990e5806e72be49 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Tue, 18 Nov 2025 02:14:37 +0900 Subject: [PATCH 3/8] =?UTF-8?q?feat:=20feed=20=EC=97=85=EB=A1=9C=EB=93=9C?= =?UTF-8?q?=20=EC=8B=9C=20=EB=AF=B8=EB=94=94=EC=96=B4=EB=A5=BC=20=EC=9E=84?= =?UTF-8?q?=EC=8B=9C=20=EA=B2=BD=EB=A1=9C=EC=97=90=EC=84=9C=20=EC=9B=90?= =?UTF-8?q?=EB=B3=B8=20=EA=B2=BD=EB=A1=9C=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= =?UTF-8?q?=ED=95=98=EA=B3=A0=20DB=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feed/application/usecase/FeedUsecase.java | 22 +++++++++++++++---- .../domain/media/domain/entity/Media.java | 1 - .../domain/service/MediaUpdateService.java | 4 ++++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/main/java/leets/leenk/domain/feed/application/usecase/FeedUsecase.java b/src/main/java/leets/leenk/domain/feed/application/usecase/FeedUsecase.java index 764db225..e4d51e1f 100644 --- a/src/main/java/leets/leenk/domain/feed/application/usecase/FeedUsecase.java +++ b/src/main/java/leets/leenk/domain/feed/application/usecase/FeedUsecase.java @@ -16,11 +16,10 @@ import leets.leenk.domain.feed.domain.entity.Reaction; import leets.leenk.domain.feed.domain.service.*; import leets.leenk.domain.feed.domain.service.dto.FeedNavigationResult; +import leets.leenk.domain.media.application.dto.request.FeedMediaRequest; import leets.leenk.domain.media.application.mapper.MediaMapper; import leets.leenk.domain.media.domain.entity.Media; -import leets.leenk.domain.media.domain.service.MediaDeleteService; -import leets.leenk.domain.media.domain.service.MediaGetService; -import leets.leenk.domain.media.domain.service.MediaSaveService; +import leets.leenk.domain.media.domain.service.*; import leets.leenk.domain.notification.application.usecase.FeedNotificationUsecase; import leets.leenk.domain.user.domain.entity.User; import leets.leenk.domain.user.domain.entity.UserBlock; @@ -58,6 +57,8 @@ public class FeedUsecase { private final MediaGetService mediaGetService; private final MediaSaveService mediaSaveService; private final MediaDeleteService mediaDeleteService; + private final MediaUpdateService mediaUpdateService; + private final MediaS3Service mediaS3Service; private final LinkedUserGetService linkedUserGetService; private final LinkedUserSaveService linkedUserSaveService; @@ -181,6 +182,11 @@ public void uploadFeed(long userId, FeedUploadRequest request) { .toList(); mediaSaveService.saveAll(medias); + medias.forEach(media -> { + String newMediaUrl = mediaS3Service.moveToOriginals(media.getMediaUrl()); + mediaUpdateService.updateMediaUrl(media, newMediaUrl); + }); + List linkedUsers = getLinkedUsers(author, request.userIds(), feed); linkedUserSaveService.saveAll(linkedUsers); @@ -247,7 +253,15 @@ public void updateFeed(long userId, long feedId, FeedUpdateRequest request) { if (request.media() != null) { mediaDeleteService.deleteAllByFeed(feed); List newMedias = request.media().stream() - .map(mediaRequest -> mediaMapper.toMedia(feed, mediaRequest)) + .map(mediaRequest -> { + String originalsUrl = mediaS3Service.moveToOriginals(mediaRequest.mediaUrl()); + FeedMediaRequest updatedRequest = new FeedMediaRequest( + mediaRequest.position(), + originalsUrl, + mediaRequest.mediaType() + ); + return mediaMapper.toMedia(feed, updatedRequest); + }) .toList(); mediaSaveService.saveAll(newMedias); } diff --git a/src/main/java/leets/leenk/domain/media/domain/entity/Media.java b/src/main/java/leets/leenk/domain/media/domain/entity/Media.java index 85e7b4a4..dc5c2979 100644 --- a/src/main/java/leets/leenk/domain/media/domain/entity/Media.java +++ b/src/main/java/leets/leenk/domain/media/domain/entity/Media.java @@ -72,5 +72,4 @@ public void updateMediaUrl(String mediaUrl) { public void updateThumbnailUrl(String thumbnailUrl) { this.thumbnailUrl = thumbnailUrl; } - } diff --git a/src/main/java/leets/leenk/domain/media/domain/service/MediaUpdateService.java b/src/main/java/leets/leenk/domain/media/domain/service/MediaUpdateService.java index b8ede38f..0699c811 100644 --- a/src/main/java/leets/leenk/domain/media/domain/service/MediaUpdateService.java +++ b/src/main/java/leets/leenk/domain/media/domain/service/MediaUpdateService.java @@ -11,4 +11,8 @@ public class MediaUpdateService { public void update(Media media, String thumbnailUrl){ media.updateThumbnailUrl(thumbnailUrl); } + + public void updateMediaUrl(Media media, String mediaUrl){ + media.updateMediaUrl(mediaUrl); + } } From c0e43aad664df85a98fcabcc643b1df843ce5de2 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Tue, 18 Nov 2025 02:19:25 +0900 Subject: [PATCH 4/8] =?UTF-8?q?feat:=20feed=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EC=8B=9C=20=EB=AF=B8=EB=94=94=EC=96=B4=EB=A5=BC=20=EC=9E=84?= =?UTF-8?q?=EC=8B=9C=20=EA=B2=BD=EB=A1=9C=EC=97=90=EC=84=9C=20=EC=9B=90?= =?UTF-8?q?=EB=B3=B8=20=EA=B2=BD=EB=A1=9C=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= =?UTF-8?q?=ED=95=98=EA=B3=A0=20DB=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feed/application/usecase/FeedUsecase.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main/java/leets/leenk/domain/feed/application/usecase/FeedUsecase.java b/src/main/java/leets/leenk/domain/feed/application/usecase/FeedUsecase.java index e4d51e1f..4068ab28 100644 --- a/src/main/java/leets/leenk/domain/feed/application/usecase/FeedUsecase.java +++ b/src/main/java/leets/leenk/domain/feed/application/usecase/FeedUsecase.java @@ -253,17 +253,14 @@ public void updateFeed(long userId, long feedId, FeedUpdateRequest request) { if (request.media() != null) { mediaDeleteService.deleteAllByFeed(feed); List newMedias = request.media().stream() - .map(mediaRequest -> { - String originalsUrl = mediaS3Service.moveToOriginals(mediaRequest.mediaUrl()); - FeedMediaRequest updatedRequest = new FeedMediaRequest( - mediaRequest.position(), - originalsUrl, - mediaRequest.mediaType() - ); - return mediaMapper.toMedia(feed, updatedRequest); - }) + .map(mediaRequest -> mediaMapper.toMedia(feed, mediaRequest)) .toList(); mediaSaveService.saveAll(newMedias); + + newMedias.forEach(media -> { + String originalsUrl = mediaS3Service.moveToOriginals(media.getMediaUrl()); + mediaUpdateService.updateMediaUrl(media, originalsUrl); + }); } if (request.userIds() != null) { From 7568a3bf8cbf04b35b1f1d8eb5384c11cc6d438c Mon Sep 17 00:00:00 2001 From: soo0711 Date: Tue, 18 Nov 2025 02:28:55 +0900 Subject: [PATCH 5/8] =?UTF-8?q?feat:=20leenk=20=EC=97=85=EB=A1=9C=EB=93=9C?= =?UTF-8?q?,=20=EC=88=98=EC=A0=95=EC=8B=9C=20=EB=AF=B8=EB=94=94=EC=96=B4?= =?UTF-8?q?=EB=A5=BC=20=EC=9E=84=EC=8B=9C=20=EA=B2=BD=EB=A1=9C=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=9B=90=EB=B3=B8=EA=B2=BD=EB=A1=9C=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20=ED=9B=84=20=EA=B2=BD=EB=A1=9C=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../leenk/application/usecase/LeenkUsecase.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/leets/leenk/domain/leenk/application/usecase/LeenkUsecase.java b/src/main/java/leets/leenk/domain/leenk/application/usecase/LeenkUsecase.java index 89b1489b..4dc7667c 100644 --- a/src/main/java/leets/leenk/domain/leenk/application/usecase/LeenkUsecase.java +++ b/src/main/java/leets/leenk/domain/leenk/application/usecase/LeenkUsecase.java @@ -39,9 +39,7 @@ import leets.leenk.domain.leenk.domain.service.LocationSaveService; import leets.leenk.domain.media.application.mapper.MediaMapper; import leets.leenk.domain.media.domain.entity.Media; -import leets.leenk.domain.media.domain.service.MediaDeleteService; -import leets.leenk.domain.media.domain.service.MediaGetService; -import leets.leenk.domain.media.domain.service.MediaSaveService; +import leets.leenk.domain.media.domain.service.*; import leets.leenk.domain.notification.application.usecase.LeenkNotificationUsecase; import leets.leenk.domain.user.domain.entity.User; import leets.leenk.domain.user.domain.service.NotionDatabaseService; @@ -75,6 +73,8 @@ public class LeenkUsecase { private final MediaSaveService mediaSaveService; private final MediaGetService mediaGetService; private final MediaDeleteService mediaDeleteService; + private final MediaUpdateService mediaUpdateService; + private final MediaS3Service mediaS3Service; private final UserGetService userGetService; private final SlackWebhookService slackWebhookService; @@ -105,6 +105,9 @@ public LeenkCreateResponse uploadLeenk(Long userId, LeenkUploadRequest request) .ifPresent(url -> { Media media = mediaMapper.toMedia(leenk, url); mediaSaveService.save(media); + + String originalsUrl = mediaS3Service.moveToOriginals(media.getMediaUrl()); + mediaUpdateService.updateMediaUrl(media, originalsUrl); }); leenkNotificationUsecase.saveNewLeenkNotification(leenk); @@ -137,10 +140,14 @@ public void updateLeenk(Long userId, Long leenkId, LeenkUpdateRequest request) { } } else { if (media != null) { - media.updateMediaUrl(newUrl); + String originalsUrl = mediaS3Service.moveToOriginals(newUrl); + media.updateMediaUrl(originalsUrl); } else { Media newMedia = mediaMapper.toMedia(leenk, newUrl); mediaSaveService.save(newMedia); + + String originalsUrl = mediaS3Service.moveToOriginals(newMedia.getMediaUrl()); + newMedia.updateMediaUrl(originalsUrl); } } } From 067abc5027662d2f029f627a25c0b1391dc576d9 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Tue, 18 Nov 2025 02:33:30 +0900 Subject: [PATCH 6/8] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=95=84=20=EC=97=85=EB=A1=9C=EB=93=9C=20?= =?UTF-8?q?=EC=8B=9C=20S3=20originals=EB=A1=9C=20=EC=9D=B4=EB=8F=99=20?= =?UTF-8?q?=ED=9B=84=20URL=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/domain/service/user/UserUpdateService.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/leets/leenk/domain/user/domain/service/user/UserUpdateService.java b/src/main/java/leets/leenk/domain/user/domain/service/user/UserUpdateService.java index 1f2f3afc..01c48e4d 100644 --- a/src/main/java/leets/leenk/domain/user/domain/service/user/UserUpdateService.java +++ b/src/main/java/leets/leenk/domain/user/domain/service/user/UserUpdateService.java @@ -1,15 +1,20 @@ package leets.leenk.domain.user.domain.service.user; +import leets.leenk.domain.media.domain.service.MediaS3Service; import leets.leenk.domain.user.application.dto.request.AgreementRequest; import leets.leenk.domain.user.application.dto.request.RegisterRequest; import leets.leenk.domain.user.domain.entity.User; +import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.time.LocalDate; @Service +@RequiredArgsConstructor public class UserUpdateService { + private final MediaS3Service mediaS3Service; + public void updateAgreement(User user, AgreementRequest request) { user.updateAgreement(request.termsService(), request.privacyPolicy()); } @@ -22,7 +27,8 @@ public void completeProfile(User user, RegisterRequest request) { } if (request.profileImage() != null) { - user.updateProfileImage(request.profileImage()); + String originalsUrl = mediaS3Service.moveToOriginals(request.profileImage()); + user.updateProfileImage(originalsUrl); } if(request.birthday() != null) { From 9087559c11c5508b78e65faec3ce289313e9651c Mon Sep 17 00:00:00 2001 From: soo0711 Date: Tue, 18 Nov 2025 02:35:33 +0900 Subject: [PATCH 7/8] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=95=84=20=EC=88=98=EC=A0=95=20=EC=8B=9C=20?= =?UTF-8?q?S3=20originals=EB=A1=9C=20=EC=9D=B4=EB=8F=99=20=ED=9B=84=20URL?= =?UTF-8?q?=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../leenk/domain/user/application/usecase/UserUsecase.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/leets/leenk/domain/user/application/usecase/UserUsecase.java b/src/main/java/leets/leenk/domain/user/application/usecase/UserUsecase.java index 024e48a7..81a8a19b 100644 --- a/src/main/java/leets/leenk/domain/user/application/usecase/UserUsecase.java +++ b/src/main/java/leets/leenk/domain/user/application/usecase/UserUsecase.java @@ -1,5 +1,6 @@ package leets.leenk.domain.user.application.usecase; +import leets.leenk.domain.media.domain.service.MediaS3Service; import leets.leenk.domain.user.application.dto.request.*; import leets.leenk.domain.user.application.dto.response.UserInfoResponse; import leets.leenk.domain.user.application.exception.SelfBlockNotAllowedException; @@ -37,6 +38,8 @@ public class UserUsecase { private final UserBlockMapper userBlockMapper; private final UserBlockService userBlockService; + private final MediaS3Service mediaS3Service; + @Transactional public void initialAgreement(long userId, AgreementRequest request) { User user = userGetService.findById(userId); @@ -69,7 +72,8 @@ public void updateKakaoTalkId(long userId, KakaoTalkIdRequest request) { public void updateProfileImage(long userId, ProfileImageRequest request) { User user = userGetService.findById(userId); - userUpdateService.updateProfileImage(user, request.profileImage()); + String originalsUrl = mediaS3Service.moveToOriginals(request.profileImage()); + userUpdateService.updateProfileImage(user, originalsUrl); } @Transactional From f819ea5b6ec9fa7334ebc6b5426143be14821fd1 Mon Sep 17 00:00:00 2001 From: soo0711 Date: Tue, 18 Nov 2025 15:54:08 +0900 Subject: [PATCH 8/8] =?UTF-8?q?feat:=20S3=20copy=20=EC=8B=A4=ED=8C=A8=20?= =?UTF-8?q?=EC=8B=9C=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/exception/ErrorCode.java | 3 ++- .../exception/S3CopyException.java | 9 ++++++++ .../domain/service/S3PresignedUrlService.java | 23 ++++++++++++------- 3 files changed, 26 insertions(+), 9 deletions(-) create mode 100644 src/main/java/leets/leenk/domain/media/application/exception/S3CopyException.java diff --git a/src/main/java/leets/leenk/domain/media/application/exception/ErrorCode.java b/src/main/java/leets/leenk/domain/media/application/exception/ErrorCode.java index 44c8e0a5..23a4840f 100644 --- a/src/main/java/leets/leenk/domain/media/application/exception/ErrorCode.java +++ b/src/main/java/leets/leenk/domain/media/application/exception/ErrorCode.java @@ -10,7 +10,8 @@ public enum ErrorCode implements ErrorCodeInterface { MEDIA_NOT_FOUND(2500, HttpStatus.NOT_FOUND, "존재하지 않는 미디어입니다."), - MEDIA_UPDATE_FAILED(2501, HttpStatus.INTERNAL_SERVER_ERROR, "미디어 업데이트에 실패했습니다."); + MEDIA_UPDATE_FAILED(2501, HttpStatus.INTERNAL_SERVER_ERROR, "미디어 업데이트에 실패했습니다."), + S3_COPY_FAILED(2502, HttpStatus.INTERNAL_SERVER_ERROR, "파일 복사에 실패했습니다."); private final int code; private final HttpStatus status; diff --git a/src/main/java/leets/leenk/domain/media/application/exception/S3CopyException.java b/src/main/java/leets/leenk/domain/media/application/exception/S3CopyException.java new file mode 100644 index 00000000..c9bb0e3f --- /dev/null +++ b/src/main/java/leets/leenk/domain/media/application/exception/S3CopyException.java @@ -0,0 +1,9 @@ +package leets.leenk.domain.media.application.exception; + +import leets.leenk.global.common.exception.BaseException; + +public class S3CopyException extends BaseException { + public S3CopyException() { + super(ErrorCode.S3_COPY_FAILED); + } +} diff --git a/src/main/java/leets/leenk/domain/media/domain/service/S3PresignedUrlService.java b/src/main/java/leets/leenk/domain/media/domain/service/S3PresignedUrlService.java index 6526a467..c52e69eb 100644 --- a/src/main/java/leets/leenk/domain/media/domain/service/S3PresignedUrlService.java +++ b/src/main/java/leets/leenk/domain/media/domain/service/S3PresignedUrlService.java @@ -1,10 +1,12 @@ package leets.leenk.domain.media.domain.service; import leets.leenk.domain.media.application.dto.response.MediaUrlResponse; +import leets.leenk.domain.media.application.exception.S3CopyException; import leets.leenk.domain.media.domain.entity.enums.DomainType; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import software.amazon.awssdk.core.exception.SdkException; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.CopyObjectRequest; import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; @@ -73,14 +75,19 @@ private String generateKey(DomainType domainType, String fileName, int index) { } public void copyObject(String sourceKey, String destinationKey) { - CopyObjectRequest copyRequest = CopyObjectRequest.builder() - .sourceBucket(bucket) - .sourceKey(sourceKey) - .destinationBucket(bucket) - .destinationKey(destinationKey) - .build(); - - s3Client.copyObject(copyRequest); + try { + CopyObjectRequest copyRequest = CopyObjectRequest.builder() + .sourceBucket(bucket) + .sourceKey(sourceKey) + .destinationBucket(bucket) + .destinationKey(destinationKey) + .build(); + + s3Client.copyObject(copyRequest); + + } catch (SdkException e) { + throw new S3CopyException(); + } } public void deleteObject(String key) {