[최종프로젝트] 쓰레드풀 튜닝 / 캐시 전략을 활용한 채팅 메시지 성능 개선

2025. 3. 24. 23:52·개발/내일배움캠프 TIL

초기 설계

초기에는 메시지를 발송하면 즉시 DB에 저장되는 방식으로 설계했었습니다. 그리고 현재 채팅 서비스를 얼마나 많은 사람이 이용할 수 있을 까 궁금했고, 단일서버기준으로 1000명정도의 사용자가 동시접속하여 안정적으로 이용하는 것을 목표로 잡고 테스트를 진행하였습니다.

 

문제점

1000명의 유저가 동시에 사용할 수 있을까?

Jmeter를 이용해 웹소켓연결 → CONNECTED → SUBSCRIBE → SEND → MESSAGE → DISCONNECTED 과정으로 시나리오를 설계하고 SEND 이후 MESSAGE 까지의 응답시간이 얼마나 나오는지를 중점으로 보았습니다. 그리고 100명부터 100씩늘려가며 1000명의 유저가 동시에 접근하는 상황을 테스트해보았습니다. (요청은 10번씩 진행)

쓰레드 평균 응답 시간 에러율
100 35ms 0.00%
500 645ms 0.14%
1000 1996ms 5.31%

 

테스트 결과, 500부터 평균 응답 시간이 느려지고 에러율이 발생하였으며 목표수치인 1000에서는 응답 시간은 약 2초, 메시지가 5.31% 에러로 유실되는 문제가 발생하였습니다. 그리고 서버를 확인해보았습니다.

 

 

동시에 접근하는 과정에서 뒤로 밀린 요청은 10초가 지나 웹소켓에서 타임아웃이 발생하였고, Redis Pub/Sub을 이용하여 발행하던 메시지 또한 RedisTimeoutException이 발생하면서 메시지가 유실되고 있었습니다.

 

이때 그라파나의 대시보드를 확인해보니 Thread States 에서 테스트 시간동안 blocked이 많은 것을 확인할 수 있었습니다. 그래서 웹소켓과 Redis를 사용할때 스프링에서 제공하는 ThreadPoolTaskExecutor 를 활용하여 쓰레프풀을 조금씩 변경해가며 튜닝하였습니다.

 

웹소켓/Redis 쓰레드풀 튜닝 테스트 결과

쓰레드 평균 응답 시간 에러율
WebSocket 291ms 0.03%
WebSocket + Redis 299ms 0.00%

 

웹소켓 메시지 처리 채널에만 적용해도 응답속도가 훨씬 빨라졌으며 에러율 또한 크게 줄었는데 하지만

RedisTimeoutException이 미세하게 발생하고 있었습니다. RedisMessageListener 도 같이 쓰레드풀을 튜닝하였을때 속도는 비슷했지만 에러율은 0%로 메시지 유실이 되지 않았습니다.

 

쓰레드 blocked 또한 초기에 순간적으로 발생하는 모습은 보였지만 이전처럼 테스트 시간 내내 유지되는 모습은 크게 감소한 것을 확인할 수 있었습니다.

5분 TPS 측정

위에선 단순히 1000개 쓰레드가 10번씩 요청하도록 테스트를 진행하였는데, 1000명이 이용할 때 초당 몇 개의 메시지를 처리할 수 있을 지 확인하기 어려워 같은 환경에서 5분동안 얼마나 처리할 수 있을 지 측정해보았습니다.

 

발행된 메시지수 평균 응답 속도 처리량(Throughput)
182908 552ms 610TPS

테스트 결과, 응답 지연 시간이 낮아야 하는 채팅 서비스 기준으로는 느린 속도와 낮은 처리량이 확인되었습니다.

 

캐시 Write-Back 전략 도입

메시지를 발행할 때마다 저장하여 DB에 너무 많은 부하가 발생한다고 판단되었습니다. 이러한 문제를 해결하기 위해 메시지 발행시 Redis 캐시에 먼저 저장하고 일정 주기로 DB에 업데이트하는 방식으로 변경해보기로 하였습니다.

발행된 메시지수 평균 응답 속도 처리량(Throughput)
390004 275ms 1293TPS

 

결론

구분 평균 응답 속도 에러율 처리량
개선 전 1996ms 5.31% 168TPS
쓰레드풀 튜닝 552ms 0.00% 610TPS
캐시 Write-Back 전략 도입 275ms 0.00% 1293TPS

 

  1. 평균 응답 속도
    • 기존 약 2초(1996ms) → 쓰레드풀 튜닝 후 0.55초(552ms) → 캐시 Write-Back 전략 도입 후 0.27초(275ms)
    • 약 7배 빠른 응답 속도를 달성
  2. 에러율
    • 기존 5.31% → 개선 후 0.00%
    • 에러 발생 완전 해소
  3. 처리량(TPS)
    • 기존 168 TPS → 쓰레드풀 튜닝 후 610 TPS → 캐시 Write-Back 전략 도입 후 1293 TPS
    • 약 7.7배 성능 향상

결과적으로 쓰레드풀 튜닝과 캐시 Write-Back 전략을 통해 응답 속도 단축, 에러율 제거, 처리량 증가라는 세 가지 핵심 개선 효과를 얻을 수 있었습니다.

 

추가 개선점

Write-Back 캐시 전략은 Redis에 기록되고 DB에 업데이트되는 사이에 Redis에 문제가 생겨 데이터가 날아간다면 기존 채팅 메시지가 유실되는 큰 문제가 발생됩니다. 이럴 경우를 대비하여 Redis의 스냅샷이나 클러스터 모드를 활용해서 방지해보는 것도 좋을 것 같습니다.

'개발 > 내일배움캠프 TIL' 카테고리의 다른 글

[최종프로젝트] 채팅 서비스 개발3 - 채팅 기록 저장  (0) 2025.02.25
[TIL #42] [최종프로젝트] 채팅 서비스 개발2 - 채팅방 설계  (0) 2025.02.19
[TIL #40] 자바에서 데이터베이스 접근하기  (0) 2025.01.14
[TIL #39] 탈퇴한 회원 관리 테이블 분리 VS 필드 트러블 슈팅  (0) 2025.01.12
[TIL #38] Spring 심화 주차 과제 Lv 6 기능 개선하기  (0) 2025.01.06
'개발/내일배움캠프 TIL' 카테고리의 다른 글
  • [최종프로젝트] 채팅 서비스 개발3 - 채팅 기록 저장
  • [TIL #42] [최종프로젝트] 채팅 서비스 개발2 - 채팅방 설계
  • [TIL #40] 자바에서 데이터베이스 접근하기
  • [TIL #39] 탈퇴한 회원 관리 테이블 분리 VS 필드 트러블 슈팅
BigChoi93
BigChoi93
이곳은 저의 성장과정과 개인적인 생각을 담기 위한 공간입니다.
  • BigChoi93
    Donologue
    BigChoi93
  • 전체
    오늘
    어제
    • 분류 전체보기 (61)
      • 개발 (53)
        • Javascript (2)
        • 내일배움캠프 TIL (41)
        • 개발일기 (4)
        • Java (2)
        • Spring (1)
        • Sql (1)
      • 일상 (0)
      • 사진 (1)
        • 포토샵 (1)
  • hELLO· Designed By정상우.v4.10.1
BigChoi93
[최종프로젝트] 쓰레드풀 튜닝 / 캐시 전략을 활용한 채팅 메시지 성능 개선
상단으로

티스토리툴바