Express 정리

그래도 아무튼 개발자·2023년 4월 25일
0

웹프로그래밍

목록 보기
6/7
post-thumbnail

Express

MERN stack은 JavaScript 생태계에서 인기 있는 프레임워크인 MongoDB, Express, React, Node.js를 지칭하는 말이다.
이 중에서 Express는 Node.js 환경에서 웹 서버, 또는 API 서버를 제작하기 위해 사용되는 인기 있는 프레임워크이다.
다만 Express로 구현한 서버가 Node.js, HTTP 모듈로 작성한 서버와 다른 점이 있다.

  1. 미들웨어 추가 가능
  2. 라우터 제공

미들웨어

미들웨어 함수는 응용 프로그램 요청-응답 사이클에서 요청 객체(req), 응답 객체(res) 및 다음 미들함수에 액세스할 수 있는 함수이다. next 함수는 익스프레스 라우터의 함수이며, 호출되면 현재 미들웨어의 뒤를 잇는 미들웨어를 실행한다.

미들 웨어를 사용하는 상황
-모든 요청에 대해 url이나 메소드를 확인할 때
-POST 요청 등에 포함된 body(payload)를 구조화할 때
-모든 요청/응답에 CORS 헤더를 붙여야 할 때
-요청 헤더에 사용자 인증 정보가 담겨있는지 확인할 때

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

가장 단순한 구조를 가진 미들웨어 로거를 예로 든다면, 로거는 디버깅이나 서버 관리에 도움이 되기 위해 console.log로 적절한 데이터나 정보를 출력한다. 데이터가 여러 미들웨어를 거치는 동안 응답할 결과를 만들어야 한다면, 미들웨어 사이사이에 로거를 삽입하여 현 데이터를 확인하거나, 디버깅에 사용할 수 있다.

위 그림은 endpoint가 /이면서 클라이언트로부터 GET 요청을 받았을 때 적용되는 미들웨어이다. 미들웨어 내부에서는 아무런 작업을 하고 있지 않고, 특정 endpoint에 적용하고있다. 그럼 모든 요청에 동일한 미들웨어를 적용하는 방법으로는, app.use를 이용하면 된다.

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);    // 모든 요청에 대해 LOGGED가 출력된다.

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

Node.js로 HTTP body(payload)를 받을 때에는 Buffer를 조합해서 다소 복잡한 방식으로 body를 얻을 수 있다.

let body = [];
request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString();
  // body 변수에는 문자열 형태로 payload가 담겨져 있습니다.
});

하지만 body-parser 미들웨어를 사용하면 상당히 간편해진다.

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

.
.
.

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

})

추가로 해당 미들웨어를 굳이 설치하지 않아도 Express 내장 미들웨어린 express.json()을 사용하기도 한다.

const jsonParser = express.json();

.
.
.

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

})

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

Node.js 코드에 CORS 헤더를 붙이려면 응답 객체의 writeHead 메소드 등을 이용해야 한다. 이러한 메소드를 이요하더라도 Access-Control-Allow-Origin 헤더를 매번 재정의해야 하며, OPTIONS 메소드에 대한 라우팅도 따로 구현해야 한다...

하지만 이러한 과정들을 cors 미들웨어를 통해 상당히 간단히 해결된다.

const cors = require('cors');

.
.
.

app.use(cors());   //모든 요청

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

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

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

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

로그인을 하지 않고 웹사이트에 접근을 시도했을 때 다시 로그인 창으로 되돌려보내는 등 미들웨어가 요구하는 조건에 맞지 않으면 돌려보낼 수 있도록 구현할 수 있다.


라우팅

라우팅은 URI(또는 경로) 및 특정 HTTP 요청 방법(GET, POST 등)인 특정 끝점에 대한 클라이언트 요청에 애플리케이션이 응답하는 방식을 결정하는 것을 말한다. 각 라우트는 하나 이상의 핸들러 함수를 가질 수 있고, 이러한 함수는 라우트가 일치할 때 실행된다.

Express는 프레임워크 자체에서 이러한 라우터 기능을 제공한다.
라우터 활용 전(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 ...
      })
    }
  }
}

라우터 활용 후

const router = express.Router()

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

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

보다 직관적이고 간단한 코드로 작성이 가능하다 🫡🫡

0개의 댓글