심화/대규모 트래픽 처리

[부하테스트] 부하 테스트 란? (feat. k6)

annovation 2026. 7. 3. 23:49

중요한 개념

💡 처리량 (Throughput)

  • 정의 : 단위 시간당 시스템이 처리하는 요청의 양
  • 지표 : 주로 TPS(Transactions Per Second)나 RPS(Requests Per Second)로 측정한다.
  • 의미 : 시스템이 얼마나 많은 일을 할 수 있는지 성능의 '양'을 나타낸다.

💡 지연 시간 (Latency)

  • 정의 : 사용자가 요청을 보낸 시점부터 응답을 받을 때까지 걸리는 시간
  • 의미 : 사용자에게 얼마나 빠른 '경험'을 주는지 성능의 '질'을 나타낸다.

💡 상관관계

  • 부하가 증가해도 일정 수준까지는 처리량이 늘어나지만, 임계치를 넘으면 지연 시간이 급격히 증가하고 처리량은 정체되거나 하락한다.

부하 테스트 툴 선정 (k6)

💡 K6 란?

  • k6 백엔드 API나 웹 서비스에 가상의 사용자, 즉 Virtual User를 만들어 반복적으로 요청을 보내고, 응답 시간, 실패율, 처리량 같은 성능 지표를 측정하는 성능 테스트 도구이다.

💡 K6 선정 이유

  • 설치가 간단하다 (macOS 기준 brew install 만 해주면 된다.)
  • 학습 곡선이 적다. (javascript로 작성하므로, 친숙한 언어로 빠르게 학습하여 적용할 수 있다.)
  • 메모리를 적게 쓰면서도 많은 트래픽을 효율적으로 발생시킬 수 있으며, 사용법이 간단하면서도 테스트 결과가 매우 정확하다.
❗️단순히 테스트 툴의 사용법을 아는 것보다, 결과 데이터를 정확하게 해석하고 이를 바탕으로 시스템 성능을 개선할 수 있는 능력이 실무에서 훨씬 중요!

부하 테스트를 통한 결과 해석

💡 병목 지점 (Bottleneck Point) 발견 가능

 

1. 병목 지점(Bottleneck Point) 이란?

  • 개념 : 전체 시스템 인프라 구성에서 특정 서버 자원(CPU, 메모리 등)이 한계에 도달하여, 전체 성능이 저하되는 구간
  • 고속도로 비유 : 넓은 3차선 도로를 달리던 차들이 갑자기 2차선으로 좁아지는 구간이나 여러 도로가 합쳐지는 구간에 진입할 때 발생하는 '교통 정체 구간'과 같다.

2. 시스템 성능 개선의 핵심 원칙

  • 시스템의 성능을 개선하려면 반드시 정체가 발생한 병목 지점(2차선 구간)을 해결해야 한다.
  • 정체가 없는 원활한 구간(3차선 도로)을 아무리 크게 넓혀봐야 좁은 구간의 정체가 나아지지 않으며, 오히려 더 많은 차들이 좁은 구간으로 몰려들어 상황이 더 나빠지게 된다.
  • 즉, 아무 곳이나 성능을 개선한다고 해서 전체 시스템의 성능이 올라가는 것이 아니다!

3. 병목 지점의 스루풋(Throughput) = 전체 스루풋

  • 처리량이 제일 낮은 병목 지점의 스루풋이 곧 전체 시스템의 스루풋이 된다.
  • ex. 백엔드 서버가 1초당 1,000개의 요청을 처리할 수 있더라도, DB가 1초당 300개의 요청만 처리할 수 있다면 전체 시스템의 1초당 처리량은 결국 300개이다.

💡 병목 지점 해소 시 나타나는 새로운 현상

  • 특정 병목 지점을 해소하면, 다른 곳에서 새로운 병목 지점이 발생한다는 사실도 명심해야 한다.


부하 테스트 전체 흐름

💡 1. 부하 테스트의 필요성 인식

  • '사용자들이 몰려서 서버가 터지면 어떡하지?' 또는 '내 서버는 과연 어느 정도의 사용자 요청을 견딜 수 있을까?' 와 같은 궁금증이 생길 때 부하 테스트가 필요하다.
  • ex. 선착순 쿠폰 발급 API 성능에 대해 궁금할 때

