From fbd2cec1dab8f74e01e21a57ba09ba643b81901f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AF=BC=ED=97=8C?= Date: Fri, 10 Jul 2026 10:50:28 +0900 Subject: [PATCH] =?UTF-8?q?test(lps):=20=EB=B6=80=ED=95=98=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=83=81=ED=92=88=EC=85=8B=20100=EC=A2=85?= =?UTF-8?q?=20=EC=B9=B4=ED=83=88=EB=A1=9C=EA=B7=B8=20=EB=B6=84=EB=A6=AC=20?= =?UTF-8?q?=E2=80=94=20=EC=8B=A4=EC=A0=9C=20=EC=9E=85=EB=A0=A5=20=EB=B6=84?= =?UTF-8?q?=ED=8F=AC=20=EC=9E=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - loadtest/catalog.json 신설(실존 상품 100종): 규격만 54 · 모델포함 26 · 이름만 20 · 기준가 포함 7 (price→가격밴드 필터 경로 포함) - loadtest.py 는 인라인 6종 대신 카탈로그 로드, 실행 시 구성 요약 출력 Co-Authored-By: Claude Fable 5 --- lps/loadtest.py | 35 ++++++++----- lps/loadtest/catalog.json | 102 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 12 deletions(-) create mode 100644 lps/loadtest/catalog.json diff --git a/lps/loadtest.py b/lps/loadtest.py index ab53050..dbdded2 100644 --- a/lps/loadtest.py +++ b/lps/loadtest.py @@ -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: # 큐/헬스 사전 확인 diff --git a/lps/loadtest/catalog.json b/lps/loadtest/catalog.json new file mode 100644 index 0000000..d7ffbc4 --- /dev/null +++ b/lps/loadtest/catalog.json @@ -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개"} +]