[NEST.JS] MICROSERVICES

birdgang
38 min readFeb 1, 2024

--

nestjs, microservices

NestJS 에서 마이크로서비스 아키텍처를 구축 하는 것은 서비스를 작고 독립적인 단위로 분리 하여 각각을 독립적으로 개발하고 배포 할 수 있도록 하는 방식 입니다. NestJS 는 TCP, Redis, RabbitMQ, Kafka 등 다양한 트랜스포트 레이어를 지원하며, 쉽게 마이크로서비스를 구축 하고 통신 할 수 있는 기능을 제공합니다.

Features ?

  1. 마이크로서비스 모듈 설정 : MicroserviceModule을 사용하여 마이크로서비스를 구성합니다.
  2. 트랜스포트 레이어 선택 및 구성 : TCP, Redis 등 NestJS 가 지원하는 트랜스포트 레이어 중 하나를 선택하여 설정합니다.
  3. 메시지 패턴 및 핸들러 구현 : 특정 메시지 패턴을 수신하고 처리하는 핸들러를 구현합니다.
// math.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class MathService {
accumulate(data: number[]): number {
return (data || []).reduce((a, b) => a + b, 0);
}
}

// math.controller.ts
import { Controller } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';
import { MathService } from './math.service';

@Controller()
export class MathController {
constructor(private readonly mathService: MathService) {}

@MessagePattern({ cmd: 'sum' })
sum(data: number[]): number {
return this.mathService.accumulate(data);
}
}

MathService는 숫자 배열을 더하는 로직을, MathController는 'sum'이라는 메시지 패턴에 반응하여 해당 로직을 호출 합니다.

// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Transport } from '@nestjs/microservices';

async function bootstrap() {
const app = await NestFactory.createMicroservice(AppModule, {
transport: Transport.TCP,
options: {
host: 'localhost',
port: 3001,
},
});
app.listen(() => console.log('Microservice is listening'));
}
bootstrap();

main.ts에서 TCP 트랜스포트 를 사용 하여 마이크로서비스 를 시작 합니다.

Redis ?

NestJS 에서 마이크로서비스 아키텍처를 Redis 를 사용 하여 구현 하는 방법은, Redis 를 메시지 브로커로 사용하여 서비스 간의 비동기 통신을 가능 하게 하는 것입니다. Redis 를 사용하면 높은 성능과 안정성을 가진 메시지 큐를 통해 서비스 간에 메시지를 전송 할 수 있습니다.

Features ?

  1. Redis 트랜스포트 채널 설정 : 마이크로서비스를 생성할 때 Redis 트랜스포트 채널을 설정 합니다.
  2. 메시지 핸들러 구현 : 각 마이크로서비스에서 메시지 패턴에 대한 핸들러를 구현 합니다.
  3. 메시지 발행 및 수신 : 한 서비스에서 메시지를 발행하고, 다른 서비스에서 해당 메시지를 수신 합니다.
// math.controller.ts
import { Controller } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';

@Controller()
export class MathController {
@MessagePattern('add')
add(data: number[]): number {
return (data || []).reduce((a, b) => a + b, 0);
}
}

MathController에서 add라는 메시지 패턴에 반응하여 숫자 배열을 더하는 로직을 구현합니다.

// math.module.ts
import { Module } from '@nestjs/common';
import { ClientsModule, Transport } from '@nestjs/microservices';
import { MathController } from './math.controller';

@Module({
imports: [
ClientsModule.register([
{
name: 'MATH_SERVICE',
transport: Transport.REDIS,
options: {
url: 'redis://localhost:6379',
},
},
]),
],
controllers: [MathController],
})
export class MathModule {}

MathModule에서 Redis 를 트랜스포트 채널로 설정 하여 마이크로서비스 를 구성 합니다.

// app.controller.ts
import { Controller, Get, Inject } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';

@Controller()
export class AppController {
constructor(@Inject('MATH_SERVICE') private client: ClientProxy) {}

@Get()
async accumulate() {
const pattern = { cmd: 'add' };
const data = [1, 2, 3, 4, 5];
return this.client.send<number>(pattern, data);
}
}

