개발/Spring & SpringBoot

aws sdk로 s3업로드하기 & steam 업로드

dev-yoon-jerry 2024. 6. 23. 22:20

s3 파일업로드를 개발하며 고생한 경험 기록.

private static AmazonS3 s3Client;

private static AmazonS3 getAmazonS3(){
// 싱글톤 적용
    if(s3Client == null){
    	// 클러스터에 role을 넣어줘서 credentials, region은 자동으로 설정된다.
        // 반대로 로컬에서 수행하려면 클라이언트에 해당정보를 넣어주면 된다.
        s3Client = AmazonS3ClientBuilder.defaultClient();
    }
    return s3Client;
}

private void uploadS3(MultipartFile multipartFile, String key, String bucketName){
    InputStream inputStream = null;
    
    try {
        inputStream = multipartFile.getInputSream();
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentType(multipartFile.getContentType());
        metadata.setContentLength(multipartFile.getSize());
        getAmazonS3().putObject(new PutObjectRequest(bucketName, key, inputStream, metadata));
    } catch (AmazonServiceException ase){
        // 에러처리
    } catch (AmazonClientException ace){
        // 에러처리
    } catch (Exception e){
        // 에러처리
    } finally {
        if(inputStream != null){
            try {
                inputStream.close();
            } catch(IOException e){
                // 에러처리
            }
        }
    }
}

uploadS3(imageFile,"image"+fileName,"bucket1");
uploadS3(imageFile,"image"+fileName,"bucket2");

정리하기에 앞서 완성된 소스는 다음과 같다. (실제소스는 다르지만 기록용으로 간략하게 정리했다)
s3버킷 두군데에 이미지파일을 stream으로 업로드하는 간단한 소스이다.

개발하면서 첫번째로 실수한 점은.  하나의 stream을 두곳에 한번에 올리려고 했다.

        inputStream = multipartFile.getInputSream();
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentType(multipartFile.getContentType());
        metadata.setContentLength(multipartFile.getSize());
        getAmazonS3().putObject(new PutObjectRequest(bucketName1, key, inputStream, metadata));
        getAmazonS3().putObject(new PutObjectRequest(bucketName2, key, inputStream, metadata));

마치 치킨하나를 튀겨서 두곳에 동시에 배달하려는 꼴이다. 하나의 스트림을 이렇게 두곳에 업로드하려고 한 바람에
AmazonClientException이 떠서 반나절을 헤맸다. 생각해보니 하나의 스트림을 왜 이렇게 썼지? 하면서 고쳤다. (코드리뷰 요청드렸으면 더 빨리 찾았을 것 같다.)

두번째로 실수한 점은 버킷의 key를 넣을때 실수를 했다.

버킷/image/~~ 이렇게 버킷에 업로드를 하려고 한다면. key를 image/~~로 넣어야한다.
처음에 /image/~~ 로 넣는바람에.  / /image/~~ 에 업로드가 되었다.
난감한게. 업로드시 에러없이 정상적으로 업로드되어서 s3콘솔에 들어가 직접 확인해 보고 원인을 알게 되었다.

세번째 실수한 점은 s3클라이언트를 여러개 생성했다.
uploadS3 메소드마다 클라이언트를 생성했더니. 여러번 파일을 업로드하자 서버가 oom으로 죽어버렸다.
싱글톤 처리하여 클라이언트를 하나만 생성하게 했다.

소스자체는 어려운게 하나도 없는 소스인데. 역시 막상 개발하려니 쉬운건 없는 것 같다. 다음부턴 같은 상황에서 잘 대처해야지.

 

'개발 > Spring & SpringBoot' 카테고리의 다른 글

Spring 3 RestController 구현  (0) 2022.06.23
카카오 로그인 만들기 3  (0) 2021.05.23
카카오 로그인 만들기 2  (0) 2021.05.21
카카오 로그인 만들기 1  (0) 2021.05.21