AWS - S3

박상은·2022년 4월 6일
0

🎁 분류 🎁

목록 보기
8/16

multer-s3를 이용해서 AWS S3에 이미지를 업로드/복사/삭제/이동하는 방법을 정리한 포스트입니다.
presignedURL에 대해서는 여기를 참고해주세요.

🤔 AWS S3와 사용이유

S로 시작하는 3가지 단어를 합쳐서 S3라고 부르는 것으로 설명하지만 본인은 제대로 이해하진 못했고 이미지 호스팅 방법을 찾다가 선택하게 되었습니다.

이미지를 서버 측에 컴퓨터에다가 저장할 수 있겠지만, 그렇게 처리하면 서버에서 이미지처리, DB처리, API요청 같은 많은 것을 혼자서 다 처리해야 하는 문제가 발생하기 때문에 방법을 찾다가 AWS-S3를 이용하게 되었습니다.

✒️ 준비 단계

  1. 사용자 생성 ( AWS가입 or IAM생성 )
  2. 버킷 생성 ( 버킷명, 지역, 접근권한 등 )
  3. 보안자격 증명에서 엑세스 키 생성

일단 프로젝트에서 사용하기위한 준비단계는 위 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);
  }
);

👏 multer와 같이 사용

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

0개의 댓글