๐Ÿ–จ๏ธ AWS - S3 ํŒŒ์ผ ๋ณต์‚ฌ ์ค‘ ๋ฐœ์ƒํ•œ ๋ฌธ์ œ ( copyObject )

ํ˜„์žฌ ํ”„๋กœ์ ํŠธ์—์„œ ์ •์ ์ธ ์ด๋ฏธ์ง€ํŒŒ์ผ๋“ค์€ AWS S3๋ฅผ ์ด์šฉํ•ด์„œ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๋ฐœ์ƒํ•œ ๋ฌธ์ œ

์ฒ˜์Œ S3.copyObject()๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” Access Denied๊ฐ€ ๋ฐœ์ƒํ•˜๊ธธ๋ž˜ ๋ฒ„ํ‚ท ์ •์ฑ…์ด๋‚˜ ์ ‘๊ทผ ๊ถŒํ•œ์„ ์ œ๋Œ€๋กœ ๋ถ€์—ฌ ์•ˆ ํ•ด์คฌ๋‹ค๊ณ  ์ฐฉ๊ฐํ•ด์„œ ๊ตฌ๊ธ€๋ง์„ ํ•˜๋ฉด์„œ ์ด๊ฒƒ์ €๊ฒƒ ์ž…๋ ฅํ•ด ๋ณด๋ฉด์„œ ๊ณ„์† ํ…Œ์ŠคํŠธ๋ฅผ ํ–ˆ์Šต๋‹ˆ๋‹ค.
๋ญ˜ ์ž…๋ ฅํ•ด๋„ ๊ณ„์† Access Denied๊ฐ€ ๋ฐœ์ƒํ•˜๊ธธ๋ž˜ ๋ญ๊ฐ€ ๋ฌธ์ œ์ธ์ง€ ํ•œ์ฐธ ์ฐพ๋‹ค๊ฐ€ ์—ฌ๊ธฐ์—์„œ ํžŒํŠธ๋ฅผ ์–ป์–ด์„œ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

Access Denied๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ด์œ ๊ฐ€ ๊ถŒํ•œ ๋ฌธ์ œ์ผ ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์ž˜๋ชป๋œ ๊ฒฝ๋กœ๋ฅผ ์ž…๋ ฅํ•  ๊ฒฝ์šฐ์—๋„ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ์œผ๋กœ ์ดํ•ดํ–ˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์ •ํ™•ํ•œ ์ด์œ ๋Š” ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ copyObject()๋ฅผ ํ•  ๋•Œ๋Š” Key์— ๋ฒ„ํ‚ท๋ช…/๋„ ๋ถ™์—ฌ์ค˜์•ผ ์ •์ƒ์ ์œผ๋กœ ๊ฒฝ๋กœ๋ฅผ ์ธ์‹ํ•ฉ๋‹ˆ๋‹ค.
์ด ๋ถ€๋ถ„์„ ๋ชฐ๋ผ์„œ ๋‹ค๋ฅธ ๋ฌธ์ œ์ธ ์ค„ ์•Œ๊ณ  ๋ฌธ์ œ ์›์ธ์„ ํ•œ์ฐธ ์ฐพ์•˜๋„ค์š”...

์ฐธ๊ณ ๋กœ ๋ฒ„ํ‚ท ์ •์ฑ…์€ "s3:GetObject"์™€ "s3:PutObject"๋งŒ ํ—ˆ์šฉํ•˜๊ณ , ์ ‘๊ทผ ๊ถŒํ•œ์€ ์ „๋ถ€ ๋‹ค ์—ด์—ˆ์Šต๋‹ˆ๋‹ค.

  • ์—๋Ÿฌ ์ฝ”๋“œ
export const copyPhoto = (originalSource: string) =>
  S3.copyObject(
    {
      Bucket: "blemarket",
      CopySource: originalSource,
      Key:
        originalSource.slice(0, originalSource.lastIndexOf("/")) +
        "/remove" +
        originalSource.slice(originalSource.lastIndexOf("/")),
    },
    (error, data) => {
      if (error) {
        console.error("error >> ", error);
      }
    }
  );
  • ์ •์ƒ ์ฝ”๋“œ
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);
      }
    }
  );

์ „์ฒด ์˜ˆ์‹œ ์ฝ”๋“œ

import AWS from "aws-sdk";
import multer from "multer";
import multerS3 from "multer-s3";

// ํ—ฌํผ ํ•จ์ˆ˜
export const getPhotoPath = (filename: string) =>
  `images/${process.env.NODE_ENV}/${filename}_${Date.now()}`;

AWS.config.update({
  region: process.env.BLEMARKET_AWS_REGION,
  accessKeyId: process.env.BLEMARKET_AWS_ACCESS_KEY,
  secretAccessKey: process.env.BLEMARKET_AWS_SECRET_KEY,
});

const S3 = new AWS.S3();

// multerS3๋ฅผ ์ด์šฉํ•ด์„œ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ ์ฒ˜๋ฆฌ
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: 1024 * 1024 }, // 1mb
});


// ์ด๋ฏธ์ง€ ์ œ๊ฑฐ ํ•จ์ˆ˜
export const deletePhoto = (photo: string) =>
  S3.deleteObject(
    {
      Bucket: "blemarket",
      Key: photo,
    },
    (error, data) => {
      if (error) {
        console.error("error >> ", error);
      }
    }
  );

// ์ด๋ฏธ์ง€ ์ด๋™ ํ•จ์ˆ˜
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);
      }
    }
  );

์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