
multer-s3를 이용해서AWS S3에 이미지를 업로드/복사/삭제/이동하는 방법을 정리한 포스트입니다.
presignedURL에 대해서는 여기를 참고해주세요.
S로 시작하는 3가지 단어를 합쳐서 S3라고 부르는 것으로 설명하지만 본인은 제대로 이해하진 못했고 이미지 호스팅 방법을 찾다가 선택하게 되었습니다.
이미지를 서버 측에 컴퓨터에다가 저장할 수 있겠지만, 그렇게 처리하면 서버에서 이미지처리, DB처리, API요청 같은 많은 것을 혼자서 다 처리해야 하는 문제가 발생하기 때문에 방법을 찾다가 AWS-S3를 이용하게 되었습니다.
일단 프로젝트에서 사용하기위한 준비단계는 위 3가지가 끝입니다.
1, 2번까지만 하면 코드상으로 말고 직접 이미지를 넣어서 오브젝트를 생성할 수 있습니다.
3번은 코드로 이미지CRUD요청을 할때 접근권한을 확인하기 위해서 다운받는 csv파일이며, 엑세스키와 시크릿키가 적혀있습니다.
npm i aws-sdk
import AWS from "aws-sdk";
import fs from "fs";
const config = {
region: process.env.AWS_REGION,
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECRET_KEY,
}
// 둘 중에 어디에 키를 적용해도 상관없었음
AWS.config.update(config);
const S3 = new AWS.S3(config);
// S3에 이미지 생성
s3.upload(
{
Bucket: "blemarket", // 실제 생성한 버킷 이름
Key: "images/cat", // 생성할폴더명/생성할파일명...
Body: fs.readFileSync("dog.jpg"), // 실제로 넣어줄 데이터 ( 현재는 이미지 파일 )
ContentType: "image/jpg", // 넣어줄 파일의 타입 ( input[type=file]로 읽으면 내부에 타입이 있음 )
},
{},
(error, data) => { // 성공 or 실패값 ... 여기 콜백이 존재하지 않으면 성공/실패 여부와 관계없이 정상적으로 작동하지 않음
console.log("error >> ", error);
console.log("data >> ", data);
}
);
npm i aws-sdk multer multer-s3
import AWS from "aws-sdk";
AWS.config.update({
region: process.env.AWS_REGION,
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECRET_KEY,
});
const S3 = new AWS.S3();
export default S3;
// 모든 이미지들은 `/images/{환경}/{이미지이름_현재시간}`으로 저장합니다. ( 환경: `development` or `production` )
export const getPhotoPath = (filename: string) => `images/${process.env.NODE_ENV}/${filename}_${Date.now()}`;
// multer와 multer-s3를 이용한 이미지 생성
import multer from "multer";
import multerS3 from "multer-s3";
export const upload = multer({
storage: multerS3({
s3: S3,
bucket: "blemarket",
key(req, file, cb) {
// 확장자 제외한 이미지명 가져오기
const filename = file.originalname.split(".")[0];
// 두 번째 인자로 생성할 이미지명을 넘겨주면 된다.
cb(null, getPhotoPath(filename));
},
}),
limits: { fileSize: 1 * 1024 * 1024 }, // 1mb
});
// S3 이미지 제거
export const deletePhoto = (photo: string) =>
S3.deleteObject(
{
Bucket: "blemarket",
Key: photo,
},
(error, data) => {
if (error) {
console.error("error >> ", error);
}
}
).promise();
// S3 이미지 이동
export const copyPhoto = (originalSource: string) =>
S3.copyObject(
{
Bucket: "blemarket",
CopySource: "blemarket/" + originalSource,
Key:
originalSource.slice(0, originalSource.lastIndexOf("/")) +
"/remove" +
originalSource.slice(originalSource.lastIndexOf("/")),
},
(error, data) => {
if (error) {
console.error("error >> ", error);
}
}
).promise();
export const movePhoto = async (photo: string, location: PhotoKinds) => {
try {
await copyPhoto(photo);
await deletePhoto(photo);
} catch (error) {
console.error("movePhoto >> ", error);
}
};
// multer에서 처리하고 나면 "req.file" or "req.files"에 생성된 이미지의 정보가 담겨있다.
// single, array 등의 메서드 사용 가능
app.post(upload.single("photo"), (req, res) => {
res.json({
ok: true,
message: "AWS S3에 이미지를 업로드 성공했습니다.",
//@ts-ignore
photo: req.file.key,
});
});
copyPhoto(이미지명);
deletePhoto(이미지명);