[Express] Middleware

이호정·2022년 10월 13일
0

Express

목록 보기
1/2

네이버 블로그에서 이전, 원글 작성일시 : 2021.08.30.22:39

오랜만의 포스팅이다.

요즘 생활코딩 님의 express 관련 강의를 수강하고 있다.
사실 이전에 다른 분의 boiler-plate 강의를 들은 적이 있었는데,
전체적인 구조는 알 수 있었지만, 포스팅할 만큼의 내용은 없어서 따로 올리지 않았다.

처음 생활코딩 님의 강의를 접할 때는 '뭐야? 너무 쉬운 내용 위주인데?' 싶었다.
하지만 요즘 들어보면서, '아 정말로 할 수 있게끔 만들어주는구나'라고 느낀다.

불편함을 겪고 난 후에야 모듈의 편리함을 깨닫게 해준다거나,
일단 모르고 사용한 후 그게 ~이거였다~라는 식의 교육 방식들이
나와 잘 맞아서 정말 좋은 강의라고 느끼며 수강 중이다.

이번에 포스팅할 미들웨어는 위에서 언급한 두 번째 방식의 예다.
모르고 사용한 것들이 알고 보면 이거더라~라는 식이다.

그럼 미들웨어가 무엇인지부터 생각해 보자


Middleware

미들웨어란 express 공식 사이트에서 아래와 같이 설명되어 있다.

Middleware functions are functions that have access to the request object (req), the response object (res), and the next function in the application’s request-response cycle. The next function is a function in the Express router which, when invoked, executes the middleware succeeding the current middleware.

req, res 객체에 접근 가능하고, 요청-응답 사이클의 next 함수에 접근할 수 있는 함수.
사실 무슨 말인지 잘 모르겠지만, 내가 이해한 내용은 아래와 같다.

기존의 요청-응답 흐름이 아래와 같다면,

미들웨어는 아래와 같이 동작하게 되는 것이다.

위 그림은 오로지 내 나름대로 이해한 것이므로 사실과는 다를 수 있다...
요청이 들어오게 되면 미리 사용한다고 정의해둔 미들웨어들을 적용한 뒤
우리가 흔히 건드리는 라우트 부분에 도달하게 된다.

이때 미들웨어에서는 여러 가지가 가능한데, 대표적으로 request 객체에 파라미터를 할당해 전달해 줄 수 있다.

지금은 express에 포함되어 있지만, 4.16 아래 버전에서 자주 쓰던 body-parser가 대표적인 미들웨어의 예시이다.

body-parser는 상단에 app.use()를 이용해 어떤 타입을 사용할 것인지 명시하고 나면
라우터에서 request.body로 http request의 body로 전달된 파라미터들을 사용할 수 있다.
body-parser 내부에서 http request 중 body 부분을 해석하고, 이를 request.body에 할당한 것이다.

이렇게 미들웨어는 request, response 객체에 접근이 가능하다.(response는 아직 실습해 본 적은 없다.)

그렇다면 next는 무엇일까?

위 설명에는, 현재 미들웨어의 다음 미들웨어를 호출시키는 함수라고 나와있다.
꽤 친절한 설명이다.

미들웨어는 하나가 아니라 여럿이 될 수 있으며, 현재 미들웨어의 실행이 끝났으면,
다음 순서의 미들웨어를 실행시켜 줘야 한다.

그럼 간단한 미들웨어를 만들어보자

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

app.use(function(req, res, next) {
    console.log('mw 1');
    req.mw1 = 'express';
    next();
});

app.use(function(req, res, next) {
    console.log('mw 2');
    req.mw2 = 'js';
    next();
});

app.get('/', function(req, res) {
    console.log(req.mw1 + req.mw2);
});

실행하고, 최상위 엔드 포인트인 '/'로 요청하면, 아래와 같은 결과가 나올 것이다.

mw 1
mw 2
expressjs

근데 재밌는 점은, 몇 가지 제약을 추가할 때 발견된다.
1. get, post로 구분되는 여러 가지 라우트가 존재
2. get 요청에 대해서만 작동하는 미들웨어가 필요

위 상황을 해결하기 위한 방법은 아래와 같다.

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

app.use(function(req, res, next) {
    console.log('entire');
    req.param1 = 'for entire method';
    next();
});

app.get('*', function(req, res, next) {
    console.log('get');
    req.param2 = 'for get method only';
    next();
});

app.get('/', function(req, res) {
    console.log("param1 : " + req.param1);
    console.log("param2 : " + req.param2);
});

app.post('/something', function(req, res) {
    console.log("param1 : " + req.param1);
    console.log("param2 : " + req.param2);
});

'/' get 요청 결과

entire
get
param1 : for entire method
param2 : for get method only

'/something' post 요청 결과

entire
param1 : for entire method
param2 : undefined

(실제로 돌려보진 않아서 undefined가 어떻게 출력될지는 모르겠다...)

잘 살펴보면, 미들웨어라고 사용한 것이, 우리가 자주 쓰는 라우트랑 비슷하게 보인다?

app.get('*', function(req, res, next) {
    console.log('get');
    req.param2 = 'for get method only';
    next();
});

그랬다.

알고 보면 우리가 너무 쉽게 사용하고 있던, app.get(), app.post() 들의
두 번째 인자로 전달한 함수는 미들웨어라고 볼 수 있었던 것이다.
(가만 생각해 보면, request, response에 당연하게 접근하고 있었다.)


express를 이번에 처음 배우는 것이 아니다. 몇 가지 실습 영상들을 보면서 사용하는 방법들은 익히고 있었다.

라우팅하는 방법, 미들웨어를 사용하고, 작성하는 방법 또한 이미 이전 강의들로 배워놓은 상태였다.

하지만 이제는
당연하게 생각하던 라우팅의 콜백 함수들을 이젠 다른 눈으로 볼 수 있게 되었다.
왜 next()가 필요한지 구조적으로 이해할 수 있게 되었다.

오래간만에 흥미로운 발견을 한 것 같아 생활코딩 님에게 그저 감사할 따름이다.

참고 : https://expressjs.com/ko/guide/using-middleware.html

0개의 댓글