AppController에서 MATH_SERVICE를 통해 add 메시지를 발행 하고, MathService에서 해당 메시지 를 수신 하여 처리 합니다.

이 예시 에서는 Redis 를 활용 하여 마이크로서비스 간에 비동기 메시지 통신을 구현하고 있습니다. Redis 의 Pub/Sub 모델은 마이크로서비스 아키텍처에서 효율적인 메시지 교환 메커니즘을 제공 합니다.

MQTT ?

MQTT 프로토콜을 기반으로 메시지를 교환하는 방식 입니다. MQTT 는 경량 메시징 프로토콜로, 특히 IoT 애플리케이션에서 널리 사용 됩니다. NestJS 에서는 이 프로토콜을 활용 하여 효율적이고 신뢰성 있는 마이크로서비스 간 통신을 구축 할 수 있습니다.

Features ?

  1. MQTT 트랜스포트 채널 설정 : 마이크로서비스를 생성할 때 MQTT 트랜스포트 채널을 설정 합니다.
  2. 메시지 핸들러 구현 : 각 마이크로서비스에서 메시지 패턴에 대한 핸들러를 구현 합니다.
  3. 메시지 발행 및 수신 : 한 서비스에서 메시지를 발행 하고, 다른 서비스에서 해당 메시지를 수신 합니다.
// math.controller.ts
import { Controller } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';

@Controller()
export class MathController {
@MessagePattern({ cmd: 'add' })
add(data: number[]): number {
return (data || []).reduce((a, b) => a + b, 0);
}
}

MathController에서 add라는 메시지 패턴 에 대한 핸들러 를 구현 합니다. 이 핸들러는 숫자 배열을 받아 그 합을 반환 합니다.

// main.ts
import { NestFactory } from '@nestjs/core';
import { MicroserviceModule } from './microservice.module';
import { Transport, MicroserviceOptions } from '@nestjs/microservices';

async function bootstrap() {
const app = await NestFactory.createMicroservice<MicroserviceOptions>(MicroserviceModule, {
transport: Transport.MQTT,
options: {
url: 'mqtt://localhost:1883',
},
});
await app.listen();
}
bootstrap();

main.ts에서 MQTT 트랜스포트 를 사용 하여 마이크로서비스를 시작 합니다. 여기서 mqtt://localhost:1883는 MQTT 브로커의 주소 입니다.

// app.module.ts
import { Module } from '@nestjs/common';
import { ClientsModule, Transport } from '@nestjs/microservices';

@Module({
imports: [
ClientsModule.register([
{
name: 'MATH_SERVICE',
transport: Transport.MQTT,
options: {
url: 'mqtt://localhost:1883',
},
},
]),
// ...
],
})
export class AppModule {}

AppModule에서 MATH_SERVICE를 통해 MQTT 클라이언트를 등록 합니다.

이 예시 에서는 MQTT 를 사용하여 마이크로서비스 간의 비동기 메시지 통신을 구현 하고 있습니다. MQTT 는 특히 네트워크 대역폭이 제한적 이거나 불안정한 환경에서 강력한 성능을 발휘하며, IoT 애플리케이션에 적합 합니다.

NATS ?

NATS 를 이용한 서비스 간 통신은, NATS 메시징 시스템을 활용하여 마이크로서비스 간 메시지를 교환하는 방식 입니다. NATS 는 고성능, 경량, 신뢰성 있는 메시징 시스템으로, 분산 시스템과 마이크로서비스 아키텍처에 잘 맞습니다.

Features ?

  1. NATS 트랜스포트 설정 : 마이크로서비스를 생성 할 때 NATS 트랜스포트 옵션을 설정 합니다.
  2. 메시지 핸들러 구현 : 각 마이크로서비스 에서 메시지 패턴에 대한 핸들러를 구현 합니다.
  3. 메시지 발행 및 수신 : 한 서비스에서 메시지를 발행하고, 다른 서비스에서 해당 메시지를 수신 합니다.
