문제상황

결론

1) 클라이언트가 이미지 전송 → 서버가 object storage에 업로드 → 서버가 url DB에 저장

단점. 업로드가 전적으로 서버에게 맡겨지는 것이기 때문에, 서버의 부하가 존재할 수 있을 것 같다.

2) 클라이언트가 서버에게 signed request url 요청 → 받아온 후 object storage에 업로드 → 서버에게 url 전달

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

export const makeSignedURL = (S3:AWS.S3, contentHash:String, musicName:String):string =>{
    const params = {Bucket: 'xoxo', Key: `${contentHash}/${musicName}`, Expires: 60};
    const url = S3.getSignedUrl('putObject', params);
    return url;
}
const getSignedURL = async (request: Request, response: Response, next: NextFunction) => {
    const { contentTypes } = request.body;
    const presignedData = await Promise.all(
      contentTypes
        .filter((type: string) => ['png', 'jpg', 'jpeg', 'webp'].includes(String(extension(type))))
        .map(async (type: string) => {
          const fileExtension = extension(type);
          const key = `${uuid()}.${fileExtension}`;
          const presignedURL = await s3.getSignedUrlPromise('putObject', {
            Bucket: process.env.NCP_BUCKET_NAME,
            Key: `raw/${key}`,
            Expires: 60,
            ContentType: type,
            ACL: 'public-read',
          });
          return { presignedURL, key };
        }),
    );
    response.json(succeed(presignedData));
}

이런식으로 서버가 signed url을 만들어서 클라이언트가 요청하면 내려주는 것.

(서버가 올릴 파일에 대한 경로와 이름을 다 설정한 url을 내려주고, 클라이언트는 그걸 받아서 파일만 업로드 하는 것임!)

단점. 아무래도 보안에 있어서 좀 취약해질 수도 있을 것 같다. (누군가가 url을 탈취한다면 기존 파일의 이름과 경로가 동일한 파일을 업로드 할 수 있음⇒파일이 덮어써질 가능성이 있음)

https://campkim.tistory.com/66

https://aws.amazon.com/ko/blogs/compute/uploading-to-amazon-s3-directly-from-a-web-or-mobile-application/