사전 JMeter
구현체

JMeter

gabury1

JMeter 는 서버에 부하를 걸어 보는 프로그램입니다. 사람이 화면에서 대본을 짜 두면 그 대본을 여러 벌 동시에 돌려 요청을 쏟아붓습니다. 요청 하나하나가 얼마나 걸렸는지는 그때마다 기록해 둡니다. 아파치 소프트웨어 재단이 내놓는 자바 프로그램입니다.

쉽고 빠른 이해

JMeter 는 서버에 요청을 대량으로 쏟아부어 성능을 재는 프로그램입니다. 사람이 화면에서 짠 대본 하나를 여러 벌 동시에 돌려 요청을 쏟아냅니다.

서버가 사용자 여러 명이 한꺼번에 몰릴 때도 버티는지는 사람 손으로는 확인할 수 없습니다. 동시에 접속하는 사람 수를 실제로 흉내 내야 확인됩니다.

어떻게 도나:

  1. 화면에서 대본을 짜고 파일로 저장합니다
  2. 흉내 낼 사람 수만큼 그 대본을 동시에 처음부터 끝까지 돌립니다
  3. 요청마다 걸린 시간을 기록해 나중에 살펴봅니다

대가도 있습니다. 브라우저가 하는 화면 그리기와 자바스크립트 실행은 흉내 내지 않고, 여러 대의 서버로 나눠 걸어도 부하를 알아서 쪼개 주지는 않습니다.

상세

프로젝트 첫 페이지는 이 물건을 "기능 동작을 부하 테스트하고 성능을 측정하려고 설계된 100퍼센트 순수 자바 애플리케이션" 이라고 소개합니다. 원래 웹 애플리케이션을 테스트하려고 설계했지만 그 뒤 다른 테스트 기능으로 넓혔다고 적습니다. 설치는 배포판 압축을 원하는 디렉토리에 푸는 것이 전부이고, 자바 실행 환경이 제대로 깔려 있고 JAVA_HOME 환경변수가 잡혀 있으면 더 할 일이 없다고 문서가 적습니다.

가상 사용자 한 명이 스레드 하나

테스트 계획(앞서 말한 대본입니다)의 시작점은 스레드 그룹입니다. 이름 그대로 JMeter 가 테스트를 실행하는 데 쓸 스레드의 개수를 이 요소가 정합니다. 여기서 정하는 것은 셋입니다. 스레드 개수, 램프업 기간, 테스트를 몇 번 반복할지입니다.

램프업 기간은 정한 스레드를 전부 띄우기까지 얼마를 쓸지 알려 주는 값입니다. 스레드 10개에 램프업이 100초면 JMeter 는 10개를 다 띄우는 데 100초를 씁니다. 각 스레드는 앞 스레드보다 10초 뒤에 시작합니다. 스레드 30개에 램프업 120초면 뒤따르는 스레드마다 4초씩 밀립니다. 스레드 수가 늘어도 램프업 기간이 그만큼 늘지 않으면 스레드 사이 간격은 좁아집니다.

sequenceDiagram
    participant A1 as 사례A·스레드1
    participant A2 as 사례A·스레드2
    participant A3 as 사례A·스레드3
    participant B1 as 사례B·스레드1
    participant B2 as 사례B·스레드2
    participant B3 as 사례B·스레드3

    Note over A1,A3: 사례A — 스레드 10개 · 램프업 100초
    Note over A1: 0초
    Note over A2: 10초 = 100÷10
    Note over A3: 20초
    Note over B1,B3: 사례B — 스레드 30개 · 램프업 120초
    Note over B1: 0초
    Note over B2: 4초 = 120÷30
    Note over B3: 8초

램프업 기간을 스레드 수로 나눈 값이 곧 스레드 사이 간격입니다.

