본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 01. 20:27

생성형 AI 개발의 오류 #3: 다른 AI로 AI의 출력을 검증할 수 있다

요약

생성형 AI 개발 시 다른 AI를 사용하여 출력을 검증하는 방식의 위험성을 경고합니다. 동일한 클래스의 모델은 유사한 실패 모드를 공유하므로, 단순한 LLM-as-judge 방식은 환각이나 보안 문제를 해결하기보다 오히려 문제를 복잡하게 만들 수 있습니다.

핵심 포인트

  • LLM은 외부 피드백 없이 스스로의 추론을 신뢰성 있게 수정하기 어려움
  • 검증용 AI도 생성용 AI와 동일한 환각 및 패턴 매칭 오류를 가질 수 있음
  • 효과적인 검증을 위해서는 형식 검증기나 이질적인 추론 엔진이 필요함
  • LLM-as-judge 패턴은 심층 방어처럼 보이지만 근본적 해결책이 아님

이 글은 생성형 AI (Generative AI)를 사용하여 구축할 때 팀들이 범하는 잘못된 가정에 관한 8개의 포스트 시리즈 중 세 번째 글입니다. 오류 #1에서는 왜 더 빠른 생성 (Generation)이 더 빠른 엔지니어링을 의미하지 않는지를 다루었습니다. 오류 #2에서는 왜 그럴듯해 보이는 것이 정답이 아닌지를 다루었습니다. 이 포스트에서는 왜 하나의 AI를 사용하여 다른 AI를 체크하는 것이 문제를 해결하지 못하고, 오히려 문제를 두 배로 만드는지를 다룹니다.

오류

"AI가 실수를 한다면, 다른 AI를 사용하여 그 작업을 확인하라."

Huang et al. (ICLR 2024)은 LLM (Large Language Models)이 외부 피드백 없이는 자신의 추론 (Reasoning)을 신뢰성 있게 스스로 수정할 수 없으며, 어떤 경우에는 자기 수정 (Self-correction)이 출력을 더 악화시킨다는 것을 보여주었습니다. LLM-as-judge (판사로서의 LLM)는 이것의 특수한 사례입니다. 즉, 오류를 생성했던 것과 동일한 추론 방식을 사용하여 자신의 출력을 평가하는 동일한 클래스의 시스템인 것입니다. 논문에서 요구된다고 명시한 외부 피드백은 형식 검증기 (Formal verifiers), 스키마 검증기 (Schema validators), 그리고 이질적인 추론 엔진 (Dissimilar reasoning engines)을 통해 제공됩니다.

왜 유혹적인가

이 논리는 매우 완벽해 보입니다. 당신은 리뷰 없이 코드를 배포하는 단 한 명의 개발자를 신뢰하지 않을 것입니다. 그래서 리뷰어를 추가합니다. AI 시스템에서 리뷰어는 또 다른 AI — 가드레일 (Guardrail), 채점자 (Grader), 또는 LLM-as-judge입니다. 첫 번째 AI가 생성하고, 두 번째 AI가 확인합니다. 두 개의 의견이 하나보다 낫습니다.

업계에서는 이를 명명된 패턴으로 공식화했습니다:

  • 입력에 대한 가드레일 (Guardrails on input): 메인 LLM이 프롬프트를 처리하기 전에 LLM이 사용자의 프롬프트가 안전한지 확인합니다.
  • 출력에 대한 가드레일 (Guardrails on output): 사용자가 확인하기 전에 LLM이 메인 LLM의 응답이 적절한지 확인합니다.
  • LLM-as-judge: 채점용 LLM이 루브릭 (Rubric)에 따라 메인 LLM 출력의 품질을 점수화합니다.
  • AI 코드 리뷰 (AI code review): LLM이 AI가 생성한 코드의 버그, 보안 문제 및 스타일을 리뷰합니다.

각 패턴은 검증 계층을 추가합니다. 각 계층은 또 다른 LLM 호출입니다. 이 아키텍처는 심층 방어 (defense in depth)처럼 보입니다.

왜 잘못되었는가

검증기 (verifier)는 검증 대상이 되는 대상과 동일한 실패 모드 (failure modes)를 가집니다.

다른 LLM의 출력에서 환각 (hallucination)을 확인하는 LLM 자체가 환각을 일으킬 수 있습니다. 프롬프트 인젝션 (prompt injection)을 확인하는 LLM 자체가 프롬프트 인젝션을 당할 수 있습니다. 보안 취약점을 위해 코드를 리뷰하는 LLM은 생성 LLM이 도입한 것과 동일한 미묘한 패턴을 놓칠 수 있습니다. 왜냐하면 두 모델 모두 동일한 작업, 즉 텍스트에 대한 패턴 매칭 (pattern matching)을 수행하고 있기 때문입니다.

