S3 Presigned URL을 사용하는 이유와 활용 방법에 대해 알아보고 정리하는 포스팅입니다.
s3 presigned url 이란
presigned url 의미 그대로 미리 서명된 url로 서버에서 AWS S3에 요청하여 presigned url을 발급 받을 수 있습니다.
즉 presigned url은 s3에 직접 파일을 업로드할 수 있도록 사전에 서명된 URL입니다.
그래서 발급 받은 presigned url을 가지고 클라이언트에서 s3로 직접 파일 업로드를 할 수 있습니다.
위 presigned url의 의미를 자세히 풀어보기 위해서 일반적인 파일 업로드 과정을 보자면
일반적인 파일 업로드 과정을 살펴보면 사용자가 이미지를 업로드할때 중간에 서버를 거치면서 파일을 전송합니다. 이때 1번 과정에서 만약 사용자가 업로드할 이미지 파일의 크기가 크다면 서버에 부담을 줄 수 있는 문제가 있습니다.
그래서 서버 부담의 문제를 줄이고자 서버에서는 s3의 presigned url을 발급받고 클라이언트에서 요청이 있으면 발급받은 presigned url을 클라이언트에 전달해주면 됩니다.
이렇게되면 클라이언트에서 서버를 거치지 않고 저장소에 직접 업로드를 할 수 있기 때문에 서버의 부담을 줄일 수 있습니다.

클라이언트에서 presigned url을 요청한다. (클라이언트 -> 서버)
서버는 s3에 presigned url 발급을 요청한다. (서버 -> s3)
s3에서 presigned url을 서버로 전달하고 클라이언트로 전달한다. (s3 -> 서버 -> 클라이언트)
클라이언트는 발급받은 presigned url로 s3에 파일을 직접 업로드한다. (클라이언트 -> s3)
클라이언트는 전달받은 presigned url을 통해 설정된 유효한 일정 시간 내 PUT 요청으로 s3에 직접 파일을 업로드 할 수 있습니다.
이미지 파일 업로드
// imageFile.ts
export const ImageUploadApi = async (prefix: string, file: File) => {
const fileId = nanoid();
const { data } = await clientAxios.get(`/api/files/presigned-url/${prefix}/${fileId}`);
const { preSignedUrl } = data.data;
const formatUrl = preSignedUrl.split("?")[0];
const upload = await axios.put(formatUrl, file, {
headers: {
"Content-Type": file.type,
},
});
return upload.request.responseURL;
};
await ImageUploadApi("profile", selectFile); // 프로필 이미지
await ImageUploadApi("thumbnail", selectFile); // 썸네일 이미지
await ImageUploadApi("editorImage", selectFile); // 에디터 첨부 이미지
이미지 파일을 업로드할때 해당 파일의 type별로 구분해서 이미지 파일을 저장합니다.

아래와 같이 업로드된 이미지 파일의 url 주소를 볼 수 있습니다.
// 업로드한 이미지 url
https://prod-momoim-bucket.s3.ap-northeast-2.amazonaws.com/thumbnail/199a1628-1edf-46d8-8ec0-07a297960c89-b7auIkMAo5XbgUn4-ZfYs