Multer를 이용하여 이미지 파일 업로드 하기

조성철 (JoSworkS)·2020년 1월 17일
3

multer를 사용해 이미지 업로드

Multer 모듈이란?

Multersms Multypart/form-data 형식의 Request을 다루기 위한 Node.js 미들웨어이다.

아래의 커맨드를 실행하면 Multer의 인스톨과 package.json의 dependencies에 추가된다.

$ npm install --save multer
  "dependencies": {
    ...
    "multer": "^1.4.2",
		...
  }

간단한 Multer 세팅

Multer 레퍼런스를 참고하면 더 많은 사용방법을 확인할 수 있다.

https://github.com/expressjs/multer/blob/master/doc/README-ko.md

라우터를 사용하고 있기 때문에 routes 디렉토리 내의 image.js을 수정해서 POST Request를 받을 수 있도록 한다.

const express = require('express');

const multer = require('multer');
const path = require('path');

const router = express.Router();
const imageController = require('../controllers/image');

// multer setting
const upload = multer({
  storage: multer.diskStorage({
    // set a localstorage destination
    destination: (req, file, cb) => {
      cb(null, 'uploads/');
    },
    // convert a file name
    filename: (req, file, cb) => {
      cb(null, new Date().valueOf() + path.extname(file.originalname));
    },
  }),
});

router.post('/', upload.single('img'), imageController);

module.exports = router;

아래의 코드에서는 Multe의 로드/작성, 저장소/파일명의 지정을 하고 있다. 업로드 된 파일은 프로젝트의 uploads 디렉토리에 저장된다.

const upload = multer({
  storage: multer.diskStorage({
    // set a localstorage destination
    destination: (req, file, cb) => {
      cb(null, 'uploads/');
    },
    // convert a file name
    filename: (req, file, cb) => {
      cb(null, new Date().valueOf() + path.extname(file.originalname));
    },
  }),
});

동작확인

위에서 만든 API가 잘 작동하는지 확인하기 위해 POSTMAN을 이용하여 서버로 이미지 파일을 POST 요청과 함께 보낸다.

http://localhost:3000/image API는 아래와 같이 요청한 이미지의 이름과 경로를 데이터베이스에 삽입하고 삽입된 데이터의 id를 클라이언트에 imageId라는 key와 함께 응답한다.

const { Images } = require('../models');

module.exports = async (req, res) => {
  const createResult = await Images.create({
    fileName: req.file.filename,
    fileAddress: req.file.path,
  });

  res.status(200).json({ imageID: createResult.dataValues.id });
};

클라이언트에 응답이 잘 받아지는 것을 확인할 수 있다.

Muler로 지정한 서버 로컬스토리지에 클라이언트로 부터 받은 이미지 파일이 저장된 것을 확인할 수 있다.

발생한 문제점

Multer을 이용한 서버 로컬스토리지에 이미지 업로드 과정을 진행하면서 발생한 문제점은 Multer 자체의 문제가 아닌 이미지 파일의 이름과 경로를 데이터베이스에 삽입하는 과정에서 발생하였다.

바로 전의 개발 로그에서도 언급한 부분이지만, 이미지 파일을 req.file을 이용하여 받게 되고 req.file.filename과 req.file.path의 값을 데이터베이스에 삽입하고자 하였다.

하지만 다음과 같은 에러 발생 !

console.log를 이용하여 req.file의 값을 확인하였지만 데이터베이스의 유효성 검사에서 번번히 실패하였다.

결국 어제와 마찬가지로 AllowNull: true로 변경한 후에야 정상적으로 데이터베이스에 삽입이 가능하였다.

문제원인에 대한 가설은 모델의 req.file를 하나의 비동기 처리의 과정으로 봤을 때, 이 처리가 완전히 끝나기 전에 Images모델의 validation이 AllowNull:false 부분을 처리하게 되어 req.file의 결과를 null 로 인식하는 것이 아닐까 라고 생각한다.

그렇다면 이러한 코드에서는 AllowNull 옵션을 사용할 수 없는 것인지? 또한 위와 같은 코딩방식은 지양되어야 하는 것인지 더 공부해야봐야겠다.

4개의 댓글

comment-user-thumbnail
2020년 8월 2일

감사합니다. 도움이 됐습니다!

1개의 답글
comment-user-thumbnail
2020년 11월 14일

코드스테이츠 후배입니다. 프로젝트하는데 도움이 되네요. 감사합니다~

1개의 답글