// math.controller.ts
import { Controller } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';

@Controller()
export class MathController {
@MessagePattern('add')
add(data: number[]): number {
return (data || []).reduce((a, b) => a + b, 0);
}
}

MathController에서 add라는 메시지 패턴에 대한 핸들러 를 구현 합니다. 이 핸들러 는 숫자 배열을 받아 그 합을 반환 합니다.

// main.ts
import { NestFactory } from '@nestjs/core';
import { MicroserviceModule } from './microservice.module';
import { Transport, MicroserviceOptions } from '@nestjs/microservices';

async function bootstrap() {
const app = await NestFactory.createMicroservice<MicroserviceOptions>(MicroserviceModule, {
transport: Transport.NATS,
options: {
url: 'nats://localhost:4222',
},
});
await app.listen();
}
bootstrap();

main.ts에서 NATS 트랜스포트 를 사용 하여 마이크로서비스를 시작 합니다. 여기서 nats://localhost:4222는 NATS 서버의 주소 입니다.

// app.module.ts
import { Module } from '@nestjs/common';
import { ClientsModule, Transport } from '@nestjs/microservices';

@Module({
imports: [
ClientsModule.register([
{
name: 'MATH_SERVICE',
transport: Transport.NATS,
options: {
url: 'nats://localhost:4222',
},
},
]),
// ...
],
})
export class AppModule {}

AppModule에서 MATH_SERVICE를 통해 NATS 클라이언트 를 등록 합니다.

RabbitMQ ?

RabbitMQ 를 사용한 마이크로서비스 통신은 메시지 기반의 분산 시스템을 구축 하는 효과적인 방법 입니다. RabbitMQ 는 강력한 메시지 브로커로서, 마이크로서비스 간의 비동기 메시지 교환을 지원 합니다. 이를 통해 각 서비스는 독립적으로 메시지를 발행하거나 수신할 수 있으며, 시스템 전반의 탄력성과 확장성 을 향상 시킬 수 있습니다.

Features ?

  1. RabbitMQ 트랜스포트 설정 : 마이크로서비스를 생성할 때 RabbitMQ 트랜스포트 옵션을 설정 합니다.
  2. 메시지 핸들러 구현 : 각 마이크로서비스에서 메시지 패턴에 대한 핸들러를 구현 합니다.
  3. 메시지 발행 및 수신 : 한 서비스에서 메시지를 발행 하고, 다른 서비스에서 해당 메시지를 수신 합니다.
// math.controller.ts
import { Controller } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';

@Controller()
export class MathController {
@MessagePattern('add')
add(data: number[]): number {
return (data || []).reduce((a, b) => a + b, 0);
}
}

MathController에서 add라는 메시지 패턴에 대한 핸들러를 구현 합니다. 이 핸들러는 숫자 배열을 받아 그 합을 반환 합니다.

// main.ts
import { NestFactory } from '@nestjs/core';
import { MicroserviceModule } from './microservice.module';
import { Transport, MicroserviceOptions } from '@nestjs/microservices';

async function bootstrap() {
const app = await NestFactory.createMicroservice<MicroserviceOptions>(MicroserviceModule, {
transport: Transport.RMQ,
options: {
urls: ['amqp://localhost:5672'],
queue: 'math_queue',
queueOptions: {
durable: false,
},
},
});
await app.listen();
}
bootstrap();

main.ts에서 RabbitMQ 트랜스포트 를 사용 하여 마이크로서비스 를 시작 합니다. 여기서 amqp://localhost:5672는 RabbitMQ 서버의 주소이며, math_queue는 사용할 큐의 이름 입니다.

// app.module.ts
import { Module } from '@nestjs/common';
import { ClientsModule, Transport } from '@nestjs/microservices';

@Module({
imports: [
ClientsModule.register([
{
name: 'MATH_SERVICE',
transport: Transport.RMQ,
options: {
urls: ['amqp://localhost:5672'],
queue: 'math_queue',
queueOptions: {
durable: false,
},
},
},
]),
// ...
],
})
export class AppModule {}

