테스트에서 놓치는 API 스키마 변경을 어떻게 미리 감지할 수 있나요?
상태 코드와 몇몇 필드만 확인하는 테스트는 API에 필드가 추가되거나, 검증하지 않는 필드가 삭제되거나, 숫자가 문자열로 바뀌어도 계속 통과합니다. Nexus Studio는 각 API 응답의 구조를 저장합니다. 필드 이름과 자료형만 저장하고 값은 저장하지 않으며, 이전 실행과 비교해 구조가 바뀌면 API_DRIFTED를 보고합니다. NEXUS_API_DRIFT_STRICT=true를 설정하면 같은 변경으로도 테스트 모음이 실패합니다.
작성: Nexus Studio 팀, Verdict System LLC. 2026년 10월 27일.
API 스키마 변동이란 무엇인가요?
스키마 변동은 실행 사이에 응답 구조가 달라지는 현상입니다: 필드가 추가되거나, 삭제되거나, 필드의 자료형이 바뀌는 경우입니다. API는 발전할 수 있습니다. 문제는 테스트 모음에서 아무런 변화도 알리지 않아, API를 사용하는 쪽에서 운영 환경에 이르러서야 이를 알게 되는 것입니다.
계약 테스트가 통과하는데도 이를 놓치는 이유는 무엇인가요?
작성자가 생각해 둔 항목만 검증하기 때문입니다. validate(res, { status: 200, hasFields: ['id'] }) 같은 규칙은 price가 숫자에서 문자열로 바뀌어도 계속 통과합니다. price가 규칙에 없기 때문입니다. 실제로 문제가 생기는 쪽은 가격을 합산하는 클라이언트입니다.
실행 가능한 예제로 확인할 수 있나요?
이 코드를 server.mjs로 저장하세요. 하나의 엔드포인트에 응답하며, SHAPE 변수로 반환할 응답을 선택합니다: 숫자형 가격 또는 새로운 currency 필드가 추가된 문자열형 가격입니다.
import http from 'node:http';
// SHAPE=v1 answers {id, price: 9.99}; SHAPE=v2 answers {id, price: "9.99", currency: "USD"}.
const v2 = process.env.SHAPE === 'v2';
http.createServer((req, res) => {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(v2 ? { id: 7, price: '9.99', currency: 'USD' } : { id: 7, price: 9.99 }));
}).listen(4010, '127.0.0.1');
이 API 테스트를 작업 공간의 api-tests/rest 폴더에 APIT900_drift_demo.api.js로 저장하세요. 실제로 많이 쓰이는 테스트 모음처럼 상태 코드와 필드 하나만 검증합니다.
// type: rest
import { runApiSuite } from '../../utils/base-api-fixture.js';
await runApiSuite([{
id: 'APIT900-1',
name: 'GET /product/7 returns 200 with an id',
fn: async ({ request, validate }) => {
const res = await request({ method: 'GET', url: '/product/7' });
validate(res, { status: 200, hasFields: ['id'] });
},
}]);
PowerShell 창 하나에서 서버를 시작하고 다른 창에서 테스트를 실행하세요. 첫 실행에서는 비교할 대상이 없으므로 구조를 기록하고 통과합니다.
$env:SHAPE = "v1"; node server.mjs
$env:API_BASE_URL = "http://127.0.0.1:4010"; nexus api APIT900 --no-app
서버를 중지한 뒤 $env:SHAPE = "v2"로 다시 시작하고 같은 테스트를 실행하세요. 여전히 통과하지만, 실행 결과는 더 이상 API_SECURE가 아닙니다. 다음은 중요한 줄만 추린 출력입니다:
schema drift: +1 field, 1 type change
+ currency
~ price: number → string
API_DRIFTED 7ms
1/1 passed
1 endpoint changed shape since the last run, set NEXUS_API_DRIFT_STRICT=true to fail the suite on it
변동이 발생하면 빌드를 실패하게 할 수 있나요?
네, 설정하면 가능합니다. 기본적으로 API_DRIFTED는 통과로 처리되며 종료 코드는 0입니다. API가 바뀌었다는 것은 정보이지 결함은 아니기 때문입니다. 다만 별도 줄에 출력되고 변경 내역과 함께 실행 증적에 기록되므로, 문제가 없는 통과로 해석되지는 않습니다. NEXUS_API_DRIFT_STRICT=true를 설정하면 같은 변경에도 종료 코드가 1이 됩니다. 확인하려면 이 변수를 설정한 상태에서 v1을 대상으로 한 번, v2를 대상으로 한 번 테스트를 실행하세요.
기준은 항상 이전 실행입니다. 변동이 발생한 실행 이후에는 새 구조가 기준이 되므로, 같은 응답을 대상으로 다음 실행을 수행하면 변동이 없다고 보고합니다.
어떤 한계가 있나요?
- 테스트의 첫 실행은 구조만 기록합니다. 아직 변동 여부를 비교할 기준이 없습니다.
- 구조는 이름과 자료형을 뜻하며, 의미는 포함하지 않습니다.
price가 숫자로 유지되면서 단위만 달러에서 센트로 바뀐다면 구조에는 변화가 없습니다. - 합의된 계약이 아니라 이전 실행과 비교합니다. 무언가 바뀌었다는 사실을 알려 줄 뿐, 허용된 변경인지는 판단하지 않습니다.
- 각 테스트 케이스는 마지막 요청의 본문에서 추출한 구조 하나를 보관합니다. 목록은 첫 번째 요소로, 객체는 최대 200개의 키로 구조를 나타내며, 중첩은 6단계까지만 확인합니다.
어디에서 볼 수 있나요?
판정 안내서는 테스트 판정을 설명하며, 증적 페이지는 실행 후 디스크에 남는 파일을 나열합니다. 30일 체험판에서도 동일한 엔진으로 직접 작성한 API 테스트를 실행할 수 있습니다.