최신 문서를 줘도 옛날 코드를 쓰는 AI
Next.js 15 코드를 짜달라고 했다. 그런데 응답이 어쩐지 미묘하다. getServerSideProps가 있고, pages/ 디렉터리 가정이 깔려 있다. 13까진 맞는 코드인데 15 기준으론 틀린 코드다.
공식 문서를 통째로 컨텍스트에 붙였다. "이 문서를 따라라"라고 명시했다. 답은 살짝 달라진다. 그런데 한두 줄만 따라가다 슬그머니 익숙한 옛날 패턴으로 돌아가고 만다.
솔직히 처음엔 내 프롬프트가 부실한 탓인 줄 알았다. 이런 경험을 해봤다면 AI 코딩 에이전트의 한계가 단순한 "지식 부족"은 아니라는 감이 올 것 같다. 모르는 게 아니라, 알고 있는 걸 잘 못 내려놓는 쪽에 가깝다.
이건 무지가 아니라 충돌이다
학계는 이 현상에 이름을 붙여놨다. Knowledge Conflict.
LLM 안에는 두 종류의 지식이 공존한다. 하나는 가중치에 박혀 있는 parametric knowledge, 학습 데이터가 모델 파라미터에 압축돼 들어간 지식이다. 다른 하나는 contextual knowledge, 추론 시점에 프롬프트로 주어지는 지식이다. RAG, 시스템 프롬프트, 첨부한 문서, 전부 여기 들어간다.
평소엔 둘이 맞물려 돌아간다. 그런데 둘이 충돌하는 순간, 모델은 한쪽을 골라야 한다. 그리고 모델은 자주, 자기가 학습한 쪽을 고른다.
EMNLP 2024 서베이 논문 Knowledge Conflicts for LLMs는 이 충돌을 정식으로 정의하고 분류했다. 학계가 이걸 따로 연구 주제로 잡았다는 건, 한두 모델의 결함이 아니라 LLM 구조에 딸려오는 성질이라는 뜻이다.
명시적으로 지시해도 안 통한다
여기서 제일 골치 아픈 대목은 이거다. 모델에게 명시적으로 "주어진 컨텍스트를 따르고 네 지식을 무시해라"라고 시켜도, 완전히 억누르지 못한다.
Understanding the Interplay between Parametric and Contextual Knowledge는 이 비대칭을 정량적으로 측정했다. 문맥과 내부 지식이 충돌할 때, 모델 성능은 둘이 일치할 때보다 일관되게 떨어진다. 컨텍스트만 따르라고 강하게 지시해도 그렇다. 반대로 "네 지식을 써라"라고 했을 때도, 모델은 이미 컨텍스트가 있으면 그걸 완전히 무시하지 못한다. 어느 한쪽으로도 깔끔하게 정리되지 않는다.
Task Matters라는 후속 연구는 더 정밀하게 들어간다. 충돌의 영향은 작업 종류에 따라 다르다. 지식이 거의 필요 없는 작업(요약, 포맷 변환)에선 컨텍스트를 잘 따른다. 그런데 knowledge-intensive 작업, 그러니까 모델이 많이 학습한 영역에 들어가는 순간, 충돌이 성능을 크게 떨어뜨린다.
코딩이 정확히 이 영역이다. API, 라이브러리 시그니처, 문법, 베스트 프랙티스. 모델이 가장 많이 학습한 영역이다. 그래서 가장 강하게 자기 지식을 신뢰한다.
세 가지 충돌
서베이는 충돌을 세 종류로 나눈다. 셋 다 코딩 에이전트에서 매일 일어난다.

