Node 강의/입문

2-3 미들웨어(Middleware)(실습에서 추가 및 수정)

kagan-draca 2024. 9. 3. 19:24

1. 미들웨어 (Middleware)

 

웹 서버에서 요청을 받을 때, 모든 요청에 대한 공통적인 처리를

하고 싶을 수 있습니다. 이때 필요한 것이 미들웨어(Middleware) 입니다.

 

미들웨어(Middleware)는 서버의 요청(Request) - 응답(Response) 과정에서

중간에 위치하여 특정 기능을 수행하는 함수라고 볼 수 있습니다.

 

ex) 모든 요청에 대해서 로그(Logging)를 남기거나,

특정 사용자만 API를 접근(Authentication & Authorization)

하게 하고 싶을 때도 미들웨어를 사용합니다.

 

또한 사용자가 웹 페이지에서 Form을 통해 전송한 데이터를 서버에게

쉽게 파싱(Body Parser)하여 사용할 수 있게 해주는 미들웨어도 존재합니다.

 

2. Express.js의 미들웨어는 어떤게 있나요?

 

app.use(express.urlencoded({ extended: true}));

app.use(express.json());

 

//use 사용이 미들웨어를 사용하겠다는 의미이다.

 

코드에서 볼 수 있듯이, Body Parser는 클라이언트의 요청(Request) 부문

데이터인 body를 쉽게 파싱할 수 있게 해주는 미들웨어입니다.

 

urlencoded : form-urlencoded 라는 규격의 body 데이터를 손 쉽게 코드에서

                      사용할 수 있게 도와주는 미들웨어입니다.

 

 json() : JSON이라는 규격의 body 데이터를 손 쉽게 코드에서 사용할 수 있게

             도와주는 미들웨어 입니다.

 

3. Express.js의 미들웨어 작성해보기

 

미들웨어는 아래의 인터페이스로 작성할 수 있습니다.

app.use((req, res, next)=>{
    // 필요한 코드
})

 

req(Request), res(Response), next는 각자 역할을 지니고 있는 인자(Parameter)입니다.

 

req(Request) : 요청(Request)에 대한 정보가 담겨 있는 객체

ex) HTTP Header, Query Parameters, URL 등 서버로 보내는 정보들

 

res(Response) : 응답(Response)을 위한 기능이 제공됩니다.

ex) HTTP Status Code로 응답할지, 어떤 데이터 형식으로 응답할지,

      헤더는 어떤 값을 넣어 응답할지 다양한 기능을 제공

 

(중요)next : 다음 스택으로 정의된 미들웨어 호출합니다.

 

 

Request 로그 남기는 미들웨어 작성

app.use((req, res, next) => {
  console.log("Request URL : ", req.originalUrl, " - ", new Date());
  next();
});

 

코드를 작성한 뒤 저장하고 다시 node app.js로 서버를 실행해서 메인 페이지로 접속해보세요!.

터미널을 확인해보면 로그를 확인할 수 있습니다.

 

4. Express.js의 미들웨어 실행 순서

import express from "express";
import connect from "./schemas/index.js";
import router from "./router/todo.router.js";

const app = express();
const PORT = 3000;

connect();

app.use(express.json()); // 미드웨어 1
app.use(express.urlencoded({ extended: true })); // 미드웨어 2
app.use(express.static("./assets")); // 미드웨어 3

// 미드웨어 4
app.use((req, res, next) => {
  console.log("Request URL : ", req.originalUrl, " - ", new Date());
  next();
});

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


// 미드웨어 5
app.use("/api", router);

app.listen(PORT, () => {
  console.log(PORT, "에 접속했습니다");
});

 

위와 같이 전역 미들웨어 부터  등록을 시작해서 아래 쪽으로 이동하며 실행된다.

 

그래서,

 

// 미드웨어 4
app.use((req, res, next) => {
  console.log("Request URL : ", req.originalUrl, " - ", new Date());
  next();
});

 

