요금제

아키텍처 개요

관련 소스 파일

이 페이지의 내용은 다음 소스 파일을 기반으로 생성되었습니다:

gochat 프로젝트는 분산형 인스턴트 메시징 시스템으로, 마이크로서비스 아키텍처 패턴을 기반으로 설계되었습니다. 이 시스템은 API 게이트웨이, 비즈니스 로직 처리, 메시지 큐잉, WebSocket 연결 관리 등 명확히 분리된 계층으로 구성됩니다. 핵심 설계 목표는 높은 동시성 처리, 수평적 확장성, 그리고 안정적인 메시지 전달 보장입니다.

전체 아키텍처 구조

gochat 시스템은 네 개의 핵심 계층으로 구성된 마이크로서비스 아키텍처를 채택하고 있습니다. 각 계층은 독립적으로 배포 및 확장 가능하며, RPC(원격 프로시저 호출)를 통해 상호 통신합니다. 전체 아키텍처 다이어그램과 서비스 디스커버리 구조는 readme.md:64-68에서 확인할 수 있으며, 이 구조는 서비스 간의 느슨한 결합과 동적 서비스 발견을 가능하게 합니다.

正在加载图表渲染器...

아키텍처 구성 요소 설명

위 다이어그램은 gochat 시스템의 핵심 계층과 데이터 흐름을 보여줍니다. 각 화살표는 동기적 RPC 호출 또는 비동기적 메시지 큐 통신을 나타냅니다.

계층 간 통신 특성:

  • API → Logic: 동기 RPC 호출로, 사용자 요청에 대한 즉각적인 응답이 필요한 작업(로그인, 메시지 발송 요청 등)을 처리합니다. readme.md:64-72
  • Logic → Queue: 비동기 메시지 푸시로, 메시지 발송 작업을 큐에 적재하여 발송자에게 즉시 응답을 반환합니다.
  • Task → Connect: 동기 RPC 호출로, 큐에서 소비한 메시지를 실제 WebSocket 연결로 전달합니다.

서비스 디스커버리: 각 Connect 계층 인스턴스는 고유한 serverId를 할당받으며, Logic 계층은 사용자의 현재 연결 위치를 serverId로 추적합니다. 이를 통해 Task 계층이 메시지를 정확한 Connect 인스턴스로 라우팅할 수 있습니다.

핵심 모듈 상세 분석

API 계층 (API Layer)

职责边界 (책임 경계):

  • HTTP/REST 인터페이스 제공
  • 사용자 인증 및 세션 토큰 발급
  • 요청 유효성 검증 및 기본 보안 처리
  • Logic 계층으로의 RPC 호출 라우팅

진입점 및 주요 API:

  • POST /login: 사용자 로그인 처리, Logic 계층에 사용자 접속 정보 기록 요청
  • POST /send: 메시지 발송 요청 접수, Logic 계층으로 메시지 전달

처리 흐름:

  1. 사용자 인증 요청 수신
  2. Logic 계층 RPC 호출을 통한 비즈니스 로직 실행
  3. 응답 반환 (로그인 성공 시 세션 정보 포함)

책임하지 않는 영역:

  • WebSocket 연결 관리 (Connect 계층 담당)
  • 메시지 큐잉 (Logic 계층 담당)
  • 실제 메시지 전달 (Task 계층 담당)

Logic 계층 (Logic Layer)

职责边界 (책임 경계):

  • 사용자 접속 상태 관리 (어느 Connect 서버에 연결되어 있는지 추적)
  • 메시지 발송 요청 처리 및 큐 적재
  • 방(Room) 멤버십 관리
  • 서비스 간 조율 및 라우팅 정보 제공

주요 데이터 구조:

  • 사용자 접속 맵: {userId: {serverId, roomId, status}}
  • 방 정보: {roomId: [userId1, userId2, ...]}

