Expressjs에서 미들웨어 및 app.use는 실제로 무엇을 의미합니까?


228

내가 본 거의 모든 Express 앱에는 app.use미들웨어에 대한 설명이 있지만 실제로 미들웨어가 무엇이며 app.use명령문이 무엇을하고 있는지에 대한 명확하고 간결한 설명을 찾지 못했습니다 . 표현 문서 자체조차도 약간 모호합니다. 이 개념들을 설명해 주시겠습니까?


3
참고로 비슷한 질문 (이것은 이전에 만들어졌습니다) : stackoverflow.com/questions/11321635/…
ericsoco

43
^ 하! 이 두 질문은 의견에서 서로를 참조합니다.
Julian H. Lam

17
Cirular Reference입니다.
Steve K

6
Express.js 미들웨어 Demystified 주제에 대한 훌륭한 블로그 게시물. 이것은 이전에 여기에 복사하여 붙여 넣었습니다. 물론 표절이지만 원래 게시물은 여전히 ​​매우 도움이되므로 여기에 링크를 남겨 두십시오.
totymedli

1
express.js 미들웨어에 대한 기사를 썼습니다. 여기 링크가 있습니다 : nodexplained.com/blog-detail/2017/12/31/…
shrawan_lakhe

답변:


111

미들웨어

나는 새 프로젝트에서 미들웨어 개념을 분리하는 중반 쯤입니다.

미들웨어를 사용하면 처리해야 할 작업 스택을 정의 할 수 있습니다. Express 서버 자체는 미들웨어의 스택입니다.

// express
var app = express();
// middleware
var stack = middleware();

그런 다음 호출하여 미들웨어 스택에 레이어를 추가 할 수 있습니다 .use

// express
app.use(express.static(..));
// middleware
stack.use(function(data, next) {
  next();
});

미들웨어 스택의 계층은 함수이며, n 개의 매개 변수 (표현식 req&에 대한 2 res)와 next함수를 갖습니다.

미들웨어는 계층이 계산을 수행하고 매개 변수를 보강 한 다음을 호출 할 것으로 예상합니다 next.

스택은 처리하지 않으면 아무것도하지 않습니다. Express는 들어오는 HTTP 요청이 서버에서 잡힐 때마다 스택을 처리합니다. 미들웨어를 사용하면 스택을 수동으로 처리합니다.

// express, you need to do nothing
// middleware
stack.handle(someData);

보다 완전한 예 :

var middleware = require("../src/middleware.js");

var stack = middleware(function(data, next) {
    data.foo = data.data*2;
    next();
}, function(data, next) {
    setTimeout(function() {
        data.async = true;
        next();
    }, 100)
}, function(data) {
    console.log(data);
});

stack.handle({
    "data": 42
})

명시 적으로 용어는 들어오는 모든 HTTP 요청에 대해 명시 적으로 처리하려는 작업 스택을 정의합니다.

연결이 아닌 Express (익스프레스) 측면에서 글로벌 미들웨어 및 라우팅 특정 미들웨어가 있습니다. 즉, 들어오는 모든 HTTP 요청에 미들웨어 스택을 첨부하거나 특정 경로와 상호 작용하는 HTTP 요청에만 미들웨어 스택을 첨부 할 수 있습니다.

익스프레스 및 미들웨어의 고급 예 :

// middleware 

var stack = middleware(function(req, res, next) {
    users.getAll(function(err, users) {
        if (err) next(err);
        req.users = users;
        next();  
    });
}, function(req, res, next) {
    posts.getAll(function(err, posts) {
        if (err) next(err);
        req.posts = posts;
        next();
    })
}, function(req, res, next) {
    req.posts.forEach(function(post) {
        post.user = req.users[post.userId];
    });

    res.render("blog/posts", {
        "posts": req.posts
    });
});

var app = express.createServer();

app.get("/posts", function(req, res) {
   stack.handle(req, res); 
});

// express

var app = express.createServer();