💡 2. 부하 테스트 목표 설정

  • 막연하게 테스트하는 것이 아니라, 스루풋(Throughput, TPS)과 레이턴시(Latency)를 기준으로 명확한 목표치를 설정

부하 테스트 목표 설정 예시

💡 3. 부하 테스트 실행 및 현재 상태 측정

  • 현재 시스템이 어느 정도의 스루풋과 레이턴시를 감당할 수 있는지 부하 테스트 툴을 활용해 직접 측정
  • 측정 방식 : 처음부터 엄청난 부하를 주는 것이 아니라, 부하의 정도를 점점 올려가면서 시스템이 어느 정도까지 견디는지 확인하고 최대 스루풋을 파악하게 된다.

💡 4. 병목 지점 파악

  • 성능을 올리려면 반드시 병목 지점을 파악해서 개선해야 한다.
  • 시스템 아무 곳이나 개선한다고 전체 성능이 좋아지는 것이 아니며, 오직 병목 지점을 개선해야만 전체 성능이 올라간다는 것을 기억해야 한다.

💡 5. 성능 개선 및 재테스트 (목표 달성까지 반복)

  • 병목 지점을 찾아 개선했다면, 개선된 시스템이 트래픽을 얼마나 더 견디는지 확인하기 위해 다시 부하 테스트를 진행한다.
  • 재테스트 : 이전과 똑같이 부하를 점점 올려가며 최대 스루풋과 평균 레이턴시를 다시 측정한다.
  • 반복 작업 : 만약 성능을 개선했는데도 측정 결과가 1,900 TPS가 나와서 여전히 목표치(2,000 TPS)에 도달하지 못했다면, 다시 또 다른 병목 지점을 파악하고 성능을 개선하는 작업을 반복해야 한다.
  • 계속해서 [병목 지점 파악 → 성능 개선 → 부하 테스트] 사이클을 돌다가, 목표치를 달성하게 되면 그때 부하 테스트 과정을 마무리하게 된다.

주의점

💡 적절한 부하 테스트 시간 확보 (최소 5분 이상)

  • 주로 1분 간격으로 지표를 기록하기 때문에, 정확한 성능 측정을 위해 최소 5분간 부하테스트를 진행해야 한다.

💡 프로덕션 환경과 동일한 데이터 세팅

  • 데이터베이스의 성능은 데이터가 어떻게 저장되어 있는지, 그리고 데이터가 얼마나 많이 저장되어 있는지(데이터 양)에 따라 엄청난 차이가 발생한다.
  • 따라서 보다 정확한 결과값을 얻으려면, 실제 서비스 중인 프로덕션(운영) 환경과 비슷하게 데이터를 구성해두고 테스트를 진행해야 한다.

💡 프로덕션과 분리된 환경에서 테스트

  • 실제 서비스가 돌아가고 있는 프로덕션 환경에서 직접 부하 테스트를 진행하게되면, 부하 테스트 자체가 인프라에 극한의 트래픽을 가하는 행위이므로, 자칫하면 실제 서비스에 장애를 유발할 수 있기 때문

부하 테스트 목표 : 성능 개선

💡 성능 개선을 위한 3가지 필수 요소

  • 대규모 트래픽 처리를 위해 시스템을 고도화할 때, 스루풋(Throughput)과 레이턴시(Latency)를 고려하게 되는데,
  • 시스템을 안정적으로 개선하기 위해서는 '가용성(Availability)'이라는 요소도 반드시 함께 고려하며 설계해야 한다.

💡 가용성(Availability)이란?

  • 개념 : 시스템이 장애 없이 서비스를 정상적으로 제공할 수 있는 가능성(확률)
  • 가용성이 높고 낮음
    • 언제 접속해도 매번 잘 작동하여 장애 발생 가능성이 극히 작은 시스템을 '가용성이 높은 시스템'이라 하고, 반대로 서비스가 다운되는 시간(다운타임)이 긴 시스템을 '가용성이 낮은 시스템'이라고 한다.
  • 정상 가동률(퍼센트 표기)
    • 가용성은 퍼센트(%)로 표시한다.
    • 예를 들어 가용성 99.99%라는 것은 1년 중 99.99%의 시간 동안 정상 이용이 가능하며, 서비스가 다운되는 시간은 1년에 단 53분 정도밖에 되지 않는 시스템을 뜻한다.
  • 가용성이 높은 시스템을 만들려면, 서비스가 사용 불가능한 시간(다운 타임)을 아예 발생시키지 않거나, 발생하더라도 그 시간이 아주 짧게 지나가도록 설계해야한다.
  • 다운 타임을 줄이는 데 가장 중요한 설계 방법 중 하나가 시스템 이중화(System Redundancy) 이다.

