포스트

인프라 TA를 위한 구글 안티그래비티 성능 테스트 가이드

인프라 TA를 위한 구글 안티그래비티 성능 테스트 가이드

Terminal Agent 기반 성능 테스트 오케스트레이션


핵심 질문: 안티그래비티로 성능 테스트가 가능한가?

직접적인 답변

안티그래비티는 전통적인 성능 테스트 도구(JMeter, k6, Locust)가 아닙니다.

하지만 성능 테스트 오케스트레이션 플랫폼으로 강력하게 활용할 수 있습니다.

안티그래비티가 할 수 있는 것

1
2
3
4
5
기존 방식:
성능 테스트 스크립트 수동 작성 → 도구 실행 → 결과 수집 → 분석 → 리포트 작성

안티그래비티 방식:
자연어 지시 → AI가 스크립트 자동 생성 → 도구 자동 실행 → 결과 자동 분석 → 리포트 자동 생성

안티그래비티의 역할:

  1. 테스트 스크립트 자동 생성 (k6, Locust, JMeter)
  2. 인프라 자동 설정 (Docker, Kubernetes, 모니터링)
  3. 테스트 실행 오케스트레이션 (Terminal Agent)
  4. 결과 분석 및 시각화 (Grafana, Prometheus 통합)
  5. 리포트 자동 생성 (Markdown, HTML)

안티그래비티가 할 수 없는 것

  • 자체적으로 가상 사용자를 생성하여 부하 발생 (전문 도구 필요)
  • 실시간 부하 분산 (k6, Locust가 수행)
  • 복잡한 프로토콜 시뮬레이션 (JMeter가 수행)

결론: 안티그래비티는 성능 테스트의 자동화 레이어입니다.

안티그래비티의 Terminal Agent 이해

Terminal Agent란?

Terminal Agent는 안티그래비티가 시스템의 터미널(bash, PowerShell 등)에 접근하여 명령을 실행할 수 있게 해주는 기능입니다.

할 수 있는 것:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 패키지 설치
npm install k6
pip install locust --break-system-packages
apt install default-jre  # JMeter용

# 스크립트 실행
k6 run load-test.js
locust -f locustfile.py --headless -u 100 -r 10
jmeter -n -t test-plan.jmx -l results.jtl

# Docker 컨테이너 실행
docker run --rm -v $PWD:/app grafana/k6 run /app/script.js

# 모니터링 도구 실행
prometheus --config.file=prometheus.yml
grafana-server --config=/etc/grafana/grafana.ini

# 인프라 구성
terraform apply
kubectl apply -f k8s-config.yaml

보안 설정:

  • Auto 모드: 에이전트가 안전하다고 판단하면 자동 실행, 위험하면 승인 요청
  • Turbo 모드: Deny List에 없으면 모두 자동 실행
  • Off 모드: Allow List에 있는 것만 자동 실행

Terminal Agent vs 전통적 CLI

전통적 방식Terminal Agent
명령어를 정확히 기억해야 함자연어로 요청
옵션과 플래그를 수동 입력AI가 자동으로 적절한 옵션 선택
에러 발생 시 수동 디버깅AI가 에러를 읽고 자동 수정 시도
스크립트를 순차적으로 실행여러 에이전트가 병렬 실행

성능 테스트 도구 선택 가이드

주요 도구 비교

k6 (권장 - 안티그래비티와 가장 궁합이 좋음)

장점:

  • JavaScript로 스크립트 작성 (안티그래비티가 생성하기 쉬움)
  • CLI 기반으로 Terminal Agent와 완벽 호환
  • Grafana와 네이티브 통합 (시각화 용이)
  • 경량, 빠름, 리소스 효율적
  • CI/CD 통합 쉬움

단점:

  • HTTP/WebSocket 중심 (FTP, SMTP 등은 제한적)
  • GUI 없음 (하지만 안티그래비티가 보완)

사용 시나리오:

  • API 부하 테스트
  • 마이크로서비스 성능 검증
  • CI/CD 파이프라인 통합
  • 클라우드 네이티브 애플리케이션

