Springboot + GCP Cloud Storage 연동(파일 업로드, 다운로드)

회원 정보 수정에서 썸네일 업로드가 필요했습니다.

파일을 Gloud에 저장하여 업로드 및 다운이 필요했기에 현재 사용하고 있는 Google Cloud Platform을 선택하였습니다.

 

적용하는데 발생한 이슈위주로 적는 글이라, 자세한 설정은 아래 블로그를 참조해주세요.

jyami.tistory.com/54

 

GCP Cloud Storage + Springboot 연동하기

이번 외주를 맡은 내용이 Google Cloud Storage를 이용해서 file을 업로드, 다운로드하는 API 기능을 구현해서 이 내용을 정리하고자 한다. Cloud Storage를 다루는 방법으로 Google Cloud Console, Cloud SDK를..

jyami.tistory.com

설정

gradle 설정을 다음과 같이 했습니다.

dependencies {
    
    ...
    
    1.
    // implementation 'org.springframework.cloud:spring-cloud-gcp-starter'
    // implementation 'org.springframework.cloud:spring-cloud-gcp-starter-storage'
    
    2.
    // compile group: 'org.springframework.cloud', name: 'spring-cloud-gcp-starter'
    // compile group: 'org.springframework.cloud', name: 'spring-cloud-gcp-starter-storage'
    
    3.
    // implementation group: 'com.google.cloud', name: 'google-cloud-storage', version: '1.111.2'
    // implementation group: 'com.google.cloud', name: 'spring-cloud-gcp-core', version: '2.0.1'
    // implementation group: 'com.google.cloud', name: 'spring-cloud-gcp-starter', version: '2.0.1'
    
    4.
    implementation group: 'org.springframework.cloud', name: 'spring-cloud-gcp-starter', version: '1.2.5.RELEASE'
    implementation group: 'org.springframework.cloud', name: 'spring-cloud-gcp-storage', version: '1.2.5.RELEASE'

   	...
}
  • 구글링으로 나온 1번 or 2번처럼 라이브러리를 추가해도 적용이 되지 않았습니다.
    • " import com.google.cloud.* "를 불러오질 못했습니다.
  • 결국, 수동으로 라이브러리를 찾아야 됬었는데, 3번의 시행착오 끝에 4번 형식의 라이브러리 적용 코드를 찾았습니다.
    • spring boot 2.3.7 버전을 사용했습니다. 혹시라도 의존성 충돌이 일어날까봐 2.3.X가 출시된 이후 나온 gcp-** 버전을 적용하였습니다.
    • maven repository에서 검색 후 적용하였습니다.

전체 라이브러리

 

spring:
  cloud:
    gcp:
      storage:
        credentials:
          location: classpath:{서비스 key파일 이름}.json
  • gradle에서 적용이 잘되었다면, application.yml에 위와같이 등록을 할 수 있습니다.
    • 만약, 밑줄이 뜨거나 자동완성으로 뜨지 않았다면 라이브러기가 정상적으로 등록이 되지 않은겁니다.
  • 이렇게하면 Spring Boot에서 자동으로 {서비스 key파일 이름}.json을 읽어 Storage에 자동으로 @Autowired를 해준다고 합니다. 하지만 왜 그런지 @Autowired가 되지 않아서 .json 파일또한 수동으로 설정을 해야 했습니다.

파일 업로드

// Controller
@PostMapping(value = "/{id}/upload")
    public ResponseEntity<?> uploadToStorage(
        @RequestBody UploadReqDto uploadReqDto
    ){

        BlobInfo blobInfo = userService.uploadFileToGCS(uploadReqDto);
        log.info("blobInfo : " + blobInfo);

        return ResponseEntity.status(HttpStatus.OK)
            .body(ResponseTemplate.create(
                "Gdc"
            ));
    }
    
    
// Dto
public static class  UploadReqDto {
    private String bucketName;
    private String uploadFileName;
    private String localFileLocation;
}
  • Controller / Dto 코드 입니다.
    public BlobInfo uploadFileToGCS(UploadReqDto uploadReqDto){
        try{
            String keyFileName = ".json 파일명";
            InputStream keyFile = ResourceUtils.getURL("classpath:" + keyFileName).openStream();

            Storage storage = StorageOptions.newBuilder().setProjectId("nosell")
               // Key 파일 수동 등록
               .setCredentials(GoogleCredentials.fromStream(keyFile))
               .build().getService();

            BlobId blobId = BlobId.of(uploadReqDto.getBucketName(), uploadReqDto.getUploadFileName());
            BlobInfo blobInfo = BlobInfo.newBuilder(blobId)
                .setAcl(new ArrayList<>(Arrays.asList(Acl.of(Acl.User.ofAllUsers(), Acl.Role.READER))))
                .build();
                
            Blob blob = storage
                .create(blobInfo, new FileInputStream(uploadReqDto.getLocalFileLocation()));
                
            return blob;
        }catch(IOException e){
            log.error(e.getMessage());
            e.printStackTrace();
        }
        return null;
    }
  • resources 폴더 바로 밑에 있는 .json 파일의 경로를 가져온 뒤 key 파일을 수동으로 등록하였습니다.
  • 암호화 하지 않는 storage.create() 메소드는 google-cloud-storage.1.111.2 에서(1.111.2 부터인지는 모르겠습니다) deprecated() 되었습니다. 일단 작동은 잘되니 추후 수정해야겠습니다.

 

 

  • 루트 바로 밑에있는 upload폴더에 존재하는 파일을 스토리지에 올리는 방식입니다.
  • 향후, 클라이언트에서 등록한 파일을 바로 스토리지에 올리는 방식이 존재하는지 찾아봐야겠군요.

 

  • PostMan 요청은 다음과 같습니다.

 

 

  • 실행 중간에 이 에러가 왜 뜨는지 잘 모르겠습니다.. 실행이 아예 멈추진 않았지만 찝찝하네요...

 

파일 다운로드 & 화면단 뷰어

jsikim1.tistory.com/27

 

Google Cloud Storage Bucket 개체 공개 액세스 변경 (allUsers 뷰어 권한 부여)

Google Cloud Storage Bucket 개체 공개 액세스 변경 (allUsers 뷰어 권한 부여) Google Data Studio의 Community Visualizations 을 직접 만들어 사용하거나 공개하고 싶을때와 같이 Google Cloud Pl..

jsikim1.tistory.com

공개액세스로 변경했다면

https://storage.googleapis.com/{Bucket Name}/{파일경로}/{파일명}.확장자 

로 다운로드 할 수 있습니다.

 

화면단에서 보여줄라면 img 태그의 src에 링크만 넣어주면 된다.

  <img src={image_url} alt=""/>

 

참조

www.programcreek.com/java-api-examples/?class=com.google.cloud.storage.BlobInfo&method=getMediaLink

mingpd.github.io/2019/03/12/develop/java-google-api/

docs.spring.io/spring-cloud-gcp/docs/1.2.6.RELEASE/reference/html/#spring-cloud-gcp-core

cloud.google.com/storage/docs/uploading-objects?hl=ko#storage-upload-object-java

stackoverflow.com/questions/41880371/com-google-cloud-storage-storageexception-401-unauthorized

r4bb1t.tistory.com/29

stackoverflow.com/questions/39820128/google-cloud-storage-image-public-link-to-img-src