핵심 기능:

  1. 접속 정보 기록: API 계층으로부터 로그인 알림을 받으면 사용자의 serverId를 저장합니다. readme.md:74-79
  2. 메시지 큐잉: 발송 요청된 메시지를 메시지 큐에 푸시합니다. readme.md:81-82
  3. 라우팅 정보 조회: Task 계층이 메시지 전달 시 필요한 사용자 위치 정보를 제공합니다.

에러 처리:

  • 큐 적재 실패 시 재시도 로직 적용
  • 사용자 오프라인 시 오프라인 메시지 저장 (구현 확인 필요)

Task 계층 (Task Layer)

职责边界 (책임 경계):

  • 메시지 큐 소비 (Logic 계층이 적재한 메시지)
  • 메시지 수신자 위치 파악 (userId, roomId, serverId 기반)
  • Connect 계층으로의 RPC 호출 수행

핵심 로직: Task 계층은 메시지 큐를 구독하며, 메시지를 소비한 후 다음과 같은 결정을 내립니다:

  1. 방송 메시지: roomId 기준으로 해당 방의 모든 사용자에게 전달
  2. 개인 메시지: userId 기준으로 특정 사용자의 serverId를 조회하여 해당 Connect 인스턴스로 RPC 호출 readme.md:91-92

메시지 처리 흐름:

메시지 수신 → 수신자 타입 판별 (방/개인) → 
대상 serverId 조회 → Connect 계층 RPC 호출

확장성 고려사항:

  • Task 계층은 상태를 가지지 않으므로 수평적 확장이 용이
  • 메시지 큐 파티셔닝을 통한 처리량 증대 가능

Connect 계층 (Connect Layer)

职责边界 (책임 경계):

  • WebSocket 연결 수립 및 유지
  • 사용자 세션(Channel) 관리
  • 방(Room) 단위 브로드캐스트
  • 실제 메시지 푸시 수행

핵심 데이터 구조 - 버킷 구조: Connect 계층은 락 경쟁을 최소화하기 위해 버킷(Bucket) 기반 구조를 사용합니다. readme.md:94-100

Connect 계층:
    Bucket[]: (락 경쟁 최소화를 위한 분할)
        Room: (방 단위 그룹화)
            Channel: (개별 사용자 세션)

버킷 구조의 이점:

  1. 세밀한 락킹: 전역 락 대신 버킷 단위 락 사용으로 동시성 향상
  2. 메모리 효율성: 방 단위 그룹화로 빠른 브로드캐스트 가능
  3. 확장성: 버킷 수를 조정하여 성능 튜닝 가능

주요 기능:

  • 인증 핸드셰이크: WebSocket 연결 시 사용자 인증 수행
  • 방 입장/퇴장: 사용자를 적절한 방에 할당
  • 메시지 푸시: Task 계층으로부터 RPC 호출을 받으면 해당 방/사용자에게 메시지 전달 readme.md:88-89

메시지 전달 흐름

gochat의 메시지 전달은 비동기 큐잉 패턴을 사용하여 높은 처리량과 안정성을 확보합니다. 사용자 A가 사용자 B에게 메시지를 보내는 전체 과정은 readme.md:71-89에 상세히 설명되어 있습니다.

正在加载图表渲染器...

메시지 전달 단계별 상세 분석

1단계 및 2단계 - 사용자 로그인 및 연결 수립: 사용자는 먼저 API 계층을 통해 로그인합니다. 로그인 성공 시 Logic 계층은 사용자가 연결된 Connect 서버의 serverId를 기록하고, 기본적으로 1번 방에 입장시킵니다. readme.md:74-79 그 후 사용자는 Connect 계층과 WebSocket 연결을 수립합니다.

3단계 - 메시지 발송 요청: 사용자 A가 메시지 발송 API를 호출하면, API 계층은 이를 Logic 계층으로 전달합니다. Logic 계층은 메시지를 즉시 큐에 푸시하고 발송자에게 성공 응답을 반환합니다. 이 비동기 패턴은 발송자의 대기 시간을 최소화합니다. readme.md:81-82