안티그래비티 통합:

1
2
3
4
"API 엔드포인트 /api/users에 대해
100명의 가상 사용자가 1분 동안 요청하는
k6 스크립트를 작성하고 실행해줘.
결과를 Grafana로 시각화해줘."

Locust (Python 친화적)

장점:

  • Python으로 스크립트 작성
  • 웹 UI로 실시간 모니터링
  • 분산 테스트 쉬움
  • 유연한 사용자 시나리오 작성

단점:

  • k6보다 리소스 사용량 높음
  • 플러그인 생태계가 작음

사용 시나리오:

  • 복잡한 사용자 플로우 시뮬레이션
  • Python 기반 팀
  • 실시간 모니터링이 중요한 경우

안티그래비티 통합:

1
2
3
"로그인 → 상품 검색 → 장바구니 추가 플로우를
시뮬레이션하는 Locust 스크립트를 작성해줘.
500명의 동시 사용자, 분당 50명씩 증가."

JMeter (레거시 지원)

장점:

  • 가장 성숙한 도구
  • 다양한 프로토콜 지원 (HTTP, FTP, JDBC, SOAP 등)
  • 플러그인 생태계 방대

단점:

  • Java 기반, 무거움
  • GUI 의존적 (자동화 어려움)
  • 리소스 소비 많음

사용 시나리오:

  • 엔터프라이즈 환경
  • 다양한 프로토콜 테스트 필요
  • 기존 JMeter 인프라 존재

안티그래비티 통합:

1
2
3
"JMeter로 SOAP API 테스트 계획 생성해줘.
XML 파일 형식으로 저장하고
headless 모드로 실행해줘."

권장 선택 기준

상황도구
현대적 REST API 테스트k6
복잡한 사용자 시나리오Locust
다양한 프로토콜JMeter
CI/CD 통합 우선k6
팀이 Python에 익숙Locust
팀이 JavaScript에 익숙k6
레거시 시스템JMeter

실전 1: k6 기반 API 성능 테스트

시나리오: REST API 부하 테스트

목표: 사용자 인증 API가 초당 1,000 요청을 처리할 수 있는지 검증

전통적 방식 (수동)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 1. k6 스크립트 수동 작성 (load-test.js)
import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  stages: [
    { duration: '2m', target: 100 },
    { duration: '5m', target: 100 },
    { duration: '2m', target: 200 },
    { duration: '5m', target: 200 },
    { duration: '2m', target: 0 },
  ],
  thresholds: {
    http_req_duration: ['p(95)<500'],
  },
};

export default function () {
  const res = http.post('https://api.example.com/auth/login', {
    email: 'test@example.com',
    password: 'password123',
  });
  
  check(res, {
    'status is 200': (r) => r.status === 200,
    'response time < 500ms': (r) => r.timings.duration < 500,
  });
  
  sleep(1);
}
1
2
3
4
5
6
7
8
# 2. 수동으로 실행
k6 run load-test.js --out json=results.json

# 3. 결과 수동 분석
cat results.json | jq '.metrics'

# 4. 리포트 수동 작성
# (엑셀이나 Google Docs에서 작업)

안티그래비티 방식 (자동화)

Chat Panel에서:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
API 성능 테스트를 수행해줘:

엔드포인트: POST https://api.example.com/auth/login
목표:
  - 초당 1,000 요청 처리 능력 검증
  - 95 백분위수 응답 시간 < 500ms
  
테스트 시나리오:
  1. 2분간 100 사용자로 램프업
  2. 5분간 100 사용자 유지 (안정화)
  3. 2분간 200 사용자로 증가
  4. 5분간 200 사용자 유지 (피크)
  5. 2분간 0으로 램프다운

요청 바디:
  {
    "email": "test@example.com",
    "password": "password123"
  }

검증:
  - HTTP 상태 코드 200
  - 응답 시간 < 500ms (95%)
  - 에러율 < 1%

k6로 스크립트 작성하고 실행 후
결과를 HTML 리포트로 생성해줘.

에이전트가 수행하는 작업

