백엔드 개발을 하고 서버를 구축하다보면 내가 구축한 서버가 어느정도의 트래픽을 감당할 수 있는지가 궁금할 수 밖에(?) 없습니다. 그래서 실제로 측정을 해봐야 하는데 이러한 측정은 성능테스트를 통해 이루어집니다.
일반적으로 특정 작업 부하 상태에서 응답성과 안정성 측면에서 시스템이 어떻게 작동하는지를 확인하기 위해 수행하는 테스트 관행으로 응답시간, 처리량, 자원 사용량(CPU, 메모리, etc...)을 주로 측정합니다.
- 부하 테스트
특정한 예상 부하에서 시스템이 어떻게 동작하는지 확인하며 이 테스트를 통해 주요 기능의 응답시간과 처리량 등의 성능 지표를 확인할 수 있고, 병목을 파악하는데 도움이 됩니다.
- 스트레스 테스트
시스템의 최대 성능을 확인하기 위한 테스트이며 예상을 뛰어넘는 부하가 발생했을 때, 시스템이 어디까지 성능을 낼 수 있는지를 확인하는 테스트 입니다.
- 지속 부하 테스트
시스템이 지속적인 부하를 견딜 수 있는지를 검증하며 장시간 동안 일정 수준의 부하를 주어 성능 저하가 발생하는지 확인하며 메모리 누수도 탐지할 수 있습니다.
- 스파이크 테스트
급격하게 트래픽이 변화할 때 시스템의 반응성과 안정성을 검증하는 테스트이며 순간적으로 트래픽이 급증했을 때 성능 저하나 실패가 발생하는지를 확인합니다.
성능테스트를 진행하는 일반적인 방식은 낮은 부하부터 시작해서 점진적으로 부하를 높이면서 테스트합니다. 예를들어 동시 사용자 수를 100명부터 시작해서 200명, 300명으로 단계적으로 부하를 높여가며 성능을 측정하면 됩니다.
이렇게 부하를 증가시키다보면 초기에는 처리량도 함께 증가하다가 일정 부하 구간에 도달하면 처리량의 증가 폭이 줄어들기 시작하고, 어느 시점부터는 처리량과 응답 시간이 급격히 저하되는데, 이때 어느 순간에 더 이상 증가하지 않고 그래프가 꺽이게 되는 곳. 즉,성능이 저하되기 전의 최대 처리량을 포화점이라고 하고, 포화점을 지나 성능이 꺾이기 시작하는 구간을 버클존이라고 합니다.

포화점이 목표로 한 성능보다 높다면 만족하면서 성능 테스트를 마치면 됩니다. 하지만.. 포화점이 목표치보다 낮거나 같다면 병목 지점을 찾아 제거해야 합니다. 일반적으로 웹 서버의 병목 지점은 호출 비중이 높으면서도 응답 시간이 긴 기능과 관련되어 있는데 DB연동, 외부 연동 시간, 트래픽 대비 부족한 커넥션 풀 크기를 확인하며 어떤 지점에서 병목이 발생하는지 확인하고 해결하도록 합시다. 그렇게 한다면 포화점을 높일 수 있을 것 입니다.
주요 측정 지표로는 응답시간 (평균, 최대, 최소, 중앙, 백분위), TPS(처리량), 에러율, CPU 사용율을 중점적으로 확인해보면 좋습니다.
성능테스트를 설계할 때는 다음 사항들을 고려해보세요.
시스템은 보통 일정한 트래픽 패턴을 가지지만 일부 서비스는 시간에 따라 트래픽 편차가 클 수 있습니다. 따라서 서비스에 맞게 테스트를 진행해주시면 될 것 같습니다.
nGrinder -> naver에서 개발한 성능 테스트 도구로, grinder를 사용한다. nGrinder는 1개의 컨트롤러와 다수의 에이전트로 구성되어있고, 웹 UI를 제공하고있어 사용하기 쉽습니다.
nGrinder는 Groovy나 Jython을 이용하여 스크립트를 작성합니다.
k6 -> k6는 Grafana Labs에서 개발한 부하 테스트 도구로 Go언어로 개발됐지만 javaScript를 사용하여 스크립트를 작성합니다.
k6는 CLI로 실행하기에 CI/CD환경에 통합이 용이하다는 장점이 있습니다.
마지막으로 성능 테스트를 진행할 때 흔히 하는 실수 중 하나가 테스트 대상 시스템과 부하기를 한 서버에서 사용하는 것입니다. 부하 생성은 그 자체로 많은 자원을 사용하기 때문에 부하기와 테스트 서버는 다른 환경에서 동작해야 정확한 테스트를 진행할 수 있으니 꼭! 분리해서 테스트를 진행합시다!
또한..! nginx에 처리율 제한을 설정했다면 이것도 테스트에 맞게 수정하도록 합시다.