HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
📯
부스트캠프 7기 BE 멤버쉽 설계
/
13주차 - 성능테스트

13주차 - 성능테스트

스프린트
강의날짜
Dec 8, 2022
키워드
🧐
마스터클래스 질의응답 모음
제목
확인
auto scailing에 github action으로 배포하기
확인
Redis 캐시 사용이 합리적인 선택일까요?
확인
WebRTC 성능 측정은 어떤 방식으로 하는게 좋을까요?
확인
부스트코스는 12.16 이후 닫힐까요??
확인
nestjs caching은 controller단과 service단 중 보통 어디 쪽을 선호하나요?
확인
First Paint가 DCL 전에 일어나는 현상
확인
에디터 미션은 결국 뭐였을까요
확인
실제 회사에서도 gzip 압축으로 퍼블리싱을 하나요?
확인
polling에서 VUser의 수는 어떻게 책정하나요? polling 쪽 테스트도 궁금합니다
확인
소켓 부하테스트도 궁금합니다!
확인
ngriner, artillery, wrk 모두 같은 지표에 대한 수치가 달라요 ㅠㅠ
확인
1. 서비스 성능 측정2. 웹 성능 예산1) 예비 분석2) 경쟁사 혹은 유사 사이트 분석 3) 성능 기준 설정ETC) 성능에 대한 관점3. 부하테스트1) 서비스가 얼마나 빠른지(Time)2) 일정 시간 동안 얼마나 많이 처리할 수 있는지(TPS)3) Performance vs Scabaility3) 얼마나 많은 사람들이 동시에 사용할 수 있는지(Users)4. 테스트 종류1) Smoke Test2) Load Test3) Stress Test5. 테스트 도구6. 테스트시 주의할 점7. 테스트 계획1) 전제 조건2) 목표값 설정3) 시나리오 대상8. K6로 작성해보기1) install2) 참고링크3) 실습코드Reference

1. 서비스 성능 측정

notion image
  • https://www.webpagetest.org/
    • notion image
    • 연결을 시도하는 위치, 환경부터 Repeat View(캐싱 등 테스트), 동일한 조건으로 여러 차례 테스트할 수 있음
    • 테스트한 결과를 영상으로 기록
  • https://pagespeed.web.dev/
    • notion image
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

2. 웹 성능 예산

https://addyosmani.com/blog/performance-budgets/
  • What
    • 웹 사이트를 유지하고 운영하는 데 필요한 예산.
    • 웹 사이트의 성능을 향상시키기 위해 필요한 서버 자원, 인프라 구축 및 유지보수 비용, 웹 서비스 제공 업체의 요금 등을 포함.
    • 웹 성능 예산을 적절히 관리하면 웹 사이트의 성능을 최적화할 수 있음
  • How
    • 정량 / 시간 / 규칙 기반으로 산정
    • 성능 목표에는 정답이 없지만, 3초의 법칙 (3초 안에 로딩되지 않으면 53%의 사용자가 떠나고 로딩 시간이 길어질수록 사용자 이탈률이 늘어남)이 있듯, 서비스의 성능 목표를 두는 것이 필요
  • Goal
    • 메인 페이지의 모든 오브젝트 파일 크기는 10MB 미만으로 제한
      • 이미지를 원본으로 사용하는 것
      • 카메라로 찍은 사진 → 용량이 매우 큼
        • 보통 모니터 1920x1080 인데, 사진은 이 크기를 매우 초과
    • 모든 웹 페이지의 각 페이지 내 포함된 자바스크립트 크기는 1MB를 넘지 않아야 함
      • SPA으로 만든 페이지가 10개
      • 10개의 페이지 정보를 다 로딩할 필요가 있을까? → Nope
      • 필요한 페이지만 로딩 하자
      • Dynamic Import
    • 검색 페이지에는 2MB 미만의 이미지가 포함
    • LTE 환경에서의 모바일 기기의 Time to Interactive는 5초 미만
    • Dom Content Loaded는 1초, First Meaningful Paint는 1.5초 미만
    • Lighthouse 성능 감사에서 80점 이상
      • 어떻게 Dom Content Loaded가 10초인데 Lighthouse 성능이 80점이 나오죠
 
 