Planning Artifact 생성:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
## k6 API 성능 테스트 계획

### 1. 환경 준비
- k6 설치 확인 (없으면 설치)
- 테스트 스크립트 생성

### 2. 스크립트 작성
- 파일명: load-test-auth-api.js
- 램프업/다운 로직
- 요청 정의
- 검증 체크
- 임계값 설정

### 3. 실행
- 명령어: k6 run load-test-auth-api.js --out json=results.json
- 실행 시간: 약 16분

### 4. 결과 분석
- results.json 파싱
- 주요 메트릭 추출
- HTML 리포트 생성

예상 소요 시간: 약 20분

Implementation:

  1. k6 설치 확인
    1
    2
    3
    4
    
    # Terminal Agent가 실행
    which k6 || brew install k6  # macOS
    # 또는
    which k6 || sudo snap install k6  # Linux
    
  2. 스크립트 자동 생성

파일: /home/claude/load-test-auth-api.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import http from 'k6/http';
import { check, sleep } from 'k6';
import { htmlReport } from 'https://raw.githubusercontent.com/benc-uk/k6-reporter/main/dist/bundle.js';

export const options = {
  stages: [
    { duration: '2m', target: 100 },   // Ramp-up to 100 users
    { duration: '5m', target: 100 },   // Stay at 100 users
    { duration: '2m', target: 200 },   // Ramp-up to 200 users
    { duration: '5m', target: 200 },   // Stay at 200 users
    { duration: '2m', target: 0 },     // Ramp-down to 0 users
  ],
  thresholds: {
    http_req_duration: ['p(95)<500'],  // 95% of requests under 500ms
    http_req_failed: ['rate<0.01'],    // Error rate under 1%
  },
};

export default function () {
  const url = 'https://api.example.com/auth/login';
  const payload = JSON.stringify({
    email: 'test@example.com',
    password: 'password123',
  });

  const params = {
    headers: {
      'Content-Type': 'application/json',
    },
  };

  const res = http.post(url, payload, params);

  check(res, {
    'status is 200': (r) => r.status === 200,
    'response time < 500ms': (r) => r.timings.duration < 500,
    'has token': (r) => r.json('token') !== undefined,
  });

  sleep(1);
}

export function handleSummary(data) {
  return {
    'summary.html': htmlReport(data),
    'summary.json': JSON.stringify(data),
  };
}
  1. 테스트 실행
    1
    2
    
    # Terminal Agent가 실행
    k6 run load-test-auth-api.js --out json=results.json
    
  2. 결과 자동 분석 및 리포트 생성

