최근 사내 서비스 유저가 점점 늘어나고 있습니다.
또한 대량 영업으로 한꺼번에 지점이 많아질 계획입니다.
서버가 버틸 수 있을까? 라는 의문이 들기 시작합니다.
따라서, 가상 유저를 만들어 가입하고 사용해보는 시나리오대로 진행시
서버가 버틸 수 있는지 테스트를 해보고자 합니다.
저희 팀이 선택한 툴은 Artillery
입니다.
Node서버에서 사용할 수 있는 Artillery는
간편하게 사용할 수 있는 기능과 유연성을 제공하여 개발자가 어플리케이션을 효과적으로 테스트할 수 있는 오픈 소스 라이브러리 입니다.
원했던 대로 가상유저, 시나리오, 리포트 페이지 등의 기능을 제공해 줍니다.
npm install -g artillery
npm으로 전역 설치를 해줍니다.
이때 주의할 점은 artillery는 최신 노드버전이 필요합니다.
에러가 뜬다면 nvm를 이용해 최신 노드버전을 설치하시면 됩니다.
앞서 말했듯이 Artillery는 시나리오 테스트를 지원합니다.
테스트 작성은 Json, yaml 파일 형식을 사용할 수 있는데요,
공식문서에는 yaml로 가이드가 나와있지만.. json이 더 친숙하고 편할 것 같아서
저는 json파일 형식을 사용했습니다.
"config": {
"target": "http://localhost:3001",
"phases": [{ "duration": 10, "arrivalRate": 2 }],
"defaults": {
"headers": {
"User-Agent": "Artillery"
}
},
"variables": { "pin": "1111", "cardData": "12341234" },
"processor": "./functions.js"
},
target : 테스트할 서버 주소
phases : 테스트할 요청시간과 비율을 정합니다.
function printLog(requestParams, response, context, ee, next) {
const { url, method } = requestParams;
const { statusCode, body } = response;
console.log(`[${method}] [${statusCode}] ${url}`);
return next();
}
module.exports = {
printLog,
};
커스텀 JS파일을 작성해서 진행상황 로그를 불러올 수 있습니다.
name : 시나리오 이름
flow : 시나리오에서 진행하는 테스트 동작을 순서대로 작성
capture: 응답으로 받은 데이터에서 다시 변수로 지정해서 뒤에 보내는 요청에 사용
match : 응답 데이터가 원하는 값이 오는지를 확인할 수 있다.
weight : 시나리오에대한 가중치, 이 값이 높으면 해당 시나리오는 더 많이 발생
예시 )
"scenarios": [
{
"flow": [
{
"post": {
"url": "/auth/kiosk/signUp",
"json": {
"hasAgreedMarketing": true,
"hasAgreedTerms": true,
"phone": "{{$randomNumber(10000000000,99999999999)}}",
"pin": null,
},
"capture": { "json": "$.result.jwtInfo.accessToken", "as": "accessToken" }
}
},
{
"get": {
"url": "/users/me",
"headers": { "Authorization": "Bearer {{accessToken}}" },
"capture": [
{ "json": "$.authCode", "as": "authCode" },
{ "json": "$.id", "as": "userId" },
{ "json": "$.phone", "as": "phone" }
],
"afterResponse": "printLog"
}
},
{
"post": {
"url": "/users/me/verify-code",
"headers": { "Authorization": "Bearer {{accessToken}}" },
"json": {
"phone": "{{phone}}",
"authCode": "{{authCode}}"
},
"afterResponse": "printLog"
}
},
{
"post": {
"url": "/users/me/set-pin",
"headers": { "Authorization": "Bearer {{accessToken}}" },
"json": {
"pin": "{{pin}}"
},
"afterResponse": "printLog"
}
},
{
"post": {
"url": "/users/me/deposit",
"headers": { "Authorization": "Bearer {{accessToken}}" },
"json": {
"money": 10000,
"payMethod": "CARD",
"storeId": "1"
},
"afterResponse": "printLog"
}
},
{
"post": {
"url": "/users/me/usages/v2",
"headers": { "Authorization": "Bearer {{accessToken}}" },
"json": {
"couponId": 4,
"funnel": "KIOSK",
"money": 10000,
"storeDeviceId": 1
},
"afterResponse": "printLog"
}
},
{
"get": {
"url": "/users/me/deposit/store/1",
"headers": { "Authorization": "Bearer {{accessToken}}" },
"capture": {
"json": "$.depositBalance",
"as": "depositBalance"
},
"afterResponse": "printLog"
}
},
{
"post": {
"url": "/users/me/usages/v2",
"headers": { "Authorization": "Bearer {{accessToken}}" },
"json": {
"funnel": "KIOSK",
"money": "{{depositBalance}}",
"storeDeviceId": 1
},
"afterResponse": "printLog"
}
},
{
"patch": {
"url": "/subscriptions/cancel-subscription/{{subscriptionId}}",
"headers": { "Authorization": "Bearer {{accessToken}}" },
"afterResponse": "printLog"
}
},
{
"delete": {
"url": "/users/me/user/{{userId}}",
"headers": { "Authorization": "Bearer {{accessToken}}" },
"afterResponse": "printLog"
}
}
]
}
]
artillery run --output report.json main.json
main.json
에 대한 시나리오를 시작하며,
report.json
이라는 리포트파일을 생성하게 됩니다.
artillery report report.json
해당 커맨드로 report를 html로 변환할 수 있습니다
Artillery를 이용한 시나리오 작성을 해보았습니다.
문법이랄 것도 없이 json파일로 작성하는 것이다보니 러닝커브가 높지 않다는 느낌을 받았습니다.
다음 계획은 staging 서버를 만들어서 부하테스트를 실제로 해보는 것입니다.