test(lps): 부하테스트 상품셋 100종 카탈로그 분리 — 실제 입력 분포 재현

- loadtest/catalog.json 신설(실존 상품 100종): 규격만 54 · 모델포함 26 ·
  이름만 20 · 기준가 포함 7 (price→가격밴드 필터 경로 포함)
- loadtest.py 는 인라인 6종 대신 카탈로그 로드, 실행 시 구성 요약 출력

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
민헌 2026-07-10 10:50:28 +09:00
parent 5e485e9b6e
commit fbd2cec1da
2 changed files with 125 additions and 12 deletions

View File

@ -1,16 +1,23 @@
"""LPS 부하 테스트 — 여러 상품을 한 번에 제출하고 처리량·지연·비용을 집계한다.
여러 상품 동시 검색을 재현한다. 워커 동시성(WORKER_CONCURRENCY)만큼 상품이 병렬 처리된다.
python loadtest.py # 기본 상품셋
N=8 python loadtest.py # 상품 8개(기본셋에서 반복 확장)
python loadtest.py # 카탈로그 앞 6개
N=100 python loadtest.py # 상품 100개(loadtest/catalog.json 전체)
BASE=http://localhost:9600 python loadtest.py
상품셋 = loadtest/catalog.json (100종, 실존 상품): 규격만(식품·생활용품) / 규격+모델(가전·디지털)
/ 이름만 / 회사 포함 / 일부 기준가(price→가격밴드 필터 경로)를 섞어 실제 입력 분포를 재현한다.
N > 카탈로그 크기면 반복 확장. product_code 는 부하테스트 전용 프리픽스(LT###, 매회 유니크라
dedupe·네거티브캐시에 안 걸림).
측정: 벽시계 총시간, 처리량(상품/분), 상품별·집계 지연(p50/p95), AI·DECODO·총비용.
워커가 떠 있어야 하고, 워커 동시성이 낮으면 상품들이 큐에서 순차 대기한다(그게 부하의 핵심 관측).
"""
import asyncio
import json
import os
import pathlib
import time
import httpx
@ -18,15 +25,9 @@ import httpx
BASE = os.environ.get("BASE", "http://localhost:9600")
N = int(os.environ.get("N", "6"))
# 실제 매칭 잘 되는 상품셋(반복해서 N개로 확장). product_code 는 부하테스트 전용 프리픽스.
_CATALOG = [
{"product_name": "코카콜라 제로", "specification": "355ml 24캔"},
{"product_name": "농심 신라면", "specification": "1박스 40개입"},
{"product_name": "오리온 초코파이", "specification": "12개입"},
{"product_name": "제주 삼다수", "specification": "2L 12개입"},
{"product_name": "맥심 모카골드 커피믹스", "specification": "1박스 160개입"},
{"product_name": "스탠리 텀블러", "specification": "887ml"},
]
_CATALOG = json.loads(
(pathlib.Path(__file__).parent / "loadtest" / "catalog.json").read_text(encoding="utf-8")
)
def _products(n):
@ -37,6 +38,15 @@ def _products(n):
return out
def _composition(products) -> str:
"""상품셋 구성 요약 — 어떤 입력 분포로 테스트하는지 리포트에 남긴다."""
model = sum(1 for p in products if p.get("model"))
spec_only = sum(1 for p in products if p.get("specification") and not p.get("model"))
name_only = sum(1 for p in products if not p.get("specification") and not p.get("model"))
priced = sum(1 for p in products if p.get("price"))
return f"모델포함 {model} · 규격만 {spec_only} · 이름만 {name_only} · 기준가 포함 {priced}"
def _pct(values, p):
if not values:
return 0
@ -47,7 +57,8 @@ def _pct(values, p):
async def main():
products = _products(N)
print(f"■ 부하 테스트: 상품 {N}개 → {BASE} (워커 동시성만큼 병렬 처리)\n")
print(f"■ 부하 테스트: 상품 {N}개 → {BASE} (워커 동시성만큼 병렬 처리)")
print(f" 구성: {_composition(products)}\n")
async with httpx.AsyncClient(timeout=30) as c:
# 큐/헬스 사전 확인

102
lps/loadtest/catalog.json Normal file
View File