AppModule에서 MATH_SERVICE를 통해 RabbitMQ 클라이언트 를 등록 합니다.

이 예시에서는 RabbitMQ 를 사용 하여 마이크로서비스 간의 비동기 메시지 통신을 구현하고 있습니다. RabbitMQ 는 메시지 전달의 신뢰성, 지연 시간의 최소화, 탄력적인 메시징 패턴을 제공 하여, 대규모 분산 시스템에 적합한 메시징 솔루션 입니다.

Kafka ?

Kafka 를 사용한 마이크로서비스 간 통신은 Apache Kafka 를 메시지 브로커로 활용 하여 서비스 간 메시지를 교환하는 방식 입니다. Kafka 는 고성능, 확장 가능한 스트리밍 플랫폼으로, 대량의 데이터를 처리하고 실시간 데이터 파이프라인 과 스트리밍 애플리케이션을 구축 하는 데 적합 합니다.

Features ?

  1. Kafka 트랜스포트 설정 : 마이크로서비스를 생성 할 때 Kafka 트랜스포트 옵션을 설정 합니다.
  2. 메시지 핸들러 및 이벤트 구현 : 각 마이크로서비스에서 Kafka 토픽에 대한 메시지 핸들러 및 이벤트를 구현 합니다.
  3. 메시지 발행 및 수신 : 한 서비스에서 메시지를 발행 하고, 다른 서비스에서 해당 메시지를 수신 합니다.
// math.controller.ts
import { Controller } from '@nestjs/common';
import { MessagePattern, Payload } from '@nestjs/microservices';

@Controller()
export class MathController {
@MessagePattern('math_topic')
add(@Payload() data: number[]): number {
return (data || []).reduce((a, b) => a + b, 0);
}
}

MathController에서 Kafka의 'math_topic'에 대한 메시지 핸들러 를 구현 합니다. 이 핸들러 는 숫자 배열을 받아 그 합을 반환 합니다.

// main.ts
import { NestFactory } from '@nestjs/core';
import { MicroserviceModule } from './microservice.module';
import { Transport, MicroserviceOptions } from '@nestjs/microservices';

async function bootstrap() {
const app = await NestFactory.createMicroservice<MicroserviceOptions>(MicroserviceModule, {
transport: Transport.KAFKA,
options: {
client: {
brokers: ['localhost:9092'],
},
consumer: {
groupId: 'math-group',
},
},
});
await app.listen();
}
bootstrap();

main.ts에서 Kafka 트랜스포트를 사용 하여 마이크로서비스를 시작 합니다. 여기서 localhost:9092는 Kafka 브로커의 주소 이며, math-group은 Kafka 컨슈머 그룹의 이름 입니다.

// app.module.ts
import { Module } from '@nestjs/common';
import { ClientsModule, Transport } from '@nestjs/microservices';

@Module({
imports: [
ClientsModule.register([
{
name: 'MATH_SERVICE',
transport: Transport.KAFKA,
options: {
client: {
brokers: ['localhost:9092'],
},
consumer: {
groupId: 'math-group',
},
},
},
]),
// ...
],
})
export class AppModule {}

AppModule에서 MATH_SERVICE를 통해 Kafka 클라이언트를 등록 합니다.

gRPC ?

gRPC 를 이용한 마이크로서비스 통신은, gRPC 프로토콜을 활용해 서비스 간에 효율적이고 강력한 원격 절차 호출(Remote Procedure Call, RPC)을 구현하는 방법 입니다. gRPC 는 HTTP/2 를 기반 으로 하는 고성능, 오픈 소스 프레임워크로, 플랫폼 간 언어 중립적인 통신을 가능 하게 합니다.

