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 버킷에 객체가 추가된 것을 확인할 수 있다!

 

복사했습니다!