πŸ“˜ Etc/Sol

[AWS] S3(Simple Storage Service)μ„œλ²„μ™€ Spring Boot 연동

Dongwoongkim 2023. 8. 17. 19:42

μ§„ν–‰μ€‘μ΄λ˜ ν”„λ‘œμ νŠΈμ— 파일 μ—…λ‘œλ“œ κΈ°λŠ₯이 μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

  • ex) κ²Œμ‹œκΈ€μ„ μ—…λ‘œλ“œ ν•  λ•Œ 이미지도 ν•¨κ»˜ μ—…λ‘œλ“œ, νšŒμ›μ •λ³΄λ₯Ό μˆ˜μ •ν•  λ•Œ ν”„λ‘œν•„ 이미지λ₯Ό 등둝

파일 μ—…λ‘œλ“œμ˜ 경우, EC2 μ„œλ²„κ°€ μ•„λ‹Œ 둜컬 μ„œλ²„λ₯Ό μ‚¬μš©ν–ˆμ„ λ•ŒλŠ” μ•„λž˜μ™€ 같이 yml에 제 개인 PC에 μ €μž₯ν•˜λ„λ‘ μ„€μ •ν•΄μ£Όμ—ˆλŠ”λ°, 배포λ₯Ό μ‹œμž‘ν•˜κ²Œ λ˜λ©΄μ„œ 파일 관리λ₯Ό μœ„ν•œ S3 μ„œλ²„λ₯Ό μ‚¬μš©ν•˜κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

upload:
  post:
    image:
      location: /Users/kdo6301/Desktop/sharing_platform_server/post/
  member:
    image:
      location: /Users/kdo6301/Desktop/sharing_platform_server/member/

 

이번 ν¬μŠ€νŒ…μ—μ„œλŠ” Spring Bootμ—μ„œ AWS S3 μ„œλ²„λ₯Ό μ΄μš©ν•˜μ—¬ 파일 관리λ₯Ό ν•˜λŠ” 방법에 λŒ€ν•΄ μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€.


1. S3 (Simple Storage Service) λž€?

  • AWSμ—μ„œ μ§€μ›ν•˜λŠ” 파일 관리 μŠ€ν† λ¦¬μ§€ μ„œλ²„μž…λ‹ˆλ‹€.
  • ν™•μž₯μ„±κ³Ό 내ꡬ성이 μ’‹μŠ΅λ‹ˆλ‹€.
  • κ°€μž…μΌ κΈ°μ€€ 12κ°œμ›”κ°„ 무료둜 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

2. 사전 μ€€λΉ„

  • S3 λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œλŠ” AWSμ—μ„œ 버킷과 IAM을 λ¨Όμ € μƒμ„±ν•΄μ£Όμ–΄μ•Όν•©λ‹ˆλ‹€.
  • 버킷 : λ‹€μˆ˜μ˜ 객체λ₯Ό κ΄€λ¦¬ν•˜λŠ” μ»¨ν…Œμ΄λ„ˆ ( νŒŒμΌμ„ 관리할 수 μžˆλŠ” 파일 μ‹œμŠ€ν…œμ΄λΌκ³  보면 됨 )
  • IAM : S3에 μ ‘κ·Όν•˜κΈ° μœ„ν•œ μ‚¬μš©μž 정보

μ‚¬μš©μž(IAM) 생성

1. AWS 검색창에 iam 을 κ²€μƒ‰ν•œ ν›„ μ£Όμš” κΈ°λŠ₯ - μ‚¬μš©μž 클릭

2. μ›ν•˜λŠ” μ‚¬μš©μž 이름 μ§€μ • - λ‹€μŒ 

3. μ•„λž˜μ™€ 같이 κΆŒν•œ μ„€μ • - λ‹€μŒ

4. κ²€ν†  및 생성 - μ‚¬μš©μž 생성

5. μ•‘μ„ΈμŠ€ ν‚€ μ„€μ • - μ‚¬μš©μž 이름 클릭 

6. μš”μ•½ - μ•‘μ„ΈμŠ€ ν‚€ λ§Œλ“€κΈ°

7. μ•‘μ„ΈμŠ€ ν‚€ μ‚¬μš© 사둀 선택 - μ•„λ¬΄κ±°λ‚˜ 선택 해도 ok