app.get("/posts", [
    function(req, res, next) {
        users.getAll(function(err, users) {
            if (err) next(err);
            req.users = users;
            next();  
        });
    }, function(req, res, next) {
        posts.getAll(function(err, posts) {
            if (err) next(err);
            req.posts = posts;
            next();
        })
    }, function(req, res, next) {
        req.posts.forEach(function(post) {
            post.user = req.users[post.userId];
        });

        res.render("blog/posts", {
            "posts": req.posts
        });
    }
], function(req, res) {
   stack.handle(req, res); 
});

4
흠 ...이 경우 미들웨어는 자신의 라이브러리 또는 표현의 일부입니까?
iZ.

5
멋있는. 나는 여전히 app.use()문법에 약간 혼란스러워 합니다. 미들웨어의 실제 리턴 값은 무엇이며 어떻게 use합니까?
iZ.

9
@iZ use는 스택에 추가합니다. 그런 다음 모든 단일 요청이 스택을 통과합니다.
Raynos

7
프로젝트의 "미들웨어"링크 인 @Raynos가 손상되었습니다.
Lee

1
@Raynos이지만 Express에서 미들웨어가 여전히 사용되고 있습니까? 이게 무슨 소리 야?
Timo Huovinen

60

일을 단순화 한 후 웹 서버는 요청을 받아 응답을 출력하는 함수로 볼 수 있습니다. 따라서 웹 서버를 함수로 볼 경우 웹 서버를 여러 조각으로 구성하고 더 작은 기능으로 분리하여 구성이 원래 기능이 될 수 있습니다.

미들웨어는 다른 사람과 구성 할 수있는 더 작은 기능이며 재사용 할 수 있다는 것이 명백한 이점입니다.


33

나는 이전 답변에서 언급되지 않은 것을 추가하기 위해 늦은 답변을 추가합니다.

이제 미들웨어가 클라이언트 요청서버 응답 사이에서 실행되고 있음을 분명히해야합니다 . 가장 일반적인 미들웨어 기능은 오류 관리, 데이터베이스 상호 작용, 정적 파일 또는 기타 리소스에서 정보 얻기입니다. 미들웨어 스택에서 이동하려면 다음 콜백을 호출해야합니다. 미들웨어 기능 끝에서 플로우의 다음 단계로 이동하는 것을 볼 수 있습니다.

app.use접근 방식을 사용하고 다음 과 같은 흐름을 가질 수 있습니다 .

var express = require('express'),
    app = express.createServer(),                                                                                                                                                 
    port = 1337;

function middleHandler(req, res, next) {
    console.log("execute middle ware");
    next();
}

app.use(function (req, res, next) {
    console.log("first middle ware");                                                                                                             
    next();
});

app.use(function (req, res, next) {
    console.log("second middle ware");                                                                                                             
    next();
});

app.get('/', middleHandler, function (req, res) {
    console.log("end middleware function");
    res.send("page render finished");
});

app.listen(port);
console.log('start server');

