Web Server - Refactor Express

김도영·2022년 5월 26일
0
post-thumbnail
post-custom-banner

Express를 활용한 미들웨어 예제

1.POST요청 등에 포함된 body(payload)를 구조화 할때

순수 node.js로 HTTP body(payload)를 받을 때에는 Buffer를 조합하여 다소 복잡한 방식으로 body를 쓸수 있다.

// 네트워크상의 chunk를 합치고, buffer를 body로 변환하는 작업이 필요
let body = [];
request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString();
});

이를 body-parser 미들웨어를 사용하면 간단하게 처리할 수있다.(express 4.16이상 부터는 body-parser 미들웨어가 따로 필요 없고 express내부에 포함되어 있다.)

express.json([option])

2.모든 요청/응답에 CORS헤더를 붙일 때

순수 node.js 코드에 CORS 헤더를 추가하려면, writeHead 메소드 등을 사용해야 한다. Access-Control-Allow-* 헤더를 매번 재정의해야하고, OPTIONS 메소드에 대한 라우팅도 따로 구현해야해서 번거롭다.

const defaultCorsHeader = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Accept',
  'Access-Control-Max-Age': 10
}
// 생략
if (req.method === 'OPTIONS') {
  res.writeHead(201, defaultCorsHeader);
  res.end();
}

cors 미드웨어를 사용하면 간략하게 작성할 수 있다.

const cors = require('cors')
//생략
app.use(cors()) // 모든 요청에 cors 허용
// 특정 요청에만 허용
app.get('/products/:id', cors(), function (req, res, next) {
  res.json({msg: 'This is CORS'})
})

모든 요청에 대해 url이나 메소드를 확인할 때

모든 요청에 동일한 미들웨어를 적용하려면 app.use 메소드를 사용하면 된다.

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

const myLogger = function (req, res, next) {
  console.log(); // req, res객체를 이용하면, 모든 요청에 대한 로그를 찍을 수 있다.
  next();
}
app.use(myLogger);
//생략

예제 실습 - Mini Node Server에 리팩토링

Mini node Server(순수 node.js)

const http = require('http');
const PORT = 4999;
const ip = 'localhost';

const server = http.createServer((req, res) => {
  if (req.method === 'OPTIONS') {
    res.writeHead(200, defaultCorsHeader);
    res.end();
  }
  
  if (req.method === 'POST') {
    let body = [];
    req.on('data', (chunk) => {
      body.push(chunk);
    })
    .on('end', () => {
      body = Buffer.concat(body).toString();
      res.writeHead(201, defaultCorsHeader);

      if (req.url === '/upper') { // 대문자
        res.end(body.toString());
      }
      else if (req.url === '/lower') { // 소문자
        res.end(body.toString());
      }
      else {
        res.writeHead(404, defaultCorsHeader);
        res.end();
      }
    })
  }
});

server.listen(PORT, ip, () => {
  console.log(`http server listen on ${ip}:${PORT}`);
});

const defaultCorsHeader = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Accept',
  'Access-Control-Max-Age': 10
};

Express로 리팩토링

const express = require('express')
const app = express();
const cors = require('cors')
const PORT = 3999;
const ip = 'localhost';

app.use(cors()); // 모든 요청/응답에 CORS 처리
// 자동 바디 퍼싱
// strict 옵션은 비활성화면 모든 것을 받을수 있다.
app.use(express.json({strict: false}))

app.post('/upper', function (req, res) {
  let newBody = req.body;
  newBody = newBody.toUpperCase();
  res.json(newBody); // 데이터를 보내줄 때 json화
}
         
app.post('/lower', function (req, res) {
  let newBody = req.body;
  newBody = newBody.toLowerCase();
  res.json(newBody); // 데이터를 보내줄 때 json화
}
         
app.use( function (req, res, next) {
  // 클라이언트의 잘못으로 인한 404에러는 err인자가 포함되지 않는다.
  res.status(404).send('Error 404');
});

app.use( function (err, req, res, next) {
  // 에러 처리
  res.status(500).send('Error 500');
}
profile
Blockchain Developer
post-custom-banner

0개의 댓글