Features ?

  1. gRPC 서비스 및 메시지 정의 (.proto 파일) : .proto 파일을 사용해 gRPC 서비스와 메시지 형식을 정의 합니다.
  2. gRPC 서비스 구현 : 정의된 gRPC 서비스에 대한 구현을 제공 합니다.
  3. gRPC 클라이언트 설정 : 다른 마이크로서비스에서 gRPC 클라이언트를 설정하여 서비스를 호출 합니다.
// math.proto
syntax = "proto3";

package math;

service MathService {
rpc Add (AddRequest) returns (AddResponse);
}

message AddRequest {
repeated int32 numbers = 1;
}

message AddResponse {
int32 result = 1;
}

math.proto 파일 에서 MathService gRPC 서비스와 관련 메시지를 정의 합니다.

// math.controller.ts
import { Controller } from '@nestjs/common';
import { GrpcMethod } from '@nestjs/microservices';

@Controller()
export class MathController {
@GrpcMethod('MathService', 'Add')
add(data: { numbers: number[] }): { result: number } {
const { numbers } = data;
const result = numbers.reduce((a, b) => a + b, 0);
return { result };
}
}

MathController에서 MathServiceAdd 메서드를 구현 합니다.

// math.module.ts
import { Module } from '@nestjs/common';
import { MathController } from './math.controller';

@Module({
controllers: [MathController],
})
export class MathModule {}

MathModule에서 MathController를 등록 합니다.

// app.module.ts
import { Module } from '@nestjs/common';
import { ClientsModule, Transport } from '@nestjs/microservices';
import { MathModule } from './math/math.module';

@Module({
imports: [
MathModule,
ClientsModule.register([
{
name: 'MATH_PACKAGE',
transport: Transport.GRPC,
options: {
package: 'math',
protoPath: join(__dirname, 'math/math.proto'),
},
},
]),
],
})
export class AppModule {}

AppModule에서 MATH_PACKAGE 이름으로 gRPC 클라이언트를 등록 하고, math.proto 파일을 참조 합니다.

gRPC 를 사용 하면, 다양한 언어와 플랫폼에서 실행되는 마이크로서비스 간의 효율적인 통신을 구현할 수 있습니다. gRPC 는 네트워크 오버헤드를 최소화하고, 강력한 타입 시스템을 제공하여, 대규모 분산 시스템에서의 통신을 최적화 합니다.

Custom transporters ?

기본 제공되는 트랜스포터(예: TCP, Redis, NATS 등) 외에도 사용자 정의 트랜스포터(Custom Transporters)를 구현 할 수 있습니다. 이를 통해 특정 사용 사례에 맞는 맞춤형 통신 프로토콜 이나 메시지 브로커를 사용 할 수 있습니다.

Features ?

  1. 사용자 정의 트랜스포터 클래스 생성: CustomTransportStrategy 인터페이스를 구현하는 클래스를 생성 합니다. listen 메서드 에서 메시지 수신 및 처리 로직을 구현합니다.
  2. 마이크로서비스 모듈에서 사용자 정의 트랜스포터 등록 : 마이크로서비스 모듈에서 생성한 사용자 정의 트랜스포터 를 사용 합니다.
// custom-transporter.ts
import { Server } from '@nestjs/microservices';

export class CustomTransporter extends Server {
async listen(callback: () => void) {
// 여기에 사용자 정의 수신 로직을 구현합니다.
callback();
}

async close() {
// 여기에 연결 종료 로직을 구현합니다.
}
}

CustomTransporter 클래스는 Server를 상속 받아 사용자 정의 트랜스포터 를 구현 합니다.

// app.module.ts
import { Module } from '@nestjs/common';
import { CustomTransporter } from './custom-transporter';

@Module({
// ...
providers: [
{
provide: 'CUSTOM_TRANSPORTER',
useClass: CustomTransporter,
},
],
})
export class AppModule {}

AppModule에서 CustomTransporterCUSTOM_TRANSPORTER로 제공 합니다.

// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { CustomTransporter } from './custom-transporter';

async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.connectMicroservice({
strategy: new CustomTransporter(),
});

await app.startAllMicroservicesAsync();
await app.listen(3000);
}
bootstrap();

