Pact contract testing, 계약 테스트 도입 판단 기준

Pact 계약 테스트, 도입할지 판단하는 기준

3줄 요약

  • 계약 테스트를 이번 분기에 넣어야 하는가 — 같은 주에 나온 일간 QA 리포트 4건이 서로 다르게 답했습니다.
  • 9월 18일자는 "MSA 전환 후 2단계 과제로 보류 권장", 9월 21일자는 "1순위 도입"이었고, 나흘 사이에 움직인 칸은 도구 평가가 아니라 유지보수 비용 한 칸이었습니다.
  • 이 답이 뒤집히는 조건으로 두 건이 함께 든 숫자는 서비스 경계 3개입니다. 19일자는 "3개 이상 분리 시 ROI 최상"이라는 도입 조건으로, 20일자는 "3개 이상 + 팀 간 배포 독립성 문제"라는 재검토 조건으로 각각 다르게 적었습니다.

"리드님, 계약 테스트 다음 분기에 넣는 걸로 정리된 거 맞죠?"

금요일에 이 질문을 받았고 저는 맞다고 답했습니다. 그런데 월요일 아침에 나흘 치 리포트를 나란히 펼쳐 놓고 보니 그 답의 근거가 흔들려 있었거든요. 같은 도구, 같은 팀 규모 전제, 같은 다섯 영역 구조인데 권고 칸만 반대로 뒤집혀 있었습니다.

먼저 밝혀 둡니다. 이 글은 지난주 주간 정리와 마찬가지로 자동 수집된 일간 QA 리포트 4건(9월 18일~21일)을 취합한 것인데요, 원문의 수치를 1차 소스로 다시 확인하지는 않았습니다. 각 리포트가 스스로 "독립 검증된 근거가 없습니다"로 표시한 수치는 아래 본문에서 뺐습니다.

1. 나흘 치 권고를 한 줄로 세우면 이렇습니다

Pact를 다룬 네 건의 판단 표만 뽑아 날짜순으로 붙였습니다.

날짜 도입 난이도 유지보수 비용 팀 학습곡선 4~6명 팀 권고
09-18 높음 중간 1~2개월 MSA 전환 후 2단계 과제로 보류 권장
09-19 중간 낮음 중간(개발팀 협조 필수) 서비스 3개 이상 분리 시 ROI 최상. 그 이하면 Postman/REST Assured로 충분
09-20 중간 중간(브로커 운영) 높음(양측 합의 필요) 보류. 서비스 경계 3개 이상 + 팀 간 배포 독립성이 문제될 때 재검토
09-21 중간(양측 코드 수정, Broker 운영 부담) 낮음(소비자 테스트 코드에서 계약 자동 생성) 중간(CDC 개념 이해 선행) 1순위 도입

나흘 사이에 같은 도구를 놓고 결론이 갈렸습니다. 네 건이 참조한 출처 목록은 일부만 겹쳤고, 각 리포트가 어느 칸에 무엇을 적었는지도 달랐습니다.

바뀐 칸은 유지보수 비용이었습니다

세 칸 중 권고 방향을 뒤집은 것은 유지보수 비용 한 칸입니다. 18일과 20일은 이 칸을 "중간"으로 적었고 그 근거로 브로커 운영 부담을 들었습니다. 19일과 21일은 같은 칸을 "낮음"으로 적었는데, 19일의 근거는 "계약 변경 시에만 갱신"이었고 21일은 "소비자 테스트 코드에서 계약이 자동 생성되므로 동기화가 자동 유지된다"였습니다.

둘은 서로 다른 것을 재고 있습니다. 전자는 인프라 운영 비용이고 후자는 계약 문서의 갱신 비용입니다. 한쪽은 서버를 세워야 하는 일이고 다른 쪽은 코드를 고치면 따라오는 일이라, 같은 칸에 들어갈 수 없는 값이 같은 칸에 들어간 셈입니다. 계약 테스트 개요 문서가 네 건 중 세 건(18·20·21일)에 공통 출처로 잡혀 있는데도 결론이 갈린 이유가 여기 있다고 봅니다.

도입 난이도는 한 번만 움직였습니다

반대로 도입 난이도 칸은 18일의 "높음"을 빼면 나흘 내내 "중간"이었습니다. 학습곡선도 19일과 21일이 "중간", 20일이 "높음"으로 한 단계 안에서만 흔들렸습니다.

그러니까 흔들린 것은 도구에 대한 평가가 아니라 무엇을 비용으로 셀 것인가였습니다. 브로커를 비용으로 세면 보류 쪽으로 기울고, 계약 갱신만 세면 조건부 권장(19일)에서 1순위 도입(21일)까지 올라갑니다. 우리 팀의 답은 리포트가 아니라 "우리가 Broker를 직접 운영할 것인가"에서 나옵니다.

2. 나흘 내내 돌아온 주제와 그 안에서 달라진 것

날짜별로 다시 요약하는 대신, 되돌아온 주제와 그 서술이 달라진 지점만 추렸습니다.

반복 주제 등장 일수 주 안에서 달라진 지점
API 계약·스키마 검증 우선 4일 18일은 스키마 검증이 1순위·Pact가 2단계, 21일은 계약과 스키마를 함께 PR 게이트에 거는 구성
Self-healing과 AI 에이전트 4일 18일은 "유지보수 구간의 첫 적용점", 20일은 "후순위"
Appium 중심의 앱 자동화 후순위 4일 Flaky 수치의 기준선이 날짜마다 다름(3절). 메이저 버전 표기도 18·20일 2.x/2.0, 19·21일 3/3.0으로 갈림
Shift-Left와 Shift-Right 결합 4일 21일에 "연속 검증"으로 합쳐지며 카나리·피처플래그 판단 체계로 흡수
Playwright 버전 표기 3일 18·19일 v1.62(2026-07), 21일 1.62.1(2026-07-30)

API 계약·스키마 검증은 네 건 전부에 있었습니다

네 건 전부에 나온 주제는 위 표의 앞 네 줄입니다. 그중 실무 순서가 가장 또렷한 것은 첫 줄인데, 18일자가 제시한 순서가 구체적이라 그대로 옮겨 둡니다. OpenAPI 스키마 검증을 CI에 넣는 일(1~2주, 비용 거의 0) → 핵심 API 3~5개 계약 테스트 → 관측성 기반 합성 모니터링 → 카오스 엔지니어링입니다.

21일자는 여기에 PR 단계 린팅을 한 겹 더 붙였습니다. Spectral로 OpenAPI 규약 준수를 PR 리뷰에서 강제하고, 스테이징에서는 스키마 드리프트 탐지를 상시 가동하는 구성입니다. 21일자는 이 항목을 두고 "오늘 항목 중 세 칸이 모두 낮은 유일한 조합"이라고 적었습니다. 다만 네 건 전체로 넓히면 19일자의 Playwright, 20일자의 OpenAPI 스키마 검증도 같은 조합이므로 21일자 안에서의 평가로 읽어야 합니다.

Playwright 버전은 21일자 표기를 따릅니다. 같은 출처 계열에서 날짜가 더 뒤인 값이라 1.62.1(2026-07-30)로 적었고, 18·19일의 v1.62는 같은 계열의 이전 표기로 봅니다.

단발로 끝난 것은 표 한 줄로만 남겼습니다

하루만 나오고 사라진 항목이 여럿이었습니다. 19일자의 TestGuild AG2026 설문(Playwright와 Selenium의 채택률 역전), 20일자의 ISO/IEC TR 29119-11, 21일자의 커리어 트랙 5종 분화가 그렇습니다. 날짜가 못박힌 사실도 아니고 이번 주 판단을 바꾸지도 않아서 본문에서는 다루지 않았습니다.

