로컬 환경에서 Docker Compose와 NestJS를 활용한 Dapr 기반 Redis 퍼블리시-서브스크라이브 분산 애플리케이션 빌드

Dapr(분산형 애플리케이션 런타임) 소개

Dapr은 분산형, 이벤트 주도형 런타임으로 다양한 언어와 프레임워크에서 탄 강성 및 무상태, 유상태 애플리케이션을 쉽게 개발할 수 있도록 지원합니다. 클라우드나 윌드-edge 환경에서도 실행할 수 있습니다.

Dapr 공식 웹사이트: https://dapr.io/

실전: Dapr의 Redis 퍼블리시-서브스크라이브 애플리케이션 구현

1. 프로젝트 생성

프로젝트 루트 폴더를 만듭니다.

mkdir dapr-nestjs-redis-pub-sub

2. Dapr Placement 서비스 구현

Docker Compose를 사용하여 서비스를 실행합니다. 프로젝트 루트 폴더에 docker-compose.yml 파일을 생성합니다.

cd dapr-nestjs-redis-pub-sub
touch docker-compose.yml

docker-compose.yml에 다음 코드를 추가합니다.

version: "3.5"

services:
  dapr-placement:
    image: "daprio/dapr"
    command: ["./placement", "-port", "50006"]

Dapr Placement는 Dapr 액터 간의 모든 통신을 관리합니다.

3. Redis 퍼블리시 서비스 구현

docker-compose.yml 파일에 Redis 퍼블리시 서비스를 추가합니다.

  redis-publisher:
    image: redis
    restart: always
    depends_on:
      - dapr-placement

4. Dapr 퍼블리시-서브스크라이브 컴포넌트 설정

dapr/components 폴더를 생성하고 redis-pubsub.yaml 파일을 만듭니다.

mkdir -p dapr/components
cd dapr/components
touch redis-pubsub.yaml

redis-pubsub.yaml에 다음 내용을 입력합니다.

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: redis-pubsub
  namespace: default
spec:
  type: pubsub.redis
  version: v1
  metadata:
    - name: redisHost
      value: redis-publisher:6379
    - name: redisPassword
      value: ""

5. Redis Dapr 사이드카 구현

docker-compose.yml 파일에 Redis Dapr 사이드카 서비스를 추가합니다.

  redis-dapr-sidecar:
    image: "daprio/daprd:edge"
    command: [
        "./daprd",
        "-app-id",
        "redis-publisher",
        "-app-port",
        "6379",
        "-dapr-http-port",
        "5000",
        "-components-path",
        "/components",
        "-placement-host-address",
        "dapr-placement:50006"
      ]
    volumes: 
      - "./dapr/components/:/components"
    depends_on:
      - redis-publisher
    network_mode: "service:redis-publisher"

6. NestJS 서버 구현

NestJS를 사용하여 Redis 서브스크라이브 서비스를 만듭니다.

cd dapr-nestjs-redis-pub-sub
npm i -g @nestjs/cli
nest new nest-subscriber

nest-subscriber/src/app.controller.ts 파일을 수정합니다.

import { Controller, Post, Body } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Post('/redis-publisher')
  async postRedisPub(@Body() reqBody) {
    console.log(`Redis가 발행한 ${JSON.stringify(reqBody)} `);

    return `NestJS 서브스크라이브자가 받은 ${reqBody} 발행`;
  }
}

7. NestJS 서버용 Dockerfile 작성

nest-subscriber 폴더에 Dockerfile을 생성합니다.

cd nest-subscriber
touch Dockerfile

Dockerfile에 다음 코드를 입력합니다.

FROM node:16.13.0-alpine

WORKDIR "/app"
COPY ./nest-subscriber/package.json ./
RUN yarn install
COPY ./nest-subscriber .
RUN yarn run build

EXPOSE 3000
CMD ["yarn","start:prod"]

Docker 이미지를 빌드합니다.