1) 예비 분석

  1. 사용자 트래픽이 많은 페이지 혹은 제품 방문 페이지 등 가장 중요한 페이지에 대해
  1. PageSpeed를 활용하여 FCP, TTI 등의 지표 확인
 

2) 경쟁사 혹은 유사 사이트 분석

  • 경쟁 사이트 또는 유사한 사이트(similarweb 등을 활용)의 성능 분석
  • 사용자는 응답시간이 20% 이상일 때 차이를 인식함 (참고) → 분석한 사이트와 20% 이상 성능 차이가 나는지 확인
 

3) 성능 기준 설정

notion image
  • 정량 / 시간 / 규칙 기반
  • 우선 서비스에 중요한 페이지부터 작성
  • 예시
    • 페이지로드 3초 미만
    • TTI 5초 미만
    • 압축된 리소스 최대 크기 200KB 미만
    • …
 
  1. 정량(Quantity based Metric)
      • 이미지 최대 크기
      • 웹 글꼴 최대 크기
      • 글꼴 최대 갯수
      • 스크립트 최대 크기
      • 스크립트 최대 갯수
      • HTML, CSS 최대 크기
      • 동영상 최대 크기
  1. 시간(Timing based Metric)
      • FCP, LCP, TTI, TBT, CLS 등 pagespeed에서 제공하는 데이터
  1. 규칙(Rule based Metric)
      • WebPageTest, pagespeed 등 웹 사이트에서 측정한 점수를 지표로 사용
  1. 우선순위
      • 여러 지표들 중 우선순위가 높은 지표 선정
      • 사용자에게 컨텐츠가 빠르게 노출되고 렌더링하는 것이 중요 → FCP 우선순위 높음
      • 사용자가 관련 링크를 빠르게 클릭해야 할 경우 → TTI 우선순위 높음
 

ETC) 성능에 대한 관점

  • 성능의 개선 및 저하는 수익에 직접적인 영향을 준다 → 화면 응답시간이 느리다고 판단되면, 어느 부분에서 지연현상이 발생하는지 파악해야 함 (참고: https://web.dev/why-speed-matters/)
  • 서비스가 얼마나 빠른지(Time) / 일정 시간 동안 얼마나 많이 처리할 수 있는지(TPS) / 얼마나 많은 사람들이 동시에 사용할 수 있는지(Users)
  • 성능 개선에는 한계가 생길 수밖에 없음(암달의 법칙) → 부하의 원인을 파악하여 제거
    • 브라우저에서 제일 성능을 많이 잡아 먹는 것 → 렌더링
    • 의외로 중요한 것 → 반복문
      • for vs forEach
      • while vs for
      • for in vs for of
        • → 사용자가 느끼기에 그렇게까지 큰 차이가 없음
        • 렌더링은? → 매우 차이가 큼
    • 화면은 60Hz, 144Hz, 240Hz
      • 1초 → 60번 렌더링
        • 16.666ms
          • 브라우저 입장에서는 어떤 명령이든 이 시간 동안에만 실행되면 된다.
      • 1초 → 144번 렌더링
      • 1초 → 240번 렌더링
 
성능 테스트 vs 부하 테스트 → ?
 
성능 테스트 → 단일 리퀘스트가 얼마나 빠른가
부하 테스트 → 요청을 얼마나 버틸 수 있는가 (가용성)
서버 개발자에게 제일 중요한 것 → 안죽는거
얼만큼 노동을 시켜야 죽는가 →
어떻게 해야 죽지? → 죽는걸 미리미리 예방해보자
 
 

3. 부하테스트

💡
부하란? 요청을 처리하려고 해도 실행할 수 없어서 대기하고 있는 프로세스의 수 https://brainbackdoor.tistory.com/117
 

1) 서비스가 얼마나 빠른지(Time)

