본문 바로가기
Spring/SpringBoot

[SpringBoot] AWS S3에 파일 업로드하기

by J4J 2022. 4. 23.
300x250
반응형

안녕하세요. J4J입니다.

 

이번 포스팅은 AWS S3에 파일 업로드하는 방법에 대해 적어보는 시간을 가져보려고 합니다.

 

 

 

들어가기에 앞서 Controller에서 파일 데이터를 받을 수 있기 위해 multipartfile을 사용할 예정입니다.

 

또한 AWS S3 버켓​ 생성하는 방법은 [AWS] 이미지 저장을 위한 S3 버킷 생성하기를 참고해주시길 바랍니다.

 

 

 

S3에 접근할 IAM 계정 생성

 

가장 먼저 S3에 접근할 수 있는 IAM 계정 생성을 해줘야 합니다.

 

계정 생성이 완료되면 해당 계정 정보를 SpringBoot에 입력해줄 것이고 이를 기반으로 S3에 접근할 수 있는 사용자인지를 판단할 수 있게 도와줍니다.

 

 

 

​​​[ 1. IAM 서비스 접근 ]

 

IAM 서비스

 

 

 

[ 2. 사용자 추가 클릭 ]

 

사용자 추가 클릭

 

 

 

[ 3. 사용자 정보 입력 ]

 

사용자 이름은 사용하고 싶은 이름으로 자유롭게 기입해주시면 됩니다.

 

액세스 유형 같은 경우는 액세스 키를 활용하기 때문에 암호 말고 액세스 키를 선택해줍니다.

 

사용자 정보 입력

 

 

 

[ 4. 권한 입력 ]

 

권한은 AmazoneS3FullAccess를 부여하면 됩니다.

 

저는 사용자에게만 권한을 부여하고 있지만 상황에 따라 S3 사용 권한을 가진 사용자 그룹을 만들어서 사용하는 것도 좋은 방법이니 참고해주시길 바랍니다.

 

권한 입력

 

 

반응형

 

 

[ 5. 태그 추가 ]

 

필요하신 분만 태그 추가해주시면 됩니다.

 

저는 따로 입력하지 않았습니다.

 

태그 추가

 

 

 

[ 6. 검토 ]

 

지금까지 작성한 내용들을 확인하는 단계입니다.

 

따로 문제가 없다면 다음으로 넘어가 주시면 됩니다.

 

검토

 

 

 

[ 7. 액세스 키 확인 ]

 

사용자 생성이 완료되었다면 다음과 같이 액세스 키 정보를 확인할 수 있습니다.

 

현재 화면에서만 확인할 수 있고 화면이 넘어가면 확인할 수 없는 정보가 있기 때문에 csv 다운을 하는 등의 방식을 통해 어디든 정보를 보관해둬야 합니다.

 

액세스 키 확인

 

 

 

 

Springboot 설정

 

위에서 생성한 IAM 계정을 이용하여 S3 Bucket에 연결해보겠습니다.

 

 

 

[ 1. application.properties 설정 ]

 

# multipart 설정
spring.servlet.multipart.max-file-size: 100MB
spring.servlet.multipart.max-request-size: 100MB

# aws 설정
# 사용할 S3 bucket region 입력
cloud.aws.region.static=ap-northeast-2
cloud.aws.stack.auto=false

 

 

 

[ 2. dependency 추가 ]

 

<dependencies>
    <!-- AWS -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-aws</artifactId>
        <version>2.2.6.RELEASE</version>
    </dependency>		
</dependencies>

 

 

 

[ 3. AWS 설정 클래스 작성 ]

 

package com.spring.s3.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;

@Configuration
public class AWSConfig {
	
	/**
	 * Key는 중요정보이기 때문에 properties 파일에 저장한 뒤 가져와 사용하는 방법이 좋습니다.
	 */
	private String iamAccessKey = "IAM 생성할 때 확인했던 AccessKey 입력"; // IAM Access Key
	private String iamSecretKey = "IAM 생성할 때 확인했던 SecretKey 입력"; // IAM Secret Key
	private String region = "ap-northeast-2"; // Bucket Region 
	
