코드 이해
AI가 더 많은 코드를 쓰는 시대에도 우리가 코드를 이해해야 하는 이유
AI와 함께 FiboCode를 만든 경험이 코드, 아키텍처, 신뢰를 바라보는 방식을 어떻게 바꾸었는지, 그리고 진화하는 소프트웨어를 사람이 계속 이해해야 하는 이유를 살펴봅니다.
나는 사람들이 코드를 이해하도록 돕는 제품을 AI로 만들었다.
그런데 흥미로운 일이 생겼다. 제품이 복잡해질수록 나 자신은 제품을 점점 덜 이해하게 되었다.
FiboCode 개발은 2025년 7월 무렵 시작했다. 당시 Vibe Coding이 확산되었고, 모두가 AI로 코드 작성을 돕고 소프트웨어 개발 비용을 낮추는 이야기를 했다. 자연스럽게 한 가지 생각이 떠올랐다.
AI가 코드 작성을 도울 수 있다면, 코드 이해도 도울 수 있지 않을까?
코드를 쓰는 비용은 계속 낮아지지만 낯선 프로젝트를 이해하는 일은 여전히 어렵다. 여러 해 동안 존재해 복잡한 디렉터리 구조, 모듈 의존성, 역사적인 설계 결정, 각종 규칙을 가진 코드베이스에서는 특히 그렇다. 어디서 시작해야 할지 알아내는 것만으로도 오랜 시간이 걸린다.
FiboCode는 그 단순한 생각에서 시작했다. AI로 코드를 분석해 문서와 관계도를 만들고, 코드와 문서와 다이어그램 사이를 이동할 수 있게 하는 것이다.
그때는 단지 코드 분석 도구였다.
나중에는 코드에 관해 더 쉽게 질문할 수 있도록 간단한 Agent를 추가했다. 코드 읽기 경험을 개선하기 위해 Monaco Editor를 통합했다. 편집기가 생기니 코드 탐색, 심볼 참조, 언어 진단도 필요해 보여 LSP 지원을 추가했다.
읽기를 지원하고 나니 편집은 자연스러운 다음 단계였다.
FiboCode가 코드를 수정할 수 있게 된 뒤에는, 현재 열린 몇 개 파일만 보고 판단하지 않고 Agent가 프로젝트를 진정으로 이해하게 할 방법을 고민했다. 점차 MCP와 Skills를 추가해 AI가 프로젝트의 설계 규칙, 아키텍처 맥락, 역사에도 접근하게 했다.
그 후 많은 개발자가 Claude와 Codex 같은 Agent CLI에 이미 익숙하다는 것을 깨달았다. 또 다른 내장 Agent보다 Agent 작업 결과를 검토하도록 설계된 인터페이스가 더 필요할지도 몰랐다.
그래서 FiboCode에 터미널을 추가하고 Agent CLI 출력에 맞춘 개선을 적용했다. 터미널의 파일 참조, 코드 변경, 실행 단계를 코드, 문서, 관계도와 연결할 수 있게 했다.
이렇게 단순한 코드 분석 모듈은 하나씩 기능을 더하며 점점 복잡한 시스템으로 성장했다.
내가 만든 프로젝트를 잊기 시작했다
AI 보조 프로그래밍은 정말 편리하다.
초기 모델은 지금만큼 뛰어나지 않았지만, 나는 생성된 코드를 여러 번 꼼꼼히 검토했다. 모듈이 어떻게 나뉘고 데이터가 어떻게 흐르며 아키텍처가 왜 그렇게 설계되었는지 살폈다.
개발 중 프로젝트는 여러 번 리팩터링되었다. 큰 변경도 있었지만 당시에는 설계 세부 사항을 알고 있었기에 결국 프로젝트가 망가지지는 않았다.
그러다 모델이 더 강력해지고 코드 생성 속도가 빨라졌으며 코드베이스가 빠르게 커졌다.
불과 한두 주 전에 검토한 코드의 설계 세부 사항도 기억하지 못한다는 사실을 점차 깨달았다.
처음에는 조금 두려웠다.
내 프로젝트였다. 모든 기능이 나에게서 나왔는데도 각 모듈이 왜 그렇게 설계되었고 각 로직이 어떻게 작동하는지 기억할 수 없었다.
시간이 지나면서 어쩌면 그저 받아들여야 하는 일이라고 생각하게 되었다.
더 이상 초창기의 작은 프로젝트가 아니었다. 충분히 복잡한 시스템에서는 누구도 모든 구현 세부 사항을 기억할 수 없다. 중요한 것은 모든 코드 줄을 머릿속에 넣는 일이 아니라 핵심이 어디에 있고 모듈이 어떻게 협력하며 무엇을 안전하게 AI에 맡기고 무엇을 신중히 이해해야 하는지 아는 일일지도 모른다.
나는 선택하는 법을 배워야 했다.
수많은 코드 속에서 핵심 경로를 찾고 시스템의 큰 정신적 그림을 만든 뒤 AI에 더 정확한 요구 사항과 제약을 제공해야 했다.
이런 관점에서 FiboCode는 내가 FiboCode를 만드는 일도 돕고 있었다.
AI로 제품을 개발하고, 제품이 더 유용해지며, 다시 그 제품이 자신을 더 빠르게 이해하고 개선하도록 도왔다. 이 선순환은 정말 짜릿했고 오랫동안 계속 작업한 중요한 이유였다.
하지만 흥분 너머에서 나는 자주 물었다.
이 개발 과정에서 나에게 남은 것은 무엇일까?
더 많은 생각을 AI에 넘겼을 때
오랜 기간에 걸쳐 한 가지 습관이 생겼다.
요구 사항이 생기면 먼저 AI에 넘겼다.
문제가 생기면 먼저 AI에 조사하도록 했다.
해결책을 제안하면 검증했다. 검증이 실패하면 결과를 돌려주고 다시 분석하고 고치게 했다.
때로는 하루 종일 요구 사항을 설명하고 버그의 현재 상태를 알리고 테스트 결과를 되돌려 주는 일을 반복했다.
거의 모든 어려운 지적 작업을 AI가 하고, 내 역할은 요구 사항을 정의하고 결과를 반환하는 것으로 줄어든 듯했다.
그 시기에 나는 강하게 느꼈다.
더 이상 내게 큰 가치가 없는 것 같았다.
그러나 계속하다 보니 그것이 완전히 사실은 아님을 알았다.
AI와 개발하면서 예전에는 공부하려 하지 않았을 기술을 접하고 다양한 구현 방식을 보았다. 구체적 구현을 보기 전에 설계와 아키텍처를 의식적으로 살피기 시작했다.
어떤 작업은 범위가 작아 AI가 바로 끝낼 수 있다고 빠르게 판단했다.
하지만 여러 모듈을 가로지르거나 프로젝트 핵심 구조에 영향을 주는 작업은 그렇게 단순하지 않다는 것을 즉시 알았다. AI는 현재 요구 사항만 보고 역사적 설계의 이유나 간접 영향을 이해하지 못할 수 있었다.
AI가 작성할 수 있어도 내가 거의 완전히 이해해야 하는 코드도 있었다. 그곳에서 문제가 생기면 결과를 통제하기 어렵기 때문이다.
모든 구현 세부 사항을 이해하려고 고집하지는 않게 되었지만 시스템 경계, 의존성, 위험, 변화에는 더 민감해졌다.
인간의 일이 사라진 것이 아니라 단지 변하고 있는지도 모른다.
과거에는 직접 코드를 구현하며 시스템을 이해했다.
앞으로는 반복 구현에 쓰는 힘을 줄이고 아키텍처, 과정, 제약, 검증, 장기적 진화에 더 집중할지도 모른다.
AI가 쓸 수 있다고 해서 신뢰할 수 있는 것은 아니다
미래에 AI가 정말 인간 전문가를 대체해 모든 프로그래밍 작업을 수행할 수 있을지는 모른다.
분명 기술적인 질문이지만 신뢰의 문제이기도 하다고 생각한다.
언젠가 AI가 매우 복잡한 시스템을 독자적으로 생성해도 우리가 아무 조건 없이 신뢰한다는 뜻은 아니다.
시스템이 예상과 다르게 동작할 때 이유를 알 수 있을까?
오류를 찾을 수 있을까?
수정을 검증할 수 있을까?
다른 사람이 인수할 수 있을까?
시스템이 심각한 피해를 일으키면 누가 책임질까?
이 질문들은 모델 정확도를 99%에서 99.9%로 높이는 것만으로 완전히 해결되지 않는다.
위험이 낮고 쉽게 대체할 수 있는 애플리케이션이라면 더 많은 블랙박스를 허용할 수 있다. 기능이 작동하고 개발이 충분히 빠르면 모든 세부 사항을 신경 쓰지 않아도 될 수 있다.
하지만 운영 체제와 데이터베이스 같은 기반 소프트웨어나 금융, 전력처럼 사회에 큰 영향을 주는 시스템에서는 이해하거나 감사하거나 인수할 수 없는 블랙박스를 받아들이기 어렵다.
이런 시스템에는 여전히 유지보수할 사람이 필요하다.
모든 줄을 직접 쓸 필요는 없지만 누군가는 시스템이 대략 어떻게 작동하고 핵심 위험이 어디에 있으며 문제가 생기면 어디서 조사를 시작해야 하는지 알아야 한다.
그래서 AI 프로그래밍이 성장해도 코드 이해는 사라지지 않을 것이라는 믿음이 점점 커진다.
단지 다른 형태가 될 뿐이다.
과거에는 코드를 쓰기 위해 이해해야 했다.
앞으로는 AI가 만든 시스템을 검증하고 유지하고 인수하고 계속 발전시키기 위해 코드를 이해해야 할지도 모른다.
사라지는 입문 단계 작업
코드 이해에는 또 다른 의미가 있다.
AI는 반복 구현과 기초 작업 중심의 일부 입문 직무를 줄이고 있다. 직무 자체가 사라지지 않아도 과거 신입에게 맡기던 많은 일이 AI로 먼저 자동화된다.
이는 신입에게 친절한 상황이 아니다.
엔지니어의 전통적인 성장 경로는 버그 수정, 작은 코드 읽기, 작은 기능 완성 같은 단순한 작업에서 시작해 점차 복잡한 모듈과 시스템 설계에 참여하는 방식이었다.
신입은 중요하지 않아 보이는 이런 작업을 통해 실제 프로젝트에 대한 이해를 조금씩 쌓는다.
하지만 이제 AI가 그 기초 작업을 바로 끝낼 수 있다.
신입을 훈련할 입구가 줄어들면 미래의 시니어 엔지니어는 어디에서 나올까?
이것도 FiboCode를 만든 이유 중 하나다.
나 역시 이 직업에서는 신입이다. 처음 복잡한 레거시 코드베이스를 마주했을 때 자주 완전히 막막했다.
파일과 디렉터리가 너무 많았다. 서비스는 서로 호출하고 타입, 인터페이스, 설정은 흩어져 있었다. 답이 코드 어딘가에 있다는 것은 알았지만 어디서 시작하고 무엇이 중요하며 무엇이 단순한 구현 세부 사항인지 알지 못했다.
진짜 어려움은 특정 코드 한 줄이 아니라 완전한 지도가 없다는 데 있었다.
먼저 전체 프로젝트 구조를 분석하고 핵심 모듈의 위치, 코드 연결 방식, 변경이 영향을 줄 영역을 알려 주는 도구를 늘 원했다.
그러면 신입이 누군가의 단계별 안내에 전적으로 의존하거나 낯선 코드베이스를 계속 더듬을 필요가 없다.
그런 도구가 성장 과정을 대신할 수는 없지만 복잡한 시스템에 들어가는 장벽을 낮출 수 있다.
AI가 옛 성장 경로를 점차 끊는 동안 FiboCode가 새로운 길을 다시 연결하기를 바란다.
모든 기초를 건너뛰는 지름길이 아니라 지도와 내비게이션, 그리고 신입이 시스템의 정신적 모델을 더 빨리 만드는 길에 가깝다.
코드는 현재만 기록한다
개발 과정에서 또 다른 문제를 발견했다.
작업을 AI에 바로 맡기고 저장소를 스스로 탐색하게 하면 때때로 생각이 불완전해진다.
AI는 현재 코드를 볼 수 있지만 모듈이 왜 특정 방식으로 설계되었는지, 무관해 보이는 파일과 간접적으로 연결되어 있는지 모를 수 있다.
코드는 보통 시스템의 현재 모습을 알려 주지만 왜 그렇게 되었는지 설명하기 어렵다.
처음에는 이 모든 정보를 코드 주석에 넣으려 했다.
나중에는 적합하지 않다고 판단했다.
많은 설계 맥락, 역사적 판단, 변경 설명은 코드 파일을 부풀리고 AI에 현재 작업과 무관한 컨텍스트를 줄 수 있다. 주석은 지역 로직 설명에는 좋지만 프로젝트 전체의 진화를 담기는 어렵다.
그래서 일련의 Fibo Skills를 설계했다.
프로젝트 규칙, 설계, 구현 과정, diff 설명을 기록해 각 코드 변경의 더 완전한 흔적을 남긴다.
미래에 AI가 코드를 수정할 때 현재 상태뿐 아니라 과거에 무슨 일이 있었고 왜 특정 설계가 유지되었는지도 이해하기를 바란다.
프로젝트의 진화 역사를 추적할 수 있으면 AI는 프로젝트를 더 완전하게 이해할 수 있다.
이것도 FiboCode가 점차 향한 방향 중 하나가 되었다.
처음에는 사람이 코드를 이해하도록 만들었다. 이후에는 AI가 코드를 더 잘 이해하는 일도 돕기 시작했다.
FiboCode가 지금의 모습으로 성장한 과정
돌아보면 FiboCode는 처음부터 지금 모습으로 설계된 것이 아니다.
단순한 코드 분석 모듈로 시작해 문서와 관계도, Agent, 편집기, 언어 서비스가 뒤따랐다. 점차 코드 편집, 터미널, MCP, Skills도 갖추었다.
Agent CLI에 Cursor 같은 코드 검토 경험을 제공하는 동시에 코드 분석이 만든 문서와 관계 정보를 AI가 실제로 사용할 수 있는 컨텍스트로 바꾸고 싶었다.
단순한 모듈에서 복잡한 시스템으로 진화하는 지속적인 성장은 Fibonacci 수열이 확장되는 방식과 조용히 닮아 있었다.
FiboCode라는 이름과 달팽이 이미지도 여기서 나왔다.
달팽이 껍질에는 황금 나선의 수학적 아름다움이 담겨 있다.
빠르게 움직이지는 않지만 계속 앞으로 성장한다.
FiboCode는 사람들이 다시 모든 코드 줄을 손으로 쓰게 하려는 것도, AI를 배제하려는 것도 아니다.
오히려 반대다. AI가 더 많은 코드를 쓰게 된다는 사실을 받아들이고, 그 전제 위에서 사람들이 자신의 시스템을 계속 이해하고 검증하고 유지하고 인수하도록 돕고자 한다.
모두가 더 빠른 생성을 추구하는 시대에도 가끔은 속도를 늦출 수 있기를 바란다.
코드가 왜 그렇게 작동하고 시스템이 왜 오늘의 모습이 되었는지 이해하기 위해서다.
그리고 처음 우리를 프로그래밍으로 이끌었던 즐거움을 다시 찾기 위해서다.