가수면

[Spring Boot] S3 연결하기 본문

Java

[Spring Boot] S3 연결하기

니비앙 2024. 3. 29. 23:31

S3 버킷 생성

1. 버킷 생성

버킷 생성 페이지에서 차례대로 작성한다.

퍼블릭 액세스 파트에 대해선 '모든 퍼블릭 액세스 차단'의 체크를 풀어준다. (필요에 따라 세부 설정)

이후 생성

2. 버킷 정책 설정

정책 설정을 하지 않으면 저장된 파일의 url 조회 시 조회가 안 된다.

버킷으로 들어가 '권한' → '버킷 정책'의 '편집' 버튼 클릭

버킷 ARN을 복사 후 정책 생성기를 클릭한다.

Step1

'S3 Bucket Policy' 선택

 

Step2

Principal에 * 입력

Actions에 Get Object, Put Object 체크

ARN에 복사한 것 붙여넣기

생성 후 나온 것 복사해서 정책에 붙여넣기

만약 ' Action does not apply to any resource(s) in statement '같은 오류가 발생한다면 Resource 끝에 /* 를 붙여준다.

IAM 설정

1. 사용자 생성하기

이름 입력 후 다음

직접 정책 연결 선택, 'AmazonS3FullAccess' 선택 후 다음

사용자 클릭해 들어가서 '액세스 키' 생성

태그를 입력 후 엑세스 키 생성

생성 완료된 화면에서 밖에 비밀 액세스 키를 확인할 수 없기 때문에 .csv 파일로 다운받아두는 것을 권장한다.

Spring Boot 설정

기본 매커니즘은 DBMS에 이미지를 저장하게 되면 용량이 줄어듦에 따라 성능 이슈 등이 발생하기 때문에 이미지는 S3에 저장한 뒤(저장된 이미지는 URL로 조회할 수 있음) URL만 DBMS에 저장하는 방식이다.

그렇게 얻은 URL을 응답값으로 프론트로 넘겨주게 되면 프론트는 해당 URL을 통해 img 태그 등으로 출력할 수 있게 된다.

 

1. 의존성 설치

	implementation 'com.amazonaws:aws-java-sdk-s3:1.12.688'
	implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

 

2. application.yml에 설정 추가

cloud:
  aws:
    s3:
      bucket: pet-project-bucket-jihyeon
    stack.auto: false
    region.static: ap-northeast-2
    credentials:
      accessKey: ${S3_ACCESS_KEY_ID}
      secretKey: ${S3_SECRET_ACCESS_KEY}

cloud.aws.stack.auto=false

EC2에서 Spring Cloud 프로젝트를 실행시키면 기본으로 CloudFormation 구성을 시작하기 때문에 설정한 CloudFormation이 없으면 프로젝트 실행이 되지 않는다. 해당 기능을 사용하지 않도록 false로 설정.

 

3. S3 Bean 설정

package com.springboot.petProject.configuration;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@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 AmazonS3Client amazonS3Client() {
        BasicAWSCredentials awsCredentials= new BasicAWSCredentials(accessKey, secretKey); // 자격 증명 객체를 생성
        return (AmazonS3Client) AmazonS3ClientBuilder.standard()
                .withRegion(region)
                .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) // 자격 증명을 사용하여 AWS 서비스에 접근할 수 있게 해줌
                .build();
    }
}

S3에 업로드

서비스 로직 생성

이 경우엔 base64 인코딩된 문자열의 배열로 받는다.

package com.springboot.petProject.service;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.springboot.petProject.exception.CustomExceptionHandler;
import com.springboot.petProject.exception.ErrorCode;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.UUID;

@Service
@RequiredArgsConstructor
public class S3Service {
    private final AmazonS3 amazonS3;
    @Value("${cloud.aws.s3.bucket}")
    private String bucketName;

    public List<String> uploadBase64Images(List<String> base64Images) {
        List<String> imageUrls = new ArrayList<>();

        for (String base64Image : base64Images) {
            // 파일명 생성
            String fileName = UUID.randomUUID().toString() + ".png"; // 확장자는 상황에 맞게 조정

            try {
                // 바이너리 데이터 배열(byte[])로 디코딩
                byte[] imageBytes = Base64.getDecoder().decode(base64Image);
                // S3 업로드 시 데이터를 읽는 데 사용되는 스트림
                ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);

                // 업로드할 이미지에 대한 메타데이터를 설정
                ObjectMetadata metadata = new ObjectMetadata();
                metadata.setContentLength(imageBytes.length);
                metadata.setContentType("image/png");

                // S3에 업로드
                amazonS3.putObject(bucketName, fileName, inputStream, metadata);

                // 업로드된 파일의 URL 추가
                String fileUrl = amazonS3.getUrl(bucketName, fileName).toString();
                imageUrls.add(fileUrl);
            } catch (Exception e) {
                throw new CustomExceptionHandler(ErrorCode.S3_ERROR);
            }
        }

        return imageUrls;
    }
}

'Java' 카테고리의 다른 글

파일 다운로드 기능 API 구현  (0) 2024.08.13
백엔드 성능 측정  (0) 2024.03.28
[Spring Boot] 에러 핸들링  (1) 2024.02.20
Junit5  (0) 2024.02.17
스프링 부트 서버에 https 설정  (0) 2024.01.23
Comments