
로직 드리프트 (Logic Drift): 에이전트가 인지하지 못하는 실패 모드
요약
에이전트 기반 코딩에서 발생하는 '로직 드리프트' 현상과 '바이브 코딩'의 위험성을 경고합니다. 에이전트가 프롬프트와 코드를 구분 없이 수정하며 발생하는 구조적 결함을 지적하고, 이를 방지하기 위한 보호된 영역(Protected region)의 필요성을 강조합니다.
핵심 포인트
- 바이브 코딩은 에이전트 기반 코딩의 위험한 실패 모드임
- 에이전트가 코드와 프롬프트를 구분 없이 입력값으로 취급하는 구조적 문제
- 인간의 승인 없이는 수정 불가능한 보호된 영역(Protected region) 필요
- 검증되지 않은 에이전트 의존은 운영 환경의 파괴를 초래할 수 있음
바이브 코딩 (Vibe coding)은 처음 1~2주 동안은 잘 작동합니다. 당신이 원하는 것을 설명하면, 에이전트 (Agent)가 코드를 작성하고, 테스트를 통과하면, 배포하면 됩니다. 하지만 몇 주가 지나면 진행 속도가 절벽처럼 떨어집니다. 새로운 프롬프트 (Prompt)가 기존 기능을 망가뜨리기 시작하는데, 이는 명백한 테스트는 통과하지만 나중에 운영 환경 (Production)에서 드러나는 방식으로 발생합니다.
바이브 코딩 (Vibe coding)은 에이전트를 전적으로 신뢰하고, 코드를 읽지 않거나 대충 훑어본 채 배포하는 버전입니다. 에이전트 기반 코딩 (Agentic coding)은 여전히 모든 차이점 (Diff)을 읽는 버전이지만, 이 둘 사이의 경계는 당신이 피곤할 때, 차이점 (Diff)이 클 때, 또는 4시간 동안 작업하여 기능이 거의 완성되었을 때 무너지는 관습에 불과합니다. 따라서 저는 여기서 바이브 코딩 (Vibe coding)을 별개의 것이 아니라 에이전트 기반 코딩 (Agentic coding)의 실패 모드 (Failure mode)로 취급하고 있습니다.
문제는 구조적입니다. 코딩 에이전트 (Coding agents)에게는 컴파일러 (Compiler)가 우리에게 제공하는 소스/생성된 출력물 (Source/generated-output) 사이의 경계와 같은 것이 없기 때문입니다. 그래서 프롬프트 (Prompt), 코드 (Code), 테스트 (Tests), 그리고 이전 에이전트 출력물 (Agent output)이 모두 수정 가능하며 모두 입력값 (Input)으로 취급됩니다. 해결책은 하네스 벤더 (Harness vendors)로부터 나와야 합니다. 즉, 에이전트가 읽을 수는 있지만 인간의 명시적인 잠금 해제 없이는 다시 쓸 수 없는 보호된 영역 (Protected region)의 형태로 제공되어야 합니다. 또 다른 지시 파일 (Instruction file)을 만드는 것만으로는 충분하지 않기 때문입니다. 그들이 진짜 해결책을 출시할 때까지, 임시방편들은 모두 다소 불만족스럽습니다.

바이브 코딩 (Vibe coding) 실패의 공개적인 사례. Lemkin은 개인 프로젝트에서 실험 중이었지만, 실제 운영 시스템 (Production systems)들도 같은 방식으로 초토화되었습니다. Replit은 그들의 마케팅에 따르면 분명히 "바이브 코딩 (Vibe coding)을 위한 가장 안전한 장소"입니다.
이것을 실제 팀을 구성하거나 진지한 코드베이스 (Codebase)를 갖게 된 후에나 발생하는 문제로 읽기 쉽지만, 이러한 에이전트를 판매하는 벤더들조차 그 한계를 보기 시작했습니다. 최근 인터뷰에 따르면:
눈을 감고 코드를 보지 않은 채, 흔들리는 기초 위에 AI가 층을 하나씩, 또 하나씩, 계속해서 쌓아 올리게 내버려 둔다면, 결국 모든 것이 무너지기 시작할 것입니다.
_Michael Truell
이제 95%의 확률로 정확하게 작동하는 컴파일러를 상상해 보십시오. 때때로 이 컴파일러는 당신이 수정할 계획이 없었던 다른 파일에 코드를 재생성하며, 이전의 출력을 다음 실행을 위한 입력으로 취급합니다. 아무도 어셈블리 (Assembly) 코드를 읽지 않는데, 그 이유는 컴파일러를 신뢰하는 주된 이유가 컴파일러를 직접 확인할 필요가 없기 때문입니다. 따라서 문제가 발생했을 때 아무도 알아차리지 못합니다. 컴파일러는 과거의 출력을 마치 소스 (Source)인 것처럼 계속 취급하며, 오류가 인지되지 않은 채 누적되게 만듭니다.