notion image
  • 시스템 입장 → 응답시간(Response Time)
  • 사용자입장 → 사용자가 요청에 대해서 응답을 받은 후에 웹 페이지를 보기 까지(Think Time)
  • 성능 테스트 시엔 실제 지연시간이 발생하는 구간을 파악 필요
    • 브라우저 → 웹 서버
      • 정적 파일 크기
      • Connection 관리
      • 네트워크 환경
    • Server
      • DB와 애플리케이션 간 연결의 문제
      • 프로그램 로직 상의 문제
        • CPU점유율이 많은 경우
          • JS에서는 response를 받아서 json으로 변환
          • json으로 변환한 다음에, dto로 변환
          • 예를들어서, 응답의 크기가 8MB → DTO 변환 → CPU를 혹사
          • 요청을 처리할 때 CPU 사용이 많아지고 → 응답이 느려지는
          • nodejs → 비동기 처리 → CPU를 점유하고 있으면 문제가 됨
          • 멀티 스레드 → CPU점유하고 있더라도 스레드를 나눠서 관리하면 되니까 비교적 리스크가 적음
          • 싱글 스레드 + 비동기 → 특정 코드가 CPU 점유율이 높음 → 다른것들을 수행할 수 없음
            • https://youtu.be/ZeRJycLzh1g
      • 서버의 리소스 부족
    • 네트워크 이슈
      • 단순히 서버를 늘린다고(Scale out) 해결 X
      • 출시 전에 테스트를 하여 최대 응답시간을 파악
      • 상위 5%의 화면이 95% 사용자 요청을 받는다는 점을 감안하고 튜닝의 대상을 선정

2) 일정 시간 동안 얼마나 많이 처리할 수 있는지(TPS)

  • Transaction
    • 시간당 처리율을 나타내는 지표의 기준
    • 서버 입장 → 각각의 요청들이 Transaction
    • 사용자 입장 → 한 화면을 보기위해 필요한 모든 요청 묶음이 Transaction
      • notion image
  • 응답시간
    • notion image
  • TPS = Transaction Per Second
    • https://www.whatap.io/ko/blog/14/
    • 서비스 처리 건수 / 측정 시간
    • 요청 사용자 수 / 평균 응답시간
    • 동시 사용자 수 / 서비스 요청 간격
notion image
  • User 증가 → TPS는 어느 정도 증가하다가 더 이상 증가하지 않음. Time은 일정하게 유지되다 점차적으로 증가
  • 부하(TPS)가 증가 → 지연시간은 변곡점에 이르기도 하는데, 이 경우 시스템 리소스가 누수되고 있는 것은 아닌지 확인 필요
    • 데드락
    • 스레드가 너무 많은 경우 → 컨텍스트 스위칭 비용이 너무 많아짐 → 요청을 처리할수 없는 상태가 되어버림
  • TPS (Transaction Per Seconds)는 Scale out 혹은 Scale up을 통해 증가시킬 수 있음
    • 성능테스트와는 다른 점 → 서버를 늘리면 TPS 자체는 증가시킬 수 있음
  • 보통 테스트 시에 단순히 응답시간을 기준으로 종료시키지 말고, TPS나 DB Connection, CPU 등을 종합적으로 확인하고 중단시켜야 합니다.

3) Performance vs Scabaility

notion image
  • 성능에 문제가 있는 경우 → 단일 사용자에 대한 응답 속도가 느려짐
  • 확장성에 문제가 있는 경우 → 단일 사용자에게는 빠르지만 부하가 많아질 경우 속도가 느려짐
 

3) 얼마나 많은 사람들이 동시에 사용할 수 있는지(Users)

notion image
얼마나 많은 사람들이 동시에 사용할 수 있는가 → 서비스를 운영하며 늘 화두
사용자 → 관점에 따라 다양한 형태로 존재함
  • 시스템 관리자의 관점 → 등록된 사용자 or 등록되지 않은 사용자
  • 서버의 관점 → 로그인한 사용자 or 로그인하지 않은 사용자
  • 성능 테스터의 관점 → Concurrent User or Active User
    • Concurrent User: 웹 페이지를 띄어놓은 사용자처럼, 언제든지 부하를 줄 수 있는 사용자
    • Active User: 메뉴나 링크를 누르고 결과가 나오기를 기다리는 등 실제로 서버에 부하를 주고 있는 사용자
💡
Active User 와 Concurrent User 의 비율은 서비스의 성격에 따라 다르므로 이 점을 감안하고 성능테스트를 계획해야 합니다. (성능 테스트시에 VUser는 Active User와 유사합니다.) 가령 수강신청의 경우, 특정 시간대엔 그 비율이 90%에 육박할 수 있어, 전체 평균을 기준으로 테스트할 경우 잘못된 판단을 이끌어낼 수 있습니다.
  • keep-alive
    • 한 번 연결을 해놓고 유지한다
    • 먼저 선점한 사용자가, 어떤 기능을 이용하든 우선순위가 높음
    • keep-alive가 끊어져야 뒷사람에게도 기회가 있음
 
 