docker build -f ./nest-subscriber/Dockerfile -t nest-subscriber:latest . --no-cache

8. NestJS 서브스크라이브 서비스 추가

docker-compose.yml 파일에 NestJS 서비스를 추가합니다.

  nest-subscriber:
    image: "nest-subscriber:latest"
    depends_on:
      - redis-publisher
      - dapr-placement
    restart: always

9. Dapr 서브스크라이브 설정

dapr/subscriptions 폴더를 생성하고 redis-subscription.yaml 파일을 만듭니다.

mkdir -p dapr/subscriptions
cd dapr/subscriptions
touch redis-subscription.yaml

redis-subscription.yaml에 다음 내용을 입력합니다.

apiVersion: dapr.io/v1alpha1
kind: Subscription
metadata:
  name: nest-redis-sub
spec:
  topic: nest-redis-pub-topic
  route: /redis-publisher
  pubsubname: redis-pubsub
scopes:
  - nest-subscriber

10. NestJS 서버용 Dapr 사이드카 구현

docker-compose.yml 파일에 NestJS 서버용 Dapr 사이드카 서비스를 추가합니다.

  nest-subscriber-dapr-sidecar:
    image: "daprio/daprd:edge"
    command: [
        "./daprd",
        "-app-id",
        "nest-subscriber",
        "-app-port",
        "3000",
        "-components-path",
        "/components",
        "-placement-host-address",
        "dapr-placement:50006",
      ]
    volumes:
      - "./dapr/components/:/components"
    depends_on:
      - nest-subscriber
    network_mode: "service:nest-subscriber"

11. 테스트

로컬 머신에서 퍼블리시 테스트를 수행합니다.

curl --location --request POST 'http://localhost:5001/v1.0/publish/redis-pubsub/nest-redis-pub-topic' \
--header 'Content-Type: application/json' \
--data-raw '{
    "hello": "world"
}'

12. CloudEvents 처리를 위한 NestJS 설정

body-parser 패키지를 설치하고 main.ts 파일을 수정합니다.

cd nest-subscriber
yarn add body-parser

main.ts 파일을 수정합니다.

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as bodyParser from 'body-parser';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  app.use(bodyParser.json({ type: 'application/cloudevents+json' }));
  app.use(bodyParser.json());
  await app.listen(3000);
}

bootstrap();

13. 완전한 docker-compose.yml

version: "3.5"

services:
  dapr-placement:
    image: "daprio/dapr"
    command: ["./placement", "-port", "50006"]
  
  redis-publisher:
    image: redis
    depends_on:
      - dapr-placement
    restart: always
    ports:
      - 5001:5000

  redis-dapr-sidecar:
    image: "daprio/daprd:edge"
    command: [
        "./daprd",
        "-app-id",
        "redis-publisher",
        "-app-port",
        "6379",
        "-dapr-http-port",
        "5000",
        "-components-path",
        "/components",
        "-placement-host-address",
        "dapr-placement:50006"
      ]
    volumes: 
      - "./dapr/components/:/components"
    depends_on:
      - redis-publisher
    network_mode: "service:redis-publisher"
  
  nest-subscriber:
    image: "nest-subscriber:latest"
    depends_on:
      - redis-publisher
      - dapr-placement
    restart: always
  
  nest-subscriber-dapr-sidecar:
    image: "daprio/daprd:edge"
    command: [
        "./daprd",
        "-app-id",
        "nest-subscriber",
        "-app-port",
        "3000",
        "-components-path",
        "/components",
        "-placement-host-address",
        "dapr-placement:50006",
      ]
    volumes:
      - "./dapr/components/:/components"
    depends_on:
      - nest-subscriber
    network_mode: "service:nest-subscriber"

14. 소스 코드

https://github.com/Hacker-Linner/dapr-nestjs-redis-pub-sub.git

더 많은 정보: Dapr을 위한 NestJS SDK 통합 방법

태그: dapr nestjs Redis docker-compose

6월 11일 16:56에 게시됨