티스토리 뷰

반응형

부제: IntelliJ에서 S3 연동하기, Spring Boot AWS 연동


 이번 포스팅에서는 Spring Boot에서 Spring Cloud AWS를 활용하여 S3를 연동하는 법을 알아보겠다. 절차는 크게 3가지(의존성 설정, Properties 파일 설정, 구현)로 나눌 수 있다.






1. 의존성 설정

 Spring Cloud AWS를 활용하면, 의존성만 추가해도 간편하게 AWS의 모든 기능을 활용할 수 있다는 장점이 있다. 아래 내용을 build.gradle에 추가하자. (버전은 알아서 적절히 넣도록 한다.)



1
2
compile("org.springframework.cloud:spring-cloud-aws-context:${springCloudVersion}")
compile("org.springframework.cloud:spring-cloud-aws-autoconfigure:${springCloudVersion}")
cs




2. application.properties 파일 설정

 위에서 autoconfigure 관련 내용을 의존성에 추가했으므로, 별도의 빈객체 생성이 필요없다. 곧바로 application.properties에 AWS S3 접속에 필요한 정보들을 넣는다.



1
2
3
4
5
6
# AWS 마스터 계정 또는 IAMUSER 정보
cloud.aws.credentials.accessKey={YOUR_USER_ACCESSKEY}
cloud.aws.credentials.secretKey={YOUR_USER_SECRETKEY}
# AWS S3 bucket의 정보
cloud.aws.s3.bucket={YOUR_BUCKET_NAME}
cloud.aws.region.static={YOUR_BUCKET_RESION}
cs



 Spring boot로 구동할 jar 파일이 cloud환경(EC2)가 아닐 경우 bucket의 resion 정보를 찾아오지 못하므로 로컬에서 테스트를 겸하려면 반드시 bucket의 지역정보를 지정하도록 한다.



3. 구현


properties 설정을 했으므로, bean 객체 생성을 따로 하지 않아도 아래와 같이 간단하게 AWS관련 객체를 주입할 수 있다.



1
2
@Autowired
private AmazonS3 amazonS3;
cs



 아래는 S3에 파일 업로드를 할 수 있는 예제이다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@Service
public class S3Service {
 
    @Autowired
    private AmazonS3 amazonS3;
 
    @Value("${cloud.aws.s3.bucket}")
    private String bucket;
 
    //S3에 파일을 업로드한다.
    public void uploadOnS3(String fileName, File file) {
 
        TransferManager transferManager = new TransferManager(this.amazonS3);
        PutObjectRequest request = new PutObjectRequest(bucket, fileName, file);    
        Upload upload = transferManager.upload(request);
 
        /* 업로드 progress가 변할 때마다 발생하는 Event Listener */
        request.setGeneralProgressListener(new ProgressListener() {
            @Override
            public void progressChanged(ProgressEvent progressEvent) {
                    double progress = progressEvent.getBytes() != 0 ?
                       (double)progressEvent.getBytesTransferred() / (double)progressEvent.getBytes()*(double)100 : 0.0;   
            }
        });
 
 
        /* 아래 내용을 활용하면, 파일 업로드가 성공할 때까지 block을 걸 수 있다. */
        try {
         
            upload.waitForCompletion();
        } catch (AmazonClientException amazonClientException) {
 
            amazonClientException.printStackTrace();
        } catch (InterruptedException e) {
     
           e.printStackTrace();
            
        }
    }
}
cs



 AWS 공식 홈페이지에 있는 SDK for JAVA 사용 예제 코드이다. TransferManager를 이용하여 단일 파일을 지정한 S3에 전송할 수 있다. 파일 다운로드의 경우, ResourceLoader를 활용하여 파일이 담겨있는 Resource 객체를 제공 받는 방식을 알아보겠다. S3에 저장되어 있는 객체들은 각각의 도메인을 갖고 있으므로, 그것으로 접근하는 원리이다. 아래 소스코드를 참고하자



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Service
public class S3Service {
 
    @Autowired
    private AmazonS3 amazonS3;
 
    @Autowired
    private ResourceLoader resourceLoader;
 
    // S3에서 파일이 들어있는 InputStream 가져옴
    public InputStream getStreamOnS3(String fileName) {
 
        try {
            InputStream inputStream = null;
            Resource resource 
                = this.resourceLoader.
                    getResource("s3://{YOUR_BUCKET_NAME}/"+fileName);
 
            if(!resource.exists()) {
                // 파일을 찾지 못했음.
            }
 
            return resource.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
            
        }
 
    }
}
cs



 Resource 객체를 받아오는 곳(15~17 Line)을 주목해보자. S3 bucket의 도메인을 입력해야하는데, s3://{버켓이름}/... 의 형태이다. 이 예제에서는 단순히 파일이름을 바로 뒤에 붙였지만, S3에 여러개의 폴더가 있고 폴더 내부의 파일에 접근할 경우 폴더 이름까지 모두 작성해 주어야한다. (ex: s3://myBucket/myfolder1/image.jpg)





 위 예제에서는 Resource에서 InputStream을 추출해 내었다. InputStream을 byte Array로 바꾸어 HttpHeader에 넣으면 파일다운로드를 구현할 수 있다. 이미지 같은 것을 단순 조회하려면, HttpResponse의 OutputStream에 넣는 방식으로 처리하면 된다. 바로 아래와 같은 방식으로 말이다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
@Service
public class S3Service {
 
    // InputStream에서 파일을 byte형태로 가져옴 (다운로드)    
    public ResponseEntity<byte[]> downloadFile (String fileName) {
        InputStream inputStream = null;
        byte[] bytes = null;
        String downloadFileName = "";
        try {
            inputStream = getStreamOnS3(fileName);
            bytes = IOUtils.toByteArray(inputStream);
            downloadFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+""%20");
 
            File tempFile = new File(fileName);
 
        } catch (IOException e) {
            e.printStackTrace();
        }
 
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.IMAGE_JPEG);    // 
        httpHeaders.setContentLength(bytes.length);
        httpHeaders.set("Content-Disposition""attachment; filename="+downloadFileName);
        return new ResponseEntity<>(bytes, httpHeaders, HttpStatus.OK);
    }
 
    // InputStream의 파일을 HttpResponse에 넣음 (조회)
    public void inquireFile (String key, HttpServletResponse response) {
        InputStream inputStream = null;
 
        try {
            inputStream = getStreamOnS3(key);
 
            /* Controller에서 주입한 HttpServletResponse 활용 */
            IOUtils.copy(inputStream, response.getOutputStream());
        } catch (IOException e) {
 
            e.printStackTrace();            
        }
    }
}

cs



지금까지 Spring Cloud AWS를 활용하여, Spring Boot에서 AWS S3를 연동하는 법을 알아보았다. 가장 중요한 점은 Properties설정을 통해 bean 객체 설정과 같은 Configuration을 따로 하지 않았다는 것이다. 이렇게 간편하게 AWS의 다른 기능도 쉽게 연동할 수 있을 것으로 보인다. 




-끝-




출처 및 참고

https://aws.amazon.com/ko/

https://cloud.spring.io/spring-cloud-aws/




«   2022/06   »
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
글 보관함
Total
809,652
Today
23
Yesterday
129