4. 테스트 종류

1) Smoke Test

notion image
  • 최소한의 부하로 구성된 테스트 → 테스트 시나리오에 오류가 없는지 검증
  • VUser를 1 ~ 2로 구성

2) Load Test

notion image
  • 서비스의 평소 트래픽과 최대 트래픽 상황에서 성능이 어떤지 확인
  • 애플리케이션 배포 및 인프라 변경(scale out, DB failover 등)시에 성능 변화 확인
  • 외부 요인(결제 등)에 따른 예외 상황을 확인

3) Stress Test

notion image
  • 서비스가 극한의 상황에서 어떻게 동작하는지 확인
  • 장기간 부하 발생에 대한 한계치를 확인
  • 최대 사용자, 최대 처리량
  • 스트레스 테스트 이후 시스템이 수동 개입없이 복구되는지 확인

5. 테스트 도구

  • Apache JMeter
    • OS의 영향이 심함
    • 윈도우 환경에서 테스트할 때 문제되는 경우가 많음
    • 네이티브 앱
  • nGrinder
    • 설치형 웹서버
  • Gatling
  • Locust
  • K6
    • 쉽고
    • cloud
 

6. 테스트시 주의할 점

  • 시나리오 기반의 테스트
    • 각 사용자마자다
      • 회원가입을 하고
      • 로그인을 하고
      • 게시물을 쓰고
        • → 사용자 인증 + DB 조회
      • 게시물을 조회하고
        • → 사용자 인증 X, DB 조회
      • 게시물을 삭제하기
  • 동시 접속자 수, 요청 간격, 최대 Throughput 등 부하를 조정할 수 있어야 함
  • 부하 테스트 서버 스케일 아웃을 지원하는 등 충분한 부하를 줄 수 있어야 함
  • 성능 테스트는 실제 사용자가 접속하는 환경에서 진행
    • 로컬 → 로컬 = 무의미
    • 내부 네트워크에서 부하를 발생 → 응답시간에 차이가 발생
  • 클라이언트 내부 처리시간이 배제되어 있음
  • 테스트 DB에 들어 있는 데이터의 양이 실제 운영 DB와 동일해야 됨
    • 통상 전체 성능의 70% 이상이 DB에 좌우됨
    • 데이터 양이 다름 → 쿼리의 실행계획이 달라짐 or 디스크 입출력 차이 → 성능이 다르게 나타남
  • 외부 요인(결제 등)의 경우 시스템과 분리된 별도의 서버로 구성
    • 객체 Mocking → Http Connection Pool, Connection Thread 등을 미사용 → I/O가 미발생
    • 같은 애플리케이션에 Dummy Controller를 구성 → 테스트 시스템의 자원과 리소스를 같이 사용 → 테스트의 신뢰성 감소
    •  
  • 네이버 → 포털 → 캐싱을 굉장히 적극적으로 사용함
  • 배민, 두나무 → 결제 시스템 → 캐시X, Real을 얼마나 잘 쓰는가

7. 테스트 계획

1) 전제 조건

  • Target 시스템의 범위 선정
  • 부하 테스트시에 저장될 데이터 건수와 크기를 결정
  • 서비스 이용자 수, 사용자의 행동 패턴, 사용 기간 등을 고려하여 계산
  • 목표값에 대한 성능 유지기간 선정
  • 서버에 같이 동작하고 있는 다른 시스템, 제약 사항 등을 파악 (사이드 이펙트)

2) 목표값 설정

  1. 예상 1일 사용자 수(DAU)
  1. 피크 시간대의 집중률 예상
    1. 최대 트래픽
    2. 평소 트래픽
  1. 1명당 1일 평균 접속 혹은 요청수 예상
  1. Throughput을 계산합니다.
    1. Throughput → 1일 평균 rps ~ 1일 최대 rps
        • 1일 사용자 수(DAU) x 1명당 1일 평균 접속 수 = 1일 총 접속 수
        • 1일 총 접속 수 / 86,400 (초/일) = 1일 평균 rps
        • 1일 평균 rps x (최대 트래픽 / 평소 트래픽) = 1일 최대 rps
      • Latency → 일반적으로 50~100ms이하로 잡는 것이 좋음
      • 사용자가 검색하는 데이터의 양, 갱신하는 데이터의 양 등을 파악

