Presigned URL
Pre-signed URL은 AWS S3에 이미지를 업로드할 때, 해당 S3의 접근 권한 인증을 마친 후 발급받는 URL이다.
사용 이유
1. 프론트에서 서버를 거치지 않고 S3에 직접 파일을 업로드하기 때문에
서버가 업로드 요청을 처리하는 데 필요한 리소스를 절약할 수 있다.
2. 백엔드에서 권한 설정을 한 url이기 때문에 보안이 강화된다.
전체 아키텍처
1. 클라이언트에서 서버에 presigned URL 요청 (POST)
2. 서버는 이 요청을 S3에 전달
3. S3는 새로운 presigned URL을 서버에 반환
4. 서버는 다시 이 presigned URL을 클라이언트에 전달
5. 클라이언트는 사용자가 선택한 파일을 S3에 직접 업로드 (PUT)
6. 클라이언트는 업로드가 완료되었음을 알리는 요청을 서버에 전달
POST 요청
export const postPresignedURL = async (fileName: string) => {
const response = await fetch(`${API_BASE_URL}/users/presigned-url`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
fileName
})
});
if (!response.ok) {
throw new Error('AWS S3 에서 presigned URL 응답 실패');
}
return response.json();
};
서버에 요청을 보내면 아래와 같은 presigned URL을 반환받는다.
PUT 요청
export const uploadFileToS3 = async (presignedURL: string, file: File) => {
const response = await fetch(presignedURL, {
method: 'PUT',
body: file
});
if (!response.ok) {
throw new Error('AWS S3로 파일 업로드 실패');
}
// PresignedURL에서 ?앞 부분이 파일 url
return presignedURL.split('?')[0];
};
전달받은 presigned URL을 이용해 클라이언트에서 이미지 파일을 S3에 바로 업로드한다.
이때 이미지를 특정한 위치(정해진 presigned URL)에 저장하기 때문에 POST가 아닌 PUT 메서드를 사용한다.
정리 - 구현 코드
const UploadImageToS3 = async (file: File) => {
try {
const { presignedURL } = await postPresignedURL(file.name);
const fileUrl = await uploadFileToS3(presignedURL, file);
return fileUrl;
} catch (error) {
console.error('파일 업로드 에러:', error);
throw error;
}
};
const handleImageUpload = async (
e: React.ChangeEvent<HTMLInputElement>
) => {
if (!e.target.files) return;
const file = e.target.files[0];
if (file) {
try {
const fileUrl = await UploadImageToS3(file);
setProfileImg(fileUrl);
} catch (error) {
console.error('이미지 업로드 중 오류 발생:', error);
}
}
};
1. postPresignedURL에 file.name을 전달해 S3에서 사용할 Presigned URL을 생성한다.
이 file.name은 S3에서 저장할 파일 이름으로 사용된다.
2. uploadFileToS3에 Presigned URL과 file을 넘겨 file url을 전달받는다.
이 file url은 Presigned URL에서 ?앞 부분 -> presignedURL.split('?')[0]으로
클라이언트에서 이미지를 미리 보기 위해 사용되며, 실제로 S3에 저장된 이미지의 경로를 나타낸다.
참고
https://medium.com/developing-koan/uploading-images-to-s3-from-a-react-single-page-application-45a4d24af09f
'React' 카테고리의 다른 글
React-Hook-Form 알아보기 - useForm / useFormContext (1) | 2024.06.28 |
---|