Back-end/Node.js

[Node.js] 미들웨어

poppy 2021. 7. 13. 15:50
반응형

미들웨어

미들웨어란?
- 구조 내에서 중간 처리를 위한 함수
1)  express 프레임워크에서 사용할 수 있는 중간 처리 목적의 소프트웨어 : 기본적인 express 구조 내에서 처리 목적으로 사용
2) 요청에 대한 응답을 완수하기 전까지 다양한 일을 처리할 수 있음
3) 미들웨어 함수 생명주기 : request - response 응답을 주기로 종료됨
4) 미들웨어 함수 우선순위 : 먼저 로드되는 미들웨어 함수가 먼저 실행됨, 코드 순서가 중요함
app.use('/', (req, res, next) => {
  console.log('모든 요청에서 실행되는 미들웨어.');
  next();
});

app.get('/', (req, res, next) => {
  console.log('GET / 요청에서만 실행되는 미들웨어.');
  next();
}, (req, res) => {
  throw new Error('에러는 에러 처리 미들웨어로')
});

app.use((err, req, res, next) => { // 모든 매개변수를 사용하지 않아도 꼭 네 개여야 함!
  console.log('에러 처리 미들웨어.');
  console.error(err);
  res.status(500).send(err.message);
});

미들웨어는 app.use와 함께 사용됩니다. app.use(미들웨어) 형식으로 사용하면 됩니다.

미들웨어에 주소를 넣으면 해당하는 요청에서만 실행되고 주소를 넣지 않으면 모든 요청에서 실행됩니다.

next() 를 사용해서 다음 미들웨어를 호출할 수 있는데 next() 하지 않으면 다음 미들웨어가 실행되지 않습니다.

 

자주 사용하는 미들웨어

1. dotenv

npm install dotenv

dotenv는 미들웨어는 아니고 패키지입니다. 비밀키를 소스 코드에 그대로 적어두면 개인 정보가 노출될 위험이 있습니다. 따라서 .env 파일에 비밀키를 저장해두고 dotenv 패키지로 비밀키를 가져오는 방식으로 관리합니다. .env 파일에는 "키=값" 형식으로 저장해두면 됩니다. git에 파일을 올릴 때 보안을 위해 .env 파일은 올리지 않는 것이 좋습니다!!

// .env
COOKIE_SECRET=cookiesecret

// app.js
const dotenv = require('dotenv');
dotenv.config();

dotenv 패키지를 가져온 후 process.env.키 로 비밀키 값을 가져올 수 있습니다. 위 코드에서는 process.env.COOKIE_SECRET 으로 가져오면 됩니다.

 

2. cookie-parser

npm install cookie-parser

cookie-parser는 요청에 동봉된 쿠키를 해석해 req.cookies 객체로 만들어줍니다. cookie-parser는 app.use(cookieParser(비밀키)) 로 사용하면 됩니다.

const express = require('express');
const cookieParser = require('cookie-parser');
const dotenv = require('dotenv');
dotenv.config();

const app = express();
app.use(cookieParser(process.env.COOKIE_SECRET));

name=node 쿠키를 보냈다면 req.cookies는 { name: 'node' } 가 됩니다. 인수로 비밀키를 넣어준 경우 쿠키 값 뒤에 비밀키를 통해 만들어낸 서명을 붙입니다. 서명이 붙으면 쿠키는 req.signedCookies 객체에 name=node.sign 으로 저장됩니다. 쿠키 서명을 위한 비밀키는 위에 dotenv를 참고해주세요!

 

3. morgan

npm install morgan

위 사진처럼 콘솔에서 보이는 로그는 morgan에서 나오는 것입니다. morgan은 요청과 응답에 대한 정보를 콘솔에 기록합니다. morgan은 app.use(morgan('dev')) 로 사용할 수 있고 인수에는 dev, combined 등이 있습니다. 보통 개발환경에서는 dev를 사용합니다. dev 모드 기준으로 정보는 [HTTP메서드] [주소] [HTTP상태코드] [응답속도] - [응답바이트] 형식으로 기록됩니다.

const express = require('express');
const morgan = require('morgan');
const app = express();

app.set('port', process.env.PORT || 3000);
app.use(morgan('dev'));

 

4. static

