본문 바로가기
TypeScript

[Nest.js] Custom Decorator

by yonikim 2022. 4. 12.
728x90

interceptor 작업을 진행하다 보니 product 라는 같은 서비스 내부에서 이게 product 이벤트인지 item 이벤트인지 구분이 필요했다.

그리하여 작업하게 된 Custom Decorator.

 

reflect-metadata 라이브러리를 사용하기로 결정했다.

npm install reflect-metadata

 

▷ tsconfig.json

{
    "compilerOptions": {
        "target": "ES5",
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true
    }
}

 

▷ sns.decorator.ts

import "reflect-metadata";

export const UseSnsDecorator = (
  serviceName: string,
  tableName: string,
): ClassDecorator => {
  return (target: any) => {
    Reflect.defineMetadata("serviceName", serviceName, target);
    Reflect.defineMetadata("tableName", tableName, target);
  };
};

 

Custom 하여 만든 Decorator 사용 방법은 아래와 같다.

1. Service 단에 해당 Decorator 를 추가한다.

 

 product.service.ts

@Controller()
@UseInterceptors(SnsInterceptor)
@UseSnsDecorator(SERVICES.Product, "Product")
export class ProductService {
...
}

 

 item.service.ts 

@Controller()
@UseInterceptors(SnsInterceptor)
@UseSnsDecorator(SERVICES.Product, "Item")
export class ItemService {
...
}

 

 

2. `Reflect.getMetadata()` 를 사용하여 Interceptor 에서 호출한다.

@Injectable()
export class SnsInterceptor implements NestInterceptor {
  async intercept(
    context: ExecutionContext,
    next: CallHandler,
  ): Promise<Observable<any>> {
    if (isLocal()) return next.handle();
    const grpcData = context.switchToRpc().getData();

    const grpcServiceName = context.getClass().name;
    const grpcMethodName = context.getHandler().name;

    const serviceName = Reflect.getMetadata("serviceName", context.getClass());
    const tableName = Reflect.getMetadata("tableName", context.getClass());
    
    ...
  }
 }

 

 

728x90