파일: /mnt/user-data/outputs/performance-test-report.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
<!DOCTYPE html>
<html>
<head>
  <title>API 성능 테스트 리포트</title>
  <style>
    body { font-family: Arial, sans-serif; margin: 40px; }
    .metric { background: #f5f5f5; padding: 20px; margin: 10px 0; }
    .pass { color: green; font-weight: bold; }
    .fail { color: red; font-weight: bold; }
    table { border-collapse: collapse; width: 100%; }
    th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
    th { background-color: #4CAF50; color: white; }
  </style>
</head>
<body>
  <h1>🚀 API 성능 테스트 리포트</h1>
  
  <div class="metric">
    <h2>테스트 개요</h2>
    <p><strong>엔드포인트:</strong> POST /auth/login</p>
    <p><strong>실행 시간:</strong> 2026-01-22 14:30:00</p>
    <p><strong>총 테스트 시간:</strong> 16분</p>
  </div>

  <div class="metric">
    <h2>전체 결과: <span class="pass">✅ PASS</span></h2>
    <p>모든 임계값이 충족되었습니다.</p>
  </div>

  <div class="metric">
    <h2>주요 메트릭</h2>
    <table>
      <tr>
        <th>메트릭</th>
        <th></th>
        <th>임계값</th>
        <th>결과</th>
      </tr>
      <tr>
        <td>총 요청 수</td>
        <td>96,000</td>
        <td>-</td>
        <td>-</td>
      </tr>
      <tr>
        <td>초당 요청 수 (RPS)</td>
        <td>1,024</td>
        <td>목표: 1,000</td>
        <td class="pass"></td>
      </tr>
      <tr>
        <td>평균 응답 시간</td>
        <td>245ms</td>
        <td>-</td>
        <td>-</td>
      </tr>
      <tr>
        <td>95 백분위수 응답 시간</td>
        <td>487ms</td>
        <td>< 500ms</td>
        <td class="pass"></td>
      </tr>
      <tr>
        <td>99 백분위수 응답 시간</td>
        <td>678ms</td>
        <td>-</td>
        <td>-</td>
      </tr>
      <tr>
        <td>에러율</td>
        <td>0.32%</td>
        <td>< 1%</td>
        <td class="pass"></td>
      </tr>
    </table>
  </div>

  <div class="metric">
    <h2>응답 시간 분포</h2>
    <img src="response-time-chart.png" alt="응답 시간 차트">
  </div>

  <div class="metric">
    <h2>권장사항</h2>
    <ul>
      <li>✅ API가 목표 성능(1,000 RPS)을 충족함</li>
      <li>⚠️ 99 백분위수가 678ms로 높음 - 데이터베이스 인덱스 최적화 권장</li>
      <li>✅ 에러율이 낮아 안정적임</li>
      <li>💡 피크 시간대 200 사용자까지 안정적으로 처리 가능</li>
    </ul>
  </div>
</body>
</html>

Walkthrough Artifact:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
## API 성능 테스트 완료

### 실행 요약
- ✅ k6 설치 확인
- ✅ 테스트 스크립트 생성
- ✅ 16분간 테스트 실행
- ✅ 96,000개 요청 완료
- ✅ 결과 분석 및 리포트 생성

### 주요 결과
**모든 임계값 통과 ✅**
- 초당 1,024 요청 처리 (목표 1,000 초과)
- 95% 응답 시간 487ms (목표 < 500ms)
- 에러율 0.32% (목표 < 1%)

### 생성된 파일
- load-test-auth-api.js (테스트 스크립트)
- results.json (원시 데이터)
- summary.html (k6 요약)
- performance-test-report.html (상세 리포트)

### 다음 단계
프로덕션 배포 준비 완료. 
필요 시 더 높은 부하(500 사용자) 테스트 권장.

실전 2: Locust 기반 시나리오 테스트

시나리오: E-commerce 전체 플로우

목표: 실제 사용자처럼 로그인 → 검색 → 구매하는 복잡한 플로우 성능 검증

안티그래비티 지시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Locust로 E-commerce 시나리오 테스트 수행:

사용자 플로우:
  1. 로그인 (POST /api/auth/login)
  2. 상품 검색 (GET /api/products?q=laptop)
  3. 상품 상세 조회 (GET /api/products/{id})
  4. 장바구니 추가 (POST /api/cart)
  5. 결제 (POST /api/checkout)

부하 설정:
  - 초기: 10 사용자
  - 증가율: 초당 5명
  - 최대: 500 사용자
  - 실행 시간: 10분

각 단계마다 1-3초 랜덤 대기 (실제 사용자 시뮬레이션)

Locust 스크립트 작성하고 실행 후
웹 UI로 실시간 모니터링 가능하게 해줘.

에이전트 생성 파일

locustfile.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from locust import HttpUser, task, between
import random

class EcommerceUser(HttpUser):
    wait_time = between(1, 3)  # 1-3초 랜덤 대기
    
    def on_start(self):
        """로그인 (모든 사용자가 시작 시 수행)"""
        response = self.client.post("/api/auth/login", json={
            "email": "test@example.com",
            "password": "password123"
        })
        self.token = response.json().get("token")
        self.headers = {"Authorization": f"Bearer {self.token}"}
    
    @task(5)  # 가중치 5 (가장 빈번한 작업)
    def search_products(self):
        """상품 검색"""
        queries = ["laptop", "phone", "headphone", "monitor"]
        query = random.choice(queries)
        self.client.get(f"/api/products?q={query}", 
                       headers=self.headers,
                       name="/api/products?q=[query]")
    
    @task(3)  # 가중치 3
    def view_product(self):
        """상품 상세 조회"""
        product_id = random.randint(1, 100)
        self.client.get(f"/api/products/{product_id}",
                       headers=self.headers,
                       name="/api/products/[id]")
    
    @task(2)  # 가중치 2
    def add_to_cart(self):
        """장바구니 추가"""
        product_id = random.randint(1, 100)
        self.client.post("/api/cart", 
                        json={"product_id": product_id, "quantity": 1},
                        headers=self.headers)
    
    @task(1)  # 가중치 1 (가장 드문 작업)
    def checkout(self):
        """결제"""
        self.client.post("/api/checkout",
                        json={
                            "payment_method": "credit_card",
                            "address": "123 Main St"
                        },
                        headers=self.headers)

실행 스크립트:

1
2
3
4
5
6
7
8
9
10
11
12
# Locust 설치
pip install locust --break-system-packages

# 실행 (웹 UI 포함)
locust -f locustfile.py --host=https://api.example.com \
       --users 500 --spawn-rate 5 --run-time 10m \
       --html locust-report.html

# 또는 headless 모드 (자동화용)
locust -f locustfile.py --host=https://api.example.com \
       --users 500 --spawn-rate 5 --run-time 10m \
       --headless --html locust-report.html --csv locust-stats

모니터링:

1
2
3
4
5
6
7
웹 UI가 http://localhost:8089에서 실행 중입니다.
실시간으로 다음을 확인할 수 있습니다:
- 현재 사용자 수
- 초당 요청 수 (RPS)
- 응답 시간 차트
- 실패율
- 각 엔드포인트별 통계

실전 3: 인프라 모니터링 통합

시나리오: Prometheus + Grafana 자동 설정

목표: 성능 테스트 중 서버 메트릭 실시간 모니터링

안티그래비티 지시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
성능 테스트를 위한 모니터링 스택을 구성해줘:

1. Prometheus 설정
   - k6 메트릭 수집
   - 서버 메트릭 수집 (CPU, 메모리, 네트워크)

2. Grafana 설정
   - Prometheus 데이터소스 연결
   - k6 대시보드 자동 import
   - 서버 메트릭 대시보드 생성

3. Docker Compose로 모두 실행

모든 설정 파일을 생성하고
한 명령어로 전체 스택을 시작할 수 있게 해줘.

에이전트 생성 파일

docker-compose.yml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
version: '3.8'

services:
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
      - GF_INSTALL_PLUGINS=grafana-k6-app
    volumes:
      - grafana-data:/var/lib/grafana
      - ./grafana-datasources.yml:/etc/grafana/provisioning/datasources/datasources.yml
      - ./grafana-dashboards.yml:/etc/grafana/provisioning/dashboards/dashboards.yml
    depends_on:
      - prometheus

  node-exporter:
    image: prom/node-exporter:latest
    container_name: node-exporter
    ports:
      - "9100:9100"
    command:
      - '--path.procfs=/host/proc'
      - '--path.sysfs=/host/sys'
      - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro

volumes:
  prometheus-data:
  grafana-data:

prometheus.yml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  # k6 메트릭 (k6를 --out experimental-prometheus-rw로 실행 시)
  - job_name: 'k6'
    static_configs:
      - targets: ['host.docker.internal:5656']

  # 서버 메트릭
  - job_name: 'node-exporter'
    static_configs:
      - targets: ['node-exporter:9100']
  
  # 애플리케이션 메트릭 (있다면)
  - job_name: 'app'
    static_configs:
      - targets: ['app-server:8080']

grafana-datasources.yml:

1
2
3
4
5
6
7
8
9
apiVersion: 1

datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://prometheus:9090
    isDefault: true
    editable: true

k6 실행 스크립트 (Prometheus 통합):

1
2
k6 run load-test.js \
  --out experimental-prometheus-rw=http://localhost:9090/api/v1/write

실행 가이드:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 전체 스택 시작
docker-compose up -d

# 상태 확인
docker-compose ps

# Grafana 접속: http://localhost:3000 (admin/admin)
# Prometheus 접속: http://localhost:9090

# k6 테스트 실행 (Prometheus에 메트릭 전송)
k6 run load-test.js \
  --out experimental-prometheus-rw=http://localhost:9090/api/v1/write

# 종료
docker-compose down

실전 4: CI/CD 통합

시나리오: GitHub Actions로 자동 성능 테스트

목표: 코드 배포 전 자동으로 성능 회귀 테스트

안티그래비티 지시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
GitHub Actions workflow를 만들어줘:

트리거:
  - main 브랜치에 PR 생성 시
  - nightly (매일 자정)

작업:
  1. 스테이징 환경 배포
  2. k6로 성능 테스트 실행
  3. 임계값 검증
  4. 실패 시 PR 차단
  5. 결과를 PR 코멘트로 게시
  
임계값:
  - 95% 응답 시간 < 500ms
  - 에러율 < 1%
  - 이전 결과 대비 응답 시간 10% 이상 증가 시 경고

에이전트 생성 파일

.github/workflows/performance-test.yml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
name: Performance Test

on:
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 0 * * *'  # 매일 자정

jobs:
  performance-test:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v3
      
      - name: Setup k6
        run: |
          sudo gpg -k
          sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
          echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
          sudo apt-get update
          sudo apt-get install k6
      
      - name: Deploy to Staging
        run: |
          # 스테이징 배포 로직
          ./deploy-staging.sh
        env:
          STAGING_API_KEY: $
      
      - name: Wait for deployment
        run: sleep 60  # 배포 완료 대기
      
      - name: Run k6 performance test
        run: |
          k6 run tests/performance/load-test.js \
            --out json=results.json \
            --env STAGING_URL=$
      
      - name: Parse results
        id: parse
        run: |
          # 결과 파싱 및 임계값 검증
          python3 scripts/parse-k6-results.py results.json > summary.txt
          
          # 이전 결과와 비교
          python3 scripts/compare-results.py results.json baseline.json > comparison.txt
      
      - name: Check thresholds
        run: |
          # 임계값 초과 시 실패
          if grep -q "THRESHOLD_EXCEEDED" summary.txt; then
            echo "❌ 성능 임계값 초과"
            exit 1
          fi
          
          # 10% 이상 성능 저하 시 경고
          if grep -q "PERFORMANCE_DEGRADATION" comparison.txt; then
            echo "⚠️ 성능 저하 감지"
          fi
      
      - name: Comment PR
        uses: actions/github-script@v6
        if: github.event_name == 'pull_request'
        with:
          script: |
            const fs = require('fs');
            const summary = fs.readFileSync('summary.txt', 'utf8');
            const comparison = fs.readFileSync('comparison.txt', 'utf8');
            
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `## 🚀 성능 테스트 결과\n\n${summary}\n\n### 📊 이전 결과 대비\n\n${comparison}`
            })
      
      - name: Upload results
        uses: actions/upload-artifact@v3
        if: always()
        with:
          name: performance-results
          path: |
            results.json
            summary.txt
            comparison.txt
      
      - name: Update baseline
        if: github.ref == 'refs/heads/main'
        run: |
          # main 브랜치 merge 시 baseline 업데이트
          cp results.json baseline.json
          git config user.name "GitHub Actions"
          git config user.email "actions@github.com"
          git add baseline.json
          git commit -m "Update performance baseline"
          git push