컴파일러는 우리가 볼 필요가 없는 어셈블리 (Assembly)를 제공했습니다. 에이전트 루프 (Agent loop)는 우리에게 그 둘 모두를 확인하라고 요구합니다.
이를 구체화하기 위해, 1주 차에 당신이 에이전트에게 결제 흐름 (Payment flow)을 추가하라고 요청했다고 가정해 봅시다. 에이전트는 올바르게 작동하여, 예를 들어 결제 전 GDPR 동의 확인 및 사용자 일일 한도에 따른 금액 제한 등을 수행합니다:
if not user.has_consent("payments"):
raise PaymentDenied("missing consent")
...
몇 주 후 동일한 함수를 다시 방문하여 에이전트에게 빠른 정리 작업 (Cleanup pass)을 수행하라고 지시하면 다음과 같은 모습이 됩니다:
if amount <= 0:
raise PaymentDenied("amount out of bounds")
...
테스트는 여전히 통과하고, 코드는 깔끔하며 가독성이 좋지만, GDPR 확인 절차는 사라졌고, 아무도 요청하지 않았음에도 프리미엄 사용자들에 대한 사기 방지 한도 (Fraud cap)가 조용히 삭제되었습니다.
저는 이것을 **로직 드리프트 (Logic drift)**라고 불러왔습니다. 코드의 형태는 대략적으로 동일하지만, 이전의 제약 조건 (Constraint)이 미묘하게 완화된 것입니다. 불변량 (Invariant)이 조건부 (Conditional)가 되고, 가드 (Guard)가 보호해야 할 대상 뒤로 몇 줄 아래로 이동하며, 권한 확인 (Authorization check)이 중복되면서 그 복사본 중 하나가 잘못되기도 합니다. 디프 (Diff)는 단지 가드가 이동했다고만 말할 뿐입니다. 소스 (Source)에는 해당 가드가 하중을 견디는 핵심 요소 (Load-bearing)라는 명시가 없었기에, 리뷰 과정에서 그것이 더 이상 핵심 요소가 아니게 된 순간을 결코 잡아내지 못합니다.
이러한 일이 최근 Linux 커널에서도 실제로 발생했습니다. 한 메인테이너(Maintainer)가 __read_mostly 어노테이션(Annotation)을 제거하는 AI가 생성한 패치(patch generated by a AI)를 제출했습니다. 이 어노테이션은 컴파일러(Compiler)에게 캐시라인(Cacheline) 배치에 대한 힌트를 주는 역할을 하는데, 이를 제거하면 커널이 배포되는 모든 멀티코어(Multi-core) 시스템에서 경합(Contention)이 발생하게 됩니다. 리뷰 과정에서는 해당 줄이 단순한 정리 작업처럼 보였기에 패치가 수락되었으며, Torvalds는 나중에 만약 그것이 AI에 의해 작성되었다는 것을 알았더라면 다르게 판단했을 것이라고 말했습니다.
수정의 형태
수정 사항은 모델과 파일 시스템 사이의 계층인 하네스(Harness, 예: Cursor, Claude Code, Replit, IDE 플러그인)에 존재해야 합니다. 가장 간단한 구현 방법은 특정 주석과 그 뒤에 오는 코드를 '인간 소유(Human owned)'로 태깅하는 것입니다. 이렇게 하면 에이전트(Agent)가 이를 읽고 참조하여 패치를 제안할 수는 있지만, 인간이 먼저 잠금을 해제하기 전에는 패치를 구현할 수 없게 됩니다. 이는 소스/어셈블리(Source/Assembly) 경계(Boundary)를 코드에 다시 부여하는 역할을 합니다.
이러한 보호 영역(Protected regions)은 매우 오래된 개념입니다. 코드 생성기(Code generators)는 수십 년 동안 BEGIN USER CODE / END USER CODE 마커를 사용해 왔는데, 이는 생성기를 다시 실행할 때 생성된 파일 내부에서 수동으로 편집한 내용이 덮어씌워지기 때문입니다. 에이전트 기반 코딩(Agentic coding) 역시 동일한 덮어쓰기 문제를 가지고 있지만, 여기에는 생성기나 재실행 과정이 없으며 단지 에이전트가 백그라운드에서 일반 소스 파일을 편집할 뿐이라는 점이 다릅니다. 마커를 넣을 코드 생성 템플릿이 없으므로, 잠금(Lock)은 한 단계 위인 하네스 자체에 존재해야 합니다.
# lock: 주석은 Python의 # type: 또는 # pragma: no cover 정신을 이어받아, 한 번에 하나의 문장(Statement) 단위로 작업을 수행합니다.
def charge_card(user, amount, idempotency_key):
# lock: gdpr art 6 - refuse charge if no payment consent
if not user.has_consent("payments"):
...
# lock: 주석은 해당 주석 자신과 바로 아래에 있는 구문 노드 (syntax node)를 잠급니다. 따라서 이를 if 문에 붙이면 블록 전체를 보호하며, 단일 호출 (call)에 붙이면 해당 라인만 보호합니다. 이 주석에는 동기 (motivation)가 포함되어 있으며 코드와 함께 잠깁니다.
이러한 솔루션들은 모델의 협조에 의존하지 않는다는 점에 주목하십시오. 하네스 (harness)는 이미 에이전트 (agent)와 파일 시스템 (filesystem) 사이에 위치해 있습니다. 패치를 적용하기 전에, 하네스는 파일을 분석하여 잠금 (lock)이 어디에 배치되었는지 결정하며, 사용자가 명시적으로 잠금을 해제하지 않는 한 잠금을 포함하는 구간 (spans)에 대한 모든 편집 시도를 거부합니다.
시도되었던 방법들
모든 사람이 가장 먼저 떠올리는 답변은 절제 (agentic coding is a trap)입니다. 즉, 에이전트 사용을 줄이고, 차이점 (diffs)을 작게 유지하며, 모든 것을 검토하는 것입니다. 이 모든 방법은 도구 자체가 당신이 가진 마지막 자제력마저 앗아가기 전까지는 잘 작동합니다. 레버를 당기면 앱에서 완벽하게 작동하는 코드 조각이 툭 떨어져 나옵니다. 또한, 당신이 강력한 절제력을 가지고 있더라도 타인에게 이를 강요할 수는 없습니다.
전통적인 엔지니어링 프로세스는 인간에게는 잘 작동하지만, 에이전트의 규모 (scale)에는 확장되지 않습니다. 요구사항 (requirements)은 코드 외부에 존재하며 일반적으로 에이전트가 읽지 않습니다. 테스트 (tests), 타입 (types), 린터 (linters)는 모두 에이전트가 따라야 할 가이드라인 (rails)을 제공하지만, 그 중 어느 것도 "이 라인은 절대 변경하지 마시오"라고 말하지는 않습니다. 코드 리뷰 (code review)를 통해 일부 드리프트 (drift)를 잡아낼 수는 있지만, 이는 규모의 문제입니다. 리뷰를 하는 데 걸리는 시간은 에이전트가 새로운 기능을 뱉어내는 시간보다 훨씬 더 오래 걸립니다.
하네스 (Harness) 제공업체들도 어느 정도 따라잡았지만, 그들이 출시한 대부분은 여전히 엄격한 제약 조건 (Hard constraints)이 아닙니다. 지속성 메모리 (Persistent memory)는 세션 간에 유지되고, 스킬 (Skills)은 알려진 절차들을 묶어주며, 코드 검색은 grep 방식에서 의미론적 인덱싱 (Semantic indexing)으로 발전했습니다. 또한 AGENTS.md 파일은 에이전트에게 특정 함수를 건드리지 말아달라고 정중하게 부탁합니다. Cursor는 프로젝트 규칙 (Project rules)을 가지고 있고, Claude Code는 도구 호출 (Tool calls)을 가로챌 수 있는 훅 (Hooks)을 제공하며, GitHub Copilot은 사용자 지정 지침 (Custom instructions)을, OpenCode는 프로덕션 파일에 아예 쓸 수 없는 모드를 가지고 있습니다. 저는 실제로 이 기능들을 많이 사용합니다.
이것이 제가 내린 대략적인 결론입니다. 하네스 제공업체들이 조만간 진정한 잠금 장치 (Lock)를 출시하지는 않을 것이며, 그전까지는 에이전트가 볼 수도, 건드릴 수도 없는 경계만이 확실하게 유지될 수 있는 유일한 경계입니다. 현재의 솔루션들은 도움이 되긴 하지만, 잠금 장치 그 자체라기보다는 그저 권고 사항 (Advisory hints)에 불과합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기