프로젝트

AWS S3 Client side에서 이미지 업로드하기

Campkim 2021. 11. 17. 03:47

진행중인 프로젝트에서 이미지 저장용으로 S3를 사용해보려고 한다.

S3 뜻은 별거없다 Simple Storage Service. S가 3개라... S3....

 

이미지 업로드에서 중점적으로 고민하고 있는 부분 중 하나는 서버에 I/O작업을 줄이고 최대한 부하를 덜어내는 방향을 우선적으로 채택하는 것이다. 현재 상황에서는 소켓통신과 실시간 위치계산 등으로 앞으로도 더 많은 resource가 서버에서 필요할 것 으로 예상되고 데이터 전송의 Cost도 만만치 않다. 

 

그래서 이미지 관련해서는 Client browser에서 직접 S3로 업로드 하고 url 만 RDB에 저장하는 방식을 사용해보기로 했다.

express 에서 multer를 사용하여 Client쪽에서 서버로 이미지를 먼저 보내고, 서버에서 S3로 업로드 하는 방법은 다른 상황에서 사용되어야 할 것 같다.

 

문제는 S3 AWS접근 권한을 Server만 가지고 있는 부분이었다 업로드는 클라이언트가 해야하는데 권한을 그대로 넘겨주면 안된다. 찾아보다가 AWS-SDK에서 관련하여 지원하는 방식이 있었다. 서명된 url을 클라이언트에서 요청하고 일정 시간내에 업로드하고 url주소를 DBV에 저장하는 방식을 사용할 수 있었다. 아래 그림과 같다.

 

  const handleSubmit = async (e) => {
    e.preventDefault();
    
    //1. 서버로부터 서명된 URL 요청
    const res = await api.get("/main/s3Url"); 
    
    console.log("url", res.data.url);
    const { url } = res.data;
    console.log(url);


    //2. post the image direclty to the s3 bucket
    if (authImage) {
      await fetch(url, {
        method: "PUT",
        headers: {
          "Content-Type": "multipart/form-data",
        },
        body: authImage[0],
      });
    }
    const imageUrl = url.split("?")[0];
    console.log(imageUrl);

    const resp = {
      user_info_id: alien.alien.user_info_id,
      Alien_id: alien.alien.id,
      Challenge_id: alien.alien.Challenge_id,
      comment: authMessage,
      imgURL: imageUrl,
    };

    //3. post requst to my server to store any extra data
    const result = await api.post("/challenge/auth", resp);  //
    console.log(result);
  };

 

S3에서 Object는 Key로 식별할 수 있다.

The object key (or key name) uniquely identifies the object in an Amazon S3 bucket. Object metadata is a set of name-value pairs. For more information about object metadata, see Working with object metadata. When you create an object, you specify the key name, which uniquely identifies the object in the bucket.

 

새로운 이미지 upload와 update API는 비슷하지만 살짝 다른 방식으로 구현해보려고 한다. 

지금 우선 고민되는 부분은

1. 서명된 url 요청시 createPresignedPost 를 사용할지, getSignedUrl을 사용하여 url을 생성할지.

createPresignedPost가 조금 더 요청을 customizing가능하지만 Client쪽에서 해줘야 하는 것들이 있다. 가능한 Client쪽에서 최소정보만 가지고 업로드 가능하도록 하면서 리소스에 대한 정보는 노출되지 않는 방향으로 해보려고 한다.

2. client쪽에서 이미지 접근시 Cloudfront를 이용하게 할지, 퍼블릭으로 image접근이 가능하도록 할지.

 

+추가 (11.18)

사실 더 고민했어야 하는 방향은 어떤식으로 이미지를 resizing 해야 하는지였다. 왜냐하면 현재 상황에서는 불필요하게 고용량의 사진들이 나의 S3에 끊임없이 저장되기 때문이다. 비용적인측면, 사진 다운로드 속도 측면에서 비효율 적이다.

사실 실제로 서비스 운영에 필요한 이미지 용량은 1/5~1/10 정도에 불과하다. 

 

이 부분은 지금 알고있는 바로는 3가지 정도 옵션이 있는데,

하나는 Image proxy 서버로 리사이징 하는것 

두번째는 Image size를 validation하는 로직을 만들어서 client가 제한 용량을 초과하는 이미지를 업로드하려고 하면 반려하는 방법

세번째는 그냥 무지성으로 다 업로드하게 허용하고 이미지 로드시 리사이징 하는법 

 

세번째가 제일 쉽다 근데 돈이 쫌 나갈 수도 있다... 어차피 바뀌어야 하는 방향인듯.. 

 

https://stackoverflow.com/questions/52656085/aws-s3-createpresignedpost-vs-getsignedurl-which-one-should-i-use-for-uploading

 

AWS S3 createPresignedPost vs getSignedUrl. Which one should I use for uploading various files from client side?

On S3 document, there is createPresignedPost and getSignedUrl. On getSignedUrl: Note: Not all operation parameters are supported when using pre-signed URLs. Certain parameters, such as

stackoverflow.com

https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#createPresignedPost-property

 

Class: AWS.S3 — AWS SDK for JavaScript

The modular AWS SDK for JavaScript (v3), the latest major version of AWS SDK for JavaScript, is now stable and recommended for general use. For more information, see the Migration Guide and API Reference. Class: AWS.S3 Inherits: AWS.Service Object AWS.Serv

docs.aws.amazon.com

https://github.com/codyseibert/youtube/blob/master/s3-upload-example/index.html

 

GitHub - codyseibert/youtube: code from my youtube channel

code from my youtube channel. Contribute to codyseibert/youtube development by creating an account on GitHub.

github.com

https://s3.console.aws.amazon.com/s3/object/namu-alien-s3?region=ap-northeast-2&prefix=namu-alien 

 

https://s3.console.aws.amazon.com/s3/object/namu-alien-s3?region=ap-northeast-2&prefix=namu-alien

 

s3.console.aws.amazon.com

https://velog.io/@metamata/AWS-S3-CloudFront%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-CDN-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0

 

AWS S3, CloudFront를 이용한 CDN 구축하기

Amazon CloudFront는 .html, .css, .js 및 이미지 파일과 같은 정적 및 동적 웹 콘텐츠를 사용자에게 더 빨리 배포하도록 지원하는 웹 서비스CloudFront는 엣지 로케이션이라고 하는 데이터 센터의 전 세계

velog.io