웹 애플리케이션을 사용하다 보면 실시간 알림을 받는 일이 매우 흔합니다. 알림은 챗봇에서 올 수도 있고, 경고 시스템에서 발생할 수도 있으며, 애플리케이션이 하나 이상의 사용자에게 전달하는 이벤트에 의해 트리거될 수도 있습니다. 알림의 출처가 무엇이든, 개발자들은 Redis를 활용해 알림 서비스를 구축하는 사례가 점점 늘어나고 있습니다.
마이크로서비스 아키텍처 기반의 현대적인 애플리케이션에서 Redis는 단순한 캐시나 기본 데이터베이스로 자주 사용됩니다. 하지만 그뿐만 아니라, Redis Streams라는 가벼운 이벤트 시스템과 잘 알려진 Pub/Sub(발행/구독) 명령어를 기반으로 하는 지속적인 메시징 계층을 통해 서비스 간 통신 레이어로도 활용됩니다.
이 글에서는 Redis Pub/Sub를 사용해 Vue.js, Node.js, WebSockets으로 개발된 웹 애플리케이션에 메시지를 전송하는 작은 알림 서비스를 얼마나 쉽게 만들 수 있는지 소개합니다.

사전 준비 사항
이 데모 서비스는 다음 도구들을 사용합니다:
- Docker
- Redis 5.0.x 이상 (이 데모는 Redis Docker 컨테이너를 사용)
- Node.js 10.x 및 npm(Node 패키지 매니저)
- nodemon — 개발 중 애플리케이션을 자동으로 재시작해 주는 간단한 도구
- Vue CLI
Redis 서버 시작하기
아직 실행 중인 Redis 인스턴스가 없다면 Docker로 손쉽게 시작할 수 있습니다. 터미널에서 다음 명령어를 실행하세요:
> docker run -it --rm --name redis-server -p 6379:6379 redis
이제 Redis가 실행되고 연결 요청을 받을 준비가 되었습니다.
Node.js로 WebSocket 서버 만들기
적절한 프로젝트 구조를 설정하려면 터미널을 열고 다음 명령어들을 입력합니다.
npm으로 새 Node.js 프로젝트를 생성합니다 (-y 파라미터는 모든 값을 기본값으로 설정합니다):
위 마지막 명령어는 프로젝트에 WebSocket과 Redis 의존성을 추가합니다. 이제 코드를 작성할 준비가 되었습니다!
WebSocket 서버 코드 작성하기
선호하는 코드 에디터(여기서는 Visual Studio Code를 사용)를 열고, 현재 디렉터리를 여는 code . 명령어를 입력합니다. 에디터에서 server.js라는 새 파일을 생성하세요.
이 간단한 Node.js 프로그램은 데모용으로 다음 핵심 기능에 집중합니다:
- Redis에 연결 (9번째 줄)
- app:notifications 채널의 메시지 구독 (10번째 줄)
- WebSocket 서버 시작 (13번째 줄)
- 사용자 클라이언트 연결 등록 (16번째 줄)
- Redis 구독 이벤트 리스닝 (19번째 줄)
- 모든 WebSocket 클라이언트에 메시지 전송 (21번째 줄)
5번과 6번째 줄은 Redis 서버 위치와 WebSocket 서버가 사용할 포트를 설정하는 데 사용됩니다. 보시다시피 매우 간단합니다.
WebSocket 서버 실행하기
아직 nodemon을 설치하지 않았다면 먼저 설치하세요. 그런 다음 아래 명령어로 WebSocket 서버를 시작합니다.
이제 알림을 받아 사용자에게 출력할 프론트엔드를 만들어 보겠습니다.
Vue.js로 프론트엔드 만들기
새 터미널을 열고 notifications 디렉터리에서 다음 명령어를 실행합니다.
아직 Vue CLI 도구를 설치하지 않았다면 npm install -g @vue/cli 명령어로 먼저 설치하세요.
이 명령어는 바로 실행하고 확장할 수 있는 새 Vue 프로젝트를 생성합니다.
이 데모를 위해 마지막으로 설치할 패키지는 BootstrapVue입니다. 이를 통해 인기 있는 Bootstrap 프레임워크의 CSS 라이브러리와 컴포넌트를 손쉽게 사용할 수 있습니다.
선호하는 코드 에디터에서 web-client 디렉터리를 연 후, 새로 생성한 Vue 애플리케이션을 시작합니다:
마지막 명령어는 Vue 개발 서버를 시작하여 페이지를 제공하고, 파일을 수정하면 자동으로 페이지를 새로고침합니다.
브라우저를 열고 https://localhost:8080에 접속하면 기본 Vue 환영 페이지를 볼 수 있습니다:

프론트엔드에 WebSocket 추가하기
Vue 프레임워크는 꽤 간단하며, 이 글에서는 코드를 최대한 단순하게 유지하겠습니다. 먼저 디렉터리 구조를 빠르게 살펴보겠습니다:
├── README.md
├── babel.config.js
├── node_modules
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
└── src
├── App.vue
├── assets
│ └── logo.png
├── components
│ └── HelloWorld.vue
└── main.js루트 레벨의 파일들(babel.config.js, package.json, package-lock.json, node_modules)은 프로젝트 설정에 사용됩니다. 지금 당장 가장 중요한 부분은 src 디렉터리에 있습니다:
- main.js 파일은 애플리케이션의 메인 JavaScript 파일로, 공통 요소들을 로드하고 App.vue 메인 화면을 호출합니다. 나중에 Bootstrap 지원을 추가하기 위해 수정하게 됩니다.
- App.vue는 특정 페이지나 템플릿의 HTML, CSS, JavaScript를 담고 있는 파일입니다. 애플리케이션의 진입점 역할을 하며, 기본적으로 모든 화면에서 공유되므로 알림 클라이언트 코드를 작성하기 좋은 위치입니다.
public/index.html은 DOM이 로드되는 정적 진입점입니다. 파일을 살펴보면 Vue 애플리케이션을 로드하는 데 사용되는 <div id="app">를 확인할 수 있습니다.
이 데모는 매우 간단해서 App.vue와 main.js 두 파일만 수정하면 됩니다. 실제 애플리케이션에서는 여러 곳에서 재사용할 수 있는 Vue.js 컴포넌트를 만드는 것이 좋습니다.
App.vue 파일 수정하여 WebSocket 메시지 표시하기
에디터에서 App.vue 파일을 열고 아래 내용을 추가합니다. 페이지 하단의 </div> 태그 바로 앞에 다음 HTML 블록을 추가하세요:
{{message}} 표기법을 사용하면 Vue에게 message 변수의 내용을 출력하라고 지시하는 것이며, 이 변수는 다음 코드 블록에서 정의합니다.
<script> 부분의 내용을 다음으로 교체합니다:
이 몇 줄의 코드는 다음 작업을 수행합니다:
- WebSocket 서버에 연결 (13번째 줄)
- 서버에서 메시지를 받아 로컬 message 변수에 할당 (13~17번째 줄)
변경된 내용을 자세히 보면 다음을 추가한 것을 알 수 있습니다:
- 화면에 바인딩할 수 있는 로컬 변수를 정의한다고 Vue 컴포넌트에 알려주는 data() 함수 (6~10번째 줄)
- Vue 컴포넌트가 초기화될 때 자동으로 호출되는 created() 함수
Redis에서 Vue 애플리케이션으로 메시지 보내기
추가한 몇 줄의 JavaScript 덕분에 이제 WebSocket 서버와 Vue 프론트엔드가 실행되고 연결되어 있을 것입니다. 이제 테스트해 볼 시간입니다!
Redis CLI 또는 RedisInsight를 사용하여 app:notifications 채널에 메시지를 발행해 보세요. 예를 들어 Docker로 Redis를 시작했다면, 다음 명령어로 접속하여 메시지 발행을 시작할 수 있습니다:
브라우저의 애플리케이션 하단에 메시지가 나타나는 것을 확인할 수 있습니다:

