Communitygithub.com

lguidolin/graphql-contract-testing

GraphQL 쿼리/뮤테이션을 UI와 테스트가 공유하거나, 라우트/스키마 계약 또는 스모크 테스트를 구축할 때 사용합니다. 증상 — 테스트에 쿼리 복사, 쿼리 텍스트에 단언하는 테스트, UI 빌드를 깨뜨리지 않은 스키마 변경, RLS/권한 드리프트. 키워드 — graphql-codegen, typed document, contract test, route smoke test.

graphql-contract-testing란 무엇인가요?

이 스킬은 GraphQL 계약 테스트(Contract Testing)를 체계적으로 적용하는 방법을 제공합니다. 핵심 원칙은 레이어 간 경계에서 동의 없이 한쪽이 변경될 때 테스트가 실패하도록 만드는 것입니다. 이를 위해 모든 GraphQL 연산은 단일 타입 문서(Typed Document)로 한 번만 작성되고, UI와 테스트가 동일한 아티팩트를 가져와 사용합니다. graphql-codegen을 통해 라이브 스키마에서 타입을 생성하여 컴파일 타임에 DB→UI 드리프트를 포착하고, 런타임 계약 테스트는 시드된 테스트 DB와 실제 호출 경로를 통해 역할 컨텍스트에서 반환된 데이터 형태와 접근 결과를 단언하여 UI→DB 및 권한 드리프트를 포착합니다. 또한 라우트 계약 및 스모크 테스트를 통해 모든 URL이 오류 없이 렌더링되고 최소한의 필수 요소를 포함하도록 강제합니다. 이 스킬은 Cursor, Claude Code, Codex 등 모든 AI 에이전트 플랫폼에서 사용할 수 있으며, SKILL.md 파일을 통해 에이전트에게 정확한 지침을 제공합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/lguidolin/agent-skills/tree/main/skills/graphql-contract-testing

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

GraphQL 계약 테스트

개요

레이어 간의 이음새에 위치하여 한쪽이 상대방의 동의 없이 움직일 때 깨지는 테스트 — 통제로서의 테스트를 경계에 적용한 것입니다. 핵심 규칙: 계약 — 즉 소비자가 의존하는 데이터 형태와 접근 의미론 — 에 대해 단언하고, 쿼리 문자열 자체에는 절대 단언하지 마십시오. 단순한 쿼리 편집으로 깨지는 테스트는 변경 감지 안티패턴입니다. 보장된 형태나 권한이 움직일 때 깨지는 테스트가 진정한 통제입니다.

§1 — GraphQL 쿼리 계약

  • 모든 연산은 알려진 위치에 타입 문서로 한 번 작성되어 내보내지며, 가져와서 사용됩니다. UI가 가져오고, 테스트는 정확히 동일한 아티팩트를 가져옵니다 — 절대 다시 입력한 복사본이 아닙니다. 테스트에 쿼리를 복사하면 계약이 조용히 사라집니다 (UI 쿼리를 편집해도 더 이상 테스트가 깨지지 않음). DRY가 중요한 책임을 지닙니다.
  • 설계상 양방향으로 깨집니다:
    • DB → UI 드리프트, 컴파일 타임. graphql-codegen이 라이브 스키마에서 TypeScript 타입을 생성합니다. 사용 중인 필드의 이름을 바꾸거나 제거하면 tsc가 모든 사용처 그리고 공유 문서에서 실패합니다 — 사용자가 빈 패널을 보기 전에 빌드가 중단됩니다. 이것이 라이브 스키마에 대한 코드 생성이 필수인 이유입니다.
    • UI → DB / 권한 드리프트, 런타임. 공유 문서가 시드된 테스트 DB에 대해 실제 호출 경로를 통해 역할 컨텍스트 하에 실행되며, 반환된 형태와 접근 결과에 대해 단언합니다 — 쿼리 텍스트가 아닙니다.
  • 계약 테스트와 RLS 역할 매트릭스는 동일한 수단입니다. 하나의 문서를 PostGraphile을 통해 역할 A(데이터 예상)와 역할 B(거부/빈 값 예상)로 실행합니다. 하나의 메커니즘으로 세 가지를 증명합니다: 쿼리가 여전히 스키마와 일치하는지, UI 가정이 여전히 유효한지, RLS가 여전히 경계를 강제하는지.