8. μ›ν•˜λŠ” νƒœκ·Έ μž‘μ„± ( 선택 ) ν›„ - μ•‘μ„ΈμŠ€ ν‚€ λ§Œλ“€κΈ°

 

9. csv 파일 λ‹€μš΄λ‘œλ“œλ₯Ό ν΄λ¦­ν•©λ‹ˆλ‹€. ( 이 νŒŒμΌμ—λŠ” κ³΅κ°œν‚€μΈ Access Key와 , 비밀킀인 Secret Key 정보가 λ“€μ–΄κ°€ 있기 λ•Œλ¬Έμ— 파일 관리에 μ£Όμ˜κ°€ ν•„μš”ν•©λ‹ˆλ‹€ )

 

이제 S3에 μ ‘κ·Όν•˜κΈ° μœ„ν•œ IAM에 λŒ€ν•œ 섀정이 μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€. 버킷을 μƒμ„±ν•΄λ΄…μ‹œλ‹€.

버킷 생성

1. 검색창에 s3 검색

2. 버킷 λ§Œλ“€κΈ° 클릭

3. 일반 ꡬ성 - 버킷 이름 μ§€μ •

4. Public Access 차단 ν•΄μ œ 및 버킷 λ§Œλ“€κΈ° 클릭

 

νŒŒμΌμ„ 관리할 수 μžˆλŠ” ν•˜λ‚˜μ˜ 버킷이 μƒμ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이제 사전 μ€€λΉ„κ°€ λͺ¨λ‘ λλ‚¬μŠ΅λ‹ˆλ‹€. 이제 Spring boot에 이 버킷과 μ—°λ™ν•΄λ΄…μ‹œλ‹€.


3. Spring Boot와 연동

1. build.gradle에 μ˜μ‘΄κ΄€κ³„ μΆ”κ°€

implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

 

2.  IAM μƒμ„±μ—μ„œ λ°œκΈ‰λ°›μ€ csv 파일의 κ³΅κ°œν‚€μ™€ λΉ„λ°€ν‚€, 그리고 버킷을 생성할 λ•Œ μ§€μ •ν•œ 버킷 이름을 yml에 λ‹€μŒκ³Ό 같이 μ„€μ •ν•΄μ€λ‹ˆλ‹€.

  • 이 λ•Œ AccessKey와 SecretKey μ •λ³΄λŠ” github에 μ˜¬λΌκ°€κ²Œ 되면 ν•΄ν‚ΉμœΌλ‘œ μΈν•œ 과금 μœ„ν—˜μ΄ λ°œμƒν•  수 μžˆμœΌλ―€λ‘œ yml νŒŒμΌμ„ gitignore둜 μ„€μ •ν•˜μ—¬ λ°˜λ“œμ‹œ github에 μ˜¬λΌκ°€μ§€ μ•Šλ„λ‘ ν•©μ‹œλ‹€.
  • cloud.aws.region.static: ap-northease2  : μ§€μ—­ ν•œκ΅­ κ³ μ •

3) μŠ€ν”„λ§ μ„€μ • μΆ”κ°€

@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() {
        BasicAWSCredentials awsCredentials   = new BasicAWSCredentials(accessKey, secretKey);
        return (AmazonS3Client) AmazonS3ClientBuilder.standard()
                .withRegion(region)
                .withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
                .build();
    }
}

4. 둜컬 μ €μž₯ ➑️ S3 μ„œλ²„μ˜ 버킷에 μ €μž₯ν•˜λ„λ‘  Refactoring

PostFileService

@Service
@RequiredArgsConstructor
public class PostFileService {

    @Value("${cloud.aws.s3.bucket}")
    private String BUCKET;
    private final AmazonS3Client amazonS3Client;


    public void upload(MultipartFile file, String filename) {
        try {
            ObjectMetadata metadata= new ObjectMetadata();
            metadata.setContentType(file.getContentType());
            metadata.setContentLength(file.getSize());
            amazonS3Client.putObject(BUCKET + "/post", filename, file.getInputStream(), metadata);
        } catch(IOException e) {
            throw new FileUploadFailureException();
        }
    }

