TIL ... day 31 6주차 - day 3. AWS S3 이미지 파일 저장 … 22.06.14

BYEONGMIN CHOI·2022년 6월 13일
0

TIL(Today I Learned)

목록 보기
19/24

글의 시작을 오늘한 실수로 시작하려고 합니다.

코드의 디버그를 활용하여 오류나는 곳을 찾아볼 수있다. 그러나... 오늘 디버그로 찾지 못한 이슈가 발생했다... 로깅으로 에러부분을 확인하였지만 계속해서 null point가 발생하여 환경설정을 확인하고 설치된 버전을 확인하며 에러를 찾고 있었습니다. 그렇게 찾다가 관련된 코드를 구글링하며 코드를 비교하면서 발견한 에러는... () 중복으로 인한 에러였습니다.
이번 경험을 통해 디버그시 에러가 발생한 부분의 코드를 더 뜯어보고 확인하는 습관을 만들어야 겠다고 생각했습니다.

AWS S3

미니 프로젝트에서 이미지 파일을 업로드하여 저장하는 기능을 구현하게 되었습니다.
처음 계획은 로컬 디렉토리에 업로드된 파일을 저장하고 저장된 위치를 DB에 저장하는 방식으로 진행하였으나,
AWS S3 storage 를 발견하여 AWS S3를 사용하기로 하였습니다.

AWS S3 페이지 설정


  • principal : * 를 입력
  • Actions : GetObject, PutObject, DeletObject 선택
  • ARN : 버킷 생성후 생긴 ARN 복사 + /*

  • 정책 내용 복사
  • 변경사항 저장

IAM 사용자 권한 추가

  • 먼저 IAM 사용자를 만들고 사용자에게 S3 접근 권한을 부여
  • 사용자에게 S3FullAccess 권한을 부여(S3 파일 업로드를 가능하게 해준다)
  • 위의 access key, secrete key 는 현재 화면에서 밖에 볼 수 없습니다. 즉, .csv파일을 받아 보관이 필요하다.

Spring Boot 환경 설정

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

application.yml 작성

spring:
  # multipartFile 용량 늘려주는 설정
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 10MB
      
cloud:
  aws:
    # s3 bucket 이름 배포시 변경 필요
    s3:
      bucket: 버킷 이름
    # user access-key, secret-key 배포시 작성 필요
    credentials:
      access-key: access-key
      secret-key: secret-key
    # s3 region
    region:
      static: ap-northeast-2 (설정한 지역)
      auto: false
    stack:
      auto: false      

AWSS3Config

@Configuration
public class AwsS3Config {

    @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
    @Primary
    public BasicAWSCredentials awsCredentialsProvider(){
        return new BasicAWSCredentials(accessKey, secretKey);
    }

  
    @Bean
    public AmazonS3 amazonS3() {
        return AmazonS3ClientBuilder.standard()
                .withRegion(region)
                .withCredentials(
                        new AWSStaticCredentialsProvider(awsCredentialsProvider())
                )
                .build();
    }

    //aws S3 접속
    @Bean
    public AmazonS3Client amazonS3Client() {
        BasicAWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);
        return (AmazonS3Client) AmazonS3ClientBuilder.standard()
                .withRegion(region)
                .withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
                .build();
    }
}
  • AmazonS3Client 객체를 만들어 IoC 컨테이너에 @Bean 사용하여 등록

S3Uploader

public class S3Uploader {

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

    private final AmazonS3Client amazonS3Client;


    @Value("${file.path}") // application.yml 에 설정된 외부경로, final 사용하면 안됨
    private String uploadFolder;

    public String S3Uploader(MultipartFile file) {
        // TODO: 2022/06/13
        // aws s3 적용
        String imgFileName = createFileName(file);

        // TODO: 2022/06/13
        // aws s3 적용
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentLength(file.getSize());
        objectMetadata.setContentType(file.getContentType());
        try {
            amazonS3Client.putObject(
                    new PutObjectRequest(bucket, imgFileName, file.getInputStream(), objectMetadata)
                    .withCannedAcl(CannedAccessControlList.PublicRead));  // S3 업로드
//            log.info("content-type : {}, getInputStream : {}", imgFile.getFile().getContentType(), imgFile.getFile().getInputStream());

        } catch (IOException e) {
            throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "File upload is failed.");
        }
        // 버킷에서 파일에 해당하는 url을 가져
        return amazonS3Client.getUrl(bucket, imgFileName).toString();
    }


    private String createFileName(MultipartFile file) {
        // 파일 이름이 1.jpg 라면 originFilename 은 1.jpg이다.
        // 동일한 파일명이 업로드 된다면 덮어씌워지기 때문에 UUID_파일명으로 생성한다.
        //        // 파일명 생성이 어떻게 되는지 확인하기 위한 log
//        log.info("imageFileName = {}", imageFileName);
        return "images/" + UUID.randomUUID() + "_" + file.getOriginalFilename();
    }
}
  • createFileName 메소드를 사용하여 파일이 저장될 경로와 파일 이름을 생성하였습니다.

  • ObjectMetadata 객체를 생성하여 AWS S3에 전달할 데이터를 저장하여 amazonS3Client.putObject 를 이용하여 AWS 에 전달하였습니다.

profile
스스로 성장하는 개발자가 되겠습니다.

0개의 댓글