실제 사례 — 실제 버그가 어떻게 포착되는지

  • DB→UI: 마이그레이션이 equipment.is_active를 제거합니다. Codegen이 새 스키마에서 다시 생성합니다. 생성된 타입이 필드를 잃습니다. tsc가 공유 문서와 해당 필드를 사용하는 모든 컴포넌트에서 실패합니다 — 병합 전 빌드에서 포착됩니다. 어떤 테스트도 "쿼리 텍스트 == X"를 단언하지 않습니다.
  • UI→DB: 개발자가 UI 쿼리를 확장하여 cancellation_reason을 가져옵니다 (RLS가 높은 역할에만 노출). 일반 멤버로 실행되는 런타임 테스트가 멤버가 볼 수 있는 형태를 단언하다가 이제 null/거부를 받고 실패합니다 — "이것을 노출하려는 의도였나?"를 강제합니다.

§2 — 라우트 계약 및 스모크 테스트

  • 라우트는 단일 소스에서 열거됩니다. 각 라우트에는 스모크 테스트가 있습니다: 오류 없이 렌더링 + 최소한의 필수 요소 세트(헤딩, 랜드마크, 주요 컨트롤 — 상세한 상호작용은 아님)를 보여줍니다.
  • 라우트를 추가/제거하면 일치하는 테스트 변경이 강제됩니다 — 새 URL은 스모크 테스트 없이 불완전합니다. 제거된 URL은 테스트를 제거합니다. URL이 조용히 나타나거나 사라지지 않습니다.
  • 명시적으로 상세한 UI/상호작용 테스트가 아닙니다 — 의도적이고 범위가 제한됩니다. 질문은 "이 URL이 작동하고 필수 요소를 렌더링하는가"이며, 그 이상은 아닙니다.

강제: CI에서 graphql-codegen + tsc (차단)로 컴파일 타임 절반을 처리하고, 시드된 DB에 대한 런타임 계약 + 라우트 스모크 테스트로 나머지를 처리합니다.

전체 근거: 엔지니어링 헌법 제XV조, engineering-constitution/references/engineering-constitution.md에 번들로 포함되어 있습니다.

Individual skills in this repo

This repo contains 18 individual skills — each has its own dedicated page.

lguidolin/change-hygiene-and-code-craft

Use when writing or refactoring code, structuring a commit or PR, or deciding whether to abstract duplication. Symptoms — mixing reorg with logic changes, a PR doing several things at once, a file growing large, the second copy of similar code, or unsure whether to DRY something up.

lguidolin/cloud-delivery-aks

Use when deploying to Kubernetes or Azure Kubernetes Service (AKS), configuring cloud secrets, setting up progressive rollout/canary, per-PR ephemeral environments, or k8s health probes. Keywords — Kubernetes, AKS, Key Vault, Argo Rollouts, Flagger, canary, blue-green, liveness, readiness, PodDisruptionBudget, HPA, rollback, GHCR.

lguidolin/commit-history-rewrite

Use when an existing repository has messy commit history that needs to conform to conventional commits before adopting release-please, or when intermediate WIP/fixup/merge commits need to be cleaned up.

lguidolin/conventional-commits-and-releases

Use when committing, writing a commit message, opening a PR that will be squash-merged, or configuring automated versioning/changelogs. Keywords — conventional commits, release-please, semver, feat/fix/chore, breaking change, changelog.

lguidolin/defense-in-depth-security

