토이 프로젝트 일지 8: 실시간 그룹 채팅 마이크로 서비스 만들기

 

그림 1. 이벤트 스토밍 설계도

그림 2. 프론트엔드 페이지들

1. 시작 계기

플랫폼 비즈니스 교육에서 수행되는 개인 PBL(Project Based Learning)에 제출하기 위해서 구현한 서비스다. 마이크로 서비스상에서 통합된 사용자 인증을 위해서 게이트웨이를 통한 JWT 단일 인증 엔드 포인트 구현, 사용자 포인트에서 동기적인 서비스 제공을 유지하기 위해서 웹 소켓을 활용해 보는 것을 중점으로 두었다. 해당 기술들을 활용하는 데 있어서 그룹 채팅 서비스를 구현해 보는 것이 가장 적합해 보여서 해당 서비스를 채택하였다.

2. 프로젝트 개요

가. 프로젝트 소개

1. 프로젝트 유형: 개인 토이 프로젝트

2. 구현 서비스: 그룹 채팅 서비스

3. 개발 환경: VS Code, Msaez

4. 활용기술

    프론트앤드: React, MUI
    백엔드 A(User, Room, Message, File, Gateway)Spring-Boot, JPA, MySQL
    백엔드 B(ExternalSystem): Flask
    구조설계: MSA(Event Driven Architecture), CQRS, SAGA, Kafka, WebSocket, JWT
    외부서비스: AWS S3
    빌드 및 배포: EKS

5. 개발 기간: 2023.12.31 ~ 2024.01.09

3. 프로젝트 구현

가. 요구사항 분석

그림 3. 요구사항 분석

나. 이벤트 스토밍 설계

나-1. 주요 Bounded Context

그림 4. 이벤트 스토밍 Bounded Context(BC)

총 6개의 BC가 존재하며, 각각의 주요 기능 및 역할을 다음과 같다.

user: 회원가입 및 RSA 기반 JWT 토큰 발급을 관리한다.

file: 프로필 및 메세지에 사용되는 이미지 파일 메타정보를 관리한다.

externalSystem: AWS S3에 이미지 파일을 저장하고, 관련 접근 URL을 반환한다.

room: 채팅룸을 생성하고, 채팅룸에 유저를 추가해 준다.

message: 메세지를 추가 및 관리한다.

collectedData: CQRS를 관리하기 위한 ReadModel이며, 모든 이벤트 관련 정보를 수집하고 웹 소켓을 통해서 이를 필요로 하는 클라이언트에 알려준다.

나-2. 회원가입 과정

그림 5. 이벤트 스토밍 회원가입 과정

모든 백엔드 알고리즘은 각각의 BC에 대해서 비동기적으로 수행된다. 하지만, 프론트엔드에서의 사용자는 동기적으로 이러한 과정을 기다릴 필요가 있기 때문에 이러한 부분을 해결하기 위해서 ReadModel에 웹 소켓을 추가해서 사용자가 웹 소켓으로 해당 과정을 기다리도록 구현했다.

회원가입 과정을 간략하게 설명하면 다음과 같다.

[1] 사용자는 user BC에 회원가입 요청을 한다.

[2] user BC에서 얻은 프로파일 이미지 Data URL을 file BC로 보낸다.

[*] 사용자는 얻게 된 유저 ID를 이용해서 collectedData에 회원가입 성공 여부를 웹 소켓으로 구독한다.

[3] file BC는 externalSystem BC를 통해서 AWS S3에 해당 이미지를 업로드한다. 실패했을 경우에는 원자성을 제공하기 위한 SAGA 패턴이 수행된다.

[4] 정상적으로 완료 시에 관련 이벤트가 발생해서 유저는 웹 소켓을 통해서 완료 여부를 알 수 있게 된다.

나-3. 로그인 과정

그림 6. 이벤트 스토밍 로그인 과정

user BC에서 발급된 JWT는 Gateway에서 통합인증을 수행하고, 관련 정보를 헤더에 추가하게 해두었다. 이렇게 함으로써 다른 BC에서는 유저 인증과 관련된 로직을 구현하지 않아도 된다.

나-4. 그룹 채팅방 생성 과정

그림 7. 이벤트 스토밍 그룹 채팅방 생성 과정

생성된 그룹 채팅방에는 고유 코드가 발급되며, 해당 코드를 다른 상대방에게 전달해서 유저를 추가할 수 있도록 해두었다.

그룹 채팅방 생성 과정을 간략하게 설명하면 다음과 같다.

[1] 사용자는 room BC에 그룹 채팅방 생성을 요청한다.

[2] 그룹 채팅방을 생성한 뒤에 생성자를 채팅방의 첫 유저로 추가한다.

[*] 그룹 채팅방 생성 여부를 웹 소켓으로 구독할 수 있다.

[3] 그룹 채팅방에서 생성된 고유 코드를 통해서 다른 유저를 추가할 수 있다.

나-5. 실시간 채팅 메세지 생성 과정

그림 8. 이벤트 스토밍 실시간 채팅 메세지 생성 과정

유저는 각각의 방에 생성된 메세지에 대해서 웹 소켓으로 구독함으로써 실시간으로 메세지를 받아볼 수 있도록 구현했다.

실시간 채팅 메세지 생성 과정을 간략하게 설명하면 다음과 같다.

[1] 사용자는 message BC에 메세지 생성을 요청한다.

[2~4] 이미지 Data URL이 전달된 경우에는 이미지 파일을 AWS S3에 업로드하고, 관련 URL을 반환시켜서 최종적으로 메세지를 생성시킨다.

[*] 메세지 생성 여부를 구독할 수 있다.

다. 프론트엔드 구현

다-1. 그룹 채팅방 관리 페이지

그림 9. 그룹 채팅방 관리 페이지


[1] 그룹 채팅방에 참여한 유저 수 표시

[2] 그룹 채팅방이 생성된 시각이나 마지막 메세지가 생성된 시각을 표시

[3] 마지막으로 생성된 메세지를 표시

다-2. 그룹 채팅방 페이지

그림 10. 그룹 채팅방 페이지

[1] 해당 메세지를 보지 않은 유저 수 표시

라. 빌드/배포

라-1. docker-compose 활용하기

그림 11. docker-compose 활용

라-2. EKS에 배포하기

그림 12. EKS 배포 내역

라-3. k8s 기능 활용하기

그림 13. k8s 기능 활용: 자동 복구

그림 14. k8s 기능 활용: 무정지 배포

그림 15. k8s 기능 활용: 자동 스케일 아웃

4. 프로젝트 소감

모노리스 아키텍처와 달리 마이크로 서비스 아키텍처에서의 유저 인증 과정 구현은 좀 더 복잡하고 명확하지 않은 부분이 있었는데 이번 구현을 통해서 이러한 부분을 깊게 이해할 수 있게 되어서 한 번 더 성장할 수 있게 되었다. 

5. 관련 링크


이 블로그의 인기 게시물

토이 프로젝트 일지 6 : React/SpringBoot 기술 스택으로 코딩 테스트 서비스 만들기

토이 프로젝트 일지 7 : RedKiwi와 유사한 이벤트 스토밍 기반 마이크로 서비스 만들기

토이 프로젝트 일지 2 : ChatGPT 서비스를 활용하는 크롬 플러그인 만들기