공식 튜토리얼은 이 칸을 "사용자 수(스레드라고 부릅니다)를 5로 올린다" 고 적습니다. 흉내 낼 사용자 한 명이 곧 스레드 하나라는 뜻입니다. 각 스레드는 테스트 계획 전체를 처음부터 끝까지, 다른 스레드와 완전히 독립해서 실행합니다. 여러 스레드를 두는 것이 서버 애플리케이션으로 가는 동시 연결을 흉내 내는 방법이라고 문서가 적습니다.

스레드 밑에는 샘플러가 걸립니다. 샘플러는 스레드가 실행하는 단위이고, 그 실행 결과 기록이 샘플입니다. 최소 구성은 테스트 계획과 스레드 그룹 하나, 샘플러 하나 이상입니다. 샘플러는 반드시 스레드 그룹 아래 놓이고, 화면의 테스트 계획 트리에 걸린 순서 그대로 스레드가 이를 실행합니다.

flowchart TD
    P["테스트 계획"] --> G["스레드 그룹 · 스레드 5개"]
    G --> T1["스레드 1"]
    G --> T2["스레드 2"]
    G --> Tn["… 스레드 5"]
    T1 --> S1["샘플러 순서대로(스레드 1 몫)"]
    T2 --> S2["샘플러 순서대로(스레드 2 몫)"]
    Tn --> Sn["샘플러 순서대로(스레드 5 몫)"]

스레드마다 살림이 따로입니다. JMeter 변수는 각 스레드에 지역이고, 한 스레드가 변수를 바꾸면 그 스레드의 사본만 바뀝니다. 스레드 사이에 값을 넘기려면 변수 대신 프로퍼티를 씁니다. 프로퍼티는 JMeter 전체에 전역이라, 한 스레드가 프로퍼티를 세우면 다른 스레드가 그 값을 읽습니다.

대본 저장

만든 대본은 파일로 저장합니다. 문서는 실행 전에 테스트 계획을 파일로 저장해 두기를 권합니다. 저장 파일의 확장자는 .jmx 입니다. JMeter 3.0 부터는 저장할 때마다 그 .jmx 를 자동으로 백업해 둡니다.

다루는 프로토콜

첫 페이지가 이 목록을 직접 냅니다. JMeter 가 무엇을 상대하는지 경계를 긋는 자리이기도 합니다.

갈래 문서가 적는 것
웹 HTTP(HyperText Transfer Protocol) · HTTPS. 자바 · NodeJS · PHP · ASP.NET 같은 구현 뒤쪽을 가리지 않습니다
웹서비스 SOAP(Simple Object Access Protocol) · REST(Representational State Transfer)
파일 전송 FTP(File Transfer Protocol)
데이터베이스 JDBC(Java Database Connectivity) 경유
디렉토리 LDAP(Lightweight Directory Access Protocol)
메시지 JMS(Java Message Service) 로 접근하는 메시지 지향 미들웨어
메일 SMTP(Simple Mail Transfer Protocol) · POP3(Post Office Protocol 3) · IMAP(Internet Message Access Protocol). 각각 보안 연결판 포함
명령 네이티브 명령이나 셸 스크립트
소켓 TCP(Transmission Control Protocol)
자바 자바 객체

포기한 것

프로토콜 수준 동작

문서에 「JMeter is not a browser」 라는 절이 따로 있습니다. JMeter 는 브라우저가 아니라 프로토콜 수준에서 동작합니다. 웹서비스나 원격 서비스 입장에서는 브라우저처럼, 정확히는 여러 대의 브라우저처럼 보이지만, 브라우저가 하는 동작을 전부 하지는 않습니다.

못 박아 둔 것이 둘입니다. HTML(HyperText Markup Language, 하이퍼텍스트 마크업 언어) 페이지 안의 자바스크립트를 실행하지 않습니다. 그리고 브라우저처럼 HTML 페이지를 렌더하지도 않습니다. 응답을 HTML 로 볼 수는 있지만 그 시간은 어떤 샘플에도 포함되지 않고, 한 번에 한 스레드의 한 샘플만 표시됩니다.

