URL: https://www.youtube.com/watch?v=5KvY8CnBB3w 날짜: 2026-09-07 채널: Theo - t3․gg (t3dotgg) 원문 제목: Stop Pretending You Understand Your Codebase
📌 핵심 질문 / 이 영상이 다루는 핵심 논점
==중요한 소프트웨어를 만드는 개발자라면 코드베이스 전체를 완전히 이해할 수 없으며, 좋은 개발자의 능력은 모든 파일을 암기하는 데 있지 않고 불완전한 모델로도 올바른 범위에서 결정을 내리는 직관과 구조 감각에 있다.==
- 운영체제, 웹 플랫폼, PostgreSQL 같은 규모 있는 시스템은 누구도 모든 코드와 예외를 머릿속에 담을 수 없다.
- 좋은 코드베이스는 모든 사람이 모든 위치를 아는 코드베이스가 아니라, 낯선 사람이 필요한 위치를 빠르게 찾을 수 있는 코드베이스다.
- 정확한 정신 모델을 유지하는 일은 속도, 법적 준수, 보안, 기능 범위, 팀 협업과 교환되는 여러 가치 중 하나다.
- AI와 LLM은 코드의 세부를 더 모르게 만들 수 있지만, 빠르게 부분적 모델을 만들고 그 모델을 활용하게 해 주는 양날의 도구다.
Theo는 Shawn의 글을 따라가며 “코드베이스를 얼마나 이해해야 하는가?”라는 질문이 작은 프로젝트의 규범을 대규모 시스템에 억지로 적용하면서 생기는 오해라고 주장한다. 코드를 전부 읽지 않아도 시스템 전체의 연결 구조, 데이터 흐름, 실패 양상, 변경할 위치를 파악하고 검증할 수 있다면 충분히 효과적으로 일할 수 있다. 오히려 모든 세부를 직접 기억하려는 노력은 자동화 가능한 확인 작업에 뇌 용량을 소모하게 하며, 사용자를 위한 실제 결과물을 늦출 수 있다.
1. “전체를 안다”는 개발자 신화
1.1. 규모가 커질수록 완전한 이해는 불가능해진다
-
완전히 이해한다면 중요한 일을 하고 있지 않을 가능성
- 작은 프로젝트에서는 자신이 작성한 코드와 주변 맥락을 대부분 기억할 수 있다.
- 그러나 더 크고 중요한 코드베이스일수록 작성자·기여자·사용자·운영 환경이 늘어나며, 모든 동작과 예외를 한 사람이 파악할 수 없게 된다.
- 우리가 매일 사용하는 운영체제, 웹 플랫폼, 기반 프레임워크, PostgreSQL 같은 기술은 아무도 전체 구현을 완전히 이해하지 못하지만 여전히 사회와 산업을 지탱한다.
-
천재 프로그래머에 대한 업계의 환상
- 업계는 최고의 개발자를 모든 파일의 위치와 모든 코드 라인을 즉시 알고 있는 사람처럼 묘사해 왔다.
- 실제로 뛰어난 개발자는 모든 위치를 암기하기보다 “이 문제를 해결하는 코드는 어디에 있어야 하는가”를 높은 수준에서 판단한다.
- 이 판단은 좋은 소프트웨어 아키텍처에 대한 이해, 반복되는 설계 패턴, 과거에 비슷한 문제가 실패한 방식에서 나오는 직관이다.
1.2. 좋은 코드베이스의 기준은 기억량이 아니라 탐색 가능성이다
-
구조를 옮겨 의사결정을 쉽게 만든다
- 기능을 올바른 위치로 이동하면 현재 작업자가 더 나은 결정을 내리기 쉬워진다.
- 같은 구조는 해당 코드베이스에 새로 합류한 개발자가 시스템을 배울 때도 안내 표지판 역할을 한다.
- 코드의 모든 부분을 모든 사람이 알도록 만드는 대신, 문제를 만났을 때 빠르게 올바른 경로를 발견하도록 설계해야 한다.
-
낯선 사람도 일할 수 있어야 한다
- 좋은 코드베이스는 회사의 모든 사람이 모든 동작을 설명할 수 있는 곳이 아니다.
- 좋은 코드베이스는 사람이 일부만 이해하고 있어도 필요한 범위까지 확장해 갈 수 있는 곳이다.
- 이해의 깊이는 위치마다 달라져야 한다. 변경할 국소 영역은 깊이 알아야 하지만, 그 영역이 시스템의 다른 부분과 어떻게 연결되는지는 먼저 넓게 파악해야 한다.
1.3. 이 논쟁이 지금 중요한 이유
-
Shawn의 글과 바이브 코딩의 맥락
- Theo는 Shawn이 쓴 “코드베이스를 이해해야 하는가?”라는 글을 읽으며 자신의 생각을 전개한다.
- 그는 이 글이 사람들이 AI로 너무 빠르게 바이브 코딩을 하다가 파일과 동작의 위치를 잃어버리는 현상에서 나왔을 것이라고 추측하지만, 글의 주제는 AI에 한정되지 않는다고 본다.
- 개발자가 코드의 어느 부분은 과거보다 더 잘 이해하면서도, 더 많은 부분은 전혀 모르는 상태가 되는 현재의 스펙트럼을 정면으로 다룰 필요가 있다.
-
금기시된 대화
- 개발자는 “내가 작성하는 코드의 구조를 모른다”고 말하기를 꺼린다.
- 이 주제를 말할 때도 실제로 뇌가 코드를 어떻게 이해하고, 불완전한 지식으로 어떻게 일하는지는 충분히 논의되지 않는다.
- Theo는 이 불편한 사실을 숨기기보다, 불완전한 이해를 관리하는 방법을 구체적으로 살펴보자고 제안한다.
2. 작은 코드베이스의 규범과 대규모 시스템의 현실
2.1. 코드베이스의 크기와 팀의 이직률이 답을 바꾼다
-
작고 안정적인 팀의 경우
- Redis 같은 라이브러리나 The Witness 같은 게임처럼 코드베이스가 작고 팀의 변동이 적은 곳에서는 전체를 이해해야 좋은 일을 할 수 있다는 말이 어느 정도 성립한다.
- 한 사람이 많은 핵심 결정을 직접 내리고, 동작의 역사와 설계 의도를 가까이서 추적할 수 있기 때문이다.
- 이런 환경에서는 정확한 이론을 유지하는 일이 작업의 즐거움이자 품질의 중요한 기반이 된다.
-
크고 변동이 큰 팀의 경우
- Google 웹 검색 백엔드나 GitHub처럼 수많은 엔지니어와 높은 이직률을 가진 시스템은 전체를 이해하는 것이 현실적으로 불가능하다.
- 각 개발자는 자신이 담당하는 지역을 최대한 잘 이해하고, 그 지역이 다른 부분과 주고받는 계약과 흐름을 파악해야 한다.
- 온라인 소프트웨어 논의에서는 첫 번째 유형의 개발 경험이 과대표집되므로, 두 번째 유형의 현실이 종종 열등한 작업 방식처럼 취급된다.
2.2. 부분적 이해는 실패가 아니라 대규모 시스템의 최선이다
-
Shawn의 핵심 주장
- 많은 소프트웨어 엔지니어링 환경에서 부분적으로 이해한 상태에 있는 것은 아무런 문제가 아니다.
- 충분히 큰 시스템에서는 부분적 이해가 할 수 있는 최선이며, 모든 것을 완전히 아는 사람이 나타날 때까지 기다리는 것은 업무를 멈추는 일이다.
- Theo는 “부분적 이해”라는 표현보다 코드베이스의 위치에 따라 이해의 깊이를 조절해야 한다고 덧붙인다.
-
변경 전 필요한 최소 범위
- 격리된 영역을 수정하기 전에 주요 구성 요소가 어떻게 연결되는지는 알아야 한다.
- 반대로 각각의 구성 요소가 내부에서 어떤 모든 선택을 했는지까지 파고들 필요는 없다.
- 이 구분이 있으면 세부를 모른다는 불안과, 영향 범위를 모른 채 변경하는 무책임함을 동시에 피할 수 있다.
3. “프로그래밍은 이론 만들기”에 대한 반론
3.1. Peter Naur의 이론 만들기 관점
-
코드보다 앞선 프로그램 이론
- Peter Naur의 유명한 논문 “Programming as Theory Building”은 개발자가 실제로 만드는 핵심 산출물이 코드가 아니라 프로그램에 대한 이론이라고 주장한다.
- 코드와 문서는 그 이론을 일부만 표현하는 부산물이고, 개발자는 무엇이 왜 일어나는지에 대한 직관을 머릿속에 구축한다.
- 이 관점에서는 코드를 잃어도 경험 많은 개발자가 다시 만들 수 있지만, 팀 전체가 이론을 잃으면 기존 코드를 보고도 시스템을 해석하기 어렵다.
-
문서로 모든 지식을 옮길 수 없는 이유
- 어디에서 실패하는지, 특정 장애가 왜 생겼는지, 어떤 기묘한 예외가 의도적으로 유지되는지는 코드와 문서만으로 완전히 표현하기 어렵다.
- 에이전트용 지침을 아무리 많이 작성해도 프로젝트에서 반복적으로 작업하며 쌓이는 역사적 맥락과 특정 코드베이스에 맞춘 직관을 모두 산문으로 옮길 수는 없다.
- 이 한계가 코드 에이전트의 맥락 관리 문제를 만든다.
3.2. 에이전트는 매번 새로 들어오는 개발자다
-
스레드마다 초기화되는 지식
- 새 에이전트 스레드를 시작할 때마다 이전 스레드가 수행한 일과 실패에서 얻은 역사적 지식이 사라진다.
- 따라서 에이전트는 높은 능력을 갖췄지만 코드베이스를 처음 보는 새 개발자처럼 행동한다.
- 이 구조는 과거의 추론이 잘못된 채 누적되는 것을 막는 장점이 있지만, 중요한 결정을 매번 다시 발견하게 만든다.
-
새 개발자가 성과를 내도록 만드는 설계
- 새 스레드가 올바른 파일과 흐름을 찾아갈 수 있도록 저장소 구조, 테스트, 명령어, 실패 사례를 접근 가능한 형태로 만들어야 한다.
- Theo는 완전히 이해하지 못한 에이전트가 실제 일을 하도록 만드는 이 과정을 어려우면서도 보람 있는 개발 과제로 본다.
- 핵심은 모든 역사적 지식을 복사하는 것이 아니라, 에이전트가 자신의 가설을 검증하고 다음 판단으로 이어 갈 수 있는 발판을 제공하는 것이다.
3.3. 기존 프로그램을 버리고 다시 만들자는 결론의 한계
-
Naur의 강한 결론
- 기존 문서만으로 프로그램 이론을 재구성하는 것은 엄밀히 불가능하므로, 기존 기술을 버리고 새 팀이 문제를 처음부터 해결해야 한다는 주장이 나온다.
- 새 팀은 코드를 해독하는 대신 문제를 다시 풀며 새로운 이론을 만들어 갈 수 있다는 논리다.
- Theo는 작은 범위에서는 설득될 수 있지만, 충분히 큰 사용자 시스템에는 적용하기 어렵다고 예고한다.
-
현실의 제약
- 사용자가 있는 대규모 시스템은 명세에 적히지 않은 동작과 예외를 수천 개 품고 있다.
- 기존 팀조차 모든 예외를 기억하지 못하는데, 새 팀이 요구사항만 보고 동일한 시스템을 재현하기는 더 어렵다.
- 결국 완전한 재작성은 기존 시스템을 변경하지 않고 대체하는 일이 아니라, 기존 시스템과 계속 비교하며 작은 단위로 바꿔 가는 작업이 된다.
4. 대규모 시스템을 처음부터 다시 쓸 수 없는 이유
4.1. 사용자가 만든 기묘한 예외는 코드 깊숙이 묻힌다
-
재현할 수 없는 동작의 축적
- 충분히 큰 시스템은 사용자와 운영 환경 때문에 수천 개의 특이 케이스와 이상한 동작을 가진다.
- 새 사용자 유형, SaaS의 온프레미스 설치, 여러 데이터베이스에 걸친 샤딩, 강한 데이터 지역성(data locality), 국제화 같은 기능은 처음에는 합리적으로 보이지만 시간이 지나면 시스템의 모든 층을 복잡하게 만든다.
- 이런 요구사항을 처리하기 위해 추가된 패치와 예외는 원래 설계보다 더 깊게 코드에 얽힌다.
-
Wicked Features의 공간 키 사례
- Theo는 소프트웨어가 오랜 시간 동안 받아들인 기묘한 요구를 보여 주는 “Wicked Features” 글의 사례를 소개한다.
- 버전 10.17에서 CPU가 사용자가 스페이스바를 누르고 있을 때 더 이상 과열되지 않도록 수정된 사례가 등장한다.
- 장기 사용자는 “컨트롤 키가 손에 닿기 어려워 스페이스바를 누르고, 급격한 온도 상승을 Emacs가 컨트롤 입력으로 해석하도록 설정했다”며 이 변경이 자신의 작업 흐름을 깨뜨렸다고 항의한다.
- 의도하지 않은 사용법처럼 보이는 설정도 실제 사용자가 의존하는 순간 제품의 일부가 되며, 새 구현팀이 이를 알아내기는 거의 불가능하다.
4.2. 성공적인 재작성은 기존 시스템을 쪼개는 일에서 시작한다
-
점진적 재작성의 구조
- 성공적인 재작성은 기존 코드베이스를 작고 격리된 조각으로 나누는 데서 시작한다.
- 한 조각을 새 구현으로 교체하고, 기존 시스템과 비교하며 동작을 확인한 뒤 다음 조각으로 넘어간다.
- 따라서 재작성은 기존 시스템을 전혀 건드리지 않는 새 프로젝트가 아니라, 기존 시스템을 단계적으로 변화시키는 작업이다.
-
재작성 전에 기존 시스템에서 일해야 하는 이유
- Theo는 자신이 재작성에 쉽게 뛰어드는 사람임을 인정하면서도, 먼저 기존 코드베이스에서 실제로 일해 본다고 말한다.
- 그 과정에서 무엇이 작동하고 작동하지 않는지, 어떤 문제가 중요하지 않은지, 팀이 어떤 작업 방식과 품질 기준을 선호하는지 파악한다.
- 기존 시스템에 의미 있는 기여를 할 만큼 이해하기 전에는 재작성의 목표와 성공 조건을 정의할 수 없다.
4.3. “Rust로 다시 썼다”는 말만으로 문제는 해결되지 않는다
-
원인을 모른 채 언어를 바꾸는 재작성
- Theo는 “느리다는 생각이 들어 Rust로 다시 썼다”는 식의 발표를 경계한다.
- 기존 시스템의 병목이 알고리즘인지, I/O인지, 데이터 모델인지, 배포 방식인지 확인하지 않고 언어만 바꾸면 문제를 그대로 옮길 수 있다.
- 재작성자는 무엇을 대체하는지와 원래 어떤 사용자를 위해 존재하는지 이해해야 한다.
-
Gemini를 근거로 한 잘못된 대체품 사례
- Theo는 T3 Code, VS Code, Cursor가 근본적인 성능 문제로 망할 것이라는 Gemini 공유 대화를 받은 일을 말한다.
- 그 분석은 Electron 인스턴스를 수백 개 동시에 열 때 이론적으로 나쁘다는 내용을, Codeex나 Claude Code 앱의 각 스레드가 새 Electron 앱을 만든다는 주장으로 잘못 확장한 환각이었다.
- 보낸 사람은 원래 시스템을 실제로 이해하거나 측정하지 않은 채 Rust로 만든 자신의 대체품을 홍보했다.
- 이런 사례 때문에 신중한 재작성까지 무지한 재작성자와 함께 평가절하되지만, 진짜 재작성은 문제를 고치려 기존 시스템을 먼저 관찰한다.
5. 버려진 코드베이스도 다시 이해할 수 있다
5.1. “팀이 사라지면 시스템을 버려야 한다”는 결론은 틀리다
-
현실에서 반복되는 소유권 단절
- 수억 줄의 코드와 수천 명의 엔지니어를 가진 기술 회사에서는 핵심 인력이 잘못된 시점에 퇴사하거나 팀이 해체되는 일이 일어난다.
- 코드베이스가 1년 동안 유지보수되지 않아 아는 사람이 아무도 남지 않는 일도 드물지 않다.
- 그때마다 새로 작성하는 것은 비용과 위험이 너무 크며, 실제 조직은 버려진 시스템을 다시 살려야 한다.
-
재구성 가능한 프로그램 이론
- Theo는 자신이 버려진 코드베이스를 넘겨받아 효과적으로 다룰 수 있는 상태까지 끌어올린 경험이 있다고 말한다.
- 먼저 한 개의 실행 흐름을 시작부터 끝까지 이해한다.
- 그 흐름과 연결된 인접 영역으로 조금씩 확장하면서, 작은 변경을 넣고 관찰한 결과를 통해 이론을 보정한다.
- 시간이 걸리지만, 과거 개발자들의 머릿속에 있던 이론을 전부 복원하지 않아도 작업 가능한 모델을 새로 세울 수 있다.
5.2. AI는 레거시 유지보다 지식 확장에 더 큰 도움을 준다
-
질문과 검증의 반복
- AI가 레거시 시스템의 모든 역사적 맥락을 자동으로 보유하는 것은 아니다.
- 하지만 코드, 테스트, 로그, 설정, 과거의 출력에 이미 남아 있는 흔적을 바탕으로 질문에 답하고, 실제 코드에서 그 답을 확인하도록 도울 수 있다.
- 새 담당자는 AI의 가설을 그대로 믿지 않고 코드 실행과 검색으로 검증하면서 지식의 범위를 빠르게 넓힐 수 있다.
-
역사적 지식의 간접 보존
- 이전 개발자가 떠나도 그 사람이 만든 함수와 테스트, 오류 처리, 데이터 변환이 저장소에 남아 있다.
- AI는 이전 개발자의 머릿속을 복사하지 못하지만, 그들이 남긴 결과를 질의 가능한 형태로 엮어 준다.
- 이 정도의 출력만으로도 완전한 이론이 아닌 실용적인 부분 이론을 만들고 안전한 다음 작업을 정할 수 있다.
6. 대규모 코드베이스에서는 누구나 틀린 이론으로 일한다
6.1. 유능한 개발자도 시스템의 일부를 오해한다
-
Twitch의 GraphQL 생성 명령 사례
- Theo가 함께 일했던 뛰어난 풀스택 개발자는 백엔드와 프론트엔드 양쪽을 모두 다뤘지만, 백엔드에 새 GraphQL 쿼리를 정의한 뒤 프론트엔드에서 호출하는 전체 절차는 한 번도 수행하지 않았다.
- 이 흐름에는 GraphQL 서버의 최신 스키마를 내려받아 React 코드에 필요한 TypeScript 정의를 생성하는 명령이 필요했다.
- 그는 양쪽 코드가 논리적으로 맞는데도 클라이언트에서 타입 오류가 나는 화면을 공유했고, 주변 사람들은 똑똑한 개발자가 겪는 문제라 더 깊은 버그라고 추측했다.
- Theo가 “GraphQL 생성 명령을 실행했느냐”고 묻자 그는 그 단계가 필요하다는 사실을 처음 깨달았고, 명령을 실행하자 문제가 해결됐다.
-
모든 것을 배우는 비용
- 그 개발자는 무능해서가 아니라, 시스템 전체를 다루는 중에도 특정 조합의 작업을 한 번도 해 보지 않았기 때문에 작은 절차를 몰랐다.
- 유능한 상태를 유지하려면 모든 것을 알아야 하는 것이 아니라, 중요한 결정을 내릴 만큼의 흐름을 알고 모르는 부분을 찾아낼 수 있어야 한다.
- 모든 세부를 학습하고 기억하는 데 뇌를 쓰면 실제로 코드를 바꾸고 사용자 문제를 해결할 시간이 줄어든다.
6.2. TypeScript와 자동화는 “덜 이해하고 더 잘 일하기”의 사례다
-
타입 시스템이 빼앗아 가는 인지 부담
- TypeScript는 오타, 잘못된 타입, 숫자를 요구하는 함수에 문자열을 전달하는 실수를 자동으로 지적한다.
- 개발자는 함수를 호출할 때마다 인자가 정확히 맞는지 머릿속에서 검사하지 않아도 된다.
- 그 결과 함수의 내부 계약을 매번 깊게 들여다보지 않게 되어, 어떤 의미에서는 코드베이스의 세부 이해가 줄어든다.
-
세부 이해를 줄인 대가보다 얻는 이익이 크다
- 타입 시스템이 반복 확인 작업을 대신하면 뇌가 더 높은 수준의 설계와 사용자 문제에 집중할 공간을 얻는다.
- 변경을 더 안정적으로 만들고, 더 빠르게 배포하며, 버그를 줄일 수 있다.
- 컴파일러, 타입 검사기, 린터, 테스트, AI 검증 등 자동화할 수 있는 지루한 세부를 넘기는 것은 전체 이해도가 내려가지 않는 한 긍정적인 교환이다.
6.3. 새 개발자는 “모든 것을 통제했던 프로젝트”의 기준을 버려야 한다
-
사이드 프로젝트에서 회사 코드베이스로의 충격
- 개인 프로젝트에서는 자신이 모든 줄을 작성하고 모든 결정을 통제했기 때문에 어디에 무엇이 있는지 자연스럽게 알 수 있다.
- 첫 직장에서 자신이 오기 전부터 존재한 코드와 다른 팀이 소유한 시스템을 만나면, 같은 수준의 완전한 통제를 기대할 수 없다.
- 새 개발자가 가장 크게 어려움을 겪는 지점은 코드가 어려워서만이 아니라, 모든 것을 알아야 한다는 기대를 버리지 못해서다.
-
현실적인 목표
- 입사할 때부터 전체를 알 수 없다는 사실을 전제로 삼아야 한다.
- 먼저 업무에 필요한 흐름과 인터페이스를 파악하고, 모르는 세부는 도구와 동료에게 확인한다.
- 불완전한 모델을 점진적으로 개선하는 능력이 처음부터 완전한 모델을 갖추는 능력보다 중요하다.
7. 불완전한 모델로도 결정을 내려야 한다
7.1. 현대 소프트웨어는 인간 한 명의 기억보다 크다
-
대규모 시스템의 정의적 특징
- 현대 소프트웨어 시스템은 한 사람은 물론 한 팀도 전체를 머릿속에 유지할 수 없을 정도로 크다.
- Shawn은 이 주제를 “아무도 대규모 소프트웨어 프로젝트가 어떻게 작동하는지 모른다”라는 별도의 글에서도 다뤘다.
- 전체를 정확하게 알 수 없다는 사실은 예외 상황이 아니라 대규모 시스템의 기본 조건이다.
-
자신감을 갖고 입장을 취하기
- 완벽하게 이해하는 사람이 나타날 때까지 결정을 미루면 아무 일도 진행되지 않는다.
- 유능한 엔지니어는 가진 정보로 가장 교육된 추측을 하고, 그 결과를 관찰하며 수정한다.
- 자신감은 모든 사실을 안다는 뜻이 아니라, 불확실성을 인정한 채 가설과 검증 계획을 세울 수 있다는 뜻이다.
7.2. 1980년대의 “대형 프로그램”과 오늘의 규모는 다르다
-
Naur의 시대적 맥락
- 1985년의 평균 프로그램 규모는 오늘날보다 몇 자릿수 작았을 가능성이 있다.
- Naur가 대형 프로그램의 예로 든 산업 모니터링 프로그램은 약 20만 줄이었다.
- 1987년 첫 GCC는 약 10만 줄이었지만, 2015년 GCC는 1,400만 줄을 넘었다.
-
재작성 가능성을 가르는 규모와 테스트 가능성
- 테스트를 재사용할 수 있다면 20만 줄 또는 그보다 작은 시스템을 다시 작성하는 일은 상대적으로 현실적일 수 있다.
- 컴파일러는 입력과 출력이 비교적 명확하므로 잔인할 정도로 강한 엔드투엔드 테스트를 만들 수 있고, 이 특성은 Bun의 Rust 재작성처럼 언어 전환을 정당화할 수 있다.
- 사용자가 직접 상호작용하는 시스템은 데이터 표현, 접근성, 응답 순서, 과거의 예외 동작까지 사용자가 기대하므로 같은 동작을 엔드투엔드로 보장하기 어렵다.
8. 이론 유지도 여러 가치 중 하나다
8.1. LLM은 정신 모델을 약화시키면서 부분 모델을 빠르게 만든다
-
LLM에 대한 단순한 비판의 한계
- LLM이 코드의 상세한 이론을 직접 구축하는 일반적인 과정을 방해하므로 나쁘다는 주장은 지나치게 단순하다.
- LLM은 개발자가 모든 구현을 읽고 기억하는 대신 빠르게 부분적 이론을 만들도록 돕는다.
- 그 부분적 이론을 바탕으로 검색, 수정, 테스트, 설명을 반복하게 해 주므로, 완전한 모델을 갖지 못해도 생산적인 일을 할 수 있다.
-
양날의 거래
- AI가 생성한 코드만 받아들이면 세부의 인과관계를 직접 학습할 기회가 줄어들 수 있다.
- 반대로 반복적인 구현과 탐색을 맡기면 개발자는 실패 패턴과 시스템 경계를 더 빠르게 발견할 수 있다.
- 어느 쪽이 좋은지는 작업 유형, 검증 가능성, 코드베이스의 위험도, 개발자의 기존 도메인 이해에 따라 달라진다.
8.2. 완전한 이론을 어렵게 만드는 것은 LLM만이 아니다
-
코드베이스의 복잡성을 키우는 다섯 가지 요인
- 다른 사람이 같은 코드베이스에 코드를 작성하도록 허용하면, 모든 변경의 의도와 맥락을 한 사람이 추적할 수 없다.
- 접근성·데이터 보호 같은 법적·사회적 요구사항을 구현하면 기술적으로 가장 단순한 설계에서 벗어나야 한다.
- 동료가 퇴사하거나 팀을 옮기고 휴가를 가면, 기존 이론을 가진 사람이 시스템에서 일시적으로 또는 영구적으로 사라진다.
- 보안 패치를 위해 라이브러리와 소프트웨어 버전을 올리면, 개발자가 직접 선택하지 않은 동작 변화가 들어온다.
- 외부 라이브러리와 의존성을 추가하면, 코드베이스의 작동 이론이 다른 프로젝트의 내부 결정까지 포함하게 된다.
-
복잡성의 원인이 곧 나쁜 것은 아니다
- 위 요소들은 모두 개인의 코드베이스 이해도를 낮추지만, 그 자체로 명백히 나쁜 것은 아니다.
- 이론을 유지하는 가치는 속도, 보안, 법적 준수, 팀의 지속 가능성, 사용자 요구와 함께 평가해야 한다.
- 복잡성을 늘리더라도 법적 요구사항을 지키거나 플랫폼을 지원하거나 고객에게 필요한 기능을 제공해야 하는 경우가 있다.
8.3. 제품 요구사항은 이해 가능성과 충돌할 수 있다
-
속도와 정치적 현실
- 일정에 맞춰 기능을 출시해야 하면 가장 아름다운 구조보다 빠르게 충분한 결과를 내는 선택을 할 수 있다.
- 조직 내 합의나 정치적 제약도 구조적 순수성을 훼손하는 요인이 된다.
- 이런 선택이 누적되면 코드베이스의 이론은 더 흐려지지만, 제품이 실제 사용자의 문제를 해결하는 데에는 필요할 수 있다.
-
플랫폼 확장의 비용
- iOS와 Android를 동시에 지원하면 플랫폼별 생명주기, UI, 네트워크, 배포 제약이 추가되어 프로젝트 복잡도가 크게 증가한다.
- 개발자가 두 플랫폼의 모든 세부를 동일한 깊이로 알지 못해도, 경계와 데이터 흐름을 파악하면 기능을 전달할 수 있다.
- 완전한 이론을 보존하는 것보다 더 많은 사용자에게 서비스를 제공하는 것이 중요한 순간이 있다.
9. 순수 엔지니어링과 불순한 엔지니어링
9.1. 서로 다른 유형의 엔지니어는 서로 다른 성공 기준을 가진다
-
순수(pure) 엔지니어링
- 순수 엔지니어는 기술 문제를 가능한 한 완벽하게 해결하는 데 관심이 있다.
- 오픈소스 라이브러리, 최고의 HTTP 요청 라이브러리, 완벽한 게임 엔진처럼 기술적 정합성 자체가 중요한 작업이 여기에 가깝다.
- 작은 범위의 코드베이스를 깊이 이해하고 정확한 모델을 유지하는 일이 재미있고 스트레스가 적다.
-
불순(impure) 엔지니어링
- 불순 엔지니어링은 실제 세계의 문제를 주어진 시간과 조건 안에서 최대한 효율적으로 해결하는 일이다.
- 돈을 받고 일하는 기술 회사에서는 특정 프로젝트나 기능을 기한 안에 최대한 잘 전달하는 것이 핵심이다.
- 사용자의 요구, 레거시, 법적 조건, 예산, 조직의 우선순위를 함께 다뤄야 하므로 기술적으로 가장 우아한 답만을 고를 수 없다.
9.2. “진짜 엔지니어링”과 실제 가치가 어긋나는 역설
-
정확한 모델을 유지하고 싶은 욕구
- 대부분의 엔지니어, 특히 순수 엔지니어 성향이 강한 사람은 코드의 정확한 정신 모델을 유지하고 싶어 한다.
- 깊은 이해와 복잡한 문제의 완벽한 해결은 자신이 중요한 일을 하고 있다는 감각을 준다.
- 그래서 그런 작업이 “진짜 엔지니어링”처럼 느껴진다.
-
고용되는 이유와 기술적 자부심의 분리
- 실제로 회사가 돈을 지불하는 이유는 사용자의 문제를 일정 안에 해결하고, 제품을 운영하며, 다른 사람과 협력하기 위해서다.
- 완벽한 모델을 유지하고 싶은 욕구와 회사가 요구하는 실제 가치는 거의 겹치지 않을 때가 많다.
- 이 모순을 인정하지 않으면 순수한 기술 기준으로 다른 유형의 개발자를 깎아내리는 나쁜 대화가 생긴다.
9.3. 오픈소스와 직장 업무를 함께 이해하는 법
-
사이드 프로젝트의 의미
- 많은 개발자가 퇴근 후 오픈소스나 작은 개인 프로젝트를 시작하는 이유는 자신이 전체 이론을 유지할 수 있는 코드베이스에서 일하고 싶기 때문이다.
- 이런 취향은 잘못된 것이 아니며, 순수 엔지니어링의 즐거움을 얻는 건강한 방법이 될 수 있다.
- 다만 직장에서는 고용주가 정한 엔지니어링 가치와 사용자 요구를 받아들이고, 개인의 순수성 기준을 조정해야 한다.
-
느린 코드도 때로는 올바른 코드다
- 성능을 중요하게 생각하더라도 출시 일정이나 특이한 요구사항 때문에 느린 구현을 선택할 수 있다.
- 이 선택은 엔지니어가 성능을 모른다는 뜻이 아니라, 성능을 다른 가치와 교환했다는 뜻이다.
- 코드베이스 이론의 정확성도 같은 방식으로 속도와 기능 범위에 교환될 수 있다.
10. 온라인 논쟁이 놓치는 것
10.1. 지역적 추론은 컴퓨터과학의 오래된 목표다
-
부분적 이해에서 지역성을 확보하기
- Lobsters의 한 댓글은 부분적 이해를 가진 채 코드의 지역적 동작을 추론하는 능력이 컴퓨터과학 초기부터 핵심 목표였다고 지적한다.
- 한 모듈의 계약과 입출력을 믿고 내부의 모든 구현을 몰라도 작업하는 설계가 소프트웨어 추상화의 핵심이다.
- 이런 관점은 대규모 회사에서 좋은 엔지니어가 때로는 나쁜 코드를 쓸 수 있다는 Shawn의 이전 글과도 연결된다.
-
AI 글로 잘못 분류되는 이유
- Shawn의 글은 LLM을 짧게 언급했지만 AI 글로 분류하지 않았고, Theo도 그 판단에 동의한다.
- AI가 주제의 한 요소일 뿐, 실제 쟁점은 규모가 큰 소프트웨어를 인간이 어떻게 운영하느냐에 있다.
- 코드 생성 도구가 사라져도 대규모 시스템에서 완전한 이해가 불가능하다는 문제는 그대로 남는다.
10.2. “상황이 나쁘다는 글이어야 한다”는 반응
-
Hacker News와 Lobsters 댓글의 한계
- Hacker News의 한 댓글은 이런 상황이 나쁘다면 글이 왜 그 나쁨을 비판하지 않느냐는 반응을 보였다.
- 이미 “현실이 얼마나 망가졌는가”를 다루는 글은 많으므로, Shawn은 그 대신 현실에서 어떻게 일할지 설명하는 틈새를 선택했다.
- 문제를 설명하는 것과 그 조건 안에서 유능하게 일하는 방법을 설명하는 것은 서로 다른 종류의 가치가 있다.
-
Seth Godin 비교에 대한 반응
- 또 다른 댓글은 Shawn을 Seth Godin에 비유하며, 기술 리더와 라인 매니저가 말하는 용어를 풀어 주는 사람일 뿐 엔지니어링에 유용한 글은 쓰지 않는다고 폄하했다.
- Theo는 그 댓글 작성자가 직업을 갖고 있는지 의심할 만큼 이 평가가 현실과 동떨어졌다고 강하게 반발한다.
- 글의 성과는 Hacker News에서 어떤 글이 잘 퍼지는지에 따라 보이는 부분이 달라지며, 엔지니어링 주제가 항상 높은 조회수를 얻는 것은 아니다.
10.3. 팀과 사용자를 이해하는 능력은 기술 능력의 일부다
-
관리자의 요구를 이해해야 한다
- 자신에게 업무를 주는 기술 리드나 라인 매니저가 무엇을 말하는지 이해하는 것은 엔지니어링 외부의 잡무가 아니다.
- 팀이 무엇을 요청하는지, 그 요청이 어떤 사용자 문제에서 나왔는지 알아야 올바른 구현을 선택할 수 있다.
- 사용자의 문제를 사람들과 함께 해결하지 못한다면, 코드 내부를 아무리 깊이 알아도 실제 엔지니어링의 핵심을 놓친다.
-
협업하지 못하면 LLM보다 못할 수 있다
- Theo는 팀과 사용자와 협력해 실제 문제를 해결하지 못하는 사람이라면 LLM보다 엔지니어링을 못하는 상태라고까지 말한다.
- 이 과격한 표현의 핵심은 구현 지식만으로 제품 개발을 완수할 수 없다는 것이다.
- 요구사항을 듣고, 불확실성을 질문하고, 결과를 공유하고, 피드백에 따라 바꾸는 능력도 기술 역량에 포함된다.
11. AI가 코드 규모를 폭발시키는 시대의 작업 방식
11.1. 10,000배 많은 코드와 정신적 미로
-
Nick의 전망
- 사람은 지금도 전체 프로그램을 머릿속에 넣을 수 없는데, AI가 코드의 양을 10,000배 늘리면 상황은 더 극단적으로 변한다.
- 완전한 핸즈오프 바이브 코딩이 기본이 될 것이라고 보는 사람들은, 인간의 뇌가 생성 속도를 따라가지 못할 것이기 때문이라고 주장한다.
- 그때 엔지니어의 일은 완벽한 지도를 만드는 것이 아니라, 불완전한 정보로 정신적 미로를 탐색하는 일이 된다.
-
개발자의 역할 변화
- 개발자는 모든 줄을 직접 작성하는 사람에서, 시스템 경계·데이터 흐름·실패 조건을 알고 에이전트를 올바른 방향으로 이끄는 사람으로 이동한다.
- 좋은 지시는 구현 세부를 전부 기술하는 대신 기준이 되는 동작, 비교할 시스템, 검증할 실패 사례를 제시한다.
- 결과를 테스트하고 실제 동작과 비교하는 루프가 코드를 직접 읽는 시간만큼 중요해진다.
11.2. Theo의 T3 Code 모바일 앱 재작성 사례
-
SwiftUI로 옮기면서 코드를 읽지 않은 경험
- Theo는 T3 Code 모바일 앱을 React Native에서 SwiftUI로 다시 작성하고 있다.
- 그는 Swift 코드 6만 줄 이상을 단 한 줄도 읽지 않았지만, 앱을 사용하며 발견한 실패와 이미 알고 있는 다른 시스템의 동작을 기준으로 에이전트를 조종했다.
- 대부분의 문제는 “다른 곳에서 이렇게 작동하니 여기서도 동일하게 미러링하라”고 말하는 것만으로 해결됐다.
-
구현 세부가 없어도 필요한 지식
- 예외적으로 해결되지 않은 문제는 새 스레드의 프로젝트 선택 같은 이상한 경계 사례였다.
- Theo가 활용한 지식은 Swift 코드의 각 함수가 아니라, 데이터가 어디서 와서 어디로 가는지, 시스템의 다른 부분과 어떻게 연결되는지, 어떤 실패 조건이 존재하는지였다.
- T3 Code의 나머지 부분에서 축적한 전체 구조 감각이 한 줄도 읽지 않은 새 영역의 구현을 올바른 방향으로 이끌었다.
11.3. “더 잘 이해하면서 더 적게 이해하는” 균형
-
새로운 개발자처럼 느끼는 경험
- Theo는 현재 코드베이스를 과거보다 더 잘 이해하는 영역이 있는 동시에, 내부 구현을 전혀 모르는 영역이 더 늘었다고 말한다.
- 이 상태는 다시 신입 개발자가 된 것처럼 낯설지만, 실제 소프트웨어를 빠르게 출시하는 새로운 작업 흐름을 만든다는 점에서 즐겁다.
- 완전한 통제감을 포기하면 오히려 더 넓은 문제와 제품 결과에 집중할 수 있다.
-
두려움과 가능성을 함께 보기
- AI 기반 개발은 무섭고 스트레스가 큰 변화지만, 현재 개발자가 할 수 있는 일의 범위는 매우 커졌다.
- 중요한 것은 코드의 모든 세부를 이해하는지보다, 부분적 모델을 만들고 검증하며 위험한 변경을 막는지다.
- 이 관점은 산업의 변화를 개발자의 무력화가 아니라 새로운 형태의 역량과 워크플로로 받아들이게 한다.
주요 발언 모음
“중요한 일을 하는 코드베이스일수록 그 안의 모든 일을 이해할 가능성은 낮아진다.”
“좋은 코드베이스는 회사의 모든 사람이 모든 위치를 아는 곳이 아니라, 필요한 위치를 비교적 빠르게 찾을 수 있는 곳이다.”
“충분히 큰 코드베이스에서는 모두가 프로그램에 대해 틀린 이론을 갖고 일한다.”
“완벽한 이해를 가진 누군가가 답을 가져올 때까지 기다릴 수 없다. 가진 정보로 가장 교육된 추측을 하고 결과를 감당해야 한다.”
“타입 시스템이 내 뇌에서 작은 확인 작업을 가져가자, 더 안정적인 변경을 더 빠르게 만들 수 있었다.”
“코드가 10,000배 많아진다면 엔지니어는 불완전한 정보만으로 정신적 미로를 다루는 법을 배워야 한다.”
핵심 데이터 & 수치
- 영상 길이: 약 28분 36초이며, Shawn의 글을 읽고 반응하는 형식으로 진행된다.
- 1987년 GCC: 첫 버전은 약 10만 줄이었다.
- 2015년 GCC: 1,400만 줄을 넘었으며, 과거의 “대형 프로그램”과 오늘날의 규모 차이를 보여 준다.
- 산업 모니터링 프로그램: Naur가 예로 든 대형 프로그램은 약 20만 줄이었다.
- T3 Code SwiftUI 재작성: Theo가 구현을 직접 읽지 않은 채 다루는 Swift 코드가 6만 줄 이상이다.
- AI 코드 증가 전망: Nick의 논지는 AI가 코드 양을 10,000배 늘릴 수 있다는 가정에 기반한다.
- Depot 후원 메시지: Depot은 Docker 빌드 레이어를 팀과 CI가 공유하는 캐시로 제공하며, 실제 Docker 빌드가 최대 40배 빨라질 수 있다고 홍보한다.
- 버전 10.17 공간 키 사례: 스페이스바를 누를 때 CPU가 과열되지 않도록 바뀐 수정이 기존 사용자의 Emacs 입력 설정을 깨뜨렸다.
결론 및 시사점
- 코드베이스 전체를 이해한다는 목표는 작은 개인 프로젝트의 경험을 대규모 시스템에 잘못 투사한 신화에 가깝다.
- 규모가 큰 시스템에서 필요한 것은 완전한 지식이 아니라 전체 연결 구조, 변경 범위, 실패 조건을 포함한 실용적인 부분 모델이다.
- 좋은 구조는 모든 파일을 암기하게 만드는 대신 낯선 개발자가 올바른 위치와 경계를 빠르게 찾게 만든다.
- 재작성은 기존 시스템을 무시하는 새 출발이 아니라, 사용자와 과거의 기묘한 요구를 보존하며 작은 조각을 점진적으로 교체하는 작업이다.
- 버려진 코드베이스도 한 흐름을 끝까지 추적하고, 인접 영역으로 확장하며, 작은 변경을 검증하면 다시 이해할 수 있다.
- TypeScript, 컴파일러, 린터, 테스트, AI에게 자동 확인을 맡기는 일은 세부 이해를 일부 줄이는 대신 중요한 판단에 쓸 뇌 공간을 확보한다.
- 완전한 정신 모델은 속도·법률·보안·플랫폼 지원·팀 협업·사용자 가치와 교환되는 여러 가치 중 하나다.
- 순수 엔지니어링의 즐거움은 유효하지만, 직장에서는 일정과 사용자 문제를 해결하는 불순 엔지니어링의 기준도 받아들여야 한다.
- AI 시대의 핵심 역량은 생성된 코드의 모든 줄을 읽는 데 있지 않고, 기준 동작과 데이터 흐름을 제시하고 결과를 검증하는 데 있다.
- 더 많은 코드를 더 적게 이해하면서도 더 나은 결과를 낼 수 있다는 역설을 받아들이면, 변화하는 개발 환경을 두려움만이 아니라 새로운 설계 문제로 다룰 수 있다.
핵심 요약 (20줄)
- 중요한 소프트웨어일수록 한 사람이 코드베이스 전체를 완전히 이해하기는 어렵다.
- PostgreSQL과 운영체제 같은 기반 시스템도 전체 구현을 아는 단일 개발자는 존재하지 않는다.
- 뛰어난 개발자는 파일을 암기하기보다 문제를 해결할 코드의 위치와 구조를 직관적으로 찾는다.
- 좋은 코드베이스는 모두가 모든 것을 아는 곳이 아니라 필요한 위치를 빠르게 찾는 곳이다.
- 작은 팀과 큰 팀은 코드 이해에 요구되는 깊이와 작업 방식이 서로 다르다.
- 대규모 시스템에서는 부분적 이해가 부족함이 아니라 현실적인 최선이다.
- 프로그램의 이론은 문서와 코드에 완전히 기록되지 않는 역사적 직관과 실패 경험을 포함한다.
- 에이전트의 새 스레드는 매번 코드베이스를 처음 보는 유능한 신규 개발자처럼 시작한다.
- 사용자가 있는 시스템에는 새 팀이 재현하기 어려운 기묘한 예외와 오래된 패치가 쌓인다.
- 성공적인 재작성은 기존 시스템을 작은 조각으로 나누고 한 부분씩 교체하는 방식으로 진행된다.
- 원인을 조사하지 않고 Rust 같은 새 언어로 옮기는 일은 성능 문제를 해결하지 못할 수 있다.
- 버려진 코드베이스도 한 실행 흐름을 끝까지 추적한 뒤 주변 영역으로 확장하면 다시 이해할 수 있다.
- AI는 과거 개발자의 머릿속을 복원하지 못해도 저장소에 남은 코드와 테스트를 질문 가능한 지식으로 바꾼다.
- 유능한 개발자도 특정 GraphQL 생성 명령처럼 자신의 시스템에 있는 작은 절차를 모를 수 있다.
- TypeScript와 자동화 도구는 반복 확인을 대신해 더 중요한 설계와 사용자 문제에 뇌를 쓰게 한다.
- 완전한 정신 모델은 속도, 보안, 법적 준수, 플랫폼 지원과 교환되는 가치 중 하나다.
- 순수 엔지니어링은 기술적 완벽성을, 불순 엔지니어링은 실제 문제를 기한 안에 해결하는 일을 중시한다.
- 팀과 사용자의 문제를 이해하고 협력하는 능력도 코드 내부 지식만큼 중요한 엔지니어링 역량이다.
- AI가 코드 양을 폭발시키면 개발자는 불완전한 정보로 데이터 흐름과 실패 조건을 추적하는 역할을 맡는다.
- 코드의 모든 세부를 모르는 상태에서도 올바른 범위를 판단하고 검증하는 능력이 미래의 핵심 역량이다.