💡 시스템 이중화 (System Redundancy)

  • 개념 : 다운타임을 줄이고 가용성을 높이기 위한 가장 중요한 설계 방법 중 하나이다. 시스템의 일부분을 사용할 수 없게 고장 나더라도, 다른 시스템을 이용하여 서비스를 계속 제공할 수 있게 만드는 것을 의미한다.
  • 예시
    • A, B, C라는 3대의 서버가 있을 때, A가 고장 나도 B와 C를 쓰고, B가 고장 나도 C를 쓸 수 있도록 구성하는 것
    • 세 대가 한 번에 동시에 고장 날 확률은 아주 적기 때문에 서비스가 계속 유지될 수 있다.

💡 인프라 설계에서의 이중화 적용 (ELB와 EC2)

  • 단일 서버 구조의 한계
    • 사용자가 ELB(로드밸런서)를 통해 단 1대의 EC2 서버로 통신하는 구조가 있다고 한다면, 만약 이 1대의 서버가 멈춰버리면, 그 순간 사용자는 곧바로 서비스 장애를 경험하게 된다. (가용성이 낮은 설계)
  • 이중화 서버 구조의 장점
    • EC2 서버를 2대 이상으로 구성하면, 1대가 고장 나더라도 살아있는 나머지 1대의 서버가 정상적으로 통신을 이어가게되고, 사용자 입장에서는 서비스가 중단되었다는 사실조차 느낄 수 없게 된다.
  • 결론 : 안정적인 서비스 운영을 위해서는 이처럼 최대한 시스템 이중화를 적용하여 가용성을 높이는 방향으로 인프라를 설계해야 한다.

성능 개선 3가지 전략

부하 테스트를 통해 병목 지점을 찾았다면, 이를 해결하고 시스템을 고도화하기 위해 주로 아래의 세 가지 방법을 사용한다.

 

💡 1. 수평적 확장 (Horizontal Scaling)

  • 특정 시스템의 성능을 올리기 위해 시스템(컴퓨터/서버)의 '개수'를 늘리는 방식
  • 예를 들어 EC2 서버 1대로 요청을 처리하기에 CPU나 메모리 리소스가 모자랄 때, 컴퓨터를 한 대 더 추가하는 것
  • 장점
    • 가용성 증가 : 서버가 여러 대가 되므로 자연스럽게 '시스템 이중화'가 되어 장애가 발생할 확률이 줄어든다.
    • 무한한 확장성 : 컴퓨터 개수를 100개, 1,000개, 10,000개로 계속 늘릴 수 있어 확장에 제한이 없다.
    • 유연성 : 필요에 따라 서버를 쉽게 추가하고 또 금방 없앨 수 있어 축소 및 확장이 매우 쉽다.
  • 단점
    • 여러 대의 서버를 한 대의 서버처럼 사용하기 위한 추가 작업이 필요하다. ex. 로드 밸런서

💡 2. 수직적 확장 (Vertical Scaling)

  • 시스템의 개수를 늘리는 것이 아니라, 기존 시스템(컴퓨터)의 스펙(CPU, 메모리 등)을 더 좋은 사양으로 업그레이드(교체)하는 방식
  • 장점
    • 단순한 인프라 : 서버가 단 한 대뿐이므로 로드 밸런서(ELB) 같은 추가 작업이 필요 없다.
    • 비용 절감 : 인프라 구성이 단순하여 금전적인 비용뿐만 아니라 시간과 노력 등 전반적인 관리 비용이 적게 든다.
  • 단점
    • 가용성 감소(단일 장애 지점) : 서버가 단 한 대뿐이라 시스템 이중화가 안 되어있기 때문에, 이 서버가 고장 나면 서비스 전체가 중단된다.
    • 확장의 한계 : 컴퓨터 부품의 최고 사양에는 물리적인 한계(ex. 꽂을 수 있는 메모리의 최대치)가 존재하므로 확장성에 명확한 제한이 있다.
    • 다운타임 발생 : 스펙을 업그레이드하려면 기존 컴퓨터를 끄고 부품을 교체해야 하므로 불가피하게 서비스 중단(다운타임)이 발생하며, 이 역시 가용성을 떨어뜨리는 요인이 된다.