얻은 것은 요청 한 벌의 값이 화면 그리기 비용에 물들지 않는다는 것입니다. 대신 자바스크립트가 뒤늦게 쏘는 요청은 대본에 적어 두지 않는 한 나가지 않습니다.

GUI 모드와 CLI 모드

JMeter 를 실행하면 화면이 뜹니다. 그런데 문서는 그 화면으로 부하 테스트를 돌리지 말라고 적습니다. "GUI(Graphical User Interface, 그래픽 사용자 인터페이스) 모드는 테스트 스크립트를 만들 때만 써야 하고, 부하 테스트에는 CLI(Command Line Interface, 명령줄 인터페이스) 모드를 써야 한다" 는 문장이 실행 절에 붙어 있습니다. 시작 안내에도 "GUI 모드로 부하 테스트를 돌리지 마세요" 가 느낌표까지 달려 있습니다.

그래서 화면은 대본을 만들고 디버깅하는 자리로만 남습니다. 실제 부하는 -n 플래그를 준 명령줄 실행이 냅니다.

원격 테스트의 부하 분배

클라이언트 기계 한 대가 사용자를 충분히 흉내 내지 못할 때 원격 JMeter 엔진 여러 대를 한 클라이언트가 제어하는 방법이 있습니다. 그런데 그 방식은 부하를 쪼개 주는 것이 아닙니다. 화면의 스레드 계수도 그 화면을 띄운 기계에서 도는 스레드만 세고, 원격 엔진에서 띄운 스레드는 여기 들어가지 않습니다.

문서가 직접 적습니다. 같은 테스트 계획을 모든 서버가 돌리고, JMeter 는 서버들 사이에 부하를 분배하지 않으며, 각 서버가 계획 전체를 돕니다. 스레드를 1000개로 잡고 원격 서버를 6대 붙이면 스레드가 나뉘지 않고 서버마다 1000개씩 그대로 돌아 합계 6000개가 걸립니다. 원하는 총량을 서버 대수로 나눠서 적는 것은 대본을 쓰는 사람 몫입니다.

architecture-beta
    service client(server)[JMeter 클라이언트 · 계획 전체 1000스레드]

    group remote(cloud)[원격 서버 6대 · 각각 계획 전체 실행 · 합계 6000스레드]
    service s1(server)[서버1 · 1000스레드] in remote
    service s2(server)[서버2 · 1000스레드] in remote
    service s3(server)[서버3 · 1000스레드] in remote
    service s4(server)[서버4 · 1000스레드] in remote
    service s5(server)[서버5 · 1000스레드] in remote
    service s6(server)[서버6 · 1000스레드] in remote

    client:R -- L:s1
    client:R -- L:s2
    client:R -- L:s3
    client:R -- L:s4
    client:R -- L:s5
    client:R -- L:s6

같은 계획이 서버마다 그대로 복제되므로 스레드 총량은 나눠지지 않고 곱해집니다(1000×6=6000).

원격 모드는 같은 개수의 명령줄 테스트를 따로 돌리는 것보다 자원을 더 쓴다고도 적습니다. 서버 인스턴스를 많이 붙이면 클라이언트 쪽 JMeter 와 그 네트워크 연결이 과부하에 걸릴 수 있습니다.

예시

공식 튜토리얼의 웹 테스트 계획 한 벌

자리 값
스레드 그룹 이름 JMeter Users
사용자 수(스레드) 5
램프업 기간 1초
반복 횟수 2
서버 이름 jmeter.apache.org
첫 요청 경로 /
둘째 요청 경로 /changes.html

문서가 이 계획의 총량을 직접 셉니다. 사용자 5 × 요청 2 × 반복 2 = HTTP 요청 20건입니다. 서버 이름은 요청마다 적지 않고 HTTP 요청 기본값 요소에 한 번만 적어 둡니다. 그 요소는 요청을 보내라고 시키는 것이 아니라 빈칸을 채워 주는 자리입니다.