이것은 심층 방어 (defense in depth)가 아닙니다. 심층 방어는 각 계층이 서로 다른 실패 모드를 가져야 합니다. 방화벽 (firewall)과 침입 탐지 시스템 (IDS)은 실패 방식이 다르기 때문에 심층 방어를 제공합니다. 방화벽은 새로운 프로토콜에서 실패하고, IDS는 암호화된 페이로드 (payload)에서 실패합니다. 두 실패 모드는 서로 겹치지 않습니다.

두 LLM은 중첩되는 (OVERLAPPING) 실패 모드를 가집니다. 둘 다 환각을 일으킵니다. 둘 다 적대적 입력 (adversarial inputs)에 취약합니다. 둘 다 텍스트에서는 보이지 않는 수학적 속성을 놓칩니다. 둘 다 그럴듯함 (plausibility)을 정확성 (correctness)과 혼동합니다. 두 번째 LLM을 추가한다고 해서 실패 모드가 제거되는 것이 아닙니다. 오히려 실패 모드의 또 다른 인스턴스를 추가하는 것뿐입니다.

중첩된 확률의 수학

만약 생성 LLM의 신뢰도가 95%이고 가드레일 (guardrail) LLM의 신뢰도가 95%라면, 결합된 신뢰도는 (독립적인 실패 모드일 때처럼) 99.75%가 아닙니다. 결합 신뢰도는 95%에 더 가까운 어딘가에 위치합니다. 왜냐하면 실패 모드가 상관관계 (correlated)를 갖기 때문입니다. 생성기가 실패하는 사례는 가드레일 또한 실패하는 사례와 불균형적으로 일치하는데, 이는 두 모델 모두 동일한 범주의 어려운 입력값들을 처리하는 데 어려움을 겪기 때문입니다.

하나의 LLM(Large Language Model)을 속이는 입력값은 종종 다른 LLM도 속이는 입력값입니다. 복잡한 조건 로직을 통해 Principal: *와 수학적으로 동일한 정책은 생성기(Generator)를 속이며(수학을 이해하지 못함), 가드레일(Guardrail) 또한 속입니다(이 역시 수학을 이해하지 못함). 정당한 시스템 지침으로 위장한 프롬프트 인젝션(Prompt injection)이 입력 가드레일을 우회하는 이유는 메인 모델을 우회하는 이유와 동일합니다. 두 모델 모두 이를 그럴듯한 텍스트로 처리하기 때문입니다.

프롬프트 인젝션 사례

이것은 문제를 구체화합니다. Fowler/Subramaniam의 GenAI 패턴 기사에서는 프롬프트 인젝션을 방지하기 위해 입력에 대한 가드레일을 권장합니다. 해당 아키텍처는 다음과 같습니다:

사용자 프롬프트 → 가드레일 LLM ("이것은 안전한가?") → 메인 LLM → 응답

가드레일 LLM은 사용자의 프롬프트를 읽고 인젝션 시도가 포함되어 있는지 여부를 결정합니다. 하지만 가드레일 또한 텍스트를 처리하는 LLM입니다. 하나의 LLM에게 정당하게 읽히는 충분히 영리한 인젝션은 다른 LLM에게도 정당하게 읽힐 것입니다. 왜냐하면 두 모델 모두 동일한 종류의 텍스트 패턴 매칭(Text pattern matching)을 수행하고 있기 때문입니다.

이제 대안적인 아키텍처를 고려해 보십시오. 자유 형식의 텍스트(Free-text) 프롬프트 접점 대신, 타입이 지정된 RPC 메서드를 노출하는 방식입니다:

에이전트 호출: search(query="s3 buckets", scope="production")
에이전트 호출: verify(property="no_public_access", resource="arn:aws:s3:::data")
에이전트 호출: compliance(framework="hipaa", account="prod-account")

여기에 인젝션할 프롬프트는 존재하지 않습니다. 에이전트는 타입이 지정된 파라미터를 수용하고 구조화된 데이터를 반환하는 타입 지정 메서드를 호출합니다. 방어 수단은 또 다른 LLM이 아니라 타입 시스템(Type system)입니다. 아키텍처에 자유 형식의 텍스트 채널이 없기 때문에 공격 표면(Attack surface) 자체가 존재하지 않습니다.

프롬프트 인젝션이 완화된 것이 아닙니다. 구조적으로 도달 불가능해진 것입니다. 아키텍처에 공격이 존재할 수 있는 표면이 없습니다.

9가지 Fowler 완화책에 걸친 패턴

이것은 단지 프롬프트 인젝션에 국한된 문제가 아닙니다. 모든 반응형 GenAI 패턴은 동일한 구조적 한계를 공유합니다:

반응형 패턴 (Reactive pattern)역할신뢰성 수렴이 어려운 이유
RAG환각 (Hallucination)을 줄이기 위해 컨텍스트 제공LLM이 여전히 컨텍스트를 무시할 수 있음
...

