ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • #TIL_미들웨어에 대하여
    TIL (Today I Learned) 2023. 11. 14. 00:18

    # 미들웨어란?

    미들웨어는  Express.js 동작의 핵심입니다. 

    양 쪽을 연결하여 데이터를 주고 받을 수 있도록 중간에서 매개 역할을 하는 소트트웨어입니다. 

     

    # 미들웨어의 동작원리 

     

    클라이언트에서 요청을 보내게 되면 서버에 있는 미들웨어들이 동작을 하게 됩니다. 요청이 들어오자마자 첫 번째 미들웨어를 거치게되고 미들웨어들 하나하나를 다 타고 들어가서 최종 미들웨어에서 응답을 보내면 그 응답이 클라이언트에게 전달되는 구조이며, 응답이 마무리될 때까지 미들웨어 동작 사이클이실행됩니다. 즉 서버가 모든 미들웨어들의 호출로 구성되어 있다는 것을 예측할 수 있게 됩니다. 

     

    Express에서는 애플리케이션은 본질적으로 일련의 미들웨어 함수라고 정의하고 있습니다. 

     


    # 미들웨어의 기본 작성예제

    var express = require('express');
    var app = express();
    
    // 미들웨어 함수 작성
    app.use(function (req, res, next) {
      req.requestTime = Date.now();
      next(); // 다음 미들웨어로 제어를 전달
    });
    
    // 라우터에서 미들웨어 사용
    app.get('/', function (req, res) {
      res.send(req.requestTime);
    });
    
    app.listen(3000);

     

    위 예제에서 `app.use`를 통해 미들웨어를 등록하고, 해당 미들웨어에서는 `req`객체에 `requestTime`을 추가하고 다음 미들웨어로 제어를 전달합니다. 이후 라우터에서 `req.requestTime`을 활용할 수 있습니다. 

     

    +++ app.use()에 관하여

    1. app.use() 함수를 사용하여 응용 프로그램 수준에서 미들웨어를 등록할 수 있습니다.
    2. 등록한 미들웨어는 Express 앱의 모든 요청에서 실행됩니다.
    3. 특정한 URL에 묶이지 않아 URL에 상관없이 매번 실행됩니다.
    4. app.Method() 함수 (app.get(), app.post() 등)는 특정 HTTP 메소드에 대한 요청을 처리하기 위한 라우팅 미들웨어를 등록하는 데 사용됩니다.
    5. app.use() 및 app.Method() 함수들을 사용하여 미들웨어를 앱 객체의 인스턴스에 바인딩할 수 있습니다.

    // 응용 프로그램 수준에서의 미들웨어 등록
    app.use((req, res, next) => {
      console.log('이 미들웨어는 모든 요청에서 실행됩니다.');
      next();
    });
    
    // 특정 URL에 대한 GET 요청을 처리하는 미들웨어 등록
    app.get('/example', (req, res) => {
      console.log('이 미들웨어는 /example 경로에 대한 GET 요청에서만 실행됩니다.');
      res.send('Hello, Express!');
    });

    # 미들웨어의 실행 순서와 `next`

    미들웨어는 `next` 함수를 통해 다음 미들웨어로 제어를 전달합니다. 미들웨어는 순차적으로 실행되며, `next` 함수를 호출하지 않으면 다음 미들웨어로 이동하지 않습니다. 또한 next('route')를 하게 되면 다음 미들웨어가 아닌 다음 라우터로 넘어가게 됩니다. 

    ...
    
    app.get('/', (req, res, next) => {
        if (false) {
        	next(); // 다음 미들웨어로 넘어간다.
        } else {
        	next('route'); // next()에 'route'인수를 주게되면, 다음 미들웨어가 아닌, 다음 라우터로 넘어가게 된다. 
        }
        
    }, (req, res) => { 
    	// ... next()면 실행되지만,
    	// ... next('route')면 실행되지 않는다.
    });
    
    
    app.get('/', (req, res, next) => { 
    	// ... next('route')면, 그 다음 라우터인 이쪽이 실행된다.
    })

     


    # 미들웨어 간 데이터 전달

    미들웨어 간 데잍터 전달은 `req` 객체를 활용합니다. 현재 요청이 처리되는 동안 `req` 객체를 통해 데이터를 공유하며, 새로운 요청이 들어올때마다 `req` 객체는 초기화 됩니다. 

    app.use(function(req, res, next) {
      req.data = 'new data...';
      next(); // 다음 미들웨어로 제어를 전달
    });
    
    app.use(function(req, res, next) {
      console.log(req.data); // 위에서 추가한 값을 사용할 수 있음
      next(); // 다음 미들웨어로 제어를 전달
    });

    # 함수형 미들웨어

     함수형 미들웨어는 설정값을 받아 재사용이 가능한 미들웨어를 생성하는데 유용합니다. 

    // 함수형 미들웨어 예시: 사용자 권한 체크
    const auth = (memberType) => {
      return (req, res, next) => {
        if (!checkMember(req, memberType)) {
          next(new Error(`User not authorized as ${memberType}`));
          return;
        }
        next();
      };
    };
    
    // 사용 예시: admin 권한을 요구하는 라우트
    app.use("/admin", auth("admin"), adminRouter);
    
    // 사용 예시: member 권한을 요구하는 라우트
    app.use("/users", auth("member"), userRouter);

     

    이렇게 하면 `auth` 함수를 사용하여 각각 다른 권한을 요구하는 라우트에 미들웨어를 쉽게 적용할 수 있습니다. 


    # 에러 처리 미들웨어

    에러가 발생했을 때 실행되는 미들웨어입니다. 다음과 같이 에러가 발생하면 에러 처리 미들웨어로 전달됩니다. 

    // 특정 경로에 대한 GET 요청을 처리하는 미들웨어 등록
    app.get('/error', (req, res, next) => {
        next(); // next()에 인수가 없다면, 다음 미들웨어 함수로 진행
    }, (req, res) => { 
        try {
            // ... 에러 발생 코드
        } catch (err) {
            error(err); // next()에 인수가 있다면, 에러 처리 미들웨어로 이동
        }  
    });
    
    // 에러 처리 미들웨어는 인자로 err, req, res, next를 받는다.
    // 매개변수는 4개이며 모든 매개변수를 사용하지 않더라도 반드시 4개여야 한다.
    app.use((err, req, res, next) => { 
        console.error(err);
        res.status(500).send(err.message); 
    });

     

    `/error` 경로에 대한 GET 요청을 처리하는 두 개의 미들웨어를 등록하고 있습니다. 첫 번째 미들웨어에서는 `next()`를 호출하여 다음 미들웨어로 이동합니다. 두 번째 미들웨어에서는 에러를 처리하고, 에러가 발생할 경우 `error()` 함수를 호출하고 해당 에러처리 미들웨어로 이동하게 됩니다. 

     

    에러처리 미들웨어는 인자로 `err`, `req`, `res`, `next`를 받으며, 매개변수는 반드시 4개여야 합니다. 


     

    # 핵심 정리

     

    1. 미들웨어는 Express 앱의 핵심으로, 요청과 응답 중간에서 작동하여 기능을 추가하거나 조작하며, 독립적인 함수로 작성되어 req, res, next를 매개변수로 받아 사용합니다.

     

    2. `next()`를 통해 다음 미들웨어로 이동할 수 있습니다.

     

    3.함수형 미들웨어는 설정값을 다르게 하여 여러 용도로 활용할 수 있습니다.

     

    4. `app.use()`는 항상 실행되는 미들웨어로 경로를 지정하지 않아 모든 요청에서 실행 됩니다.

     

    5. 에어처리 미들웨어는 `err`,`req`,`res`, `next`를 인자로 받아 전역적으로 에러를 처리합니다. 

Designed by Tistory.