메시지 생성 API 성능 측정 및 개선 가이드
1. 성능 측정 접근 방법
- 가장 중요한 API인 메시지 생성 API의 성능 측정과 성능 개선을 진행합니다.
- 초당 몇 TPS를 처리할 수 있는지, 어떤 부분에서 병목이 발생하는지 확인합니다.
1.1 메시지 생성 API의 주요 작업
성능 측정 전에 메시지 생성 API의 주요 작업을 파악해봅시다.
- 조회 작업 (Read Operations)
- MongoDB에서 특정 채팅방의 전체 멤버 조회
- Redis에서 특정 방의 시청자 조회
- 메사지 전송자의 유저 이름 조회
- 저장 작업 (Write Operations)
- MongoDB에 메시지 저장
- ReadReceipt(읽음 상태) 업데이트
- MongoDB 채팅방의 최신 메시지 업데이트
- 이벤트 발행 (Event Publishing)
- Redis pub/sub: 메시지 생성 이벤트 발행
- FCM: 푸시 알림 이벤트 발행
2. 메트릭 수집 전략
2.1 기본 메트릭 수집
- 현재 CloudWatch를 통해 다음 기본 메트릭들을 수집중입니다
http.server.requests
: API 응답 시간mongodb.driver.commands
: MongoDB 작업 시간jvm.memory.used
: 메모리 사용량process.cpu.usage
: CPU 사용량system.cpu.usage
: 시스템 CPU 사용량
3. 세부 메트릭 수집 (Custom Metrics)
- 더 세부적인 메트릭을 수집하여 API의 성능을 더 상세히 분석합니다
- Micrometer Timer를 사용하여 메시지 생성 API의 세부 작업 시간을 측정합니다.
- 메시지 생성 API의 세부 작업에 대해 세세한 메트릭을 수집하기 전에 먼저 Timer 개념을 이해해봅시다.
3.1 Micrometer Timer 개념
- Timer는 Spring Boot의 Micrometer 라이브러리에서 제공하는 시간 측정 도구입니다
- 특정 작업의 수행 시간을 측정하고, 해당 작업의 실행 횟수와 시간 분포를 기록합니다
- 주요 특징:
- 시간 단위로 나노초(nanoseconds) 사용
- 작업의 실행 횟수(count)와 전체 시간(total time) 기록
- percentile 값 (p50, p95, p99 등) 계산 가능
- 태그를 통한 메트릭 세분화 지원
Timer 메트릭 생성 예시
// 1. 기본적인 Timer 생성
val timer = Timer.builder("operation.timer")
.tag("type", "process") // 태그 추가
.publishPercentileHistogram()
.register(meterRegistry)
// 2. Timer를 사용한 시 간 측정
timer.record {
// 측정하고자 하는 작업 수행
someOperation()
}
// 3. 수동으로 시간 측정
val start = System.nanoTime()
performOperation()
timer.record(System.nanoTime() - start, TimeUnit.NANOSECONDS)
- operation.timer: 메트릭의 고유 이름
- tag(): 메트릭을 분류하고 필터링할 수 있는 레이블 추가
- publishPercentileHistogram(): 백분위수 기반 히스토그램 활성화
- register(): 생성된 타이머를 레지스트리에 등록
3.2 @Timed 어노테이션 사용
- Spring Boot Actuator의
@Timed
어노테이션을 사용하여 메서드 실행 시간을 측정합니다 - 위 예시의 Timer를 직접 생성하는 대신
@Timed
어노테이션을 사용하여 메서드 실행 시간을 측정할 수 있습니다- 이를 사용하면 코드 중복을 줄이고 간편하게 메서드 실행 시간을 측정할 수 있습니다.
@Timed 어노테이션 사용 예시
import io.micrometer.core.annotation.Timed
@Timed(value = "operation.timer", description = "Operation Timer")
fun someOperation() {
}
3.3 메시지 생성 API 세부 메트릭
- 전체 작업 메트릭
- 메트릭명:
message.overall
- 측정내용: 메시지 생성 전체 프로세스 소요 시간
- 태그: messageType (TEXT, FILE 등)
- 용도: 메시지 생성 API 전체 성능 모니터링
- 메트릭명:
- 조회 작업 메트릭 (
message.read.*
)message.read.operations
: 전체 조회 작업 시간message.read.room_members
: 채팅방 멤버 조회 시간message.read.viewers
: 시청자 목록 조회 시간message.read.sender_info
: 발신자 정보 조회 시간
- 저장 작업 메트릭 (
message.write.*
)message.write.operations
: 전체 저장 작업 시간message.write.store_message
: 메시지 저장 시간message.write.read_receipt
: 읽음 상태 업데이트 시간message.write.room_update
: 채팅방 최신 메시지 업데이트 시간
- 이벤트 발행 메트릭 (
message.event.*
)message.event.operations
: 전체 이벤트 발행 시간message.event.redis_publish
: Redis 이벤트 발행 시간message.event.fcm_publish
: FCM 푸시 알림 발행 시간
3.4 메트릭 수집 설정
management:
metrics:
distribution:
percentiles-histogram:
message.creation: true
message.read.*: truecl
message.write.*: true
message.event.*: true
slo:
message.creation: 100ms,200ms,500ms,1000ms
message.read.*: 50ms,100ms,200ms
message.write.*: 50ms,100ms,200ms
message.event.*: 100ms,200ms,500ms
4. 부하 테스트 도구 선정
- Apache JMeter
- 장점:
- GUI 기반 테스트 시나리오 작성 용이
- 다양한 프로토콜 지원
- 상세한 리포트 제공
- 단점:
- Java 기반으로 리소스 사용량이 높음
- 분산 테스트 구성이 복잡함
- 장점:
- K6
- 장점:
- JavaScript/TypeScript로 테스트 작성
- 가볍고 효율적인 리소스 사용
- 클라우드 연동 용이
- 단점:
- 상대적으로 새로운 도구
- 플러그인 생태계가 작음
- 장점:
권장: K6 선택
- 가벼운 리소스 사용으로 더 정확한 성능 측정 가능
- 코드 기반 테스트로 버전 관리 용이
- CloudWatch 연동 지원
5. 테스트 시나리오 설계
기본 시나리오:
- 단일 사용자 응답 시간 측정
- 텍스트만 있는 메시지
- 파일이 포함된 메시지
- 멘션이 포함된 메시지
- 부하 테스트
- 동시 사용자 50명
- 초당 100개 메시지 생성
- 1시간 지속 테스트
- 스파이크 테스트
- 갑작스러운 부하 증가 상황 테스트
- 동시 사용자 500명으로 순간 증가
6. 모니터링 대시보드 구성
CloudWatch 대시보드에 필요한 지표들:
- API 성능 지표
- 요청별 응답 시간 분포
- 초당 처리 요청 수
- 오류율
- 리소스 사용량
- CPU 사용률
- 메모리 사용량
- MongoDB 커넥션 수
- 구간별 성능
- MongoDB 작업 시간
- Redis 발행 시간
- FCM 처리 시간
7. 최적화 방향
수집된 메트릭을 바탕으로 다음 영역의 최적화를 검토:
- 데이터베이스 최적화
- MongoDB 인덱스 최적화
- 쿼리 패턴 개선
- 비동기 처리
- FCM 알림 발송 비동기화
- 이벤트 발행 최적화
- 캐싱 전략
- 사용자 정보 캐싱
- FCM 토큰 캐싱