이 튜토리얼에서는 Jedis 라이브러리를 활용해 Redis Pub/Sub(발행/구독) 시스템을 구현하는 방법을 단계별로 알아봅니다.
Jedis 라이브러리란?
Jedis는 Redis 데이터 저장소를 위한 Java 클라이언트 라이브러리입니다. 가볍고 사용법이 매우 간단하며, Redis 2.8.x, 3.x.x 이상 버전과 완벽하게 호환됩니다. 최신 버전은 Maven Central Repository에서 확인할 수 있습니다.
Redis Pub/Sub 시스템의 동작 원리
Redis는 발행/구독(Publish/Subscribe) 메시징 패러다임을 지원합니다. 이 패러다임에서 메시지 발신자(발행자, Publisher)는 특정 수신자(구독자, Subscriber)에게 메시지를 직접 전송하지 않습니다. 대신 발행자는 특정 채널(channel)에 메시지를 발행(publish)하며, 그 메시지를 누가 소비할지, 아니면 아무도 소비하지 않을지조차 알지 못한 채 전송합니다.
반대로 메시지를 받고 싶은 수신자는 하나 이상의 채널을 구독(subscribe)함으로써 관심을 표현하고, 해당 채널에 발행된 메시지만 수신하게 됩니다. 이때 구독자 역시 메시지를 보낸 발행자가 누구인지 알 필요가 없습니다. 이렇게 발행자와 구독자는 서로 완전히 분리(decoupled)되어 있어, 유연하고 확장 가능한 비동기 메시징 아키텍처를 구성할 수 있습니다.
프로젝트 설정
선호하는 IDE에서 간단한 Maven 프로젝트를 생성한 뒤, pom.xml 파일에 다음 의존성을 추가합니다.
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.0.1</version> </dependency>
더 최신 버전의 Jedis 라이브러리가 필요하다면 Maven Central 페이지에서 확인하세요.
Redis 설치
실습을 진행하려면 최신 버전의 Redis가 설치되어 있어야 합니다. 운영체제에 맞게 공식 설치 가이드를 참고해 Redis를 준비해 주세요.
Jedis 연결 생성
Java 코드와 Redis 서버를 연결하려면 Jedis(redis.clients.jedis.Jedis) 클래스의 객체를 생성합니다.
Jedis jedis = new Jedis();
로컬 머신에서 기본 포트(6379)로 Redis 서비스를 실행 중이라면 기본 생성자만으로 충분합니다. 그렇지 않은 경우에는 생성자에 올바른 호스트 주소와 포트 번호를 인자로 전달해야 합니다.
채널 구독하기 (Subscribe)
"ChannelSubscribe" 클래스를 생성합니다. 이 클래스는 클라이언트를 만들어 C1, C2 두 개의 채널을 구독하며, 다른 클라이언트가 C1 또는 C2 채널에 메시지를 발행할 때마다 해당 메시지를 수신합니다.
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;
public class ChannelSubscribe {
public static void main(String[] args) {
Jedis jedis = null;
try {
/* Creating Jedis object for connecting with redis server */
jedis = new Jedis();
/* Creating JedisPubSub object for subscribing with channels */
JedisPubSub jedisPubSub = new JedisPubSub() {
@Override
public void onMessage(String channel, String message) {
System.out.println("Channel " + channel + " has sent a message : " + message );
if(channel.equals("C1")) {
/* Unsubscribe from channel C1 after first message is received. */
unsubscribe(channel);
}
}
@Override
public void onSubscribe(String channel, int subscribedChannels) {
System.out.println("Client is Subscribed to channel : "+ channel);
System.out.println("Client is Subscribed to "+ subscribedChannels + " no. of channels");
}
@Override
public void onUnsubscribe(String channel, int subscribedChannels) {
System.out.println("Client is Unsubscribed from channel : "+ channel);
System.out.println("Client is Subscribed to "+ subscribedChannels + " no. of channels");
}
};
/* Subscribing to channel C1 and C2 */
jedis.subscribe(jedisPubSub, "C1", "C2");
} catch(Exception ex) {
System.out.println("Exception : " + ex.getMessage());
} finally {
if(jedis != null) {
jedis.close();
}
}
}
}
실행 결과
"ChannelSubscribe" 클래스를 실행하면 다음과 같은 출력 결과를 확인할 수 있습니다.