static은 정적인 파일들을 제공하는 역할을 합니다. 기본적으로 제공하기 때문에 따로 설치할 필요가 없습니다.

express.static(경로) 를 사용하여 정적파일이 위치한 경로를 입력하면 파일을 제공해줍니다. 요청 경로에 파일이 없으면 알아서 내부적으로 next를 호출해 다음 미들웨어를 실행합니다. 

const express = require('express');
const app = express();
app.use('/', express.static(path.join(__dirname, 'public')));

 

5. body-parser

body-parser는 요청의 본문의 데이터를 해석해서 req.body 객체로 만들어주는 미들웨어입니다. ( 단, 이미지/동영상/파일은 처리하지 못함!!) express에 body-parser의 일부 기능이 내장되었으므로 따로 설치할 필요는 없습니다! 하지만 Raw나 Text 형식의 데이터를 해석하기 위해서는 설치해주어야 합니다

const express = require('express');
const app = express();

app.use(express.json());
app.use(express.urlencoded({ extended: false })); // false - querystring 모듈 사용, true - qs 모듈 사용

위 코드에서 사용한 요청 데이터 종류에는 JSON과 URL-encoded 가 있습니다. JSON은 말그대로 JSON 형식 데이터이고, URL-encoded는 주소 형식 데이터를 말합니다. JSON, URL-encoded 방식 모두 req.body에 { name: 'node', book: 'nodejs' } 형식으로 들어갑니다

 

6. express-session

npm install express-session

express-session은 세션 관리용 미들웨어입니다. 세션은 req.session 객체 안에 유지됩니다. 세션을 아래 코드처럼 설정할 수 있습니다.

const express = require('express');
const session = require('express-session');
const app = express();

app.use(session({
  resave: false, // 요청이 올 때 세션에 수정 사항이 생기지 않더라도 세션을 다시 저장할지
  saveUninitialized: false, // 세션에 저장할 내역이 없더라도 처음부터 세션을 생성할지
  secret: process.env.COOKIE_SECRET, // 비밀키 ( 쿠키의 비밀키와 같은 것이 좋음)
  cookie: { // 세션 쿠키에 대한 설정
    httpOnly: true,
    secure: false,
  },
  name: 'session-cookie', // 세션쿠키 이름
}));

 

7. multer

npm install multer

multer는 이미지/동영상/파일같은 멀티파트 형식을 업로드할 때 사용하는 미들웨어입니다.

const express = require('express');
const app = express();

app.set('port', process.env.PORT || 3000);

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

const upload = multer({
  storage: multer.diskStorage({
    destination(req, file, done) {
      done(null, 'uploads/');
    },
    filename(req, file, done) {
      const ext = path.extname(file.originalname);
      done(null, path.basename(file.originalname, ext) + Date.now() + ext);
    },
  }),
  limits: { fileSize: 5 * 1024 * 1024 },
});

// 파일 하나 업로드
app.post('/upload', upload.single('image'), (req, res) => {
  console.log(req.file);
  res.send('ok');
});

storage - 어디에(destination) 어떤 이름으로(filename) 저장할 지에 대해 설정합니다. req는 요청에 대한 정보, file은 업로드한 파일에 대한 정보가 있고, done은 함수입니다. done의 첫번째 인수에는 에러 있다면 에러를 넣고, 두번째 인수에는 실제 경로나 파일이름을 넣어주면 됩니다. 위 코드는 uploads 폴더에 "파일명+현재시간.확장자" 파일명으로 업로드합니다. 

limit - 업로드에 대한 제한 사항을 설정합니다. 여기서는 파일사이즈를 5MB로 제한했습니다.

 

설정이 끝나면 파일을 업로드 할 수 있는데 파일에 따라 미들웨어가 달라집니다.

파일 하나 업로드 upload.single() 사용
이미지 정보는 req.file 로, 나머지 정보는 req.body 로 
파일 여러개 업로드 (input 키가 같은 경우) upload.array() 사용
이미지 정보들을 req.files 로, 나머지 정보는 req.body 로
파일 여러개 업로드 (input 키가 다른 경우) upload.fields() 사용
이미지 정보들을 req.files 로, 나머지 정보는 req.body 로
파일 업로드하지 않고 멀티 파트 형식 업로드 모든 정보가 req.body 로

 

반응형