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

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

수많은 우여곡절 끝에 배포된 서버에 채팅 기능을 적용하게 되었다!

간단히 말하자면 원래 담당했던 백엔드 팀원이 던져놓은 빅 똥을 치우게 되었다.

내 프로젝트의 스택은 아래와 같다.

Java 17 / Spring 3.x / JPA / Redis / Spring Security / JWT / OAuth / Websocket / MySQL / Firebase

그리고 처음 팀원이 던져놨던 채팅 구현을 위한 기능은 Kafka + Socket.io 였다. 내가 알기로 Kafka는 MSA구조에서 그룹으로 묶어 메세지를 전달하는 메세지 큐 방식에 적합한 절대 가볍지 않은 스펙의 프레임워크였으며, Socket.io 또한 Spring으로 만든 프로젝트가 아닌 별도로 서버가 생성되는 과정을 요구하는 방식이였으나 팀원을 믿고 기다렸었다.

하지만... 결국 팀원은 중도하차하게 되었고 채팅과 알람을 내가 맡게 되었다.

변경점은 아래와 같고 앞으로 이야기 하게 될 내용들은 아래 기술위주로 진행되었다.

Redis, Websocket, Firebase

 

1. Redis의 Pub/Sub 방식의 사용

가장 접하기 쉽고 자주 만져봤던 Redis를 사용하였고 Pub/Sub 방식으로 구현할 예정이었다.

Pub/Sub에 대한 개념은 아래 그림으로도 충분히 이해 가능할것이다.

Topic(신문)을 구독한 사람이 Publisher(출판사)에서 Topic을 던져주면 Subscriber(구독자)들이 내용을 읽을 수 있게 만드는 것이다.

이론은 항상 쉽지만 막상 만들려고 하면 매우 막막한 주제였다.

2.  WebSocket과 STOMP

이 두 가지는 Spring에서 많은 지원을 해주는 기능이다. 아래 링크를 통해 공식문서 내용을 확인할 수 있다.

https://docs.spring.io/spring-framework/reference/web/websocket/stomp.html

 

STOMP :: Spring Framework

The WebSocket protocol defines two types of messages (text and binary), but their content is undefined. The protocol defines a mechanism for client and server to negotiate a sub-protocol (that is, a higher-level messaging protocol) to use on top of WebSock

docs.spring.io

물론 이걸 다 읽기는 매우 귀찮고 시간이 촉박한 분들이 있을 수 있으니 핵심기능을 간략히 설명하자면 아래와 같다.

프로젝트에서 구현한다는 건 물론 면접에서 물어볼 수도 있는 부분이기에 한 번 알아두면 좋을 것이다.

 

1. Webosocket 프로토콜 지원

클라이언트와 서버가 실시간으로 양방향 통신(전이중 통신)을 할 수 있는 소켓을 연결시켜준다. 기존의 HTTP 통신은 계속해서 연결(stateful)이 아닌 무상태성(stateless) 방식의 연결이다. 이 방식은 다양한 전략이 있으나 내가 아는건 Polling / Long Polling / Streaming정도이다. 이 개념들을 설명하면 글이 길어지니 별도로 기록해두겠다.

스프링은 Websocket을 지원하지 않는 환경에서는 SockJS를 통해 Fallback 옵션을 제공한다.

 

2. STOMP 프로토콜 지원

STOMP(Simple Text Oriented Messaging Protocol)은 Websocket위에 동작하며, Spring에서는 이를 구현하여 메세지 기능을 제공한다. 그 기능으로서 첫 번째는 라우팅 기술이다. @MessageMapping으로 라우팅된 메세지를 처리하고, 특정 목적지로 메세지를 보낸다. 두 번째는 주제 및 큐 지원이다. STOMP의 목적지 패턴을 통해  topic(BroadCasting)과 queue(1:1메시징)를 모두 지원한다.

 

3. 메세지 브로커 구성

내장 브로커를 통해 Web Socket 세션 내에서 간단한 목적지 간의 메세지 전달을 처리한다.

외장 브로커를 통해 RabbitMQ와 같은 외부 메세지 브로커를 사용하여 확장가능하고 신뢰성 있는 메세지를 전달한다.

 

4. SockJS폴백 지원

HTTP기반 대체 통신으로 AJAX Long Polling, XHR Streaming, Server-Sent Events(SSE) 등을 사용하여 WebSocket이 지원되지 않는 환경에서도 동작할 수 있게 해준다.

클라이언트 호환성 확대로 구형 브라우저에서도 Websocket기반 메세징 기능을 제공한다.

 

5. 메세지 처리 핸들러

@MessageMapping으로 특정 목적지에 도달한 메세지를 처리한다.

@SendTo 처리된 결과를 특정 주제나 목적지로 브로드캐스트 한다.

@SubScribeMapping으로 클라이언트가 특정 주제를 구독했을 때  초기 데이터를 제공한다.

 

6. WebSocket 세션 관리

연결 이벤트 리스너 SessionConnectEvent, SessionDisconnectEvent를 통해 연결 상태를 추적할 수 있다.

 

7. 권한 통합

Spring Security와 통합하여 Handshake인증 , 목적지 기반 권한 부여가 가능하다.

 

8. 클라이언트 라이브러리 호환성

STOMP.js를 사용하여 브라우저에서 STOMP프로토콜 사용이 가능하다.

브라우저에서 Sock JS 폴백 옵션을 활용할 수 있다.

 

 

3.  의존성 주입

일부 의존성만 보여주면 환경구성에 문제가 생길 수 있기 때문에 중요한 정보들을 제외하고는 전체 코드를 공개하려고 한다.

yml파일은 websocket관련 설정이 없기 때문에 넘어가겠다.

여기서 사용한 Firebase는 유저가 미접속 상태일때 채팅이 전송되는 경우 알림을 생성해내기 위한 용도로 사용되었다.

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-jdbc'
    implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-validation'
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-redis', version: '3.3.0'



    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    implementation 'com.mysql:mysql-connector-j'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.security:spring-security-test'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

    //jwt
    implementation 'org.json:json:20231013'
    implementation 'com.auth0:java-jwt:4.2.1'
    implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
    implementation 'io.jsonwebtoken:jjwt-impl:0.11.5'
    implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5'

    //mapstruct
    implementation 'org.mapstruct:mapstruct:1.5.5.Final'
    annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final'
    annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0'

    //swagger ui
    implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'
    implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.1.0'
    testImplementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-api', version: '2.1.0'

    //Json Parsing
    implementation 'com.fasterxml.jackson.core:jackson-databind'

    //aws s3
    implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

    //AOP
    implementation 'org.springframework.boot:spring-boot-starter-aop'

    //fcm
    implementation 'com.google.firebase:firebase-admin:9.2.0'

    //web socket
    implementation 'org.springframework.boot:spring-boot-starter-websocket'

 

 

다음 포스팅에서는 Websocket과 Redis Config파일 설정을 알아보겠다.

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.29
[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)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

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

    • 최근 글

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

    티스토리툴바