GenAI 개발의 오류 #5: 더 나은 컨텍스트가 환각을 방지한다
요약
생성형 AI 개발 시 더 많은 컨텍스트와 RAG를 제공하면 환각이 완전히 사라질 것이라는 오해를 다룹니다. 컨텍스트가 환각을 줄일 수는 있지만, 모델이 훈련 데이터의 패턴을 우선시하여 검색된 정보를 무시할 수 있다는 점을 경고합니다.
핵심 포인트
- 더 나은 컨텍스트는 환각을 줄이지만 완전히 제거하지는 못함
- 모델이 훈련 데이터의 패턴을 검색된 컨텍스트보다 우선시할 수 있음
- RAG를 통한 정보 제공이 항상 정확한 출력으로 이어지지는 않음
이 글은 생성형 AI (Generative AI)를 사용하여 구축할 때 팀들이 범하는 잘못된 가정에 관한 8개의 포스트 시리즈 중 다섯 번째 글입니다. 오류 #1은 생성-엔지니어링 격차 (generation-engineering gap)를 다루었습니다. 오류 #2는 그럴듯함(plausible) 대 정확함(correct)을 다루었습니다. 오류 #3은 AI가 AI를 검증하는 문제를 다루었습니다. 오류 #4는 리뷰 게이트 (review gate)를 제거하는 문제를 다루었습니다. 이 포스트는 더 나은 입력이 정확한 출력을 보장한다는 가정에 대해 다룹니다.
오류
"AI에게 더 나은 문서, 최신 API, 그리고 더 많은 컨텍스트 (Context)를 제공하면 환각 (Hallucination)을 일으키지 않을 것이다."
유혹적인 이유
여러분은 이 문제를 직접 목격했을 것입니다. AI에게 API를 호출하라고 요청하면, 폐기된 엔드포인트 (deprecated endpoint)를 사용합니다. 라이브러리 함수를 구현하라고 요청하면, 존재하지 않는 메서드 (method)를 만들어냅니다. 팀의 코딩 컨벤션 (coding conventions)을 따르라고 요청하면, 2019년의 컨벤션을 읽은 것 같은 코드를 생성합니다.
진단은 명확해 보입니다. AI가 올바른 정보를 가지고 있지 않다는 것입니다. 해결책도 명확해 보입니다. 올바른 정보를 제공하는 것입니다. RAG (Retrieval-Augmented Generation)는 AI가 생성하기 전에 관련 문서를 검색합니다. Context Hub 도구들은 최신 API 문서를 가져옵니다. 시스템 프롬프트 (System prompts)는 팀의 컨벤션을 주입합니다. 컨텍스트 윈도우 (Context window)는 AI가 필요로 하는 정보로 채워집니다.
그리고 실제로 작동합니다. AI는 현재 API를 사용하는 코드를 생성합니다. 최신 컨벤션을 따릅니다. 환각 (Hallucination) 발생률이 눈에 띄게 감소합니다. 컨텍스트 인프라 (Context infrastructure)에 대한 투자가 결실을 맺습니다.
그렇다면 무엇이 오류일까요?
이것이 틀린 이유
더 나은 컨텍스트는 환각 (Hallucination)을 줄여줍니다. 하지만 이를 완전히 제거하지는 못합니다. 프로덕션 환경에서의 실패는 '줄어든 상태'와 '제거된 상태' 사이의 간극에서 발생합니다.
컨텍스트가 그 간극을 완전히 메울 수 없는 세 가지 이유가 있습니다:
이유 1: AI가 컨텍스트를 무시할 수 있음
검색 증강 생성 (Retrieval-Augmented Generation, RAG)은 문서를 검색하여 컨텍스트 창 (Context window)에 배치합니다. 모델은 이를 사용하도록 되어 있습니다. 하지만 모델은 훈련 데이터 (Training data)의 패턴이 생성 과정에서 더 자연스럽게 느껴질 경우, 검색된 컨텍스트를 무시하고 훈련 데이터의 패턴을 우선시할 수 있으며, 실제로 그렇게 합니다.
Liu 등 (2023)은 이를 "중간에서 길을 잃는 (lost in the middle)" 문제로 기록했습니다. 관련 정보가 긴 컨텍스트 창의 중간에 위치할 때 LLM의 성능이 현저히 저하되는 현상입니다. 성능은 시작 부분이나 끝 부분에서 가장 높고, 그 사이에서는 떨어집니다. 이것만으로도 "더 많은 컨텍스트"가 "더 높은 정확도"로 이어지는 선형적인 경로가 아님을 증명합니다.
하지만 문제는 위치 편향 (Positional bias)보다 더 깊은 곳에 있습니다. 파라미터 메모리 (Parametric memory) 대 비파라미터 메모리 (Non-parametric memory)에 대한 연구 (Longpre et al., 2021; Neeman et al., 2022)에 따르면, LLM의 내부 훈련 가중치 (Parametric)가 제공된 RAG 컨텍스트 (Non-parametric)와 충돌할 때, 모델은 빈번하게 자신의 훈련 데이터로 회귀하며, 특히 훈련 데이터가 강력하게 강화되었을 때 더욱 그렇습니다. 모델의 내부 가중치는 수십억 개의 패턴을 나타내지만, 컨텍스트 창은 단 몇 천 개의 토큰을 나타냅니다. 이 두 가지가 충돌할 때, 모델은 컨텍스트를 안정적으로 선택하지 못합니다.
여러분은 직접 이를 테스트해 볼 수 있습니다: 모델의 훈련 데이터와 명시적으로 모순되는 문서를 제공하십시오. 그리고 그에 대해 질문하십시오. 모델은 때로는 문서에 따라 답변하고, 때로는 자신의 훈련 데이터에 따라 답변할 것입니다. 그 비율은 모델, 프롬프트 (Prompt), 그리고 구체적인 충돌 내용에 따라 달라집니다. 결코 100% 문서에 기반하여 답변하지 않습니다. 모델은 지시 사항을 읽고 따르는 것이 아닙니다. 모델은 훈련 가중치와 컨텍스트 창을 모두 결합한 모든 입력값을 바탕으로 가장 가능성 높은 다음 토큰을 예측하는 것입니다.
이유 2: 컨텍스트는 필수적이지만, 검증은 별개의 문제임
컨텍스트(Context)는 "AI가 어떤 정보를 사용해야 하는가?"에 답합니다.
검증(Verification)은 "AI가 정보를 올바르게 사용했는가?"에 답합니다.
이것들은 서로 다른 메커니즘을 가진 별개의 질문입니다. 올바른 재료를 가지고 있다고 해서 요리가 반드시 완벽하다는 보장은 없습니다. 완벽한 재료를 가진 요리사라도 재료를 잘못 조합하거나, 단백질을 너무 오래 익히거나, 아예 다른 요리를 접시에 담을 수 있습니다. 재료는 필수적이지만, 맛을 보는 과정(taste test)은 여전히 필요합니다.
최신 벤치마크(benchmarks)들은 이러한 격차를 확인해 줍니다. 검색 증강 생성 벤치마크(Retrieval-Augmented Generation Benchmark, RGB)에 따르면, 모델들은 검색(retrieval)이 100% 정확하더라도 검색된 문서에 대해 올바르게 추론하는 데 자주 실패합니다. 컨텍스트 윈도우(context window)에 올바른 문서를 배치하는 것과 이를 올바르게 사용하는 것은 독립적인 능력이며, 현재의 모델들은 첫 번째 능력이 완벽하더라도 두 번째 능력에서 실패하곤 합니다.
엔지니어링 관점에서는 다음과 같습니다:
컨텍스트 파이프라인(Context pipeline): AI가 올바른 정보를 '가지고 있는지' 보장함
→ 벡터 데이터베이스(vector database), 검색(retrieval), 랭킹(ranking), 주입(injection)
→ 측정 지표: 검색 정확도(retrieval accuracy), 관련성 점수(relevance scores)
...
대부분의 팀은 첫 번째 파이프라인에는 막대한 투자를 하지만, 두 번째 파이프라인을 위해서는 아무것도 준비하지 않습니다. 그들은 검색 품질, 즉 "AI에게 올바른 문서를 제공했는가?"는 측정하지만, 출력의 정확성, 즉 "출력이 충족해야 할 속성(properties)을 만족했는가?"는 측정하지 않습니다.
이는 최고급 식재료를 조달하기 위해 수백만 달러를 투자하고, 모든 공급업체 관계를 추적하며, 시간 단위로 신선도를 모니터링하지만, 완성된 요리에 대한 품질 검사는 전혀 하지 않는 레스토랑과 같습니다. 재료는 세계 최고 수준일지 모르나, 고객에게 전달되는 접시에는 아무런 맛이 없을 수도 있습니다.
이유 3: 컨텍스트는 속성(properties)을 다루지 못함
완벽한 컨텍스트가 있더라도 — 즉, 모든 문서가 검색되고, 모든 API가 최신 상태이며, 모든 컨벤션(convention)이 주입되더라도 — AI에게는 생성된 출력물 전체에 걸쳐 적용되는 속성(PROPERTIES)을 강제할 수 있는 메커니즘이 없습니다.
"이 모듈의 어떤 함수도 타임아웃(timeout) 없이 외부 서비스를 호출해서는 안 된다." 이것은 속성(property)입니다. 이는 어떤 API 문서에도 들어있지 않습니다. 검색된(retrieved) 문서에도 없습니다. 이것은 팀이 내린 아키텍처 결정(architectural decision)입니다. AI는 컨텍스트(context)만으로는 이를 알 방법이 없습니다. 왜냐하면 이것이 검색 가능한 문서로 작성된 적이 없기 때문입니다. 이는 팀의 공유된 이해(shared understanding) 속에 존재합니다.
"이 데이터 파이프라인은 메시지 순서를 보존해야 한다." 이것은 제약 조건(constraint)입니다. 이는 아키텍처에 내재되어 있습니다. 누군가 이를 기록해 두었더라도, RAG는 '그 특정' 생성을 위해 '그 특정' 문서를 검색해야만 합니다. 이러한 속성의 수가 늘어날수록, 적절한 시점에 적절한 생성을 위해 올바른 문서가 검색될 확률은 감소합니다.
컨텍스트는 사실(facts)을 제공할 수 있습니다. 하지만 생성되는 모든 결과물 전체에 걸쳐 유지되어야 하는 속성의 완전한 집합을 제공할 수는 없습니다. 속성은 포괄적입니다("모든 함수는 반드시 타임아웃을 가져야 한다"). 반면 컨텍스트는 샘플링된 것입니다("여기 몇 가지 관련 문서가 있다").
RAG가 속성을 놓치는 데에는 더 깊은 구조적 이유가 있습니다. RAG는 의미론적 유사성(semantic similarity)에 따라 검색합니다. 즉, 의미 공간(meaning space)에서 쿼리와 "가까운" 문서를 찾는 벡터 수학(vector math)을 사용합니다. 보안 불변성(security invariant, 예: "개인정보(PII)를 절대 로그에 남기지 말 것")은 사용자 데이터를 처리하는 함수와 의미론적으로 "멀리" 떨어져 있습니다. 벡터 공간에서 이들은 유사하지 않습니다. RAG 시스템은 해당 특정 생성을 위해 보안 규칙을 결코 검색하지 못합니다. 보안 제약 조건과 구현 코드는 임베딩(embeddings) 상에서 서로 닮지 않았기 때문입니다. 사실은 그것을 사용하는 코드 근처에 존재합니다. 하지만 속성은 완전히 다른 의미론적 이웃(semantic neighborhood)에 존재합니다.
Mishra 등(2022)은 이와 관련된 실패 사례를 입증했습니다. LLM은 지시 사항 내의 부정(negation)과 제약 조건(constraints)을 처리하는 데 상당한 어려움을 겪습니다. "개인정보(PII)를 절대 로그에 남기지 말 것"은 부정적 속성(negative property)입니다. 제약 조건이 컨텍스트에 명시적으로 포함되어 있더라도, 모델의 학습 데이터는 부정적인 예시("X를 절대 하지 마라")가 아닌, 거의 전적으로 긍정적인 예시("Y를 하라")로 구성되어 있습니다. 컨텍스트는 제약 조건을 제공하지만, 모델의 아키텍처는 이를 따르지 않는 방향으로 편향되어 있습니다.
붐 (The boom)
1~3개월 차: 컨텍스트 투자. 팀은 정교한 RAG (Retrieval-Augmented Generation, 검색 증강 생성) 파이프라인을 구축합니다. 벡터 데이터베이스 (Vector database), 문서 전처리 (Document preprocessing), 청크 최적화 (Chunk optimization), 관련성 점수 산정 (Relevance scoring) 등이 포함됩니다. AI는 더 나은 코드를 생성합니다. 환각 (Hallucination) 발생률이 15%에서 5%로 떨어집니다. 팀은 이러한 개선을 기념하는 내부 블로그 포스트를 게시합니다.
4~6개월 차: 중요한 5%. 남은 5%의 환각은 무작위로 발생하지 않습니다. 이는 어려운 사례들에 집중되어 있습니다. 즉, 컨텍스트가 학습 데이터 (Training data)와 충돌하는 경우, 속성이 검색 가능한 문서 어디에도 없는 경우, AI가 개별 사실을 패턴 매칭 (Pattern-match)하는 대신 구성 (Composition)에 대해 추론해야 하는 경우들입니다. 이러한 사례들은 불균형적으로 운영 환경의 장애 (Production incidents)를 일으키는 원인이 됩니다.
7~9개월 차: 잘못된 자신감으로 인한 장애. 한 개발자가 새로운 기능을 위한 코드를 생성합니다. RAG는 올바른 API 문서를 검색합니다. AI는 올바른 API 엔드포인트 (Endpoint)를 사용합니다. 코드는 컴파일됩니다. 테스트도 통과합니다. 하지만 이 코드는 아키텍처 제약 조건 (Architectural constraint)을 위반합니다. 트랜잭션 (Transaction) 내부에서 타임아웃 (Timeout) 설정 없이 외부 서비스에 동기식 호출 (Synchronous call)을 수행한 것입니다. 검색된 컨텍스트 어디에도 타임아웃 요구 사항에 대한 언급은 없었습니다. 해당 제약 조건은 팀의 아키텍처 결정 기록 (Architecture decision records)에 있었으나, 벡터 데이터베이스에 인덱싱 (Indexed)되지 않았습니다. 서비스가 멈춥니다. 데이터베이스 커넥션 풀 (Connection pool)이 고갈됩니다. 장애는 4시간 동안 지속됩니다.
여기에 잔인한 아이러니가 있습니다. 더 나은 컨텍스트가 환각을 줄이기는커녕 오히려 더 위험하게 만들었습니다. 코드는 올바른 API를 사용했습니다. 올바른 컨벤션 (Conventions)을 따랐습니다. RAG 없이 생성된 코드보다 훨씬 더 올바르게 보였고, 이는 모두가 그 코드를 더 신뢰하게 만들었습니다. 더 나은 컨텍스트는 AI가 위반 사항을 생성하는 것을 막지 못합니다. 단지 AI가 그 위반 사항을 감쌀 수 있는 더 나은 사실들을 제공할 뿐입니다. 그럴듯함 (Plausibility)은 올라가고, 정밀한 검토 (Scrutiny)는 줄어들며, 피해는 커집니다.
사후 분석 (Post-mortem): "우리는 올바른 컨텍스트 (Context)를 가지고 있었습니다. AI는 올바른 API를 사용했습니다. 하지만 우리가 타임아웃 제약 조건 (Timeout constraint)을 검색 (Retrieve)하지 않았기 때문에 AI는 이를 알지 못했습니다. 그리고 우리가 그것을 인덱싱 (Index)하지 않았기 때문에 검색하지 못했습니다. 그리고 우리가 그것이 필요하다는 사실을 몰랐기 때문에 인덱싱하지 않았습니다."
이 사후 분석은 구조적 격차를 드러냅니다. 컨텍스트는 AI가 무엇을 '로부터 (FROM)' 생성하는지를 개선합니다. 하지만 AI가 생성한 것이 무엇과 '대조하여 (AGAINST)' 맞는지 검사하지는 않습니다. 검색된 문서들은 정확했습니다. 생성된 코드는 그럴듯했습니다 (Plausible). 위반된 속성 (Property)은 컨텍스트 파이프라인 (Context pipeline)에 전혀 포함되지 않았으며, 이를 잡아낼 검증 파이프라인 (Verification pipeline)도 존재하지 않았습니다.
10개월 차, 그에 대한 대응: 팀은 벡터 데이터베이스 (Vector database)에 ADR (Architecture Decision Records)을 인덱싱합니다. RAG (Retrieval-Augmented Generation) 파이프라인에 더 많은 문서를 추가합니다. 컨텍스트가 좋아집니다. 하지만 다음 사고는 인덱싱되지 않은 또 다른 속성 때문에 발생합니다. 두더지 잡기 (Whack-a-mole) 사이클이 시작됩니다. 각 사고는 컨텍스트에 포함되었어야 했지만 포함되지 않았던 속성을 드러냅니다. 팀은 무엇이 중요한지에 대한 완전한 목록을 가지고 있지 않기 때문에 모든 것을 인덱싱할 수는 없습니다.
해결책: 입력뿐만 아니라 출력을 검증하라
컨텍스트와 검증은 상호 보완적입니다. 둘 다 필요합니다. 하지만 어느 하나만으로는 충분하지 않습니다.
입력 품질 (Input Quality, 컨텍스트):
"AI에게 올바른 정보를 제공하라"
→ RAG, 컨텍스트 허브 (Context Hub), 최신 문서, 시스템 프롬프트 (System prompts)
...
컨텍스트에만 투자하는 팀은 입력 품질을 최적화하며 출력의 정확성 (Output correctness)이 뒤따라오기를 희망합니다. 때로는 그렇게 됩니다. 하지만 그렇지 않은 5%의 영역에서 사고가 발생합니다.
검증을 추가하는 팀은 출력이 어떻게 생성되었는지와 '상관없이 (REGARDLESS)' 출력을 검사합니다. AI가 완벽한 컨텍스트를 가졌든 혹은 컨텍스트가 전혀 없었든 간에, 검증은 위반 사항을 잡아냅니다. 왜냐하면 검증은 입력 (Inputs)이 아니라 속성 (Properties)을 확인하기 때문입니다.
주방 비유, 완성
컨텍스트 = 재료
더 좋은 재료 → 좋은 요리가 될 확률이 높아짐
하지만: 요리사가 여전히 재료를 잘못 조합할 수 있음
...
검증(verification)에 대한 투자 없이 RAG(Retrieval-Augmented Generation)에만 투자하는 것은, 최고의 식재료를 조달하면서도 음식이 고객에게 전달되기 전에 요리사가 맛을 보지 않는 레스토랑과 같습니다. 대부분의 요리는 괜찮을 것입니다. 하지만 문제가 있는 요리들은 고객의 기억에 남게 될 것입니다.
컨텍스트 파이프라인이 대체할 수 없는 것
더 나은 컨텍스트로도 해결할 수 없는 다섯 가지 범주의 문제들:
1. 구성적 정확성 (Compositional correctness). AI가 함수 A를 올바르게 생성하고(올바른 컨텍스트 검색됨), 함수 B를 올바르게 생성합니다(올바른 컨텍스트 검색됨). 하지만 A와 B의 구성이 교차 속성(cross-cutting property)을 위반합니다. RAG 파이프라인 내의 어떤 개별 문서도 이 구성을 다루지 않습니다. 왜냐하면 해당 속성은 단일 구성 요소가 아닌, 요소 간의 상호작용에서 발생하기 때문입니다.
2. 아키텍처 제약 사항 (Architectural constraints). "모든 서비스 간 호출은 데드라인 전파(deadline propagation)를 포함한 gRPC를 사용해야 한다." 이는 조직의 결정이지, 문서에 적힌 사실이 아닙니다. 인덱싱되어 있더라도, RAG는 서비스 호출이 포함된 모든 생성 과정에서 이를 검색해야 합니다. 단 한 번의 검색 누락이 곧 한 번의 위반으로 이어집니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기