이번 포스팅은 웹 서버 부하 테스트를 진행했던 경험을 적어보려 한다.
이번 부하 테스트의 목표는 다음 두가지를 확인하는 것이였다.
- 현재 우리 웹 서버 스펙의 한계
- 서버가 Scale-Out & Scale-Up 되었을 때 향상된 성능과 한계
과연 동일한 스펙의 서버 2대(양) vs 전자의 2배의 성능을 가진 서버 1대(질)의 성능은 무엇이 더 좋을까?
처음 해봤던 테스트라 부족한 점과 아쉬운 점이 많지만, 그래도 나에겐 좋은 경험이였어서 글로 남긴다.
테스트 배경
22년 7월, 우리 서비스가 앱스토어에 피처링(추천 앱) 여부를 검토 중이라는 이메일을 받았다..!

앱스토어 '투데이' 탭에 오늘의 게임, 오늘의 앱 등이 추천되는데, 바로 이곳에 우리의 앱이 노출이 된다니.. 정말 신기했다.
빠르면 몇 주, 길게는 몇 달안에 선정될 것이라고 전달받았다.
일주일정도 기초적인 js, node 공부를 마친 나에게 첫 task가 주어졌다.
아무래도 앱 스토어 메인에 노출이 된다면, 평상시보다 사용자가 증가할 것이고, 설령 크게 사용자가 증가하지 않는다고 하더라도, 나중에 서비스가 커졌을 때를 대비할 수 있는 가이드 라인을 구축할 수 있기 때문에 겸사겸사 서버 부하테스트를 내가 진행하게 되었다. 그리고 백엔드 개발자라면, 서버 성능 테스트는 매력적인 경험이라고 생각했다.
필요한 테스트 정의 및 목표
테스트를 시작하기에 앞서, 우리 서버에 필요한 테스트가 무엇일까를 먼저 고민했고, 검토했다.
서버 성능 테스트에는 다양한 종류의 부하 테스트들이 있더라.
구글링 중 가장 도움이 되었던 레퍼런스 링크도 공유하겠다.
성능테스트란 서비스 및 서비스 시스템의 성능을 확인하기 위해 실제 사용환경과 비슷한 환경에서 테스트를 말한다.
이를 통해서 응답시간(Response Time)과 처리량(Throughput), 병목구간 등을 확인할 수 있고,
성능 테스트로 얻은 정보로 서비스나 서비스 시스템의 문제점을 확인하고 이를 개선하여 보완할 수 있다.
그리고 부하로 인해 서버 장애가 일어났을 때 정상 복구가 되는지 확인하는 것까지 체크해야 한다.
성능테스트라는 큰 개념 안에 부하 테스트들인 Stress, Spike, Stability, Soak Test 등이 있다.
나에게 필요한 테스트들의 용어를 내가 이해한대로 간단하게 정의하고 우리의 테스트 목표를 세웠다.
- Spike Test (스파이크 테스트): 사용자가 갑자기 증가하는 시나리오에 대한 테스트
- 서버 스펙에 따라 동시 요청을 몇 개까지 에러없이 5초이내로 처리하는가?
- Stress Test (스트레스 테스트): 일정 간격으로 부하를 증가시켜 서버의 한계를 테스트
- 서버 스펙에 따라 초당 몇개의 요청을 처리하는가?
- 스파이크 테스트에서 얻은 한계점에서부터 계속 부하를 증가시켰을 때, 우리가 정한 일정 개수까지 버티는가?
- Soak Test (내구성 테스트): 일정 기간동안 지속적으로 걸리는 부하에 대한 테스트
- 서버 스펙에 따라 스파이크 테스트에서 얻은 값을 일정 시간(10분)동안 반복해서 요청했을 때 버틸 수 있는가?
테스트 시나리오
오늘의 앱으로 노출이 되었을 때, 우리 앱을 처음 사용하는 사용자의 입장에서 트래픽이 몰릴 수 있는 예상 시나리오를 구상했다. 그리고 이를 DB 작업 기준으로 크게 3가지로 나눴다.
1. DB 쓰기 트래픽: 회원가입 API
2. DB 쓰기 + 파일 업로드 트래픽: 작품 업로드 API (이미지를 포함한 게시글 작성)
3. DB 조회 트래픽: 갤러리 조회 API (앱의 메인화면으로 이미지 조회)
이렇게 3가지 API를 테스트 하는데, 현재 우리 서버 스펙에서부터 시작해서 한계점을 찾고,
서버의 개수를 증가시키면서 (Scale-Out) 한계점을 찾고, 서버의 스펙을 상승시키면서 (Scale-Up) 한계점을 찾아
동시요청(부하) 개수에 따른 서버 스펙 및 오토스케일링 가이드라인을 찾는 것이 목표였다.
테스트 진행
테스트 툴은 Jmeter를 활용했고, AWS Cloud Watch를 활용해 서버로그, CPU/메모리 사용률을 체크했다.
제이미터 설치 ~ 기본 세팅에 도움이 되었던 블로그이다.
자세한 세팅법이나 사용법은 많은 레퍼런스가 있으므로, 내가 테스트를 진행하면서 얻은 팁들을 공유하겠다.
Jmeter
매번 세팅하지 않도록 테스트할 API들을 저장하자. File - Open Recent File을 통해 저장한 테스트를 쉽게 불러올 수 있다.
만일 포스트맨 같은 API 테스트 툴에 테스트할 API가 저장되어 있다면, 왼쪽 상단의 Tools - ImportFromcURL에 복사한 curl을 붙혀넣기해서 Jmeter를 자동으로 세팅할 수 있다.
나는 Summary Report를 통해 테스트의 전체 결과(평균/최소/최대 응답시간, 에러율, 처리량)를 엑셀에 기록했다.

