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(이미지명);