Infra/AWS
AWS - S3를 활용한 파일 및 이미지 업로드
now0204
2024. 5. 9. 15:55
s3란?
파일 저장 서비스이다. 사진이나 동영상 같은 파일을 구글 드라이브나 icloud에 업로드 하는 것과 비슷하다 |
- 백엔드 서버를 구현하다보면, 이미지 업로드를 구현할 때가 많다. 이 이미지를 EC2 내부에 저장할 수도 있지만, EC2에 쌓이는 파일이 너무 많아질 우려가 있다.
- 따라서 파잃은 S3서비스를 이용해서 따로 관리하는 것이다.
- 현업에서도 파일 업로드 기능을 구현할 때면 대부분 S3를 활용한다고 한다.
1. S3 버킷 생성하기
버킷이란? S3 서비스 내에 여러 Repositroy를 의미한다. 객체란? S3에 업로그한 파일을 파일이라 부르지 않고 객체라고 부른다. |
- 버킷에 이미지나 파일을 올리기 위해 모든 퍼블릭 액세스를 일단 허용해두자
2. 버킷 정책 추가하기
정책이란 권한을 정의하는 JSON문서이다. AWS의 특정 소스에 접근하려면 권한을 허용해 주어야 한다. |
- 모든 사용자에게 상품 이미지를 보여주거나, 다운받을 수 있게 하려면, 액세스를 해제하는 것과 동시에 권한을 주어야한다.
- 버킷에 들어가서 버킷 정책에 편집을 누르자
- ARN에 {버킷명}/접근 오브젝트 명 (*이면 모든 오브젝트)
- 그냥 접근 가능한 오브젝트에 경로 설정해주는 부분이다
ARN이란 Amazon Resource Number의 약자이다. AWS에 존재하는 리소스를 표현하는 문법이다. |
- 마지막으로 principal을 설정해 주자 이는 허용 대상을 의미한다. *이면 모두에게 허용하는 것
3. S3에 파일을 업로드 할 수 있도록 IAM에서 엑세스 키 발급받기
- AWS의 리소스에 아무나 접근 못하도록 막아놨으므로, S3에 접근해서 파일을 막 업로드할 수 는 없다.
- 백엔드 서버에서만 업로드 할 수 있도록 하기 위해 키를 발급 받고, 이를 서버 설정에 추가해줘야한다.
- 먼저 IAM으로 들어가자
- 사용자를 추가하자
- 여기서 직접 정책 연결은 AWS에서 미리 지정해둔 ROLE들을 의미한다.
- 마치 DB에서 권한을 설정할 때 세부적으로 설정할 수 도 있지만, 권한들을 미리 묶어둔 ROLE이 있는 것과 같다
- 이제 엑세스 키를 만들자
- AWS 외부에서 실행되는 애플리케이션이 백엔드 서버 같은 걸 의미한다.
- 발급받은 액세스 키는 두번 알려주지 않는다. 까먹으면 새로 발급받아야한다.
- 잘 저장해두자
- 버킷 종료시 안에 있는 파일을 모두 삭제하고 버킷만 삭제하면 된다.
4. 스프링 부트 S3 연동하기
- 먼저 의존성을 하나 추가해준다.
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
- application.yml에 설정 정보를 추가한다.
cloud:
aws:
s3:
bucket: <S3 버킷 이름>
credentials:
access-key: <저장해놓은 액세스 키>
secret-key: <저장해놓은 비밀 액세스 키>
region:
static: ap-northeast-2
auto: false
stack:
auto: false
- 주의할 점으로 저어어어얼대 이 설정을 github에 올리면 안된다. 털리면 엄청난 과금 폭탄을 맞을 수 있다.
- region은 아시아로 연동되어 있다.
- stack은 EC2에서
- 다음으로 Config 파일을 구성하자
@Configuration
public class S3Config {
@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 AmazonS3Client amazonS3Client() {
//accessKey, secretKey, region 값으로 S3에 접근 가능한 객체 등록
BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
return (AmazonS3Client) AmazonS3ClientBuilder
.standard()
.withRegion(region)
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.build();
}
}
4.1 파일 업로드
@Service
@RequiredArgsConstructor
public class S3UploadService {
private final AmazonS3 amazonS3;
@Value("${cloud.aws.s3.bucket}")
private String bucket;
public String saveFile(MultipartFile multipartFile) throws IOException {
String originalFilename = multipartFile.getOriginalFilename();
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(multipartFile.getSize());
metadata.setContentType(multipartFile.getContentType());
amazonS3.putObject(bucket, originalFilename, multipartFile.getInputStream(), metadata);
return amazonS3.getUrl(bucket, originalFilename).toString();
}
}
- putObject 메서드가 파일을 저장해주는 메서드이다.
- ObjectMetadata에 파일의 사이즈와 타입을 입력한다.
- 마지막에 파일 URL은 꼭 줘야하는건 아님! 들어가서 확인할 수 있도록 URL Return해준것
- ObjectMetadata는 com.amazonaws.services.s3.model 패키지에 존재한다.
- S3에 저장될 Object(파일)의 정보를 저장하는 객체이다.
4.2 파일 다운로드
public ResponseEntity<UrlResource> downloadImage(String originalFilename) {
UrlResource urlResource = new UrlResource(amazonS3.getUrl(bucket, originalFilename));
String contentDisposition = "attachment; filename=\"" + originalFilename + "\"";
// header에 CONTENT_DISPOSITION 설정을 통해 클릭 시 다운로드 진행
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition)
.body(urlResource);
}
- UrlResource를 사용해서 간단하게 구현할 수 있다. 응답 해더에 Disposition을 추가해두자
- 해당 헤더 설정 값이 있으면, 클릭시 다운로드 가능
4.3 파일 삭제
public void deleteImage(String originalFilename) {
amazonS3.deleteObject(bucket, originalFilename);
}
아래는 관련 공식문서 주소이다. (AWS SDK for java)
https://docs.aws.amazon.com/ko_kr/sdk-for-java/v1/developer-guide/examples-s3-objects.html
참고자료
https://chb2005.tistory.com/200
https://velog.io/@galmegi/Spring-Amazon-S3-%EC%97%B0%EB%8F%99