클라이언트에서 넘겨준 이미지가 있을 때, 데이터베이스에서는 해당 이미지의 파일 이름이나 파일의 경로만 저장한다는 것은 언뜻 들은 적이 있었다. 하지만 막상 프로젝트를 시작하니 '그래서 진짜 이미지는 어디에 저장하는 건데?' 하는 생각이 들었고, 이미지 뿐만 아니라 이런 식으로 클라이언트에서 받은 파일을 저장할 때 S3 를 파일을 저장하는 곳으로 이용할 수 있다고 한다. (S3 이름 자체가 Simple Storage Service 이다. 아마존에서도 스토리지 서비스라고 안내하고 있다.)
- IAM 사용자 생성 및 설정
- AWS S3 bucket 생성 및 설정
- Spring boot 설정
- gradle 에 dependencies 수정
- application.yml 수정
- config 자바 파일 생성
위와 같은 순서로 작성하고자 한다.
1. IAM 사용자 생성 및 설정
AWS 에 접속하면 볼 수 있는 첫 화면이다. 바로 저 IAM 사용자를 말하는 것이다.
이 때 IAM은 Identity and Access Management 의 줄임말로, AWS의 리소스에 대한 액세스 권한을 제어할 수 있는 계정이라는 뜻이다. 즉 IAM 계정이란 AWS 의 리소스들(EC2, RDS, S3..)에 대해 어떤 리소스는 사용할 수 있도록, 어떤 리소스는 사용하지 못하도록 권한을 제어받고 있는 계정이라는 의미이다.
AWS IAM 사용설명서에서 볼 수 있는 글이다. 간단하게 요약하자면, AWS 서비스/리소스에 모든 권한이 있는 루트 계정을 사용하는 것을 지양하고, 서비스/리소스마다 권한을 제한할 수 있는 IAM 계정을 여러개 생성하여 안전하게 사용하라는 이야기이다. 때문에 IAM 계정을 우선 생성해주도록 하자. (이미 사용하고 있다면 당연히 생략한다.)
IAM 을 검색한 후 사용자 추가를 누르고, 이름, 자격 증명 유형을 선택해준다.
액세스키를 체크함으로써 아래 설명되어 있듯이 AWS API 등에 접근할 수 있는 access key, secret key 를 받을 수 있다. 두 번째 체크박스도 체크했는데, 해당 증명 유형도 선택해주어야 AWS 콘솔에 로그인하여 페이지를 확인할 수 있으므로, 대부분 AWS 페이지를 볼 필요가 있을테니 두 번째 체크박스도 체크해주자.
그 다음으로 생성할 IAM 계정의 권한을 설정해야 한다. 이 때 권한을 이미 설정 해 둔 사용자 그룹에 지금 사용자를 포함시킬 수도 있고, 위 이미지와 같이 AWS 에서 일반적인 상황들에 대해 제공해주는 정책을 선택해주어도 된다.
이 때 '정책' 이란, 어떠한 '권한' 들의 모음을 말한다. 즉 이러이러한 권한을 가지는 정책을 지금 사용자에게 적용하겠다는 뜻이다. AmazonS3FullAccess 를 선택해준다.
여담으로, FullAccess 를 주는 것이 탐탁치 않아 직접 권한을 제어해보려 했는데, 생각보다 작업에 대한 권한이 굉장히 세세하게 분리되어 있어서 '이 정도면 IAM 사용자로도 작업할 수 있겠지?' 싶을 정도로 권한을 부여해도 상당히 많은 작업에서 '권한필요' 라는 메시지를 마주하곤 했다....그래서 일단 급한 일은 아니니 AmazonS3FullAccess 로 진행했다.
이후에 선택사항 몇 개를 건너뛰고 나면 사용자 추가가 완료된다. 이 때 .csv 파일을 반드시 다운받아두길 권장한다. 현재 생성한 IAM 사용자에 대한 access key, secret key 는 현재 페이지에서 밖에 볼 수 없기 때문이다. (물론 secret key 를 잃어버린다고 방법이 없는 것은 아니다. IAM Management Console 에서 access - secret key 페어 자체를 새로 발급할 수도 있다.)
2. AWS S3 bucket 생성 및 설정
그 다음으로는 버킷을 만들어준다. 리전은 가장 가까운 곳으로 설정해주면 된다.
이 때 퍼블릭 액세스에 대해 설정해야 하는 항목이 있는데, 각 단어의 의미를 간단히 살피자면
- ACL 은 Access Controle List의 줄임말로, 각 버킷과 객체마다 ACL 을 가지며 ACL은 액세스를 허용할 AWS 계정 / 그룹 / 액세스 유형을 정의한다.
- 리소스에 대한 요청을 수신하면, S3는 해당 리소스의 ACL 을 확인하여 리소스 요청자가 필요한 권한을 보유하고 있는지 확인한다.
- '퍼블릭'은 누구나 객체 목록 생성, 객체 쓰기, 읽기 및 쓰기 권한 중 하나 이상에 액세스할 수 있다는 의미이다.
위 네 항목이 각각 무엇을 말하는지 해당 링크를 통해 자세히 살펴볼 수 있다. (참고)
되도록이면 정확히 어떤 의미인지 알고싶어 가이드를 정독해보았으나, 구체적으로 무엇을 말하는지 감이 잡히지 않아 일단 다른 분들에게서도 자주 볼 수 있는 설정으로 체크하였다...
그렇게 버킷을 생성한 후 권한 - 버킷 정책 편집에 들어간다. 세 번째 이미지의 버킷 ARN 을 복사한 후 정책 생성기를 클릭한다.
위의 네모 박스 부분을 이미지와 같이 설정해주고, Actions 에서는 파일 업로드, 다운로드, 삭제를 위해 3가지 Actions 를 추가해주었다. 그 후 Generate Policy 를 누르면 json docs 가 나오는데, 해당 json 을 복사하여 정책 편집 화면에 붙여넣고 변경 사항을 저장해주면 된다.
정책 편집까지 마쳤다면 S3 bucket 설정도 완료되었다.
3. Spring boot 설정
1. gradle 에 dependancies 추가
해당 링크 에서 확인해보니 현재 날짜 기준 최신버전인 2.2.6 release 를 사용하여도 괜찮을 것 같아 해당 버전을 사용하였다. build.gradle 파일에 아래와 같이 dependencies 를 추가해주자
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
2. application.yml 수정
.yml 파일을 통해 처음에 생성한 IAM 계정의 access, secret key 정보, S3 에 대한 정보 등을 입력해주어야 하므로 application-aws.yml 이라는 파일을 따로 생성해주었으며 서브모듈([Git] git submodule을 이용하여 중요한 정보 숨기기)을 통해 관리하기로 하였다.
cloud:
aws:
credentials:
access-key: {your access-key}
secret-key: {your secret-key}
s3:
bucket: 버킷 이름
region:
static: ap-northeast-2 # 리전 정보
stack:
auto: false
- credentials : 생성한 IAM 계정의 access, secret key 를 적으면 된다.
- bucket : 자신이 생성한 버킷 이름을 적으면 된다.
- region : 리전 정보를 적으면 되는데, 서울의 경우 ap-northeast-2 이다.
- stack : 로컬에서 프로젝트를 실행할 때에는 문제가 되지 않지만, EC2 에 배포를 할 때 해당 조건이 없으면 다음과 같은 에러가 발생한다고 한다. EC2 에 Spring Cloud 프로젝트를 실행시키면 기본으로 CloudFormation 구성을 시작하는데, 설정한 CloudFormation이 없으면 프로젝트를 실행할 수 없으므로 사용하지 않겠다는 설정이다.
※ 위 파일은 반드시 .gitignore 처리를 해주어야 합니다!
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
또한 기본적으로 multipart 를 통해 보낼 수 있는 max-file-size 와 max-request-size 는 1MB 인데, 요즘 휴대폰으로 촬영한 사진을 살펴보면 2~5MB까지도 되는 것 같아 넉넉히 수정해주었다.
3. S3 Config 자바 파일 생성
AWS IAM 계정도 만들었고, 이를 이용하여 AWS S3 와 연결하기 위한 파일도 생성해주었으니, 이제 정말 연결하기 위한 설정을 해 줄 차례이다.
적용하고자 하는 프로젝트의 디렉토리이다.
- domain : ERD 에서 Entity 에 해당하는 것들을 단위로 묶어 안쪽에 비즈니스 기능들을 구현
- global : jwt, error handling 등 domain에서 공통적으로 사용하는 기능들
- infra : oath, sms 인증 등 외부 프로그램을 이용하여 프로젝트에 적용하고자 하는 기능들
이렇게 디렉토리 구조를 잡는다고 가정하고, infra/S3Storage 하위에 S3Config.java 라는 파일을 두었다.
S3Config.java
@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;
@Bean
public AmazonS3 amazonS3() {
BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKey, secretKey);
return AmazonS3ClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
.withRegion(region)
.build();
}
}
댓글