4단계 - 메시지 전달 처리: Task 계층이 큐에서 메시지를 소비한 후, 메시지 내용에 포함된 userId, roomId, serverId 정보를 기반으로 수신자의 위치를 파악합니다. readme.md:84-86 이후 해당 Connect 인스턴스로 RPC 호출을 수행하고, Connect 계층은 메시지를 적절한 방 또는 개별 사용자에게 전달합니다. readme.md:88-89

방송 vs 개인 메시지 구분:

  • 방 메시지: Task 계층이 방 ID를 기반으로 Connect 계층을 호출하면, Connect 계층은 해당 방의 모든 사용자에게 브로드캐스트
  • 개인 메시지: Task 계층이 userIdserverId를 조회한 후, 해당 Connect 인스턴스로 직접 RPC 호출하여 특정 사용자에게만 전달 readme.md:91-92

모듈 간 의존 관계

正在加载图表渲染器...

의존 관계 분석

강한 의존성 (실선):

  • API → Logic: 모든 비즈니스 요청이 Logic 계층을 거침
  • Task → Logic: 사용자 위치 조회를 위한 필수 호출
  • Task → Connect: 메시지 전달의 최종 단계
  • Logic → Queue: 메시지 발송의 핵심 경로

약한 의존성 (점선):

  • 모든 계층 → Service Discovery: 서비스 인스턴스 발견을 위한 참조용 의존성

확장성 영향:

  • Logic 계층과 Connect 계층은 상태를 가지므로 신중한 확장 전략 필요
  • API 계층과 Task 계층은 무상태로 쉽게 수평 확장 가능

핵심 설계 결정사항

1. 비동기 메시지 큐 도입

결정: 메시지 발송 요청과 실제 전달 사이에 메시지 큐를 배치

이유:

  • 발송자에게 즉각적인 응답 제공 (사용자 경험 향상)
  • 트래픽 스파이크 완충 (큐가 버퍼 역할)
  • 발송/전달 계층의 독립적 확장 가능

트레이드오프:

  • 메시지 전달 지연 증가 (큐 대기 시간)
  • 시스템 복잡도 증가 (큐 운영 필요)

증거: readme.md:81-82에서 Logic 계층이 메시지를 큐에 푸시하는 것을 확인

2. Connect 계층의 버킷 구조

결정: Connect 계층 내부를 Bucket → Room → Channel 계층 구조로 조직화

이유:

  • 락 경쟁 최소화: 전역 락 대신 버킷 단위 락 사용
  • 빠른 브로드캐스트: 방 단위 그룹화로 O(1) 방 조회
  • 메모리 지역성 향상: 관련 데이터의 물리적 근접 배치

트레이드오프:

  • 구현 복잡도 증가
  • 버킷 수 튜닝 필요

증거: readme.md:94-100에서 버킷 구조 설명 확인

3. RPC 기반 서비스 간 통신

결정: 서비스 간 통신에 REST 대신 RPC 사용

이유:

  • 타입 안전성: IDL(Interface Definition Language) 기반 계약
  • 성능: 바이너리 프로토콜로 오버헤드 감소 (gRPC 등 사용 시)
  • 코드 생성: 클라이언트/서버 스텁 자동 생성

트레이드오프:

  • 디버깅 어려움 (바이너리 프로토콜)
  • HTTP 친화적이지 않음 (브라우저 직접 호출 불가)

4. serverId 기반 라우팅

결정: 각 Connect 인스턴스에 고유 serverId 할당 및 사용자-서버 매핑 유지

이유:

  • 정확한 메시지 라우팅: 사용자가 연결된 서버로 직접 전달
  • 상태 관리 단순화: 사용자 위치를 단일 키로 표현

증거: readme.md:76에서 serverId 기록 언급

5. 기본 방 입장 전략

결정: 로그인 시 기본적으로 1번 방에 자동 입장

