Skip to content

test(S15P11A705-192): 로컬 스택 API 종단 검증 하네스를 추가한다 - #142

Merged
minyongP merged 23 commits into
devfrom
test/S15P11A705-192-api-verification-harness
Aug 1, 2026
Merged

test(S15P11A705-192): 로컬 스택 API 종단 검증 하네스를 추가한다#142
minyongP merged 23 commits into
devfrom
test/S15P11A705-192-api-verification-harness

Conversation

@minyongP

Copy link
Copy Markdown
Contributor

요약

로컬 스택 전체를 상대로 29개 API를 전수 호출하고 응답 계약과 DB 상태를 함께 검증하는 하네스를 loadtest/에 추가한다. Swagger로는 보이지 않는 비정규화·불변식(BD-20 record_count 등)을 SQL 두 겹이 대조하며, 전역 스윕이 찾은 기존 데이터 위반 4,696건은 전수 삼분류 결과 전부 시드 생성기 산물로 확정했다(코드 결함 0건).

Jira (필수)

  • 키: S15P11A705-192

변경 사항

  • loadtest/k6/ — 29개 엔드포인트 전수 시나리오(138 검사)와 공용 라이브러리(쿠키·CSRF·엔벨로프·기록기). CSRF는 서버가 매 응답 토큰을 회전시키므로 캐시하지 않고 항아리에서 매번 읽는다
  • loadtest/sql/verify-by-id.sql — k6가 만진 행만 지목 검증(BD-20·BD-08·BD-25·BD-11 파급·BD-33)
  • loadtest/sql/verify-invariants.sql — 전역 불변식 17종 스윕, owner 열로 back/ai 소유 분리
  • loadtest/tools/ — RS256 토큰 발급(openssl, k6는 RSA 서명 불가), 전용 테스트 회원 생성·정리(골든 id 보호 가드, 소셜 계정 동반 생성), 오케스트레이터 run.sh(전 과정 + trap 정리, [FAIL] 단언·미호출·스윕 오류·골든 훼손 전부 종료 코드 반영)
  • docs/backend/BI-32 구현 보고서(시드 원인 삼분류 근거 포함), WORKLOG 1줄
  • .gitignoreloadtest/artifacts/(서명 토큰·키 사본) 제외

테스트 / 검증

  • ./gradlew clean check --no-daemon — BUILD SUCCESSFUL (Java 소스 무변경, 기존 스위트 그대로)
  • DB 변경 시 PostgreSQL 통합 테스트 (해당 없음 — 스키마·Java 무변경)
  • migration 변경 시 빈 DB migration 테스트 (해당 없음)
  • API 계약 변경 시 관련 문서 갱신 — 계약 변경 없음, 하네스 문서는 loadtest/README.md·BI-32

RED/GREEN 증거 (하네스 자체의 TDD — 자세한 실행 기록은 BI-32):

  • RED: 각 조각을 만들기 전 실행 실패를 먼저 관측(파일 부재 → k6 module not found → 미호출 엔드포인트 목록 보고). 검출력 증명은 일부러 불정합을 주입해 확인 — record_count +7 조작을 지목 검증이, 활성 Context 전량 소프트 삭제를 BD-11 스윕이 잡았고 둘 다 원상 복원
  • GREEN: bash loadtest/tools/run.sh138/138 검사, 29개 전수, 지목 위반 0, 종료 코드 0, 골든 행 수 유지(6/25/7), 테스트 회원 정리 후 member 3007 복원
  • Regression: 전역 스윕 back_violations=4696은 하네스 쓰기(생성·교체·409→force 연쇄·탈퇴)가 존재하는 채로 매 실행 불변 — API 삭제·탈퇴 파급이 위반을 만들지 않음을 실측. 새 종료 코드 게이트는 실전에서 검증됨(합성 회원의 me/summary 500을 정확히 exit 1로 잡았고, 원인 수정 후 0)

배경

  • 티켓 본문은 "27개 전수"였으나 열거 시점 이후 dev에 탈퇴(feat(S15P11A705-65): 회원 탈퇴 구현 #120)·마이페이지 요약(feat(S15P11A705-200): 마이페이지 요약 조회 구현 #128)이 머지되어 실제 전수는 29개다. 티켓의 상위 목표(전수 검증)에 맞춰 확장했다
  • 전역 스윕이 찾은 4,696건(삭제된 Collection의 살아있는 연결 2,390 · 탈퇴 회원의 살아있는 Record 2,169 · 빈 Collection 137)은 위반 행 100%가 대량 더미 대역이고 API로 재현 불가 — 시드 생성기가 파급 규칙 없이 직접 INSERT한 산물이다. seed/는 개인 작업 폴더 자산이라 이 PR 범위 밖이며, 근거 전문은 BI-32에 있다

리뷰 포인트

  1. run.sh의 종료 코드 계약 — 계약 검사·지목 검증·스윕 실행 오류·골든 훼손은 실패, 전역 불변식 "위반 수"는 리포트만(기존 데이터 기준선 4,696 때문). 이 구분이 타당한지
  2. teardown-test-member.sql의 하드 삭제 범위 — ai.*는 SELECT-only 경계라 고아 행이 실행마다 남는다(README 「알려진 잔여물」). 수용 가능한 잔여인지

미결 / 후속

  • 부하 프로파일(smoke·average·stress·spike)은 2단계 — 에픽 S15P11A705-193 아래 별도 티켓 예정
  • 관측 2건 기록만: heavy 사용자 지도 응답 61KB(페이지네이션 없음), 검색 p95 415ms(FastAPI 왕복 포함)

🤖 Generated with Claude Code

@minyongP minyongP added the test 테스트 추가·수정 label Jul 31, 2026
@minyongP minyongP self-assigned this Jul 31, 2026
minyongP added 23 commits August 1, 2026 15:17
run.sh로 처음 전 과정을 실제로 돌려보니 k6 시나리오가 force 연쇄로 Collection을
지운 뒤 그 record_count를 지목 검증하면서 매번 거짓 위반이 났다 — 삭제된 행은
record_count가 더 갱신되지 않으므로 활성 연결 수(0)와 항상 어긋난다.
리베이스로 들어온 GET /v1/me/summary(#128)를 시나리오에 더하고, 그 검사가 드러낸
하네스 한계를 고쳤다 — SQL로 회원 행만 만들면 '소셜 계정 없는 활성 회원'이라는
API로 도달 불가능한 상태가 되고 summarize가 계약대로 500을 던진다. setup이 소셜
계정까지 만들어 실제 가입 결과와 같은 모양을 갖춘다. 전체 파이프라인 138/138, exit 0.
@minyongP
minyongP force-pushed the test/S15P11A705-192-api-verification-harness branch from f161d5a to f92e2bf Compare August 1, 2026 06:18
@minyongP
minyongP merged commit 2cf3964 into dev Aug 1, 2026
2 checks passed
@minyongP
minyongP deleted the test/S15P11A705-192-api-verification-harness branch August 1, 2026 06:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test 테스트 추가·수정

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant