![article thumbnail image](https://blog.kakaocdn.net/dn/chyW53/btrLh8FEheT/sUjUQN12nRKZgoYf9uVFd0/img.jpg)
Amazon S3 ?
Simple Storage Service 의 약자
이미지, 파일 등의 정적 리소스를 REST 인터페이스를 통해 저장/삭제/조회할 수 있다.
Object
객체, 저장되는 대상을 의미한다.
실제 파일과 메타 데이터로 구성
Bucket
Object 가 저장되는 곳, 최상위 디렉토리
Region
Object 가 저장되는 물리적 위치
IAM 정책 생성하기
Identity and Access Management 의 약자
AWS 리소스에 접근하도록 권한이 부여 된 대상을 관리하는 서비스
액세스 유형
액세스 키, Programmatic access
사용자가 AWS API, SDK 등의 개발 도구에 대해 접근이 필요한 경우, 각 사용자에 대한 액세스 키가 생성된다.
암호, AWS Management Console access
각 신규 사용자에 대해 AWS Management Console에 직접 로그인을 할 수 있도록 허용하는 비밀번호를 생성한다.
이미지 업로드 시에 스프링 부트에서 Amazon SDK 를 이용한 접근이 필요하기 때문에
액세스 키 방식을 사용해서 IAM 사용자를 생성해보도록 하자.
IAM 사용자 추가
AWS Console 검색창에 'IAM' 검색 후 주요 기능의 '사용자' 클릭
사용자 추가 버튼을 누르면 사용자를 추가할 수 있다.
사용자 이름을 입력하고 액세스키 방식을 선택한다.
기존 정책 직접 연결 -> s3full 검색 -> 체크 후 다음 버튼 클릭
선택사항은 넘어가고 사용자를 만들고 나면 해당 사용자의 액세스 키 ID 와 비밀 액세스키가 나오는데,
화면을 벗어나면 다시 조회할 수 없으니 따로 저장해두자.
이미지 업로드하기
- S3 버킷명, 오브젝트 키 이름 및 파일 (또는 Byte 배열) 필요
- PutObjectRequest 객체를 사용해서 업로드 요청
pom.xml
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.11.313</version>
</dependency>
application.yml
cloud:
aws:
s3:
region: S3 리전 위치
accessKey: 발급 받은 accessKey
secretKey: 발급 받은 secretKey
url: S3 접근 URL
bucketName: 버킷명
AwsConfigure.java
@Component
@ConfigurationProperties(prefix = "cloud.aws.s3")
public class AwsConfigure {
private String accessKey;
private String secretKey;
private String region;
private String url;
private String bucketName;
public String getAccessKey() {
return accessKey;
}
public void setAccessKey(String accessKey) {
this.accessKey = accessKey;
}
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getBucketName() {
return bucketName;
}
public void setBucketName(String bucketName) {
this.bucketName = bucketName;
}
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
.append("accessKey", accessKey)
.append("secretKey", secretKey)
.append("region", region)
.append("url", url)
.append("bucketName", bucketName)
.toString();
}
}
Amazon S3 객체는 설정 파일에 빈으로 등록해준다.
@Bean
public AmazonS3 amazonS3Client(AwsConfigure awsConfigure) {
return AmazonS3ClientBuilder.standard()
.withRegion(Regions.fromName(awsConfigure.getRegion()))
.withCredentials(
new AWSStaticCredentialsProvider(
new BasicAWSCredentials(
awsConfigure.getAccessKey(),
awsConfigure.getSecretKey())
)
)
.build();
}
S3Client.java
Amazon S3 에 request 하는 클래스를 작성한다.
PutObjectRequest 객체를 사용해서 upload 한다.
public final class S3Client {
private final AmazonS3 amazonS3;
private final String url;
private final String bucketName;
public S3Client(AmazonS3 amazonS3, String url, String bucketName) {
this.amazonS3 = amazonS3;
this.url = url;
this.bucketName = bucketName;
}
public String upload(File file) {
PutObjectRequest request = new PutObjectRequest(bucketName, file.getName(), file);
return executePut(request);
}
public String upload(InputStream in, long length, String key, String contentType, Map<String, String> metadata) {
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(length);
objectMetadata.setContentType(contentType);
if (metadata != null && !metadata.isEmpty()) {
objectMetadata.setUserMetadata(metadata);
}
PutObjectRequest request = new PutObjectRequest(bucketName, key, in, objectMetadata);
return executePut(request);
}
private String executePut(PutObjectRequest request) {
amazonS3.putObject(request.withCannedAcl(CannedAccessControlList.PublicRead)); // PublicRead 권한으로 업로드
StringBuilder sb = new StringBuilder(url);
if (!url.endsWith("/"))
sb.append("/");
sb.append(bucketName);
sb.append("/");
sb.append(request.getKey());
return sb.toString();
}
}
S3Client 도 설정파일에 빈으로 등록한다.
@Bean
public S3Client s3Client(AmazonS3 amazonS3, AwsConfigure awsConfigure) {
return new S3Client(amazonS3, awsConfigure.getUrl(), awsConfigure.getBucketName());
}
작성을 완료했다면 S3Client 를 이용해 사진을 업로드해보자.
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.net.URL;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class S3ClientTest {
private final Logger log = LoggerFactory.getLogger(getClass());
private S3Client s3Client;
@BeforeAll
void setUp() {
String region = "리전명";
String accessKey = "발급 받은 accessKey";
String secretKey = "발급 받은 secretKey";
AmazonS3 amazonS3 = AmazonS3ClientBuilder.standard()
.withRegion(Regions.fromName(region))
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey)))
.build();
String url = "S3 URL";
String bucketName = "버킷명";
s3Client = new S3Client(amazonS3, url, bucketName);
}
@Test
void 이미지_업로드() {
URL testFile = getClass().getResource("/test.jpeg");
assertThat(testFile, is(notNullValue()));
File file = new File(testFile.getFile());
String url = s3Client.upload(file);
assertThat(url, is(notNullValue()));
log.info("S3 bucket url: {}", url);
}
}
S3 버킷에 객체가 추가된 것을 확인할 수 있다!
'Spring Boot' 카테고리의 다른 글
[Spring Boot] DTO 는 왜, 언제 사용할까? (2) | 2023.01.03 |
---|---|
[Spring Boot] Maven Multi Module (0) | 2022.12.16 |
[Spring Boot] Mockito 로 테스트 하기 (0) | 2022.08.06 |
Spring Security 인가 처리 - AccessDecisionManager, AccessDecisionVoter (0) | 2022.08.04 |
Spring Security 인증 처리 (2) Filter, AuthenticationManager, AuthenticationProvider, WebSecurityConfigure (0) | 2022.07.26 |