Context-memory conflict. 컨텍스트와 모델 내부 지식이 부딪힌다. 가장 흔한 케이스다. 최신 문서를 붙여줬는데 모델은 학습 시점의 옛날 API로 돌아간다.
Inter-context conflict. 컨텍스트 안의 정보끼리 부딪힌다. README엔 v3 예제가 있는데 코드베이스엔 v2가 깔려 있을 때. 사용자가 붙인 문서 두 개의 버전이 다를 때. 모델은 어느 쪽을 따라야 할지 결정 못 하고 둘을 어색하게 섞어버린다.
Intra-memory conflict. 모델 내부 지식 자체가 일관되지 않다. 같은 질문을 살짝 다르게 물어보면 다른 답이 나온다. 학습 데이터에 들어 있는 여러 시점, 여러 버전의 정보가 가중치 안에서 단일한 답으로 수렴되지 못한 결과다.
세 충돌이 겹치면 디버깅하다 머리를 싸매게 된다. 모델이 왜 그 코드를 썼는지 되짚을 방법이 마땅치 않다. 사용자 컨텍스트 탓인지, 학습 지식 탓인지, 학습 지식 안의 어느 시점 탓인지.
코딩 에이전트에서 제일 심하다
When LLMs Lag Behind는 코드 생성 영역에서 이 충돌이 어떻게 작동하는지 측정했다. 결론은 이렇다. 라이브러리 API가 바뀌면 모델이 잘 못 따라간다. 최신 스펙을 프롬프트로 주입해도 마찬가지다. 모델은 자주 예전에 학습한 지식으로 되돌아간다. 업데이트 설명만 줬을 때 실행되는 코드는 평균 42.55%였다. 문서를 통째로 붙여줘도 66.36%까지밖에 오르지 않았다. 스펙을 다 줘도 세 번에 한 번은 실행조차 안 된다는 뜻이다.

