프로젝트/Trend-Pick

AWS S3를 이용한 사진 저장

chanhee01 2023. 7. 31. 19:00

AWS의 S3를 이용해서 S3 버킷을 생성했다.

프리티어를 이용하면 20000개의 GET 요청과 2000개의 PUT, POST 요청이 월별 무료라고 한다.

 

 

 

기본 설정

 

 

build.gradle에 추가

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

 

application.properties에 추가

cloud.aws.credentials.accessKey='엑세스 키'
cloud.aws.credentials.secretKey='엑세스 비밀 키'

cloud.aws.s3.bucket=trendpick-photo
cloud.aws.region.static=ap-northeast-2
cloud.aws.stack.auto=false

 

 

 

S3 Configuration

@Configuration
public class S3Config {

    @Value("${cloud.aws.credentials.accessKey}")
    private String accessKey;
    @Value("${cloud.aws.credentials.secretKey}")
    private String secretKey;
    @Value("${cloud.aws.region.static}")
    private String region;

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

 

 

 

Service 계층에서의 upload 로직 추가

public class S3FileService {

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

    private final AmazonS3 amazonS3;

    public String upload (MultipartFile multipartFile) throws IOException {
        String s3FileName = UUID.randomUUID() + "-" + multipartFile.getOriginalFilename();
        // filename을 랜덤으로 생성

        ObjectMetadata objMeta = new ObjectMetadata();
        objMeta.setContentLength(multipartFile.getInputStream().available());
        // file 사이즈 알려주는거

        amazonS3.putObject(bucket, s3FileName, multipartFile.getInputStream(), objMeta);
        // S3의 메서드인데 파일 stream을 열어서 S3에 파일을 업로드 하는 기능

        return amazonS3.getUrl(bucket, s3FileName).toString();
        // 업로드 된 사진 URL을 가져오는 기능
    }
}

Service 계층에서 bucket을 이용해서 fine이름을 UUID로 랜덤으로 생성한 다음에 업로드 된 사진의 url을 return 해주는 로직이다.

 

 

 

컨트롤러에서 이미지 저장 로직 사용

@PostMapping("/create_picture")
public CreatePictureDto savePicture(@RequestParam("cody_img") MultipartFile codyImg)
        throws Exception{
    // PictureCreateDto pictureDto = new PictureCreateDto.builder()
    // 여기서 날라왔을 때
    Member member = (Member) session.getAttribute(SessionConst.LOGIN_MEMBER);
    String oriImgName = codyImg.getOriginalFilename();
    String imgName = "";
    String imgUrl = "";

    imgName = s3FileService.upload(codyImg);

    imgUrl = imgLocation+"/"+ imgName;

    Picture picture = Picture.builder()
            .picture_member(member)
            .imgName(imgName).oriImgName(oriImgName).imgUrl(imgUrl).pictureTime(LocalDateTime.now()).build();

    pictureService.save(picture);
    return new CreatePictureDto(picture);
    //  codyImgService.save(picture_member,codyImg);

}

가운데 보이는 s3FileService.upload() 로직으로 S3에 파일을 저장할 수 있다.

로컬로 했을 때에는 FileSerivce에서 로컬로 저장했는데 이제는 S3에 있는 저장소로 저장되게 된다.

 

S3에 객체가 넣어졌다.
물론 db에도 반영이 됐다. (mysql workbench 캡처)

 

 

투표를 하는 cody_image랑 post_image, member_image가 같은 S3에 들어가는게 문제인데 이 문제는 폴더를 만들거나 S3 버킷을 여러개 만드는 것을 공부해가면서 분리해야겠다.