기술 부채, 인지 부채, 의도 부채
(martinfowler.com)- LLM이 코드를 대량 생산하는 환경에서는 코드 자체의 문제만이 아니라 팀의 공유 이해와 시스템 목표 기록까지 함께 약해지며, 이를 기술 부채·인지 부채·의도 부채의 세 층으로 나눠 다룰 필요가 커짐
- Technical debt는 미래 변경 가능성을 제한하고, Cognitive debt는 팀이 시스템 변경을 추론하는 능력을 약화시키며, Intent debt는 목표와 제약의 기록이 흐려져 인간과 AI 에이전트의 지속적 진화를 가로막음
- AI를 System 3로 놓는 Tri-System 이론은 외부 인공 추론을 비판 없이 신뢰해 숙고를 건너뛰는 cognitive surrender를 구분하며, 전략적으로 인지를 위임하는 cognitive offloading과는 다르게 봄
- 코딩 비용이 낮아질수록 비싸지는 것은 verification이며, 정확성과 성공의 기준은 교통 ETA, 기사 배차, 수백 개 마이크로서비스 운영처럼 맥락마다 달라져 인간의 판단과 검증 체계 설계가 더 중요해짐
- 엔지니어링의 중심축은 구현량보다 검증으로 이동하고, 앞으로도 인간은 유용한 추상화와 이름 짓기, acceptance criteria와 test harness 설계처럼 시스템의 의미를 붙잡는 역할을 계속 맡게 됨
세 가지 부채와 시스템 건강
- LLM이 대량의 코드를 만들어내는 환경에서는 팀이 시스템이 무엇을 하는지에 대한 이해를 잃기 쉬우며, 이를 Cognitive Debt로 보는 관점이 커지고 있음
- 세 가지 시스템 건강 계층은 부채를 코드, 사람, 아티팩트 차원으로 나눔
- Technical debt는 코드에 존재하며, 구현 결정이 미래 변경 가능성을 해칠 때 쌓이고 시스템이 어떻게 바뀔 수 있는지를 제한함
- Cognitive debt는 사람에게 존재하며, 시스템에 대한 공유 이해가 보충되는 속도보다 더 빨리 약해질 때 쌓이고 팀이 변경을 추론하는 능력을 제한함
- Intent debt는 아티팩트에 존재하며, 시스템을 이끌어야 할 목표와 제약이 제대로 기록되거나 유지되지 않을 때 쌓이고 원래 만들고자 했던 바를 계속 반영하는지, 또 인간과 AI 에이전트가 시스템을 효과적으로 계속 진화시킬 수 있는지를 제한함
- 이 관점은 각 부채를 진단하고 완화하는 섹션까지 포함하며, 세 부채가 서로 상호작용한다는 점도 함께 다룸
- 팀은 이 세 부채를 통제하기 위한 일반 활동을 함께 수행해야 함
Tri-System 이론과 인지적 항복
- LLM을 Kahneman의 두 시스템 사고모델에 추가하는 논문은 AI를 System 3로 놓고 사고 체계를 확장함
- System 1은 직관으로 빠르게 결정을 내리고, System 2는 문제를 의도적으로 사고하는 단계로 구분됨
- 에너지를 아끼기 위해 인간은 기본적으로 직관에 의존하는 경향이 있으며, 그 결과 숙고했다면 발견했을 요소를 놓칠 수 있음
- System 3의 결과로 cognitive surrender가 등장하며, 이는 외부에서 생성된 인공 추론을 비판 없이 신뢰해 System 2를 우회하는 상태로 규정됨
- 논문은 이를 cognitive offloading과 구별함
- cognitive offloading은 숙고 과정에서 인지를 전략적으로 위임하는 행위로 다뤄짐
- 이 논문은 Tri-System theory of cognition을 자세히 전개하고, 최소한 실험실 환경에서는 이 이론이 행동 예측에 얼마나 유효한지도 여러 실험으로 검증함
코드 아이콘으로서의 <> 표기
- 최근 몇몇 일러스트는 코드 아이콘으로 “<>” 기호를 사용하지만, 이 표기는 프로그래밍 언어 요소를 감싸는 표기로는 낯설게 보임
- “{ }” 같은 다른 기호가 아니라 “<>”가 쓰이는 이유는 HTML 또는 XML을 떠올리기 때문으로 읽힘
- “</>” 형태까지 쓰는 경우에는 HTML을 더 직접적으로 연상시키지만, HTML은 프로그래머가 프로그램을 작성하는 언어로 다뤄지지 않음
코딩이 싸지면 비싸지는 것은 검증
- if coding agents make coding free, what becomes the expensive thing는 코딩 에이전트가 코딩 비용을 낮출수록 비싸지는 요소는 verification이라고 봄
- 정확성의 기준은 맥락마다 계속 달라짐
- Jakarta 교통에서의 ETA 알고리듬과 Ho Chi Minh City 교통에서의 ETA 알고리듬은 “correct”의 의미가 다를 수 있음
- 기사 배차에서는 수익의 공정성, 고객 대기 시간, 차량 활용률을 동시에 맞춰야 하므로 “successful”의 정의가 하나가 아니라 여러 개가 됨
- 수백 명의 엔지니어가 약 900개의 마이크로서비스에 계속 배포하는 환경에서는 “correct”가 하나의 정의가 아니라 수천 개의 정의로 분화되며, 모두 계속 바뀌고 맥락 의존적임
- 이런 판단은 에이전트가 대신할 수 없는 작업으로 놓임
- 에이전트는 작업 결과에 대해 좋고 가능하면 자동화된 검증이 있을 때 특히 잘 작동하는 흐름이 커지고 있음
- 이런 흐름은 Test Driven Development를 장려함
- 여전히 해야 할 검증량은 많으므로, 사람이 더 넓은 테스트 범위를 쉽게 이해할 수 있도록 돕는 방법에 더 많은 노력이 필요함
- 레거시 현대화에 대해서는 일부 이견도 함께 제시됨
- agentic coding이 레거시 현대화를 최종적으로 해결할 것이라는 기대는 과대평가되어 있음
- 다만 understanding what legacy code is doing 측면에서는 LLM이 큰 도움을 준다는 강한 근거가 있음
검증 중심 조직으로의 재편
- 에이전트가 실행을 맡으면 인간의 일은 verification system 설계, quality 정의, 그리고 에이전트가 해결하지 못하는 모호한 경우를 처리하는 쪽으로 이동함
- 조직 구조도 이 변화에 맞춰 바뀌어야 함
- 월요일 아침 스탠드업의 질문은 “무엇을 배포했는가”보다 “무엇을 검증했는가”가 중심이 됨
- 출력량 추적보다 결과가 정확했는지를 추적하게 됨
- 기능을 만들던 10명의 엔지니어 팀은 3명의 엔지니어와, acceptance criteria 정의, test harness 설계, outcome 모니터링을 맡는 7명으로 재구성될 수 있음
- 이런 재편은 만드는 행위의 위상을 낮추고 판단하는 행위의 위상을 높이기 때문에 불편하게 느껴질 수 있음
- 이런 변화를 거부하지 않는 엔지니어링 문화가 더 잘해낼 가능성이 큼
소스 코드의 미래와 LLM 친화적 언어
- LLM을 프로그래머처럼 다루는 흐름 속에서 소스 코드의 미래 자체가 질문으로 떠오름
- several views of the future of code는 코드의 미래를 둘러싼 여러 관점을 모아 다룸
- 일부는 LLM을 염두에 두고 설계한 완전히 새로운 언어를 실험 중임
- 다른 쪽은 기존 언어, 특히 TypeScript와 Rust 같은 엄격한 타입 언어가 LLM에 더 잘 맞을 수 있다고 봄
- 이 글은 인용이 많고 자체 분석은 많지 않지만, 논의 전반을 훑는 개관 자료로 읽을 만함
인간이 맡는 추상화와 이름 짓기
- LLM과 함께 소프트웨어를 만드는 과정에서도 인간은 코드가 무엇을 하는지 이야기할 수 있는 유용한 추상화를 만드는 역할을 계속 맡게 됨
- 이는 DDD의 Ubiquitous Language와 연결됨
- growing a language는 LLM과 함께 언어를 키워가는 방식을 다룸
- 프로그래밍은 컴퓨터가 이해하고 실행할 수 있는 코딩 문법을 입력하는 일만이 아니라 해결책을 형태화하는 작업이기도 함
- 문제를 집중된 조각으로 나누고, 관련 데이터와 동작을 함께 묶으며, 의도를 드러내는 이름을 선택하게 됨
- 좋은 이름은 복잡성을 가르고 모두가 따라갈 수 있는 도식으로 코드를 바꾸며, 문제 구조와 해결 구조를 선명하게 연결해 줌
Hacker News 의견들
-
내가 배포하는 걸 전부 깊이 이해해야 마음이 놓이는 타입이면, 이런 변화가 꽤 불안하게 느껴짐
지금은 2개월 걸릴 modernization 프로젝트도, 비즈니스 로직을 전부 파고들어 그대로 복제하려 하기보다 경계와 인터페이스를 잘 설계하는 데 집중하면 일주일 안팎으로 끝낼 수 있음
그리고 글에서 말하듯 테스트 하네스를 잘 만들어서 가능한 한 동등성을 검증하면 됨
나도 처음엔 꽤 갈등했는데, 곰곰이 생각해보니 내가 매일 유지보수하는 다른 시스템들도 내부 구현이나 비즈니스 로직을 그렇게 잘 아는 편이 아니었음
몇 년 전에 내가 짜고 거의 안 건드린 코드라서, 뭔가 바꿔야 하면 결국 테스트 스위트를 믿거나 코드 구조를 따라가며 특정 동작을 파악하고 있었음- 업계와 회사에 대한 깊은 도메인 지식은 팀과 회사에서 사람을 아주 가치 있게 만들어줌
감원이나 비용 절감 국면에서도, 그런 지식을 많이 가진 사람은 그렇지 않은 사람보다 오래 살아남는 걸 여러 번 봄 - 좋은 테스트 하네스를 만들려면 결국 비즈니스 로직을 깊이 이해해야 하지 않나 싶음
내가 뭘 놓치고 있는지 궁금함
- 업계와 회사에 대한 깊은 도메인 지식은 팀과 회사에서 사람을 아주 가치 있게 만들어줌
-
LLM에 게으름의 미덕이 없는 건 아님
의도에 맞는 베이스 프롬프트만 주면, Claude 기반 에이전트에게 코드 변경을 최소화하게 하고, 중복 제거 패스를 돌리게 하고, 아주 시니어 개발자다운 본능처럼 보이는 행동들을 꽤 잘 유도할 수 있었음
모델이 그 지식을 아예 못 배운 게 아니라, 기본 설정에서는 그게 전면에 안 나와 있을 뿐이라고 봄
온 코드베이스를 마구 건드리고, 남의 변경이나 지식 손실 위험은 전혀 신경 안 쓰는 과잉 수정 스타일의 모델은 다들 본 적 있을 것 같음
문서 생성과 검증 얘기도 결국 전통적인 락킹 문제와 비슷하고, 전통적인 해법이 있음
에이전트가 git을 읽고 무엇이 먼저 되었는지, 관례상 다른 변경을 기다리는 상태인지도 충분히 파악할 수 있음
나도 꽤 시니어고, 이 글에 나온 몇몇 사람들과 실제로 같은 팀에서 일한 적도 있음
그 사람들이 내 엔지니어링 기준을 의심하진 않을 거라고 생각함
그런데 내 LLM 워크플로에서는 그런 종류의 부채가 거의 보이지 않았고, 오히려 예전과 같은 기준으로 봐도 5년 전, 10년 전보다 프로젝트 품질이 더 좋아졌다고 느낌
마법 같은 건 아니고, 그런 품질 우선순위를 공유하는 에이전트를 잘 돌리면 됨
그리고 나는 컨퍼런스에서 관심 끌기보다 실제 일을 더 많이 해내고 있음- 여기서 말하는 방향성에는 동의함
다만 전통적인 소프트웨어 품질 지표로 봐도 5년 전, 10년 전보다 낫다는 부분은 너무 모호하게 들림
어떤 지표를 쓰는지, 10년 전·5년 전·지금 코드가 각각 어떻게 비교되는지 더 구체적으로 알고 싶음
그런 설명이 없으면 메시지가 오히려 흐려지고 핵심에서 벗어나는 느낌이 듦
더 공유할 게 있다면 꽤 궁금함 - Claude에게 최소 변경이나 비슷한 방향을 유도할 때 어떤 지시를 주는지 공유해줄 수 있나 궁금함
- 컨퍼런스에도 나가보면 좋겠음
Practical LLM Coding 같은 제목으로 책을 써도 될 듯함
- 여기서 말하는 방향성에는 동의함
-
여기서 가장 저평가된 건 intent debt라는 프레이밍이라고 봄
인지 부채나 기술 부채는 최소한 코드에 흔적이 보이는데, intent debt는 보이지 않음
그래서 로컬하게는 그럴듯하지만 전역적으로는 틀린 변경이 들어왔을 때야 비로소 드러남
원래 제약이 어떤 산출물에도 남아 있지 않기 때문임
가장 어려운 경우는 엔터프라이즈 시스템에서 그 제약이 규제 요구사항이었는데, 3년 전에 조용히 바뀌었고 아무도 코드를 갱신하지 않은 상황임
테스트는 계속 통과하니까 더더욱 놓치기 쉬움
테스트 스위트만으로는 의도를 복구할 수 없음 -
Martin의 말이 완전히 틀렸다고는 생각하지 않지만, 이 논리는 추상화 계층이 올라갈 때마다 항상 할 수 있는 주장처럼 보임
그의 정의대로라면 Assembly에서 Python으로 가는 것도 intent debt와 cognitive debt를 엄청 만드는 셈임
비트를 어떻게 조작할지 직접 고민하지 않고 인터프리터에게 맡겼기 때문임
내 반론은, 그가 말하는 기술적 의도라는 건 결국 인간의 의도를 기계어로 번역해야 했기 때문에 생긴 것이라는 점임
문제를 깊이 생각하는 일 자체는 코드 안에서 도메인 주도 추상화를 반드시 세워야만 가능한 게 아님
마인드맵을 그리거나, 저널을 쓰거나, 벽에 포스트잇을 붙여도 깊이 생각할 수 있음
객체지향 추상화 자체가 마법은 아님- 의도를 형식 언어로 옮기는 과정 자체가 사고 도구이기도 함
그 과정에서 애매함이나 미처 고려하지 못한 세부사항, 심지어 접근 자체를 다시 생각해야 한다는 사실까지 드러나곤 함
자연어로 쓰는 것도 사고 도구가 될 수는 있지만, 모호함을 허용하지 않는 형식 언어에 사고를 맞추는 데는 본질적으로 다른 요소가 있음
수학 기호 없이 자연어만으로 수학을 하면 번거롭고 오류가 많아지는 것과 비슷함 - 결정적 코드를 생각한다는 건 결국 하드웨어 비트 조작을 생각하는 것이기도 함
다만 인간이 이해하기 더 쉬운 언어로 하고 있을 뿐임
의도와 구현 사이에 직접적인 매핑이 존재함 - 그 부채는 이미 한 번 지불한 것에 가까움
매핑이 잘 정의되어 있고 결정적이기 때문임
추상화의 목적은, 그 아래를 다시 들여다보지 않아도 지금 한 일이 여전히 맞는지 믿을 수 있게 만드는 데 있음
나나 내가 신뢰하는 누군가가 한 번 그 비용을 치렀기 때문에 가능한 일임
그런데 LLM은 생성할 때마다 출력을 검증해야 하고, 매번 그 부채를 다시 내야 함
그래서 이건 추상화라고 보기 어려움 - 인터프리터는 결정적이지만 LLM은 그렇지 않음
- AI는 추상화 계층이 아님
- 의도를 형식 언어로 옮기는 과정 자체가 사고 도구이기도 함
-
The most creative act is this continual weaving of names that reveal the structure of the solution that maps clearly to the problem we are trying to solve.
공자의 정명과도 닿아 있다고 느낌
《논어》 13.3에 따르면, 이름이 바로 서지 않으면 말이 진실에 맞지 않고, 말이 진실에 맞지 않으면 일이 이루어지지 않음
결국 해법의 구조를 문제에 정확히 대응시키는 이름 짓기가 핵심이라는 뜻으로 읽힘 -
글을 정말 잘 썼음
나도 어제 개인 노트에, 코드를 유기적으로 계속 발전시키지 않으면 그걸 진짜로 소유한다고 말하기 어렵다고 적었음
자율주행차처럼 예전엔 가는 길 풍경이라도 기억하는데, 이제는 그냥 다른 장소로 순간이동해 놓고 녹화본만 보여주는 느낌임
이런 식의 리뷰는 효과가 떨어짐
작은 도구에는 이런 ghosted code가 괜찮을 수 있어도, 데이터베이스 같은 시스템에서는 정말 걱정됨
그래서 이제는 에이전트에 쓰기 권한을 거의 안 주고, 2년 전처럼 수동 QA 중심으로 돌아왔음
토큰 사용량이나 결과 면에서도 오히려 그쪽이 더 효율적이었음
물론 이건 어디까지나 내 경험임 -
안타깝게도 그가 링크한 Wharton 논문의 상당 부분은 AI로 생성된 것처럼 보이고, 아직 peer review도 안 된 상태임
요즘 연구자들이 글쓰기에 AI 도움을 받는 건 알지만, 논문 주제가 하필 cognitive surrender라면 그 내용을 진지하게 받아들이기 어려워짐not merely를 무려 7번이나 쓰더라
LLM이 그렇게까지 같은 표현을 반복할까 싶기도 하고, 오히려 저자가 LLM처럼 쓰는 습관을 들인 걸 수도 있겠다는 생각이 듦- 다행히 나는 그 논문을 직접 읽지 않고 LLM 요약만 돌려봤음
-
I realize that most researchers use AI to assist with writing
이건 정말 역겨움
-
Martin 말이 아주 틀린 건 아니지만, 나는 AI가 게으른 코드를 만든 사례를 직접 봤고, 그때 정답은 오히려 코드가 더 많아지는 쪽이었음
구체적으로는, 어떤 논리 개념 집합에 대한 데이터베이스 스키마를 정의하는 Python 모델들이 있었음
여기에 기존 논리 집합과 아주 유사한 새 개념을 추가했는데, Claude는 기존 모델 세트를 그냥 재사용하면 된다고 판단했음
이론상으로는 돌아갔지만, 실제 소비자 쪽에서는 런타임 타입 추론 때문에 별별 우회를 해야 했음
작동은 했어도 추상화 계층을 완전히 잘못 잡은 사례였음- 코드가 더 많은 것이 정말 나쁜가 싶음
인간 입장에서는 추상화를 원하지만, 때로는 차라리 반복이 더 맞는 경우도 있음
기계가 코드를 쓰고 유지보수한다면, 예전의 추가 추상화 계층이 이제 꼭 필요하지 않을 수도 있음
옛날엔 Duff's device를 쓰고 루프를 수동으로 언롤해서 중복 코드를 직접 만들었음
지금은 컴파일러가 의도를 이해해서 중복된 어셈블리를 생성해주고, 우리는 그 중복을 신경 쓰지 않음
최근엔 LLM으로 꽤 비자명한 계산 기하학 코드 몇 조각이 필요했는데, 예전 같으면 라이브러리를 찾고 컴플라이언스 승인을 받고, 내 도메인 데이터 구조를 그 라이브러리 형식으로 바꾸는 비용이 들었을 것임
그게 직접 구현하는 것보다 싸긴 해도 결코 사소하진 않았음
이제는 LLM이 내게 필요한 부분만 써주고, 내가 저장한 데이터 형식 그대로 사용하게 할 수 있음
큰 라이브러리를 들여오지 않아도 되고 데이터 구조 변환도 필요 없음
정석적으로는 geometry library를 써서 중복을 막는 게 맞다고 하겠지만, 여기서는 자기완결적인 함수 하나가 그냥 잘 동작함
- 코드가 더 많은 것이 정말 나쁜가 싶음
-
정말 오랜만에 Hacker News에서 읽은 것 중 최고였음
너무 공감됨
Simon Willison이 말한 cognitive debt와, “증명해서 동작함을 확인한 코드만 배포하는 것이 네 일”이라는 관점 때문에, 나는 Intent-Driven Development 쪽 프로젝트를 작업하게 됐음
이전 의도는 변경이 누적될수록 항상 희미해지는 것처럼 보였음
이걸 실제 프로토콜로 정리해서 나중에 Hacker News에 올릴 수도 있을 듯함- 혹시 같은 걸 만들고 있는 건가 싶음
내 글들을 아직 못 봤다면 한번 찾아보길 권함
요약하면 이렇다- stacked-commits automation: context/why/verify 섹션은 건너뛸 수 없게 만듦
- product specs: 전체 ERD까지 포함 (https://excalidraw.com/#json=WT-oRUdyKBhAsDZJ3NwAR,WAbVgfO39...)
- SCIP 인덱스로 spec과 코드를 연결하고, commit과 AC도 연결해서 나중엔 원하는 산출물을 계속 붙일 수 있게 함
- 혹시 같은 걸 만들고 있는 건가 싶음
-
지금 내 문제 시각화는 이 그림에 가까움: https://excalidraw.com/#json=y1fSSx2z8-0nFs7CDnqhp,d9Di8JdGU...
소프트웨어 엔지니어링의 인지 병목은 코드 내부라기보다 산출물들 사이에 있다고 봄
코드는 그중 하나일 뿐임
outcome → requirements → spec → acceptance criteria → executable proof → review
나는 이 전이들 사이의 지루한 부분을 자동화하고, 각 단계에서 의도가 살아남았는지 검증하는 일에는 인간이 집중하도록 하는 실험적 툴링을 만들고 있음- 산출물 사이라는 프레이밍이 좋음
여기에 하나 더 넣고 싶은 계층은 proxies/metrics임
분석 비중이 큰 시스템에서는 진짜 손실이 spec → code가 아니라 question → proxy에서 생기는 경우가 많음
proxy가 acceptance criteria나 대시보드, eval에 박혀버리면 사람들은 그걸 최적화하고, 그게 단지 대리 지표였다는 사실은 점점 잊게 됨 - 데이터 시각화는 멋진데 편집 가능 상태라서 아쉬움
휴대폰에서 팬·줌·스크롤하려다가 캔버스 요소들을 자꾸 움직이게 됨
- 산출물 사이라는 프레이밍이 좋음