[express] 이미지 요청/응답

zwundzwzig·2022년 9월 18일
0

EXPRESS

목록 보기
4/6
post-thumbnail

앞서 클라이언트에서 어떤 방식으로 이미지 데이터를 서버에 전송하는지 공부했다.

이제, multipart/form-data를 다루는 미들웨어를 소개하고 어떻게 이미지를 서버에 받고 활용할 수 있는지 알아본다.


multer

이미지를 비롯해 클라이언트가 단순 텍스트 이외의 데이터를 요청할 때 적절한 응답을 위해 express에선 multer라는 모듈을 제공한다.

npm 공식 홈페이지 multer 페이지에 따르면, 다음과 같이 multer를 설명한다.

파일 업로드를 위해 사용되는 multipart/form-data를 다루기 위한 node.js 의 미들웨어
(multipart/form-data)가 아닌 form 요청에선 동작하지 않습니다.

multer의 기본 사용 예시는 다음 세 가지이다.

ex-1) 서버 폴더에서 하나의 파일을 불러올 경우

const express = require('express');
const multer = require('multer');
const uploadFile = multer({dest: './uploads'});

const app = express();

app.post('/uploads', 
         uploadFile.single("profileImg"//클라이언트 input name element 이름),
  		 (req, res, next) => {
// req.file에 profileImg라는 필드의 이미지 파일 정보가 담김.
// req.body에는 이미지 이외의 필드의 텍스트 정보가 담김.
})

module.exports = { uploadFiles };

ex-2) 서버 폴더에서 일정 범위의 파일을 불러올 경우

const express = require('express');
const multer = require('multer');
const uploadFiles = multer({dest: './uploads'});

const app = express();

app.post('/uploads/photo', 
         uploadFiles.array('profileImg', 12//maxCount), 
         (req, res, next) => {
// req.files는 필드 내 req.file 정보가 maxCount 만큼 array에 담김.
// req.body에는 이미지 이외의 필드의 텍스트 정보가 담김.
})

module.exports = { uploadFiles };

ex-3) 서버 폴더에서 여러 필드 내 파일들을 불러올 경우

const express = require('express');
const multer = require('multer');
const uploadFiles = multer({dest: './uploads'});

const app = express();

const cpUpload = uploadFiles.fields([
  { name: 'avatar', maxCount: 1 }, 
  { name: 'gallery', maxCount: 8 }
]);
app.post('/chosen-profile', cpUpload, (req, res, next) => {
// req.files는 (String -> Array) 객체
// 필드명은 객체의 key에, 파일 정보는 배열로 value에 저장.
// e.g.
//  req.files['avatar'][0] -> File
//  req.files['gallery'] -> Array
// req.body에는 이미지 이외의 필드의 텍스트 정보가 담김.
})

module.exports = { uploadFiles };

req.file vs req.files

multipart 데이터가 담긴 클라이언트의 요청은 multer 미들웨어를 거치면 file이라는 객체를 프로퍼티로 갖게 된다.

file은 다음 프로퍼티를 갖고 있다.

  • fieldname : 클라이언트 html 폼에 정의된 필드 이름
  • originalname : 사용자가 업로드할 때 작성한 파일 이름
  • encoding : 파일 인코딩 타입
  • mimetype : 파일 정보 ex) jpg, jpeg...
  • size : 파일 byte 사이즈
  • destination : 파일이 저장된 폴더, DiskStorage Key
  • filename : destination에 저장된 파일 명, DiskStorage Key
  • path : 업로드된 파일의 전체 경로, path 모듈 설치 후 사용, DiskStorage Key
  • buffer : Buffer 방식의 업로드, MemoryStorage 방식

dest vs storage

위 예제처럼 multer({dest: './uploads'}) dest 옵션을 활용해 default로 제공되는 multer 기능만으로 파일을 저장할 수 있다.

그러나 multer는 여러 옵션 객체를 갖고, 이를 통해서 파일을 저장하는 방식을 개발자가 직접 지정할 수 있다.

DiskStorage

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

const uploadFiles = multer({
  storage: multer.diskStorage({
    destination: (req, file, cb) => {
      cb(null, "./uploads");
    },
    filename: (req, file, cb) => {
      const ext = path.extname(file.originalname);
      cb(null, path.basename(file.originalname, ext) + Date.now() + ext);
    },
  }),
});

module.exports = { uploadFiles };

destination 프로퍼티로 저장 경로를, filename으로 파일 이름을 지정할 수 있다. filename의 기본값은 아래와 같은 무작위 문자열이다.

MemoryStorage

파일 전체를 포함하는 buffer 방식을 따른다. (버퍼링 할 때 그 버퍼이다!!)

메모리 스토리지를 사용시, 매우 큰 사이즈의 파일을 업로드 하거나 많은 양의 비교적 작은 파일들을 매우 빠르게 업로드 하는 경우 응용 프로그램의 메모리 부족이 발생 할 수 있다.

fileFilter

각각의 밸류 중 세 번째 인자로 받는 콜백 함수의 두 번째 인자로 boolean을 받아 어느 파일을 업로드하거나 제어할지 필터링할 수 있따.

이외에도 limits 객체를 활용해 데이터 한도를 지정할 수 있고, preservePath를 통해 보존 파일 전체의 경로를 지정할 수 있다.

만약, 경로를 지정하지 않으면 파일은 디스크가 아닌 메모리에 저장될 것이다.

항상 사용자가 업로드한 파일을 다뤄 보안에 취약할 수 있으므로 절대 global 미들웨어로 사용하면 안 된다!

참조

profile
개발이란?

0개의 댓글