Skip to content

Commit

Permalink
refactor: 이미지 처리 방식 변경
Browse files Browse the repository at this point in the history
- S3에는 UUID로 변환된 이미지 파일명을 저장
- DB에는 https://{CDN 경로}/{UUID}.{확장자} 형식으로 저장

CHZZ-111
  • Loading branch information
viaunixue committed Sep 30, 2024
1 parent 4b3f223 commit b40b319
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 25 deletions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
package org.chzz.market.domain.image.service;

import static org.chzz.market.domain.image.error.ImageErrorCode.IMAGE_DELETE_FAILED;
import static org.chzz.market.domain.image.error.ImageErrorCode.IMAGE_URL_ENCODING_FAILED;

import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.s3.AmazonS3;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.chzz.market.domain.image.entity.Image;
Expand Down Expand Up @@ -44,7 +40,7 @@ public List<String> uploadImages(List<MultipartFile> images) {
.map(this::uploadImage)
.toList();

uploadedUrls.forEach(url -> log.info("업로드 된 이미지 : {}", url));
uploadedUrls.forEach(url -> log.info("업로드 된 이미지 : {}", getFullImageUrl(url)));

return uploadedUrls;
}
Expand All @@ -53,8 +49,8 @@ public List<String> uploadImages(List<MultipartFile> images) {
* 단일 이미지 파일 업로드 및 CDN 경로 리스트 반환
*/
private String uploadImage(MultipartFile image) {
String cdnPath = imageUploader.uploadImage(image);
return getFullImageUrl(cdnPath);
String uniqueFileName = createUniqueFileName(image.getOriginalFilename());
return imageUploader.uploadImage(image, uniqueFileName);
}

/**
Expand All @@ -64,7 +60,7 @@ private String uploadImage(MultipartFile image) {
public List<Image> saveProductImageEntities(Product product, List<String> cdnPaths) {
List<Image> images = cdnPaths.stream()
.map(cdnPath -> Image.builder()
.cdnPath(cdnPath)
.cdnPath(cloudfrontDomain + cdnPath)
.product(product)
.build())
.toList();
Expand All @@ -85,10 +81,9 @@ public void deleteUploadImages(List<String> fullImageUrls) {
*/
private void deleteImage(String cdnPath) {
try {
// String encodeKey = cdnPath.substring(cdnPath.lastIndexOf("/") + 1);
String decodedKey = URLDecoder.decode(cdnPath, StandardCharsets.UTF_8.toString());
amazonS3Client.deleteObject(bucket, decodedKey);
} catch (AmazonServiceException | UnsupportedEncodingException e) {
String key = cdnPath.substring(1);
amazonS3Client.deleteObject(bucket, key);
} catch (AmazonServiceException e) {
throw new ImageException(IMAGE_DELETE_FAILED);
}
}
Expand All @@ -97,13 +92,25 @@ private void deleteImage(String cdnPath) {
* CDN 경로로부터 전체 이미지 URL 재구성 이미지 -> 서버에 들어왔는지 확인하는 로그에 사용
*/
public String getFullImageUrl(String cdnPath) {
try {
// URL 인코딩
String encodedPath = URLEncoder.encode(cdnPath, StandardCharsets.UTF_8.toString());
return cloudfrontDomain + encodedPath;
} catch (UnsupportedEncodingException e) {
throw new ImageException(IMAGE_URL_ENCODING_FAILED);
}
// URL 인코딩
return cloudfrontDomain + cdnPath;
}

/**
* 고유한 파일 이름 생성
*/
private String createUniqueFileName(String originalFileName) {
String uuid = UUID.randomUUID().toString();
String extension = getFileExtension(originalFileName);

return uuid + "." + extension;
}

/**
* 파일 확장자 추출
*/
private String getFileExtension(String originalFileName) {
return originalFileName.substring(originalFileName.lastIndexOf(".") + 1);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
테스트 이미지 업로드 인터페이스
*/
public interface ImageUploader {
String uploadImage(MultipartFile image);
String uploadImage(MultipartFile image, String fileName);
}

Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.ObjectMetadata;
import java.io.IOException;
import lombok.RequiredArgsConstructor;
import org.chzz.market.domain.image.error.ImageErrorCode;
import org.chzz.market.domain.image.error.exception.ImageException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

@Service
@RequiredArgsConstructor
public class S3ImageUploader implements ImageUploader {
Expand All @@ -20,8 +19,7 @@ public class S3ImageUploader implements ImageUploader {
private String bucket;

@Override
public String uploadImage(MultipartFile image) {
String fileName = image.getOriginalFilename();
public String uploadImage(MultipartFile image, String fileName) {
try {
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(image.getSize());
Expand Down

0 comments on commit b40b319

Please sign in to comment.