	@Bean
	public AmazonS3Client amazonS3Client() {
		BasicAWSCredentials basicAWSCredentials = new BasicAWSCredentials(iamAccessKey, iamSecretKey);
		return (AmazonS3Client) AmazonS3ClientBuilder.standard()
                                                             .withRegion(region)
                                                             .withCredentials(new AWSStaticCredentialsProvider(basicAWSCredentials))
                                                             .build();
	}
}

 

 

 

[ 4. Controller 클래스 작성 ]

 

package com.spring.s3.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;

@RestController
public class FileController {
	
	private String S3Bucket = "j4j-test-bucket"; // Bucket 이름
	
	@Autowired
	AmazonS3Client amazonS3Client;
	
	@GetMapping("/upload")
	public ResponseEntity<Object> upload(MultipartFile[] multipartFileList) throws Exception {
		List<String> imagePathList = new ArrayList<>();
		
		for(MultipartFile multipartFile: multipartFileList) {
			String originalName = multipartFile.getOriginalFilename(); // 파일 이름
			long size = multipartFile.getSize(); // 파일 크기
			
			ObjectMetadata objectMetaData = new ObjectMetadata();
			objectMetaData.setContentType(multipartFile.getContentType());
			objectMetaData.setContentLength(size);
			
			// S3에 업로드
			amazonS3Client.putObject(
				new PutObjectRequest(S3Bucket, originalName, multipartFile.getInputStream(), objectMetaData)
					.withCannedAcl(CannedAccessControlList.PublicRead)
			);
			
			String imagePath = amazonS3Client.getUrl(S3Bucket, originalName).toString(); // 접근가능한 URL 가져오기
			imagePathList.add(imagePath);
		}
		
		return new ResponseEntity<Object>(imagePathList, HttpStatus.OK);
	}
}

 

 

 

 

테스트

 

실행해보면 다음과 같은 에러를 확인하실 수 있습니다.

 

com.amazonaws.SdkClientException: Failed to connect to service endpoint: 
	at com.amazonaws.internal.EC2ResourceFetcher.doReadResource(EC2ResourceFetcher.java:100) ~[aws-java-sdk-core-1.11.792.jar:na]
	at com.amazonaws.internal.InstanceMetadataServiceResourceFetcher.getToken(InstanceMetadataServiceResourceFetcher.java:91) ~[aws-java-sdk-core-1.11.792.jar:na]
	at com.amazonaws.internal.InstanceMetadataServiceResourceFetcher.readResource(InstanceMetadataServiceResourceFetcher.java:69) ~[aws-java-sdk-core-1.11.792.jar:na]
	at com.amazonaws.internal.EC2ResourceFetcher.readResource(EC2ResourceFetcher.java:66) ~[aws-java-sdk-core-1.11.792.jar:na]
	at com.amazonaws.util.EC2MetadataUtils.getItems(EC2MetadataUtils.java:402) ~[aws-java-sdk-core-1.11.792.jar:na]
	at com.amazonaws.util.EC2MetadataUtils.getData(EC2MetadataUtils.java:371) ~[aws-java-sdk-core-1.11.792.jar:na]

 

 

 

EC2 메타데이터 관련 에러인 것으로 보이는데 해당 에러가 보여도 동작되는 데는 문제가 없지만 이런 에러가 보이고 싶지 않으신 분들은 로그가 안 나오게 하거나 또는 VM 옵션 설정을 통해 해결할 수 있는 것으로 보입니다.

 

구글에 검색하면 관련 정보들을 빠르게 확인하실 수 있습니다.

 

 

 

 

작성한 코드들을 테스트하기 위해 포스트맨을 사용해보겠습니다.

 

다음과 같이 관련 정보들을 입력해주고 Send를 클릭하면 Response값에 다음과 같이 업로드된 이미지 URL을 확인할 수 있습니다.

 

포스트맨 테스트

 

 

 

또한 S3에서도 업로드된 것이 확인 가능합니다.

 

S3 리스트

 

 

 

마지막으로 전달받은 URL 중 하나를 선택하여 브라우저에서 접근해보면 다음과 같이 이미지도 보이는 것을 확인할 수 있습니다.

 

이미지 확인

 

 

 

 

 

 

 

이상으로 AWS S3에 파일 업로드하는 방법에 대해 간단하게 알아보는 시간이었습니다.

 

읽어주셔서 감사합니다.

 

 

 

728x90
반응형

댓글