AWS S3 Multer

2 minute read

문제상황 - 비디오 파일을 어떻게 저장할 것인가?

비디오 파일의 경우에는 텍스트 파일과는 다른 바이너리 파일입니다. 바이너리 파일은 텍스트와 다르게 다루어야 하기에 multer라는 nodejs 모듈을 활용했습니다. 우선 multer가 무엇인지부터 알아보겠습니다.

Multer란?

서버가 프론트로부터 받아오는 정보는 크게 텍스트와 파일 이렇게 2가지로 나눌 수 있습니다. Express는 사용자가 전송하는 파일을 처리할 기본 기능을 제공하지 않습니다. 따라서 이런 비디오나 이미지 파일을 처리할 모듈이 필요했고 이 기능을 하는 것이 바로 multer입니다.

$ npm install multer
const multer = require('multer'); 
// multer 모듈을 가져옵니다.

const videoMulter = multer({dest: "uploads/"}) 
// 업로드 되는 파일이 해당 서버의 uploads 폴더에 저장됩니다. 
// multer 모듈은 기본적으로 함수이므로 옵션을 줘서 실행하게 되면, 해당 함수는 미들웨어를 return 하게됩니다.

const uploadVideo = multerVideo.single("videoFile");
// single은 오직 하나의 파일만 업로드 할 수 있다는 것을 의미합니다. single()안에는 html에서 넘어온 input중에서 원하는 input의 name 속성 값을 담으면 됩니다.

module.exports = multerVideo;

이렇게 작성한 multer를 export한 후, upload 로직에 추가합니다.

const express = require("express");
const uploadMulter = require("../common/multer");

router.post("/upload", auth.authenticate(), uploadMulter, async (req, res) => {
  const {
    body: { title, description, userId },
    file: { location },
    user: { id }
  } = req;

  try {
    const newVideo = await Video({
      fileUrl: location,
      title,
      description,
      creator: id
    });
    newVideo.save();

    const user = await User.findById(id);
    user.videos.push(newVideo);
    user.save();

    res.json({ result: "File Uploaded" });
  } catch (error) {
    res.status(500).json({
      result: false,
      error
    });
  }
});

하지만 위와 같이 로직을 짜게되면 문제점이 발생합니다. 바로 서버에 파일이 그대로 업로드된다는 문제점입니다. 서버에 video file이 업로드된다고 하면 서버는 무거워 질것이고 이는 서버 성능 저하로 이어지게됩니다. 같은 논리로 데이터베이스에 저장할 수도 없습니다. 이런 경우 어떻게 해야 할까요?

해결 - S3 Multer

AWS S3는 파일을 저장할 수 있는 일종의 저장소입니다. 웹을 호스팅하는 서버 역할을 할 수도 있지만 여기서는 비디오 파일을 저장하는 저장소로 활용하도록 하겠습니다. (AWS S3를 생성하는 것은 다른 포스트에서 다루도록 하겠습니다.) 우선 AWS S3를 생성하고 해당 설정들을 가져옵니다. 그 후, multer-s3 module 그리고 aws와 연결할 aws-sdk 모듈을 설치합니다.

$ npm install multer-s3
$ npm install aws-sdk

multer 파일에 코드를 추가해 최종적으로 아래와 같게 만들어줍니다.

const multer = require("multer");
const multerS3 = require("multer-s3");
const aws = require("aws-sdk");
const dotenv = require("dotenv");

dotenv.config();

const s3 = new aws.S3({
  accessKeyId: process.env.AWS_KEY,
  secretAccessKey: process.env.AWS_PRIVATE_KEY,
  region: "ap-northeast-1"
});

const multerVideo = multer({
  storage: multerS3({
    s3,
    acl: "public-read",
    bucket: "wetube-api/video"
  })
});

const uploadMulter = multerVideo.single("videoFile");

module.exports = uploadMulter;

s3 설정에 초점을 맞춰 설명하겠습니다. const s3 = new aws.S3 이 부분 코드는 s3와 연결하는 설정입니다. S3 저장소를 생성하면 AWS_KEY와 AWS_PRIVATE_KEY를 받게됩니다. 이 데이터는 접근 권한에 해당 되기에 노출이 되어서는 안되므로 환경변수로 설정해서 외부에서 볼 수 없게 위와 같이 작성합니다. 그리고 region은 지역을 뜻하는데 해당 저장소가 위치해 있는 곳을 입력하면 됩니다.

const multerVideo = multer 는 처리한 비디오 파일을 저장하는 코드입니다. multer에 storage: 코드는 여기에 저장하겠다는 의미입니다. multer-s3 모듈에 저장소에 접근할 수 있는 권한이 부여된 s3 객체를 주고 접근 통제목록 중 파일을 읽어 올 수 있는 “public-read”를 설정합니다. 마지막으로 폴더는 저장되는 파일이 비디오 파일이므로 video 폴더에 저장되게 합니다.

이렇게 하면 데이터베이스는 파일이 저장되어 있는 S3저장소를 참조하는 형태로 비디오 파일을 관리하고 서버 과부하를 막을 수 있습니다.