이미지 업로드

seanical·2021년 11월 21일
2

경험

목록 보기
1/1

대용량 이미지, 동영상을 업로드시 백엔드 or 프론트엔드 누가 책임을 져야 할까?

Background

현재 회사는 GCP(구글 클라우드 플랫폼)를 사용하여 시스템을 운영하고있다.

사용자가 이미지 또는 파일 업로드시 어떤 과정을 거쳐야 할까?

  1. 브라우저에서 사용자는 이미지를 첨부파일에 넣는다.
  2. 첨부파일을 base 64로 인코딩 시켜준다. (base64의 문자열을 갖고있으면 이미지 객체를 갖고있을 필요없다)
    또는 이미지 객체 자체를 바로 스토리지에 업로드하는 방법도있다.
  3. base64를 바탕으로 GCS에는 올리는 모듈을 통해 업로드 한다.

논의 주제

어떤 서버에서 파일을 업로드해야하는 것인가?

일단 프론트엔드, 백엔드가 단독으로 담당했을때를 정리해봤습니다.

  1. 백엔드가 책임져야 하는 이유
  • 만약 프론트엔드가 직접 GCS(google cloud stroage)와 rest-api로 파일을 업로드할 경우
    - 프론트엔드에서 CREDENTIAL을 갖고있어야하고 노출 위험이 많다.
    • 만약 CREDENTIAL을 어떤 유저가 알게된다면 회사의 Storage에 마음대로 파일을 업로드 할 수있다.
  • 용량을 제한 할 수있다.
  • 어떤 유저가 올렸는지 추적 할 수 있다.

이런 단점들이 있기 때문에 백엔드에서 관리해야된다고 생각했다.

  1. 프론트가 책임져야 하는 이유
  • 서버 트래픽 낭비
    - 프론트엔드에서 그 무거운 파일을 백엔드한테 전달해주는 일은 결국 서버 트래픽을 낭비하는 것이다.
    • 만약 이미지 업로드 하는것이 빈번하게 일어난다면 서버 트래픽을 많이 잡아 먹어서 비효율적이다.

결론적으로 백엔드에서 처리 하는것이 맞다고 생각하여 위의 내용을 정리하여 올렸다.
하지만 사실상 리드개발자인 영욱님에게 피드백을 받아 다시 생각하는 계기를 갖었다.
(윽.. 엄청난 뼈와 살이되는 피드백 이런 것을 통해 더 성장해 나가는거죠..)

일단 내가 주장한 것에 앞서 GCS에서 어떤 기능을 제공하고있는지 제대로 문서를 안 읽어본 문제가 있었다.
보내주신 링크 signed_url를 공부해보며 다시 생각을 정리하였다.

GCS 에서는 signed_url 이라는 기능을 제공하고 있다.
쉽게 말하면 황금 열쇠이다. 누구나 이 열쇠로 받은 권한에 대해서 사용 할 수 있는 것이다.
구글에서는 다음과 같이 정의 하였다.

Google 계정 유무에 관계없이 서명된 URL을 가진 모든 사람에게 제한된 시간 동안 리소스 액세스 권한을 부여

결국 권한을 총 관리자가 권한을 부여할(객체 생성, 읽기, 삭제) 것을 정하고 서명하면 누군가가 와서 그 서명된 url을 통해 권한 받은 행동을 마음껏 제한 시간내에 할 수 있다.

sigend_url은 다음과 같은 것을 설정 할 수있다.

  • expire_time
  • 컨텐츠 타입 (img,video)
  • 컨텐츠 파일 크기 제한
  • 저장 장소

결론

결국 우리가 문제 삼았던 것은 signed_url을 통해 모든 문제를 해결 할 수 있었다.

sigend_url을 사용한 사례를 검색해보다가 잘 정리되어있는 것을 가져왔다.

출처


고생했던점

해당 sigend_url을 백엔드에서 발급해 주기 위하여 조금 고생했던 경험이 있어서 작성합니다.
우리는 이 signed_url을 테스트하기위하여 dev환경으로 테스트 하였습니다.

위에서 말한 sigend_url을 발급해주려면 최고 관리자가 서명을 해야해줘야 합니다.
결국 최고 관리자는 IAM에서 저장소 관리자를 갖고있어야 다른 사람에게 줄 서명 url을 만들 수 있다고 할 수 있겠죠.
하지만 저장소 관리자는 너무 많은 권한을 갖고 있는 친구입니다.

storage.objects.create
storage.objects.delete
storage.objects.get
storage.objects.getIamPolicy
storage.objects.list
firebase.projects.get
resourcemanager.projects.get
resourcemanager.projects.list
storage.buckets.create
storage.buckets.createTagBinding
storage.buckets.delete
storage.buckets.deleteTagBinding
storage.buckets.get
storage.buckets.getIamPolicy
storage.buckets.list
storage.buckets.listTagBindings
storage.buckets.setIamPolicy
storage.buckets.update
storage.multipartUploads.abort
storage.multipartUploads.create
storage.multipartUploads.list
storage.multipartUploads.listParts
storage.objects.setIamPolicy
storage.objects.update

너무 많은 권한을 할 수 있게 한 계정에게 주어지는것은 굉장히 위험하고 좋지 않습니다.
이런 점을 방지하고자 저희는 커스텀 권한을 생성해주었습니다.
저희가 딱 필요한 것은 storage.obejects.create , storage.buckets.get 의 권한입니다.
이 권한을 커스텀에 담아 권한을 생성해 주었고 원하는 signed_url을 발급 해줄 수 있었습니다.

마치며

우선 이 작업을 도와주신 인프라 마스터 병훈님께 감사합니다!
과연 노션같은 페이지는 파일을 올릴때 과연 백엔드가 업로드를 할 것인가? 라고 생각했을때 정답은 모르지만 아닐거라고 생각합니다.
특히 노션은 데이터 용량을 제한해 두지않아 그 높은 용량의 파일을 백엔드에 전송하여 트래픽을 감당하고 있지 않을것입니다.

결국 위와같은 방법과 비슷하게 로직을 처리 하고 있을것이라고 생각이 듭니다.
내가 사용하는 서비스의 문서를 제대로 읽어보는것이 중요하다고 느낀 사례인것 같습니다.

궁금하신점 있으시면 댓글 남겨주시면 답글 달아드리겠습니다!

2개의 댓글

comment-user-thumbnail
2022년 1월 9일

경험 공유 감사합니다!

1개의 답글