DB를 로컬에서 AWS RDS로 전환한 것에 이어, 강의나 코스 커버에 첨부되는 이미지를 로컬이 아니라 AWS S3에서 관리하도록 전환하겠습니다.
1. S3 버킷 생성하기
AWS에서 S3를 검색하면 위와 같은 화면이 나오고, '버킷 만들기' 버튼을 클릭합니다.
버킷 생성 옵션을 입력해주고 생성하면 됩니다.
이름 등을 설정해주고, 기본 옵션에서 크게 변경할 것은 없습니다.
퍼블릭 액세스를 허용하면 개발할 때는 조금 편할 수 있지만, 실제로 모든 퍼블릭 액세스를 열어둘 경우는 없으므로, 이번 프로젝트에서도 이후에 '버킷 정책'을 통해 접근을 제어하는 것으로 하겠습니다.
2. IAM 사용자 생성하기
AWS에서 자격을 증명할 때는 AWS에서 생성한 계정을 직접 이용하기 보다는 IAM을 이용하는 것이 바람직하다고 합니다.
따라서 S3에 접근할 '사용자'를 먼저 생성하겠습니다.
프로필을 클릭하면 '보안 자격 증명' 페이지로 이동할 수 있고, '액세스 관리-사용자' 로 이동하여 '사용자 추가' 버튼을 클릭하여 새로운 사용자를 만듭니다.
생성한 사용자를 선택한 후,
'보안 자격 증명'에서 accessKey와 secretKey를 생성해줍니다. (생성 시 잘 저장해두어야 합니다!)
3. S3 버킷 정책 설정하기
모든 public access를 막아두었으므로, 버킷 정책을 설정하여 앞서 생성한 사용자가 S3 버킷에 접근할 수 있도록 해줍니다.
'버킷 - 권한 - 버킷 정책'을 통해 JSON 형태로 액세스 권한을 설정할 수 있습니다.
위 설정에서 의미는 다음과 같습니다.
- Effect: 'Allow/Deny' -> 명시한 조건에 대해 허용할 것인지, 차단할 것인지
- Principal: 사용자 구분 -> 앞서 생성한 사용자를 명시해줍니다. 가려진 부분만 AWS ID(12자리 숫자)로 채워주면 됩니다.
- Action: 행위 -> s3와 관련된 모든 action으로 명시해두었습니다.
- Resource: 생성해둔 bucket
4. 스프링 설정
이제 스프링에서 권한이 있는 사용자임을 증명하고, S3를 이용하면 됩니다.
(1) build.gradle
AWS 관련 라이브러리들을 사용하기 위해 관련 의존성을 추가해줍니다.
(2) application.yml 설정
인증 정보와 버킷 정보를 설정해줍니다.
accessKey와 secretKey는 앞서 사용자를 생성할 때 발급 받았던 값이고, bucket은 S3 버킷의 이름입니다.(glo'g'learn-image 로 잘못 생성해두고 glolearn-image라고 적었다고 고생했네요😂)
region도 bucket의 regision으로 설정해주면 되고, stack의 경우 아직 정확히 무슨 옵션인지는 모르겠으나 생략하면 오류가 뜨니 stack 옵션도 설정해주면 됩니다.
※ 간단한 프로젝트이더라도, AWS는 accessKey나 secrectKey가 유출되면 요금 문제로까지 이어질 수 있으니, 항상 gitignore 설정을 해줘야합니다!
(3) 이미지 서비스 클래스 생성
JAVA 코드를 통해 이미지에 접근하고 읽어오는 서비스는 다음과 같습니다.
ImageService에 대한 인터페이스를 생성하고 구현하는 것이 더 좋겠지만 우선은 바로 클래스로 구현했습니다.
(S3 무료 읽고, 쓰기 횟수에 제한이 있는 것으로 알고 있어, 로컬에 저장하는 ImageService 구현체와 S3를 이용하는 구현체 2가지로 나눠야 할 듯 합니다.)
@Service
@RequiredArgsConstructor
public class AwsS3Service {
private final AmazonS3Client amazonS3Client;
@Value("${cloud.aws.s3.bucket}")
private String bucket;
@Value("${cloud.aws.credentials.accessKey}")
private String accessKey;
@Value("${cloud.aws.credentials.secretKey}")
private String secretKey;
@Value("${cloud.aws.region.static}")
private String region;
// 이미지 불러오기
public void findImage(String filename, HttpServletResponse response) throws IOException {
InputStream inputStream = amazonS3Client.getObject(bucket, filename + ".PNG").getObjectContent();
IOUtils.copy(inputStream, response.getOutputStream());
inputStream.close();
}
// 이미지 저장하기
// https://stackoverflow.com/questions/50248710/upload-multipart-file-to-aws-without-saving-it-locally
public String saveImage(MultipartFile multipartFile, String directory, String filename) throws IOException, InterruptedException {
ObjectMetadata data = new ObjectMetadata();
data.setContentType(multipartFile.getContentType());
data.setContentLength(multipartFile.getSize());
amazonS3Client.putObject(bucket, directory + "/" + filename + ".PNG", multipartFile.getInputStream(), data);
multipartFile.getInputStream().close();
return directory + "/" + filename;
}
}
bucket이나 accessKey 등을 주입 받으면 되고, 이미지 파일을 읽고 쓰는 방법은 코드를 통해 확인하실 수 있습니다.
이렇게 이미지가 S3 버킷에 저장되도록 변경하였고, 이어지는 글에서는 서버를 EC2 인스턴스에 올리도록 하겠습니다.
'프로젝트 > 글로런' 카테고리의 다른 글
[글로런] 지연로딩 이용하기 (0) | 2023.03.29 |
---|---|
[글로런] 배포 (3) - AWS EC2 배포하기 (0) | 2023.03.23 |
[글로런] 배포(1) - AWS RDS로 전환하기 (0) | 2023.03.22 |
[글로런] 프로젝트 개요 (0) | 2023.03.22 |