scripts/parse-k6-results.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import json
import sys

def parse_results(results_file):
    with open(results_file) as f:
        data = json.load(f)
    
    metrics = data['metrics']
    
    # 주요 메트릭 추출
    p95 = metrics['http_req_duration']['values']['p(95)']
    error_rate = metrics['http_req_failed']['values']['rate']
    rps = metrics['http_reqs']['values']['rate']
    
    # 임계값 검증
    thresholds_passed = True
    
    print("### 주요 메트릭")
    print(f"- **RPS**: {rps:.2f} requests/sec")
    print(f"- **P95 응답 시간**: {p95:.2f}ms")
    print(f"- **에러율**: {error_rate*100:.2f}%")
    print()
    
    if p95 > 500:
        print("❌ THRESHOLD_EXCEEDED: P95 > 500ms")
        thresholds_passed = False
    
    if error_rate > 0.01:
        print("❌ THRESHOLD_EXCEEDED: 에러율 > 1%")
        thresholds_passed = False
    
    if thresholds_passed:
        print("✅ 모든 임계값 통과")
    
    return thresholds_passed

if __name__ == "__main__":
    passed = parse_results(sys.argv[1])
    sys.exit(0 if passed else 1)

베스트 프랙티스

1. 테스트 환경 격리

1
2
3
4
프로덕션과 동일한 스펙의 스테이징 환경에서 테스트
- 프로덕션 데이터 사용 금지
- 별도의 데이터베이스 인스턴스
- 네트워크 분리

