Spring-boot & AWS S3 연동 이미지 업로드 - (2)

2024. 4. 28. 19:35스프링

 

https://kjy154969.tistory.com/48 - Spring-boot & AWS S3 연동 이미지 업로드 - (1)

 

Spring-boot & AWS S3 연동 이미지 업로드 - (1)

S3 란?AWS(아마존 웹 서비스)가 제공하는 클라우드 스토리지 서비스이다. 다양한 유형의 미디어(파일, 데이터 등)를 저장하고 관리하는데 사용되는 웹 기반 스토리지 시스템이다. 저장하는 데이터

kjy154969.tistory.com

 

이전 글에서는 AWS S3 버킷 생성 후 정책 설정까지 완료하였다. 이번에는 스프링 부트와 연동을 해보도록 하자.

build.gradle

 AWS cloud와 연동시켜서 S3를 사용하기 위해 build.gradle 파일에 해당 코드를 입력해준다.

implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

 

application-aws.yml 파일 생성

그리고 resources 디렉터리에 application-aws.yml 파일을 생성해주고

cloud:
  aws:
    s3:
      bucket: 버킷 이름
    stack.auto: false
    region.static: ap-northeast-2
    credentials:
      accessKey: 제공받은 액세스키
      secretKey: 제공받은 시크릿 액세스 키

버킷 이름, 제공받은 액세스키, 시크릿 액세스 키를 발급 받아서 입력 해준다.

spring:
	{다른 설정들}
  profiles:
    include: aws #aws.yml 불러오기

application.yml 파일에 application-aws.yml 파일을 불러오기 위해 해당 코드를 입력해준다.

config/S3Config

메인 java에서 com.example.프로젝트명 패키지 안에 config 패키지를 생성 해준 후 S3 설정을 위한 S3Config.java 파일을 만들어준다.

package com.example.fzana.config;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class S3Config {
    @Value("${cloud.aws.credentials.access-key}") // 액세스 키
    private String accessKey;
    @Value("${cloud.aws.credentials.secret-key}") // 비밀 액세스 키
    private String secretKey;
    @Value("${cloud.aws.region.static}")          // 지역
    private String region;

    // 아마존 s3 클라이언트 연결
    @Bean
    public AmazonS3Client amazonS3Client() {
        BasicAWSCredentials awsCredentials= new BasicAWSCredentials(accessKey, secretKey);
        return (AmazonS3Client) AmazonS3ClientBuilder.standard()
                .withRegion(region)
                .withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
                .build();
    }
}

액세스키와 시크릿 액세스 키, 지역 값을 가져오고 해당 변수 값들을 amazonS3Client 메서드에서 연결을 할 수 있게 한다. 

위 코드를 파일에 입력 해준다.

 

이제 연동은 다 되었고, 각자 기능에 맞게 구현을 해주면 된다.

필자는 프로필 사진 업로드 기능을 구현하였으므로 해당 로직으로 코드를 작성하였다.

 

- Controller

// 사용자 프로필 입력 & 수정
    @PostMapping(value = "/members/{memberId}/profile", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    @Operation(summary = "사용자 프로필 사진 수정", description = "사용자의 프로필 사진을 수정합니다.")
    public ResponseEntity<String> fileUpload(@RequestParam("file") MultipartFile file, @PathVariable Long memberId) {
        try {
            String bucketName = "fzana"; // S3 버킷 이름 설정
            String fileUrl = memberService.uploadFileAndSaveUrl(bucketName, file, memberId);
            return ResponseEntity.status(HttpStatus.CREATED).body("File uploaded successfully: " + fileUrl);
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Upload failed: " + e.getMessage());
        }
    }

 

- Service

 /*
     * 사용자 프로필 사진 등록 로직 (s3)
     */
    public String uploadFileAndSaveUrl(String bucketName, MultipartFile multipartFile, Long memberId) throws IOException {
        Member member = memberRepository.findById(memberId)
                .orElseThrow(() -> new MemberNotFoundException("올바르지 않은 사용자"));

        String fileUrl = uploadFileToS3Bucket(bucketName, multipartFile);

        member.updateProfile(fileUrl);

        memberRepository.save(member);

        return fileUrl;
    }

    // S3에 업로드 하기
    private String uploadFileToS3Bucket(String bucketName, MultipartFile multipartFile) throws IOException {
        File file = convertMultiPartToFile(multipartFile);
        String fileName = System.currentTimeMillis() + "_" + multipartFile.getOriginalFilename();

        s3Client.putObject(new PutObjectRequest(bucketName, fileName, file));
        file.delete(); // 임시 파일 삭제

        return s3Client.getResourceUrl(bucketName, fileName); // s3에 저장된 파일의 Url 받기
    }

    // MultiPart 를 파일로 변환 (임시 파일 생성)
    private File convertMultiPartToFile(MultipartFile multipartFile) throws IOException {
        File convFile = new File(multipartFile.getOriginalFilename());
        FileOutputStream fos = new FileOutputStream(convFile);

        fos.write(multipartFile.getBytes());
        fos.close();

        return convFile;
    }

 

이제 사진이 S3에 업로드가 잘 되는지 알아보자.

S3에 업로드 할 사진

이 사진을 업로드 할 것이다.

S3 업로드 성공!

업로드가 잘 된 것을 볼 수 있다.

'스프링' 카테고리의 다른 글

Spring-boot & AWS S3 연동 이미지 업로드 - (1)  (0) 2024.04.25