💡 3. 캐싱 (Caching)

  • 데이터를 조회할 때, 원래 데이터가 있는 곳보다 더 빠르게 액세스(접근)할 수 있는 곳에 데이터를 '임시로 저장'해두고 가져오는 방식
  • 예시 1 : Redis

  • 자주 접근하는 데이터를 DB 보다 훨씬 속도가 빠른 임시 저장소인 '레디스(Redis)'에 일부 저장해 두고 가져오면 성능을 크게 끌어올릴 수 있다.
  • 예시 2 : CDN - CloudFront

  • AWS S3에 동영상 원본이 저장되어 있을 때, 물리적으로 거리가 먼 나라의 사용자는 다운로드 속도가 오래 걸려 성능 악화를 경험하게 된다.
  • 이를 해결하기 위해 각 나라별로 가까운 곳에 임시 저장소를 두고 원본 동영상을 '복제'해 둔다.
  • 사용자는 거리가 먼 S3 원본이 아니라 자신과 가장 가까운 복제 저장소에서 데이터를 빠르게 가져올 수 있는데, 이 CDN(Content Delivery Network) 기법 역시 캐싱 전략의 일종이다.

트래픽 증가에 따른 시스템 설계 및 확장 방법

부하 테스트를 통해 설정한 목표 스루풋과 레이턴시를 달성하려면 병목 지점을 찾고 그에 맞는 적절한 확장을 해야 한다.

병목 지점이 어디서 발생하느냐에 따라 성능 개선 방법이 달라지는데, 이 방법에 대해 대략적으로 알아놓으면 성능 개선을 수월하게 진행할 수 있다.

💡 1단계 : 단일 서버 구성 (모든 것을 한 곳에)
  • 구조 : EC2 서버 단 한 대에 프론트엔드, 백엔드, 데이터베이스(DB)를 모두 설치해서 운영하는 가장 심플한 형태
  • 장점 : 여러 리소스를 쓰지 않아 비용이 적게 들고, 서버 한 대만 조작하면 되므로 관리가 아주 쉽다.
  • 문제점(병목) : 서비스가 커지면 DB가 CPU, 메모리, 디스크 등 컴퓨터 자원을 엄청나게 잡아먹기 시작하면서, 같은 서버에 있는 웹 애플리케이션의 성능까지 함께 떨어뜨리는 악영향을 준다.
💡 2단계 : 데이터베이스(DB) 서버 분리
  • 구조 : 1단계의 문제를 해결하기 위해 웹 애플리케이션(EC2)과 데이터베이스(RDS)를 별도의 서버로 분리한다.
  • 문제점(병목) : 트래픽이 더 늘어나면, 용량이 큰 '정적 파일(이미지, 동영상 등)'을 제공하는 과정에서 웹 서버가 자원을 너무 많이 소모하여 과부하에 걸리게 된다. (단순 HTML, CSS, JS는 용량이 작지만, 이미지나 영상은 서버에 큰 부담을 준다.)
💡 3단계 : 정적 파일 서버(S3) 분리
  • 구조 : 웹 서버의 과부하를 막기 위해 이미지, 동영상 같은 정적 파일만 전담해서 제공하는 별도의 서버(AWS S3)를 구축한다.
  • 문제점(병목) : 정적 파일을 분리하긴 했지만, 넷플릭스를 볼 때처럼 사용자와 데이터를 제공하는 원본 서버(S3)의 물리적 거리가 멀면 응답 속도(다운로드)가 매우 느려지는 문제가 발생한다.
💡 4단계 : CDN (CloudFront) 도입
  • 구조 : 물리적 거리로 인한 지연을 해결하기 위해 캐싱 원리가 적용된 CDN(AWS CloudFront)을 도입한다.
  • 전 세계 곳곳에 임시 저장소를 두고 원본 데이터를 복제해 두어, 사용자가 가장 가까운 곳에서 파일을 빠르게 다운받을 수 있게 한다.