AI 채택률과 멀티 프레임워크 병행 비율 수치도 뺐습니다. 19일자가 해당 수치에 대해 "벤더 블로그 기반이며 원 설문의 표본·정의가 공개되지 않았다"고 스스로 적어 두었기 때문입니다. 18일자가 인용한 통합 환경 복잡도 감소치도 같은 리포트가 "벤더 주장이며 미검증"으로 표시해 제외했습니다.

3. Appium Flaky 수치가 날짜마다 다릅니다

앱 자동화를 뒤로 미루라는 권고는 네 건이 일치했습니다. 그런데 근거로 든 숫자가 서로 달랐습니다.

날짜 수치 측정 기준
09-19 첫 실행 flaky 22% Appium 스위트 초기 실행 기준
09-19 15% → 5~10% 로케이터·동기화·리트라이·병렬 디바이스 풀에 투자한 팀의 개선 사례
09-21 Appium 약 15% vs Espresso 2~3% 잘 작성된 Espresso 스위트와의 대조
09-21 10% → 26% 모바일 빌드 Flakiness를 겪는 팀 비율(2022 → 2025)

15%와 22%는 같은 것을 재지 않았습니다

19일자의 22%는 첫 실행 기준이고, 21일자의 15%는 Espresso와 대조하기 위한 일반 수준값입니다. 19일자 안에서 15%는 개선 전 값으로 쓰였습니다. 두 리포트 중 어느 쪽도 15%를 "안정화 이후"로 규정하지는 않았고, 21일자는 오히려 이 값에 "상시 안정화 공수 필요"를 붙였습니다.

21일자가 데이터 한계 고지에 적어 둔 문장이 이 상황을 정확히 설명합니다. Flaky 비율은 스위트 작성 품질에 크게 좌우되므로 절대 기준이 아닌 상대 비교 참고값으로만 쓰라는 것입니다. 21일자가 이 수치의 출처로 든 것은 Appium 대안을 다룬 글인데, 원 글 자체의 전제는 이번에 확인하지 않았습니다.

그래서 한쪽만 인용할 수 없었습니다

제목에 숫자 하나를 넣으려면 둘 중 하나를 골라야 하는데, 고르는 순간 유리한 값만 쓴 글이 됩니다. 그래서 이번 글의 제목에는 Flaky 수치를 넣지 않았습니다.

팀에 공유할 때도 마찬가지입니다. "Appium은 15% 깨집니다"라고 옮기면 그 15%가 우리 스위트의 목표치처럼 읽힙니다. 네 건을 읽고 남는 실무 결론은 숫자가 아니라 방향입니다. 크로스플랫폼 계층의 구조적 비용이므로 팀 실력으로 메우려 들지 말고, 앱 자동화 범위를 결제·로그인 같은 핵심 시나리오 3~5개로 의도적으로 좁게 유지하라는 쪽입니다.

4. Self-healing 권고도 같은 방향으로 흔들렸습니다

계약 테스트만의 일이 아니었습니다. AI가 테스트를 고치는 기능에 대한 권고도 나흘 안에서 반대로 움직였습니다.

날짜 권고 근거로 든 것
09-18 소규모 팀의 첫 적용점은 생성이 아니라 유지보수 구간 자동화 초기 팀의 최대 비용이 깨진 셀렉터 수정
09-19 PoC 한정. 회귀 스위트 자동 커밋은 리뷰 게이트 확립 전까지 보류 생성물 리뷰 공수 발생
09-20 후순위 실패 원인 중 셀렉터 파손은 약 28%
09-21 적용 범위가 시각 회귀·우선순위화·근본원인 분석까지 확장 에이전틱 QA 4계층 구조 서술

28%라는 반증이 사흘 뒤에 나왔습니다

