Daily Front_Minhhk

express, Middleware 본문

Code개발일지

express, Middleware

Minhhk 2022. 12. 14. 16:35

Refactor Express

학습목표

  • Express로 간단한 서버를 구현할 수 있다.
  • 미들웨어를 이해할 수 있다.
  • 미들웨어를 이용할 수 있다.
  • 미들웨어를 구현할 수 있다.

개념학습) Express 시작하기

Node.js

  • 구글의 크롬 v8 자바스크립트 엔진을 기반으로 하는 비동기 입출력(I/O)을 지원하는 고성능 네트워크 서버
  • 개발자가 모든 종류의 서버사이드 도구들과 애플리케이션을 자바스크립트로 만들 수 있도록 해주는 런타임 환경
  • 프론트가 아닌 백엔드에서도 자바스크립트 기술을 쓸 수 있게 고안된 언어
  • npm : node package manager

Express

  • Node.js위에서 동작하는 웹 프레임워크
  • Node.js 개발 시 개발을 빠르고 손쉽게 할 수 있도록 도와주는 역할을 한다. 이것은, 미들웨어 구조 때문에 가능한 것이다. 자바스크립트 코드로 작성된 다양한 기능의 미들웨어는 개발자가 필요한 것만 선택하여 Express와 결합해 사용할 수 있다.

1. Express 설치 (reference)

npm으로 express를 설치한다.

npm install express

2. 간단한 웹 서버 만들기 (reference)

응답으로 'Hello World!'를 보내는 Express 서버 코드

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

3. 라우팅: 메서드와 url에 따라 분기(Routing)하기

  • 메서드와 url(/lower, /upper 등)로 분기점을 만드는 것을 라우팅(Routing)이라고 한다.
  • 클라이언트는 특정한 HTTP 요청 메서드(GET, POST 등)와 함께 서버의 특정 URI(또는 경로)로 HTTP 요청을 보낸다. 라우팅은 클라이언트의 요청에 해당하는 Endpoint에 따라 서버가 응답하는 방법을 결정하는 것이다.

3-1. 추가적인 라이브러리를 사용하지 않고, 순수한 Node.js로 코드 작성하는 법

const requestHandler = (req, res) => {
  if(req.url === '/lower') {
    if (req.method === 'GET') {
      res.end(data)
    } else if (req.method === 'POST') {
      req.on('data', (req, res) => {
        // do something ...
      })
    }
  }
}

3-2. Express로 라우팅을 구현하는 법

  • Express는 프레임워크 자체에서 라우터 기능을 제공한다.
  • Express의 라우터를 활용하면 아래와 같이 직관저인 코드를 작성할 수 있다.
const router = express.Router()

router.get('/lower', (req, res) => {
  res.send(data);
})

router.post('/lower', (req, res) => {
  // do something
})

 

 

개념학습) Middleware

 

미들웨어를 사용하는 상황 (자주 사용하는 미들웨어)

  • 미들웨어를 통해 Node.js만으로 구현한 서버에서 번거로울 수 있는 작업을 쉽게 적용이 가능하다!

case 1. POST 요청 등에 포함된 body(payload)를 구조화할 때 (쉽게 얻어내고자 할 때)

  • Node.js로 HTTP body(payload)를 받을 때에는 Buffer를 조합해서 다소 복잡한 방식으로 body를 얻을 수 있다. 다만 네트워크 상의 chunk를 합치고, buffer를 문자열로 변환하는 작업이 필요하다.

Node.js로 HTTP 요청 body를 받는 코드

let body = [];
request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString();
  // body 변수에는 문자열 형태로 payload가 담겨져 있습니다.
});
  • body-parser 미들웨어를 사용하면 이 과정을 간단하게 처리할 수 있다.
  • (자료 구조를 변환하는 것을 parsing이라고 하며, 변환을 실행하는 프로그램을 parser라고 한다.)

npm으로 body-parser를 설치

npm install body-parser

body-parser를 미들웨어를 이용한 코드

const bodyParser = require('body-parser');
const jsonParser = bodyParser.json();

// 생략
app.post('/users', jsonParser, function (req, res) {

})
  • Express v4.16.0 부터는 body-parser를 따로 설치 하지 않고, Express 내장 미들웨어인 express.json()을 사용한다.

express.json()을 이용한 코드

const jsonParser = express.json();

// 생략
app.post('/api/users', jsonParser, function (req, res) {

})

options에 {strict: false}를 추가

Object 형태가 아닌 String 형태도 받을 수 있게 하려면 아래와 같은 처리를 해줘야 합니다. express.json 속성 중 strict의 디폴트 값은 true로 되어있어 Object만 허용되어 있는 상태이기 때문입니다.

const jsonParser = express.json({strict: false});

// 생략
app.post('/api/users', jsonParser, function (req, res) {

})

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

  • Node.js HTTP 모듈을 이용한 코드에 CORS 헤더를 붙이려면, 응답 객체의 writeHead 메서드를 이용할 수 있다. Node.js에서는 이 메서드 등을 이용하여 라우팅마다 헤더를 매번 넣어줘야 한다. 또한, OPTIONS 메서드에 대한 라우팅도 따로 구현해야 한다.

Node.js에 CORS를 적용한 예시

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()
}

npm으로 cors를 설치

npm install cors

모든 요청에 대해 CORS 허용

const cors = require('cors');

// 생략
app.use(cors());

특정 요청에 대해 CORS 허용

const cors = require('cors')

// 생략
app.get('/products/:id', cors(), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for a Single Route'})
})

case 3. 모든 요청에 대해 url이나 메서드를 확인할 때

3-1. 미들웨어 구성

아래의 그램은 endpoint가 / 이면서, 클라이언트로부터 GET 요청을 받았을 때 적용되는 미들웨어이다. 파라미터의 순서에 유의해야 한다. reqres는 우리가 잘 아는 요청(request), 응답(response)이고 next는 다음 미들웨어를 실행하는 역할을 한다.

3-2. 메서드 app.use

  • use 메서드로 모든 요청에 대하여 미들웨어를 적용할 수 있다.

모든 요청에 대해 LOGGED가 출력되는 코드

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

const myLogger = function (req, res, next) {
  console.log('LOGGED');
  next();
};

app.use(myLogger);

app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.listen(3000);

모든 요청에 대해 메서드와 url을 출력하는 코드

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

const myLogger = function (req, res, next) {
  //req를 활용합니다.
  next();
};

app.use(myLogger);

app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.listen(3000);

case 4. 요청 헤더에 사용자 인증 정보가 담겨있는지 확인할 때

  • 서버에서는 요청에 포함된 데이터를 통해 미들웨어가 요구하는 조건에 맞지 않으면, 돌려보낼 수 있는 구현을 할 수 있다.

HTTP 요청에서 토큰(주로 사용자 인증에 사용한다.)이 있는지를 판단하여, 이미 로그인한 사용자일 경우 성공, 아닐 경우 에러를 보내는 미들웨어 예제

app.use((req, res, next) => {
  // 토큰이 있는지 확인, 없으면 받아줄 수 없음.
  if(req.headers.token){
    req.isLoggedIn = true;
    next();
  } else {
    res.status(400).send('invalid user')
  }
})

'Code개발일지' 카테고리의 다른 글

my-agora-states Server  (1) 2022.12.14
express refactoring MiniServer  (0) 2022.12.14
Web Server/ mininode Server  (0) 2022.12.08
Web Server (SOP, CORS)  (0) 2022.12.08
[REACT] StatesAirline Server  (0) 2022.12.08