이유:

  • 사용자 경험 단순화: 별도 방 입장 절차 없이 즉시 메시지 수신 가능
  • 테스트 및 데모 용이성

트레이드오프:

  • 1번 방에 과도한 트래픽 집중 가능성
  • 유연성 저하 (사용자가 방 선택 권한 제한)

증거: readme.md:76에서 "기본적으로 1번 방 입장" 언급

기술 스택 선정

기술용도선정 이유대안
Go주요 개발 언어높은 동시성 처리(goroutine), 낮은 메모리 footprint, 빠른 컴파일Rust, Java
WebSocket실시간 양방향 통신HTTP 폴링 대비 낮은 지연, 서버 푸시 가능Server-Sent Events, Long Polling
RPC (gRPC 등)서비스 간 통신타입 안전성, 바이너리 직렬화, 스트리밍 지원REST API, GraphQL
Message Queue (Kafka/RabbitMQ)비동기 메시징높은 처리량, 내구성, 재시도 메커니즘Redis Pub/Sub, NATS
Service Discovery (etcd/Consul)서비스 등록 및 발견동적 인스턴스 관리, 헬스체크 통합Kubernetes Service, 정적 설정
Bucket 구조세션 관리 최적화락 경쟁 감소, 빠른 방 조회단일 맵, 분산 캐시
Room/Channel 추상화사용자 그룹화브로드캐스트 효율성, 논리적 그룹핑사용자별 직접 관리

주요 설정 및 시작 프로세스

필수 구성 요소

메시지 큐 설정:

  • Logic 계층이 메시지를 푸시할 대상 큐/토픽 구성
  • Task 계층이 구독할 컨슈머 그룹 설정
  • 재시도 정책 및 데드레터 큐 구성 (구현 확인 필요)

서비스 디스커버리 설정:

  • Connect 인스턴스의 serverId 자동 생성 또는 할당 메커니즘
  • Logic 계층의 접속 정보 저장소 (Redis 등 사용 가능, 구현 확인 필요)
  • 헬스체크 및 인스턴스 등록/해제 로직

RPC 통신 설정:

  • 서비스 간 타임아웃 및 재시도 정책
  • 로드 밸런싱 전략 (라운드 로빈, 최소 연결 등)
  • 서킷 브레이커 설정 (장애 전파 방지)

시작 순서 권장사항

  1. 인프라 계층: 메시지 큐, 서비스 디스커버리 시작
  2. 상태 관리 계층: Logic, Connect 계층 시작 (순서 무관)
  3. 무상태 계층: API, Task 계층 시작 (순서 무관)

Connect 계층 버킷 튜닝

버킷 수는 예상 동시 접속자 수와 서버 하드웨어 스펙에 따라 조정해야 합니다. 일반적인 권장사항:

  • 버킷 수: CPU 코어 수 × 2~4배
  • 방 분산: 해시 기반 방-버킷 매핑으로 고른 분산 유지
  • 모니터링: 버킷별 락 대기 시간 모니터링으로 병목 식별

증거: readme.md:94-100에서 버킷 구조와 락 최적화 목적 명시

알려진 제약사항

  1. 메시지 순서 보장: 현재 아키텍처에서는 단일 사용자의 메시지 순서 보장이 명시되지 않음 (큐 파티셔닝 전략에 따라 달라질 수 있음)

  2. 오프라인 메시지: 소스에서 오프라인 메시지 저장 및 전달 메커니즘이 명시되지 않음 (추가 확인 필요)

  3. 메시지 영속성: 메시지 큐의 보존 기간 이후 메시지는 복구 불가능할 수 있음

  4. 수평 확장 시 고려사항: Connect 계층 확장 시 기존 연결의 마이그레이션 전략 필요 (Graceful Shutdown/Restart)

  5. 단일 지역 가정: 현재 설명은 단일 데이터센터/지역 내 배포를 가정하는 것으로 보임 (다중 지역 복제 전략은 별도 설계 필요)