규턴의 개발블로그
article thumbnail

 

해당 프로젝트에서 채팅 구현을 맡고 있었다.

 

이전까지는 단지 STOMP프로토콜을 사용해 직접 client에게 메세지르 바로 보내는 것을 구현하였다.

 

하지만 해당 과정은 synchronize하기 때문에 다량의 트래픽이 몰린다면 문제가 발생될 수 있었다.

 

이것을 해결하기 위해서 pub/sub 구조인 Message queue를 도입하고자한다.

 

Message queue의 후보지는 2가지가 있다.

 

1. Kafka

2. Redis

 

이 두개의 차이점을 비교하고 현재 나의 프로젝트에 맞는 Message Queue를 선택하고자 한다.

 

또한 DB도 문제이다.

 

현재는 MYSQL에다 채팅 데이터를 저장하고 있다.

 

항상 고민됐던게 MYSQL에 트랜잭션도 자주 발생하고 성능도 고려가 된다...

 

만약 채팅을 위한 DB를 구성하고 해당 DB를 NOSQL을 사용한다면? 이라는 고민을 시작하게 되었다.

 

 

 

 

Kafka vs Redis

 

해당 표는 Message Queue에 대한 관점만을 비교한다.

 

내가 중점적으로 비교할 것은 순서보장과 실시간성이다.

 

 

  Kafka Redis
브로커 종류 이벤트 브로커(삭제 X) 메세지 브로커(처리되면 삭제)
속도 redis보다 느림(디스크 기반) kafka 보다 빠름 (memory 기반)
topic topic생성이 필요 생성이 필요없음
삭제 작업 기본적으로 데이터가 삭제되지않고 따로 처리를 해야함 처리가 되면 바로 삭제 가능
thread multi single
scale-out 가능( zookeeper 필요) 가능
무거운 정도 무거움 가벼움
순서보장 O 애매

 

kafka도 사용해본 경험이 있으며, redis도 사용해본 경험이 있지만, redis를 pub/sub 모델로는 사용해본 경험이 없으며 redis에 대해 깊게 공부해보고 싶은 생각도 있기에 redis 가 끌렸다.

 

하지만 일반적으로 redis를 사용하는경우는 순서보장이 확실하지 않은 라이브 다중 채팅에 더 어울리는것 같다.

 

내가 구현하고자 하는것은 1:1 채팅 프로그램이며 순서보장이 중요하며 redis만큼 빠르지 않아도 괜찮다.

 

그렇기에 kafka를 사용하고자 한다.

 

 

어떠한 DB를 선택?

 

 

이전에 구현했을때는 MYSQL에 다른 비지니스로직과 합쳐진 데이터베이스를 구축하였다. 

 

하지만 해당 과정은 많은 트랜잭션을 요구로 하기에 우선은 채팅 메세지를 저장하는 다른 DB를 별도로 구축할 예정이다.

 

해당 과정을 통해 얻는 이점은

 

많은 트랙잭션으로부터 벗어날 수 있으며 채팅 메시지의 특성상 Read:Write 비율이 1:1로 같다.  성능적으로 접근이 빠른 NOSQL을 사용해볼 수 있다.

 

그렇다면 NOSQL중에는 어떤 DB가 좋을까?

 

선택과정은 다음과 같았다. (MONGODB 선택)

 

 

1.유연한 스키마(추후 데이터 추가 및 변경 될 수 있음)
2.수평적 확장이 쉽다
3.데이터 접근 지연시간이 낮음
4.TTL 인덱스 지원
채팅 데이터는 라이브 방송이 끝나면 삭제되어야한다.
5.read/write 성능 뛰어남(write에 최적화된 cassandra 제외)
6.러닝커프가 너무 높지 않은 수준이어야함(hbase 제외)

 

 

최종 결론

 

kafka를 사용하여 MQ기능을 구현할 예정이며 MongoDB를 구성하여 채팅메세지 전용 DB를 구축할 예정이다.

 

우선은 채팅서버를 두지 않으며 비지니스 로직 API 서버와 함께 구현하고 추후 사용자가 많이질 경우에 분리해서 사용할 예정이다. 그렇기에 현재 코드를 구성할때 추후 확장성을 고려해서 채팅 메세지 관련된 로직은 최대한 확장성을 열어두고 코드를 작성해야 할 것 같다.

 

 

@Controller
public class ChatController {

  @Autowired
  private KafkaTemplate<String, String> kafkaTemplate;

  @Autowired
  private SimpMessagingTemplate messagingTemplate;

  @MessageMapping("/chat/{roomId}")
  public void sendMessage(@DestinationVariable String roomId, String message) {
    kafkaTemplate.send(roomId, message);
  }

  @KafkaListener(topics = "{roomId}", groupId = "group_id")
  public void receiveMessage(@Payload String message, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) {
    ChatMessage chatMessage = new ChatMessage();
    chatMessage.setMessage(message);
    // set other fields in chatMessage as needed

    // process chat message as needed, e.g. saving to database

    ChatMessageResponseDto chatMessageResponseDto = new ChatMessageResponseDto(chatMessage);

    messagingTemplate.convertAndSend("/queue/"  + chatMessage.getChatRoom().getChatRoomId(), chatMessageResponseDto);
  }
}

(해당 코드는 chat gpt에게 받은 샘플코드이다. 추후 고려해서 코드를 작성해볼까 한다.)

 

https://velog.io/@gkdud583/%EC%B1%84%ED%8C%85-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EC%84%A4%EA%B3%84%ED%95%98%EA%B8%B0

 

채팅 아키텍처 설계하기 v1

이번에 진행하는 프로젝트에서 채팅, 신고 도메인을 맡았고 캠프장님께 아키텍처 리뷰를 받기전에 간략하게 설계한 아키텍처를 기록한다. 신고

velog.io

https://www.youtube.com/watch?v=73Utd7nDYDs

profile

규턴의 개발블로그

@규턴이

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!