이 코드를 미드웨어 5 밑에 넣으면

Log가 출력되지 않을 것이다.

 

5. 미들웨어는 어떤 경우에 사용하는게 적합할까요?

 

미들웨어는 개발자가 만들기 위한 기능에 다양하게 사용 가능하고,

관리 측면에서도 많은 이점이 있습니다.

 

ex)

 

1. 인증 미들웨어는 사용자가 로그인 상태인지 확인하고,

 

2. 로깅 미들웨어클라이언트의 요청에 대한 정보기록하며,

 

3. 에러 핸들링 미들웨어에러를 처리하게 됩니다.

 

6. 여러 개의 미들웨어가 겹치는 경우 동작하는 방식

 

 

- 미들웨어는 어디에 위치시키느냐에 따라 다르게 동작합니다. 일반적으로 어플리케이션에 등록된 순서대로 실행됩니다.

 

- 여러개의 미들웨어가 겹치는 경우, 이는 첫번째 미들웨어부터 순차적으로 진입하게 됩니다.

 

 

순차적으로 미들웨어를 통과하고 중간에 응답을해서 종료가 되거나 다음 미들웨어로 넘어갑니다.

 

그래서,

 

첫번째 미들웨어부터 세번째 미들웨어라는 로그가 쓰여진 걸 확인 할 수 있습니다.

 

하지만, next()가 실행되지 않으면 다음 미들웨어는 실행되지 않고, 클라이언트의 요청은 종료됩니다.

 

현재 미들웨어에서 응답을 보내는 경우, 즉

res.send()res.json() 등의 메서드를 호출하는 경우에는

next()를 호출하면 안 됩니다.

 

왜냐하면, 이미 요청이 종료된 상태에서 다른 미들웨어가 응답을 보내려고 하여

중복된 요청이 전달되는 문제가 발생하게 됩니다.

 

7. Router와 미들웨어의 차이

 

- Router는 미들웨어 기반으로 구현된 객체이다!!!!!

  그래서, 미들웨어와 동일한 방식으로 작동한다.

 

- 즉, Router는 미들웨어 함수를 특정 경로에 바인딩 하는 역할을 하며,

  요청이 들어온 URL 경로에 따라 서로 다른 미들웨어를 실행시킬 수 있게 도와줍니다.

 

 

8. Express.js의 미들웨어가 실행되는 경우

 

app.use(Middleware) : 모든 요청에서 미들웨어가 실행된다.

app.use('/api', Middleware) : /api로 시작하는 모든 요청에서 미들웨어를 실행한다.

app.post('/api', Middleware, (req, res) =>{}) : /api로 시작하는 POST 요청에서 미들웨어를 실행한다.

 

 

문제 : 실행 결과를 작성하세요!

 

예상 결과 실제 결과
포트로 서버가 열렸어요!
GET / 요청이 발생했습니다
첫번째 미들웨어
두번째 미들웨어
서번째 미들웨어

Client 한테 Hi
포트로 서버가 열렸어요!
첫번째 미들웨어
두 번째 미들웨어
GET /  요청이 발생했습니다
세번째 미들웨어

Client 한테 'Hi"
틀린 이유
use가 함수처럼 보여서 처음에 Client가 웹 서버에 들어와서 호출해야 동작한다고 착가했다...
실제
use는 Middleware 인터페이스로 Middleware를 호출 및 사용하는 역할을 수행한다.
따라서, 함수가 아닌 전역 코드이고 프로그램이 실행할 때 동작한다.  

 

만약, res.json()된 이후 next()가 있고 실행된다고 가정하면,

 

"네번째 미들웨어" 문구가 출력될 것이다.

 

하지만,

 

기존 "세번째 미들웨어" 이후 res.json으로 Client에게 응답을 보냈는데

res.json({message : "마지막 미들웨어 입니다.'})로 다시 Client에게 응답을 시도할거라

 

누구에게 응답을 보내줘야 하는지 모르기 때문에

 

오류가 발생할 것 입니다!!