대략의 SA 작성 및 MVP 설정 후, 각자 대용량 트래픽 처리와 관련된 키워드에 관한 공부를 시작하였다. 내가 현재 가장 관심이 가는 부분은 테스트와 모니터링 분야다. 물론 다른 것들에도 관심이 가지만 최우선으로 관심이 가는 키워드부터 먼저 콕 집어서 공부를 시작해볼 예정.
이전 글에서 테스트와 모니터링의 관계는 닭과 달걀의 관계라고 생각했다. 모니터링을 수행해야 해당 데이터를 바탕으로 테스트를 진행하고, 테스트를 수행함으로써 얻어낸 취약점을 지속적으로 모니터링하는 것이므로 결국 둘 다 익숙해져야 할 부분이라고 생각했다.
우선 키워드를 정리해보자. 물론 키워드는 추가될 수 있다.
테스트
JUnit, JMeter, nGrinder
모니터링
Prometheus, influxDB, Grafana
저 위의 개념들을 우선 특징들 기반으로 공부한 후, 어떤 것을 프로젝트에 투입하는 데에 선택할 지를 정리하는 것이 이번 포스팅의 목적이 되겠다.
이제까지의 프로젝트 구축은 일회성 단발 이벤트 형식으로 동작 과정을 확인하는 것에 그쳤다. 개념이 빈약한 상태로 억지로 개발에만 몰두해서 동작 과정이 순탄하게 흘러가면 그대로 프로젝트 종료를 선언하는 내 나태함 때문이려나.
그래서 더더욱 테스트 코드 작성을 비롯한 테스트와는 거리가 매우매우 멀었다. 테스트라는 것은 결국 지속 가능성을 확인하는 것이고 지속 가능성은 확장성의 전제 조건이 되므로 테스트의 중요성은 생략해도 한참 길지만... 아 힘들어
서버의 성능 테스트만이 아닌, 단순 자바 코드의 테스트를 수행할 수 있는 JUnit 역시 포함시켜서 차분히 알아볼 예정.
성능 테스트에는 꽤 다양한 종류가 있었다. 현재 정리하는 테스트는 4가지인데, 4가지 이외에도 다양한 테스트가 추가로 있는데 이 부분은 일단 개념 정리하면서 추후 보강해야겠다.
특정한 부하를 제한된 시간을 두어서 웹 어플리케이션에 이상이 없는지 파악하는 테스트이며, 통상 수행 시간은 1시간으로 둔다.
부하 테스트처럼 특정한 부하를 가하지만, 그 시간이 부하 테스트보다 길다. 위의 예시처럼 5시간 가량을 기준으로 테스트를 수행한다.
점진적으로 부하를 가하면서 시스템의 임계점을 찾고, 장애상황에서의 시스템 반응을 확인해서 복구가 잘 수행되는 것을 검증하는 테스트다.
일순간 서버의 감당 범위를 넘어서는 부하를 가하여 웹 어플리케이션이 죽지 않고 제대로 동작하고 회복하는지 보는 테스트이며, 특정 이벤트(우리의 프로젝트에 빗대자면 수강신청 날짜 등)에 대비하는 목적의 테스트다.
TPS
TPS(Transaction per second)는 성능 테스팅의 주요 지표로 활용되며, 일정 시간동안 얼마나 많은 요청을 처리할수 있는지를 나타낸다.
Time
서비스 사용 중의 시간을 뜻하나, 관점에 따라 정의가 달라진다.
위의 이미지에서 Think time은 사용자가 Response를 받고 이를 활용하는 시간(예를 들면,
GET
을 통해 불러온 게시글을 읽는 시간)이며, 이 부분은 서버의 성능과 무관하므로 테스트 대상에 포함시키지 않는다. 즉, 우리가 테스트로 고려할 부분은 Request time ~ Response time이다.
좀 더 자세히 파고들면, Request time에서 사용자가 요청을 보낸 그 직후부터 Response time에서 사용자가 응답을 받기 직전(네트워크의 개폐 시간)이 성능 테스트 대상이 된다.
Users
서버를 사용하는 사용자를 뜻하며, 성능 측면에서는 서버에 부하를 가할 수 있는 사용자를 뜻한다. 사용자의 종류에는 단순히 웹 페이지를 띄어놓기만 한, 언제든지 부하를 가할 사용자인 Concurrent user와, 특정 요청을 가하고 응답을 대기하는 사용자인 Active user가 있다. 둘 다 테스트 고려 대상이지만 우선 고려대상은 당연히 Active user가 될 것이다.
사실 JUnit은 서버 전반의 성능 테스트를 수행하기에는 부족하지만 자바의 단위 코드 및 최적화를 이끌어내기 위한 중요한 프레임워크다. 일반적으로 자바 기반 프로젝트의 테스트 기준은 클래스 혹은 메소드 단위로 정해지게 되는데, 이를 수행할 수 있는 도구가 JUnit이다.
특정 소스코드의 모듈이 정상적으로 동작하는지 확인하려는 목적으로 수행하고, 현재 대부분의 프로젝트 기반 프레임워크를 맡고 있는 Spring에서는 컨테이너가 관리하는 Bean이 JUnit 기반 테스트의 대상이 된다.
JUnit의 기본적인 특징은 아래와 같다.
- 현재 가장 많이 쓰이는 버전은 JUnit 5이다.
- JUnit 5는 3가지 이상의 모듈(= JUnit Platform + JUnit Jupiter + JUnit Vintage)로 구성되어 있다.
- 테스트 작성자를 위한 API 모듈과 테스트 실행을 위한 API가 분리되어 있다.
- Java 8 이상을 요구한다.
JUnit 5를 구성하는 모듈의 내용은 다음과 같다.
TestEngine
인터페이스를 정의, 기초적인 역할을 수행하며 TestEngine API를 제공한다.TestEngine
API 구현체다. Jupiter 모듈은 테스트 코드 작성에 필요한 junit-jupiter-api 모듈과 테스트 실행을 위한 junit-jupiter-engine 모듈로 분리되어 있다.TestEngine
이며, 하위 호환성을 위해서 존재한다.테스트 코드 작성은 org.junit.jupiter.api.Assertions
패키지에 위치한 Assertions
객체와 AssertJ
라이브러리를 통해 수행할 수 있다. 또한, 테스트 주도 개발(TDD)을 수행할 수도 있어서 꽤 중요하게 다룰 내용이라고 생각했다. JUnit에 대한 작성 문법은 참조 블로그 링크를 참고할 것.
JMeter는 아파치 재단에서 제공하는, 서버 부하 내구도 측정을 위한 성능 테스트 툴이다. Mac OS
사용자들은 homebrew
가 설치됐다면 빠르게 설치가 가능한 것 같다(오예)
자바 기반 오픈소스 데스크탑 애플리케이션이며 서버나 네트워크 또는 개체에 대해 과부하를 시뮬레이션하여 강도를 테스트하거나 다양한 부하 유형에서 전체 성능을 분석하는 데 사용할 수 있다.
후술할 nGrinder가 현재 자바 11까지 확장 지원되고, 프로젝트의 주력 버전으로 쓰일 자바 17과의 호환이 되지 않는 관계로 팀원들과의 테스트 방법을 논할 때 해당 툴에 대해 의견을 꺼내지 싶다.
주의! 여전히 JDK 8이 디폴트 지원값이며, JDK 11까지 확장된다. 즉, JDK 17과는 호환되지 않는다.
2024년 2월 14일에 작성된 버전 호환 오류 내용 포함 nGrinder 블로깅 포스트
https://curiousjinan.tistory.com/entry/ngrinder-script-write