-
[AWS] AWS S3 생성 및 Spring 연결프로그램/AWS 2024. 2. 22. 21:41
최근 진행한 프로젝트에서 AWS S3 버킷을 생성해 영상과 사진을 별도로 관리했습니다. AWS S3를 사용하는 이유로 다음과 같은 세 가지를 꼽았습니다.
- AWS 서버를 사용하기에 업로드된 파일의 내구성(파일이 실제로 존재하는지, 99.99...99%의 내구성을 보장함)이 뛰어나다.
- 파일을 언제든지 쓸 수 있는지의 가용성(내구성과 조금 다른 의미로 만약 파일을 당장 사용할 수 없다해도 파일이 존재한다면 내구성은 뛰어나며 가용성이 낮은 것 입니다.)이 뛰어나다.
- 언제든지 저장 용량을 늘릴 수 있는 확장성이 뛰어나다.
그렇다면 실제로 AWS S3 버킷을 생성하고 설정하는 과정과 Spring에 연결하는 과정을 살펴보겠습니다.
| AWS S3 버킷 생성
1. AWS S3 > 버킷 > 버킷 만들기 순서로 이동합니다.
아래의 스크린샷에 표시된 주황색 박스 외에는 default 값으로 진행했습니다.
모든 퍼블릭 액세스 차단을 꼭! 체크 해제 해주시기 바랍니다.
엑세스 차단을 해제해야 이후 이미지 및 동영상 업로드시 문제없이 진행됩니다!
아래와 같이 버킷 생성이 성공적으로 되었습니다. 이제 생성된 버킷에 파일을 업로드 및 호출 할 수 있도록 정책을 설정하도록 하겠습니다.
2. 생성된 버킷 이름 클릭
3. 권한 > 버킷 정책 편집 클릭
4. 버킷 정책 JSON 형태로 입력 & 변경 사항 저장 클릭
아래 주석에서 'sta-d' 는 저의 test 버킷 명이므로 사용자의 버킷 명으로 변경해 주셔야합니다.
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Statement1", "Effect": "Allow", "Principal": "*", "Action": "s3:*", "Resource": "arn:aws:s3:::sta-d/*" } ] }
이제 버킷에 대한 생성과 설정은 완료됐습니다. 아래에서는 버킷을 사용하기 위한 S3 권환을 가진 사용자 IAM을 만들어 보겠습니다.
| 사용자 추가
버킷은 생성 완료되었으며, 해당 버킷에 접근할 수 있는 권한을 부여 받을 사용자를 생성하기 위해 AWS IAM으로 이동합니다.
1. AWS IAM > 엑세스 관리 > 사용자 > 사용자 생성 순서로 이동합니다.
2. 사용자 이름을 입력해줍니다.
3. 권한 설정을 아래 화면과 같이 amazonS3FullAccess로 설정해 줍니다.
4. 검토 및 생성 페이지는 별도의 수정 없이 '사용자 생성' 버튼 클릭으로 마무리했습니다.
여기까지 진행 하셨다면 하기와 같이 사용자가 생성된 것을 보실 수 있으며, 아직 액세스 키는 생성하지 않은 상태입니다.
| 액세스 키 생성
1. 사용자 이름을 클릭
2. 보안 자격 증명 > 엑세스 키 만들기 클릭
3. 액세스 키 모범 사례 및 대안은 보기 중 한 개를 선택해 주시면 됩니다. 기능의 차이는 없습니다.
4. 설명 태그 설정은 선택 사항으로 저는 빈칸으로 넘어갔습니다.
5. 액세스 키 검색페이지에서 나오는 엑세스 키와 비밀 엑세스 키는 깃 토근과 같이 현재 페이지를 벗어나면 다시는 확인할 수 없기에 csv 파일로 다운 받거나 어딘가에 꼭 백업을 해두어야 합니다! 만약 키 백업을 못하신 경우 새로운 액세스 키를 생성해 사용하셔야 합니다.
| Spring 연결 with gradle, yml
1. gradle에 dependency 추가
dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' }
2. yml 생성
cloud.aws.credentials.access-key: 사용자 access key
cloud.aws.credentials.secret-key: 사용자 secret key
설정도 들어가야하며 저는 별도의 secret 관련 yml을 만들어 사용해 해당 파일에는 없습니다.
추가로 file size를 300mb로 설정해주었습니다. default는 20mb이었던 것으로 기억합니다.
cloud: aws: s3: bucket: sta-d stack.auto: false region.static: ap-northeast-2 spring: servlet: multipart: max-file-size: 300MB max-request-size: 300MB
3. config 생성
import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @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; /** * @AmazonS3Client : AWS S3를 연결하기 위한 객체 * @BasicAWSCredentials : 사용자에 대한 액세스 키, 비밀번호 키 */ @Bean public AmazonS3Client amazonS3Client() { BasicAWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey); return (AmazonS3Client) AmazonS3ClientBuilder.standard() .withRegion(region) .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) .build(); } }
4. service 작성
service에서 동영상 업로드 관련 부분만 기재해 드렸습니다. UUID로 파일명이 겹치지 않게 설정하였으며(겹치는 경우 파일을 덮어버립니다), S3에는 ObjectMetadata라는 별도의 파일로 업로드가 가능해 MultiparFile의 자료를 ObjectMetadata로 변환해 업로드 후 해당 video의 url을 추출하는 과정입니다.
@Value("${cloud.aws.s3.bucket}") private String bucket; @Transactional(readOnly = false) public String uploadJustVideoS3(MultipartFile justVideo) { try { String justVideoName = UUID.randomUUID().toString().replace("-", "") + StringUtils.cleanPath(justVideo.getOriginalFilename()); ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentType(justVideo.getContentType()); metadata.setContentLength(justVideo.getSize()); amazonS3Client.putObject(bucket, "video/" + justVideoName, justVideo.getInputStream(), metadata); String justVideoUrl = amazonS3Client.getUrl(bucket, "video/" + justVideoName).toString(); return justVideoUrl; } catch (IOException e) { e.printStackTrace(); return null; } }
5. controller 작성
controller에서 동영상 업로드 관련 부분만 기재해 드렸으며, Spring을 사용해 MultipartFile 타입으로 동영상을 받았습니다.
@PostMapping("/upload/video") public ResponseEntity<ApiResponse<String>> uploadJustVideo(@RequestParam("file") MultipartFile justVideo) { String videoUrlPath = videoPostService.uploadJustVideoS3(justVideo); if (videoUrlPath == null) return new ResponseEntity<>(ApiResponse.createError("video error"), HttpStatus.BAD_REQUEST); return new ResponseEntity<>(ApiResponse.createSuccess(videoUrlPath), HttpStatus.OK); }
요번 포스터에서는 간단하게 AWS S3의 기본적인 설정을 알아보았습니다. 이 외에도 파일 자동삭제 기간 등 설정해 주어야 하는 부분이 많아 기회가 된다면 추후 포스팅 하도록 하겠습니다. 추가적으로 포스트맨으로 test 하실 경우 form-data로 자료를 전송해 test하시기 바랍니다.