멋사 Backend Plus 40일차 🦁

μ‹ μž¬μ›Β·2023λ…„ 12μ›” 26일

μ˜€λŠ˜μ€ S3 버킷에 λ“±λ‘ν•˜κΈ° μœ„ν•œ 파일 μ—…λ‘œλ“œ λ‘œμ§μ— λŒ€ν•œ μ œλ„€λ¦­ μ μš©μ„ ν•˜μ˜€κ³  ν”„λ‘ νŠΈ μ—”λ“œ 쑰금, ν…ŒμŠ€νŠΈ μ½”λ“œ μž‘μ„±μ„ ν•˜μ˜€λ‹€

μ˜€μ „

문제 발견

AWS S3 버킷에 이미지λ₯Ό λ“±λ‘ν•˜λŠ” λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 μžˆμ—ˆλ‹€.

	@Transactional
    public void uploadImage(Product requestType, MultipartFile file) throws IOException {
        String imageLocation = bucketUrl;
        String imageName = file.getOriginalFilename();
        String requestTypeSimpleName = "product" + "/";

        String imagePath = imageLocation + requestTypeSimpleName + imageName;

        String fileName = requestTypeSimpleName + file.getOriginalFilename();

        Image productImage = Product.
        		createProductImage(fileName, imagePath);

        imageRepository.save(productImage);
        createS3Bucket(fileName, file);
    }

μ΄λŸ¬ν•œ λ‘œμ§μ€ 였직 Product (μƒν’ˆ) 객체에 λŒ€ν•΄μ„œλ§Œ νŒŒμΌμ„ μ—…λ‘œλ“œ ν• μˆ˜ μžˆλŠ” κΈ°λŠ₯μ΄μ˜€μŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ ν”„λ‘œμ νŠΈλ₯Ό μ§„ν–‰ν•˜λ©΄μ„œ, 파일 μ—…λ‘œλ“œλ₯Ό κ³΅ν†΅μ μœΌλ‘œ μ‚¬μš©ν•΄μ•Όν•  뢀뢄이 κ²Œμ‹œκΈ€μ„ μž‘μ„±ν• λ•Œ, μƒν’ˆμ„ λ“±λ‘ν• λ•Œ μ˜€μŠ΅λ‹ˆλ‹€.

➑ μ΄λŸ¬ν•œ λ¬Έμ œμ μ„ ν•΄κ²°ν•˜κΈ°μœ„ν•΄ Generic (μ œλ„€λ¦­) νƒ€μž…μ„ μ‚¬μš©ν•  ν•„μš”μ„±μ„ 느끼게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

μ˜€ν›„

@Service
@RequiredArgsConstructor
public class ImageServiceImpl implements ImageService {
    private final AmazonS3Client amazonS3Client;
    private final ImageRepository imageRepository;

    @Value("${cloud.aws.s3.bucket}")
    private String bucket;

    @Value("${cloud.aws.s3.url}")
    private String bucketUrl;

    @Transactional
    public <T> Optional<Image> uploadImage(T requestType, MultipartFile file) throws IOException {
        String imageLocation = bucketUrl;
        String imageName = file.getOriginalFilename();
        String requestTypeSimpleName = requestType.getClass().getSimpleName() + "/";

        String imagePath = imageLocation + requestTypeSimpleName + imageName;

        String fileName = requestTypeSimpleName + file.getOriginalFilename();

        Optional<Image> image = Optional.empty();

        if (requestType instanceof Product) {
            Image productImage = Product.createProductImage(fileName, imagePath);
            image = Optional.of(productImage);
        }

        if (requestType instanceof Post) {
            Image postImage = Post.createProductImage(fileName, imagePath);
            image = Optional.of(postImage);
        }

        if (image.isPresent()) {
            imageRepository.save(image.get());
            createS3Bucket(fileName, file);
        }

        return image;
    }

    private void createS3Bucket(String fileName, MultipartFile image) throws IOException {
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentType(image.getContentType());
        metadata.setContentLength(image.getSize());
        amazonS3Client.putObject(bucket, fileName, image.getInputStream(), metadata);
    }
    
}

μ½”λ“œλ₯Ό ν•˜λ‚˜ ν•˜λ‚˜ λœ―μ–΄ λ³΄κ² μŠ΅λ‹ˆλ‹€.

	private final AmazonS3Client amazonS3Client;
    private final ImageRepository imageRepository;

    @Value("${cloud.aws.s3.bucket}")
    private String bucket;

    @Value("${cloud.aws.s3.url}")
    private String bucketUrl;

AmazonS3Client : AWS S3에 μ ‘κ·Όν•˜κΈ° μœ„ν•΄ μ œκ³΅λ˜λŠ” 객체
Value : yml μ„€μ • νŒŒμΌμ— μž‘μ„±ν•œ AWS S3 버킷에 λŒ€ν•œ 정보

<T> Optional<Image> uploadImage(T requestType, MultipartFile file)

ν•΄λ‹Ή 파일 μ—…λ‘œλ“œμ—μ„œ 핡심적인 둜직이라고 ν•  수 μžˆλ‹€.

T : λ‹€μ–‘ν•œ νƒ€μž…μ„ λ§€κ°œλ³€μˆ˜λ‘œ 받을 수 μžˆλ‹€λŠ” μ˜λ―Έμž…λ‹ˆλ‹€,
즉 Product 객체와, Post 객체λ₯Ό λ‘˜ λ‹€ λ°›μ„μˆ˜ μžˆμ–΄, μ½”λ“œμ— μž¬μ‚¬μš©μ„±μ„ 높일 수 μžˆμŠ΅λ‹ˆλ‹€.

마무리

controller μ—μ„œ Post μš”μ²­μœΌλ‘œ API ν…ŒμŠ€νŠΈ ν•˜κ²Œ 되면 μ‹€μ œλ‘œ S3에 νŒ¨ν‚€μ§€κ°€ λ§Œλ“€μ–΄μ§€κ³  νŒ¨ν‚€μ§€ μ•ˆμ— 파일이 μ €μž₯되게 λ©λ‹ˆλ‹€.


0개의 λŒ“κΈ€