각 패턴은 비결정론적 (Non-deterministic) 시스템을 또 다른 비결정론적 계층으로 감싸는 방식입니다. 각 계층은 비용과 지연 시간 (Latency)을 추가합니다. 그 어떤 것도 근본적인 비신뢰성을 구조적으로 도달 불가능하게 만들지 못합니다. 이들은 실패 확률을 줄일 뿐, 실패 모드 (Failure mode) 자체를 제거하지는 못합니다.

붐 (The boom)

AI로 AI를 검증하는 방식에 의존하는 팀들은 특정한 벽에 부딪힙니다: 바로 재귀적 환각 (Recursive hallucination)입니다.

1개월 차: 팀은 배포 전 AI가 생성한 IAM 정책을 확인하기 위해 LLM 가드레일 (Guardrail)을 배포합니다. 가드레일은 와일드카드 주체 (Wildcard principals), 누락된 조건(Missing conditions)과 같은 명백한 문제들을 잡아냅니다. 경영진은 만족합니다. AI가 AI를 검토하고 있으니까요.

3개월 차: 미묘한 정책 변경 사항이 생성기와 가드레일을 모두 통과합니다. 정책의 조건 블록 (Condition blocks)들이 함께 평가되었을 때 수학적으로 Principal: *와 동일합니다. 어느 LLM도 이 수학적 원리를 이해하지 못합니다. 둘 다 텍스트의 패턴을 매칭했을 뿐입니다. 텍스트는 제한적인 것처럼 보이지만, 수학적으로는 그렇지 않습니다.

4개월 차: 사고 발생. 정책 구성(Policy composition)을 통해 공개 액세스 경로가 존재함이 드러납니다. 데이터가 노출됩니다.

4개월 차, 사후 분석 (Post-mortem): "왜 가드레일이 이것을 놓쳤는가?" 가드레일이 정책 텍스트(TEXT)를 읽는 방식이 생성기가 정책 텍스트를 쓰는 방식과 동일하기 때문입니다. 가드레일은 텍스트가 액세스를 제한하는 것처럼 '보이는지'를 확인했을 뿐입니다. 로직(LOGIC)이 액세스를 제한하는지는 확인하지 않았습니다. 당신은 두 개의 독립적인 검증 수단을 가진 것이 아닙니다. 동일한 오류를 서로에게 반사하는 두 개의 거울을 가졌을 뿐입니다.

5개월 차, 대응: 팀은 가드레일의 결정을 검토하기 위해 세 번째 LLM을 추가합니다. 재귀적 환각은 더욱 깊어집니다. 비용은 세 배가 됩니다. 지연 시간도 세 배가 됩니다. 상관관계가 있는 실패 모드는 그대로 남아 있습니다. 다음 사고는 세 개의 LLM 모두가 승인하는 또 다른 정책 구성에서 발생할 것입니다. 왜냐하면 세 LLM 모두 로직이 아닌 텍스트의 패턴을 매칭하기 때문입니다.

재귀적 환각 (Recursive hallucination)은 AI 검증 측면에서 무한 루프 (Infinite loop)와 같습니다. 각 반복 단계는 신뢰성을 더하지 못한 채 비용만 추가할 뿐인데, 이는 각 계층이 동일한 범주의 입력값에 대해 실패하기 때문입니다.

결정론적 검증 (Deterministic verification)이란 무엇인가

대안은 더 나은 AI 검증이 아닙니다. 기계적으로 확인할 수 있는 속성들에 대해서는 AI를 전혀 사용하지 않는 검증입니다.

확률적 방식 (LLM-as-judge):
    "이 코드가 보안 정책을 위반합니까?"
    → 채점자의 해석에 따라 달라짐
...

결정론적 검증은 정교함의 각 단계마다 특정한 도구들을 갖추고 있습니다:

타입 체크 (Type checking). 컴파일러 (Compiler)가 타입 계약 (Type contracts)을 검증합니다. 만약 AI가 타입 시그니처 (Type signature)를 위반하는 코드를 생성하면, 컴파일러가 이를 즉각적이고 결정론적으로, LLM 호출 없이 잡아냅니다. 이는 타입이 표현할 수 있는 속성에 대해 위음성 (False negatives) 확률이 전혀 없으면서도 코드 생성 속도와 동일한 속도로 이루어지는 검증입니다.

계약 테스트 (Contract testing). Pact나 Dredd와 같은 도구들은 API 구현이 OpenAPI 명세 (OpenAPI specification)와 일치하는지 검증합니다. 모든 엔드포인트 (Endpoint), 모든 필드 (Field), 모든 응답 코드 (Response code)가 선언된 계약에 따라 기계적으로 확인됩니다. 명세가 신뢰할 수 있는 단일 원천 (Source of truth)이며, 구현은 명세와 일치하거나 일치하지 않거나 둘 중 하나입니다.

