멋사 부트캠프

[Project - Howru] (5) kafka를 활용한 비동기처리 및 성능개선

sagecode 2025. 8. 25. 15:21

1. 가설 설정

  • 우리 채팅 시스템은 MongoDB + Redis + Kafka를 활용해 메시지를 저장/전달한다.
  • 기본 구조에서는 모든 저장 과정을 동기 처리하기 때문에,
    트래픽이 몰리면 메시지 저장 속도가 느려지고, 응답 시간이 길어진다.
  • 비동기 처리캐싱 최적화를 도입하면 성능이 개선될 것이라 가정했다.

2. 문제 설정

  • 동기 처리 기반 메시지 저장 구조에서 성능 문제 발생:
    • p95 응답시간(95% 요청 응답 속도): 약 5초
    • 실패율: 약 47% (timeout/drop)
    • TPS(초당 처리 메시지): 50~60 수준으로 제한
  • 실제 채팅 서비스라면, 이런 응답 속도와 실패율은 사용자 경험에 치명적임.

3. 시나리오 (부하 테스트)

  • 도구: k6 + Grafana
  • 시뮬레이션:
    • 로그인 후 JWT 토큰 발급
    • 채팅방 선택 → 메시지 전송 API 호출
    • VU(가상 사용자) 증가에 따라 초당 수백~수천 개 메시지 전송
  • 측정 지표:
    • TPS (Throughput, 초당 메시지 저장 수)
    • p95 응답시간
    • 실패율(http_req_failed)
    • 드롭된 요청 수(dropped_iterations)

4. 해결 방법

  1. MongoDB 성능 튜닝
    • 채팅방 ID, 송신자 ID, 메시지 시간에 인덱스 추가
    • WriteConcern 기본값 유지(w=1)
  2. 비동기 구조 도입
    • 기존: mongoRepository.save()까지 완료된 후 응답 반환
    • 변경: 요청 시 **ACK(접수 확인)**만 빠르게 반환 → 실제 저장은 Kafka 이벤트 기반 비동기 처리
  3. Redis 캐시 최적화
    • 최근 메시지 리스트를 Redis에 저장 (30개 유지)
    • 메시지 조회는 Redis 우선 조회 → Mongo는 배치성 저장

5. 성능 개선 결과

  • Before (동기 저장 구조)
    • p95 응답시간: ≈ 5,000 ms (5초)
    • 실패율: ≈ 47%
    • TPS: ≈ 50~60 req/s
    • 안정성 부족
  • After (비동기 + 캐싱 구조)
    • p95 응답시간: ≈ 8 ms
    • 실패율: 0%
    • TPS: ≈ 745 req/s (2000 VU 기준)
    • 응답 안정성 확보

최종 요약

  • 가설: 동기 처리로는 한계가 있고, 비동기 + 캐싱 구조가 필요하다.
  • 문제: 초기 구조에서 응답 지연 및 높은 실패율 발생.
  • 시나리오: k6 부하 테스트로 수백~수천 명 동시 사용자 환경을 재현.
  • 해결 방법: Mongo 튜닝 + Redis 캐싱 + Kafka 비동기 처리.
  • 성과:
    • 응답 속도 5초 → 8ms
    • 실패율 47% → 0%
    • TPS 50/s → 745/s 이상