GDSC 1차프로젝트(3) - S3 사용하기

chaejm55·2023년 9월 2일
1

GDSC-KNU-2nd-Backend

목록 보기
9/10

GDSC 1차 프로젝트(네컷앨범 고도화) 세 번째 게시물입니다.

S3 버킷 생성, IAM 계정 생성 등에 대한 부분은 생략하겠습니다.

1. S3 API 알아보기

https://docs.aws.amazon.com/ko_kr/sdk-for-java/v1/developer-guide/examples-s3-objects.html

위 링크의 AWS SDK for Java1.x 공식 문서를 참조하였습니다. 예제 코드를 바탕으로 서비스를 구현하였습니다.

2. S3Service.java 코드 작성하기

앱에 사진 수정 기능은 구현하지 않으므로, 수정을 제외한 기능을 서비스로 구현하였습니다.

1) 업로드

S3ServiceImpl.java

@Slf4j
@RequiredArgsConstructor
@Service
public class S3ServiceImpl implements S3Service {

    private final AmazonS3 amazonS3Client;

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

    @Override
    public String upload(String base64, String fileName) {
        boolean result = decode(base64, fileName);
        System.out.println(result);
        File uploadFile = new File(fileName);

        amazonS3Client.putObject(new PutObjectRequest(bucket, fileName, uploadFile).withCannedAcl(CannedAccessControlList.PublicRead));
        // remove new temp file
        if (uploadFile.delete()) {
            log.info(uploadFile.getName() + "로컬 이미지 파일이 삭제 되었습니다.");
        } else {
            log.info(uploadFile.getName() + "로컬 이미지 파일이 삭제 되지 못했습니다.");
        }

        return amazonS3Client.getUrl(bucket, fileName).toString();
    }
 }
  • AmazonS3 amazonS3Client: S3 사용을 위한 클라이언트입니다.
  • String bucket: .yml에서 버킷이름을 가져옵니다.
  • String upload(): 안드로이드 클라이언트로부터 받은 base64문자열을 디코딩합니다.
  • amazonS3Client.putObject(): S3 버킷에 이미지 파일을 업로드합니다.

2) 다운로드

S3ServiceImpl.java

@Slf4j
@RequiredArgsConstructor
@Service
public class S3ServiceImpl implements S3Service {

...
    private final TransferManager transferManager;
...

    @Override
    public void downloadDirectory(String prefix, String localDirectoryPath) {
        File localDirectory = new File(localDirectoryPath);

        try {
            MultipleFileDownload downloader = transferManager.downloadDirectory(
                    bucket, prefix, localDirectory);
            downloader.waitForCompletion();


            log.info(downloader.getDescription());
        } catch (Exception e) {
            log.info(e.getMessage());
        }
    }
 }
  • TransferManager transferManager: S3 객체 다운로드를 위해 사용합니다.
  • downloadDirectory(): 다운로드 받을 로컬 주소를 지정해 S3에서 디렉토리의 개체를 전부 다운로드합니다.

3) 삭제

S3ServiceImpl.java

@Slf4j
@RequiredArgsConstructor
@Service
public class S3ServiceImpl implements S3Service {

...

    @Override
    public void delete(String key) {
        if (amazonS3Client.doesObjectExist(bucket, key)) {
            try {
                amazonS3Client.deleteObject(new DeleteObjectRequest(bucket, key));
                log.info(key + ": s3 객체 삭제에 성공했습니다.");
            }
            catch (Exception e) {
                log.info(key + ": s3 객체 삭제에 실패했습니다.");
                log.info(e.getMessage());
            }
        }
    }
  • delete(): S3 객체의 key를 전달 받아 버킷의 객체를 삭제합니다.
  • amazonS3Client.doesObjectExist(): 해당 key의 객체의 존재 여부를 확인한 후 삭제합니다.

3. 애먹었던 오?류

사실 delete() 구현에는 굉장히 시간을 많이 썼습니다... 다름아닌 권한 문제 때문이었습니다. 블로그에 많이 적힌 것들 처럼 S3 버킷 - 권한 - 버킷 정책 JSON 파일을 수정해서 모든 권한을 주기도 하고, delete 권한만 따로 주기도 하고 무슨 짓을 해도 안 되던 오류가 발생해서 코드도 고쳐보고 다 했으나 되지 않았습니다...

그렇게 삽질을 하던결과 IAM 계정 자체의 권한 문제였습니다. 저는 IAM 계정에 AmazonS3FullAccess 정책을 연결했으나, 그 이전에 생성 시 연결된 다른 정책에 삭제 권한을 Deny하는 정책이 있어 권한이 없던 것이었습니다. 다음부턴 이런 권한 충돌이 일어나지 않는지 잘 살펴보고 IAM 정책 설정을 해야한다는 것을 깨달았습니다. ㅠㅠ

4. 추후 개선 방안

  • 버킷 및 객체를 지정된 사용자만 접근 가능하도록 pre-signed 등 방법 적용해보기
  • 정교한 test 코드를 작성하여 서비스 유지보수 용이하게 하기

5. 결과물 링크

https://github.com/GDSC-KNU/4CutAlbum-server

profile
여러가지를 시도하는 학생입니다

0개의 댓글