My Boundary As Much As I Experienced

AWS) S3, MongoDB, Multer를 이용하여 이미지 업로드 crud 구현하기 (+ejs문법에서 조건적으로 이미지 파일 첨부) 본문

BackEnd/Node.js

AWS) S3, MongoDB, Multer를 이용하여 이미지 업로드 crud 구현하기 (+ejs문법에서 조건적으로 이미지 파일 첨부)

Bumang 2024. 8. 26. 00:02

공부하게 된 계기:

별거 없다.. 요새 듣는 Node.js 강의에서 사용해보길래 사용해봤고,

까먹기 전에 블로그 포스팅으로 남겨보려 한다.

 

S3란?

AWS S3(Amazon Simple Storage Service)는 AWS에서 제공하는 대용량 객체 스토리지 서비스다.

S3는 여러가지 목적으로 쓸 수 있지만 주로 웹 어플리케이션의 이미지 및 동영상 등 대용량 데이터를 저장하기 위해 쓰인다.

Firebase의 Firebase Cloud Storage와 거의 같은 용도로 쓰인다고 보면 된다.

 

Multer란?

multer는 Node.js에서 파일 업로드를 처리하기 위한 미들웨어 라이브러리이다.

이 라이브러리는 특히 Express.js와 함께 사용되며, HTTP 요청을 통해 전송된 파일 데이터를 쉽게 다룰 수 있게 해준다.

파일 업로드와 관련된 작업을 처리하는 데 유용하며, 다양한 옵션을 통해

파일 저장 방식, 파일 이름 지정, 필터링 등의 기능을 제공하는 것이 특징이다.

 

 

초기 설치 및 초기 설정

관련 라이브러리들을 모두 설치한 뒤

npm install multer multer-s3 @aws-sdk/client-s3

 

라이브러리 객체들을 초기화해준다. 나는 클라우드 스토리지를 사용할 것이기 때문에

아래처럼 s3객체를 만든 뒤 multer에 이 객체를 초기화하는 방식으로 초기화하였다.

const { S3Client } = require("@aws-sdk/client-s3");
const multer = require("multer");
const multerS3 = require("multer-s3");

const s3 = new S3Client({
  region: "ap-northeast-2",
  credentials: {
    accessKeyId: process.env.ACCESSKEY_ID,
    secretAccessKey: process.env.SECRET_ACCESSKEY_ID,
  },
});

const upload = multer({
  storage: multerS3({
    s3: s3,
    bucket: process.env.STORAGE_NAME,
    key: function (req, file, cb) {
      cb(null, Date.now().toString()); //업로드시 파일명 변경가능
    },
  }),
});

module.exports = upload;


// 나는 이 모든 설정들을 server.js에 하지 않고,
// multer.js라는 별도의 파일들을 만들고 거기에 해줬다.

 

요새 실제 서버를 가지고 있는 회사는 드물기 때문에 거의 다 클라우드를 사용할테지만..

실제 서버 컴퓨터를 구비하고 있는 경우엔 diskStorage를 통해 하드디스크에 파일을 저장할수도 있다.

const multer = require('multer');

const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, 'uploads/'); // 파일이 저장될 경로
    },
    filename: function (req, file, cb) {
        cb(null, file.fieldname + '-' + Date.now()); // 파일 이름 설정
    }
});

const upload = multer({ storage: storage });

 

또한 서버 램에 가볍게 저장하려면 memoryStorage를 쓸수도 있다.

const multer = require('multer');

const storage = multer.memoryStorage();

const upload = multer({ storage: storage });

diskStorage와 memoryStorage를 사용할 일은 없을거 같지만

클라우드가 없었을 당시엔 원래 이렇게 사용했다는 느낌만 가져가면 될거같다.

 

실제 사용법

upload 객체를 가져와서 초기화시켜준 다음

라우트에서 사용하면 된다. 끝!!

 

아래는 미들웨어에 설정해줘서 req, res를 처리하기 전에

S3 업로드를 미리 진행해준다.

사실 S3에 업로드 시 에러처리를 따로 못 해줘서 이런 방식은 좋지 않다고 한다.

const upload = require("../multer.js");

app.post('/add', upload.single('img1'), (요청, 응답) => {
  console.log(요청.file)
  (생략)
})

 

실제 사용할 때는 미들웨어에 사용하기보단

아래처럼 콜백 안에서 그냥 사용해주는게 좋다고 한다.

그러면 에러처리도 가능하다.

const upload = require("../multer.js");

// write라우터
router.post("/", async (req, res) => {
  await upload.single("img1")(req, res, async (err) => {
    if (err) return 응답.send("업로드 에러");

    try {
      if (req.body.content === "" || req.body.title === "") {
        throw new Error("no Title or no Content");
      }
      const col = db.collection("post");

      const temp = {
        title: req.body.title,
        content: req.body.content,
        img: req.file.location,
      };
      const insert = await col.insertOne(temp);
      console.log(insert, "insert");
      res.send({ message: "Item successfully saved!" });
    } catch (err) {
      console.log(err, "err");
      if (err.message === "no Title or no Content") {
        res
          .status(400)
          .json({ message: "empty title or content are not allowed" });
      }
    }
  });
});

 

역시 코딩은 해보면서 배워야 한다. 백날천날 s3에 대한 소개 영상만 보는 것보다

그냥 구현 한 번 해보니.. 'firebase cloud storage 사용하는거랑 비슷하네?' 싶고

별로 어렵지 않다는걸 깨닿게 된다.