View Results in Table을 통해 각각의 요청에 대한 상세 정보가 필요한 경우 확인했다. (주로 언제 에러가 났나 체크)

요청이 실패 했을 경우, 어떤 에러메세지를 서버에서 뱉었는지 확인하기 위해서 View Results Tree에서 Error 로그만 남기도록 설정하였다.

options - log viewer를 체크하면 툴 아래에 로그창이 표시된다. 테스트 완료 시간이나 병렬로 요청이 처리가 되는지 등을 확인하는데 사용할 수 있다.
현재 우리 서버의 스펙은 0.25vCPU / 0.5GiB 메모리(ECS)이며, 서버 메모리 사용률에 따라 로드밸런서를 통해 오토스케일링이 되도록 적용하고 있었다.
테스트의 순서는 다음과 같다.
1 .0.25vCPU / 0.5GB (현재 서버 스펙)에서 Spike, Stress, Soak 테스트 & Scale-Out 하고 다시 테스트
2. 0.5vCPU, 1GB 으로 Scale-Up을 하여 테스트 & Scale-Out 하고 다시 테스트
3. 1vCPU, 2GB 으로 Scale-Up을 하여 테스트 & Scale-Out 하고 다시 테스트
ECS에서 제공하는 모든 스펙으로 테스트 할 수는 없기에, 서버 비용과 작업공수를 고려해서 적당한 ScaleUp, ScaleOut 기준을 정했다.
테스트 결과
스파이크 테스트

테스트 결과에 따르면, 우리 서버는 보수적으로 계산해도 시간 당 1만개의 아트워크가 등록 가능하며,
(5초 이내로 30개 등록 가능 -> 1분에 360개 -> 시간당 최대 2.16만 개인데 보수적으로 보고 1만개)
그래프는 서버 스펙마다, 5초 이내로 처리할 수 있는 동시요청 수를 나타낸다.
수치가 클수록 더 많은 동시 요청을 처리할 수 있다.
스트레스 테스트
스트레스 테스트같은 경우는 아래의 그래프처럼 요청(부하)을 발생시키며 진행하였다.


스트레스 테스트는 스파이크 테스트에서 얻은 서버 스펙의 한계에서 1000개가 될 때까지 지속적으로 부하를 발생시켰다.
(이미지 업로드는 100개까지)
각 서버 스펙 별 평균응답시간, 초당 처리량, 메모리 사용률을 표로 기록하고, 1000개의 요청을 에러없이 처리하는것을 확인했다.
서버 성능이 좋아질수록 평균응답시간이 줄어들고, 초당 처리량이 많아지는 것은 당연하겠지만, 우리가 기준으로 정한 1000개의 요청에 대해 어느정도의 성능으로 에러없이 처리하는가를 테스트하는것이 주 목적이였다.
그리고 스파이크 테스트의 결과와 동일하게 더 낮은 스펙의 서버를 2대로 늘렸을 때(0.25 cpu/0.5GB 2대) 결과가
스케일 업(0.5cpu/1.0GB 1대) 했을때의 결과보다 좋았다.
1000개 이상의 부하를 지속적으로 가했을 때 서버의 반응은 Soak테스트 결과에서 다루겠다.
Soak 테스트 결과

