nGrinder란?
nGrinder는 Naver가 The Grinder를 기반으로 만든 엔터프라이즈급 부하 테스트 플랫폼입니다. 국내 대형 서비스에서 검증된 안정성과 웹 UI를 통한 편리한 관리가 특징입니다.
주요 특징
- 웹 기반 UI — 브라우저에서 스크립트 작성, 테스트 실행, 결과 확인
- 분산 테스트 기본 내장 — Controller + 다수의 Agent로 대규모 부하 생성
- Groovy/Jython 스크립트 — 유연한 시나리오 작성
- 스크립트 버전 관리 — SVN 기반 스크립트 저장소
- 실시간 모니터링 — TPS, 응답 시간, 에러율 실시간 그래프
아키텍처
| 컴포넌트 | 역할 | 포트 |
|---|---|---|
| Controller | 웹 UI 제공, 테스트 조율, 결과 수집 | 8080 (HTTP) |
| Agent | 실제 부하 생성 워커 노드 | 16001 (Controller 통신) |
| Monitor | 대상 서버의 CPU/메모리 모니터링 | 13243 |
Controller 1대 + Agent N대 구성으로 선형적으로 부하를 확장할 수 있습니다. Agent 1대당 일반적으로 500~2000 VU를 처리할 수 있습니다.
설치
Controller 설치
요구사항
- Java 11+ (OpenJDK 권장)
- 최소 4GB RAM (권장 8GB)
- 포트 8080 오픈
# nGrinder Controller WAR 다운로드
wget https://github.com/naver/ngrinder/releases/download/ngrinder-3.5.9/ngrinder-controller-3.5.9.war
# 실행 (기본 포트 8080)
java -jar ngrinder-controller-3.5.9.war
# 포트 변경
java -jar ngrinder-controller-3.5.9.war --port 8090
# 백그라운드 실행
nohup java -jar ngrinder-controller-3.5.9.war > ngrinder.log 2>&1 &bash
실행 후 http://localhost:8080에 접속합니다. 기본 계정: admin / admin
보안 주의: 프로덕션 환경에서는 반드시 기본 관리자 비밀번호를 변경하고, nginx 등 리버스 프록시 뒤에 배치하세요.
Agent 설치
# Controller 웹 UI에서 Agent 패키지 다운로드
# Admin 메뉴 → Download Agent
# 또는 직접 다운로드
wget https://github.com/naver/ngrinder/releases/download/ngrinder-3.5.9/ngrinder-agent-3.5.9-localhost.tar
tar -xf ngrinder-agent-3.5.9-localhost.tar
cd ngrinder-agent
# Agent 시작
./run_agent.sh
# Controller IP 지정
./run_agent.sh -ch CONTROLLER_IPbash
Agent가 성공적으로 연결되면 Controller 웹 UI의 Agent Management 페이지에서 확인할 수 있습니다.
Agent 설정 파일 (agent.conf)
# ~/.ngrinder_agent/agent.conf
agent.controller_host=192.168.1.100
agent.controller_port=16001
agent.region=NONEini
스크립트 작성
Groovy 기본 스크립트
웹 UI에서 Script → Create Script를 선택하거나, 아래 템플릿을 사용합니다.
import static net.grinder.script.Grinder.grinder
import static org.junit.Assert.*
import static org.hamcrest.Matchers.*
import net.grinder.script.GTest
import net.grinder.script.Grinder
import net.grinder.scriptengine.groovy.junit.GrinderRunner
import net.grinder.scriptengine.groovy.junit.annotation.RunWith
import net.grinder.scriptengine.groovy.junit.annotation.BeforeThread
import net.grinder.scriptengine.groovy.junit.annotation.BeforeProcess
import org.ngrinder.http.HTTPRequest
import org.ngrinder.http.HTTPResponse
import org.ngrinder.http.cookie.Cookie
import org.ngrinder.http.cookie.CookieManager
@RunWith(GrinderRunner)
class TestRunner {
public static GTest test
public static HTTPRequest request
public static Map headers = [:]
@BeforeProcess
public static void beforeProcess() {
HTTPRequestControl.setConnectionTimeout(300000)
test = new GTest(1, "testforge.kr")
request = new HTTPRequest()
grinder.logger.info("프로세스 초기화 완료")
}
@BeforeThread
public void beforeThread() {
test.record(this, "test")
grinder.statistics.delayReports = true
grinder.logger.info("스레드 초기화 완료")
}
@Test
public void test() {
HTTPResponse response = request.GET("https://testforge.kr/")
if (response.statusCode == 301 || response.statusCode == 302) {
grinder.logger.warn("리다이렉트: ${response.headers.location}")
}
assertThat(response.statusCode, is(200))
}
} groovy
고급 시나리오 — 로그인 후 API 호출
import static net.grinder.script.Grinder.grinder
import net.grinder.scriptengine.groovy.junit.annotation.*
import net.grinder.scriptengine.groovy.junit.GrinderRunner
import org.ngrinder.http.HTTPRequest
import org.ngrinder.http.HTTPResponse
@RunWith(GrinderRunner)
class ApiTestRunner {
public static HTTPRequest request
@BeforeProcess
public static void beforeProcess() {
request = new HTTPRequest()
}
@BeforeThread
public void beforeThread() {
// 스레드별 로그인 처리
def loginBody = '{"email":"test@example.com","password":"password123"}'
def loginRes = request.POST(
"https://api.example.com/login",
loginBody.bytes,
["Content-Type": "application/json"]
)
def token = parseJson(loginRes.text).token
request.headers["Authorization"] = "Bearer ${token}"
grinder.logger.info("로그인 성공, 토큰 획득")
}
@Test
public void getUsers() {
def res = request.GET("https://api.example.com/users")
assertThat(res.statusCode, is(200))
}
@Test
public void createUser() {
def body = '{"name":"LoadUser","email":"load@example.com"}'
def res = request.POST(
"https://api.example.com/users",
body.bytes,
["Content-Type": "application/json"]
)
assertThat(res.statusCode, is(201))
}
private static Map parseJson(String json) {
new groovy.json.JsonSlurper().parseText(json)
}
}groovy
테스트 실행
웹 UI에서 실행
- Quick Start 또는 Performance Test → Create Test
- 스크립트 선택 (SVN 저장소에서)
- 테스트 파라미터 설정:
| 파라미터 | 설명 | 예시 |
|---|---|---|
| Agent | 사용할 Agent 수 | 3 |
| Vuser per agent | Agent당 가상 사용자 수 | 100 (총 300 VU) |
| Script | 실행할 Groovy 스크립트 | api_test.groovy |
| Duration | 테스트 시간 (분) | 10분 |
| Run count | 각 VU의 반복 횟수 | Duration 또는 횟수 |
| Ramp-up | VU를 점진적으로 증가 | 초기 10, 단계 10, 간격 1분 |
모니터링
nGrinder Monitor 설치 (대상 서버)
# 부하 대상 서버에 Monitor 설치
wget https://github.com/naver/ngrinder/releases/download/ngrinder-3.5.9/ngrinder-monitor-3.5.9.tar
tar -xf ngrinder-monitor-3.5.9.tar
cd ngrinder-monitor
./run_monitor.shbash
Controller 웹 UI에서 테스트 실행 시 대상 서버의 IP를 Target Host에 입력하면 CPU, 메모리, 네트워크 I/O가 실시간으로 표시됩니다.
보고서
테스트 완료 후 자동으로 HTML 보고서가 생성됩니다. 포함 내용:
- 테스트 요약 (최대 TPS, 평균 응답 시간, 총 에러 수)
- TPS 시간 그래프
- 응답 시간 분포 (히스토그램)
- Agent/서버 리소스 사용률
Docker 배포
version: '3.8'
services:
controller:
image: ngrinder/controller:3.5.9
ports:
- "8080:8080"
- "9010-9020:9010-9020"
- "12000-12009:12000-12009"
volumes:
- ngrinder-controller:/opt/ngrinder-controller
restart: unless-stopped
agent:
image: ngrinder/agent:3.5.9
depends_on:
- controller
environment:
- CONTROLLER_ADDR=controller
deploy:
replicas: 3
restart: unless-stoppedyaml
실전 팁
Vuser 수 계산: 목표 TPS = Vuser 수 / 평균 응답 시간(초)
예: TPS 100 목표, 평균 응답 시간 0.5초 → Vuser 50개 필요
예: TPS 100 목표, 평균 응답 시간 0.5초 → Vuser 50개 필요
도구 비교
| 항목 | nGrinder | k6 | JMeter |
|---|---|---|---|
| 인터페이스 | 웹 UI | CLI | GUI + CLI |
| 스크립트 | Groovy / Jython | JavaScript | GUI + Groovy |
| 분산 테스트 | 기본 내장 ⭐⭐⭐⭐⭐ | k6 Cloud | 별도 설정 필요 |
| CI/CD 통합 | REST API | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
| 학습 곡선 | 중간 | 낮음 | 중간 |
nGrinder 추천 상황: 팀 내 비개발자도 테스트에 참여하거나, 분산 부하가 필수이고 웹 UI 기반 관리가 필요한 경우.
더 자세한 내용은 TestForge Docs에서 확인하고, 다른 도구와 비교는 k6 가이드 및 JMeter 가이드를 참고하세요.
더 자세한 내용은 TestForge Docs에서 확인하고, 다른 도구와 비교는 k6 가이드 및 JMeter 가이드를 참고하세요.