Middlewares

 

1. Middleware는 요청과 응답 사이의 소프트웨어다.


2. 모든 Middleware는 handler다.

Middleware = handler = controller
(앞으로는 handler 대신 controller 라고 부를 것임)


3. 사실 controller의 인수에는 next도 있다.

const handleHome = (req, res, next) => {

   return res.end();

};


4. res.end() 리턴 대신에 next()를 사용하면 어떨까? -> cannot get 이 나옴. -> get 인수 중 next to handleHome 에 아무것도 없어서 접속 자체가 안된다.

 

5. Middleware를 만들어보자.

여기서 handleHome은 finalware에 해당한다. 뭐가 됐든 return을 하면 연결이 종료되니까.

이 middleware에서도 handler와 같이 return할 수 있다. middleware = handler = controller 니까!

const gossipMiddleware = (req, res, next) => {
  console.log(`Someone is going to: ${req.url}`);
  next();
};

const handleHome = (req, res) => {
  return res.send("I love middlewares");
};

app.get("/", gossipMiddleware, handleHome);

const handleListening = () =>
  console.log(`✅ Server listening on port http://localhost:${PORT} 🚀`);

app.listen(PORT, handleListening);

 

+ 실습 도중에 에러가 나서 터미널을 들여다보고, 구글링도 했는데

터미널에서는 에러가 어디서 뜨는지 확인하는 법을 알았다.

저 화살표 윗부분을 확인해보니 에러 해결 바로 완료... 터미널이 복잡해보여서 걱정했는데 여기도 에러를 알려주니 좋다.

 

 

ex.
// 미들웨어 "1"로 시작하지만 결국 컨트롤러 "3"으로 끝날 것이다.
// 미들웨어 "1"과 "2"의 본체에 코드를 넣어 컨트롤러 "3"에 도달하기 전에 확인할 수 있다.

const one = (req,res,next) => {
next();
}
const two = (req,res,next) => {
next();
}
const three = (req,res) => {
console.log("Now three is handling")
}

// app.get will handle users who visit "/" URL with "one" handler
app.get("/", one, two, three)

 


 

app.use() 사용하기

 

app.get() 말고 app.use()도 있다는 사실!

 

app.use = global middleware를 만들 수 있게 해주는 함수
(global middleware: 어떤 url에서도 작동하는 미들웨어)

 

이때 순서에 주의해야 함. express또한 위에서 아래로 읽기 때문이다.

request를 받으면 express가 먼저 handleHome을 설정한 다음에 middleware를 사용한다.

 

따라서 middleware를 먼저 use 해주고  ->   그 다음에 url을 get 해준다

app.use(gossipMiddleware);
app.get("/", handleHome);

 

app.use를 한 후에 새로고침하면 여전히 잘 돌아가는 걸 볼 수 있고,

/wonderland 와 같이 없는 주소로 이동하면 gossipMiddleware가 아래와 같이 작동한 것을 터미널에서 볼 수 있다.

 


 

중간에 이동을 차단해주는 middleware 만들기

새로고침 후 사이트에 들어가보면 홈은 잘 들어가지지만,

/protected 으로 접속하면 Not Allowed가 뜨면서 그 다음 절차로 가지 못하게 막는다. 이게 미들웨어의 기능!

import express from "express";

const PORT = 4000;

const app = express();

///여기부터
const logger = (req, res, next) => {
  // console.log(`Someone is going to: ${req.url}`);
  console.log(`${req.method} ${req.url}`);
  next();
};

const privateMiddleware = (req, res, next) => {
  const url = req.url;
  if (url === "/protected") {
    return res.send("<h1>Not Allowed</h1>");
  }
  console.log("Allowed, you may continue");
  next();
};

const handleHome = (req, res) => {
  return res.send("I love middlewares");
};

const handleProtected = (req, res) => {
  return res.send("Welcome to the private lounge");
};

app.use(logger);
app.use(privateMiddleware);
app.get("/", handleHome);
app.get("/protected, handleProtected");

const handleListening = () =>
  console.log(`✅ Server listening on port http://localhost:${PORT} 🚀`);

app.listen(PORT, handleListening);

 

 

미들웨어의 개념은 중요하니 반드시 이해하고 넘어가기!

 

middleware는 일반적인 controller와 같은 것이다.

다만 req, res 외에 next라는 함수 argument 하나가 추가된다는 점은 다르다.

 

middleware를 app 전체에 어떤 url에서도 사용 가능하게 할 수도 있고, 

아래처럼 한 middleware 의 url에만 사용되게 할 수도 있다.

ex.

app.use();
app.get("/", logger, handleHome);
app.get("/protected", logger, handleProtected);


// -> app.get("/", logger, handleHome);

 

기억해야 할 것은,

middleware가 next function을 호출하지 않으면

handleProtected 나 handleHome 과 같은 함수들은 절대 실행되지 않는다는 점!

PrivateMiddleware처럼 무언가를 return 하면 PrivateMiddleware가 거기서 연결을 종료시킬 것이다. (다음은 없다...!)

 

어떤 middleware는 next 함수를 사용하고

어떤 middleware는 res.send를 사용한다

 

privateMiddleware에는 두 가지 옵션이 있는데

조건에 따라 send함수를 호출해주거나(안돼. 돌아가)

next 함수를 호출해준다.(드루와)

 

결론은 next();를 호출하면 미들웨어다!! 

 

아래에서는 괄호 안에 순서대로

1. route

2. 첫번째 함수 실행

3. 만약 logger가 next()를 호출하면 다음으로 handleHome 이 실행됨

+ handleHome 이 next()를 호출하면 다음 거를 실행하고....

4. 근데 여기서는 handleHome이 마지막이기 때문에 여기서 res.send를 사용함

app.get("/", logger, handleHome);