본문 바로가기
spring boot

(2) spring boot 게시글 이미지 기능 구현 (AWS S3, AWS cloudfront)

by junjunjun 2023. 3. 8.
반응형

본 글은 정확하지 않을 수 있습니다. 참고용으로만 봐주시면 감사하겠습니다.

 

(1) spring boot 게시글 이미지 구현 흐름 (AWS S3)

(2) spring boot 게시글 이미지 기능 구현 (AWS S3, AWS cloudfront)

 

s3를 이용하여 스프링 파일 업로드를 구현하는 것은 생각보다 간단하다. s3에 이미지 저장을 요청하고, url을 받아오기만 하면 된다. 하지만 aws 서비스를 설정하는 과정이 생각보다 까다로웠다.

 

목차

  1. AWS S3 생성
  2. AWS IAM 생성
  3. spring boot와 s3 연동
  4. AWS cloudFront 생성
  5. cloudFront와 S3 연동
  6. spring 코드 수정

 

1. AWS S3 생성

aws s3에 들어가서 버킷을 하나 생성한다.

위 두 개의 설정을 제외한 설정은 모두 디폴트값으로 내버려 두었다.

 

2. AWS IAM 생성

spring boot에서 aws s3에 접근하기 위한 설정이다. 우리가 생성한 S3에 접근할 수 있는 정책을 가진 IAM을 만들어 준다. 그리고 접근 수단인 액세스 키를 발급받는다. 추후 spring boot의 yml파일에 지정해 주면 된다.

 

https://kim-jong-hyun.tistory.com/85

 

[AWS] - IAM 사용자 및 사용자에 대한 Role 추가하기

IAM 이란 Identity and Access Management (IAM) 의 약자이며 AWS 리소스에 대한 액세스를 안전하게 제어할 수 있는 웹 서비스이며 IAM을 사용하여 리소스를 사용하도록 인증 및 권한부여가 된 대상(사용자)을

kim-jong-hyun.tistory.com

이 분의 설정을 그대로 따라 했다. 하지만 액세스 키 발급 방식은 조금 바뀌었다. 

IAM을 생성해 준 뒤에 "보안 자격 증명"에 들어가 주면 "액세스 키 만들기" 버튼이 있다. 버튼을 클릭하여 키를 발급받으면 된다. 참고로 키는 해당 페이지를 벗어나면 사라지기 때문에 따로 기록해두어야 한다.

 

3. spring boot와 s3 연동

 

의존성 주입

//  aws s3
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

yml 파일

spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 10MB

cloud:
  aws:
    credentials:
      access-key: test  # IAM 계정의 accessKey
      secret-key: test  # IAM 계정의 secretKey
    region:
      static: ap-northeast-2  # 버킷의 리전
    s3:
      bucket: masil-bucket  #  버킷 이름
    stack:
      auto: false

config

@Configuration
public class AwsS3Config {
    @Value("${cloud.aws.credentials.access-key}") // application.yml 에 명시한 내용
    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 awsCreds = new BasicAWSCredentials(accessKey, secretKey);

        return (AmazonS3Client) AmazonS3ClientBuilder.standard()
                .withRegion(region)
                .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
                .build();
    }
}

service 

@Service
@RequiredArgsConstructor
public class AwsS3Service {

    @Value("${cloud.aws.s3.bucket}")
    private String bucket;

    private final AmazonS3 amazonS3;

    /**
     * AWS S3에 이미지 파일 업로드
     * @param multipartFile : 파일
     * @param dirName : s3 버킷에서 만들어준 폴더 이름
     * @return : Url
     */
    public Url upload(MultipartFile multipartFile, String dirName){

        String fileName = createFileName(multipartFile.getOriginalFilename(), dirName);

        // s3에 이미지 저장
        try(InputStream inputStream = multipartFile.getInputStream()){
            amazonS3.putObject(new PutObjectRequest(bucket, fileName, inputStream));
        } catch (IOException e){
            // 예외처리
            throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "파일 업로드에 실패했습니다.");
        }

        // s3에 저장된 파일 url 얻어옴.
        Url url = amazonS3.getUrl(bucket, fileName)

        return url;
    }

    // 파일 이름이 같으면 저장이 안 된다. 따라서 파일이름 앞에 UUID를 붙인다.
    private String createFileName(String fileName, String dirName){
        return dirName + "/" + UUID.randomUUID() + fileName;
    }

}

 

이미지를 s3에 저장하고 이미지 url을 가져올 수 있게 되었다.

하지만 가져온 이미지 url로 요청을 보내면 access denied 페이지가 보일 것이다. 해결 방법은 다양하지만 일단 내버려 둔다.

cloudfront를 연동해 주는 과정에서 해결된다.

 

4. AWS cloudFront 생성

이미지를 조회할 때마다 s3에 url 요청을 보내게 될 텐데.. 당장 게시글 목록 조회를 생각해 보면 게시글의 썸네일 이미지가 있고 무한 스크롤로 구현되어 있다. 드래그를 내릴 때마다 게시글 목록을 조회하는데 드래그 몇 번으로 순식간에 썸네일 이미지 url 요청양이 엄청 많아진다.

이러한 과금에 대한 해결방안을 찾던 중 cdn을 알게 되었다. 그리고 aws에서는 cloudfront 이름으로 cdn서비스를 제공한다.

 

간단하게 cdn이 클라이언트와 s3서버 사이에서 캐시역할을 한다고 생각하면 된다.

cdn에 대한 설명은 아래 블로그에 자세히 나와있다.

