Computer >> 컴퓨터 >  >> 프로그래밍 >> Redis

Redis Pub/Sub 완벽 가이드: 게시/구독 패턴으로 확장성 높은 애플리케이션 만들기

유지보수가 쉽고, 확장성이 뛰어나며, 성능까지 갖춘 애플리케이션을 개발할 때 Publish/Subscribe(게시/구독) 메시징 패턴은 탁월한 선택입니다.

이 패턴의 핵심 아이디어는 단순하지만 강력합니다. 먼저 퍼블리셔(publisher)라고 불리는 발신자가 있습니다. 퍼블리셔의 유일한 역할은 메시지를 보내거나 게시(publish)하는 것입니다. 누가 이 메시지를 받을지, 아니면 아무도 받지 않을지조차 전혀 신경 쓰지 않습니다. 그저 메시지를 발사하고 잊어버리는(fire and forget) 방식입니다. 그리고 이 모든 과정은 채널(channel)을 통해 이루어집니다.

채널을 TV 방송국에 비유해 볼 수 있습니다. 스포츠 채널, 날씨 예보 채널, 요리 채널 등이 있듯이, 각 퍼블리셔는 특정 채널로 메시지를 전송하고, 해당 채널을 구독(subscribe) 중인 모든 구독자가 그 메시지를 수신할 수 있습니다.

여기서 구독자(subscriber)가 등장합니다. 구독자는 하나 이상의 채널을 구독하여 그곳에서 방송되는 메시지를 수신하기 시작합니다.

앞서 언급했듯이 메시지는 '보내고 잊는' 방식입니다. 즉, 어떤 구독자가 나중에 특정 채널을 구독하더라도, 그 이전에 해당 채널에서 전송된 메시지들은 이 구독자에게 전달되지 않습니다.

이러한 아키텍처의 특성 덕분에 서로 다른 컴포넌트 간에 낮은 결합도(loose coupling)를 손쉽게 달성할 수 있으며, 견고하고 유지보수하기 쉬운 애플리케이션을 구축하는 탄탄한 기반이 마련됩니다.

예를 들어, 시스템의 게시 부분을 교체하거나 개선해야 하는 상황을 상상해 보세요. 더 많은 퍼블리셔나 새로운 채널을 추가하는 경우 말입니다. 두 파트가 서로 격리되어 있어 퍼블리셔는 구독자를 신경 쓰지 않고, 그 반대도 마찬가지이기 때문에, 시스템의 다른 부분을 망가뜨릴 걱정 없이 손쉽게 변경할 수 있습니다. 그저 새 퍼블리셔를 추가하면 됩니다. 이후 구독자가 관련 채널에 연결되면 자연스럽게 사용하기 시작합니다.

Redis란 무엇인가?

Redis의 초기 목적은 선배격인 Memcached의 대안으로서 인메모리 캐시 솔루션 역할을 하는 것이었습니다.

하지만 오늘날 Redis는 올인원 솔루션으로 발전했습니다. 인메모리 데이터 구조 저장소, 키-값 데이터베이스, 메시지 브로커 등 다양한 기능을 제공합니다. 덕분에 초고속 캐싱 솔루션과 함께 앞서 언급한 여러 기능이 필요한 애플리케이션을 만들 때 완벽한 후보가 됩니다. 특히 앱의 성능이 일상적인 사용에 결정적인 요소라면 더욱 그렇습니다.

Redis 성능 비교 (출처: Google)

Redis를 사용할 때 가장 큰 장점 중 하나는 온라인에서 찾을 수 있는 방대한 커뮤니티와 기술 자료입니다. 이러한 리소스 상당수는 무료이며, 프리 티어(free tier)를 제공하는 온라인 플랫폼도 있습니다.

또한 Redis는 클라우드 솔루션도 함께 제공합니다. 직접 사용해 보고 싶다면 공식 사이트에서 무료 계정을 등록하거나 초기 쿠폰 혜택을 활용할 수 있습니다.

Pub/Sub란?

Redis의 Publish/Subscribe 채널은 위에서 언급하지 않았지만 최신 버전의 Redis에 포함된 기능입니다. 퍼블리셔와 구독자가 채널을 통해 메시지를 주고받는 pub/sub 메시징 패턴의 Redis 구현체입니다.

아래에서 간략히 살펴본 뒤, 준비한 작은 데모 앱을 통해 실제 동작을 확인해 보겠습니다.

Redis Pub/Sub는 어떻게 동작하는가?

Redis Pub/Sub에는 세 가지 요소가 있습니다. 메시지를 생산하는 퍼블리셔, 메시지가 지나가는 통로인 채널, 그리고 메시지를 수신하는 구독자입니다. 누가 무엇을 받는지는 오직 '누가 어느 채널을 구독했는가'에 달려 있습니다.

예시를 통해 살펴보겠습니다:

세 개의 퍼블리셔가 세 개의 서로 다른 채널(채널 1, 2, 3)로 메시지를 게시한다고 가정해 봅시다. 또한 구독자 A, B, C 세 명이 있다고 하겠습니다.

