ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Express 미들웨어에 중요한 특징
    FrameWork/Express.js 2022. 8. 4. 15:12

    Middleware callback 함수의 특징

    import express from "express";
    const app = express();
    
    app.get(
      "/",
      (req, res, next) => {
        console.log("first");
      },
      (req, res, next) => {
        console.log("first2");
      }
    );
    
    app.get("/", (req, res, next) => {
      console.log("second");
    });
    
    
    app.listen(8080);

    등록한 callback함수는 누가 먼저 등록했는 지가  정말 중요하다. 특정한   URL에 대해서 특정한 처리를 하는 callback함수에 대해서 등록을 했어도 또 동일한 URL에 대해서도 또 한번더 등록할 수 있다.

     

    우리가 등록하는 middleware callback함수는 한URL에 대해서 배열 형태로 여러개를 등록 할 수 있다.

     

    그래서 root 경로에 들어간 뒤에 터미널에 들어가서 확인을 하면, 아무리 여러번 root경로를 요청해도 first만 찍혀 나오는 것을 확인할 수 있다.


    Middleware Chaining

     (req, res, next) => {
        console.log("first");
      },

    즉 위 단계에서 더이상 진행이 되지 않고, server는 계속 loading 중인 것을 확인 할 수 있다.

     

    왜냐하면  해당 middleware callback함수에서 response도 하지않고, next도 호출하지 않았음으로, middleware chaning은 연결이 되어 있지만 server는 아무것도 반응하지 않는 중지된 상태가 된다. 그래서 이러한 점을 유의해서 sever의 코드를 작성을 해야한다.


    next()

     (req, res, next) => {
        console.log("first");
        next();
      },

    첫번째 middleware에서 아무것도 보내지 않고, next()를 이용해서 다음으로 넘어가면, 해당 get메서드 안에서 등록된 두번째 middleware로 넘어간다. 하지만 두번째 middleware에서도 아무것도 하지 않으므로, 그 다음으로 넘어가지 않고 

    이번에는 아무리 요청을 해도 first와 first2만 반복해서 출력한다. 

     

    next(route)

    import express from "express";
    const app = express();
    
    app.get(
      "/",
      (req, res, next) => {
        console.log("first");
        next('route')
      },
      (req, res, next) => {
        console.log("first2");
      }
    );
    
    app.get("/", (req, res, next) => {
      console.log("second");
    });
    
    
    app.listen(8080);

     

    같은 get()메서드에 있는 배열의 다음 순번 middleware는 건너 뛰고, 현재 get()메서드와 동일한 URL에 매칭된 다른 get()메서드의 middleware로 넘어간다.


    Error 응답하기

    app.get(
      "/",
      (req, res, next) => {
        console.log("first");
        next(new Error("error"));
      },
      (req, res, next) => {
        console.log("first2");
      }
    );

    별도로 처리하지 않으면 Error가 고스란히 사용자에게 전달 된다. 그래서 항상 Application 마지막에는 Error를 처리하는 것을 달아주어야 한다.

     

     

    ErrorHandler

    app.use((error, req, res, next) => {
      console.error(error);
      res.status(500).send("Sorry, try later!");
    });

    그래서 어떤 메소드인지 상관없이 어떤 경로든지 상관없이 처음에 error를 받고, req,res,next를 받는 ErrorHandler를 등록해주어야 한다.

     

    error가 발생하면 server 내부적으로는 error를 출력해 놓고,사용자에게는 error의 경위를 설명하는 문자열을 응답한다. 그러므로써 중간중간 error가 발생하더라도 제일 마지막에 있는 middleware가 error가 발생하면 error에 대해서 처리해준다.


    res.send()

    app.get(
      "/",
      (req, res, next) => {
        console.log("first");
        res.send("Hello");
      },
      (req, res, next) => {
        console.log("first2");
      }
    );

    이처럼 middleware는 설정된 순서가 매우 중요하고, 항상 middleware callback 함수에서 next()메서드를 이용해서 다음으로 넘어 가던지 아니면 res 인스변수와 send()와 같은 메서드를 사용해서 응답을 보내는 처리를 해준어야한다.

     

    그럼 get()메서드와 매칭된 URL를 요청한 브라우저에 인자로 담긴 data를 응답으로 보낼 수 있다. 그렇게 이렇게 처리가 됐을 경우에는 그다음에 이어지는 middleware는 호출되지 않는다.

     

    그래서 똑같은 URL에 여러가지 middleware가 설정되어 있다면, 처음으로 res.send를 한 middleware callback함수가 우선된다. 

     

    항상 res.send()혹은 next()메서드를 호출해서 middleware가 잘 동작할 수 있도록 만들어 주어야 한다.


    없는 page를 요청했을 경우 

    아무 처리도 해주지 않았을 경우 =>

    app.use()로 처리를 해주었을 경우 =>

    app.use((req, res, next) => {
      res.status(404).send("Not available!@_@");
    });

     


     

    app.use()와 app.all()의 차이점

     

    app.all()

    app.all("/api", (req, res, next) => {
      console.log("all");
      next();
    });

    app.all()을 사용했을 경우 어떤 HTTP 경로로 보내던 (post(),get() 등등) 무엇으로 보내던 실행이된다.

     

    위와 같이 매치된 URL에 덧붙여서 URL을 추가하면 log에 문자열 'all'이 찍히지 않는 것을 확인 할 수 있다. 그래서 app.all()은 첫번째 인자로 명시한 URL에만 한해 서 모든 HTTP메서드에 대응해서 실행이 된다.

     


    app.use()

    app.use("/sky", (req, res, next) => {
      console.log("ues");
      next();
    });

    URL /sky 요청시 =>

    URL /sky/wedsg 요청시 =>

    app.user()경우 첫번째 인자로 전달된 URL에 대응하는 URL로 요청이 왔을 때 뿐만아니라, 그 뒤에 다른 URL이 덧붙여진 요청이 오더라도 항상 app.use()가 호출되어서 log에 문자열 use가 출력되는 것을 확인 할 수 있다.

     

    하나의 middleware callback에서 두번의 응답을 보낼시

    app.get(
      "/",
      (req, res, next) => {
        console.log("first");
        if (true) {
          res.send("Hello");
    	}
         res.send("Bye");
      });

    위 코드와 같이 if문은 사용해서 어떤 특정한 조건에 따라 2번씩 response를 보내게 되면, 해당 URL 요청시 error가 발생한다. erorr 메시지에 Cannot set headers after they are sent to the client라고 출력되는 것을 확인할 수 있는데, 같은 callback함수에서 또다시 send를 하면 안된다는 의미이다.

     


    res.send()시 callback함수가 끝나도록한다.

    app.get(
      "/",
      (req, res, next) => {
        console.log("first");
        if (true) {
          return res.send("Hello");
        }
        res.send("Bye");
      });

     

    그래서 send()함수를 사용할 때는 항상 return을 붙여서 res.send()하고 있는 callback함수에서 나오도록 해야한다. 해당 함수가 끝나도록 만들어 주는 것이 중요하다.

     

    정리

    등록한 middleware에서는 항상 response를 하거나 next를 호출해서 middleware의 chining이 끊어지지 않게 해주는 것이 중요하다.

     

    [출처 -https://academy.dream-coding.com/courses/node ]

    댓글

Designed by Tistory.