https://velog.io/@ygreenb/AWS-S3-CloudFront를-이용한-CDN-구축하기

 

AWS S3, CloudFront를 이용한 CDN 구축하기

상품 리스트를 불러올 때, S3 버킷에 있는 큰 이미지를 그대로 가져오느라 로딩시간이 엄청 오래걸리는 문제점이 발생했습니다. 프록시 서버를 둠으로써 이미지 로딩 속도를 단축하고 싶었고,

velog.io

 

 

aws cloudfront에 들어가서 배포를 생성해 준다.

원본 도메인에 아까 생성해 준 s3를 지정한다. 

S3 버킷 액세스를 원복 액세스 제어 설정(권장)으로 설정하게 되면 cloudfront의 url를 통해서만 s3이미지에 접근할 수 있게 된다.

그 외에 다른 옵션들은 일단 모두 디폴트 값으로 설정하였다.

5. cloudFront와 S3 연동

이제 S3에서 cloudFront의 요청을 받을 수 있도록 설정만 해주면 된다.

cloudfront > 배포 > 만든 객체 > 원본 편집으로 가서 정책 복사 버튼을 눌러준다.

cloudfront > 배포 > 만든 객체 > 원본 편집

 

다시 S3 > 만든 버킷 > 권한 > 버킷 정책 편집으로 들어가서 정책 복사한 거를 붙여 넣기 해준다.

+ 복붙 한 거 이외에 다른 정책이 있을 경우 충돌이 발생하여 동작이 안 할 수도 있다.

버킷 정책은 아래 블로그에 자세하게 나와있다. 간단하게 접근 제어 설정이라 생각하면 된다.

https://inpa.tistory.com/entry/AWS-📚-S3-버킷-생성-사용법-실전-구축 

 

[AWS] 📚 S3 개념 정리 & 버킷 생성 · 권한(Policy / ACL) 설정하기

S3 (Simple Storage Service) 개념 AWS S3는 업계 최고의 확장성과 데이터 가용성 및 보안과 성능을 제공하는 온라인 오브젝트(객체) 스토리지 서비스이다. (참고로 S 앞글자가 3개라서 S3 이라고 한다.) 쉽

inpa.tistory.com

 

이제  "https://s3-url/폴더이름/이미지이름.jpg" 가 아닌

"https://cloudfront-url/폴더이름/이미지이름.jpg" 으로 요청을 보내면 이미지가 잘 나온다.

 

url 요청을 처음 보낼 때는 200을 반환하는 반면 두 번째에는 304를 반환하는 것을 볼 수 있다.

첫 번째 요청
두 번째 요청

클라이언트 리디렉션 응답 코드 304 Not Modified는 요청된 리소스를 재전송할 필요가 없음을 나타낸다.

 

5. spring 코드 수정

기존에는 S3 url을 반환해 줬다면 이제는 host를 cloudfront로 바꿔서 반환해줘야 한다.

@Service
@RequiredArgsConstructor
public class AwsS3Service {

	.. 생략 
    public String upload(MultipartFile multipartFile, String dirName){

        .. 생략 
        
        // s3에 저장된 파일 url 얻어옴.
        String path = amazonS3.getUrl(bucket, fileName).getPath()

        return "https://cloudfront-url" + path;
    }
}

클라이언트에도 바뀐 url를 반환해줘야 한다.

 

 

 

참고자료

https://kim-jong-hyun.tistory.com/85

 

[AWS] - IAM 사용자 및 사용자에 대한 Role 추가하기

IAM 이란 Identity and Access Management (IAM) 의 약자이며 AWS 리소스에 대한 액세스를 안전하게 제어할 수 있는 웹 서비스이며 IAM을 사용하여 리소스를 사용하도록 인증 및 권한부여가 된 대상(사용자)을

kim-jong-hyun.tistory.com

 

https://velog.io/@ygreenb/AWS-S3-CloudFront를-이용한-CDN-구축하기

 

AWS S3, CloudFront를 이용한 CDN 구축하기

상품 리스트를 불러올 때, S3 버킷에 있는 큰 이미지를 그대로 가져오느라 로딩시간이 엄청 오래걸리는 문제점이 발생했습니다. 프록시 서버를 둠으로써 이미지 로딩 속도를 단축하고 싶었고,

velog.io

 

https://inpa.tistory.com/entry/AWS-📚-S3-버킷-생성-사용법-실전-구축

 

[AWS] 📚 S3 개념 정리 & 버킷 생성 · 권한(Policy / ACL) 설정하기

S3 (Simple Storage Service) 개념 AWS S3는 업계 최고의 확장성과 데이터 가용성 및 보안과 성능을 제공하는 온라인 오브젝트(객체) 스토리지 서비스이다. (참고로 S 앞글자가 3개라서 S3 이라고 한다.) 쉽

inpa.tistory.com

https://kim-jong-hyun.tistory.com/78

 

[Spring] - Spring Boot + AWS S3를 이용하여 이미지 조회/등록/삭제 및 accessKey, secretKey, butket 값을 외부에

이번장에는 Spring Boot와 AWS SDK를 이용하여 AWS S3에 이미지/파일 정적리소스들을 등록, 조회, 삭제하는 내용에 대해 정리해보고자한다. 그전에 AWS S3에 버킷생성 / IAM 사용자를 생성후 S3 액세스 권

kim-jong-hyun.tistory.com

 

반응형

'spring boot' 카테고리의 다른 글

(1) spring boot 게시글 이미지 구현 흐름 (AWS S3)  (0) 2023.03.07

댓글