이제 구독자 A가 세 채널 모두를 구독하여 메시지를 수신 대기 중이라고 해봅시다. 그리고 구독자 B와 C는 채널 2와 3만 구독하고 있습니다. 이 경우 세 퍼블리셔 중 누가 메시지를 보내든 구독자 A는 항상 수신하게 됩니다. 반면 구독자 B와 C는 채널 2와 3의 메시지만 듣고 있으므로, 해당 채널로 전송된 메시지만 받게 됩니다.

주목할 점은 한 채널을 사용하는 두 개체, 즉 보내는 쪽과 받는 쪽이 완전히 독립적이라는 사실입니다. 그리고 전송되는 메시지는 영속화되지 않습니다. 퍼블리셔가 메시지를 보내면 곧바로 잊혀지며, 전송 시점에 구독 중이던 개체만 그 메시지를 받습니다.

Redis에서 Pub/Sub 사용하는 방법

Redis와 함께 사용할 수 있는 클라이언트 라이브러리는 매우 다양합니다. Redis 공식 문서에는 프로젝트 요구사항이나 선호하는 프로그래밍 언어에 따라 선택할 수 있는 전용 페이지가 마련되어 있습니다.

또한 Redis 측에서 일부 저장소를 추천(recommended)으로 표시해 두었기 때문에, 처음 접하는 분들도 선택이 한결 수월합니다.

아래 데모에서는 Node.js용 풀 피처(full-featured) Redis 클라이언트인 ioredis를 사용했습니다. 데모 앱 UI가 React와 Node.js로 구축되어 있어 서버 코드와 잘 어울린다고 판단했기 때문입니다.

Redis Pub/Sub 데모

Redis Pub/Sub 시각화 앱

이제 시연할 차례입니다!

데모 애플리케이션의 목적은 이 패턴이 어떻게 동작하는지 시각적으로 보여주는 것입니다.

앱을 처음 열면 Weather(날씨), Sports(스포츠), Music(음악)이라는 세 개의 가상 TV 채널로 간단한 메시지(뉴스)를 게시하는 버튼 세 개가 보입니다.

게시 버튼 아래의 카드들이 바로 구독자입니다. 카드 위에 마우스 커서를 올리면 카드가 뒤집히면서 버튼 세 개가 나타납니다. 이 버튼들을 이용해 해당 채널을 구독할 수 있습니다.

구독자가 채널에 등록된 상태에서 해당 채널의 아이콘이나 게시 버튼을 클릭하면, 카드 앞면에 샘플 뉴스가 나타나는 것을 확인할 수 있습니다.

다양한 퍼블리셔/구독자 조합으로 실험해 보며 결과를 확인해 보세요. 앞서 설명드린 내용을 더 깊이 이해하는 데 도움이 되기를 바랍니다.

데모 앱을 로컬에서 실행하는 방법

데모 애플리케이션을 로컬에 설치하고 실행하려면 아래 단계를 따르세요. (모든 명령어는 프로젝트 루트 디렉터리에서 실행하는 것으로 가정합니다.)

프론트엔드 실행:

cd client && yarn && yarn dev

백엔드 실행:

cd server && yarn && yarn start

마지막으로 로컬에 설치된 Docker를 사용해 다음 명령어를 실행합니다. (Docker가 없다면 공식 사이트에서 다운로드할 수 있습니다.)

docker run -p 6379:6379 redislabs/redismod:preview

이것이 아마도 로컬에서 Redis를 실행하는 가장 간단한 방법일 것입니다. 다른 방법으로는 Redis Cloud를 직접 활용해 애플리케이션을 온라인에 배포하는 것이 있는데, 이 부분은 아직 조사 중이며 성공하면 전체 앱을 배포하고 소식을 알려드리겠습니다.

마무리

이 글에서는 pub/sub 메시징 패턴의 기본 개념을 소개했습니다. 높은 성능과 낮은 결합도의 아키텍처, 그리고 실시간과 유사한 메시징 기능을 갖춘 애플리케이션을 만들고 싶다면 Publish/Subscribe 패턴, 특히 Redis 사용을 고려해 보시기 바랍니다.

실제로 Redis를 활용하는 많은 실무 애플리케이션은 대시보드 기반입니다. 즉, 다양한 데이터를 실시간으로 업데이트하며 보여주는 멋진 대시보드 화면이 있는 경우가 많습니다.

예를 들어 특정 지역의 교통 상황을 보여주는 시스템을 상상해 보세요. 이런 종류의 소프트웨어는 pub/sub의 장점을 활용하기에 완벽한 후보이며, 많은 경우 Redis를 통해 구현됩니다.

어떤 경우든 개발자와 엔지니어로서 우리는 항상 진행 중인 프로젝트의 구체적인 요구사항에 따라 판단해야 합니다. 새로운 패턴이나 기술을 도입하기로 결정할 때는 신중하게 접근하고 철저한 조사를 통해 뒷받침해야 합니다.