미들웨어(Middleware) 함수
Express는 자체적인 최소한의 기능을 가진 라우팅 및 미들웨어 웹 프레임워크다. Express 애플리케이션은 일련의 미들웨어 함수를 호출한다.
미들웨어 함수란 요청 오브젝트(req)와 응답 오브젝트(res) 그리고 애플리케이션의 요청-응답 주기 중 다음 미들웨어 함수에 대한 액세스 권한을 가지는 함수다. express내에서 미들웨어 함수는 next()로 표시된다.
현재 미들웨어 함수가 요청-응답 주기를 종료하지 않는 경우 next()를 호출하여 다음 미들웨어 함수에 제어를 전달해야 한다. 만약 다음 next() 미들웨어 함수로 제어권을 전달하지 않는 경우 요청은 정지된 채로 아무것도 하지 않게 된다.
미들웨어 함수 구조
미들웨어는 프로세스 중간에 관여해 특정 역할을 수행하게 된다. express에서는 수많은 미들웨어 함수가 존재하기 때문에 필요할 때 마다 필요한 미들웨어 함수를 적용해 서버를 구성할 수 있다. 미들웨어의 일반적인 구성은 아래 그림과 같다.
간단한 미들웨어 함수 작성하기
미들웨어 함수 중 가장 간단한 LOGGER 미들웨어는 현재 상황을 출력하는 기능외에 아무런 기능을 수행하지 않는다. 모든 요청이 들어오는 경우에 LOGGER 미들웨어가 실행되도록 app 인스턴스에 바인딩시킨다.
주의할 점은 LOGGER 미들웨어 함수에서 next() 함수를 호출하면서 다음 미들웨어에 제어권을 넘겨주고 있다는 사실이다. 만약 next() 함수를 호출하지 않으면 서버가 멈춰버린다.
// Logger 미들웨어 함수
const myLogger = function(req, res, next){
const {method, url} = req;
console.
log(`http request method is ${method}, url is ${url}`);
// next();
}
// Logger 미들웨어 로드
// 모든 요청에 대해 Logger 미들웨어 실행됨
app.use(myLogger);
// 모든 요청에 대해 응답 진행
app.use('/', (req, res)=>{
res.send("This is the Express Server!");
})
next() 함수 제거한 경우
여기서 서버가 멈춰버림. 다음 제어권을 받을 함수를 찾지 못하기 때문
미들웨어 함수가 할 수 있는 것?
- 모든 코드 실행
- 요청 및 응답 오브젝트에 대한 변경 실행
- 요청-응답 주기 종료
- 스택 내 다음 미들웨어 함수 호출 가능
미들웨어를 사용하는 상황
- 모든 요청에 대해 url이나 메소드를 확인 하는 경우
- POST 요청 등에 포함된 body(payload로 전달)를 구조화 하는 경우
- 모든 요청/응답에 CORS 헤더를 붙이는 경우
- 요청 헤더에 사용자 인증 정보가 담겨있는지 확인하는 경우
애플리케이션 레벨 미들웨어
애플리케이션 레벨 미들웨어 함수는 선택적인 마운트 경로를 통해 로드가 가능하다. 일련의 미들웨어 함수를 함께 로드할 수도 있다. 여러개의 미들웨어 함수를 하나의 마운트 위치 지정하고 미들웨어 시스템의 하위 스택을 생성할 수 있다.
app.use()이나 app.put(), app.get()등 HTTP 메소드를 app 인스턴스에 바인드해서 사용할 수 있다. 마운트 경로가 없는 미들웨어 함수는 앱이 요청을 수신할 때 마다 실행된다.
app.use() 미들웨어 함수에서 마운트가 /data/:id 로 지정된 경우 모든 HTTP 메소드에서 실행된다.
const app = express();
app.use((req, res)=>{
console.log("Time : ", Date.now());
next();
})
app.use('/data/:id', (req, res)=>{
console.log('Request Method : ', req.method);
next();
})
하나의 마운트 경로에 대해 일련의 미들웨어 함수를 위치시킬 수 있다. 일련의 미들웨어 함수는 하위 스택을 생성하게 된다.
app.use('/', (req, res, next)=>{
console.log(`resquest : ${req.originalUrl}`)
next();
},(req, res, next)=>{
console.log(`request type : ${req.method}`)
res.send("this is the second function")
})
라우터 레벨 미들웨어
라우터 레벨 미들웨어는 express 인스턴스에 바인딩 되지 않고 express.Router() 인스턴스에 바인딩된다. 나머지 기능은 애플리케이션 레벨 미들웨어와 동일한 방식으로 작동한다.
const router = express.Router();
router.use(), router.METHOD()를 사용해서 라우터 레벨 미들웨어를 로드할 수 있다. 미들웨어에 마운트 지점이 지정되지 않은 경우 모든 요청에 대해 미들웨어 함수가 실행된다.
const app = express();
const router = express.Router();
router.use(function (req, res, next) {
console.log('Time:', Date.now());
next();
});
router.use('/user/:id', function(req, res, next) {
console.log('Request URL:', req.originalUrl);
next();
}, function (req, res, next) {
console.log('Request Type:', req.method);
next();
});
CORS 미들웨어 함수 사용
순수 Node.js에서 CORS 헤더를 붙이기 위해서는 응답 객체의 whiteHead를 사용한다. 매번 Access-Control-Allow-* 헤더를 정의해줘야 한다. 또한 preflight를 위한 라우팅 코드도 구현해줘야 한다.
const basic_CORS_Headers = {
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Method' : 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers' : 'Content-Type, Accept',
'Access-Control-Max-Age' : 10
}
if(req.method === 'OPTIONS'){
res.whiteHead(201, basic_CORS_Headers);
res.end();
}
express의 CORS 미들웨어 함수를 사용하면 위 과정을 간략하게 바꿀 수 있다.
const cors = require('cors');
// 애플리케이션 레벨 미들웨어 use()를 통해 cors()를 로드함.
// 모든 요청에 CORS를 허용함.
app.use(cors());
// 마운트를 지정해서 특정 메소드에 대해 CORS 적용
app.get('/test/:id', cors(), (req, res)=>{
res.json("This is about CORS");
})
Reference
'Programming' 카테고리의 다른 글
[Programming] Content-Type과 Accept Header 차이점 (0) | 2022.05.26 |
---|---|
[Web Server] fetch API 사용하는 방법 (0) | 2022.05.26 |
[Web Server] Express Routing query VS params (0) | 2022.05.26 |
[Programming] 웹서버(Web)와 웹 어플리케이션 서버(WAS) 차이점 The difference between Web Server and Web Application Server (0) | 2022.05.25 |
[Programming] CORS란? (preflight, OPTIONS 메소드?) (0) | 2022.05.25 |
댓글