본문 바로가기
개발/SpringBoot

SpringBoot Redis 활용 - Pub/Sub

by 궁즉변 변즉통 통즉구 2022. 12. 16.
반응형

Redis는 DB,Cache 기능 외에 Pub/Sub기능을 제공한다. SpringBoot에서 Redis의 Pub/Sub을 어떻게 활용하는지 알아보고자 한다.

Redis Pub/Sub의 특징을 간단히 다음과 같다

 - 가볍고 빠르다

 - 메시지 전송에 대한 보장을 못한다(Subscriber가 실시간으로 메시지를 받지 못하면 그 메시지는 버려진다)

 - 간단하고 가벼운 실시간 pub/sub 처리에 적합

 

SpringBoot에서 Redis Pub/Sub을 사용하기 위한 설정부터 알아보자

1. SpringBoot 설정

build.gradle에 redis 의존성을 추가한다.

implementation 'org.springframework.boot:spring-boot-starter-data-redis'

 

application.yml에 redis 접속정보를 설정한다.

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    # password: 'xxxx' # 비밀번호 있을 경우 설정

 

RedisConfig파일을 작성한다. RedisMessageListenerContainer빈을 등록하면서 redis연결정보, 메시지 리스너, 토픽을 설정한다.

@RequiredArgsConstructor
@Configuration
public class RedisConfig {

    // applicaton.yml redis 설정
    private final RedisProperties redisProperties;
    
    // redisSubscriber(아래 내용에 빈 선언 있음)
    private final RedisSubscriber redisSubscriber;

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory(redisProperties.getHost(), redisProperties.getPort());
    }

    @Bean
    public RedisMessageListenerContainer redisMessageListener(RedisConnectionFactory connectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.addMessageListener(redisSubscriber, myTopic()); // listener 및 토픽 등록
        return container;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        // Jackson2JsonRedisSerializer 설정
        redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(String.class));
        return redisTemplate;
    }

	@Bean
	public ChannelTopic myTopic() {
		return new ChannelTopic("myTopic");
	}

 

테스트를 위한 간단한 도메인 객체를 생성한다.

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Member {
    private String id;
    private String fName;
    private String lName;
    private Address address;
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Address {
    private String address;
    private String etc;
}

 

메시지를 전송한 Publisher를 작성한다. 메소드는 일단 String 메시지와 객체 전송을 위한 메소드 2개로 작성했다.

@Service
@AllArgsConstructor
public class RedisPublisher {

    private final RedisTemplate<String, Object> redisTemplate;

    public void publish(ChannelTopic topic, String message) {
        redisTemplate.convertAndSend(topic.getTopic(), message);
    }

    public void publishPojo(ChannelTopic topic, Member member) {
        redisTemplate.convertAndSend(topic.getTopic(), member);
    }
}

 

메시지를 수신해서 처리할 Subscriber를 작성한다. MessgeListener를 implements 해야한다. 

@Service
@AllArgsConstructor
public class RedisSubscriber implements MessageListener {

    private final ObjectMapper objectMapper;
    private final RedisTemplate redisTemplate;

    @Override
    public void onMessage(Message message, byte[] pattern) {
        try {
            // simple message 테스트
//            String msg = (String) redisTemplate.getStringSerializer()
//                          .deserialize(message.getBody());
//            String data = objectMapper.readValue(msg, String.class);
//            System.out.println(data);


            // pojo 메시지 테스트
            Member member = objectMapper.readValue(message.getBody(), Member.class);
            System.out.println(member);
            System.out.println(member.getFName());
            System.out.println(member.getLName());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

테스트를 위한 Controller를 작성하고 실행해본다. 

@RestController
@RequestMapping("pubsub")
@AllArgsConstructor
public class PubSubController {

    private final ChannelTopic myTopic;
    private final RedisPublisher redisPublisher;
    
    @PostMapping("/topics/myTopic")
    public void pushMessage(@PathVariable String name) {

        // simple message
        //redisPublisher.publish(myTopic, message);

        // pojo
        Address address = new Address("Korea Seoul", "kangnam");
        Member member = new Member(null, "kildong", "hong", address);
        redisPublisher.publishPojo(myTopic, member);
    }
    
}

POST방식으로 http://localhost:8080/pubsub/topics/myTopic 호출하면 myTopic이라는 채널로 메시지를 Publish하고, myTopic 채널을 Subscribe하고 있는 RedisSubscriber가 메시지를 수신하여 아래와 같은 콘솔 로그를 출력하는 것을 볼수 있다.

 

 

반응형

댓글