여기에 HTTP 쿠키 관리자를 스레드 그룹마다 하나씩 답니다. 그러면 스레드마다 자기 쿠키를 갖고, 그 쿠키를 그 스레드의 모든 HTTP 요청이 나눠 씁니다.

명령줄로 돌리기

jmeter -n -t my_test.jmx -l log.jtl -H my.proxy.server -P 8000

문서가 싣는 실행 예입니다. 명령줄 모드가 받는 주요 플래그의 뜻은 다음과 같습니다.

플래그 문서가 적는 것
-n JMeter 를 명령줄 모드로 돌린다
-t 테스트 계획이 든 .jmx 파일 이름
-l 샘플 결과를 기록할 .jtl 파일 이름
-j JMeter 실행 로그 파일 이름
-r 프로퍼티 remote_hosts 에 적힌 서버에서 테스트를 돌린다
-R 지정한 원격 서버 목록에서 테스트를 돌린다
-e 부하 테스트가 끝난 뒤 보고서 대시보드를 만든다
-o 그 대시보드를 만들 출력 폴더. 없거나 비어 있어야 한다
-H 프록시 서버 호스트 이름이나 IP(Internet Protocol, 인터넷 프로토콜) 주소
-P 프록시 서버 포트

문서는 자원 사용을 줄이는 요령도 따로 모아 둡니다. 그 목록의 첫 줄도 이 형태입니다.

jmeter -n -t test.jmx -l test.jtl

같은 목록이 함께 적는 것은 샘플 결과를 모아 보여주는 요소인 리스너를 되도록 적게 두라는 것, 그중 「View Results Tree」와 「View Results in Table」은 부하 테스트 도중에는 쓰지 말고 대본을 짜는 동안 디버깅에만 쓰라는 것, 결과를 XML(eXtensible Markup Language) 대신 CSV(Comma-Separated Values)로 내보내라는 것, 필요한 데이터만 저장하라는 것입니다.

원격 서버에서 돌리기

jmeter -n -t script.jmx -R server1,server2,…

원격 서버에서 시작할 때도 화면이 아니라 명령줄 클라이언트를 쓰라고 문서가 적습니다. -R 대신 -r 만 주면 프로퍼티 remote_hosts 에 정의된 서버에서 돕니다.

운영

스레드 수와 힙

스레드를 몇 개까지 돌릴 수 있는지는 하드웨어 능력과 테스트 계획 설계가 함께 좌우한다고 문서가 적습니다. 대상 서버가 응답을 얼마나 일찍 돌려주는지도 영향을 줍니다. 응답이 빠를수록 스레드가 반복을 더 자주 돌아 그만큼 JMeter 가 처리할 샘플이 늘기 때문입니다. 스레드 수를 제대로 잡지 못하면 결과가 틀리거나 부정확해질 수 있는데, 문서는 이 문제에 조율된 누락이라는 이름을 붙여 경고합니다. 그 이름이 가리키는 것이 정확히 무엇인지는 이 출처가 풀어 적지 않습니다.

큰 규모가 필요하면 여러 기계에서 명령줄 JMeter 인스턴스를 여러 개 돌리는 쪽을 고려하라고 권합니다. 스레드 생성을, 스레드 그룹에 걸어 둔 시작 대기 시간과 그 스레드의 램프업 시간이 다 지나 첫 샘플러를 실행하기 시작하는 시점까지 미루는 옵션도 있습니다. 동시에 활성인 스레드가 너무 많지만 않다면 총 스레드 개수를 아주 크게 잡을 수 있게 해 준다고 문서가 적습니다.

기본 힙(자바 프로그램이 다루는 객체를 담아 두는 런타임 메모리 영역)은 1기가바이트입니다. 문서는 이 값이 테스트 계획과 돌리려는 스레드 개수에 따라 충분하지 않을 수 있다고 적고, 자바 힙 크기를 올리라고 시작 안내에 넣어 두었습니다.

