카페24같은 쇼핑몰 홈페이지 서비스를 react 없이 바닐라 자바스크립트로 구현해 보고 있다
구현하는 과정에서 사용한 aws s3사용법을 작성하려고 한다
사용을 시작할 땐 간단한 줄 알았는데 아니었다...
참고
amazon 웹 서비스 중 이미지 등 파일 저장하고 접근 가능한 url을 제공하는 서비스
버킷이란 파일들을 담을 버킷이라는 storage 공간

로그인 없이도 안전하게 권한 설정을 도와주는 서비스




@aws-sdk/client-s3: S3 관리 SDK 라이브러리@aws-sdk/credential-provider-cognito-identity: 권한 인증용npm i @aws-sdk/client-s3 @aws-sdk/credential-provider-cognito-identity
주의
aws-sdk 라이브러리는 v2@aws-sdk/client-s3 라이브러리는 v3 <main id="admin">
<input id="s3-image-input" type="file" accept="image/*" />
<button id="s3-button" type="submit">url 생성</button>
<p id="s3-url-result">접근 URL: </p>
<div class="image-container">
<img id="s3-image-preview" src="" alt="업로드 이미지 미리보기">
</div>
</main>
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { fromCognitoIdentityPool } from "@aws-sdk/credential-provider-cognito-identity";
// S3 객체 생성 및 환경 설정
const s3 = new S3Client({
region: "ap-northeast-2",
credentials: fromCognitoIdentityPool({
clientConfig: { region: "ap-northeast-2" },
identityPoolId: import.meta.env.VITE_AWS_S3_IDENTITY_POOL_ID,
}),
});
// AWS S3 요청 시 보내는 파라미터 객체를 반환하는 함수
async function getUploadParams (file) {
// S3에 올릴 파일 전처리
const arrayBuffer = await file.arrayBuffer();
const body = new Uint8Array(arrayBuffer);
// 버킷 내부에 products라는 디렉토리에 파일 이름이 겹칠 것을 염두해 업로드 시각을 이름에 포함 시킴
const fileName = `products/${Date.now()}-${file.name}`;
return {
Bucket: import.meta.env.VITE_AWS_S3_BUCKET_NAME,
Key: fileName,
Body: body,
ContentType: file.type,
};
}
// S3로 파일 업로드 후 URL return
export async function uploadFileToS3(file) {
const uploadParams = await getUploadParams(file)
try {
const command = new PutObjectCommand(uploadParams);
await s3.send(command);
const fileUrl = `https://${uploadParams.Bucket}.s3.ap-northeast-2.amazonaws.com/${uploadParams.key}`;
console.log("[SUCCESS] ", fileUrl);
return fileUrl;
} catch (err) {
console.error("[ERROR] ", err);
throw err;
}
}
// 업로드드 버튼 이벤트 설정
// 업로드 후 url, image 미리보기 화면에 띄우기
document.getElementById("s3-button").addEventListener("click", async () => {
const imageInput = document.getElementById("s3-image-input");
const resultPara = document.getElementById("s3-url-result");
const imgPreview = document.getElementById("s3-image-preview");
const file = imageInput.files[0];
if (!file) return;
try {
const url = await uploadFileToS3(file);
resultPara.textContent = "접근 URL: " + url;
imgPreview.src = url;
} catch (error) {
console.error(error);
}
});
aws.js:36 업로드 실패: TypeError: readableStream.getReader is not a function
Body: file 그대로 넣었다body에 담긴 파일 형태가 nodejs에서 ReadableStream으로 변환되지않아 타입 에러를 일으켜 형식을 바꿔줘야한다고 했다blob -> uint8array로 타입을 변환해 주라는 글이 라이브러리 이슈페이지에 있어서 해보니 해결됐다ㅎㅎ const arrayBuffer = await file.arrayBuffer();
const body = new Uint8Array(arrayBuffer);
실패: TypeError: Failed to fetch
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "PUT", "POST", "HEAD"],
"AllowedOrigins": ["*"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3000
}
]