main.ts에서 CustomTransporter 인스턴스 를 마이크로서비스 트랜스포터 로 사용 합니다.

Exception filters ?

Exception Filters 는 서비스 간 통신에서 발생할 수 있는 예외 상황을 처리 하는 데 사용 됩니다. 이 필터 들은 예외를 캡처하고, 사용자 정의된 방식으로 클라이언트에 응답을 보내거나 로깅 하는 데 활용 됩니다.

Features ?

  1. Exception Filter 클래스 생성 : ExceptionFilter 인터페이스를 구현하는 클래스를 생성 합니다. catch 메서드에서 예외 처리 로직을 구현 합니다.
  2. 필터를 마이크로서비스에 적용 : 마이크로서비스 컨트롤러 또는 전역적으로 Exception Filter 를 적용 합니다.
// custom-exception.filter.ts
import { Catch, RpcExceptionFilter, ArgumentsHost } from '@nestjs/common';
import { Observable, throwError } from 'rxjs';

@Catch(Error)
export class CustomExceptionFilter implements RpcExceptionFilter<Error> {
catch(exception: Error, host: ArgumentsHost): Observable<any> {
// 여기에 예외 처리 로직을 구현합니다.
console.error('Exception caught by CustomExceptionFilter', exception);
return throwError(exception);
}
}

CustomExceptionFilter 클래스는 모든 종류의 에러를 캡처 하고 콘솔에 로그를 남깁니다.

// math.controller.ts
import { Controller, UseFilters } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';
import { CustomExceptionFilter } from './custom-exception.filter';

@Controller()
@UseFilters(new CustomExceptionFilter())
export class MathController {
@MessagePattern('add')
add(data: number[]): number {
if (!Array.isArray(data)) {
throw new Error('Data must be an array of numbers');
}
return (data || []).reduce((a, b) => a + b, 0);
}
}

MathController에서 CustomExceptionFilter를 사용 하여 예외를 처리 합니다.

CustomExceptionFilterMathController의 모든 메서드에서 발생하는 예외를 캡처하고, 이를 로그로 남기며 클라이언트에 에러 응답을 반환 합니다. NestJS 에서 Exception Filters 를 사용하면 마이크로서비스 간의 통신에서 발생하는 예외를 효과적으로 관리하고, 시스템의 안정성을 향상시킬 수 있습니다.

Pipes ?

Pipes 는, 요청 데이터의 변환과 유효성 검사를 위해 사용 됩니다. 마이크로서비스에서 Pipes 를 사용하면, 들어오는 메시지 데이터를 적절하게 처리하고, 서비스 로직 에 전달하기 전에 필요한 검증을 수행 할 수 있습니다.

Features ?

  1. Pipe 클래스 생성 : PipeTransform 인터페이스를 구현하는 클래스를 생성 합니다. transform 메서드 에서 변환 및 유효성 검사 로직을 구현 합니다.
  2. 마이크로서비스 컨트롤러 에 Pipe 적용 : 컨트롤러 또는 핸들러 레벨에서 Pipe 를 적용 합니다.
// validate-numbers.pipe.ts
import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common';

@Injectable()
export class ValidateNumbersPipe implements PipeTransform {
transform(value: any) {
if (!Array.isArray(value)) {
throw new BadRequestException('Value must be an array of numbers');
}
return value.map(num => parseInt(num, 10));
}
}

ValidateNumbersPipe는 전달된 데이터가 숫자 배열 인지 검증하고, 숫자로 변환하는 로직을 구현 합니다.

// math.controller.ts
import { Controller, UsePipes } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';
import { ValidateNumbersPipe } from './validate-numbers.pipe';

@Controller()
export class MathController {
@MessagePattern('add')
@UsePipes(new ValidateNumbersPipe())
add(data: number[]): number {
return (data || []).reduce((a, b) => a + b, 0);
}
}

MathControlleradd 메서드에서 ValidateNumbersPipe를 사용 하여 들어오는 데이터의 유효성을 검사 합니다.

