framework/NestJS

๐Ÿ› ๏ธ NestJS Middleware ์™„์ „ ์ •๋ณต – ์š”์ฒญ ์ „์ฒ˜๋ฆฌ, ๋กœ๊น…, ์ธ์ฆ ํ•„ํ„ฐ์˜ ํ•ต์‹ฌ

octo54 2025. 4. 16. 13:32
๋ฐ˜์‘ํ˜•

๐Ÿ› ๏ธ 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์™€ ์œ ํšจ์„ฑ ๊ฒ€์ฆ ํŒจํ„ด์œผ๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค. ์›ํ•˜์‹œ๋ฉด ๋ฐ”๋กœ ์ž‘์„ฑํ•ด๋“œ๋ฆด๊ฒŒ์š”! ๐Ÿ˜Š