[Server] pub/sub 이란?

resilient

·

2022. 6. 9. 17:42

728x90
반응형

 

최근 회사에서 MSA로 마이그레이션을 진행하고 있습니다. 거의 대부분은 MSA로 프로젝트들이 설계되어 있죠.

MSA에 대해서는 이 블로그에서 아주 간단명료하게 설명되어 있으니 모르시는 분들은 한 번 보고 오시는 걸 추천드립니다!

 

0. pub/sub을 알기 전, 메세지 큐(Message Queue) 란?

 

MSA구조에서는 하나하나의 애플리케이션끼리 통신을 해야 하거나 한 API에서 다른 API로 데이터를 넘겨야 하는 순간들이 생기게 됩니다. 여기서 메세지 큐가 등장하는데요. 메세지 큐(Message Queue)는 프로세스 또는 프로그램 간에 데이터를 교환할 때 사용하는 통신 방법 중에 하나로, 메세지 지향 미들웨어(Message Oriented Middleware: MOM)를 구현한 시스템을 의미합니다.

 

메세지 큐(Message Queue)에 대해서는 다음 게시물에서 더 자세히 살펴보도록 하겠습니다.

 

1. pub/sub이란?

 

pub/sub은 위에서 설명했던 메세지 큐 시스템, 메세징 패턴 중 하나입니다.

간단하게 알고 가자면 pub(publisher)가 topic에 메세지를 보내면 해당 topic을 구독해놓은 sub(subscriber) 모두에게 메세지가 전송되면서 데이터 교환이 이루어지는 방법입니다.

 

pub/sub 패턴은 비동기식 메세징 패턴이기 때문에 publisher가 연산해야 할 다른 topic(task)을 publish 하면 topic (task)를 가져갈 subscriber가 받아서 받은 task를 처리하고, 처리하는 시간 동안 publisher는 다른 작업을 수행할 수 있다는 장점이 있습니다.

 

2. pub/sub의 구조에 대해서 알아보겠습니다.

 

회사는 클라우드로 GCP를 사용하는데요. 구글 클라우드 페이지에 Cloud Pub/Sub에 대한 그림을 올려놨습니다. 아래 그림을 보면서 설명해보겠습니다.

  • publisher(게시자)
    • publisher는 message를 생성한 뒤에, topic에 담아두도록 전달해주는 서버입니다.
  • message(메세지)
    • message는 publisher로부터 subscriber에게 최종적으로 전달되는 데이터와 property의 조합입니다. 쉽게 얘기하면 서로 다른 API끼리 통신을 할 데이터라고 할 수 있죠.
  • topic(토픽), channel
    • topic은 task, 즉 업무입니다. publisher가 message를 전달하는 리소스입니다.
  • subscription(구독)
    • subscription은 message 스트림이 subscriber들에게 전달되는 과정을 나타내는 이름을 가지고 있는 리소스라고 할 수 있습니다.
  • subscriber(구독자)
    • subscriber는 message를 수신하려는 서버입니다.

 

먼저 publisher와 subscriber은 서로에 대해 전혀 알 필요가 없습니다. 그렇다면 어떻게 message를 주고받게 되는 걸까요? 

 

중간다리 역할을 해주는 브로커(broker), 혹은 버스(bus)라고 불리는 존재가 있습니다. 브로커나 버스는 publisher와 subscriber 모두가 서로 알고 있는 존재로, 브로커나 버스 역할을 해줄 redis 혹은 kafka에서 지원하는 서비스를 사용하죠.

 

위 내용들을 쭉 읽다 보면 이거 Observer 패턴 아니야?라고 생각하시는 분들이 계실 수도 있습니다. 하지만 엄연히 다른 구조이죠.


둘의 차이점은 이 블로그 에서 자세하게 다뤘으니 한 번 읽어보시는 걸 추천드립니다.

 

3. 간단한 실습을 통해 살펴보겠습니다.

 

먼저 Kafka는 진입장벽이 있을 수 있어서 아주 간단하게 사용해볼 수 있는 Redis로 구현했고, ExpressJS 기반의 NestJS 프레임워크를 사용했습니다.

 

실습은 구독해놓은 topic에 publish를 발생시키는 API를 만들고, 구독해놓은 topic으로부터 message를 받을 subscriber를 생성해서 통신이 되는지를 살펴보려고 합니다. ( NestJS 아키텍처를 어느 정도 이해하고 있다는 가정하에 설명하겠습니다! )

 

먼저 publish를 발생시키는 API를 만들겠습니다.

//message.service.ts

@Injectable()
export class MessageService {
  publish() {
    const pub = createClient({
      host: 'localhost',
      port: 8080,
    });

    const message = '{"name" : "steady","age:27","sex":"male"}';
    pub.publish('test_topic_channel', message);
  }
}

 

// message.controller.ts

@Controller('message')
export class MessageController {
  constructor(private readonly messageService: MessageService) {}

  @Post()
  publish(): void {
    return this.messageService.publish();
  }
}

 

다음으로는 topic을 구독하고 message를 받을 subscriber을 생성해보겠습니다.

 

@Injectable()
export class MessageSubscriber implements OnApplicationBootstrap {
  onApplicationBootstrap() {
    this.subscribeMessage();
  }

  async subscribeMessage() {
    const subscriber = createClient({ host: 'localhost', port: 8080 });
    subscriber.subscribe('test_topic_channel');
    subscriber.on('message', (channel, message) => {
    
      const data = JSON.parse(message); 
      console.log(data.name);
      console.log(data.age);
      console.log(data.sex);
    });
    return;
  }
}

 

4. 정리

 

이번 게시물에서는 messaging 패턴 중 하나인 pub/sub에 대해서 알아보았습니다. MSA, message 등 생소한 단어들이 많아서 자칫 어려워 보일 수도 있지만 사실 간단하게 정리해보자면 서로 다른 API끼리 통신하기 위한 수단이라고 이해하시면 될 것 같습니다.

 

다음 시간에는 Message Queue가 무엇인지, 비동기 패턴에 대해서도 자세히 알아보겠습니다.

 

감사합니다.

 

반응형