Use when handling untrusted input, secrets, authentication/authorization, or dependencies — or threat-modeling a new surface. Keywords — STRIDE, threat model, least privilege, secrets management, supply chain, dependency scanning, input validation, audit log, defense in depth.

lguidolin/designing-before-building

Use when starting a feature, fixing a non-trivial bug, or about to write implementation code — before any code exists. Symptoms you need this: "this is simple, I'll just code it", reaching for the editor before a design is approved, or an idea that hasn't been turned into a spec and plan.

lguidolin/engineering-constitution

Use when starting work in a project that follows the engineering constitution, orienting to its rules, or deciding which engineering practice applies to a task — spec writing, commits, testing, security, deploys, database, or UI work.

lguidolin/init-repo-CI

Use when setting up a new repository with conventional commits, release-please, and CI automation, or when retrofitting an existing repository that lacks automated versioning and PR validation workflows.

lguidolin/interface-craft-and-accessibility

Use when building or styling UI — components, layouts, forms, design tokens — or making accessibility decisions. Keywords — a11y, WCAG, keyboard navigation, focus state, contrast, design system, minimalist UI, component reuse, ARIA, semantic HTML.

lguidolin/merge-gates-and-automation

Use when setting up or changing CI, pre-push hooks, or a task runner, or deciding what must pass before merge. Symptoms — tempted to put authoritative checks only in a local hook, skip CI, bypass with --no-verify, or unsure what gates a merge vs. runs locally.

lguidolin/observability-and-slos

Use when adding logging, metrics, tracing, health checks, SLOs, or alerting — or when building a service surface that needs to be operable and debuggable. Keywords — structured logs, OpenTelemetry, correlation id, RED metrics, liveness, readiness, SLI, SLO, error budget, alerting.

lguidolin/performance-and-scale

Use when working on hot paths, list endpoints, pagination, data-access in loops, or public interfaces/schemas. Symptoms — unbounded queries, N+1 access, no latency budget, optimizing without measuring, or changing an interface many consumers depend on. Keywords — pagination, N+1, Hyrum's Law, performance budget, bundle size.

lguidolin/postgres-postgraphile-rls-and-sql

Use when writing PostgreSQL, PostGraphile config, Row-Level Security policies, SQL schema files, or working on the Browser→App→PostGraphile→Postgres data path. Keywords — RLS, SECURITY DEFINER, search_path, pgSettings, grants, roles, GraphQL depth limit, query cost, statement_timeout, SQL file organization.

lguidolin/recording-decisions

Use when a design or architecture decision has been made and needs to be captured — writing a decision record or ADR, updating a decision index, noting a deferred idea, or superseding a past decision. Keywords — ADR, decision record, rationale, rejected alternatives, dependency index.

lguidolin/resilience-and-deploy-safety

Use when planning a deploy, designing a rollback, or responding to an incident or writing a postmortem. Keywords — deploy safety, rollback, immutable artifact, progressive delivery, canary, blast radius, incident response, blameless postmortem, error budget.

lguidolin/ship-it

Use when the user wants to ship work — push, PR, archive decision records, merge, and clean up. Handles the full lifecycle from committing final changes through post-merge cleanup including converting specs/plans to compact decision records.

lguidolin/tests-as-a-control

Use when writing or modifying tests, when a test breaks during a refactor, or when testing permission/role rules. Symptoms — tempted to edit a test to make it pass, testing only the happy path, a deny-test that started passing, flaky tests, or unsure what to assert.

lguidolin/zero-downtime-migrations

Use when changing a database schema where data must survive the change — adding/removing/renaming columns, constraints, indexes, or backfilling. Symptoms — a destructive migration bundled with a code deploy, a NOT NULL column with a backfill, a table-locking UPDATE, or a rename. Keywords — expand/contract, parallel change, backfill, NOT VALID, CREATE INDEX CONCURRENTLY, graphile-migrate.

관련 스킬