Hurl 실전 활용 가이드: 다양한 예제와 응용 시나리오
- 기본 설치 및 시작하기
- 예제 1: 기본적인 HTTP GET 요청
- 예제 2: 응답 검증하기
- 예제 3: POST 요청 보내기
- 예제 4: 값 캡처 및 재사용
- 예제 5: 인증 처리
- 예제 6: 파일 업로드
- 예제 7: 쿠키 처리
- 예제 8: 복잡한 시나리오 테스트
- 예제 9: XML 응답 처리
- 예제 10: 환경별 설정 관리
- 예제 11: CI/CD 파이프라인 통합
- 예제 12: 성능 테스트 응용
- 예제 13: HTML 응답 테스트
- 예제 14: GraphQL 요청
- 예제 15: 데이터 기반 테스트
- Hurl의 고급 기능
- 실전 활용 시나리오
- Hurl 활용 팁
- 결론
- 참고 자료
- Keywords
Hurl은 HTTP 요청을 간단한 텍스트 형식으로 정의하고 실행할 수 있는 강력한 명령줄 도구입니다. 이 블로그에서는 개발자와 QA 엔지니어가 일상적인 작업에서 Hurl을 효과적으로 활용할 수 있는 다양한 실전 예제를 상세히 살펴보겠습니다.
기본 설치 및 시작하기
Hurl을 사용하기 전에 먼저 설치해야 합니다. 주요 운영체제별 설치 방법은 다음과 같습니다:
macOS (Homebrew 사용)
brew install hurl
Linux (Debian/Ubuntu)
curl -LO https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl_1.8.0_amd64.deb
sudo dpkg -i hurl_1.8.0_amd64.deb
Windows (Chocolatey 사용)
choco install hurl
설치가 완료되면 다음 명령으로 버전을 확인할 수 있습니다:
hurl --version
예제 1: 기본적인 HTTP GET 요청
가장 간단한 형태의 Hurl 파일은 다음과 같습니다:
# basic-get.hurl
GET https://api.github.com/users/torvalds
이 파일을 basic-get.hurl
로 저장한 후 다음 명령어로 실행합니다:
hurl basic-get.hurl
실행 결과로 GitHub API에서 반환한 JSON 응답이 표시됩니다.
예제 2: 응답 검증하기
Hurl의 강력한 기능 중 하나는 응답을 검증하는 기능입니다:
# validate-response.hurl
GET https://api.github.com/users/torvalds
# 상태 코드 검증
HTTP 200
# 헤더 검증
[Asserts]
header "Content-Type" contains "application/json"
header "Server" exists
# JSON 응답 검증
jsonpath "$.login" equals "torvalds"
jsonpath "$.id" greaterThan 1000
jsonpath "$.type" equals "User"
이 예제는 응답의 상태 코드, 헤더, JSON 내용을 검증합니다.
예제 3: POST 요청 보내기
데이터를 서버에 전송하는 POST 요청 예제입니다:
# post-request.hurl
POST https://httpbin.org/post
Content-Type: application/json
{
"name": "John Doe",
"email": "john.doe@example.com",
"message": "Hello from Hurl!"
}
HTTP 200
[Asserts]
jsonpath "$.json.name" equals "John Doe"
jsonpath "$.json.email" equals "john.doe@example.com"
예제 4: 값 캡처 및 재사용
이전 응답에서 값을 캡처하여 후속 요청에 사용하는 강력한 기능입니다:
# capture-and-reuse.hurl
# 첫 번째 요청: 모든 사용자 조회
GET https://jsonplaceholder.typicode.com/users
HTTP 200
[Captures]
user_id: jsonpath "$[0].id"
# 두 번째 요청: 캡처한 ID로 특정 사용자의 게시물 조회
GET https://jsonplaceholder.typicode.com/posts?userId={{user_id}}
HTTP 200
[Asserts]
jsonpath "$[0].userId" equals {{user_id}}
이 예제에서는 첫 번째 응답에서 사용자 ID를 캡처하고, 이를 두 번째 요청의 쿼리 파라미터로 사용합니다.
예제 5: 인증 처리
다양한 인증 방식을 처리하는 예제입니다:
기본 인증(Basic Auth)
# basic-auth.hurl
GET https://httpbin.org/basic-auth/user/passwd
[BasicAuth]
user: user
password: passwd
HTTP 200
[Asserts]
jsonpath "$.authenticated" equals true
OAuth 2.0 토큰 인증
# oauth-token.hurl
# 토큰 획득
POST https://auth-server.example.com/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=my-client&client_secret=my-secret
HTTP 200
[Captures]
access_token: jsonpath "$.access_token"
# 토큰 사용
GET https://api.example.com/protected-resource
Authorization: Bearer {{access_token}}
HTTP 200
예제 6: 파일 업로드
멀티파트 폼 데이터를 사용하여 파일을 업로드하는 예제입니다:
# file-upload.hurl
POST https://httpbin.org/post
[MultipartFormData]
field1: value1
field2: value2
file1: file,example.txt;text/plain
file2: file,image.jpg;image/jpeg
HTTP 200
[Asserts]
jsonpath "$.files" exists
예제 7: 쿠키 처리
쿠키를 설정하고 후속 요청에서 사용하는 예제입니다:
# cookie-handling.hurl
# 쿠키 설정
GET https://httpbin.org/cookies/set?cookie1=value1&cookie2=value2
HTTP 302
# 쿠키 확인
GET https://httpbin.org/cookies
HTTP 200
[Asserts]
jsonpath "$.cookies.cookie1" equals "value1"
jsonpath "$.cookies.cookie2" equals "value2"
예제 8: 복잡한 시나리오 테스트
여러 요청을 체이닝하여 복잡한 시나리오를 테스트하는 예제입니다:
# e-commerce-flow.hurl
# 1. 로그인
POST https://demo-shop.example.com/api/login
Content-Type: application/json
{
"username": "testuser",
"password": "password123"
}
HTTP 200
[Captures]
token: jsonpath "$.token"
user_id: jsonpath "$.user_id"
# 2. 상품 검색
GET https://demo-shop.example.com/api/products?query=laptop
HTTP 200
[Captures]
product_id: jsonpath "$.products[0].id"
# 3. 장바구니에 상품 추가
POST https://demo-shop.example.com/api/cart
Authorization: Bearer {{token}}
Content-Type: application/json
{
"user_id": "{{user_id}}",
"product_id": "{{product_id}}",
"quantity": 1
}
HTTP 201
[Captures]
cart_id: jsonpath "$.cart_id"
# 4. 주문 생성
POST https://demo-shop.example.com/api/orders
Authorization: Bearer {{token}}
Content-Type: application/json
{
"user_id": "{{user_id}}",
"cart_id": "{{cart_id}}",
"shipping_address": {
"street": "123 Test St",
"city": "Test City",
"zipcode": "12345"
}
}
HTTP 201
[Asserts]
jsonpath "$.order_status" equals "created"
jsonpath "$.payment_status" equals "pending"
예제 9: XML 응답 처리
XML 응답을 처리하고 검증하는 예제입니다:
# xml-handling.hurl
GET https://httpbin.org/xml
HTTP 200
[Asserts]
xpath "//title" equals "Sample Slide Show"
xpath "count(//slide)" equals "2"
xpath "//slide[@type='all']/title" equals "Wake up to WonderWidgets!"
예제 10: 환경별 설정 관리
개발, 테스트, 프로덕션 환경에 따라 다른 설정을 사용하는 예제입니다:
# api-test.hurl
GET {{base_url}}/api/users
HTTP 200
[Asserts]
jsonpath "$.length" greaterThan 0
이 파일을 실행할 때 변수를 주입하는 방법:
# 개발 환경
hurl --variable base_url=http://dev-api.example.com api-test.hurl
# 테스트 환경
hurl --variable base_url=http://test-api.example.com api-test.hurl
# 프로덕션 환경
hurl --variable base_url=http://api.example.com api-test.hurl
또는 환경 변수 파일을 사용할 수도 있습니다:
# dev.env
base_url=http://dev-api.example.com
api_key=dev-api-key
hurl --variables-file dev.env api-test.hurl
예제 11: CI/CD 파이프라인 통합
Jenkins, GitHub Actions 등의 CI/CD 파이프라인에 Hurl을 통합하는 예제입니다:
GitHub Actions 예제
# .github/workflows/api-test.yml
name: API Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Hurl
run: |
curl -LO https://github.com/Orange-OpenSource/hurl/releases/download/1.8.0/hurl_1.8.0_amd64.deb
sudo dpkg -i hurl_1.8.0_amd64.deb
- name: Run API Tests
run: hurl --test --glob "tests/**/*.hurl"
예제 12: 성능 테스트 응용
Hurl의 --retry
및 --retry-interval
옵션을 사용한 간단한 성능 테스트:
# performance-test.hurl
GET https://api.example.com/high-load-endpoint
HTTP 200
[Asserts]
duration lessThan 1000
실행 명령:
hurl --retry 10 --retry-interval 1000 performance-test.hurl
예제 13: HTML 응답 테스트
웹사이트의 HTML 응답을 테스트하는 예제입니다:
# html-test.hurl
GET https://example.com
HTTP 200
[Asserts]
header "Content-Type" contains "text/html"
xpath "//title" contains "Example Domain"
xpath "count(//a)" greaterThan 0
xpath "//h1" exists
예제 14: GraphQL 요청
GraphQL API에 요청을 보내는 예제입니다:
# graphql-request.hurl
POST https://api.github.com/graphql
Authorization: Bearer {{github_token}}
Content-Type: application/json
{
"query": "query { viewer { login name bio repositories(first: 5) { nodes { name url } } } }"
}
HTTP 200
[Asserts]
jsonpath "$.data.viewer.login" exists
jsonpath "$.data.viewer.repositories.nodes" count greaterThan 0
예제 15: 데이터 기반 테스트
CSV 파일의 데이터를 사용하여 여러 테스트 케이스를 실행하는 예제입니다:
users.csv
파일:
id,name,email
1,John,john@example.com
2,Jane,jane@example.com
3,Bob,bob@example.com
스크립트:
#!/bin/bash
while IFS=, read -r id name email
do
if [ "$id" != "id" ]; then # 헤더 행 건너뛰기
echo "Testing user $name"
hurl --variable id="$id" --variable name="$name" --variable email="$email" user-test.hurl
fi
done < users.csv
user-test.hurl
파일:
# 사용자 생성
POST https://api.example.com/users
Content-Type: application/json
{
"name": "{{name}}",
"email": "{{email}}"
}
HTTP 201
# 생성된 사용자 조회
GET https://api.example.com/users/{{id}}
HTTP 200
[Asserts]
jsonpath "$.name" equals "{{name}}"
jsonpath "$.email" equals "{{email}}"
Hurl의 고급 기능
조건부 실행
특정 조건이 충족될 때만 요청을 실행하는 예제입니다:
# conditional.hurl
GET https://api.example.com/feature-flags
HTTP 200
[Captures]
new_feature_enabled: jsonpath "$.features.new_feature"
# 새 기능이 활성화된 경우에만 실행
{% if new_feature_enabled == true %}
GET https://api.example.com/new-feature
HTTP 200
{% endif %}
SSL 검증 우회
개발 환경에서 자체 서명된 인증서를 사용할 때 유용합니다:
hurl --insecure api-test.hurl
상세한 로깅
디버깅을 위한 상세 로깅 활성화:
hurl --verbose api-test.hurl
JUnit 형식의 테스트 보고서 생성
CI/CD 파이프라인 통합을 위한 JUnit 형식의 보고서:
hurl --test --report-junit results.xml tests/**/*.hurl
실전 활용 시나리오
시나리오 1: API 회귀 테스트 자동화
개발 과정에서 API 변경으로 인한 회귀를 방지하기 위한 테스트 자동화:
# regression-tests/user-api.hurl
# 사용자 생성
POST https://api.example.com/users
Content-Type: application/json
{
"name": "Test User",
"email": "test@example.com"
}
HTTP 201
[Captures]
user_id: jsonpath "$.id"
# 사용자 조회
GET https://api.example.com/users/{{user_id}}
HTTP 200
[Asserts]
jsonpath "$.name" equals "Test User"
jsonpath "$.email" equals "test@example.com"
# 사용자 업데이트
PUT https://api.example.com/users/{{user_id}}
Content-Type: application/json
{
"name": "Updated User",
"email": "test@example.com"
}
HTTP 200
[Asserts]
jsonpath "$.name" equals "Updated User"
# 사용자 삭제
DELETE https://api.example.com/users/{{user_id}}
HTTP 204
시나리오 2: 마이크로서비스 통합 테스트
여러 마이크로서비스 간의 통합 테스트:
# integration-tests/order-flow.hurl
# 1. 제품 서비스: 제품 조회
GET {{product_service_url}}/products?category=electronics
HTTP 200
[Captures]
product_id: jsonpath "$.products[0].id"
product_price: jsonpath "$.products[0].price"
# 2. 사용자 서비스: 사용자 인증
POST {{auth_service_url}}/login
Content-Type: application/json
{
"username": "{{test_username}}",
"password": "{{test_password}}"
}
HTTP 200
[Captures]
token: jsonpath "$.token"
user_id: jsonpath "$.user_id"
# 3. 장바구니 서비스: 장바구니에 제품 추가
POST {{cart_service_url}}/carts
Authorization: Bearer {{token}}
Content-Type: application/json
{
"user_id": "{{user_id}}",
"product_id": "{{product_id}}",
"quantity": 1
}
HTTP 201
[Captures]
cart_id: jsonpath "$.cart_id"
# 4. 주문 서비스: 주문 생성
POST {{order_service_url}}/orders
Authorization: Bearer {{token}}
Content-Type: application/json
{
"user_id": "{{user_id}}",
"cart_id": "{{cart_id}}",
"total_amount": {{product_price}},
"shipping_address": {
"street": "123 Test St",
"city": "Test City",
"zipcode": "12345"
}
}
HTTP 201
[Captures]
order_id: jsonpath "$.order_id"
# 5. 결제 서비스: 결제 처리
POST {{payment_service_url}}/payments
Authorization: Bearer {{token}}
Content-Type: application/json
{
"order_id": "{{order_id}}",
"amount": {{product_price}},
"method": "credit_card",
"card_details": {
"number": "4111111111111111",
"expiry": "12/25",
"cvv": "123"
}
}
HTTP 201
[Asserts]
jsonpath "$.status" equals "completed"
# 6. 주문 서비스: 주문 상태 확인
GET {{order_service_url}}/orders/{{order_id}}
Authorization: Bearer {{token}}
HTTP 200
[Asserts]
jsonpath "$.status" equals "paid"
jsonpath "$.payment_status" equals "completed"
시나리오 3: 점진적 배포 검증
카나리 릴리스 또는 블루/그린 배포 검증:
# deployment-validation.hurl
# 현재 프로덕션 환경 검증
GET {{production_url}}/health
HTTP 200
[Asserts]
jsonpath "$.status" equals "ok"
jsonpath "$.version" equals "{{current_version}}"
# 새 배포 환경 검증
GET {{new_deployment_url}}/health
HTTP 200
[Asserts]
jsonpath "$.status" equals "ok"
jsonpath "$.version" equals "{{new_version}}"
# 핵심 기능 검증
GET {{new_deployment_url}}/api/critical-feature
HTTP 200
[Asserts]
jsonpath "$.working" equals true
duration lessThan 1000
Hurl 활용 팁
파일 구조화: 관련 요청을 하나의 파일로 그룹화하고, 테스트 목적에 따라 폴더를 구성합니다.
환경 변수 활용: 다양한 환경(개발, 테스트, 프로덕션)에서 실행할 수 있도록 환경 변수를 활용합니다.
CI/CD 통합: 빌드 및 배포 파이프라인에 Hurl 테스트를 통합하여 자동화된 API 검증을 구현합니다.
테스트 보고서 생성:
--report-junit
옵션을 사용하여 CI/CD 도구와 호환되는 테스트 보고서를 생성합니다.병렬 실행: 대규모 테스트 스위트의 경우 병렬 실행 스크립트를 작성하여 실행 시간을 단축합니다.
결론
Hurl은 간단한 텍스트 형식의 명령어로 복잡한 HTTP 통신을 테스트하고 자동화할 수 있는 강력한 도구입니다. 이 블로그에서 살펴본 다양한 예제를 통해 API 테스트, 통합 테스트, 배포 검증 등 다양한 시나리오에서 Hurl을 효과적으로 활용할 수 있음을 확인했습니다.
Hurl의 장점은 간결한 문법, 강력한 검증 옵션, 변수 캡처 및 재사용, CI/CD 통합 용이성 등 다양합니다. 이러한 기능을 활용하여 개발자와 QA 엔지니어는 더 효율적이고 안정적인 HTTP 기반 시스템을 구축할 수 있습니다.
참고 자료
Keywords
HTTP Testing Tool, Command-line Tool, API Testing, Text Format, Request Chaining, 응답 검증, 값 캡처, CI/CD 통합, RESTful API, GraphQL, XML 테스트, 마이크로서비스 테스트
'IT Best Practise > Network' 카테고리의 다른 글
Hurl: 효율적인 HTTP 테스트 및 통신 도구 (0) | 2025.04.02 |
---|---|
TCPDump 사용법: 설치부터 활용까지 (1) | 2024.11.11 |
TCPFlow 사용법: 설치부터 활용까지 (1) | 2024.11.11 |