Airbnb의 LLM 기반 GraphQL Mock 자동 생성
Airbnb가 @generateMock 디렉티브로 GraphQL mock 데이터를 LLM이 생성하게 만들어, 700건 이상 mock을 iOS·Android·Web에 머지한 사례.
요약
Airbnb가 @generateMock GraphQL 디렉티브를 도입, Niobe CLI가 스키마·디자인 URL·이미지 시드를 컨텍스트로 묶어 Gemini 2.5 Pro에 전달 → 검증 실패 시 에러를 다시 LLM에 돌려 자가 수정 → 쿼리·인자 해시를 mock JSON에 박아 자동 동기화. iOS·Android·Web에서 700건 이상 mock 생성·머지, 클라이언트가 서버 미구현 상태에서도 @respondWithMock으로 개발 진행.
내용
GraphQL mock은 데모·테스트·프로토타이핑 모두에 필요하지만, 손으로 만들면 세 갈래로 깨짐. 쿼리가 수백 줄에 이르면 raw JSON 작성·수정이 시간을 잡아먹음. 서버·클라이언트가 스키마 합의 후 병렬로 갈라질 때 클라이언트는 서버 구현 전까지 UI를 못 돌려 hardcode·proxy·네트워킹 레이어 패치 같은 임시 처방을 함. 시간이 흐르면 손으로 쓴 mock이 쿼리·스키마와 점점 어긋나 테스트 품질이 떨어짐.
랜덤 값 생성기·필드 stub 같은 기존 도구로는 한계가 있음 — 도메인 컨텍스트가 없어 사실적인 데이터가 안 나오기 때문. Airbnb는 데모 품질을 중시하기 때문에 mock이 실제 production처럼 보여야 하고, 엔지니어가 사이트·다른 레포·낯선 도구로 컨텍스트 스위칭 없이 로컬 작업 흐름 안에 통합돼야 함. 이 위에서 새 디렉티브 + 기존 GraphQL 인프라 + LLM을 엮은 것이 출발점.
해결 / 접근
@generateMock 디렉티브
- 쿼리·프래그먼트·필드 어디든 붙일 수 있는 클라이언트 디렉티브
- 인자 —
id(mock 식별자, 같은 쿼리에 여러 변종 만들 때 헬퍼 함수 이름에도 사용),hints(예: "Barcelona, Paris, Kyoto travel entries 포함"),designURL(디자인 mockup 노드 URL — 같은 디자인의 이름·주소 톤에 맞춰 생성) - 작업 흐름:
.graphql파일 수정 → 사내 코드 생성기 Niobe 실행 → mock JSON 파일 + 헬퍼 소스 파일(Swift/Kotlin/TypeScript) 생성 → 데모·스냅샷·유닛 테스트에서 호출
LLM에 전달하는 컨텍스트
- @generateMock가 붙은 쿼리·프래그먼트·필드 정의와 의존 관계
- 쿼리가 사용하는 GraphQL 스키마의 부분 + 인라인 주석 문서 (전체 스키마는 컨텍스트 윈도우를 압박해 Niobe가 필요 없는 타입·필드와 공백을 제거)
- designURL이 있으면 사내 API로 디자인 노드 스냅샷 이미지를 생성·스토리지 저장 후 URL을 LLM에 전달
- hints, 플랫폼(iOS·Android·Web — 스타일 specificity)
- Airbnb가 호스팅하는 이미지 URL 시드 + 텍스트 설명 — LLM이 존재하지 않는 이미지 URL을 환각하지 않도록, 런타임에 실제 로드되는 URL만 사용
- 모델: Gemini 2.5 Pro (1M 토큰 컨텍스트, 사내 테스트에서 비교 모델 대비 속도 우위·품질 동등)
검증 + 자가 수정 루프
- LLM 응답 mock JSON을 graphql NPM 패키지의 graphqlSync로 스키마 대비 검증
- enum 환각·필수 필드 누락 같은 에러가 나오면 에러 메시지를 초기 mock과 함께 LLM에 다시 전달 → self-heal
- LLM을 기존 GraphQL 인프라 안에 배치했기 때문에 가능한 가드레일 — 외부 챗봇 도구로는 같은 보장이 안 됨
@respondWithMock — 서버 미구현 차단 해소
- 디렉티브 추가 시 GraphQL 클라이언트가 런타임에 서버 응답 대신 로컬 mock JSON 반환
- 필드 단위로 쓰면 나머지 필드는 서버에서, 해당 필드만 mock — 기존 쿼리에 신규 미구현 필드를 끼워 개발 가능 (production + mock 하이브리드)
- 쿼리 input variable에 따라 조건부로 mock 선택도 가능
스키마 진화 시 자동 동기화
- mock JSON에 두 해시를 박음 — 클라이언트 엔티티(쿼리 문서) 해시 + @generateMock 인자 해시
- 코드 생성 시 현재 해시와 비교 — 일치하면 mock 재생성 skip
- 변경됐으면 기존 mock + 쿼리 diff를 컨텍스트로 LLM에 전달, 변경 필드만 수정. 사람이 수동으로 손본 값과 무관 필드는 보존하도록 prompt 튜닝
- 클라이언트 코드베이스에 자동 체크 — 코드 제출 시 mock 버전 해시가 최신인지 검사. 어긋나면 로컬에서 코드 생성 재실행만 하면 됨
결과 / 참고
- iOS·Android·Web에서 700건 이상의 mock 생성·머지, 백엔드 서비스 내부 지원 도입 예정
- 이전: 손으로 mock JSON 작성·수정, 서버 미구현 시 hardcode/proxy 임시 처방, 시간 흐를수록 mock 표류
- 이후: @generateMock + @respondWithMock 디렉티브 추가만으로 mock 생성·하이브리드 응답·동기화 모두 자동
- 핵심 결정 — 검증을 LLM 출력 뒤에 GraphQL 인프라 안에 두기 / Gemini 2.5 Pro 1M 컨텍스트 / 이미지 URL 시드로 환각 차단 / 해시 기반 변경 감지로 수동 수정 보존
- 출처: Airbnb Tech Blog (Medium)