S3에 이미지 저장

이전 글에서 S3 버킷을 만들어두었다.

이번 글에서는 S3에 이미지를 저장하는 방법을 정리해보려 한다.

최근 알게 된 Presigned URL 방식으로 프론트에서 이미지를 저장하는 방식도 있지만

이번 글에서는 프론트에서 MultipartFile 형태로 이미지를 받아서 저장하는 방식으로 해보았다.

Presigned URL 방식은 추후 따로 글 쓸듯.


사용 기술

  • Spring Boot 3.2.4 / gradle-kotlin
  • Java 17
  • Aws SDK

1. Aws SDK 관련 설정

Aws SDK 의존성 추가

// build.gradle.kts
implementation(platform("software.amazon.awssdk:bom:2.25.35"))
implementation("software.amazon.awssdk:s3")

 

Aws SDK를 사용하는 방법은 두가지가 있다.

  • BOM을 이용한 개별 의존성 추가 방법
  • SDK 전체 추가

본인은 어차피 S3만 쓸것 같기 때문에 S3만 추가하였다.

application.yml 설정

액세스 키, 시크릿 키를 확인하는 방법은 이 글을 확인하자.

이전 글의 마지막에서 만든 액세스 포인트를 활용한다.

aws:
  access-key: # AWS 액세스 키
  secret-key: # AWS 시크릿 키
  s3-access-point: # S3 액세스 포인트

AwsConfig 설정

이미지 업로드에 사용할 S3Client를 빈 등록해준다.

@RequiredArgsConstructor
@ConfigurationProperties(prefix = "aws")
public class AwsConfig {

    private final String accessKey;
    private final String secretKey;
    private final String s3AccessPoint;

    public String getS3AccessPoint() {
        return s3AccessPoint;
    }

    @Bean
    public S3Client s3Client() {
        return S3Client.builder()
            .credentialsProvider(getAwsBasicCredentials())
            .region(Region.AP_NORTHEAST_2)
            .build();
    }

    private StaticCredentialsProvider getAwsBasicCredentials() {
        return StaticCredentialsProvider.create(
            AwsBasicCredentials.create(accessKey, secretKey)
        );
    }
}

2. S3Client를 이용하여 이미지 업로드

ImageController

@RequestParam이나 @RequestPart 애노테이션을 이용해서 MultipartFile을 받는다.

@ModelAttribute로 객체로 받아도 무관하다.

@RestController
@RequiredArgsConstructor
public class ImageController {

    private final ImageService imageService;

    @PostMapping("/upload")
    public String uploadFile(@RequestPart MultipartFile file) throws IOException {
        imageService.upload(file);
        return "이미지 저장 성공";
    }
}

ImageService

컨트롤러에서 받은 MultipartFile을 서비스 레이어에서 처리한다.

S3Client.putObject() 메서드가 받는 인자는 PutObjectRequest, RequestBody 두 개이다.아래처럼 MultipartFile의 inputStream으로 RequestBody를 만들어주면 되고key에는 S3에 저장할 파일 이름을 넣어주면 된다.PutObject라는 이름처럼 같은 이름의 파일이라면 덮어 씌우므로 여러 사람이 이미지를 올린다면 UUID 형태로 저장하는게 좋다.

@Service
@RequiredArgsConstructor
public class ImageService {

    private final S3Client s3Client;
    private final AwsConfig awsConfig;

    public void upload(MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
        RequestBody requestBody = RequestBody.fromInputStream(file.getInputStream(), file.getSize());

        s3Client.putObject(builder -> builder
                .bucket(awsConfig.getS3AccessPoint())
                .key(fileName)  // S3에 저장할 파일명
            , requestBody);
    }
}

3. 결과 확인

PostMan 으로 이미지를 저장해보자.

MultipartFile 형태로 데이터를 받으므로 form-data로 요청을 보내야한다.

S3 버켓을 확인하면 이미지도 제대로 저장됨을 알 수 있다.

+ Recent posts