[프로젝트명]-[환경]-[용도] 가 보편적이다
testPj-prod-uploads 같이 짓는다

S3, RDS 의 필요성
운영 환경의 안정적인 상태를 유지하려면 Stateless 구조를 유지해야한다
그래야 교체와 확장이 용이하고 데이터의 유지보수성이 좋아진다
그러므로 외부 스토리지와 외부 DB 서비스가 필요하다
S3 → 외부 파일 저장소
RDS → 외부 DB 서비스
다양한 서버의 인스턴스를 외부 저장소, 외부 DB 서비스를 이용하게 하면
가용성도 좋고 Stateless 구조를 유지할 수 있다
S3
S3는 AWS가 서비스하는 외부 파일 저장 스토리지 서비스이다
S3 생성
다음엔 이름과 ACL 제어 활성화 여부, 퍼블릭 액세스 차단 여부,
암호화 방식을 설정하면 된다, 우선은 기본 체크 된 내역 그대로 진행한다
암호화 방식에 대해서는 추후 AWS 가 익숙해지면 포스트 하려한다
구조
Bucket
파일을 담는 저장소 컨테이너 → 폴더와 비슷하다
이름은 리전 전체를 통틀어서 고유해야한다
소문자, 숫자, 하이픈만 허용
문자, 숫자로 시작하며 3~63자 이내
💡
Object
저장된 파일
Key
오브젝트의 고유 경로, 이름
예시
s3://test_bucket -> bucket
├─test/ -> key 의 일부
│ ├─profile/
│ │ └─test_user1.docs -> key (test/profile/test_user1.docs)
│ └─test.log -> key (test/test.log)
└─result
└─result.log -> key (result/result.log)
보안
Public Access 는 전부 차단 되어 있음
최소 권한만 부여해야함
필요시엔 IAM Policy 사용
EC2 연동
Spring Cloud AWS 의존성 추가
만약 Parameter store 도 이용 중이면 통합 관리 하는 것이 좋다
// BOM으로 Spring Cloud AWS Starter 버전 통합 관리
implementation platform('io.awspring.cloud:spring-cloud-aws-dependencies:4.0.0-RC1')
implementation 'io.awspring.cloud:spring-cloud-aws-starter-parameter-store'
implementation 'io.awspring.cloud:spring-cloud-aws-starter-s3'추가로 yml에 region 설정이 필요하다
# S3 region 설정
spring:
cloud:
aws:
region:
static: ap-northeast-2파일 크기도 제한하는 것이 좋다
servlet:
multipart:
max-file-size: 10MB간단한 컨트롤러와 서비스, DTO를 만들어
업로드와 다운로드 응답을 받을 수 있게 만든다그런데 S3 는 퍼블릭 액세스가 차단되어있다
허용하기 위해서 일일히 IAM 을 지정하는 것이 맞을까?
→ Presinged URL 사용Presigned URL은 임시로 접근을 허용하는 서명된 URL
유효시간을 지녀서 유효시간 내엔 접근이 가능하게 할 수 있음💡
Presigned URL은 임시로 접근을 허용하는 서명된 URL
유효시간을 지녀서 유효시간 내엔 접근이 가능하게 할 수 있음@RestController @RequiredArgsConstructor public class FileController { private final S3Service s3Service; @PostMapping("/files/upload") public ResponseEntity<FileUploadResponse> upload(@RequestParam("file") MultipartFile file) { String key = s3Service.upload(file); return ResponseEntity.ok(new FileUploadResponse(key)); } @GetMapping("/files/download-url") public ResponseEntity<FileDownURLResponse> getDownloadUrl(@RequestParam String key) { URL url = s3Service.getDownloadUrl(key); return ResponseEntity.ok(new FileDownURLResponse(url.toString())); } } //----- @Service @RequiredArgsConstructor public class S3Service { // Presigned URL은 임시로 접근을 허용하는 서명된 URL, // 유효시간을 지녀서 유효시간 내엔 접근이 가능하게 할 수 있음 private static final Duration PRESIGNED_URL_EXPIRATION = Duration.ofMinutes(10); private final S3Template s3Template; @Value("${spring.cloud.aws.s3.bucket}") private String bucket; public String upload(MultipartFile file) { try { String key = "uploads/" + UUID.randomUUID() + "_" + file.getOriginalFilename(); s3Template.upload(bucket, key, file.getInputStream()); return key; } catch (IOException e) { throw new RuntimeException("파일 업로드 실패", e); } } public URL getDownloadUrl(String key) { return s3Template.createSignedGetURL(bucket, key, PRESIGNED_URL_EXPIRATION); } }IAM Policy 설정
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:PutObject", "s3:GetObject"], "Resource": "arn:aws:s3:::{버킷 이름}/{업로드 파일이 담길 폴더명 or 경로}/*" } ] }s3:PutObject → 업로드, s3:GetObject → 다운로드
IAM user 에 IAM policy 를 연결 하고 Access key를
CLI나 로컬로 받아준다, 지금은 개발 코드에서 활용할 것이므로 로컬 코드로 받았다// yml 내에 spring.cloud.credentials.access-key, secret-key 설정이 필요하다 // EC2 환경이라면 굳이 credentials 가 필요하진 않다 // 다만 Presigned URL의 만료시간이 최대 12시간으로 고정된다이제 세팅은 완료 되었으니 Postman으로 업로드와 다운로드를 테스트 해보자
다운로드 URL
RDS
RDS 는 AWS 에서 서비스하는 데이터베이스 서비스이다
AWS 가 대신 백업과 유지관리 기간에 패치를 하며
리전 별 AZ에 복제본을 유지하므로 장애조치가 가능하며
콘솔에서 쉽게 스펙 변경을 통해 확장이 가능하다
인바운드 규칙만 설정하면 쉽게 사용 가능하다
RDS 의 VPC 내 서브넷 위치는 기본적으로 알 수가 없다
퍼블릭 액세스를 허용해도 EC2 상으로 접근하는 것이 안전하다
그러므로 SSH 접근을 통해 로컬 환경의 툴에서도 접근하는 것이 좋다