@ -0,0 +1,102 @@
[
{"product_name": "코카콜라 제로", "specification": "355ml 24캔", "price": "21000"},
{"product_name": "농심 신라면", "specification": "1박스 40개입", "price": "33000"},
{"product_name": "오리온 초코파이", "specification": "12개입"},
{"product_name": "제주 삼다수", "specification": "2L 12개입", "price": "13000"},
{"product_name": "맥심 모카골드 커피믹스", "specification": "1박스 160개입"},
{"product_name": "서울우유 멸균우유", "specification": "1L 10팩"},
{"product_name": "햇반 백미밥", "specification": "210g 24개입"},
{"product_name": "스팸 클래식", "specification": "200g 10캔"},
{"product_name": "카누 마일드 아메리카노 미니", "specification": "0.9g 100T"},
{"product_name": "동원 라이트스탠다드 참치", "specification": "100g 10캔"},
{"product_name": "크리넥스 데코앤소프트 3겹 화장지", "specification": "27m 30롤", "price": "24000"},
{"product_name": "다우니 섬유유연제 실내건조", "specification": "8.5L"},
{"product_name": "리스테린 쿨민트", "specification": "750ml 2개"},
{"product_name": "페리오 캐비티케어 치약", "specification": "160g 6개"},
{"product_name": "베베숲 시그니처 블루 물티슈", "specification": "70매 10팩"},
{"product_name": "백설 하얀설탕", "specification": "3kg"},
{"product_name": "오뚜기 진라면 매운맛", "specification": "120g 40개입"},
{"product_name": "롯데 빼빼로 오리지널", "specification": "54g 10갑"},
{"product_name": "매일 바이오 플레인 요거트", "specification": "450g 4개"},
{"product_name": "광동 옥수수수염차", "specification": "500ml 20병"},
{"product_name": "칠성사이다", "specification": "250ml 30캔"},
{"product_name": "롯데 레쓰비 마일드", "specification": "175ml 30캔"},
{"product_name": "농심 새우깡", "specification": "90g 20봉"},
{"product_name": "CJ 비비고 왕교자", "specification": "1.05kg 2개"},
{"product_name": "풀무원 국산콩 두부", "specification": "300g 4모"},
{"product_name": "청정원 순창 재래식 된장", "specification": "2kg"},
{"product_name": "오뚜기 3분 카레 약간매운맛", "specification": "200g 10개"},
{"product_name": "샘표 진간장 금F3", "specification": "1.7L"},
{"product_name": "케라시스 러블리 데일리 샴푸", "specification": "980ml 2개"},
{"product_name": "테크 액체세제 드럼겸용", "specification": "4.5L"},
{"product_name": "홈스타 맥스프레쉬 곰팡이싹", "specification": "900ml 2개"},
{"product_name": "3M 스카치브라이트 다목적 수세미", "specification": "10개입"},
{"product_name": "유한락스 레귤러", "specification": "1L 4개"},
{"product_name": "깨끗한나라 순수 소프트 3겹", "specification": "30m 30롤"},
{"product_name": "코멧 일회용 마스크 대형", "specification": "50매"},
{"product_name": "정식품 베지밀A 담백한맛", "specification": "190ml 24팩"},
{"product_name": "남양 프렌치카페 카페믹스", "specification": "162T"},
{"product_name": "크라운 참크래커", "specification": "280g 4개"},
{"product_name": "삼성전자 갤럭시 버즈2 프로", "model": "SM-R510", "specification": "블루투스 이어폰"},
{"product_name": "삼성전자 970 EVO Plus NVMe M.2 SSD", "model": "MZ-V7S1T0BW", "specification": "1TB"},
{"product_name": "삼성전자 T7 포터블 외장 SSD", "model": "MU-PC1T0T", "specification": "1TB"},
{"product_name": "로지텍 K380 멀티디바이스 블루투스 키보드", "model": "K380", "specification": "무선", "price": "33000"},
{"product_name": "로지텍 MX Master 3S 무선 마우스", "model": "MX Master 3S"},
{"product_name": "ipTIME 기가비트 유무선공유기", "model": "A3004T"},
{"product_name": "티피링크 무선 공유기", "model": "Archer AX53", "specification": "AX3000 Wi-Fi 6"},
{"product_name": "샤오미 미밴드 8", "model": "Mi Band 8", "specification": "스마트밴드"},
{"product_name": "애플 에어팟 프로 2세대", "model": "MTJV3KH/A", "specification": "USB-C", "price": "300000"},
{"product_name": "WD 마이 패스포트 외장하드", "model": "WDBYVG0020BBK", "specification": "2TB"},
{"product_name": "필립스 1000시리즈 전기면도기", "model": "S1121/41"},
{"product_name": "샤오미 미지아 전기면도기", "model": "S500"},
{"product_name": "쿠쿠 6인용 전기압력밥솥", "model": "CRP-P0610FD"},
{"product_name": "소니 노이즈캔슬링 헤드폰", "model": "WH-1000XM5"},
{"product_name": "소니 노이즈캔슬링 이어폰", "model": "WF-1000XM5"},
{"product_name": "벤큐 아이케어 모니터", "model": "GW2480", "specification": "24인치 FHD"},
{"product_name": "델 프로페셔널 모니터", "model": "P2422H", "specification": "24인치 FHD"},
{"product_name": "앱코 해커 기계식 키보드", "model": "K660", "specification": "청축"},
{"product_name": "레고 테크닉 부가티 시론", "model": "42083"},
{"product_name": "레고 클래식 라지 조립 박스", "model": "10698"},
{"product_name": "샤오미 공기청정기 4 라이트", "model": "AC-M17-SC"},
{"product_name": "다이슨 V15 디텍트 무선청소기", "model": "SV22"},
{"product_name": "보쉬 충전 드릴드라이버", "model": "GSR 12V-15"},
{"product_name": "고프로 히어로12 블랙", "model": "CHDHX-121"},
{"product_name": "삼성전자 흑백 레이저프린터", "model": "SL-M2030"},
{"product_name": "샌디스크 울트라 USB 3.0", "model": "SDCZ48-064G", "specification": "64GB"},
{"product_name": "다이슨 에어랩"},
{"product_name": "스탠리 퀜처 H2.0 텀블러"},
{"product_name": "닌텐도 스위치 OLED"},
{"product_name": "플레이스테이션5 슬림 디스크 에디션"},
{"product_name": "애플 매직 마우스"},
{"product_name": "갤럭시 워치7"},
{"product_name": "에어팟 맥스"},
{"product_name": "몰스킨 클래식 노트 라지 하드커버"},
{"product_name": "라미 사파리 만년필"},
{"product_name": "킨들 페이퍼화이트"},
{"product_name": "발뮤다 더 토스터"},
{"product_name": "네스프레소 버츄오 팝"},
{"product_name": "마샬 액톤3"},
{"product_name": "JBL 플립6"},
{"product_name": "인스타360 X4"},
{"product_name": "조지루시 스테인리스 보온병"},
{"product_name": "브리타 정수기 마렐라"},
{"product_name": "옥소 팝컨테이너"},
{"product_name": "루메나 무선 선풍기"},
{"product_name": "크록스 클래식 클로그"},
{"product_name": "진라면 순한맛", "company": "오뚜기", "specification": "120g 20개입"},
{"product_name": "초코송이", "company": "오리온", "specification": "36g 10개"},
{"product_name": "바나나맛우유", "company": "빙그레", "specification": "240ml 8개"},
{"product_name": "갈아만든배", "company": "해태htb", "specification": "1.5L 12병"},
{"product_name": "2080 진지발리스 치약", "company": "애경", "specification": "120g 5개"},
{"product_name": "자연퐁 솔잎 주방세제", "company": "LG생활건강", "specification": "1.2L 2개"},
{"product_name": "딱풀", "company": "아모스", "specification": "35g 5개"},
{"product_name": "하이테크C 볼펜", "company": "파이롯트", "specification": "0.4mm 검정"},
{"product_name": "모나미 153 볼펜", "company": "모나미", "specification": "0.7mm 12자루", "price": "4000"},
{"product_name": "포스트잇 노트 654", "company": "3M", "specification": "76x76mm 5패드"},
{"product_name": "곰표 밀가루 중력분", "specification": "1kg"},
{"product_name": "종가집 포기김치", "specification": "3.3kg"},
{"product_name": "동서 보리차 티백", "specification": "300g 30T"},
{"product_name": "락앤락 밀폐용기 세트", "specification": "10P"},
{"product_name": "델몬트 오렌지 주스", "specification": "1.8L 2병"},
{"product_name": "니베아 립케어 오리지널", "specification": "4.8g 2개"}
]