환경변수 기본값
HEAP 힙 1기가바이트에 메타스페이스(자바 클래스 정보를 담는 네이티브 메모리 영역, 자바 힙과는 별도입니다) 상한 256메가바이트
GC_ALGO JVM(Java Virtual Machine, 자바 가상 머신)의 가비지 컬렉션 알고리즘을 정합니다. 기본값은 -XX:+UseG1GC -XX:MaxGCPauseMillis=250 -XX:G1ReservePercent=20 입니다

JMeter 5.6.x 는 실행에 자바 8 이상을 요구하고 자바 17 이상을 권합니다. 다음 주요 판은 자바 17 이상을 요구하게 된다고 변경 이력이 예고합니다.

멈추는 자리

화면의 메뉴에는 멈추는 명령이 둘 있습니다.

명령 하는 일
Stop 가능하면 스레드를 즉시 멈춥니다. 많은 샘플러가 중단 가능이라 진행 중인 샘플도 일찍 끝날 수 있습니다
Shutdown 스레드에 지금 하던 일이 끝나면 멈추라고 요청합니다. 진행 중인 샘플은 끊지 않습니다

Stop 은 모든 스레드가 기본 제한 시간 안에 멈췄는지 확인합니다. 그 기본값은 5000밀리초, 곧 5초이고 프로퍼티 jmeterengine.threadstop.wait 로 바꿉니다. 가는 길은 다르지만 Stop 도 Shutdown 도 결국 같은 정지됨 상태로 모입니다.

이 두 명령은 화면 모드라야 메뉴로 내릴 수 있습니다. 명령줄 모드에는 메뉴가 없고 Control + . 같은 키 입력에도 반응하지 않아서, 대신 포트 하나를 열고 같은 명령을 기다립니다. 기본값은 4445 이고 프로퍼티 이름은 jmeterengine.nongui.port 입니다. 그 포트를 다른 JMeter 인스턴스가 이미 쓰고 있으면 다음 포트로 올라가며 jmeterengine.nongui.maxport 까지 시도합니다. 이 값의 기본은 4455 입니다.

결과 파일과 백업

결과를 어떤 형식으로 저장하고 대본을 어떻게 자동으로 백업해 둘지도 프로퍼티 값으로 정해져 있습니다.

프로퍼티 기본값 · 문서가 적는 것
jmeter.save.saveservice.output_format 결과 데이터를 어떻게 저장할지 정합니다. 값은 xml · csv · db 이고 지금 지원하는 것은 xml 과 csv 뿐입니다. 기본값은 csv 입니다
jmeter.gui.action.save.backup_on_save 테스트 계획을 저장할 때 .jmx 자동 백업을 켭니다. 저장 직전에 백업 디렉토리로 복사합니다
jmeter.gui.action.save.keep_backup_max_count 남겨 둘 백업 파일의 최대 개수입니다. 기본값은 10 입니다

백업 파일 이름은 저장하는 파일 이름 뒤에 자동으로 올라가는 판 번호를 붙여 만듭니다. test-plan.jmx 를 저장하면 백업 디렉토리에 test-plan-000012.jmx 같은 파일이 생깁니다.

프로퍼티를 고칠 때는 jmeter.properties 를 직접 고치지 말고 그 줄을 user.properties 로 복사해 거기서 값을 바꾸라고 문서가 권합니다. 다음 판으로 옮겨 갈 때가 수월해진다는 이유입니다.

관련 항목

성능 측정 개념

부하 테스트 · 가상 사용자 · 성능 · 처리량 · 지연 · 백분위수 · 램프업 · 조율된 누락

견주어지는 도구

k6 · 스레드 · 스레드 풀 · 프로세스

상대 프로토콜

HTTP · TCP · JDBC · JMS · LDAP · FTP · SMTP · SOAP · REST

딛고 선 바탕

자바 · JVM · 힙 · 가비지 컬렉션 · XML · CSV

다른 이름: Apache JMeter