-
[Express] app.use()에 대해개발/node.js 2020. 3. 28. 18:44
미들웨어 레벨
app.use() 함수에 대해 알아보기 전에 미들웨어 동작 레벨에 대해 알아 보겠다.
1. 애플리케이션 레벨
2. 라우터 레벨
일단은 두가지로 나누어질 수 있다.
물론 단계는 애플리케이션 -> 라우터 단계로 실행순서가 이루어져 있다고 볼 수 있다.
애플리케이션 레벨과 라우터 레벨은 실행단계의 차이지 기능적으론 다른 점이 없다.
애플리케이션 분기 + 라우터 분기 로 더 세세하게 요청 URL을 분리하여 제어가 가능하다는 점이다.
코드로 알아보자.
var indexRouter = require('./routes/index'); var usersRouter = require('./routes/users'); var app = express(); app.use('/', indexRouter); app.use('/users', usersRouter);
위의 예는 애플리케이션 단계에서 '/' 와 '/users'로 URL을 분리하여 처리를 하도록 한것이다.
또한 callback 인자에 express.Router() 오브젝트를 생성하여 넣음으로 라우터 단계에서의 URL 제어도 가능 하도록 등록하였다.
var express = require('express'); var router = express.Router(); /* GET users listing. */ router.get('/', function(req, res, next) { console.log('originalUrl : '+req.originalUrl); console.log('baseUrl : '+req.baseUrl); console.log('path : '+req.path); res.send('respond with a resource'); }); router.get('/user', function(req, res, next) { console.log('originalUrl : '+req.originalUrl); console.log('baseUrl : '+req.baseUrl); console.log('path : '+req.path); res.send('respond with a resource'); }); module.exports = router;
위의 예는 라우터 단계의 미들웨어다.
app.use() 처럼 router.use()도 쓸 수 있고 app.METHOD() 처럼 router.METHOD()도 사용 가능하다.
use와 METHOD의 다른점은 use()는 모든 METHOD에서 동작한다는 것이고 METHOD()는 지정된 요청(GET, POST, PUT, DELETE 등)에서만 동작을 한다는 것
위는 express에서 라우터 기능이 어떻게 흘러가는가를 보여주고 있다.
1. 애플리케이션 단계에서의 URL 제어
- '/', 'users' 두가지 분기
2. 라우터 단계에서의 URL 제어 (예는 'users' 미들웨어)
- '/', 'user' 두가지 분기
위에서 언급한 미들웨어의 라우터 실행 단계는 app.use()의 동작과도 밀접한 관련이 있어서 미리 소개를 하였다.
자 그럼 본격적으로 app.use()에 대해 알아보자.
URL은 '/users/user'로 진행하겠다.
app.use(cookieParser()); app.use('/users', usersRouter); . . . router.get('/', function(req, res, next) { console.log('originalUrl : '+req.originalUrl); console.log('baseUrl : '+req.baseUrl); console.log('path : '+req.path); res.send('respond with a resource'); }); router.get('/user', function(req, res, next) { console.log('originalUrl : '+req.originalUrl); console.log('baseUrl : '+req.baseUrl); console.log('path : '+req.path); res.send('respond with a resource'); });
모든 요청에 cookieParser()을 실행, '/users'라는 URL이 들어오면 usersRouter을 실행
// cookieParser 로그 p originalUrl : /users/user p baseUrl : p path : /users/user // usersRouter 로그 originalUrl : /users/user baseUrl : /users path : /user
'http://localhost:3000/users/user'을 웹브라우저에 쳤을 때 url의 변화를 로그로 찍어보았다.
여기서 중요한 request 오브젝트가 가지고 있는 멤버변수에 대해 알아보자.
1. originalUrl
- 이 변수는 express 에서 동작하는 http module의 request.url라는 변수를 라우팅을 목적으로 재생성한 변수이다. (cookieParser 가 request.headers.cookie 를 request.cookies로 가공을 거쳐 재생성한 것처럼) 실제 클라이언트가 브라우저에 입력한 url을 뜻한다.
2. baseUrl
- 이 변수는 간단히 말하자면 애플리케이션 레벨에 등록된 URL을 뜻한다. 실제로 app.use() 함수에 path 값을 넣지 않던가 '/'를 통해 모든 요청에 해당하는 미들웨어를 등록하면 위의 cookieParser 로그처럼 값이 비어있다.
3. path
- baseUrl이 애플리케이션 레벨의 URL이라면, 이 변수는 라우터 레벨에 등록된 URL 이다.실행 순서를 같이 보자면
위와 같은 프로세스로 라우팅을 하는 것 같다.
결국 app.use()의 매개변수인 path는 originalUrl과 match하는 애플리케이션 미들웨어를 동작키는 것이고, 그 이후 express.Router()로 등록된 미들웨어일 경우 baseUrl을 제외한 나머지 path로 라우터 미들웨어를 동작시키는 것 같다.
여기서 express.Router()로 등록된 애플리케이션 미들웨어의 path가 root path('/') 일 경우에는 라우터 레벨 단계까지의 path와 일치하여야 실행 되는 것 같다.
물론 매개변수 path는 정규식 표현으로도 실행이 가능하다.
직접 미들웨어를 간단하게 등록하여 아래와 같이 실행 가능하다.
app.use('/users',cookieParser()); app.use('/', (req, res, next)=>{ console.log('모든 요청에 log 남기기'); next(); }); app.use('/', indexRouter); app.use('/users', usersRouter);
http://localhost:3000/users/user 요청 시 log
cookieParser log 모든 요청에 log 남기기 usersRouter '/users/user' log
또한 중복으로 callback 함수를 등록 가능
app.use('/', (req, res, next)=>{ console.log('모든 요청에 log 1'); next(); }, (req, res, next)=>{ console.log('모든 요청에 log 2'); next(); }); app.use('/', indexRouter); app.use('/users', usersRouter);
http://localhost:3000/users/user 요청 시 log
모든 요청에 log 1 모든 요청에 log 2 usersRouter '/users/user'
중복으로 등록된 callback 함수 사이에도 등록된 순서대로 실행되게 되어있다.
연속으로 등록된 callback 메소드의 순서를 제어하기위해, 다음 미들웨어를 호출하고 싶다면 next('route') 를 실행시키면 된다. 이때 path는 동일하여야 하고 app.METHOD()나, router.METHOD()를 사용해야지만 가능하다.
이것이 뜻하는 것은 path가 같은 METHOD로 스택(자료구조?)이 생성되어 순차적으로 실행하기 때문인 것 같다.
아래는 예시이다.
app.use('/', (req, res, next)=>{ console.log('모든 요청에 log 1'); next('route'); }, (req, res, next)=>{ console.log('모든 요청에 log 2'); next(); }); app.use('/', indexRouter); // console.log('indexRouter '/'');
app.use로 아무리 path가 '/'로 같다고는 하나 특정된 METHOD가 아니기 때문에 next('route')가 제대로 동작하지 않는다.
모든 요청에 log 1 모든 요청에 log 2 indexRouter '/'
아마 app.use()에서는 next('route')의 'route' 매개변수를 무시하고 그냥 next()로 동작을 하는 것 같다.
그러나 다음과 같이 app.METHOD()로 get을 특정해버린다면?
app.get('/', (req, res, next)=>{ console.log('모든 요청에 log 1'); next('route'); }, (req, res, next)=>{ console.log('모든 요청에 log 2'); next(); }); app.get('/', indexRouter);
모든 요청에 log 1 indexRouter '/'
원하는 순서대로 라우터 미들웨어가 동작했다. 아마 아래와 같이 생성되어 있을 것이다.
이렇게 오늘은 use(), METHOD() 에 대해서 알아보았다. 다음번엔 이것을 바탕으로 express --ejs 프로젝트의 구조를 알아보자.
'개발 > node.js' 카테고리의 다른 글
[Express]debug 모듈 + VSCode 디버그 연동하기 (0) 2020.04.16 [Express]express 프레임워크 구조(1) (0) 2020.04.13 [Express] 프레임워크 미들웨어(Middleware)란? (0) 2020.03.24