본문 바로가기
Web/Backend

[GCS] [번역] 브라우저에서 구글 클라우드 스토리지(GCS)로 파일 업로드하기

by r4bb1t 2020. 6. 1.
반응형

원글 | https://medium.com/imersotechblog/upload-files-to-google-cloud-storage-gcs-from-the-browser-159810bb11e3

 

Upload Files to Google Cloud Storage (GCS) From the Browser

After having spent the better part of a day struggling to upload files straight from the browser to GCS I felt the internet could do good…

medium.com

Papago와 짧은 영어 지식을 동원해서 번역했습니다. 오역한 부분이 있다면 알려주세요😏

 


브라우저에서 GCS로 파일을 직접 업로드하기 위해 하루 종일 애쓰면서 나는 인터넷이 결과를 설명하는 방법을 통해 좋은 결과를 낼 수 있다는 것을 느꼈다. 

 

배경 |

우리는 app.imerso.com 플랫폼의 파일들을 저장하기 위해 GCS를 쓴다. 하지만, 우리는 자체적인 인증방식을 사용하기 때문에 사용자들에게 구글 연결을 요구하지 않는다. 그래서 승인을 위해 표준 구글 API 클라이언트 라이브러리 자바스크립트를 사용할 수 없다. 대신 우리는 Signed URL을 사용하기로 했다.

 

해결책 |

업로드는 백엔드에서 승인하고, 파일 전송은 프론트엔드에서 GCS의 API로 직접 전송하여 인증된 사용자만 GCS 버킷에 파일을 업로드할 수 있게 하고 싶었다. 그래서 REST API에 사용자 인증 요청을 하고, REST API는 지정된 파일의 이름 및 Content-Type으로 PUT 요청을 하기 위한 URL에 서명한 후 Signed URL을 프론트엔드로 반환한다.

백엔드 |

우리의 백엔드는 스칼라(Scala)로 작성되어 있으며, Signed URL을 만들기 위해 아래 코드를 사용한다.

// contentType과 objectPath값은 프론트엔드에서 보내야 함
val contentType = "image/png"
val objectPath = "my-favorite-cat-photo.png"

val bucket = "my-cat-bucket"
val storage = StorageOptions.getDefaultInstance.getService
val blob = storage.create(
      BlobInfo.newBuilder(bucket, objectPath)
        .setContentType(contentType)
        .build()
    )

// <objectPath> 와 Content-Type "PUT"으로 파일 PUT에 유효한 Signed URL을 만듦. 하루 동안 유효함.
val urlPut = storage.signUrl(blob, 1, TimeUnit.DAYS, SignUrlOption.httpMethod(HttpMethod.PUT), SignUrlOption.withContentType())

GCP 프로젝트의 백엔드를 인증하기 위서비스 계정 키를 만들자. json 키를 생성한 후에는 서버의 키를 가리키도록 환경 변수를 설정하자.

GOOGLE_APPLICATION_CREDENTIALS=path/to/service-account/key.json

안 하면 storage.create가 StorageException를 뿜는다. 또 여기서 사용하는 서비스 계정이 "Object Creator" 또는 "Object Admin" 처럼 사용하는 버킷에 대한 올바른 권한을 가지고 있는지 확인하자.

 

프론트엔드 |

GCS는 GCS에 대해 두 가지 다른 API를 제공한다.

- XML-API
- JSON-API
불행하게도 (작성 당시 기준
으로) XML-API만 Signed URL을 지원하기 때문에 XML-API를 쓴다.

아래는 REST-API에서 제공하는 signed Url과 XML-API를 사용하여 파일을 업로드하는 코드이다.

const signedUrl = getSignedUrlFromBackend();

// this can be a file from e.g. <input type="file"/>
const file = getFileToUpload();

const xhr = new XMLHttpRequest();
xhr.open("PUT", signedUrl, true);
xhr.onload = () => {
  const status = xhr.status;
  if (status === 200) {
    alert("File is uploaded");
  } else {
    alert("Something went wrong!");
  }
};

xhr.onerror = () => {
  alert("Something went wrong");
};
xhr.setRequestHeader('Content-Type', file.type);
xhr.send(file);

브라우저에서 이 기능을 실행하려면 백엔드 코드에 지정된 버킷에 올바른 CORS 설정이 있는지 확인해보자. (gsutil로 CORS 설정 확인하기 : gsutil cors get gs://<your-bucket>)

[
  {
    "maxAgeSeconds": 3600,
    "method": ["GET", "HEAD", "PUT"],
    "origin": [<http://your-super-awesome-domainz.gov>],
    "responseHeader": ["Content-Type", "Access-Control-Allow-Origin"]
  }
]

끝이다. 누군가 유용하다고 생각했으면 좋겠다!

반응형

댓글