응애개발자
article thumbnail
728x90

프로젝트 진행 시 이미지를 서버에 저장해야 할 경우가 많다. AWS의 S3를 이용하면 이미지를 저장하고 해당 링크를 DB에 저장하여 효율적으로 관리할 수 있다. 이를 통해 서버 용량을 절약하고, 비용 절감 효과를 얻을 수 있다.

 

그럼 AWS의 S3를 활용하여 이미지를 저장하고 확인해보자.

1. S3 버킷 생성하기

1.버킷 생성하기

AWS > S3 > 버킷 > 버킷만들기 클릭

또는 밑의 주소로 접속합니다.

https://ap-northeast-2.console.aws.amazon.com/s3/bucket/create?region=ap-northeast-2#

 

2. 버킷 생성

버킷을 생성하기 위해 이름을 만들어 줍니다.

버킷은 디렉토리/폴더 개념으로 이해하시면 됩니다.

 

그리고 버킷의 퍼블릭 엑세스 차단을 해제해줍니다.

 

3. 버킷 정책 설정

S3 > 버킷 > 권한 > 버킷 정책 > 편집

퍼블릭IP에서 데이터를 조회할 수 있도록 정책을 설정해셔야 합니다.

 

 

그 후에 정책 설정을 입력해줍니다. 저는 밑과 같이 입력해 주었고, < 버킷명 > 여기서 이 안에 만드신 버킷 이름을 넣어줍니다.  ex) "arn:aws:s3:::asdf/*" 또한 주석도 삭제해주셔야 합니다.

{
    "Version": "2012-10-17",
    "Id": "Policy1464968545158",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow", // 허용
            "Principal": "*",
            "Action": "s3:GetObject", // 객체 읽기 권한
            "Resource": "arn:aws:s3:::<버킷명>/*"
        },
        {
            "Sid": "DenyOtherAccess",
            "Effect": "Deny", // 차단
            "Principal": "*",
            "Action": "s3:PutObject", // 객체 업로드 권한
            "NotResource": [
                "arn:aws:s3:::<버킷명>/*.jpg",
                "arn:aws:s3:::<버킷명>/*.png",
                "arn:aws:s3:::<버킷명>/*.jpeg",
                "arn:aws:s3:::<버킷명>/*.gif"
            ] // 해당 확장자를 가지지 않은 객체
        }
    ]
}

 

2. S3 사용자(I AM 자격증명) 설정

1. 사용자 생성을 설정합니다.

AWS > IAM > 엑세스관리 > 사용자 > 사용자 생성 또는 밑의 링크를 클릭하시면 됩니다.

https://ap-northeast-2.console.aws.amazon.com/access-analyzer/home?region=ap-northeast-2#/

 

 

 

 

2. 사용자 이름 설정

 

3. 권한 설정

권한 정책에서 AmazonS3FullAccess를 설정해줍니다.

4. 사용자 생성

 

 

3. 엑세스 키 생성

1. AWS > IAM > 사용자 > 사용자 이름(생성된 사용자) > 엑세스 키 만들기를 선택합니다.

 

2. 엑세스 키모범 사례 및 대안

저는 로컬 코드를 사용했습니다. (아무것이나 선택 가능)

 

3. 엑세스키, 비밀 엑세스키 확인

사용자가 생성되었으면 엑세스키를 생성할 수 있습니다. 여기서 비밀 엑세스 키는 다시 볼수 없기 때문에 CSV파일로 받아두시는 것을 추천드립니다.

 

4. Spring 설정

1. build.gradle 의존성 추가

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

 

2. application.yml 추가

cloud:
  aws:
    credentials:
      accessKey: ${AWS_ACCESS_KEY_ID}       # AWS IAM AccessKey 적기
      secretKey: ${AWS_SECRET_ACCESS_KEY}   # AWS IAM SecretKey 적기
    s3:
      bucket: 버킷명  # 예) myawsbucket
      dir: S3 디렉토리 이름 # 예) /home
    region:
      static: ap-northeast-2
    stack:
      auto: false

 

3. S3Config 설정

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;

    @Bean
    public AmazonS3Client amazonS3Client() {
        BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKey,secretKey);
        return (AmazonS3Client) AmazonS3ClientBuilder.standard()
                .withRegion(region)
                .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
                .build();
    }
}

 

 

4. S3 Service , S3ServiceImpl

 

S3 Service

package com.wms.global.util.s3;

import org.springframework.web.multipart.MultipartFile;

public interface S3Service {
    String uploadFile(MultipartFile multipartFile, String url);
    boolean delete(String fileUrl);
}

 

S3 ServiceImpl

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.wms.global.exception.exception.S3Exception;
import com.wms.global.exception.responseCode.S3ExceptionResponseCode;
import lombok.RequiredArgsConstructor;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.UUID;

@RequiredArgsConstructor
@Service
public class S3ServiceImpl implements S3Service {
    private final AmazonS3 amazonS3;

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

    // 파일 업로드
    @Override
    public String uploadFile(MultipartFile multipartFile, String url) {
        String fileName = url+"/"+ UUID.randomUUID().toString() + "_" + multipartFile.getOriginalFilename();
        ObjectMetadata objMeta = new ObjectMetadata();
        objMeta.setContentLength(multipartFile.getSize());
        try {
            amazonS3.putObject(bucket, fileName, multipartFile.getInputStream(), objMeta);
        } catch (IOException e) {
            throw new S3Exception(S3ExceptionResponseCode.UPLOAD_EXCEPTION,"S3 업로드 중 에러가 발생");
        }
        return amazonS3.getUrl(bucket, fileName).toString();
    }

    // 파일 삭제
    @Override
    public boolean delete(String fileUrl) {
        try {
            String[] temp = fileUrl.split(".com/");
            String fileKey = temp[1];
            amazonS3.deleteObject(bucket, fileKey);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

 

5. controller

밑처럼 사진 파일을 받을 때에는 @RequestPart로 받으시면 됩니다.

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/v1/users")
public class UserController 

    private final FeedService feedService;

    @PostMapping("/register")
    public ResponseEntity<ApiResponse<?>> register(@Validated @RequestPart("signUpRequest") SignUpRequestDTO signUpRequestDTO, @RequestPart(value = "profileImage", required = false) MultipartFile profileImage) {
        ...
    }

}

5. Postman,S3 테스트

localhost:8080/api/v1/users/register 쪽으로 회원가입 할때 필요한 json 타입의 request요청과 multipart/form-data 타입의 사진을 넣어주고 동작시키면 잘 작동이 된다.

 

 

 

이미지가 잘 들어온 것을 확인할 수 있다.

profile

응애개발자

@Eungae-D

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!