3) 시나리오 대상

  • 접속 빈도가 높은 기능
    • 홈페이지 등
  • 서버 리소스 소비량이 높은 기능
    • CPU
      • 이미지, 동영상 변환
      • 인증
      • 파일 압축/해제
    • Network
      • 응답 컨텐츠 크기가 큰 페이지
      • 이미지, 동영상 업로드/다운로드
    • Disk
      • 로그가 많은 페이지
  • DB를 사용하는 기능
    • 많은 리소스를 조합하여 결과를 보여주는 페이지
    • 여러 사용자가 같은 리소스를 갱신하는 페이지
  • 외부 시스템과 통신하는 기능
    • 결제 기능
    • 알림 기능
    • 인증/인가
 
 
네이버 → 굉장히 계획적임 → 1년치 계획 → 각각의 구성원에 대해 성과를 측정하는 것에 적극적 → 경쟁이 심할 수 있음
 
기업자체가 계획적인 사람을 좋아하는가?
팀 자체가 계획적으로 움직이는가?
→ 대기업
팀 자체가 인사이트를 통해서 움직이는가?
→ 스타트업
 
 
토스 → 구성원의 성과를 측정하지 않음 → 기업의 성과를 측정 → 구성원에게 보상
 
토스 → 전직원 성과금 = 연봉의 최소 10% ~ 최대 200%
네이버 → 개개인의 성과에 따라 차등 지급
 
토스 → 목적조직 위주
→ 채팅 팀
→ FE, BE, 디자이너, 기획자, PO 한 팀
→ 서비스를 만들 때, 커뮤니케이션이 미친듯이 빠름 → 일이 너무 많아
네이버 → 기능조직 위주
→ 백엔드 개발자 팀
→ 프론트엔드 개발자 팀
→ 디자인 팀
→ 서비스를 만들 때, 커뮤니케이션이 좀 느릴 수 있음 → 누군가는 답답함을 느낌
→ 안정감. 시니어가 밀집되어있음. 깊게 배울 수 있는 것들이 많음
 
카카오 → 일이 많이 없다 + 보상도 많이 짜다
 
대기업(네카라)
→ 연봉테이블
→ 3년차 연봉의 최대치 6500
 
우형, 토스, 당근, … → 상한선이 거의 없는 편
 
우형 → 모니터링을 굉장히 빡세게 → 항상 긴장감을 유지하는 곳

8. K6로 작성해보기

1) install

https://k6.io/docs/get-started/installation/

2) 참고링크

https://blog.outsider.ne.kr/1610
https://k6.io/docs/
https://devocean.sk.com/blog/techBoardDetail.do?ID=164237

3) 실습코드

script.js
import http from 'k6/http'; import { check, group, sleep, fail } from 'k6'; export let options = { stages: [ // target = VUser = Active User { duration: '1m', target: 30 }, { duration: '1m', target: 60 }, { duration: '1m', target: 90 }, { duration: '1m', target: 120 }, { duration: '1m', target: 150 }, ], thresholds: { http_req_failed: ['rate<0.01'], // http 오류는 1% 미만이어야 함 http_req_duration: ['p(95)<200'], // 요청의 95%는 200ms 미만으로 응답해야 함 }, }; const BASE_URL = 'https://httpbin.test.k6.io/'; const USERNAME = '***'; const PASSWORD = '***'; export default function () { const res = http.get('https://httpbin.test.k6.io/'); check(res, { 'status was 200': (r) => r.status == 200 }); sleep(1); }
$ k6 run ./script.js
notion image

Reference

  • 부하란 무엇인가?
  • https://web.dev/vitals/
  • https://web.dev/lighthouse-ci/
  • https://web.dev/user-centric-performance-metrics/
  • https://web.dev/lcp/
  • https://web.dev/fcp/
  • https://web.dev/cls/
  • https://web.dev/fid/
  • https://web.dev/tti/
  • https://web.dev/tbt/
  • https://www.whatap.io/ko/blog/14/
  • https://blog.outsider.ne.kr/1610
  • https://k6.io/docs/
  • https://naver.github.io/ngrinder/
  • https://partnerjun.tistory.com/95
  • 토스의 서버 인프라 모니터링
    • Video preview