MathController는 메시지 패턴 'add'로 들어오는 요청에 대해 ValidateNumbersPipe를 사용하여 들어오는 데이터가 유효한 숫자 배열인지 확인 합니다. 이렇게 NestJS 에서 Pipe 를 사용 하면, 마이크로서비스 간의 통신 에서 데이터의 정확성과 일관성을 보장 할 수 있습니다.

Guards ?

Guards 는 요청을 처리 하기 전에 특정 조건을 충족 하는지 검사하는 역할 을 합니다. 마이크로서비스에서 Guards 를 사용하면, 인증 및 권한 부여와 같은 보안 관련 작업을 수행하거나, 특정 비즈니스 로직을 실행하기 전에 필요한 전 처리를 할 수 있습니다.

Features ?

  1. Guard 클래스 생성 : CanActivate 인터페이스를 구현하는 클래스를 생성합니다. canActivate 메서드 에서 검사 로직을 구현 합니다.
  2. 마이크로서비스 컨트롤러 에 Guard 적용 : 컨트롤러 또는 핸들러 레벨에서 Guard 를 적용 합니다.
// auth.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';

@Injectable()
export class AuthGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const request = context.switchToRpc().getData();
// 인증 로직 구현
return validateRequest(request);
}
}

AuthGuardcanActivate 메서드 에서 요청을 검사 하고, 요청이 유효한지 여부를 반환 합니다.

// math.controller.ts
import { Controller, UseGuards } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';
import { AuthGuard } from './auth.guard';

@Controller()
@UseGuards(AuthGuard)
export class MathController {
@MessagePattern('add')
add(data: number[]): number {
return (data || []).reduce((a, b) => a + b, 0);
}
}

MathController에서 AuthGuard를 사용 하여 모든 메서드에 대한 인증을 요구 합니다.

MathController는 메시지 패턴 'add' 로 들어오는 요청에 대해 AuthGuard를 사용하여 인증을 확인 합니다. NestJS 에서 Guard 를 사용 하면, 마이크로서비스 간의 통신에서 보안과 데이터 무결성을 보장 하는 데 도움이 됩니다.

Interceptors ?

Interceptors 는 컨트롤러 핸들러 의 실행 전후에 특정 로직을 적용 할 수 있는 강력한 기능을 제공 합니다. Interceptors 는 AOP(Aspect-Oriented Programming)의 개념을 활용하여, 비즈니스 로직과 분리된 관심사(로깅, 트랜스포밍, 에러 처리 등)를 처리 하는데 유용 합니다.

Features ?

  1. Interceptor 클래스 생성 : NestInterceptor 인터페이스를 구현 하는 클래스를 생성 합니다. intercept 메서드 에서 로직을 구현 합니다.
  2. 마이크로서비스 컨트롤러 에 Interceptor 적용 : 컨트롤러 또는 핸들러 레벨에서 Interceptor 를 적용 합니다.
// logging.interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
console.log('Before...');

const now = Date.now();
return next
.handle()
.pipe(
tap(() => console.log(`After... ${Date.now() - now}ms`)),
);
}
}

LoggingInterceptor는 요청 처리 전후로 로그를 남기는 로직을 구현 합니다.

// math.controller.ts
import { Controller, UseInterceptors } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';
import { LoggingInterceptor } from './logging.interceptor';

@Controller()
@UseInterceptors(LoggingInterceptor)
export class MathController {
@MessagePattern('add')
add(data: number[]): number {
return (data || []).reduce((a, b) => a + b, 0);
}
}

MathController에서 LoggingInterceptor를 사용 하여 모든 메서드의 실행 전후에 로그를 남깁니다.

MathController의 각 메서드는 LoggingInterceptor에 의해 요청 처리 시간을 로깅 합니다. NestJS 의 Interceptors 를 사용하면, 로깅, 데이터 변환, 통계 수집, 에러 처리 등의 관심사를 효과적으로 처리할 수 있으며, 마이크로서비스 간의 통신을 더욱 효율적으로 관리 할 수 있습니다.

--

--