Redis Pub/Sub을 활용한 채팅 구현의 여정 - 환경설정

2024. 11. 29. 02:18·Redis/Redis 채팅
728x90
반응형
SMALL

https://sunro1994.tistory.com/253

 

Redis Pub/Sub을 활용한 채팅 구현의 여정 - 개념편

수많은 우여곡절 끝에 배포된 서버에 채팅 기능을 적용하게 되었다!간단히 말하자면 원래 담당했던 백엔드 팀원이 던져놓은 빅 똥을 치우게 되었다.내 프로젝트의 스택은 아래와 같다.Java 17 / Sp

sunro1994.tistory.com

이전 글에서는 Redis를 사용한 채팅 기능 구현을 위한 개념에 대해 간단히 알아보았다.

 

이번에는 WebSocket과 Redis의 Config파일 및 필요한 설정들에 대해 적어보려고 한다.

@EnableWebSocketMessageBroker어노테이션을 적용하여 웹소켓 메세지 브로커에 대한 설정을 적용한다.

통신에 필요한 목적지 설정(configureMessageBroker)에서 목적지 접두사는 /sub,  애플리케이션에서 처리할 메세지는 /pub 으로 접두사를 지정한 것을 확인할 수있다.

configureWebSocketTransport메서드는 전송할 수 있는 파일크기이다. 이 파일크기를 적절하게 저장하지 않으면 저장소에 엄청난 용량의 데이터를 전송시켜 서버를 과부하걸리게 공격할 수도 있다고한다. 
registerStompEndpoints 메서드는 엔드포인트를 설정해준다. 나는 /ws를 설정했고 오리진으로 내 도메인 주소를 적용했다.
예를들어 실제 통신 주소는 wss://도메인주소/ws를 통해 소켓연결을 할 수 있다는 설정이다.
ssl을 적용했다면 wss일테고 그냥 http통신으로 보안적용이 되지 않았다면 ws 프로토콜을 사용할 것이다.
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {


    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        //간단한 메모리 기반 메시지 브로커를 활성화, 브로커의 목적지 접두사는 "/sub"
        registry.enableSimpleBroker("/sub");
        // 애플리케이션에서 처리할 메시지의 접두사는 "/pub"
        registry.setApplicationDestinationPrefixes("/pub");
    }

    @Override
    public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
        registration.setMessageSizeLimit(200 * 1024 * 1024); // 메세지 크기 제한 오류 방지(이 코드가 없으면 byte code를 보낼때 소켓 연결이 끊길 수 있음)
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) { // (5)
        registry.addEndpoint("/ws")
                .setAllowedOriginPatterns("통신할 주소")
                .withSockJS();
    }
}

 

 

 

다음은 Redis의 Config파일 설정이다.

1. redis host와 port를 @Value 어노테이션으로 설정값을 불러와 변수로 사용한다.

2. ChannelTopic을 빈으로 등록하여 해당 토픽으로 채팅 내용을 주고 받을 수 있도록 채널을 설정한다.

3. redisTemplate의 지네릭은 각자 타입에 맞게 생성해주길 바란다. 지금은 <Object,Object> 이지만 <String, ChattingRequestDto>와 같은 타입으로 변경하여 설정해야 하는 상황이 발생할 수도 있다.

4. 이 부분에서 삽질을 많이 할 수도있다. messageListenerAdapter 메서드를 보면 "sendMessage"라는 메서드를 ListenerMethod로 설정한다. 이 메서드는 SubScriber전용 클래스를 생성하여 내부 메서드이름을 동일하게 생성해야 한다.

아래 예시코드를 첨부해놨다.

5. 마지막 redisMessageListener 에서는 위에서 설정한 내용들을 담는 컨테이너를 생성하여 빈으로 등록해주었다.

 

이 과정을 통해서 애플리케이션이 초기화 단계에 아래 내용들을 설정하고 웹소켓을 이용할 준비를 마친다.

@RequiredArgsConstructor
@Service
@Slf4j
public class RedisSubscriber {

    private final ObjectMapper objectMapper;
    private final SimpMessageSendingOperations messagingTemplate;

//messageListenerAdapter의 매개변수 이름과 동일해야 감지가 가능하다
    public void sendMessage(String message) {
        try{
            ChattingResponseDto requestMessage = objectMapper.readValue(message, ChattingResponseDto.class);
            log.info("chattingRequestDto: {}", requestMessage.getContent());
            log.info("chattingResponseDto: {}", requestMessage.getImage());
            messagingTemplate.convertAndSend("/sub/chat/room/" + requestMessage.getRoomId(), requestMessage);
        } catch (Exception e){
            log.error(e.getMessage());
        }
    }


}

 

위 설명을 기반으로 한 전체 코드

@Configuration
public class RedisConfig {

    @Value("${spring.data.redis.host}")
    private String host;


    @Value("${spring.data.redis.port}")
    private String port;

    //RedisConnectionFactory 빈을 생성하는 메서드
    //Redis서버와의 연결을 설정하고 관리하는데 사용

