요약
AI가 코드를 쏟아내면서 시스템이 일관성을 잃는 '결어긋남'이 가장 나쁜 기술 부채가 되고 있습니다.
여러 회사에서 결어긋남을 겪어 온 소프트웨어 엔지니어 크리스텐 메이빈의 에세이입니다. 결어긋남은 부분만 보면 맞지만 서로 어긋나거나 겹치는 설계가 한 시스템에 쌓이는 현상을 가리킵니다.
왜 중요한가
- AI 코딩 도구의 성과를 쓴 코드의 양이 아니라 실제로 끝낸 일로 따져야 한다는 문제 제기입니다.
- 결어긋남은 시스템이 바뀔 때마다 불어나므로, 변경을 빠르게 하는 AI가 부채도 빠르게 키웁니다.
- 지능 폭발(AI가 스스로를 고쳐 가며 급격히 발전하는 현상)도 현실 검증 없이는 이 벽에 막힌다고 봅니다.
핵심 내용
- 하버드의 718개 기업 연구에서 코딩 에이전트는 코드량을 30% 늘렸지만, 완료된 작업은 눈에 띄게 늘지 않았습니다.
- AI가 쓴 커밋 30만여 건 가운데 약 11건에 1건이 품질 문제를 남겼고, 도구에 따라 7건에 1건까지 올라갔습니다.
- 저자의 시뮬레이션에서 일관성을 낮추면 초반엔 빨랐지만 갈수록 크게 느려졌고, 적당한 일관성을 지키는 최적 지점이 있었습니다.
- AI 코드가 곧 나아진다는 반론에는 코드는 직물이 아니라 직물을 짜는 기계라서 결함이 그 위로 번진다고 답했습니다.
- 결어긋남은 되돌릴 수 있지만 일관성을 일부러 쌓아야 하며, 그 본보기로 오픈소스의 방식을 들었습니다.
HN 반응
- AI가 기능 추가 비용을 낮춰 군더더기를 막던 제동 장치마저 없앴다는 공감이 많았고, 기존 코드를 고치지 않고 덧쌓는다는 경험담도 나왔습니다.
- 'decoherence'는 물리학 용어인 데다 상태가 아닌 과정을 뜻해 잘못 썼다는 지적과, 시스템이 서서히 무너지는 과정을 담기에 오히려 알맞다는 반론이 맞섰습니다.
훌륭한 글입니다. 소프트웨어를 만든다는 건 본질적으로 시스템을 모델링하는 일이고, 모든 모델은 같은 한계에 부딪힙니다. 시스템이 커질수록 부분들 사이의 상호작용 수가 조합적으로 늘어난다는 한계입니다. 그 부분이나 상호작용 중 일부가 아무 가치도 만들지 못한다면(군더더기), 얻는 건 없이 복잡도만 더해집니다. 이는 모델을 만든 쪽이나 코드를 쓴 쪽이 누구든 마찬가지입니다. 그런데 대부분의 사람은, 뛰어난 소프트웨어 엔지니어조차 이런 직관적인 이해가 부족해 보입니다.
오히려 AI가 어떻게든 이 본질적인 자연법칙을 피해 갈 수 있다고 생각하는 것 같습니다.
제가 본 바로는 AI는 오히려 배율을 곱해 주는 존재입니다. 새 기능을 추가하는 초기 비용이 낮아지면서, 많은 조직에서 군더더기가 쌓이는 걸 막던 유일한 제동 장치가 사라졌습니다.
AI가 일하는 방식 자체도 한몫합니다. 제 경험으로는 새 기능을 추가할 때 기존 코드를 리팩터링하는 일이 거의 없습니다.
AI는 기존 코드 위에 새 코드를 덧얹는 경향이 있어서, 조심하지 않으면 금세 엉망진창이 됩니다.
기존 코드를 언제 리팩터링할지 스스로 거리낌 없이 결정하는 하네스를 써 본 적이 있습니다. 경험이 더 나아지지는 않았습니다.
게으름은 소프트웨어 엔지니어에게 아주 중요한 필터이자 장점입니다. 열정 넘치는 (AI) 개발자들이 팀에 잔뜩 있어서, 지나치게 복잡하거나 결국 쓸모없는 기능을 몇 초 만에 구현해 낸다고 상상해 보세요. 그 기능들은 비용 대비 효과를 따져 본 적도 없이 앞으로 몇 년 동안 테스트하고 유지보수해야 합니다. 프로젝트 매니저가 변덕으로 아무 아이디어나 던지기만 하면, 그걸 영원히 끌고 가야 하는 겁니다.
소프트웨어에서 전에 없던 군더더기 대유행을 보게 될 겁니다.
어쩌면 이미 보고 있는 건지도 모릅니다. 우리 같은 오렌지색 웹사이트 사람들은 요즘 결과물을 얼마나 빨리 찍어 낼 수 있는지에 신이 나 있죠. 그런데 제 주변의 비기술 쪽 사람들은 할 말이 있으면 그만 좀 했으면 좋겠다고 합니다. 끊임없이 바뀌는 걸 바꾸기 위한 변화로 보고 짜증스러워하고, 요즘 컴퓨터가 점점 쓰기 어려워진다는 느낌이 전반적으로 퍼져 있습니다.
스포일러를 하자면, 게으름은 일관성(coherence)을 만들어 내는 가장 중요한 요인 중 하나입니다. 우리에게는 일을 더 빠르게, 더 낫게, 더 게으르게 하고 싶어 하는 뿌리 깊은 생물학적 욕구가 있습니다. 이 부분은 Open Capital에서 더 깊이 다룰 예정입니다.
AI의 현재와 미래 능력에 대한 마법 같은 사고가 정말 많습니다.
그리고 한 시스템 모델에서 다른 시스템 모델로 옮겨 가는 일은 또 하나의 시스템 모델입니다. 그걸 만들어 낼 수 있는 사람은 더더욱 드물고요.
이 글은 더 일반적인 문제로 이어집니다. 저는 "모든 모델은 틀렸지만, 어떤 모델은 쓸모가 있다"라는 말을 즐겨 꺼내는데, 사실 이 말은 통계 모델을 이야기한 어느 통계학자의 말로 알려져 있습니다. AI보다 훨씬 이전에, 컴퓨터 과학이 데이터 과학·공학을 파고들기도 전 시대에 활동한 수학자가 쓴 말이죠.
글에서 말하는 디코히어런스 함정은 AI와 관련된 이야기지만, 물리 시뮬레이션과 모델링을 배경으로 수학 모델과 시스템 제어 알고리즘을 적용해 온 입장에서 보면, 소프트웨어는 늘 현실과의 연결 문제를 안고 있었습니다. 현실을 확인하는 속도보다 모델을 만드는 속도가 언제나 더 빨랐습니다. 사람들은 늘 결과를 서둘러 얻고 그에 따라 행동하고 싶어 하지만, 장기적으로 진짜 한계는 대개 이것입니다. 어떤 최적화 모델 규칙을 쓰든 좋은 결정을 내릴 만큼 충분한 실제 데이터 신호를 관찰할 수 있는가. 실제 데이터와 아이디어, 표본을 모으는 일은 그걸 빠르게 처리하는 일보다 대체로 더 어렵고 더 느립니다. AI가 있으면 (LLM이라는 뜻이 아니라 운영 차원에서) 아름답고 정밀한 결과를 내놓는 모델을 훨씬 더 빨리 만들 수 있게 되겠지만, 그 결과가 현실과 연결된 방식으로 쓸모가 있을지는 알 수 없습니다.
모델이 잘못된 데이터로 돌아가면, 늘 위험한 건 정밀해 보이는 기술적 답을 그대로 적용하고 싶어지는 유혹입니다. 실무 방식은 갱신되어야 하겠지만, 시스템 엔지니어링의 검증(validation)·확인(verification)과 소프트웨어 QA의 마인드셋이 앞으로 크게 필요해질 거라고 생각합니다.
사실 관련된 문제가 하나 더 있습니다. 우리 경제 전체에 지나치게 일관된 모델 집합이 돌아가는 건 바람직하지 않다고 봅니다. 경쟁하고 실험하는 시장에 비해 중앙 계획의 실패라는 큰 위험이 있으니까요. 다만 이건 곁가지 이야기입니다.
"디코히어런스(decoherence)"는 상태가 아니라 과정(일관성을 잃어 가는 것)을 가리키는데, 이 글은 마치 상태처럼 씁니다. "Well, for one thing, it creates decoherence."가 그 예입니다. 상태를 뜻하려면 "인코히어런스(incoherence)"(일관성이 없는 것)가 맞습니다.
이 부분은 "incoherent"(일관성이 없는)나 "decohered"(일관성을 잃은)가 되어야 합니다.
그렇긴 해도, 시스템의 비일관성이 기술 부채의 한 형태라는 데에는 동의합니다. 그리고 소프트웨어 개발에 AI를 쓰면 시스템이 비일관적으로 변할 위험이 커집니다.
글 첫 문장에서 새로운 용어를 소개한다고 밝히고 있습니다. 그러니 저자가 원하는 대로 정의할 수 있고, 이 뜻이 아직 사전에 없다고 불평하는 건 합리적이지 않습니다. 당연히 없죠. 의도적인 신조어니까요.
물리학 용어에서 가져온 비유, 그러니까 상태를 나타내는 명사라는 점은 저한테는 충분히 분명해 보입니다. 이 비유가 얼마나 적절한지는 말씀드릴 수 없지만, 소프트웨어 업계 용어라는 게 대부분 다른 분야의 용어를 부적절한 비유로 가져다 쓴 것이라서 그게 중요한지 모르겠습니다.
그리고 incoherent의 일상적인 뜻은 오히려 "의미 없는"에 가깝습니다. 그 이유만으로도 저자가 설명하는 개념에는 더 나쁜 단어라고 생각합니다.
"Incoherent"는 정적인 느낌이 있지만, "decoherent"는 반대로 동적이고 대응하는 동사가 있습니다. 기능이 추가되면서 (거의) 필연적으로 일어나는 점진적 과정을 설명할 때 아주 편리하죠. 양자물리학에서의 쓰임과 헷갈릴 일도 없을 테니, 저도 글처럼 이 용어를 겹쳐 쓰는 게 안전하고 적절하다고 생각합니다.
네, 이 용어를 쓴 이유가 바로 그겁니다. incoherence와 다른 점은 또 있습니다. 디코히어런트한 시스템도 어떤 면에서는 여전히 말이 된다는 겁니다. 계속 작동하고, 계속 개선해 나갈 수도 있습니다.
그런데도 디코히어런트하다고 하는 건 그걸 바꾸는 작업이 극도로 어렵기 때문입니다. 이건 전혀 다른 상태이고, 그 안에 있는 데는 훨씬 큰 비용이 듭니다.
제 학계 경험(벌써 10년도 더 됐지만)으로는 "decoherent"를 "decohered"와 거의 같은 뜻으로 씁니다.
동의합니다! 게다가 "decoherence"라는 용어는 아주 구체적인 의미를 갖고 있습니다.
https://en.wikipedia.org/wiki/Decoherence
https://www.collinsdictionary.com/dictionary/english/decoherence
두 분야가 충분히 떨어져 있으니 용어를 겹쳐 써도 안전하다고 생각합니다. 시스템이 요즘 너무 디코히어하고 있다고 불평한다고 해서, 양자 상태를 가리킨다고 생각할 사람은 없을 겁니다. 저자가 이 용어를 고른 이유도 이해가 됩니다. "decohere"는 동사라서, 변화가 쌓이면서 시스템에 서서히 일어나는 과정을 나타내는 데 어울리거든요. "incoherence"에는 그런 뉘앙스도, 대응하는 동사도 없습니다.
개념으로 갖춰 두면 좋은 멋진 용어네요!
그런데 이게 바로 지금 모델들이 128k에서 1M 정도의 컨텍스트 크기 한계 때문에 디코히어런트한 시스템을 만들게 된다고 제가 보는 이유입니다. 복잡도가 어느 수준을 넘으면 전체 그림을 볼 능력이 없어서, 시스템을 디코히어하게 만드는 국소 최적화를 잔뜩 하게 됩니다.
동의하지 않습니다. LLM이 비일관성을 만들어 내는 건 컨텍스트 크기 한계가 너무 낮아서가 아니라 너무 높아서일 수 있습니다. 한계가 인간보다 훨씬 높으니까요.
하지만 그 한계를 극복하려면 더 단순하고 더 일관된 현실 모델을 채택해야 하고, 제가 보기에 인간은 바로 그렇게 합니다. 그런데 컨텍스트 윈도우가 상황 전체를 이해할 수 있게 해 준다면, 그렇게 할 동기가 거의 없습니다.
그러니 트레이드오프가 있어 보입니다. 어떤 해법(복잡한 명제의 증명 같은 것)은 일정 크기 이상의 컨텍스트를 필요로 할 수 있습니다. 그러면 인간의 방식은 확장되지 않습니다.
어쩌면 작업 중인 시스템에 맞춰 컨텍스트 윈도우를 조정해서, 시스템 아키텍처가 필요한 최소 컨텍스트 크기 안에서 성립하는 구조가 되도록 해야 할지도 모릅니다.
인간은 추상적인 모델을 만들고 다듬어서 기억에 새기는 방식으로 대규모 시스템에 대한 이해를 머릿속에 넣습니다.
LLM은 그렇게 하지 않습니다. 추상화라고 할 만한 건 전부 학습 시점에 일어납니다. 추론 시점에 새 모델을 동적으로 구성할 수 없고, 장기 기억에 저장할 수도 없습니다. LLM에는 그런 메커니즘이 없으니까요. 그러니 점진적인 개선도 불가능합니다.
우리는 에이전트 하네스로 모든 걸 컨텍스트 윈도우에 욱여넣는 식으로 이 문제를 우회합니다. (이것 자체가 인간에게는 사실상 없는 방식입니다.) 그래서 대부분의 실제 작업에서 큰 컨텍스트 윈도우가 그토록 중요한 겁니다. 학습 코퍼스에 없던 정보를 LLM이 다룰 수 있는 유일한 방법이니까요.
그 말이 맞는지 잘 모르겠습니다. LLM의 설계라는 물리적 관점에서는 위 설명이 맞습니다. 하지만 LLM도 학습을 통해 일을 하도록 진화한 시스템이라서, 다른 수준에서 새 추상화를 만드는 걸 흉내 낼 수 있을 가능성을 배제할 수는 없습니다.
LLM은 이미 "참조"라는 개념을 갖고 있습니다. 예를 들어 함수 같은 어떤 것의 이름을 말하면, 이름 자체에 딸린 속성이 아니라 그 이름이 가리키는 대상이 중요하다는 걸 이해합니다.
그런데 새 추상화를 만드는 데 필요한 게 바로 이겁니다. 어떤 개념의 정의(설명)가 담긴 문단에 이름을 붙이고, 추론을 하려면 그 이름으로 그 문단을 떠올릴 수 있어야 하죠.
그러니 참조를 쓰면 인간처럼 컨텍스트 크기 한계를 우회할 수 있습니다. 외워서 "통째로" 익히는 것보다는 느리지만, LLM은 충분히 그럴 능력이 있다고 봅니다. 증거로, 컨텍스트보다 큰 코드베이스를 탐색해 내는데, 그런 코드베이스에는 새로운 추상화가 많이 들어 있는 경우가 흔합니다.
제가 하려던 말을 아주 분명하게 말씀드릴 수 있습니다. LLM은 근사적으로 순수 함수입니다. 부수 효과도 없고 상태 변화도 없습니다. 신경가소성도 없고, 작업 기억도 없습니다. 정말로 이전 토큰을 바탕으로 다음 토큰을 예측할 뿐입니다. 그러니 같은 입력에 대한 출력을 바꾸는 유일한 방법은 입력을 바꾸는 것, 즉 다른 정보를 컨텍스트 윈도우에 넣는 것뿐입니다.
물론 확률적 토큰 샘플링과 분산 추론 때문에 비결정성은 어느 정도 있습니다. 하지만 가끔 두 번째로 가능성이 높은 다음 토큰을 무작위로 고른다고 해서 인지적 피드백 루프가 생기지는 않습니다.
맞습니다. 하지만 지금 우리가 이야기하는 건 사실 LLM이 아니라 LRM입니다. LRM은 작업 기억을 아주 잘 흉내 내서, 벡터 DB 기반 RAG 대신 .md 파일 여러 개를 (일종의 컨텍스트 밖 메모로) 쓰라고 권하는 사람이 많을 정도입니다. 컨텍스트를 압축하고 기억을 적어 두는 방식으로, 꽤 자율적으로 컨텍스트를 유지할 수 있습니다.
그러니 가중치를 갱신하지 않더라도 새로운 것과 개념을 얼마든지 배울 수 있고, 세상에 대한 새 모델을 만들 수 있습니다.
그런데 그러면 제가 처음에 했던 말로 돌아옵니다. 큰 컨텍스트 윈도우가 잘 작동하게 하는 데 필수라는 거죠. 그 *.md 파일들도 추론 시점에 LLM에 넣어 주지 않으면 아무 일도 하지 않습니다.
(수정: 그렇긴 해도, 그렇게 큰 윈도우가 필요 없도록 시스템을 설계해야 한다는 생각에는 동의합니다. 하지만 에이전트 코딩으로 개발을 대폭 가속하는 게 목표라면 그건 스스로 발목을 잡는 일 같습니다. 이 모델들은 단순함을 위한 엔지니어링에는 꽤 서툰 것 같고요. 사람이 꼼꼼히 감독해서 시스템 설계를 지킨다면, 결국 사람이 코드를 읽고 이해하는 속도에 계속 묶이게 됩니다.)
충분히 큰 컨텍스트 윈도우면 됩니다. 네, md 파일을 다시 채워 넣을 수 있고, 다른 것(불필요한 세부 사항)은 내보낼 수 있습니다.
알겠습니다. 죄송합니다. 처음 하신 말씀을 오해해서 지금까지 엇나가는 이야기를 하고 있었던 것 같네요.
저는 문서화를 개선해서 코딩 에이전트의 성능을 높이는 실험을 해 왔습니다. 일화이긴 하지만, 제가 물려받은 바이브코딩 난장판에 비해 문서를 개선했더니 더 작은 모델을 쓰고도 그러면서 더 나은 품질의 결과물을 얻을 수 있었습니다.
스킬 파일을 마크다운 문서로 바꾼 것도 차이를 만들었습니다. 제 감으로는 스킬이 컨텍스트 윈도우에 한꺼번에 쏟아부어지는 경향이 있는 반면, 에이전트 하네스는 그 정보를 어떻게 포함할지 더 신중하게 결정할 수 있기 때문인 것 같습니다.
하지만 컨텍스트 윈도우 크기와 상관없이, 모델이 코드를 엉망으로 만드는 경향에 이게 영향을 준다는 징후는 별로 못 봤습니다. 문서도 마찬가지고요. 이것도 잘 하게 만드는 편법을 찾을 수 있을지도 모르겠습니다. 그러길 바랍니다. 이 컨텍스트 윈도우 크기 붉은 여왕 달리기가 어떻게 지속 가능할지 저는 모르겠으니까요.
동의합니다. 다만 대부분의 인간이 이미 국소 최적 위에서 움직이고 있기는 하죠. 그러니 인간 집단도 복잡한 시스템을 나눠서 정복할 수 있는 만큼, 엔지니어링으로 해결할 방법이 있을 수도 있어 보입니다.
동의합니다. 그런데 그건 더 이상 엔지니어링 해법이 아니라 경영/조직 설계 해법으로 보입니다.
저는 특이점을 반박하는 이 논증이 별로 마음이 놓이지 않습니다. 진화하는 지능이 현실 세계에 접근할 수 없다는 사실에 기대고 있는 것 같거든요. 좋아요, 하지만 저는 데이터센터 안의 특이점은 딱히 걱정하지 않았습니다. 걱정했던 건 모든 로봇과 센서와 전원 스위치를 AI가 제어하는 시스템에 연결했을 때입니다. 우리가 지금도 그렇게 하고 있잖아요, 맞죠?
요점은 물리 공간에 접근하지 못한다는 게 아니라, 반복은 근본적으로 '마음 안'에 머물러 있을 때만 빨라진다는 겁니다. 세상과 상호작용하는 순간 병목이 생기죠.
예를 들어 AI에게 상사가 연봉을 올려 줄 만큼 설득력 있는 문장이 뭘까 하고 엄청 열심히 생각하게 할 수는 있겠지만, 결국 어떤 문장을 직접 말해 보고 상사의 대답을 기다려야 결과가 좋았는지 나빴는지 알 수 있습니다. 그러지 않으면 시도를 개선하고 있는 건지, 몇 시간 동안 목적 없이 환각만 하고 있는 건지 알 수 없습니다.
그러면 개선 속도는 반복 속도만큼만 빠릅니다. 로봇은 넘어지면서 걷는 법을 배울 수 있지만, 실제 사람보다 더 빨리 넘어질 수는 없으니 초당 100만 번씩 넘어지며 배울 수는 없습니다.