18일자는 "자동화 초기 팀의 최대 비용은 깨진 셀렉터 수정"이라는 전제 위에서 self-healing을 권했습니다. 20일자는 같은 전제를 정반대 방향에서 셉니다. 리포트끼리 주고받은 것은 아니고, 20일자가 독립적으로 셀렉터 파손은 약 28%이고 나머지는 타이밍 이슈, 부적합한 테스트 데이터, 런타임 에러, 시각적 변경이라는 것입니다.

이 수치가 맞다면 self-healing 도구를 먼저 사는 팀은 실패의 72%를 그대로 둔 채 비용만 선지출하게 됩니다. 20일자가 제시한 순서는 명시적 대기 전략 정리 → 테스트 데이터 격리 → 그래도 남는 셀렉터 문제에 self-healing 검토였습니다.

리뷰 게이트를 먼저 만들라는 말은 네 건 중 두 건에 있었습니다

19일자는 self-healing의 동작을 단계까지 적어 두었습니다. 실패 스텝으로 이동해 현재 DOM의 접근성 스냅샷을 얻고, 테스트가 쓰던 로케이터와 비교해 원래 의도에 맞는 요소를 찾은 뒤, role이나 test-id 기반 로케이터로 테스트 파일을 직접 수정합니다.

파일을 고치는 단계까지 올라왔기 때문에 통제점이 필요해집니다. 19일자의 권고는 healer 결과를 자동 커밋이 아니라 PR로 발행하고, 로케이터 변경 diff만 담긴 PR은 리뷰 기한을 24시간으로 두라는 것이었습니다. 승인 없이 자가수정이 쌓이면 테스트는 초록색인데 검증 대상이 바뀌어 있는 상태가 조용히 진행된다는 설명이 붙어 있었습니다.

21일자는 이 통제점을 "에이전트 감독(agent oversight)"이라는 신규 책임 항목으로 명시했습니다. 개인 역량이 아니라 팀 규칙의 문제라는 뜻입니다.

5. 이번 주에 우리 팀이 확인할 것

네 건을 통으로 읽고 나서 제가 정리한 판단 표입니다. 리포트의 권고를 그대로 옮긴 것이 아니라, 권고가 갈린 항목은 갈린 이유를 조건으로 바꿔 적었습니다.

항목 도입 난이도 유지보수 비용 팀 학습곡선 우리 팀 판단
OpenAPI 스키마 린팅(Spectral) 낮음 낮음 낮음 이번 주. 21일자가 "세 칸이 모두 낮은 유일한 조합"으로 지목
OpenAPI 스키마 검증 CI 편입 낮음 낮음 1~2주 이번 주. 18일자가 순서상 첫 항목으로 지목
Pact 계약 테스트 중간 Broker를 직접 운영하면 중간, 관리형이면 낮음(후자는 제 가정) 중간(CDC 개념 선행) 서비스 경계 3개 미만이면 보류. 단일 소비자-제공자 쌍 파일럿은 가능
Self-healing 도구 낮음(SaaS) 18일 낮음 / 20일 중간(오탐 검수) — 여기서도 갈림 낮음 ~ 2~4주 대기 전략·데이터 격리 정리 후. 리뷰 게이트 문서가 선행
Appium 범위 확대 중간~높음(날짜별로 갈림) 높음(네 건 일치) 중간 ~ 1~2개월 보류. 핵심 3~5개 시나리오로 고정

Broker 칸을 둘로 나눈 것이 제가 손댄 부분입니다. 리포트 네 건이 이 칸에서 갈렸는데 원문은 갈린 이유를 설명하지 않거든요. 저는 Broker 운영 주체가 이 칸의 값을 좌우한다고 보고 조건으로 나눠 적었고, 관리형 Broker에 대한 평가는 네 건 어디에도 없으므로 그 줄은 제 가정입니다.

먼저 팀에서 확인할 항목을 적어 둡니다. 앞 두 항목은 20일자의 「이번 주」 액션, 세 번째는 21일자의 「2주」, 다섯 번째는 21일자의 「분기」 항목에서 뽑았고, 네 번째 Broker 항목만 제가 더했습니다. 전부 도구를 사지 않아도 시작할 수 있는 것들입니다.