2. 점진적 부하 증가

1
2
3
4
❌ 나쁜 예: 0 → 1000 사용자 즉시
✅ 좋은 예: 0 → 100 → 300 → 500 → 1000 단계적 증가

이유: 시스템이 적응할 시간을 주고, 정확한 임계점 파악

3. 현실적인 시나리오

1
2
3
4
5
6
❌ 나쁜 예: 모든 사용자가 동일한 동작 반복
✅ 좋은 예:
  - 70% 브라우징만
  - 20% 검색 + 브라우징
  - 10% 구매까지 완료
  - 사용자마다 1-5초 랜덤 대기

4. 모니터링 필수

1
2
3
4
5
6
7
성능 테스트 중 반드시 모니터링:
- CPU 사용률
- 메모리 사용률
- 디스크 I/O
- 네트워크 대역폭
- 데이터베이스 커넥션 풀
- 응답 시간 분포

5. 베이스라인 유지

1
2
3
첫 테스트 결과를 베이스라인으로 저장
이후 모든 테스트를 베이스라인과 비교
10% 이상 성능 저하 시 자동 경고

안티그래비티 한계와 대안

안티그래비티가 어려운 것

  1. 매우 복잡한 분산 테스트
    • 수천 대의 머신에서 동시 실행
    • 대안: BlazeMeter, AWS DevOps Guru 같은 전문 플랫폼
  2. 실시간 대화형 조정
    • 테스트 중 실시간으로 부하 조정
    • 대안: Locust 웹 UI 직접 사용
  3. 매우 특수한 프로토콜
    • MQTT, CoAP, gRPC 등
    • 대안: 해당 프로토콜 전용 도구 + 안티그래비티로 스크립트 생성