💡 5단계 : 웹 서버(EC2)의 수평적 확장과 로드 밸런서(ELB)
  • 구조
    • 트래픽이 더 늘어 EC2 자체의 성능이 모자라 병목이 발생하면 확장이 필요하다.
    • 가용성(시스템 이중화)의 이점을 얻기 위해 EC2 서버의 개수를 늘리는 '수평적 확장' 방식을 주로 선택한다. (물론 컴퓨터 사양을 높이는 수직적 확장을 병행할 수도 있다.)

  • 로드 밸런서(ELB) 필수 도입 : 서버가 여러 대가 되면 사용자에게 '알아서 나눠서 접속해라'라고 할 수 없으므로, 트래픽을 각 서버에 골고루 공평하게 분배해 주는 로드 밸런서를 반드시 도입해야 한다.
💡 6단계 : 데이터베이스(RDS)의 성능 개선 및 확장
  • 웹 서버가 늘어나면 수많은 요청이 DB로 몰리며 결국 DB에서 병목 현상이 발생한다.
  • DB의 병목은 아래의 순서대로 해결을 시도해야 한다.
    1. DB 자체 튜닝 (최우선) : 무작정 서버를 늘리기 전에 인덱스(Index) 활용, SQL 쿼리문 튜닝, 역정규화(테이블 설계 변경) 등을 통해 DB 내부적으로 먼저 성능 개선을 시도
    2. 수직적 확장 (Scale-up) : 튜닝으로도 안 되면 DB 컴퓨터의 사양을 높인다. (주의 : DB를 여러 대 두는 '수평적 확장'은 각 DB 간의 '데이터 동기화' 과정이 필수적인데, 이 동기화 작업이 오히려 DB 성능을 심각하게 저하시키기 때문에 우선순위에서 밀린다.)
    3. 읽기 전용 DB (Read Replica) 도입 : 실시간으로 완벽한 데이터 동기화가 필요 없는 쿼리(ex. 작성 후 몇 초 뒤에 보여도 상관없는 게시글 조회)를 분담시키기 위해 '읽기 전용 데이터베이스'를 추가로 도입하여 조회 트래픽을 분산시킨다.
    4. 캐시 서버 (Redis 등) 도입 : DB 사양을 계속 높이면 한 달에 천만 원 이상이 나갈 정도로 비용이 너무 비싸지므로. 비용 절감과 조회 속도 향상을 위해 데이터 조회 요청을 DB와 나눠서 처리해 주는 '캐시 서버'를 도입하여 DB의 부하를 줄이고 전체 스루풋을 상승시킨다.

🎯 [요약] 병목 지점 관점에서의 성능 개선 방법 정리
1. EC2 (웹 애플리케이션) 병목 발생 시
  • 서버 내 비효율적인 로직(ex. 무한 루프 등 CPU 낭비 코드)이 있는지 체크하고 개선하기
  • 정적 파일(S3) 서빙이 분리되어 있는지 확인하고 분리하기
  • 수평적 확장 (서버 개수 늘리기 + 로드 밸런서)
  • 수직적 확장 (서버 스펙 올리기)
2. DB (데이터베이스) 병목 발생 시
  • (최우선) 비효율적인 쿼리 개선 (인덱스 적용, SQL 튜닝, 역정규화 등)
  • 수직적 확장 (비용 고려 필요)
  • 읽기 전용 데이터베이스(Read Replica) 도입
  • 캐시 서버(Cache Server) 도입

참고 자료

1. youtube : [인프런] 대규모 트래픽 처리를 위한 부하 테스트 입문/실전

https://www.youtube.com/playlist?list=PLtUgHNmvcs6qAqWz-UhH-_ploSbK2eHwG

 

[인프런] 대규모 트래픽 처리를 위한 부하 테스트 입문/실전

풀버전 강의는 아래 링크를 참고해주세요😊✔ https://inf.run/f23VE

www.youtube.com

2. 블로그 : Grafana k6 - 터미널에서 5분만에 도입하는 부하테스트

https://innovation123.tistory.com/295

 

Grafana k6 - 터미널에서 5분만에 도입하는 부하테스트

이 글에서는 터미널에서 서버 성능 테스트를 아주 간편하게 할 수 있는 방안을 소개한다.작성자는 "k6 부하테스트"라는 단어를 처음 보고 나서 5분 내에 실제 부하테스트를 완료하고, 결과를 도

innovation123.tistory.com