๐ ๏ธ NestJS Middleware ์์ ์ ๋ณต – ์์ฒญ ์ ์ฒ๋ฆฌ, ๋ก๊น , ์ธ์ฆ ํํฐ์ ํต์ฌ
๐ ๏ธ NestJS Middleware ์์ ์ ๋ณต – ์์ฒญ ์ ์ฒ๋ฆฌ, ๋ก๊น , ์ธ์ฆ ํํฐ์ ํต์ฌ
NestJS์์ **Middleware(๋ฏธ๋ค์จ์ด)**๋ HTTP ์์ฒญ์ด Controller์ ๋๋ฌํ๊ธฐ ์ ์ ์คํ๋๋ ํจ์์
๋๋ค.
์ด ๊ธ์ NestJS ๊ณต์ ๋ฌธ์์ Middleware๋ฅผ ํ๊ธ ๋ฒ์ญ + ์ค๋ฌด ์ค์ฌ ํด์ค๋ก ํ์ด๋ธ ๋ธ๋ก๊ทธ์
๋๋ค.
๋ก๊น , ์ธ์ฆ, ์์ฒญ ์กฐ์ ๋ฑ ๋ชจ๋ "์ ์ฒ๋ฆฌ ์์ "์ Middleware์์ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ์ ์์ ๋๋ค.
โ Middleware๋?
NestJS์ Middleware๋ ๋ค์๊ณผ ๊ฐ์ ์ญํ ์ ์ํํฉ๋๋ค:
- ์์ฒญ ๋ก๊น
- ์ธ์ฆ ํ ํฐ ๊ฒ์ฆ
- ์์ฒญ ๊ฐ์ฒด(req) ๊ฐ๊ณต
- ํน์ ๋ผ์ฐํธ ์ ๊ทผ ์ ํ
Express์ ๋งค์ฐ ์ ์ฌํ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๋ฉฐ, ๋ด๋ถ์ ์ผ๋ก Express ๊ธฐ๋ฐ ๋ฏธ๋ค์จ์ด๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
1๏ธโฃ ๊ธฐ๋ณธ Middleware ๊ตฌ์กฐ
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log(`[์์ฒญ] ${req.method} ${req.originalUrl}`);
next(); // ๋ฐ๋์ ํธ์ถ!
}
}
- NestMiddleware ์ธํฐํ์ด์ค ๊ตฌํ
- use() ๋ฉ์๋ ์์์ ์ํ๋ ์์ ์ํ ํ next() ํธ์ถ
2๏ธโฃ Middleware ๋ฑ๋กํ๊ธฐ (forRoutes)
Middleware๋ Module์์ configure() ๋ฉ์๋ ๋ด์ ๋ฑ๋กํฉ๋๋ค.
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
@Module({})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('*'); // ๋ชจ๋ ๋ผ์ฐํธ์ ์ ์ฉ
}
}
์ค๋ฌด ํ
- forRoutes('*'): ์ ์ฒด ๋ผ์ฐํธ์ ์ ์ฉ
- ํน์ ์ปจํธ๋กค๋ฌ ํน์ ๋ฉ์๋๋ง ์ ์ฉํ๊ณ ์ถ์ ๋:
.forRoutes({ path: 'cats', method: RequestMethod.GET })
์ด ๊ตฌ๊ฐ์ ์ค์ ์ ์ฉ ์ง์ ์ผ๋ก ์ ๋์ผ์ค ๊ด๊ณ ํด๋ฆญ๋ฅ ์ด ๋งค์ฐ ๋์ ๊ตฌ๊ฐ์ ๋๋ค.
<ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-XXXXXX"
data-ad-slot="YYYYYY"
data-ad-format="auto"
data-full-width-responsive="true"></ins>
3๏ธโฃ ๋ฏธ๋ค์จ์ด์์ ์์ฒญ ๋ฐ์ดํฐ ์กฐ์
use(req: Request, res: Response, next: NextFunction) {
req.headers['x-custom-header'] = 'PoweredByNestJS';
next();
}
์ด๋ ๊ฒ ํ๋ฉด ์ดํ Controller์์๋ req.headers['x-custom-header'] ๊ฐ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
4๏ธโฃ ์ฌ๋ฌ Middleware ๋์์ ์ ์ฉํ๊ธฐ
consumer
.apply(AuthMiddleware, LoggerMiddleware)
.forRoutes('cats');
NestJS๋ ์ฌ๋ฌ ๊ฐ์ ๋ฏธ๋ค์จ์ด๋ฅผ ์ฒด์ธ ํํ๋ก ๋ฑ๋กํ ์ ์์ต๋๋ค.
์์๋๋ก ์คํ๋๋ฉฐ, next() ํธ์ถ์ ์์ผ๋ฉด ํ์ ๋ฏธ๋ค์จ์ด๊ฐ ์คํ๋์ง ์์ต๋๋ค.
5๏ธโฃ ์ ์ญ ๋ฏธ๋ค์จ์ด ๋ฑ๋ก (Express ๋ฐฉ์)
Nest ์ ํ๋ฆฌ์ผ์ด์ ๋ ๋ฒจ์์ ์ง์ ๋ฑ๋ก๋ ๊ฐ๋ฅํฉ๋๋ค:
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use((req, res, next) => {
console.log('์ ์ญ ๋ฏธ๋ค์จ์ด');
next();
});
await app.listen(3000);
}
๋จ์ : DI ๋ถ๊ฐ๋ฅ → Nest ์์กด์ฑ์ ์ฃผ์
ํ ์ ์์
๊ถ์ฅ ๋ฐฉ์์ @Injectable()์ ์ฌ์ฉํ DI ๊ธฐ๋ฐ์ Nest Middleware์
๋๋ค.
6๏ธโฃ ์ค๋ฌด ์์ : JWT ํ ํฐ ์ธ์ฆ ๋ฏธ๋ค์จ์ด
@Injectable()
export class AuthMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
const token = req.headers['authorization'];
if (!token) {
return res.status(401).json({ message: '์ธ์ฆ ํ์' });
}
// ํ ํฐ ๊ฒ์ฆ ๋ก์ง ์ถ๊ฐ ๊ฐ๋ฅ
next();
}
}
Tip: ์ธ์ฆ์ Middleware์์ 1์ฐจ์ ์ผ๋ก ํ์ธํ๊ณ , ์ธ๋ถ ๊ถํ์ Guard์์ ์ฒ๋ฆฌํ๋ ๊ตฌ์กฐ๊ฐ ์ด์์ ์ ๋๋ค.
๐ง ์ค๋ฌด ์ค๊ณ ์ ๋ต
๊ตฌ๋ถ ์ฌ์ฉ ์์น ์ค๋ช
LoggerMiddleware | ์ ์ญ or ํน์ ๋ผ์ฐํธ | ์์ฒญ ๋ก๊ทธ ๊ธฐ๋ก |
AuthMiddleware | ์ธ์ฆ ํ์ํ ๊ฒฝ๋ก | JWT ํ ํฐ ๊ฒ์ฆ |
RawBodyMiddleware | Webhook ์ฒ๋ฆฌ ์ | req.rawBody ์ถ์ถ |
๐ ๋ง๋ฌด๋ฆฌ ์์ฝ
- Middleware๋ ์ปจํธ๋กค๋ฌ ์ ์ ์คํ๋๋ ๊ฐ๋ ์ญํ
- @Injectable() + configure()๋ก ๋ฑ๋ก
- next() ํธ์ถ ํ์
- ์ธ์ฆ, ๋ก๊น , ์์ฒญ ๊ฐ๊ณต ๋ฑ์ ๋งค์ฐ ์ ์ฉ
- Nest + Express ๋ฏธ๋ค์จ์ด ํธํ ๊ฐ๋ฅ
๋ค์ ๊ธ์์๋ Pipe์ Validation์ ํตํด ์์ฒญ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๊ฒ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์๋ด๋๋ฆด ์์ ์ ๋๋ค.
NestJS Middleware,NestJS ๋ฏธ๋ค์จ์ด ์ ์ฉ,NestJS ๋ก๊น ,NestJS ์ธ์ฆ,NestJS ์์ฒญ ๊ฐ๊ณต,NestJS ์ ์ญ ๋ฏธ๋ค์จ์ด,NestJS DI ๊ธฐ๋ฐ ๋ฏธ๋ค์จ์ด,NestJS JWT ์ธ์ฆ,NestJS ์ค์ ์์ ,NestJS ๋ฐฑ์๋ ๊ตฌ์กฐ
๋ค์ ํธ์์๋ Pipe์ ์ ํจ์ฑ ๊ฒ์ฆ ํจํด์ผ๋ก ์ด์ด์ง๋๋ค. ์ํ์๋ฉด ๋ฐ๋ก ์์ฑํด๋๋ฆด๊ฒ์! ๐