귀하의 채팅 UI는 모든 응답 아래에 작은 "AI 생성" 배지를 가지고 있습니다. 좋습니다. 이제 파트너 팀이 배치 작업에서 귀하의 /summarize 엔드포인트를 호출하여 출력을 데이터베이스에 기록하고 고객 대면 보고서 내에 렌더링합니다. 귀하의 배지는 아무에게도 도움이 되지 않았습니다.
이것이 AI 공개가 계속해서 빠지는 함정입니다. 공개는 UI 결정으로 설계되므로 자체 프런트엔드의 가장자리에서 멈춥니다. 기계 소비자는 아무것도 얻지 못하며, 응답을 보고 모델에서 온 것인지 알 수 없기 때문에 가장 필요한 쪽은 바로 그들입니다.
2026년 8월 2일부터 EU AI 법의 제50조는 많은 팀에게 이 문제를 구체화했습니다. Anthropic과 같은 모델 제공업체는 모델 수준에서 출력을 표시하지만, 사람들이 AI를 다루고 있다는 사실을 알릴 의무는 시스템을 배포하는 사람에게 있습니다. 귀하의 API가 이 둘 사이에 있다면, 귀하가 호출자가 규정을 준수할 수 있는지 없는지의 이유가 됩니다.
인터페이스 대신 계약에 공개를 포함시키는 방법은 다음과 같습니다: 무엇을 반환하고, 어디에 배치하고, 어떻게 문서화하며, 다음 리팩토링에서도 살아남도록 테스트하는 방법입니다. Apidog는 이 모든 것의 설계, 문서화, 테스트 측면을 한 곳에서 다룹니다.
응답에 무엇을 넣을 것인가
세 가지이며, 각각 다른 질문에 답합니다.
생성된 것인가? 불리언(boolean), 또는 더 좋게는 열거형(enum)입니다. ai_generated: true는 좋은 시작이지만, generation: "synthetic" | "assisted" | "human"이 더 유용합니다. 왜냐하면 "Claude가 사람이 작성한 초안을 다듬었다"와 "Claude가 모든 것을 작성했다"는 본질적으로 다르며 제50조의 예외 조항이 이들을 다르게 취급하기 때문입니다.
무엇에 의해? 공급업체 및 모델 ID입니다. 호출자는 자체 모델 정책을 가질 수 있으며, 모델을 전환하는 대체(fallback)는 출력으로 무엇을 할 수 있는지 변경합니다.
우리가 실제로 무엇을 알고 있는가? 확인했다면 출처(provenance) 상태입니다. "우리가 이것을 생성했다"는 귀하가 소유한 사실이고, "우리가 C2PA 매니페스트를 검증했다"는 귀하가 관찰한 내용이므로 이를 생성 플래그와 분리하십시오.
유지되는 형태:
{
"id": "sum_4f81a2",
"content": "The incident affected two regions for 41 minutes...",
"ai": {
"generation": "synthetic",
"vendor": "anthropic",
"model": "claude-opus-5",
"human_review": false,
"generated_at": "2026-08-11T09:14:22Z"
},
"provenance": {
"status": "unchecked",
"standard": null
}
}
옹호할 가치가 있는 두 가지 세부 사항.
human_review는 제50조(4)항에 따라 존재합니다. 공공의 이익과 관련된 사안에 대해 대중에게 알리기 위해 게시된 AI 생성 텍스트는 인간 검토 또는 편집 책임자가 있는 편집 통제를 거치지 않은 한 공개되어야 합니다. 귀하의 플랫폼이 인간이 초안을 승인했다고 기록한다면, 그 사실은 응답에 포함되어야 합니다. 이는 호출자가 라벨을 필요로 하는지 여부를 결정하는 차이점이기 때문입니다.
provenance.status는 두 가지 이상의 상태를 가집니다. verified(검증됨), absent(부재), invalid(유효하지 않음), unchecked(확인되지 않음)는 모두 다른 의미를 가지며, 이들을 불리언으로 통합하는 것은 유용한 정보를 버리는 행위입니다. 검증 서비스의 중단이 깨끗한 결과와 동일하게 보여서는 안 됩니다.
헤더 또는 본문?
다른 소비자를 위해 둘 다.
본문은 진실을 담고 있습니다. 이는 저장되고, 로깅되고, 재생되며, 다운스트림으로 전달되는 내용입니다. 호출자가 파싱된 JSON만 보관한다면, 공개 내용은 그 안에 있어야 합니다.
헤더는 가장자리에서 도움이 됩니다. 프록시, 게이트웨이 또는 본문을 파싱하지 않는 로깅 계층도 헤더를 기반으로 라우팅하거나 기록할 수 있습니다. 또한 일반 텍스트 또는 바이너리 엔드포인트와 같이 JSON이 아닌 응답에 대한 공개를 위한 유일하게 합리적인 장소이기도 합니다.
HTTP/1.1 200 OK
Content-Type: application/json
X-AI-Generated: synthetic
X-AI-Model: anthropic/claude-opus-5
헤더에 대한 두 가지 규칙입니다. 모든 엔드포인트에서 일관성을 유지하십시오. 왜냐하면 일부 경로에만 나타나는 헤더는 전혀 나타나지 않는 헤더보다 더 나쁘기 때문입니다. 그리고 본문과 헤더가 일치하지 않는 경우 헤더를 권위 있는 것으로 취급하지 마십시오. 하나를 정식(canonical)으로 선택하고, 어떤 것이 정식인지 문서화하며, 테스트에서 이를 강제하십시오.
스트리밍 응답의 경우, 공개 내용을 첫 번째 이벤트나 응답 헤더에 넣으십시오. 토큰 하나를 렌더링하기 시작하는 호출자는 무엇을 렌더링하는지 알기 위해 트레일러를 기다릴 필요가 없습니다. 헤더 설계에 일반적으로 익숙하지 않다면, HTTP 헤더란 무엇인가가 기본 사항을 다룹니다.
사양에 포함하기
OpenAPI 정의에 없는 공개 필드는 관례이며, 관례는 퇴색합니다. 모든 AI 기반 엔드포인트가 동일한 형태를 사용하도록 재사용 가능한 스키마로 정의하십시오:
components:
schemas:
AiDisclosure:
type: object
required: [generation]
properties:
generation:
type: string
enum: [synthetic, assisted, human]
description: >
synthetic = produced by a model with no human authoring.
assisted = a human authored the content and a model edited,
translated, or summarised it.
human = no model involvement.
vendor:
type: string
example: anthropic
model:
type: string
example: claude-opus-5
human_review:
type: boolean
description: >
True when a person reviewed the output before it was returned
and an identifiable party holds editorial responsibility.
generated_at:
type: string
format: date-time
그런 다음 모든 곳에서 참조하고, 모델 출력을 포함할 수 있는 모든 응답에서 ai를 필수 속성으로 만드십시오. 필수성은 중요합니다. 선택적 필드는 호출자가 방어 코드를 작성해야 하는 필드이며, 대부분은 그렇게 하지 않을 것입니다.
두 가지 연쇄적인 이점이 있습니다. 이제 생성된 문서가 위키 페이지를 작성하지 않고도 모든 소비자에게 필드를 설명합니다. 그리고 사양 유효성 검사는 실제로 발생하는 실패 모드인 필드가 사라지는 날을 잡아낼 것입니다. OpenAPI 사양 유효성 검사 방법은 유효성 검사 측면을 다루며, CI에서 중단 변경 사항을 차단하는 OpenAPI diff는 누군가가 조용히 이를 선택 사항으로 만드는 것을 잡아낼 것입니다.
사람들이 잊는 경로
공개 필드는 아무도 생각하지 않는 경로에서 누락됩니다. 명시적으로 확인할 네 가지:
캐시된 응답. 공개가 첨부되기 전에 본문을 저장하는 캐시 계층은 TTL이 지속되는 동안 표시되지 않은 출력을 제공할 것입니다. 모델 출력과 재구축하는 래퍼를 캐시하는 대신 전체 응답을 캐시하십시오.
오류 및 부분 응답. 부분 요약을 반환하는 타임아웃도 여전히 모델 출력을 반환하는 것입니다. 오류 엔벨로프가 다른 형태를 가진다면, 해당 필드도 필요합니다.
배치 및 웹훅 페이로드. 비동기 전달은 종종 다른 코드에 의해 구축된 더 간소화된 스키마를 사용합니다. 이곳이 해당 필드가 가장 흔하게 누락되는 지점입니다.
대체 경로(Fallback paths). 주 모델이 실패하고 대체할 때, model 값도 따라와야 합니다. 공개 블록에 하드코딩된 모델 문자열은 언제든 거짓말이 될 수 있습니다.
네 가지 모두에 대한 해결책은 동일합니다: 모델 출력이 응답 객체에 들어가는 시점에 공개를 첨부해야 하며, 성공적인 경로를 직렬화하는 시점에 첨부하는 것이 아닙니다.
보증처럼 테스트하기
공개 필드는 호출자에게 하는 약속입니다. 테스트되지 않은 약속은 그저 문서일 뿐입니다.
다섯 가지 단언(assertion)이 대부분을 다루며, 이들은 일반적인 API 테스트입니다.
1. 모든 AI 기반 경로에 필드가 존재합니다.
const body = pm.response.json();
pm.test("response carries AI disclosure", function () {
pm.expect(body).to.have.property("ai");
pm.expect(body.ai.generation).to.be.oneOf(["synthetic", "assisted", "human"]);
});
2. 헤더가 본문과 일치합니다.
pm.test("header and body agree", function () {
pm.expect(pm.response.headers.get("X-AI-Generated")).to.eql(body.ai.generation);
});
3. 보고된 모델이 실제로 호출한 모델과 일치합니다. 이것이 은밀한 대체(fallback)를 잡아내는 부분입니다. 출력물이 업스트림에서 워터마크 처리되는지 여부는 모델 ID에 따라 달라지며, 이것이 Claude의 API 워터마킹이 모델 고정을 성능 문제가 아닌 규정 준수 세부 사항으로 만드는 이유입니다.
4. 캐시된 경로도 여전히 공개합니다. 두 번 호출하고, 캐시에서 온 두 번째 응답이 첫 번째 응답과 동일한 공개 내용을 가지고 있는지 단언합니다.
5. 오류 경로도 여전히 공개합니다. 타임아웃이나 다운스트림 실패를 강제하고 엔벨로프에 여전히 필드가 포함되어 있는지 단언합니다.
이것들을 테스트 시나리오로 그룹화하고, OpenAPI 정의에 대한 스키마 유효성 검사를 추가한 다음, CI에서 apidog-cli로 실행하십시오:
apidog run --access-token "$APIDOG_ACCESS_TOKEN" \
-t "$DISCLOSURE_SCENARIO_ID" -e "$APIDOG_ENV_ID" -r cli,html
단언이 실패하면 0이 아닌 값으로 종료되므로, 필드를 삭제하는 병합은 배포되지 않고 빌드 실패로 이어집니다. 전체 파이프라인 설정은 GitHub Actions에서 API 테스트 자동화에 있으며, 일반적인 단언 패턴은 API 단언에 있습니다. 자신의 엔드포인트에 대해 시나리오를 구축하려면 Apidog 다운로드.
호출자가 찾는 곳에 문서화하기
두 대상, 두 장소.
참조 문서에. 스키마 설명은 제대로 작성하면 대부분의 작업을 수행합니다. 추상적인 의미가 아니라 제품에서 assisted가 무엇을 의미하는지 설명하십시오. 라벨이 필요한지 여부를 결정하는 호출자는 법적 결정을 내리기 위해 그 문장을 읽고 있습니다.
짧은 정책 페이지에. 어떤 엔드포인트가 모델 출력을 반환할 수 있는지, 어떤 모델을 사용하는지, 인간 검토가 발생하는지 그리고 그 의미는 무엇인지, 그리고 무엇을 보증하고 보증하지 않는지를 다루는 한 페이지를 만드십시오. 참조 문서에서 링크하고 버전을 관리하십시오.
제한 사항에 대해 구체적으로 설명하십시오. Claude 출력을 전달하는 경우, 텍스트에는 스스로 검증할 수 없는 내장된 워터마크가 포함되어 있으며 Anthropic은 감지 기능을 공개하지 않았습니다. 그러한 사실을 밝히는 것이 귀하가 가지고 있지 않은 검증 능력을 암시하는 것보다 낫습니다. 그 이유는 Claude의 워터마크를 감지하는 방법에 있습니다.
대화형 문서는 여기에서 평소보다 더 도움이 됩니다. 왜냐하면 호출자가 테이블을 신뢰하는 대신 라이브 응답에서 공개 필드를 볼 수 있기 때문입니다. 콘솔 체험 기능이 있는 대화형 API 문서 호스팅이 이 설정을 다룹니다.
자주 묻는 질문 (FAQ)
X-AI-Generated 헤더가 표준인가요? 아닙니다. AI 공개를 위한 승인된 표준 헤더는 없습니다. 이름을 정하고, 문서화하고, 일관성을 유지하며, 계약의 일부로 취급하십시오.
공개는 헤더에 있어야 하나요, 아니면 본문에 있어야 하나요? 둘 다입니다. 본문은 저장되고 전달되는 내용입니다. 헤더는 프록시, 게이트웨이, 로그 및 비JSON 응답에 사용됩니다. 둘이 불일치하는 경우 어떤 것이 정식(canonical)인지 문서화하십시오.
법적으로 이것을 해야 하나요? 귀하의 역할과 콘텐츠에 따라 다릅니다. 제50조의 의무는 제공업체와 배포업체에 다르게 적용되며, 50조(4)항은 인간 편집 통제에 대한 면제 조항이 있는 딥페이크 및 공공 이익 텍스트에 한정됩니다. API 개발자를 위한 EU AI 법 제50조에서 자세히 설명합니다. 법률적 판단은 변호사의 몫이고, 구현은 귀하의 몫입니다.
제공업체가 이미 출력물에 워터마크를 찍습니다. 이것만으로 충분하지 않나요? 아닙니다. 워터마크는 현재 귀하의 호출자가 텍스트에 대해 읽을 수 없는 기계 판독 가능한 신호이며, 배포자로서 귀하의 공개 의무를 충족시키지 못합니다. 이는 보완책이지 대체제가 아닙니다.
스트리밍 응답은 어떻게 해야 하나요? 공개 내용을 응답 헤더나 첫 번째 이벤트에 넣으십시오. 호출자는 토큰이 도착하는 대로 렌더링하므로 끝까지 기다릴 필요가 없습니다.
생성 후 사람이 편집한 콘텐츠는 어떻게 처리하나요? 그것이 assisted와 human_review가 필요한 이유입니다. 제50조(4)항은 편집 책임이 있는 인간 검토 하의 콘텐츠에 대한 면제 조항이 있으므로, 이를 정확하게 기록하는 것이 단일 불리언 값보다 더 중요합니다.
이 필드에 버전을 매겨야 하나요? 이 필드는 응답 스키마의 일부이므로, 나머지 스키마와 동일하게 버전을 관리하십시오. 열거형 값을 추가하는 것은 호출자가 알아야 할 변경 사항이며, CI의 사양 diff가 이를 알려줄 것입니다.
핵심 요약
AI 공개는 UI 기능으로서는 실패하고 계약으로서는 작동합니다. 응답에 필수 필드를 넣고, 헤더에 미러링하며, OpenAPI 사양에 한 번 정의하고, 항상 누락되는 캐시된, 오류, 배치 및 대체 경로에서 이를 단언하십시오.
이것은 아마도 오후 한나절 작업일 것이며, 마케팅의 주장을 호출자가 기반으로 삼고 테스트가 강제할 수 있는 것으로 전환할 것입니다.