속성 기반 테스트 (Property-based testing). QuickCheck나 Hypothesis와 같은 도구들은 수천 개의 무작위로 생성된 입력값에 대해 특정 속성이 유지되는지 검증합니다. "이 특정 입력이 이 특정 출력을 생성하는가?"가 아니라, "도구가 생성할 수 있는 모든 입력에 대해 이 속성이 유지되는가?"를 묻습니다. 이는 예시 기반 테스트 (Example-based testing)보다 한 단계 더 높은 추상화 수준을 가지며, 증명 (Proof)에 한 단계 더 가까운 방식입니다.

정적 분석 (Static analysis). Semgrep, SonarQube, Checkov와 같은 도구들은 코드를 실행하지 않고 코드의 구조적 속성을 확인합니다. "어떤 코드 경로가 정제되지 않은 사용자 입력을 포함한 데이터베이스 쿼리에 도달하는가?" 혹은 "이 Terraform 플랜이 공개 S3 버킷을 생성하는가?"와 같은 사항들을 확인합니다. 이러한 검사들은 전체 코드베이스 또는 인프라 정의에 대해 모든 커밋 (Commit) 시마다 기계적으로 수행됩니다.

형식 검증 (Formal verification). Z3, Dafny, Lean과 같은 도구들은 가능한 모든 (ALL) 입력값에 대해 수학적으로 속성을 증명합니다. "공개된 주체 (public principal)로부터 이 정책이 허용하는 요청이 존재하는가?" 만약 솔버 (Solver)가 UNSAT이라고 답한다면, 그러한 요청은 존재하지 않는 것입니다. 테스트된 것이 아니라 증명된 것입니다. AWS는 이를 (Zelkova) 사용하여 매일 수십억 번의 IAM 정책을 검증합니다.

각 도구는 결정론적 (Deterministic)입니다. 각 도구는 동일한 입력에 대해 매번 동일한 답을 내놓습니다. 각 도구는 LLM-as-judge가 잡아낼 수 없는 범주의 오류를 포착합니다. 왜냐하면 그 오류들은 텍스트적인 것이 아니라 수학적이기 때문입니다.

언제 무엇을 사용할 것인가

모든 속성을 결정론적으로 검증할 수 있는 것은 아닙니다. 의사결정 트리 (Decision tree):

속성을 타입 제약 조건 (Type constraint)으로 표현할 수 있는가?
    → YES: 타입 시스템 (Type system)을 사용하십시오. 가장 저렴하고, 가장 빠르며, 이미 배포되어 있습니다.

...

LLM-as-judge는 주관적인 속성에 적합합니다. 결정론적인 답이 존재하는 속성에는 부적합합니다. 코드가 타입 계약 (Type contract)을 위반하는지 확인하기 위해 LLM을 사용하는 것은, 2 + 2 = 4인지 확인하기 위해 언어 모델을 사용하는 것과 같습니다. 할 수는 있겠지만, 계산기가 더 빠르고, 더 저렴하며, 절대 틀리지 않습니다.

원칙: 속성에 맞는 검증기를 매칭하라

해결책은 검증에 AI를 절대 사용하지 말라는 것이 아닙니다. 각 속성에 맞는 올바른 검증 방법을 사용하라는 것입니다.

주관적인 속성    → LLM-as-judge (확률적, 적절함)
    "이 응답이 도움이 되는가?"
    "이 코드는 스타일이 잘 잡혀 있는가?"
...

보안이 중요하거나, 금융적으로 중요하거나, 데이터 무결성 (Data integrity)이 중요한 시스템에서의 대부분의 속성은 주관적이지 않습니다. 그것들은 결정론적인 답을 가집니다. 그것들을 LLM으로 검증하는 것은 잘못된 도구를 사용하는 것입니다. 왜냐하면 해당 특정 범주에 대해 더 나은 도구가 존재하기 때문입니다.

환멸의 계곡 (Trough of disillusionment)에서 가장 빠르게 벗어나는 팀은 모든 것을 검증하기 위해 AI를 사용하는 것을 멈추고, 각 속성을 그에 적합한 검증 방법과 매칭하기 시작하는 팀이 될 것입니다. 주관적인가? LLM을 사용하십시오. 그 외의 모든 것인가? 기계적 (Mechanical)인 방법을 사용하십시오.

이번 주에 할 수 있는 일

1. 현재의 AI 검증 스택 (Verification Stack)을 감사하십시오. 하나의 LLM이 생성한 출력을 확인하기 위해 또 다른 LLM을 사용하는 모든 지점을 나열하십시오. 각 지점에 대해 다음을 질문하십시오: 확인하려는 속성이 주관적인가(Subjective), 아니면 결정론적인가(Deterministic)? 만약 결정론적이라면

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0