NestJS에 관한 강의를 듣다 보니 라우터와 미들웨어라는 용어가 자주 등장했다.
하지만 이런 개념을 처음 배우다 보니 다소 추상적으로 느껴져서 쉽게 와닿지 않는 부분이 있었다.
그래서 두 개념의 차이점을 조금 더 명확하게 이해하기 위해 추가로 찾아보게 되었다.
라우팅
라우팅은 특정 엔드포인트(URI + HTTP 메소드(GET,POST,,,) )에 대한 클라이언트 요청에 애플리케이션이 응답하는 방법을 정의해두는 것을 말한다.
예를 들어 " '/user' 구조의 URI가 get 메소드로 올 대는 user.html을 보내주자!" 와 같은 규칙들을 미리 짜놔야 한다.
Express에는 이를 간단하게 처리해주는 함수가 존재한다.
구조는 다음과 같다.
app.METHOD(PATH,HANDLER);
- app은 express의 인스턴스
- METHOD는 HTTP 요청 메소드
- PATH는 서버의 경로
- HANDLER는 METHOD 와 PATH가 일치할 때 실행되는 함수
ex)
app.get('users', (req, res) => {
res.send('this is users');
})
HANDLER 2개를 순차 실행할 수도 있다.
app.get('users', (req, res, next) => {
console.log('the response will be sent by the next function ,,,,,');
next(); //반드시 next를 호출해줘야 다음 HANDLER로 갈 수 있다.
}, function (req, res) {
res.send('HELLOOO');
});
라우터에서 HANDLER는 2개 이상 올 수 있다. HANDLER는 인자 순서로 차례대로 실행된다. 다음 HANDLER를 실행시키고 싶다면,
반드시 핸들러에 next라는 인자를 추가해주고, HANDLER 내부의 마지막에 next를 호출해줘야 한다.
여기서, HANDLER의 인자가 (req, res, next)인 함수를 미들웨어라고 한다!
그리고 주의할점은 라우팅 경로 상에서 응답은 한번만 해야 한다는 것이다. 두번 이상 하면 에러난다.
미들웨어
그럼 미들웨어는 뭘까?
인자가 req,res, next인 함수 라고 생각하면 편할 것 같다. 조금 더 이론적으로 말하면 FE의 요청 과 라우터의 응답 사이에서 실행되는 함수다.
req, res 는 각각 요청, 응답 객체고, next는 아주 특별한 함수다.
만약에 next가 인자 없이 그냥 호출되면 이는 '다음 라우트로 이동'이라는 뜻이고, next안에 있는 인자가 있는 상태로 호출되면 바로 '에러 처리 미들웨어'로 이동한다. 라우트 이동시 req,res 객채는 그대로 전달된다.
따라서 (req, res, next) 3개의 인자만 가지는 다른 미들웨어와 달리
에러처리 미들웨어는 err라는 인자가 추가된다. err의 정체는 next의 인자값이다.
미들웨어가 들어가는 위치는 일반적으로 다음과 같다.
//모든 요청에 대해 적용
app.use(Middleware);
//라우터에 적용
router.use(Middleware);
//METHOD, PATH에 맞는 요청일때만 적용
app.METHOD(PATH, Middleware[, Middleware[, Middleware ...]])
큼직한 개념은 이렇고,
공식문서를 참고하여 좀 더 자세히 보자
Express 미들웨어의 구조
Express 미들웨어는 기본적으로 세 가지 인수를 받는다.
- req (요청 객체)
- res (응답 객체)
- next (다음 미들웨어로 넘어가기 위한 함수)
미들웨어 함수는 next()를 호출하여 다음 미들웨어 or 라우터로 요청을 전달할 수 있으며,
next()를 호출하지 않으면 현재 미들웨어에서 요청이 종료된다.
예를 들어, res.send()를 호출하여 응답을 반환하면 요청 처리가 해당 미들웨어에서 완료된다.
그리고 이 미들웨어는 순서가 굉장히 중요하다.
순서대로 실행된다.
따라서 실행하고 res를 반환한 라우터보다 미들웨어가 아래 있으면 해당 미들웨어는 실행되지 않는다.
ex )
function exampleMiddleware(req, res, next) {
console.log('Middleware executed');
next(); // 다음 미들웨어로 제어를 넘깁니다.
}
미들웨어 사용 방법
글로벌 미들웨어
Express 애플리케이션에서 모든 메서드 요청에 대해 실행되는 미들웨어로, app.use()를 사용하여 등록한다.
const express = require('express');
const app = express();
app.use(exampleMiddleware); // 모든 요청에 대해 실행됨
특정 메서드 요청에서만 사용하고 싶다면
app.get, app.post 이런식으로 쓰면 된다.
특정 경로에 적용되는 미들웨어
특정 경로에서만 실행되도록 미들웨어를 설정할 수 있다. 예를 들어, /user 경로에만 적용하려면 다음과 같이 작성할 수 있다.
app.use('/user', exampleMiddleware); // /user 경로에 대해서만 실행
특정 라우터에 적용되는 미들웨어
특정 라우트에서만 미들웨어를 사용하고 싶을 때는 라우트에 직접 미들웨어를 추가할 수 있다.
app.get('/profile', exampleMiddleware, (req, res) => {
res.send('User profile');
});
//또는 이런식으로 사용할 수도 있다.
app.get('/profile', (req, res, next) => {
console.log("이건 profile경로에서만 사용하는 미들웨어");
next();
})
app.get('/profile', (req, res) => {
res.send('User profile');
});
미들웨어의 주요 목적
- 요청 데이터 처리: express.json()을 사용해 JSON 형식의 데이터를 파싱하거나, express.urlencoded()를 통해 URL-encoded 데이터를 파싱.
- 로깅: 요청 메서드, 경로, 응답 시간 등을 로그로 기록하기 위해 사용된다. 예를 들어, morgan 미들웨어는 HTTP 요청 로깅에 자주 사용된다.
- 인증 및 권한 부여: 요청에 포함된 토큰을 검증하거나, 사용자의 권한을 확인하여 특정 자원에 대한 접근을 제한하는 데 사용된다.
- 보안: helmet과 같은 패키지를 사용해 보안 헤더를 추가하거나, CORS 설정을 통해 허용된 도메인만 요청을 보낼 수 있도록 제한할 수 있다.
- 오류 처리: Express에서는 에러 핸들러 미들웨어를 통해 모든 오류를 한 곳에서 처리하고, 일관된 오류 응답을 보낼 수 있다. 이때 오류 핸들러 미들웨어는 err, req, res, next의 네 가지 인수를 받는다.
예를 들어, 요청 로깅과 인증 검사를 위한 미들웨어를 다음과 같이 작성할 수 있다.
// 로깅 미들웨어
function loggingMiddleware(req, res, next) {
console.log(`${req.method} ${req.url}`);
next(); // 다음 미들웨어로 이동
}
// 인증 미들웨어
function authMiddleware(req, res, next) {
if (req.headers.authorization) {
next(); // 인증 성공 시 다음 미들웨어로 이동
} else {
res.status(401).send('Unauthorized');
}
}
app.use(loggingMiddleware); // 모든 요청에 대해 로깅
app.get('/secure', authMiddleware, (req, res) => {
res.send('Secure data');
});
loggingMiddleware -> 모든 요청에 대해 로그를 남김
authMiddleware -> /secure 경로에 접근할 때 인증을 확인
참고
탄탄한 백엔드 NestJs 강의
'NestJS' 카테고리의 다른 글
[NestJS] Provider, Module (0) | 2024.11.20 |
---|---|
[NestJS] Controller (0) | 2024.11.20 |
[Express] 라우터 분리, 모듈화 (0) | 2024.11.14 |
[Express] CRUD 기능 만들기 (0) | 2024.11.14 |
TypeScript와 Express로 Node.js 서버 구축하기 (7) | 2024.11.13 |