cloud:
  aws:
    credentials:
      accessKey: {{ AWS IAM AccessKey }}
      secretKey: {{ AWS IAM SecretKey }}
    s3:
      bucket: {{ bucket 이름 }}
      dir: profile
    region:
      static: ap-northeast-2 # 해당 지역 작성
    stack:
      auto: false
interface
public interface S3Upload {
    String upload(InputStream inputStream, String originFileName, String fileSize);
}
implement
@RequiredArgsConstructor
@Service
public class S3UploadImpl implements S3Upload{
    @Value("${cloud.aws.s3.bucket}")
    private String bucket;
    @Value("${cloud.aws.s3.dir}")
    private String dir;
    private final AmazonS3Client s3Client;
    @Override
    public String upload(InputStream inputStream, String originFileName, String fileSize) {
        // image 체크       
        if (!originFileName.substring(originFileName.length()-4).equals(".jpg") &&
                !originFileName.substring(originFileName.length()-4).equals(".png")){
            throw new BusinessLogicException(ExceptionCode.NOT_IMAGE_EXTENSION);
        }
        // 저장할 파일 이름 설정
        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss-SSS");
        // "/"를 이용해 파일 하위 폴더 설정
        String s3FileName = dir + "/" +LocalDateTime.now().format(format)+ "-" + originFileName;
        ObjectMetadata objMeta = new ObjectMetadata();
        objMeta.setContentLength(Long.parseLong(fileSize));
        s3Client.putObject(bucket, s3FileName, inputStream, objMeta);
        return s3Client.getUrl(bucket, s3FileName).toString();
    }
}
사용 예시
  @PatchMapping("/profile-image/{member-id}")
  @Secured("ROLE_USER")
  public ResponseEntity patchImage(@PathVariable("member-id") @Positive long memberId,
                                   Authentication authentication,
                                   @RequestParam("images") MultipartFile multipartFile,
                                   @RequestParam String fileSize) throws IOException {
      securityService.checkMemberEqual(authentication, memberId);
      String url = s3Upload.upload(multipartFile.getInputStream(),
              multipartFile.getOriginalFilename(), fileSize);
      Member member = new Member();
      member.setMemberId(memberId);
      member.setImage(url);
      Member updateMember = memberService.updateMember(member);
      MemberDto.Response response = mapper.memberToMemberResponseDto(updateMember);
      return new ResponseEntity<>(
              new SingleResponseDto(response), HttpStatus.OK
      );
  }