여기서 짚어둘 건 이게 "knowledge cutoff"와는 다른 문제라는 점이다. 컷오프는 모르는 것의 문제고 이건 아는 걸 잘 못 내려놓는 것의 문제다. 결이 좀 다르다.
컷오프는 RAG로 풀린다. 최신 정보를 컨텍스트에 넣어주면 된다. 그런데 Knowledge Conflict는 RAG로 잘 안 풀린다. 정보를 넣어줘도 모델이 그걸 자기 지식보다 덜 신뢰하면 소용이 없다. RAG는 모델이 모를 때 가장 잘 듣고, 모델이 안다고 여기는 영역에서는 덜 듣는다.
RAG로는 안 풀린다
돌이켜보면 지난 2-3년간 LLM 업계는 RAG를 일종의 만능 해결책처럼 다뤘다. 환각이 문제? RAG로 풀어라. 최신성? RAG. 도메인 특화? RAG.
이 낙관에는 전제가 하나 깔려 있었다. 모델은 컨텍스트에 정답이 있으면 그걸 충실히 쓴다는 것.
그런데 Knowledge Conflict 연구가 보여주는 건 그 가정이 부분적으로만 참이라는 거다. 모델이 자기 지식이 없는 영역에서는 RAG가 잘 작동한다. 모르는 사람의 위키피디아 문서를 붙여주면 그걸 충실히 인용한다. 그런데 모델이 강하게 학습한 영역, 코딩처럼 자신감이 높은 영역에선 모델이 자기가 학습한 쪽을 앞세워 RAG로 넣어준 정보를 부분적으로 무시해버린다.
기업 RAG 시스템의 성능이 데모와 프로덕션에서 자주 갈리는 데는 이런 이유도 있지 싶다. 데모는 모델이 모르는 영역(회사 내부 문서)에서 만들어지는데, 실제 사용자는 모델이 강하게 학습한 영역(일반 코딩, 일반 지식)에서 답을 받기 때문이다. 후자에선 모델이 컨텍스트보다 자기가 학습한 쪽을 자주 앞세운다.
그럼 어떻게 해야 하나
이 문제는 프롬프트를 더 잘 쓰는 정도로는 잘 안 풀리는 것 같다. 모델 구조 차원의 비대칭이라 지금은 부분적으로 완화하는 정도가 현실적이라고 본다.
이런저런 삽질 끝에 실무에서 건진 건 이 정도였다.
충돌 영역을 의식하고 설계한다. 모델이 강한 영역(주류 라이브러리, 표준 패턴)일수록 컨텍스트 우선이 잘 안 통한다고 보고 시작한다. 핵심 API는 코드 예제로 못 박아둔다. 설명만 주는 게 아니라, "이 시그니처를 정확히 이렇게 호출해라"라는 구체 예시를 함께 준다. 두루뭉술한 지시만으로는 모델의 prior를 밀어내기가 어려웠다.
컨텍스트 안의 충돌을 줄인다. Inter-context conflict는 우리가 통제할 수 있는 영역이다. 버전이 다른 문서를 동시에 넣지 않는다. 코드베이스의 실제 버전과 붙이는 문서의 버전을 일치시킨다. "정답이 어딨는지"를 모델이 추측하지 않게 만든다.
모델이 자기 지식을 쓴 흔적을 검출한다. 생성 결과를 그대로 신뢰하지 않고, 실제로 컨텍스트에 있는 식별자만 등장하는지 검증하는 단계를 둔다. 코딩이라면 타입 체크, 린터, 컴파일이 그 역할을 해준다. 써보니 AI 코딩 에이전트는 만드는 쪽보다 걸러내는 쪽에서 더 도움이 됐다.
물론 모델 쪽에서도 변화가 있다. 앞으로 나올 모델들은 instruction following을 더 강하게 훈련받는다. 일부 최신 모델들은 이미 컨텍스트 우선 행동을 명시적으로 학습한다. 이게 일관되게 작동하기 시작하면 우리가 지금 겪는 답답함의 상당 부분이 줄어들 거다. 다만 아직 거기까지 못 왔다.
우리가 만든 모순
LLM은 처음부터 "많이 아는 것"을 목표로 훈련됐다. 데이터를 늘리고 파라미터를 키우고 더 많은 사실을 가중치에 집어넣었다. 모델이 똑똑하다는 말은 곧 "내부에 정보가 많다"는 뜻이었다.
그런데 에이전트 시대로 들어오면서 요구가 뒤집혔다. 우리는 이제 모델이 자기가 아는 걸 일단 내려놓고 지금 주어진 컨텍스트를 따라주길 원한다. 코드베이스의 실제 버전을 따르고 우리 회사의 실제 문서를 따르고 우리가 방금 붙인 최신 스펙을 따라야 한다. 모델이 가진 "일반 지식"은 오히려 방해가 된다.
학습 목표와 쓰는 쪽의 요구가 어긋났다. 모델은 많이 아는 걸로 보상받았는데, 그런 모델한테 필요할 땐 좀 잊어달라고 하는 셈이다. 이 비대칭이 풀리지 않는 한, RAG도 긴 컨텍스트 윈도우도 반쪽짜리 답이다.
그래서 병목은 토큰 수가 아니라 신뢰 우선순위 쪽이다. 모델이 자기가 학습한 걸 얼마나 쉽게 내려놓느냐. 이걸 훈련 목표에 어떻게 넣느냐에 따라 다음 세대 모델의 차이가 꽤 클 것 같다.
지금 "프롬프트 엔지니어링"이라 부르는 일도 절반쯤은 이 줄다리기다. 모델의 prior와 우리가 주는 컨텍스트 중 어느 쪽을 앞에 세울지 매번 다시 정하는 일. 같은 모델을 쓰는데도 결과가 갈리는 이유가 대체로 여기 있다.
참고 자료
- Knowledge Conflicts for LLMs: A Survey (EMNLP 2024)
- Understanding the Interplay between Parametric and Contextual Knowledge for Large Language Models
- Task Matters: Knowledge Requirements Shape LLM Responses to Context-Memory Conflict
- When LLMs Lag Behind: Knowledge Conflicts from Evolving APIs in Code Generation