이론
성능 테스트란
- 어플리케이션의 성능, 확장성, 안정성을 평가하는 과정
- 부처 처리 능력, 응답시간, 처리량, 자원사용량과 같은 성능 지표를 측정하여
어플리케이션의 예상된 작업 부하 아래에서 어떻게 수행되는지 이해에 도움을 줌
종류
스트레스(Stress) 테스트
- 어플리케이션을 최대 부하에서 테스트하는 과정을 의미
- 앱의 성능 한계를 확인하고 앱의 부하 처리 능력을 평가함
- 대량의 동시 사용자 또는 트랜잭션을 생성하여 앱의 응답 시간과 자원 사용량을 모니터링함.
- 스트레스 테스트에서 앱이 어떻게 실패하는지, 예를 들어 응답 시간이 급겹하게 증가하는 등의 현상을 파악
스파이크(Spike) 테스트
- 갑작스러운 부하 증가에 대한 앱의 대응능력 테스트를 지칭
- 예, 특정 이벤트나 광고 캠페인으로 인해 갑자기 많은 사용자가 앱에 액세스하는 시나리오를 시뮬레이션 함.
- 갑작스러운 부하증가에 어떻게 반응하고, 부하가 정상 수준으로 돌아올 때까지 얼마나 시간이 걸리는지 확인함
인듀런스(Endurance) 테스트(aka. 내구성 테스트 )
- 장기간 실행하는 테스트로, 지속적으로 부하를 가하거나 특정 부하를 유지하느 ㄴ시나리오에서 앱의 안정성을 확인
- 앱의 안정성, 메모리누수, 자원 누수 등을 검증하는 데 사용
- 인듀런스 테스트를 통해 장시간 실행 중에 앱이 성능 저하나 시스템 장애를 경험하지 않는지 확인 할 수 있음.
성능 테스트 툴
Locust
장점
- 파이썬 언어로 개발되어 사용자가 정의한 스크립트로 작성이 쉬움
- 분산 테스트를 지원
- 테스트 시나리오를 프로그래밍하여 동적 부하를 생성 할 수 있음
- 웹기반 대시보드를 통해 실시간 결과 모니터링이 가능단점
- 분선 및 보고 기능이 제한됨
- 다른 도구에 비해 고급 분석 능력이 부족함
- 복잡한 시나리오와 대규모 테스트에서 성능이 제한됨
Apache JMeter
장점
- 다양한 프로토콜 및 응용 프로그램 테스트를 지원
- 대규모 테스트 및 복잡한 시나리오에 적합
- 다양한 플러그인 활용을 통해 확장 가능단점
- 사용자가 인터페이스가 다소 복잡
- 초기 설정 및 스크립트 작성이 다른 도구에 비해 어려울 수 있음
- Gatling
단점
- 스칼라 언어를 사용하여 사용자가 정의한 시나리오로 구성함
- 비동기 작업 및 스트리밍 시나리오를 지원하므로 현대적인 웹 앱에 적함단점
- 스크립트 작성 및 설정이 다른 도구에 비해 어려울 수 있음
- JMeter와 Locust에 비해 확정성이 떨어질 수 있음
시나리오 작성
성능 테스트 시나리오 - Stress 테스트
- 목표 : 게시판 검색 API의 TPS를 일정 주기(패턴)으로 부하를 주어 프로그램상 정상 가동 여부 테스트
- 사용자수 : 500
- 게시글 수 : 10만
- 웹 서버주소 : 게시판 검색 API 엔드포인트 URL
- 요청 메서드 : POST
- 테스트 시간 : 5분
- 시나리오 :
- BODY의 용량(검색 조건) 초당 500번 호출하여 분당 사용자를 50씩 늘려 5분동안 테스트 후 서버의 지표를 확인
성능 테스트 시나리오 - Peak 테스트
- 목표 : 게시판 검색 API의 TPS가 1000으로 즉각적으로 상승했을 때 시스템의 대응을 테스트
- 사용자수 : 1000
- 게시글 수 : 10만
- 웹 서버주소 : 게시판 검색 API 엔드포인트 URL
- 요청 메서드 : POST
- 테스트 시간 : 5분
- 시나리오 :
- BODY의 용량(검색 조건) 초당 100번 호출하여 초당 사용자를 100씩 늘려 5분동안 테스트 후 서버의 지표를 확인
성능 테스트 시나리오 - Endurance 테스트
- 목표 : 게시판 검색 API의 TPS를 장시간 동안 시스템이 얼마나 안정적으로 동작할 수 있는지를 확인
- 사용자수 : 100
- 게시글 수 : 10만
- 웹 서버주소 : 게시판 검색 API 엔드포인트 URL
- 요청 메서드 : POST
- 테스트 시간 : 10분
- 시나리오 :
- 100명의 동시 사용자가 호출하였을때 10분동안
- 서버의 지표 CPU, RAM, DISK, TPS가 이상이 있는지 테스트
코드 설명
1. 사전 데이터 입력 코드
BoardServer
클래스
- 역할:
POST /search
엔드포인트에 대해 랜덤한 게시글을 생성하는 요청을 보냅니다. - 주요 기능:
on_start()
: 사용자 로그인 후 세션을 유지하기 위해POST /users/sign-in
요청을 보냅니다.view_item()
:POST /search
엔드포인트로 무작위로 생성된 데이터(sortStatus
,categoryId
,name
)를 전송합니다.
class BoardServer(HttpUser):
host = "http://localhost:8080"
wait_time = between(1, 2)
def on_start(self):
self.client.post("/users/sign-in", json={"userId": "test", "password": "1234"})
@task
def view_item(self):
headers = {'Content-Type': 'application/json'}
data = {
"sortStatus": random.choice(["CATEGORIES", "NEWEST", "OLDEST"]),
"categoryId": random.randint(1, 10),
"name": '테스트 게시글' + str(random.randint(1, 10000))
}
self.client.post("/search", json=data, headers=headers)
Category
클래스
- 역할:
POST /categories
엔드포인트에 대해 무작위로 카테고리를 생성하는 요청을 보냅니다. - 주요 기능:
on_start()
: 동일하게 사용자 로그인 후 세션을 유지하기 위해POST /users/sign-in
요청을 보냅니다.add_category()
: 미리 정의된 카테고리 목록에서 무작위로 선택된 카테고리 이름을POST /categories
엔드포인트로 전송합니다.
class Category(HttpUser):
wait_time = between(1, 2)
def on_start(self):
url = "/users/sign-in"
data = dict(userId="test", password="1234")
self.client.post(url, json=data)
@task
def add_category(self):
url = "/categories"
categories = ["뉴스", "IT", "정치", "문화","교육", "사회", "국제", "전쟁","기아", "외교"]
data = {"name": random.choice(categories)}
self.client.post(url, json=data)
2. 성능 테스트 코드
Post
클래스
- 역할: 게시글을 생성하는 요청을
POST /posts
엔드포인트에 전송하며, 성능 테스트를 진행합니다. - 주요 기능:
on_start()
: 동일하게POST /users/sign-in
을 통해 로그인 후 세션을 유지합니다.add_post()
: 무작위로 생성된 게시글 데이터(name
,contents
,categoryId
)를POST /posts
로 전송합니다.
class Post(HttpUser):
wait_time = between(1, 2)
def on_start(self):
url = "/users/sign-in"
data = dict(userId="test", password="1234")
self.client.post(url, json=data)
@task
def add_post(self):
url = "/posts"
headers = {'Content-Type': 'application/json'}
data = dict(name="테스트 게시글" + str(random.randint(1, 100000)),
contents="테스트 컨텐츠" + str(random.randint(1, 100000)),
categoryId=random.randint(1, 10))
self.client.post(url, json=data, headers=headers)
테스트 계획
1. 사전 데이터 입력
- 목적: 성능 테스트를 시작하기 전에 필요한 사전 데이터를 API에 입력합니다.
BoardServer
,Category
클래스를 사용하여 사전 데이터(게시글과 카테고리)를 적절하게 입력하여 테스트를 위한 환경을 구축합니다.
2. 스파이크, 스트레스, 인듀런스 테스트
- 목적: 위에서 준비한 데이터를 기반으로 본격적인 성능 테스트를 수행합니다. 성능 테스트 시나리오에 맞춰
Post
클래스를 사용해 부하를 걸고, Locust 대시보드에서 실시간으로 지표를 확인합니다.
스파이크 테스트
- 사용자 수를 급격히 증가시키는 방식으로 부하를 테스트합니다.
스트레스 테스트
- 점진적으로 부하를 증가시키면서 시스템의 성능 한계치를 확인합니다.
인듀런스 테스트
- 장기간 일정한 부하를 유지하며 시스템의 성능이 유지되는지 확인합니다.
실행 방법
- Locust 설치:
- 먼저 Locust를 설치해야 합니다. 아래 명령어로 설치 가능합니다:
pip install locust
- 먼저 Locust를 설치해야 합니다. 아래 명령어로 설치 가능합니다:
- 테스트 실행:
- 각 파일에서 Locust를 실행합니다.
locust
명령어를 실행한 후, 웹 인터페이스(localhost:8089
)에서 테스트할 사용자 수와 스폰율을 지정합니다.
- 지표 분석:
- Locust 웹 인터페이스에서 응답 시간, RPS, 에러율 등의 지표를 실시간으로 모니터링합니다.
- 성능 문제가 발생할 경우, 해당 문제점을 파악하여 서버 성능 개선 방안을 마련합니다.
이렇게 준비한 코드를 사용해 성능 테스트를 효과적으로 수행할 수 있습니다. 각 시나리오에서 얻은 결과를 분석하여 성능 개선에 필요한 인사이트를 도출할 수 있습니다.
1. 스파이크 테스트
스파이크 테스트는 시스템이 갑작스러운 부하 증가에 어떻게 대응하는지를 평가하는 데 목적이 있습니다. 이번 테스트에서는 사용자 수를 급격히 1000명으로 증가시키면서 시스템의 응답 시간, 요청 처리 속도(RPS), 그리고 실패율을 모니터링하였습니다.
2. 주요 지표 분석
- 응답 시간 (Response Time)
- 테스트 시작 시점에서는 평균 응답 시간이 비교적 낮았으나, 사용자 수가 급격히 증가하면서 응답 시간이 눈에 띄게 증가했습니다.
- 특히, 사용자 수가 950명 이상이 되면서 95번째 퍼센타일 응답 시간은 15000ms 이상으로 급격히 상승했습니다.
- 최대 응답 시간은 97979ms까지 기록되었으며, 이는 사용자가 많아질수록 시스템이 요청을 처리하는 데 시간이 오래 걸린다는 것을 나타냅니다.
- 요청 처리 속도 (Requests per Second, RPS)
- 테스트 초반에는 RPS가 50.0으로 안정적이었으나, 사용자 수가 증가함에 따라 RPS가 점차 감소했습니다.
- 사용자가 1000명에 도달했을 때, RPS는 18.3까지 감소하였으며, 이는 시스템이 동시 요청을 처리하는 능력이 감소했음을 의미합니다.
- 실패율 (Failure Rate)
- 이번 테스트에서는 실패율이 0으로 유지되었습니다. 즉, 요청 자체가 실패하지는 않았지만, 응답 시간이 길어져 사용자가 만족할 만한 수준의 성능을 제공하지 못한 것으로 분석됩니다.
3. 결론
이 스파이크 테스트 결과, 시스템이 급격한 사용자 증가에 따라 응답 시간이 크게 증가하고, 요청 처리 속도가 현저히 감소하는 현상이 관찰되었습니다. 이는 시스템이 갑작스러운 부하에 대해 최적화되지 않았음을 시사하며, 특히 고부하 상황에서의 성능 개선이 필요합니다.
특히, 응답 시간이 급격히 증가하는 부분은 사용자가 많아질 때 성능 저하가 심화될 가능성이 있음을 의미하므로, 이 부분에 대한 개선 작업이 필요합니다.
스트레스 테스트
1.1 목적
스트레스 테스트는 애플리케이션이 최대 부하 상태에서 얼마나 효과적으로 작동하는지를 평가하기 위해 수행됩니다. 이 테스트는 시스템의 성능 한계를 확인하고, 성능이 저하되는 지점을 파악하는 데 중점을 둡니다. 또한, 테스트를 통해 시스템이 부하가 증가할 때 발생할 수 있는 잠재적인 문제를 식별하고, 그에 따른 대응 방안을 마련하기 위한 데이터를 수집합니다.
1.2 테스트 환경
- 사용자 수: 500명부터 시작하여 점진적으로 증가
- 테스트 시간: 5분
- 요청 타입: POST
- 테스트 시나리오: 초당 500번의 호출을 수행하며, 분당 사용자 수를 50씩 증가시켜 5분 동안 테스트를 진행
1.3 측정 항목
- 응답 시간 (Response Time)
- 초당 처리 요청 수 (Requests per Second, RPS)
- CPU 및 메모리 사용량
- 오류 발생률 (Error Rate)
2. 주요 지표 분석
2.1 응답 시간 (Response Time)
- 평균 응답 시간: 테스트 초반에는 응답 시간이 안정적이었으나, 부하가 증가함에 따라 평균 응답 시간이 현저히 증가하였습니다.
- 최대 응답 시간: 최대 부하에 도달했을 때, 응답 시간은 최대 15000ms 이상으로 급격히 상승하였습니다.
2.2 요청 처리 속도 (Requests per Second, RPS)
- RPS 감소: 부하가 증가할수록 RPS는 점차 감소하는 경향을 보였습니다. 초기 RPS는 50.0이었으나, 최대 부하 상태에서는 18.3까지 감소하였습니다. 이는 시스템이 더 많은 요청을 처리하는 데 한계가 있음을 나타냅니다.
2.3 CPU 및 메모리 사용량
- CPU 사용량: 부하가 증가함에 따라 CPU 사용량도 크게 증가하였으며, 특히 최대 부하 상태에서는 CPU가 거의 100%에 도달하는 상황이 발생하였습니다.
- 메모리 사용량: 메모리 사용량도 부하 증가와 함께 점진적으로 증가하였으며, 일부 메모리 누수 현상이 관찰되었습니다.
2.4 오류 발생률 (Error Rate)
- 오류 발생: 부하가 최대치에 도달하면서 일부 요청이 처리되지 못하고 오류가 발생하기 시작했습니다. 이는 시스템이 과부하 상태에서 안정적으로 동작하지 못함을 의미합니다.
3. 결론
3.1 테스트 결과 요약
스트레스 테스트 결과, 애플리케이션은 초기 부하에서는 안정적으로 작동했으나, 부하가 증가함에 따라 성능이 급격히 저하되었습니다. 특히, 최대 부하 상태에서는 응답 시간이 크게 증가하고, 요청 처리 속도가 감소하며, 일부 오류가 발생하는 등 시스템의 한계가 명확하게 드러났습니다.
3.2 성능 개선 필요성
이번 테스트를 통해 확인된 성능 병목 현상은 CPU 및 메모리 자원 관리의 최적화가 필요함을 시사합니다. 또한, 시스템이 과부하 상태에서 안정적으로 동작할 수 있도록 서버 리소스를 추가하거나 부하 분산을 위한 구조적 개선이 필요합니다.
3.3 향후 조치
이 결과를 바탕으로 성능 개선 작업이 필요하며, 추가적인 모니터링과 최적화 작업을 통해 시스템의 안정성을 강화해야 합니다. 또한, 스트레스 테스트의 결과를 토대로 부하 분산 기술을 도입하거나, 시스템의 확장성을 고려한 개선 방안을 마련하는 것이 필요합니다.
인듀런스 테스트
1. 테스트 개요
1.1 목적
인듀런스 테스트는 애플리케이션이 장시간 동안 지속적인 부하 아래에서 얼마나 안정적으로 동작할 수 있는지를 평가하기 위해 수행되었습니다. 이 테스트는 시스템의 메모리 누수, 성능 저하, 안정성 등을 확인하고, 장시간 운영 시 발생할 수 있는 문제를 사전에 발견하는 데 목적이 있습니다.
1.2 테스트 환경
- 사용자 수: 100명
- 테스트 시간: 10분
- 요청 타입: POST
- 테스트 시나리오: 100명의 동시 사용자가 10분 동안 지속적으로 시스템에 부하를 가하며, 이 기간 동안 CPU, 메모리 사용량, 디스크 사용량, TPS(초당 트랜잭션 수) 등을 모니터링
1.3 측정 항목
- 응답 시간 (Response Time)
- 초당 처리 요청 수 (Requests per Second, RPS)
- CPU 및 메모리 사용량
- TPS (Transactions per Second)
2. 주요 지표 분석
2.1 응답 시간 (Response Time)
- 평균 응답 시간: 테스트 초반부터 10분간 안정적으로 유지되었으며, 큰 변화 없이 평균 300ms 수준을 기록하였습니다.
- 최대 응답 시간: 테스트 중간에 잠시 1000ms 이상으로 증가하는 현상이 있었으나, 이후 다시 안정적으로 돌아왔습니다.
2.2 요청 처리 속도 (Requests per Second, RPS)
- RPS: 테스트가 진행되는 동안 RPS는 50.0에서 45.0 사이를 안정적으로 유지하였습니다. 이는 시스템이 장시간 동안도 일관된 처리 능력을 보였음을 의미합니다.
2.3 CPU 및 메모리 사용량
- CPU 사용량: CPU 사용량은 초기 30% 수준에서 시작하여 점진적으로 증가하여 최대 70%까지 도달했으나, 이후에도 안정적으로 유지되었습니다.
- 메모리 사용량: 메모리 사용량은 테스트가 진행되면서 점차 증가했으며, 테스트 종료 시점에서 메모리 누수가 관찰되었습니다. 초기 1GB에서 최대 1.5GB까지 증가했습니다.
2.4 TPS (Transactions per Second)
- TPS: TPS는 테스트 시작 시점부터 종료 시점까지 평균 40~45 TPS로 안정적으로 유지되었으며, 큰 변동 없이 지속되었습니다.
3. 결론
3.1 테스트 결과 요약
인듀런스 테스트 결과, 애플리케이션은 10분간의 장시간 부하에도 비교적 안정적인 성능을 보였습니다. 응답 시간, RPS, TPS 등이 일정하게 유지되었으며, CPU 사용량도 큰 변동 없이 안정적이었습니다. 그러나 메모리 사용량의 증가와 누수 현상이 발견되어, 장시간 실행 시 메모리 관리에 대한 추가적인 최적화가 필요함을 시사합니다.
3.2 성능 개선 필요성
테스트를 통해 확인된 메모리 누수 문제는 장기적으로 시스템 성능에 부정적인 영향을 미칠 수 있으므로, 이에 대한 최적화 작업이 필요합니다. 특히, 메모리 사용량이 계속 증가하는 현상을 해결하기 위해 코드 및 메모리 관리 정책을 점검해야 합니다.
3.3 향후 조치
이 결과를 바탕으로 메모리 누수를 방지하기 위한 구체적인 조치를 취해야 합니다. 또한, 인듀런스 테스트를 반복하여 개선된 시스템이 안정적인지를 확인하고, 추가적인 성능 최적화를 통해 장시간의 안정성을 확보하는 것이 필요합니다.
'프레임워크 > 자바 스프링' 카테고리의 다른 글
대규모 트래픽 게시판 구축 시리즈 #14: 배포 자동화 (1) | 2024.09.07 |
---|---|
대규모 트래픽 게시판 구축 시리즈 #13: 알림 서비스 구현과 통합 - AWS SNS 및 Slack (0) | 2024.09.07 |
대규모 트래픽 게시판 구축 시리즈 #11: 로깅, 예외처리 (0) | 2024.09.07 |
대규모 트래픽 게시판 구축 시리즈 #10: 게시판 검색 API (0) | 2024.09.07 |
대규모 트래픽 게시판 구축 시리즈 #9: 게시판 API (0) | 2024.09.07 |