그러나 다른 접근 방식을 사용하고 각 미들웨어를 함수 인수로 전달할 수도 있습니다. 다음은 Midoware가 클라이언트로 다시 전송 되기 전에 midleware가 Twitter, Github 및 블로그 플로우를 가져 오는 MooTools Nodejs 웹 사이트예입니다response . 에서 함수가 인수로 전달되는 방식에 유의하십시오 app.get('/', githubEvents, twitter, getLatestBlog, function(req, res){. 사용 app.get은 GET 요청에 대해서만 app.use호출되며 모든 요청에 ​​대해 호출됩니다.

// github, twitter & blog feeds
var githubEvents = require('./middleware/githubEvents')({
    org: 'mootools'
});
var twitter = require('./middleware/twitter')();
var blogData = require('./blog/data');
function getLatestBlog(req, res, next){
    blogData.get(function(err, blog) {
        if (err) next(err);
        res.locals.lastBlogPost = blog.posts[0];
        next();
    });
}

// home
app.get('/', githubEvents, twitter, getLatestBlog, function(req, res){
    res.render('index', {
        title: 'MooTools',
        site: 'mootools',
        lastBlogPost: res.locals.lastBlogPost,
        tweetFeed: res.locals.twitter
    });
});

2
Express.js가 라우터 기반 미들웨어 마운트를 지원하는지 여부 에 대한 답을 찾고 있었습니까? 당신이 당신의 대답에 그것을 보여준 것 같습니다.
Selçuk

위의 예제를 설명 할 수 있습니까?, 많은 함수를 app.get (...)에 어떻게 전달할 수 있으며 어떤 순서로 호출됩니까?
Tanner Summers

2
안녕 @TannerSummers,이 .get()방법은 세 가지 유형의 인수, 첫 번째, 마지막 및 중간 인수를 취합니다. 내부적으로는 2보다 많은 인수가 있는지 감지하고 그 중 하나를 미들웨어 함수로 사용하여 왼쪽에서 오른쪽으로 호출합니다.
Sergio

22

expressjs 가이드 는 귀하의 질문에 대한 깔끔한 답변을 제공합니다. 가이드의 짧은 스 니펫을 게시하고 있으며 가이드는 매우 좋습니다.

Express 앱에서 사용할 미들웨어 작성

개요

미들웨어 함수는 요청 오브젝트 ( req ), 응답 오브젝트 ( res ) 및 애플리케이션의 요청-응답주기에서 다음 함수에액세스 할 수있는함수입니다. 다음 기능은 Express 라우터의 기능으로, 호출 될 때 현재 미들웨어에 이어 미들웨어를 실행합니다.

미들웨어 기능은 다음 작업을 수행 할 수 있습니다.

  • 모든 코드를 실행하십시오.
  • 요청 및 응답 오브젝트를 변경하십시오.
  • 요청-응답주기를 종료하십시오.
  • 스택에서 다음 미들웨어를 호출하십시오.

현재 미들웨어 함수가 요청-응답주기를 종료하지 않으면 next () 를 호출 하여 제어를 다음 미들웨어 함수로 전달 해야합니다 . 그렇지 않으면 요청이 중단됩니다.

여기에 이미지 설명을 입력하십시오

다음은 간단한 "Hello World"Express 응용 프로그램의 예입니다. 이 기사의 나머지 부분에서는 두 개의 미들웨어 함수를 정의하고 애플리케이션에 추가합니다. 하나 는 간단한 로그 메시지를 인쇄하는 myLogger 이고 다른 하나 는 HTTP 요청의 시간 소인을 표시하는 requestTime 1 입니다.

var express = require('express')
var app = express()

app.get('/', function (req, res) {
  res.send('Hello World!')
})

app.listen(3000)   

미들웨어 기능 myLogger

다음은“myLogger”라는 미들웨어 함수의 간단한 예입니다. 이 함수는 앱에 대한 요청이 통과 할 때 "LOGGED"를 인쇄합니다. 미들웨어 함수는 myLogger라는 변수에 지정됩니다.

var myLogger = function (req, res, next) {
  console.log('LOGGED')
  next()
}

next ()에 대한 호출을 주목하십시오 . 이 함수를 호출하면 앱에서 다음 미들웨어 함수가 호출됩니다. 다음 () 함수는 Node.js를 또는 익스프레스 API의 일부가 아니라 미들웨어 함수에 전달 된 세 번째 인수입니다. 다음 () 함수는 어떤 이름 할 수 있지만 관례 적으로 항상 "다음"이름이 지정됩니다. 혼동을 피하려면 항상이 규칙을 사용하십시오.

미들웨어 함수를로드하려면 미들웨어 함수를 지정하여 app.use ()를 호출 하십시오 . 예를 들어 다음 코드 는 루트 경로 (/) 로의 경로 이전에 myLogger 미들웨어 함수를 로드합니다 .

var express = require('express')
var app = express()

var myLogger = function (req, res, next) {
  console.log('LOGGED')
  next()
}

app.use(myLogger)

app.get('/', function (req, res) {
  res.send('Hello World!')
})

app.listen(3000)

앱이 요청을받을 때마다 "LOGGED"메시지를 터미널에 인쇄합니다.

미들웨어 로딩 순서는 중요합니다. 먼저로드 된 미들웨어 기능도 먼저 실행됩니다.

경우 myLogger이 루트 경로에 대한 경로 후로드, 요청이 결코 도달하지 루트 경로의 경로 핸들러가 요청 - 응답주기를 종료하기 때문에 응용 프로그램은, "LOGGED"를 인쇄하지 않습니다.

미들웨어 함수 myLogger는 단순히 메시지를 인쇄 한 후 next () 함수를 호출하여 요청을 스택의 다음 미들웨어 함수로 전달 합니다.


  1. 이 게시물에는 myLogger 미들웨어 만 포함됩니다. 추가 게시물을 보려면 여기 에서 원본 expressjs 안내서를 참조하십시오 .


1
아주 좋은 설명입니다.
Drumbeg

특급 사이트 herejs.com/en/guide/writing-middleware.html 에서 구할 수 있습니다 . 정말 좋습니다. 왜 지금까지 아무도 언급하지 않았는지 궁금합니다.
Suraj Jain

2
좋은데 내가 본 가장 명확한 설명이며, 아무도 그것을 참조하지 않은 것이 이상합니다!
Drumbeg 2019

1
잘 설명
Rehan Shikkalgar

미들웨어 로딩 순서는 중요합니다. 먼저로드 된 미들웨어 기능도 먼저 실행됩니다. : 이것은 중요한 메모입니다. 다른 대답은 이것을 언급하지 않습니다. 파이썬에서만 일한 초보자에게는 이런 일이 결코 발생하지 않았으므로 매우 중요합니다.
Tessaracter

11

===== 매우 간단한 설명 =====

미들웨어는 종종 Express.js 프레임 워크에서 사용되며 node.js의 기본 개념입니다. 간단히 말해서, 기본적으로 응용 프로그램의 요청 및 응답 객체에 액세스 할 수있는 기능입니다. 내가 생각하고 싶은 방법은 요청이 응용 프로그램에 의해 처리되기 전에 요청이 통과하는 일련의 '확인 / 사전 화면'입니다. 예를 들어, 미들웨어는 애플리케이션으로 진행하기 전에 요청이 인증되는지 여부를 판별하고 요청이 인증되지 않은 경우 또는 각 요청을 로깅하기 위해 로그인 페이지를 리턴하는 데 적합합니다. 다양한 기능을 가능하게하는 많은 타사 미들웨어를 사용할 수 있습니다.

간단한 미들웨어 예 :

var app = express();
app.use(function(req,res,next)){
    console.log("Request URL - "req.url);
    next();
}

위의 코드는 들어오는 각 요청에 대해 실행되고 요청 URL을 기록합니다. next () 메소드는 본질적으로 프로그램을 계속할 수있게합니다. next () 함수가 호출되지 않으면 프로그램은 더 이상 진행되지 않으며 미들웨어 실행시 정지됩니다.

몇 가지 미들웨어 문제 :

  1. 요청이 각 순서대로 순차적으로 진행되므로 애플리케이션의 미들웨어 순서가 중요합니다.
  2. 미들웨어 함수에서 next () 메소드를 호출하지 않으면 요청 처리가 중단 될 수 있습니다.
  3. 미들웨어 기능에서 req 및 res 오브젝트를 변경하면 req 및 res를 사용하는 애플리케이션의 다른 부분에서 변경 사항을 사용할 수 있습니다.

1
대단히 감사합니다! 이것은 지금까지 이것을 이해하는 가장 좋은 설명입니다. 질문, 미들웨어로 코드를 읽고 있는데 호출하지 next()않지만 return next(). 차이점은 무엇입니까?
KansaiRobot

감사합니다 종류의 단어에 대한 많은 친구 ... 우리가 next()우리가 다음 미들웨어가 호출되는 원하기 때문에, 내가 생각하지 않는다 next()거나 return next(), 어떤 차이를 확인해야합니다! 아직도 그것은 코드가 무엇인지에 달려 있습니다 ...
Vaibhav Bacchav

7

미들웨어는 입력 / 소스 다음에 중간에서 실행되는 기능으로, 최종 출력 일 수 있거나주기가 완료 될 때까지 다음 미들웨어가 사용할 수있는 출력을 생성합니다.

마치 완성, 평가 또는 거부 될 때까지 움직일 때 수정되는 조립 라인을 통과하는 제품과 같습니다.

미들웨어는 일부 값 (예 : 매개 변수 값)이 작동 할 것으로 예상하고 일부 논리에 따라 미들웨어가 다음 미들웨어를 호출하거나 호출하지 않거나 클라이언트에 응답을 보냅니다.

미들웨어 개념을 여전히 파악할 수없는 경우 데코레이터 또는 명령 패턴 체인과 유사한 방식입니다.


5

미들웨어는 사용자 정의 핸들러가 호출되기 전에 Express js 라우팅 계층에서 호출하는 체인 함수의 서브 세트입니다. 미들웨어 기능은 요청 및 응답 오브젝트에 대한 전체 액세스 권한을 가지며 이들 중 하나를 수정할 수 있습니다.

미들웨어 체인은 항상 정의 된 순서대로 호출되므로 특정 미들웨어가 수행하는 작업을 정확히 아는 것이 중요합니다.
미들웨어 함수가 완료되면 다음 인수를 함수로 호출하여 체인에서 다음 함수를 호출합니다.
전체 체인이 실행 된 후 사용자 요청 핸들러가 호출됩니다.


1

일을 단순하게 유지하십시오!

참고 : 답변은 ExpressJS 내장 미드들웨어 사례와 관련이 있지만 미들웨어의 정의 및 사용 사례가 다릅니다.

필자의 관점에서 미들웨어는 유틸리티 또는 도우미 기능으로 작동하지만app.use('path', /* define or use builtin middleware */) 클라이언트의 각 HTTP 요청에 필요한 매우 일반적인 작업을 수행하기위한 코드를 작성하지 않기를 원 함으로써 활성화 및 사용이 완전히 선택적 입니다. 대부분의 응용 프로그램에서 매우 일반적인 쿠키, CSRF 토큰 및 ... 처리와 같은 미들웨어는 스택, 시퀀스 또는 작업 순서에 따라 클라이언트의 각 HTTP 요청에 대해 이러한 모든 작업을 수행하는 데 도움이됩니다. 단일 클라이언트 요청 단위 .

예:

클라이언트 요청을 수락하고 요청에 따라 응답을 제공하는 것은 웹 서버 기술의 특성입니다.

"Hello, world!"만으로 응답을 제공한다고 상상해보십시오. 웹 서버의 루트 URI에 대한 GET HTTP 요청에 대한 텍스트는 매우 간단한 시나리오이며 다른 것이 필요하지 않습니다. 대신 현재 로그인 한 사용자를 확인한 다음 "Hello, Username!" 이 경우 평소보다 더 많은 것이 필요합니다. 모든 클라이언트 요청 메타 데이터를 처리하고 클라이언트 요청에서 가져온 식별 정보를 제공하기 위해 미들웨어가 필요합니다. 그 정보에 따라 현재 사용자를 고유하게 식별 할 수 있으며 그에 대한 응답이 가능합니다 / 그녀는 관련 데이터가 있습니다.

누군가를 돕기를 바랍니다!


-1

매우 기본적인 용어로 이것을 이와 같이 설명하고 싶다면 traversymedia youtube channel express crash course에서 이것을 배웁니다.
좋아, 미들웨어는 경로를 호출 한 후 실행하는 함수입니다.

var logger = function(req, res, next){
   console.log('logging...');
   next();
}

app.use(logger);

이 로거 기능은 페이지를 새로 고칠 때마다 실행되므로 페이지가 작업 API 호출을 렌더링 한 후 기본적으로 모든 것을 재설정 한 후 필요한 작업을 수행 할 수 있습니다. 미들웨어의 경로 기능 순서가 정말로 중요하거나 작동하지 않기 전에이 미들웨어를 넣으십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.