권장 하이브리드 접근

1
2
3
4
1. 안티그래비티로 스크립트 초안 생성
2. 필요 시 수동으로 미세 조정
3. 안티그래비티로 실행 및 분석
4. 복잡한 경우 전문 도구 직접 사용

결론

구글 안티그래비티는 직접적인 성능 테스트 도구는 아니지만, 성능 테스트 자동화의 강력한 오케스트레이터입니다.

핵심 가치:

  1. 테스트 스크립트 작성 시간 90% 단축
  2. 인프라 설정 자동화
  3. 결과 분석 및 리포팅 자동화
  4. CI/CD 통합 간소화
  5. 여러 도구(k6, Locust, JMeter)를 통합 관리

인프라 TA의 역할 변화:

1
2
3
4
기존: 스크립트 작성 + 실행 + 분석 + 리포트
안티그래비티 활용: 요구사항 정의 + 검증 + 의사결정

저수준 작업은 AI에게, 고수준 판단은 사람이

시작하기:

  1. k6로 간단한 API 테스트부터 시작
  2. 안티그래비티에게 스크립트 생성 요청
  3. 결과 검토 후 점진적으로 복잡한 시나리오로 확장
  4. Workflow로 표준화하여 팀 전체 활용

성능 테스트의 미래는 “스크립트를 작성하는 것”이 아니라 “시스템의 성능 목표를 정의하고 검증하는 것”입니다. 안티그래비티는 그 전환을 가능하게 합니다.


문서 작성 일자: 2026-01-22

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.