보시다시피 WebSocket을 사용하면 웹 프론트엔드에 실시간으로 콘텐츠를 푸시하는 것이 매우 쉽습니다. 이제 Bootstrap을 활용해 더 사용자 친화적인 인터페이스로 디자인을 개선해 보겠습니다.
Bootstrap으로 알림 블록 만들기
이 섹션에서는 새 메시지가 수신되면 나타나고, 간단한 카운트다운 후 몇 초 뒤 자동으로 사라지는 Bootstrap 알림(alert) 컴포넌트를 사용하는 방법을 보여드립니다.
main.js 파일 수정
main.js 파일을 열고 마지막 import 문 뒤에 다음 줄을 추가합니다:
이 네 줄의 코드는 Vue 애플리케이션에 Bootstrap 컴포넌트를 가져오고 등록합니다.
App.vue 파일 수정
App.vue 파일에서 앞서 추가한 코드(두 <hr/> 태그 사이의 모든 내용과 태그 자체)를 다음으로 교체합니다:
이 컴포넌트는 여러 속성을 사용합니다:
- id="notification": JavaScript나 CSS 코드에서 해당 요소를 참조할 때 사용하는 요소 ID입니다.
- :show="dismissCountDown": dismissCountDown 변수가 null이나 0이 아닐 때만 컴포넌트가 표시됨을 의미합니다.
- dismissible: 사용자가 직접 닫을 수 있도록 알림에 작은 아이콘을 추가합니다.
- @dismissed="dismissCountDown=0": dismissCountDown 값이 0이 되면 알림 상자가 닫힙니다.
- @dismiss-count-down="countDownChanged": 카운트다운 처리 메서드입니다.
이제 알림 컴포넌트에서 사용할 변수와 메서드를 정의하는 JavaScript 코드를 추가합니다:
이 섹션에서 수행한 작업은 다음과 같습니다:
- 알림을 표시했다가 다시 숨기는 타이머를 제어하는 dismissSecs와 dismissCountDown 변수를 data() 메서드에 추가 (4~5번째 줄)
- 알림 컴포넌트를 표시하고 숨기는 메서드 생성 (10~26번째 줄)
- 새 메시지가 수신될 때 showAlert() 메서드 호출 (13번째 줄)
이제 직접 확인해 볼 차례입니다!
redis-cli 또는 RedisInsight로 돌아가 app:notifications 채널에 새 메시지를 발행해 보세요.

마무리
보시다시피 Redis를 활용하면 애플리케이션을 위한 강력한 알림 서비스를 쉽게 만들 수 있습니다. 이 샘플은 단일 채널과 서버를 사용해 모든 클라이언트에 브로드캐스팅하는 매우 기본적인 형태입니다.
이 글의 목표는 WebSocket과 Redis Pub/Sub를 사용해 Redis에서 웹 애플리케이션으로 메시지를 푸시하는 쉬운 시작점을 제공하는 것이었습니다. 다양한 채널을 통해 특정 클라이언트에게 메시지를 전달하고, 애플리케이션을 확장하고 보안을 강화하는 방법은 무궁무진합니다.
또한 WebSocket 서버를 반대 방향으로도 사용할 수 있습니다. 즉, 클라이언트에 메시지를 푸시하는 것뿐만 아니라 메시지를 소비(consume)하는 것도 가능합니다. 다만 이것은 다음 블로그 포스트에서 다룰 큰 주제입니다. 실제로 Redis Gears를 사용해 Redis 데이터베이스 내에서 직접 이벤트를 캡처하고 다양한 클라이언트에 이벤트를 푸시하는 방법에 대한 추가 포스트도 기대해 주세요.
더 자세한 정보는 다음 자료들을 참고하세요:
- Redis Microservices for Dummies (무료 전자책)
- Introduction to Redis Streams (Redis 공식 문서)
- Redis Pub/Sub (Redis 공식 문서)
- Redis University의 무료 온라인 강좌 수강
- Redis Enterprise Cloud 살펴보기