
프로젝트 진행하면서, 졸업 작품의 사진 및 개인 회원 프로필 사진 등을 업로드 및 관리해줘야 합니다. 이를 단순하게 로컬에서 관리하기에는 물리적인 측면에서 한계가 있습니다. 또한, 보안적으로도 취약점을 갖습니다. 따라서, AWS에서 제공하는 Simple Storage Service(S3)를 사용하여 이미지들을 처리하기 위해 도입하게 되었으며, 이 과정을 기록한 포스팅입니다.
과정을 간단하게 알아보면 다음과 같습니다.
S3를 이용하기 위해서는 객체를 저장할 Bucket을 생성해줘야 합니다.

우선, Bucket 이름을 입력해줍니다.

그 다음으로 Bucket 퍼블릿 엑세스 차단 설정을 풀어줍니다.

외부에서 해당 Bucket에 접근을 제어하기 위한 설정입니다.

AWS console > IAM > 엑세스 관리 > 사용자 > 사용자 추가 클릭

S3에 접근하기 위해서는 IAM 사용자에서 S3 접근 권한을 부여하고, 엑세스 키와 시크릿 키를 사용하여 접근 가능합니다.
사용자 이름을 입력한 뒤 다음을 클릭해줍니다.
그룹에 사용자 추가를 연결한 뒤, 그룹을 생성해줍니다. 보안 정책은 AmazonS3FullAccess 를 선택해줍니다.

검토 및 생성 화면에서 사용자 생성을 클릭하면 사용자가 생성됩니다.

외부에서 접속이 가능하도록 하기 위해 사용자의 액세스 키를 생성해줘야 합니다.
AWS console > IAM > 액세스 관리자 > 사용자 > 생성한 사용자명 클릭 > 보안 자격 증명 > 액세스 키 만들기 클릭

액세스 키 모범 사례 및 대안에서 "AWS 외부에서 실행되는 애플리케이션"을 선택한 뒤 다음으로 넘어갑니다.

태그를 입력하고 액세스 키 만들기 버튼을 클릭합니다.
액세스 키 생성 완료 화면에서 생성된 공개키와 비밀키를 확인할 수 있습니다. 생성 완료 화면이 아니면 비밀 액세스 키 확인이 불가능하기 때문에 .csv 파일로 다운로드 받아 놓는것이 좋습니다.

📜 참고 포스팅
우선, spring-cloud-aws-starter-s3 관련 의존성을 추가해줍니다. awspring은 spring-cloud-aws 라이브러리에 대한 의존성을 의미합니다.
implementation platform("io.awspring.cloud:spring-cloud-aws-dependencies:3.0.0")
implementation 'io.awspring.cloud:spring-cloud-aws-starter-s3'
'implementation platform("io.awspring.cloud:spring-cloud-aws-dependencies:3.0.0")' 는 BOM 입니다.
BOM(Bill Of Materials) 파일은 프로젝트에서 사용하는 라이브러리들의 버전을 명시적으로 정의하고, 다른 프로젝트 또는 모듈에서 재사용이 가능하도록 해주기 위해 사용됩니다.
Spring Cloud AWS와 같은 큰 라이브러리는 내부적으로 여러 모듈들이 정의되어 있습니다. 이 경우, 모든 하위 라이브러리의 호환되는 버전을 일일히 찾아서 명시해줄 수도 있지만, BOM을 사용하면 이러한 복잡성을 줄이고 특정 버전의 라이브러리가 의존하는 모든 하위 모듈의 호환되는 버전을 자동으로 가져와줍니다.
Spring Cloud Aws를 사용하여 AWS에 접속하기 위해서는 생성한 액세스키를 가지고 인증 설정을 추가해줘야 합니다. 관련 방식은 여러가지로 다양하지만, 필자는 application.yml 파일에 정의하여 사용했습니다.
#S3
spring:
servlet:
multipart:
max-file-size: 20MB # 최대 파일 사이즈
max-request-size: 20MB #최대 요청 사이즈
cloud:
aws:
credentials:
access-key: # IAM access-key
secret-key: # IAM secret-key
region:
static: # ap-northeast-2 # bucket region
s3:
bucket: # bucket 명
@Component
@RequiredArgsConstructor
@Slf4j
public class S3Util {
private final S3Template s3Template;
@Value("${spring.cloud.aws.s3.bucket}")
private String bucketName;
public String upload(MultipartFile file){
try {
String fileName = file.getOriginalFilename();
String extension = StringUtils.getFilenameExtension(fileName);
String key = UUID.randomUUID() + "." + extension;
S3Resource s3Resource = s3Template.upload(bucketName, key, file.getInputStream(),
ObjectMetadata.builder().contentType(file.getContentType()).build());
return s3Resource.getURL().toString();
}catch(IOException e){
throw new UploadException();
}
}
버켓명을 yaml 파일에서 데이터를 가져옵니다.
버켓 내 각 객체들마다 고유한 키를 부여해줍니다.(UUID)
업로드할 파일의 contentType을 설정해줍니다.
@PostMapping("/image")
public ApiResponse<String> image(@RequestPart(value = "file") MultipartFile file){
String url = testService.uploadImageTest(file);
return ApiResponse.ok(url);
}
S3 연동을 테스트하기 위해 엔드포인트를 정의합니다.


정상적으로 S3에 업로드 되는것을 확인했습니다.
이후, 업로드된 이미지 URL에 접속하여 확인 및 SpringBoot 프로젝트 빌드 시 발생한 오류에 대해서는 아래의 포스팅에 작성하였으니 참고 바랍니다.
⚠️ Trouble-Shooting
오늘은 S3 연동, 이미지 업로드 테스트 과정에 대해서 알아봤습니다. 처음 연동해봤기 때문에 모든 설정에 대해서 정확하게 이해하고 구현하지는 못했지만, 프로젝트를 진행하면서 여러 오류들과 상황들을 마주하며 학습해봐야겠습니다.