□ 최근 30일 테스트 실패 로그를 4분류로 태깅한다
     셀렉터 / 타이밍 / 데이터 / 시각 변경
     → 우리 분포가 업계 기준(셀렉터 약 28%)과 얼마나 다른지 먼저 본다
□ Pass rate 기준선을 대시보드 지표로 등록한다
     20일자 제시값은 98%. 미만이면 신규 기능보다 flaky 정리를 우선
□ Flaky 판정 임계값과 격리 절차를 문서 1장으로 합의한다
     21일자 예시: 최근 20회 중 2회 이상 불안정 시 격리
     격리 후 복구 책임자와 주간 재검토 시점을 같이 적는다
□ 우리가 Pact Broker를 직접 운영할 것인지 먼저 정한다
     이 답이 위 판단 표의 Pact 줄을 결정한다
□ AI에게 검색시킬 참조 자산 4종의 현재 상태를 확인한다
     테스트 코드 저장소 / 페이지 오브젝트 / OpenAPI 스펙 / 결함 이력

첫 항목의 4분류 태깅부터 하려면 실패가 재현돼야 하는데, 순서 의존으로 깨지는 케이스는 그냥 돌려서는 안 잡힙니다. 그 분류 작업에 쓸 셔플 실행은 pytest-randomly 훅 래퍼 전환을 다룬 글에 적어 둔 것을 그대로 씁니다. 아래는 그 글의 스크립트를 이번 분류 용도에 맞게 줄인 형태이고, 시드 개수 근거와 플러그인 예외 처리는 원문에 있습니다.

#!/usr/bin/env bash
# 출처: 위 pytest-randomly 발행 글의 셔플 잡을 4분류 태깅용으로 줄인 것입니다.
# 시드 6개인 이유(회당 탐지율 0.567 기준 1-(1-p)^6 = 99%)는 원문에 있습니다.
set -uo pipefail

PLUGIN_OFF="${PLUGIN_OFF:--p no:django}"   # 정렬하는 플러그인 이름으로 바꾸십시오
FAILED=0

for SEED in $(python3 -c "import random;print(*[random.randrange(2**32) for _ in range(6)])"); do
  echo "::group::seed=${SEED}"
  python3 -m pytest -q ${PLUGIN_OFF} --randomly-seed="${SEED}" || {
    # 여기서 떨어진 케이스는 '타이밍/데이터' 분류 후보입니다. 셀렉터로 세지 마십시오
    echo "순서 의존 의심: --randomly-seed=${SEED} 로 재현하십시오"
    FAILED=1
  }
  echo "::endgroup::"
done

exit "${FAILED}"

저는 이번 주에 Pact를 건드리지 않기로 했습니다. 우리 서비스 경계가 아직 3개 미만이고요, 무엇보다 Broker 운영 주체를 안 정한 상태에서는 위 판단 표의 Pact 줄을 채울 수가 없거든요. 대신 Spectral 린팅 한 단계와 실패 로그 4분류만 잡을 생각입니다.

나흘 치를 겹쳐 읽고 남은 것은 도구 목록이 아니라 읽는 법이었습니다. 동향 리포트의 권고 칸은 그 리포트가 그날 무엇을 비용으로 셌는지에 따라 움직이는데요. 그러니 권고를 옮겨 적기 전에 비용 칸의 근거 문장을 먼저 보십시오. 이번 주에는 그 한 칸이 보류와 1순위를 갈랐습니다.

댓글

이 블로그의 인기 게시물

옵시디언 3기기 동기화, 유료 결제 없이 구글 드라이브로 끝내기

최저가 주유소, 얼마나 돌아가면 손해일까?

회의시간 줄이는 법, 개수보다 배치 먼저

유류세 인하 2개월 연장, 주유소 가격 실제 인하폭 계산

국민연금 추납 조회, 미루면 얼마나 더 낼까?