AWS

[AWS] AWS S3 연동 해보자

lnacles 2023. 4. 4. 22:26

AWS 계정 만들기

1. 루트 사용자를 만든다.

2. IAM 사용자를 하나 만들어서 사용한다.

 

루트 사용자로 사용할 경우 팀원들과 아이디 패스워드를 공유하게 되는데 무슨 일이 일어날지 모른다. 계정이 노출되면 과금이 결제될 수도 있다.

IAM사용자는 여러 명의 사용자들 등록할 수 있다. 팀원들의 IAM을 등록해서 같이 사용할 수 있고, 권한도 설정해줄 수 있다. 이번 프로젝트에서 권한에 대해 깊게 생각해보지  못해서 기회가 되면 권한에 관련한 글도 써보겠다.

 

1. S3를 사용하게 되면 버킷이라는 키워드를 만날수 있다. 버킷은 데이터 컨테이너로써 최대 100개까지 생성가능하며 100개 이상 만들 경우 서비스 할당량에서 설정할 수 있다.

2. 버킷 아래에 객체가 만들어지는데 데이를 담기 위한 상위 경로라고 생각하면 된다.

 

여기까지가 AWS S3연동을 위한 설정이다.

application.yml에 추가해줘야 할 것

cloud:
    aws:
      credentials:
        access-key: ********************
        secret-key: ****************************************
      s3:
        bucket: *************
      region:
        static: ap-northeast-2
      stack:
        auto: false

access-key와 secret-key는 IAM 계정으로 로그인한 뒤 > 액세스 관리 > 사용자에서 받을 수 있다.

주의❗ cloud-aws-credentials 설정이 깃에 공유될 경우 AWS에서 해당 키의 접근을 막는다고 한다. Access deny가 뜨길래 액세스와 시크릿 키를 다시 받아서 설정해 주니 잘 동작되었다.

 

build.gradle 설정이다.

implementation 'io.awspring.cloud:spring-cloud-starter-aws:2.3.1'

AWS S3 설정이다.

@Configuration
public class AmazonS3Config {
    @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 amazonS3Client(){
        BasicAWSCredentials basicAWSCredentials = new BasicAWSCredentials(accessKey,secretKey);
        return AmazonS3ClientBuilder.standard()
                .withRegion(region)
                .withCredentials(new AWSStaticCredentialsProvider(basicAWSCredentials)).build();
    }
}

upload와 delete를 구현 분리 해놨다. 파일 이름을 정해줘야 한다. 겹치지 않게 하면 되는데

1. 랜덤 UUID

2. 밀리 세컨즈

이 두 가지 말고도  파일 이름이 안 겹치게 하면 된다.

@RequiredArgsConstructor
@Component
public class AwsS3 {
    private final AmazonS3Client amazonS3Client;
    @Value("${cloud.aws.s3.bucket}")
    private String bucket;
    private final String AWS_URL = "https://mydanimbucket.s3.ap-northeast-2.amazonaws.com";
    public String upload(MultipartFile file,String directoryName)throws Exception{

        String originalName = file.getOriginalFilename();
        String uploadPath = directoryName;
        String uploadFileName = UUID.randomUUID().toString()+"."+originalName.substring(originalName.indexOf(".")+1);
        String uploadUrl = "";
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentLength(file.getSize());
        objectMetadata.setContentType(file.getContentType());
        String keyname =uploadPath+"/"+uploadFileName;
        amazonS3Client.putObject(new PutObjectRequest(bucket,keyname,file.getInputStream(),objectMetadata).withCannedAcl(CannedAccessControlList.PublicRead));
        uploadUrl = amazonS3Client.getUrl(bucket,keyname).toString();
        return uploadUrl;
    }
    public void delete(String url){
        url = url.substring(AWS_URL.length());
        boolean isObjectExist = amazonS3Client.doesObjectExist(bucket, url);
        if(isObjectExist)amazonS3Client.deleteObject(new DeleteObjectRequest(bucket, url));
    }
}

이렇게 객체 주입을 해주고

 

private final AwsS3 awsS3;

 

이렇게 사용하면 리턴으로 해당 uri를 받을 수 있다.

아래 줄을 풀어보면 Danim은 버킷 아래에 있는 객체이다. 그 아래 Voic폴더에 저장을 한다.

awsS3.upload(voiceFile, "Danim/Voice")

amazonS3 Client에서 제공해 주는 여러 가지 메서드들이 있으니 찾아보고  AwsS3에 구현해서 사용하면 된다.

 

사실 S3연동은 크게 복잡하지 않은 작업이었다. 다만 경로를 설정하는 일이다 보니 serviceImpl에서 코드가 길어졌고, 여러 곳에서 AwsS3가 사용되어서 분리해 구현하고자 했다.