채널에 메시지 발행하기 (Publish)
"ChannelPublish" 클래스를 생성합니다. 이 클래스는 Jedis 연결을 통해 Redis 서버에 접속한 후, C1과 C2 채널 각각에 두 개씩 총 네 개의 메시지를 발행합니다.
import redis.clients.jedis.Jedis;
public class ChannelPublish {
public static void main(String[] args) {
Jedis jedis = null;
try {
/* Creating Jedis object for connecting with redis server */
jedis = new Jedis();
/* Publishing message to channel C1 */
jedis.publish("C1", "First message to channel C1");
/* Publishing message to channel C2 */
jedis.publish("C2", "First message to channel C2");
/* Publishing message to channel C1 */
jedis.publish("C1", "Second message to channel C1");
/* Publishing message to channel C2 */
jedis.publish("C2", "Second message to channel C2");
} catch(Exception ex) {
System.out.println("Exception : " + ex.getMessage());
} finally {
if(jedis != null) {
jedis.close();
}
}
}
}
실행 결과
"ChannelPublish" 클래스를 실행하면 ChannelSubscribe 콘솔에 다음과 같은 출력이 나타납니다.

패턴 구독하기 (PSubscribe)
"PatternSubscribe" 클래스를 생성합니다. 이 클래스는 클라이언트를 만들어 C*와 D? 패턴을 구독합니다. 패턴 구독을 활용하면 glob 스타일 와일드카드(*, ? 등)와 일치하는 모든 채널의 메시지를 한 번에 수신할 수 있어, 채널 이름이 규칙적으로 관리되는 환경에서 특히 유용합니다.
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;
public class PatternSubscribe {
public static void main(String[] args) {
Jedis jedis = null;
try {
/* Creating Jedis object for connecting with redis server */
jedis = new Jedis();
/* Creating JedisPubSub object for subscribing with channels */
JedisPubSub jedisPubSub = new JedisPubSub() {
@Override
public void onPMessage(String pattern, String channel, String message) {
System.out.println("Channel " +channel+ " has sent a message : " +message+ " on pattern " + pattern);
if(pattern.equals("C*")) {
/* Unsubscribe from pattern C* after first message is received. */
punsubscribe(pattern);
}
}
@Override
public void onPSubscribe(String pattern, int subscribedChannels) {
System.out.println("Client is Subscribed to pattern : "+ pattern);
System.out.println("Client is Subscribed to "+ subscribedChannels + " no. of patterns");
}
@Override
public void onPUnsubscribe(String pattern, int subscribedChannels) {
System.out.println("Client is Unsubscribed from pattern : "+ pattern);
System.out.println("Client is Subscribed to "+ subscribedChannels + " no. of patterns");
}
};
/* Subscribing to channel C1 and C2 */
jedis.psubscribe(jedisPubSub, "C*", "D?");
} catch(Exception ex) {
System.out.println("Exception : " + ex.getMessage());
} finally {
if(jedis != null) {
jedis.close();
}
}
}
}
실행 결과
"PatternSubscribe" 클래스를 실행하면 다음과 같은 출력 결과를 확인할 수 있습니다.

패턴 대상 채널에 메시지 발행하기
"PatternPublish" 클래스를 생성합니다. 이 클래스는 Jedis 연결을 통해 Redis 서버에 접속한 후, C13, D2, C134, D3 채널에 각각 메시지를 발행합니다. C* 패턴은 C13, C134 채널에, D? 패턴은 D2, D3 채널에 매칭됩니다.
import redis.clients.jedis.Jedis;
public class PatternPublish {
public static void main(String[] args) {
Jedis jedis = null;
try {
/* Creating Jedis object for connecting with redis server */
jedis = new Jedis();
/* Publishing message to channel C13 */
jedis.publish("C13", "Message to channel C13");
/* Publishing message to channel D2 */
jedis.publish("D2", "Message to channel D2");
/* Publishing message to channel C134 */
jedis.publish("C134", "Message to channel C134");
/* Publishing message to channel D3 */
jedis.publish("D3", "Message to channel D3");
} catch(Exception ex) {
System.out.println("Exception : " + ex.getMessage());
} finally {
if(jedis != null) {
jedis.close();
}
}
}
}
실행 결과
"PatternPublish" 클래스를 실행하면 PatternSubscribe 콘솔에 다음과 같은 출력이 나타납니다.

참고 자료
- Redis Pub/Sub 공식 명령어 문서
지금까지 Jedis 라이브러리를 사용해 Redis Pub/Sub 시스템을 구현하는 방법을 알아보았습니다. 내용이 도움이 되셨다면 댓글로 의견을 남겨주시고, 주변에도 널리 공유해 주세요!