    public void delete(String fileName){
        DeleteObjectRequest request = new DeleteObjectRequest(BUCKET + "/post", fileName);
        amazonS3Client.deleteObject(request);
    }
}
  • κΈ°μ‘΄μ—λŠ” upload()λ©”μ†Œλ“œμ—μ„œ try/catch문으둜 λ‘œμ»¬μ—μ„œ ν•„λ“œμ— μ§€μ •ν•œ μœ„μΉ˜μ— μ ‘κ·Όν•˜μ—¬ νŒŒμΌμ„ μ €μž₯ν•˜κ³ , λ§Œμ•½ IOException으둜 νŒŒμΌμ—…λ‘œλ“œμ— μ‹€νŒ¨ν•˜λŠ” 경우 Customν•œ extended RuntimeException인 FileUploadException을 λ˜μ§€λ„λ‘ κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€.
  • κΈ°μ‘΄μ—λŠ” delete() λ©”μ†Œλ“œλ„ ν•„λ“œμ— μ§€μ •ν•œ μœ„μΉ˜μ— μ ‘κ·Όν•˜μ—¬ νŒŒμΌμ„ μ‚­μ œν•˜λ„λ‘ κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€.
  • S3 μŠ€ν† λ¦¬μ§€ μ„œλ²„λ₯Ό μ‚¬μš©ν•œ 이후 λΆ€ν„°λŠ” μœ„ μ½”λ“œμ™€ 같이 yml에 μ§€μ •ν•΄μ€€ BUCKET의 폴더에 μ ‘κ·Όν•˜μ—¬ νŒŒμΌμ„ μ—…λ‘œλ“œν•˜κ³ , μ§€μšΈ 수 μžˆλ„λ‘ λ³€κ²½ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

5. Postman Test

μ—…λ‘œλ“œ ν…ŒμŠ€νŠΈ

1) κ²Œμ‹œκΈ€ 생성 μš”μ²­ with 파일 

  • 이 λ•Œ λ³„λ„λ‘œ 생성해둔 Post Image λ°μ΄ν„°λ² μ΄μŠ€μ— 파일의 originNameκ³Ό uniqueName이 μ €μž₯λ©λ‹ˆλ‹€. (for μ‚¬μš©μžκ°€ νŒŒμΌμ„ μƒμ„±ν•˜κ³ , μ‚­μ œν•  λ•Œ S3에 μ €μž₯된 파일이 무엇인지 νŒŒμ•…ν•˜κΈ° μœ„ν•΄μ„œ)

2) 버킷에 파일이 잘 μ €μž₯된 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

 

κ²Œμ‹œκΈ€ μˆ˜μ • ν…ŒμŠ€νŠΈ - 이미지 파일 μ‚­μ œ 

1) μˆ˜μ • μš”μ²­

 

2) λ²„ν‚·μ—μ„œ μ‚­μ œλœ 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. 

  • 참고둜 이미지 μ‚­μ œλŠ” λ‚΄λΆ€μ μœΌλ‘œ κ²Œμ‹œκΈ€ μˆ˜μ • APIμ—μ„œ Post Imageλ₯Ό μœ„ν•œ λ³„λ„μ˜ λ°μ΄ν„°λ² μ΄μŠ€λ₯Ό μ΄μš©ν•˜μ—¬ μš”μ²­ API의 폼데이터에 deleteImageNames둜 μž‘μ„±ν•œ originNameκ³Ό μΌμΉ˜ν•˜λŠ” 파일의 uniqueName을 S3μ„œλ²„μ—μ„œ μ‚­μ œν•˜λ„λ‘ κ΅¬ν˜„ν•˜μ˜€μŠ΅λ‹ˆλ‹€)

 

<참고 자료>

 

[Spring boot] AWS S3 λ₯Ό μ΄μš©ν•œ 파일 μ—…λ‘œλ“œ

개인 ν”„λ‘œμ νŠΈλ₯Ό ν•˜λ©° 이미지 μ„œλ²„λ‘œ μ‚¬μš©ν•˜κΈ° μœ„ν•΄ AWS S3 버킷을 λ§Œλ“€κ³  Spring 을 μ—°λ™ν•˜λŠ” 방법을 μ •λ¦¬ν•΄λ³΄μ•˜λ‹€. [1] AWS S3 κ°œμš” AWS S3 λž€? S3λŠ” Simple Storage Service 의 μ•½μžλ‘œ 주둜 파일 μ„œλ²„λ‘œ μ‚¬μš©

gaeggu.tistory.com