    @Bean
    public ChannelTopic channelTopic() {
        return new ChannelTopic("chatroom");
    }
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setHostName(host);
        redisStandaloneConfiguration.setPort(Integer.parseInt(port));
        return new LettuceConnectionFactory(redisStandaloneConfiguration);
    }

    @Bean
    public RedisTemplate<Object, Object> redisTemplate() {
        RedisTemplate<Object,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        //키를 위한 직렬화 설정
        redisTemplate.setKeySerializer(new GenericToStringSerializer<>(Long.class)); // Key를 Long 타입으로 처리
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        //값을 위한 직렬화 설정
        Jackson2JsonRedisSerializer<ChatRoom> serializer = new Jackson2JsonRedisSerializer<>(ChatRoom.class);
        redisTemplate.setValueSerializer(serializer);  // Value를 JSON 형태로 직렬화
        redisTemplate.setHashValueSerializer(serializer);
        return redisTemplate;
    }

    
    @Bean
    public MessageListenerAdapter messageListenerAdapter(RedisSubscriber subscriber) {
        return new MessageListenerAdapter(subscriber, "sendMessage");
    }

    /**
     * redis 에 발행(publish)된 메시지 처리를 위한 리스너 설정
     */
    @Bean
    public RedisMessageListenerContainer redisMessageListener (
            MessageListenerAdapter listenerAdapterChatMessage,
            ChannelTopic channelTopic
    ) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory());
        container.addMessageListener(listenerAdapterChatMessage, channelTopic);
        return container;
    }
}

 

 

다음 포스팅에서는 Chat 도메인에 대한 엔티티(ChatRoom) 및 컨트롤러(ChatController), 서비스(pubService, subService, Chatservice)를 올리도록 하겠다.

참고로 나는 채팅방은 MySQL로 저장하고 채팅 내용은 Redis에 저장하며 3일동안만 저장이 가능하도록 설정하였다.

728x90
반응형
SMALL

'Redis > Redis 채팅' 카테고리의 다른 글

Redis Pub/Sub을 활용한 채팅 구현의 여정 - Service 레이어  (0) 2024.12.19
Redis Pub/Sub을 활용한 채팅 구현의 여정 - Chat Domain(Entity ~ Controller)  (1) 2024.12.08
Redis Pub/Sub을 활용한 채팅 구현의 여정 - 개념편  (0) 2024.11.28
[Redis] SpringBoot + Redis Pub/Sub 으로 채팅 구현 하기  (0) 2024.07.18
'Redis/Redis 채팅' 카테고리의 다른 글
  • Redis Pub/Sub을 활용한 채팅 구현의 여정 - Service 레이어
  • Redis Pub/Sub을 활용한 채팅 구현의 여정 - Chat Domain(Entity ~ Controller)
  • Redis Pub/Sub을 활용한 채팅 구현의 여정 - 개념편
  • [Redis] SpringBoot + Redis Pub/Sub 으로 채팅 구현 하기
공부하고 기억하는 공간
공부하고 기억하는 공간
IT 비전공자로 시작하여 훌륭한 개발자가 되기 위해 공부하고 있는 공간입니다. 틀린 내용이나 부족한 부분이 있으면 댓글로 알려주세요 바로 수정하겠습니다.
    250x250
  • 공부하고 기억하는 공간
    IT - railroad
    공부하고 기억하는 공간
  • 전체
    오늘
    어제
    • 분류 전체보기 (325)
      • 면접 준비 (22)
        • OS (6)
        • Spring Security (0)
        • Java (3)
        • DB (11)
        • Network (3)
      • ElasticSearch (2)
      • Kafka (4)
      • Spring (22)
        • Spring Cloud (7)
        • Security6 (5)
        • JPA (12)
        • 프로젝트 리팩토링 회고록 (4)
        • Logging (8)
        • Batch (2)
      • Redis (17)
        • Redis 개념 (8)
        • Redis 채팅 (5)
        • Redis 읽기쓰기 전략 (1)
      • AWS (11)
      • 리눅스 (29)
        • 리눅스 마스터 2급 (5)
        • 네트워크(기초) (7)
        • 리눅스의 이해 (6)
        • 리눅스의 설치 (2)
        • 리눅스 운영 및 관리 (6)
      • JAVA-기초 (16)
        • JAVA기본 (11)
        • Design Pattern (5)
      • JSP (27)
        • JSP 기본 개념 (10)
        • JSP (1)
      • SQL (1)
      • TIL (36)
      • 문제 풀이 (2)
        • Programmers (9)
        • 백준 문제풀이 (28)
      • JavaScript (10)
      • HTML (17)
      • Ngrinder (1)
        • Ngrinder 문서 정리 (1)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      자바스크립트
      스프링프레임워크
      자바 면접
      리눅스
      JavaScript
      Til
      자바 반복문
      jsp request
      백준
      CSS
      springsecurity
      JS
      자바 알고리즘
      jsp기초
      redis
      Spring
      자바기초
      자바
      리눅스마스터2급
      Spring Data Redis
      레디스
      spring redis
      JSP
      리눅스마스터2급정리
      redis 채팅
      프로그래머스
      HTML
      Springframework
      자바 면접질문
      java
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.3
    공부하고 기억하는 공간
    Redis Pub/Sub을 활용한 채팅 구현의 여정 - 환경설정
    상단으로

    티스토리툴바