
사용자가 이미지 업로드를 하면 서버에서 S3 로 사진을 저장해주면된다.(Service layer)
예를들어 , 사용자가 게시글에 사진을 첨부하면, 그 사진들은 S3 에 저장이 될것이다.
그리고 RDS 에 게시글, 이미지URL 이 연관관계를 통해서 저장이 될것이다.
SpringBoot 에서 S3 와 연결을 위해 의존성을 추가하자
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
의존성을 추가했으면
S3Config 에 수동으로 빈등록을 해야한다. 여기서 중요한 점이 외부에서 S3 를 접근하기 위해서는 액세스 키를 발급 받아서 사용해야한다.
액세스 키 발급 과정 : https://jscode.notion.site/2-S3-IAM-fa151c4afcad4d00b0dc6f6518d83c0c
우리는 발급받은 키를 저장해놓고 SpringBoot 내부에서 사용하자.
package com.project.modac.global.config;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Slf4j
@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() {
//accessKey, secretKey 를 인자로
BasicAWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);
log.info("S3Config 등록 성공");
return (AmazonS3Client) AmazonS3ClientBuilder
.standard()
.withRegion(region)
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.build();
}
}
발급받은 엑세스 키는 application.yml 에 두고 , @Value 를 통해서 주입을 받으면 된다.
AmazonS3Client 는 S3 에 접근하기 위한 객체라고 생각하자.
package com.project.modac.controller;
import com.project.modac.service.ImageService;
import com.project.modac.service.RegisterService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.Map;
@RestController
@RequiredArgsConstructor
public class ImageController {
private final ImageService imageService;
@PostMapping(value = "/image/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public String imageUpload(@RequestParam("request") MultipartFile request
) throws Exception {
String s3UploadUrl = imageService.imageUpload(request);
return s3UploadUrl;
}
}
컨트롤러에서 받은 MultipartFile 을 서비스단에 넘기자.
package com.project.modac.service;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.project.modac.global.config.S3Config;
import jakarta.servlet.annotation.WebServlet;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
@Service
@RequiredArgsConstructor
public class ImageService {
private final AmazonS3Client s3Client;
@Value("${file.dir}")
private String dir;
@Value("${cloud.aws.s3.bucket}")
private String bucketName;
@Transactional
public String imageUpload(MultipartFile file) throws IOException {
String originalFilename = file.getOriginalFilename();
//확장자 가져오기
String ext = originalFilename.substring(originalFilename.indexOf("."));
//이미지 파일이름 유일성을 위해서
String uuidFileName = UUID.randomUUID() + ext;
// 서버local, 저장url
String localPath = dir + uuidFileName;
File localFile = new File(localPath);
// transferTo(localFile) 은 파일을 내 로컬(서버로컬) 해당 경로에 넣어준다.
file.transferTo(localFile);
//S3 의 파일은 오브젝트라고 한다. 그래서 putObject
s3Client.putObject(
new PutObjectRequest(
bucketName, uuidFileName, localFile
)
);
//S3에 이미지 올림
//S3에 이미지가 저장된경로
String S3url = s3Client.getUrl(bucketName,uuidFileName).toString();
//로컬에 저장한거 삭제
localFile.delete();
return S3url;
}
}
여기서 putObject 는 S3에 저장하는 메서드인다.
여기서 new PutObjectRequest("버킷이름", "버킷에 저장할 파일명", "실제파일") 을 넣어주면 S3에 이미지가 올라간다.

이미지를 다운받을때 S3 를 사용하기 전에는 local 에 요청을 보내면 local 에서 이미지를 직접 client 에게 넘겨주었다. 하지만 S3 를 사용하면 서버에서는 RDS 를 통해서 S3 에 저장한 이미지 URL 을 client 에 넘기고 직접 S3 를 통해서 이미지를 다운받는다.