-
AWS - S3를 활용한 파일 및 이미지 업로드Infra/AWS 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
'Infra > AWS' 카테고리의 다른 글
EC2로 Spring 레거시 배포하고 HTTPS 인증받기 (Nginx + Tomcat 연동 With Docker) (0) 2024.08.13 AWS - S3,Cloudfront를 활용한 웹 페이지 배포 (0) 2024.05.09 AWS - RDS 생성 (0) 2024.05.09 ELB를 활용하여 HTTPS 연결하기 (2) - ELB에 도메인 연결 HTTPS 적용 (0) 2024.05.08 Route53 - 도메인 등록 (0) 2024.05.08