안녕하세요!
이전에 언급했던 것처럼 Now, Here 글로 다시 찾아왔습니다.
현재 출시가 얼마 남지 않았고, 대부분의 기능 구현은 완료한 상태입니다.
그래서 성능 테스트를 통해 웹 서비스의 성능을 측정하고, 병목지점을 찾아 성능 개선을 이루는 경험을 공유합니다.
😊 성능 테스트 가이드 시리즈😊 / 클릭 시 이동
1. 성능 테스트_성능 목표 잡기
2. 성능 테스트_HikariCP의 연결 최대 풀 설정
3. 성능 테스트_Caffeine 캐시 설정 및 적용
4. 성능 테스트_인덱싱과 트랜잭션 관리 최적화
5. 성능 테스트_하드웨어 리소스 업그레이드
성능 목표 잡기
성능이 좋다는 의미는 무엇인가?
보통 웹 성능이 좋다는 의미는 웹사이트에 접속했을 때 이들이 원하는 콘텐츠가 로딩될 때까지 걸리는
Average response time이 적다는 것을 의미한다.
그래서 웹 성능이 좋다 → 콘텐츠가 빨리 로딩된다로 해석할 수 있다.
그렇다면 웹 성능 예산은? 목표로 둔 웹 로딩 시간을 의미한다.
세부적으로는 여러 가지 과정에 대하여 최대 허용 시간을 배분하는 것을 의미하는데
총예산 3초, DB 조회 1초, API 요청 처리는 0.5초 이런 식이다.
또한 성능 개선은 비용, 시간이 많이 드는 작업이라 모든 서비스 페이지를 빠르게 만드는 것은 ROI가 좋지 않고
가장 중요하고, 성능이 안 좋은 페이지에 성능 개선을 하는 것이 권장된다.
사진에서 보다시피 로컬 DB, 서버에서 간단하게 테스트했을 때
가장 많은 비즈니스 로직을 가지고 있는 매칭 엔티티와 관련된 API에서 가장 느린 로딩 시간이 측정됐기 때문에
해당 부분에 원인 분석 및 성능 개선을 하기로 했다.
웹 성능 예산을 잡고 최적화하는 이유는 사용자들이 해당 성능에 만족하지 못하는 경우
서비스를 이탈할 확률이 높아지기 때문이다.
하지만 아무리 좋은 성능 목표를 가지고 있더라도 이를 위한 비용이 현재 서비스의 수익이나 리소스에 따라서
많이 좌우되기 때문에 적절한 성능 목표를 잡는 것이 중요하다.
우리 서비스의 현재 목표는 2학기 대학교 축제에 MVP를 출시해 시장 반응을 보기 위함이고
MVP에는 결제 기능을 넣지 않아 오히려 기부를 하며…? 서비스를 하는 것이라
더욱 오버스러운 성능 예산을 잡지 않도록 하는 것이 중요했다.
목표 지표
웹 성능을 측정하기 위한 지표는 여러 가지가 있다.
- TTI(Time To Interative)
- 사용자가 상호작용이 가능해지기까지 걸리는 시간
- LCP(Largest Contentful Paint)
- 가장 큰 비주얼 콘텐츠가 표시되는 시간
- FCP(First Contentful Paint)
- 첫 번째 비주얼 콘텐츠가 표시되는 시간
- TTFB (Time To First Byte)
- 서버가 첫 번째 바이트를 보내는 데 걸리는 시간을 측정하며, 이는 서버의 응답 속도 표현
이 중에서 우리는 서버의 입장에서 TTFB를 기준으로 한 것이고
그중에서 평균 응답 시간과 백분율 90까지의 응답 시간을 기준으로 측정했다.
응답 시간과 관련된 설명은 아래와 같다.
Perplexity에서의 설명
- 주요 통계
- 모바일 웹사이트 방문자의 53%는 웹페이지 로딩에 3초 이상 걸리면 해당 사이트를 떠납니다.
- 평균적으로 모바일 사이트의 로딩 시간은 3G 연결에서 19초, 4G 연결에서 14초입니다.
- 로딩 속도의 영향
- 5초 내에 로딩되는 모바일 사이트는 19초가 걸리는 사이트에 비해 다음과 같은 이점이 있습니다:
- 25% 더 높은 광고 가시성
- 70% 더 긴 평균 세션 시간
- 35% 더 낮은 이탈률
- 페이지 로딩 시간이 1초에서 3초로 증가하면 이탈 확률이 32% 증가합니다.
- 5초 내에 로딩되는 모바일 사이트는 19초가 걸리는 사이트에 비해 다음과 같은 이점이 있습니다:
- 사용자 기대치
- 인터넷 사용자의 약 50%는 웹페이지 로딩 시간이 2초 미만이기를 기대합니다.
- 성능이 좋지 않은 경험을 한 사용자의 약 80%는 해당 페이지를 영구적으로 피하고 다시 방문하지 않습니다.
- 참고 링크
- https://www.thinkwithgoogle.com/marketing-strategies/app-and-mobile/mobile-page-speed-new-industry-benchmarks/
- https://www.akamai.com/newsroom/press-release/akamai-releases-spring-2017-state-of-online-retail-performance-report
- https://www.portent.com/blog/analytics/research-site-speed-hurting-everyones-revenue.htm|
이 정보를 바탕으로 약 90 퍼센트까지의 TTFB가 3초 이내인 것을 목표로 두었다.
테스트
테스트란, 특정한 상황을 가정하고 발생하는 문제를 사전에 찾기 위한 작업이다.
성능 테스트란 특히 트래픽이 많은 상황에서 발생하는 문제를 찾는 작업이다.
트래픽이란?
1초 동안 서버로 요청되는 수이고, RPS(Request Per Second)로 표현된다
트래픽이 많아서 생길 수 있는 문제는
- 서버의 리소스 부족으로 인해 사용자의 요청에 응답 X
- 서비스 처리 속도가 느려진다.
이런 문제에 대비하기 위해 성능 테스트를 진행하고, 문제를 미리 찾아내 해결하는 것을 목표로 한다.
이를 통해서 고객 중심의 서비스와 고가용성을 만족하는 서비스를 구축할 수 있다.
트래픽 산정
Now, Here 프로젝트는 축제 때 무작위 번호팅을 좀 더 쉽게 이용할 수 있게 만든 것으로
벤트 단위로 서비스와 데이터를 운영한다.
가장 메인 로직이자 TTFB가 가장 높게 나온 매칭과 관련해서
한 대학교의 축제에서 50명씩, 총 10개의 축제에 동의를 구해 프로젝트를 진행했다고 가정한다.
최대 가능한 매칭 수 계산:
- 총 유저 수: 500명
- 각 유저는 자신을 제외한 499명과 매칭 가능
- 총 가능한 매칭 수: 500 * 499 / 2 = 124,750개 (양방향 매칭 고려)가 된다.
하지만 부하를 주는 것이 목표이고, 양방향 매칭이 가능하다는 것을 생각해
25만 건의 매칭 데이터를 가지고 테스트를 진행했다.
이 정도 규모의 서비스에 테스트를 진행할 때는 postman의 유료 기능 중 하나인
api 성능 테스트로 충분하다는 판단이 들어 이를 통해 진행했다.
또한 postgreSQL을 사용 중이라, DB 관련해서는 pgAdmin4에 있는
대시보드를 통해 db 성능을 모니터링하였다.
목표
성능 테스트를 통해서 문제 원인을 파악하고 이를 성능 개선하는 것이 목표다.
문제 원인을 파악하기 위해서 k6, Grafana를 이용해 테스트 환경을 구축하고 실제로 사용해 봤지만
이 정도 규모의 서비스와 테스트에는
API 서버 → Postman의 API Performance Testing 기능
DB 서버 → pgAdmin4의 Dashboard
를 통해서 모니터링하는 것이 시간/비용적 측면에서 적절하다고 판단해 진행했다.
성능 개선에 가장 중요한 것은 리소스이고, 이를 위한 방법은 크게 두 가지 있다.
- 비효율적인 프로세스 개선 / 리소스 사용 줄이기
- 낮은 시간 복잡도를 가진 알고리즘을 사용
- 캐시를 사용
- 아키텍처를 개선
- 비동기 처리
- 인덱싱
- 리소스 업그레이드 / 리소스 용량 늘리기
- 하드웨어 리소스 측면에서는 CPU 코어를 늘리거나 메모리 용량을 늘릴 수 있다.
- 소프트웨어 리소스 측면에서는 락 범위를 최소화해 락을 잡는 시간을 줄이던가, 여러 개로 락을 나눌 수 있다.
현재 우리의 테스트 환경은 아래와 같은데
실제로 배포할 때 환경
API 서버:
총 2개
각각 VM OCPU 1/8개
1GB 메모리
총 디스크 100GB
DB 서버:
총 2개
GCP의 vCPU core 2
메모리 8GB
SSD 10GB (Master - Slave 구조, CUD / R을 나눠서 사용)
테스트할 때 환경
API 서버:
프로세서 Intel(R) Core(TM) Ultra 7 16코어
설치된 RAM 32.0GB
디스크 1TB
DB 서버:
cloudtype의 vCPU 프리티어(측정 불가 최소 자원), 메모리 512MB, HDD 1GB
사양에 대한 클로드의 평가
두 환경을 비교해 보면 다음과 같은 차이점이 있습니다
API 서버:
실제 배포: 2개의 서버, 각각 1/8 OCPU, 1GB 메모리 (총 1/4 OCPU, 2GB 메모리)
테스트: 16 코어 프로세서, 32GB RAM, 1TB 디스크
DB 서버:실제 배포: 2개의 서버, 각각 2 vCPU, 8GB 메모리, 10GB SSD
테스트: 최소 자원 (vCPU 측정 불가), 512MB 메모리, 1GB HDD
총 성능 비교:
API 서버: 테스트 환경이 압도적으로 우수합니다.
16 코어 프로세서와 32GB RAM은 실제 배포 환경의 1/4 OCPU와 2GB 메모리를 크게 상회합니다.
DB 서버: 실제 배포 환경이 훨씬 우수합니다.
총 4 vCPU, 16GB RAM, 20GB SSD는 테스트 환경의 최소 자원(512MB RAM, 1GB HDD)을 크게 능가합니다.
결론:
총체적인 성능을 고려할 때 실제 배포 환경이 더 우수할 가능성이 높습니다.
데이터베이스 성능이 전체 시스템 성능에 큰 영향을 미치는 경우가 많기 때문입니다.
또한, 실제 배포 환경은 이중화 구성으로 안정성도 더 높습니다.
→ 내 판단과 더불어 클로드가 판단 하에도 DB의 성능이 백엔드 전체 성능을 좌우하는 경우가 많다고 생각하는데
테스트 환경이 실제 배포 환경보다 훨씬 DB 성능이 안 좋기 때문에
더 열악한 환경 속에서 테스트하는 것이라 훨씬 유의미하다고 생각했다.
결론적으로 현재 서비스를 운용할 때 사용할 하드웨어 리소스는 한정되어 있기 때문에
최대한 비효율적인 프로세스 개선을 통해서 리소스 사용을 줄이는 것을 목표로 하였다.
또한 이미 테스트하는 환경이 실제 운용 환경보다 안 좋은 환경으로 예상하기 때문에
하드웨어 리소스는 자연스럽게 개선될 것으로 예상한다.(마지막에 밝혀짐)