57. Artillery(2) (항해 65일차)

코이그·2023년 6월 6일

항해99

목록 보기
53/54

설치

// 전역 설치
npm install -g artillery@latest

// 프로젝트 설치
npm install -D artillery@latest

테스트 한번 작성해보자

온라인 쇼핑몰의 백엔드에서 동작하는 한 API의 성능을 테스트 한다고 가정해보자.

보통 온라인 쇼핑몰은 블랙프라이데이나 사이버먼데이와 같은 행사기간에 트래픽이 급증하는 현상이 발생한다.

백엔드가 위와 같은 대용량 트래픽을 무리 없이 처리할 수 있는지 확인할 수 있는 매우 좋은 방법은 사용자들이 실제로 어떤 행동을 할지 시뮬레이션을 해보는 것이다.

온라인 쇼핑몰에서 상품을 구매하려 할 때 사용자는 다음과 같은 행동들을 할 것이다.

  • 상품 키워드 검색
  • 상품 클릭
  • 상품 정보 읽기
  • 장바구니 추가

위의 동작들이 동시에 100명에 의해서 실행되도 잘 작동하는지 확인하고자 한다.

구성

대상 URL

테스트하고자 하는 URL.

config:
  target: "https://example.com/api"

로드 단계

각 단계마다 몇 명의 가상의 사용자를 생성할지, 얼마나 자주 요청을 보낼지 등을 정의하면 된다.

config:
  target: "https://example.com/api"
  phases:
    - duration: 60
      arrivalRate: 5
      name: Warm up
    - duration: 120
      arrivalRate: 5
      rampTo: 50
      name: Ramp up load
    - duration: 600
      arrivalRate: 50
      name: Sustained load

첫번째 단계: 백엔드를 웜업하는 (느린 증가)단계이다. 60초마다 5명의 가상 사용자를 백엔드로 보냄.
두번째 단계: 120초 동안 5명의 가상 사용자로 시작해서 매 초마다 수를 증가시켜 단계가 끝나는 피크에는 50명의 사용자를 보냄.
세번째 단계: 600초 동안 매 초마다 50명의 가상 사용자를 유지하는 지속적인 스파이크를 시뮬레이션.

외부파일에서 데이터 주입

상품 검색은 성능 테스트에서 확인할 섹션 중 하나다. 제품 검색과 같은 동적 콘텐츠에 접근할 때 시스템이 어떻게 처리하는지 확인하는 것이 좋다.

artillery에서는 외부 csv파일을 불러와서 시나리오의 변수로 주입시킬 수 있다.

// keywords.csv
computer
video game
vacuum cleaner
toys
hair dryer

위와 같은 파일이 있을 때

config:
  ...
  ...
  payload:
    path: "keywords.csv"
    fields:
      - "keyword"

payload 키로 불러올 수 있다.

  • path: csv파일의 경로
  • fields: 테스트 시나리오에서 사용하고자 하는 변수 이름 (파일의 한 줄에 값이 여러 개가 존재한다면 fields의 value값도 여러 개 선언할 수 있다)

시나리오

위에서는 테스트에 필요한 구성을 설정했다면 이제 실제로 가상의 사용자들이 어떤 과정을 거치면 좋을지 시나리오를 구상해볼 것이다.

각 가상 사용자들에 대해서 다양한 시나리오를 정의할 수 있고 각 시나리오는 한개 이상의 동작을 수행한다.

시나리오와 흐름 추가

테스트 스크립트에 scenarios를 추가해아한다.

scenarios:
  - name: "Search and buy"
    flow:
      - post:
          url: "/search"
          json:
            kw: "{{ keyword }}"
  • 가상 사용자마다 기본 URL에 대한 POST /search 요청을 생성한다.
  • 요청 바디에는 kw(JSON 객체)가 있어야 하고 config.payload의 키워드 중 하나로 설정한다.
    • 예를 들어 가상의 사용자 A는 { "kw": "toys" }를 요청으로 보내고, 가상의 사용자 B는 { "kw": "computer" }를 요청으로 보낸다.

응답받은 변수 사용

다음으로는 백엔드로부터 반환받은 결과값의 상세정보를 조회하는 것이다.

scenarios:
  .
  .
    - post:
      .
      .
      capture:
        - json: "$.results[0].id"
        as: "productId"
  • POST /search 요청을 보내면 백엔드는 키워드가 포함된 객체들을 배열로 반환해준다. 첫 번째 결과물의 ID만 필요하다고 했을 때 capture옵션을 사용하여 id 프로퍼티를 productId에 저장할 수 있다.

저장된 productIdGET /product/:productId/details 요청 등에 사용할 수 있다.

scenarios:
  .
  .
    - post:
      .
      .
    - get:
      url: "/product/{{ productId }}/details"

테스트 일시정지

가상의 사용자가 요청을 보낸 뒤 사이트에 머무르는 것을 시뮬레이션할 수 있다.

.
.
- get:
  url: "/product/{{ productId }}/details"
- think: 5
  • 위의 think: 5는 가장 최근 요청인 get 요청을 보낸 뒤 5초 동안 테스트가 일시정지된다.

시나리오 이어서..

상품을 장바구니에 추가하는 시나리오를 생각해보자. 이 동작을 수행하는 요청은 POST /cart이다. 요청 바디로 productId가 필요하다.

.
  .
    .
      - post:
          url: "/cart"
          json:
            productId: "{{ productId }}"

여기서 사용되는 productIdPOST /search 요청 때 캡쳐해둔 productId이다.

성능 테스트 실행

# search-and-add-to-cart.yml
config:
  target: "https://example.com/api"
  phases:
    - duration: 60
      arrivalRate: 5
      name: Warm up
    - duration: 120
      arrivalRate: 5
      rampTo: 50
      name: Ramp up load
    - duration: 600
      arrivalRate: 50
      name: Sustained load
  payload:
    path: "keywords.csv"
    fields:
      - "keyword"

scenarios:
  - name: "Search and buy"
    flow:
      - post:
          url: "/search"
          json:
            kw: "{{ keyword }}"
          capture:
            - json: "$.results[0].id"
              as: "productId"
      - get:
          url: "/product/{{ productId }}/details"
      - think: 5
      - post:
          url: "/cart"
          json:
            productId: "{{ productId }}"

위의 파일이 최종 테스트 스크립트이다.

테스트 실행 방법:artillery run search-and-add-to-cart.yml

profile
COYG🔴⚪

0개의 댓글