Soak 테스트는 시간 상 모든 서버의 스펙을 테스트 해보지는 못했고, 현재 우리 서버 스펙에서만 테스트를 진행하였다.
스트레스 테스트로 일정 개수까지 버티는가를 테스트 해보았다면, 소크 테스트는 일정 시간을 버티는가를 테스트하였다.
10분 동안 지속적으로 부하를 발생시켰을 때 에러없이 처리하는 것을 확인할 수 있었다.
테스트 결과 정리 및 요약
가장 무겁다고 생각했던 이미지 업로드 작업이 아무래도 회원가입, 이미지 조회 api보다 같은 스펙대비 동시요청개수 한계점이 가장 작았다.
그리고 같은 스펙에 서버 개수를 늘린 스케일 아웃한 결과가 서버 스펙을 한단계 스케일 업한 결과보다 조금 더 결과가 좋았다.
현재 우리 실서버는 0.25cpu / 0.5GB 에 오토스케일링이 2대~8대로 늘어나도록 설정되어있는데, 이 테스트를 통해 서버 스펙을 스케일업 하기보단 지금처럼 스케일 아웃 하는 방식으로 가도 괜찮을 것 같다고 팀원들에게 공유했다.
얻은 성과 및 후기
- 스케일업 VS 스케일 아웃 성능 비교
- 백엔드 오토스케일링 가이드 라인 구축
- 아트워크 추가(이미지 업로드) 쿼리문 수정 (limit 설정)
- 오토스케일링으로 ECS 작업 task를 4,8대로 늘렸을 때 커넥션 에러
먼저, 나중에 서비스가 커졌을 때 스케일 아웃만으로 다 감당할 수 있을까를 백엔드 팀내에서 고민하고 있었는데, 동일한 스펙 서버 여러대가 한단계 높은 서버 스펙 한대보다 결과가 더 좋다는것을 확인했다.
3가지 API 중 가장 한계점이 작았던 이미지 업로드 API 기준으로 초당 처리량 약 30개 정도까지는 5초이내에 에러없이 완료했으므로, 이 기준까지는 서버 비용을 올릴 필요가 없다는점을 확인했다.
따라서 지금 서비스 규모에서 오토스케일링 정책은 기존과 동일하게 가도 문제 없다고 팀에서 판단했다.
다음은 실제 코드를 수정한 점이다.
아트워크 추가 API 테스트 진행 중 서버 스펙을 올렸는데 올리기 전과 결과가 다를게 없는 상황이 발생해,
AWS Cloud Watch를 통해 서버 로그를 확인해보았고, SELECT 쿼리에서 2초가 걸리는 것을 발견하였다.
보통 쿼리문은 ms 단위로 이루어질텐데, 너무 오래걸렸다.
해당 부분 원인을 찾아보니 이미지 업로드 시 화면에 보여지는 순서를 저장하는 쿼리가 있었는데, 사용자가 올린 모든 이미지개수를 조회 후 순서를 계산하고 있었다.
테스트 파일이 몇천개가 쌓이다보니 조회하는 시간이 오래걸렸던 것이다.
아직은 사용자가 많아야 몇백개의 작품을 갖고있다보니 실서버에서는 발생하지 않았던 문제였다.
팀 내 공유 후 빠르게 쿼리를 수정하였다.
마지막으로는 서버 개수를 4,8대로 늘렸을 때 too many connections 에러가 발생한다는 것이였다.
DB 커넥션 개수를 조절한다던지 커넥션 풀 관련해서 조치가 필요하다는점을 인지하고 공유했다.
개인적으로 얻은 성과로는, 부하 테스트를 경험해본것 외에도 우리 서비스에 구축되어있는 AWS 인프라를 알아볼 수 있었고, 다뤄볼 수 있었다.
ECS, 로드밸런서를 통한 오토스케일링 정책, cloudwatch를 활용한 다양한 지표 및 로그 등을 직접 만져보았고,
대략 어떤 역할을 하고 있는지 알 수 있었다.
이번 테스트를 마치고 나서 아쉬웠던 점과 다음에 테스트를 진행한다면 고려해볼만한 점은
1. 테스트 결과를 표 뿐만이 아니라 그래프 같은걸로 시각화 할 수 있는 툴을 사용했다면 어땠을까
2. 귀찮고 반복적인 작업의 연속이였는데, 스크립트나 무언가 테스트를 자동화 할 수 있는 방법
이렇게 두가지가 가장 크게 느껴졌다.
처음 해본 테스트라 아쉬운점과 부족한점이 많지만, 이를 토대로 다음에 부하테스트를 해야할 기회가 생긴다면, 더 나은 테스트를 진행할 수 있을 것 같다.
'AWS' 카테고리의 다른 글
AWS Lambda를 이용한 이미지 리사이징 (0) | 2023.03.30 |
---|---|
Pre-Signed URL을 이용한 S3 이미지 업로드 (0) | 2023.03.13 |