Main Project (1)

김준영·2023년 7월 14일
1

Main-Project

목록 보기
1/4
post-thumbnail

Main Project를 진행하면서 느낀점, 에러 또는 참고, 검색한 것에 대해 작성할 것이다.

S3 연결 및 이미지 업로드


프로젝트를 진행하면서 이미지를 서버에 올려야하는 기능이 필요했다.
예전에도 혼자 미니 프로젝트를 진행하면서 이 부분에 대해서 많이 생각해봤는데 그땐 지식이 짧다보니 DB에 이미지를 바로 올리려고 했고, 그 방법에 대해 검색을 해봤지만 많은 전문가 분들이 이미지를 DB에 올리는건 아니라고 말씀하셨다.

Spring boot만 공부했던터라 AWS, docker 등 아무것도 몰랐으니 그런 생각을 당연하게 했고, 어느 정도 공부를 하니 어떻게 올려야하는지, 어떻게 사용해야하는지 감이 잡혔다.

AWS에 S3를 사용하여 이미지 파일을 올리고, URL을 통해 그 이미지를 사용했다.

참고 사이트


https://chb2005.tistory.com/102#2.4.FileStore클래스 의 블로그를 참고했다. 너무 잘 작성되어있고, 바로 따라해 올리는 방법과 사용방법에 대해 이해했다.

내 코드



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 credentials = new BasicAWSCredentials(accessKey, secretKey);

        return (AmazonS3Client) AmazonS3ClientBuilder
                .standard()
                .withRegion(region)
                .withCredentials(new AWSStaticCredentialsProvider(credentials))
                .build();
    }

}

S3 설정 코드이다.
위 코드를 통해 S3에 연결하였다.

@Value값을 사용해 yml파일에 있는 access key, secret key, region을 가지고와 빈 등록을 하고 연결을 해주었다.


import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.ObjectMetadata;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

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

@Service
@RequiredArgsConstructor
@Transactional
public class S3UploadService {

    private final AmazonS3 amazonS3;

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

    public String saveFile(MultipartFile multipartFile, String originalFilename) throws IOException {

        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentLength(multipartFile.getSize());
        metadata.setContentType(multipartFile.getContentType());

        amazonS3.putObject(bucket, originalFilename, multipartFile.getInputStream(), metadata);
        return amazonS3.getUrl(bucket, originalFilename).toString();
    }

    public void deleteImage(String originalFilename) {
        amazonS3.deleteObject(bucket, originalFilename);
    }

}

이미지에 관한 서비스 코드이다.

yml파일에서 s3 bucket 이름을 가지고와 사용했다.
saveFile 메서드는 multipartFile 즉, 이미지와 파일의 원본 이름을 파라미터로 받게하였다.
원본 파일 이름을 받는 이유는 만약 같은 이미지, 같은 이름을 가진 파일이 올라가면 하나의 이미지만 등록된다.

만약 각자 다른 곳에서 쓰여야할 이미지라면, 하나가 삭제되면 다른 하나도 사용을 못하게 되버리는 것이다.
그래서 랜덤 아이디를 원본 파일 이름에 붙여 저장하게 하였다.

putObject 메서드를 사용하여 s3 버킷, 원본 파일 이름, 이미지와, 이미지 정보를 파라미터로 넣어 업로드한다.

그 후 getUrl 메서드를 통해 파일 Url을 받아 DB에 저장했다.

삭제는 아래와 같이 deleteObject 메서드를 통해 삭제를 진행했다.

후기


참고한 블로그 덕분에 어렵지 않게 사용 방법을 배웠고 응용도 했다.

하지만 이 부분도 리팩토링을 진행해야한다.

서버의 입장에서 이미지를 업로드한다는 것이 부담이라고 한다.
그래서 프론트에서 이미지를 업로드 및 저장 후 URL을 서버에 보내 저장하는 형식이 보편적이라고 한다.

또한 Presigned URL을 사용해보라는 조언도 들었다.

S3에 직접 업로드하기 위해선 해당 S3에 접근 권한 인증을 해야한다.
이 접근 권한 인증을 마치면 업로드할 수 있는 URL을 발급해주는데 이것을 Presigned URL이라고 한다.

이 URL을 받은 사용자는 일정 기간 객체에 access 할 수 있다고 한다.

https://dev.classmethod.jp/articles/create-pre-signed-url-in-s3/

새로운 기술, 사용 방법에 대해 배우고, 멘토님에게 조언도 들으니 부족한 부분, 공부해야할 방향성 등 좋았다!

profile
ㅎㅎ

0개의 댓글