이 책의 첫 장은 정의로 시작하지 않는다. 마틴이 먼저 하는 일은 두 단어 사이에 사람들이 그어 놓은 선을 지우는 것이다 — 설계(design)와 아키텍처(architecture). 흔히 아키텍처는 저 위 고결한 무언가, 세부와 무관한 큰 그림이고, 설계는 그 아래 실무의 잡일처럼 여겨진다. 마틴은 이 구분이 허구라고 말한다. 집을 지을 때 건축가가 그린 외형과 방 배치가 아키텍처라면, 콘센트 위치와 배관 굵기는 설계다. 그런데 그 콘센트가 어디 붙느냐가 벽 안에 무엇이 지나가는지를 결정하고, 그것이 다시 전체 구조를 좌우한다. 고수준의 형태와 저수준의 세부는 끊긴 두 세계가 아니라, 연속된 하나의 직물을 이룬다. 좋은 세부 없는 좋은 구조는 없고, 그 반대도 없다.
그래서 이 장이 진짜로 던지는 질문은 “아키텍처란 무엇인가”가 아니라 다른 데 있다 — 왜 그렇게 많은 시스템이, 그렇게 많은 인력을 갈아 넣고도 점점 더 느려지다 결국 멈추는가. 첫 장의 나머지는 이 질문에 대한 통렬한 그래프 두 장으로 채워진다.
설계와 아키텍처는 하나의 연속체다
아키텍처를 세부와 분리된 성역으로 떠받드는 태도에는 함정이 있다. 세부를 무시한 큰 그림은 실현되지 않고, 큰 그림을 무시한 세부는 방향을 잃는다. 마틴이 강조하는 것은 아키텍트가 여전히, 그리고 반드시 프로그래머여야 한다는 점이다 — 코드에서 손을 뗀 채 다이어그램만 그리는 사람은 자신이 내린 결정이 저 아래 세부에서 무엇을 강요하는지 볼 수 없다. 고수준의 선 하나가 수천 줄의 저수준 코드를 특정한 모양으로 못 박고, 그 저수준의 제약이 다시 위로 올라와 구조를 흔든다.
이 연속성을 받아들이면 “언제부터가 아키텍처고 어디까지가 설계인가”라는 경계 긋기 자체가 무의미해진다. 중요한 건 층의 이름표가 아니라, 어느 수준의 결정이든 그것이 전체 시스템의 유지 비용에 어떻게 반영되는가다.
판단 기준: 어떤 결정을 “아키텍처냐 설계냐”로 분류하려 애쓰지 말고, “이 결정이 앞으로의 변경 비용을 올리는가 내리는가”로 물어라. 그것이 두 층을 관통하는 유일한 척도다. 함정: 아키텍처를 세부와 무관한 고상한 그림으로 격상시키는 순간, 아키텍트는 코드에서 멀어지고 그가 그린 선은 현실의 저항을 모른 채 공허해진다.
척도는 기능이 아니라 인력이다
그렇다면 좋은 아키텍처인지 아닌지는 무엇으로 잰단 말인가. 마틴의 답은 놀랄 만큼 건조하다 — 소프트웨어 아키텍처의 목표는, 요구된 시스템을 만들고 유지하는 데 필요한 인력을 최소로 유지하는 것이다. 아름다움도, 우아함도, 이론적 순수함도 아니다. 척도는 사람이 드는 비용이다.
이 정의가 왜 중요한지는 그 뒤집힌 명제를 보면 드러난다. 어떤 시스템이 기능을 다 갖추고 지금 잘 돌아간다 해도, 손볼 때마다 점점 더 많은 사람이 붙어야 하고 그 사람들이 점점 더 적은 일을 해낸다면 — 그 아키텍처는 실패하고 있는 것이다. 반대로 코드가 화려하지 않아도 한 사람이 변경을 감당할 수 있고 그 비용이 시간이 지나도 완만하다면, 그 아키텍처는 제 몫을 하는 것이다. 설계의 성패는 “지금 동작하느냐”가 아니라 “앞으로도 값싸게 바꿀 수 있느냐”에서 판가름 난다.
판단 기준: 아키텍처의 건강은 기능 목록이 아니라 “새 기능 하나를 추가하는 데 드는 인력이 릴리스마다 늘고 있는가 줄고 있는가”로 진단한다. 비용 곡선이 우상향이면 이미 병들어 있는 것이다. 함정: 지금 잘 돌아간다는 사실을 건강의 증거로 오해하기 쉽다 — 동작은 최소 자격일 뿐, 유지 비용의 추세를 보지 않으면 붕괴 직전까지 아무 이상도 감지하지 못한다.
폭증하는 비용, 0으로 수렴하는 생산성
마틴은 추상론 대신 실제 회사의 데이터를 꺼낸다. 어느 성공한 제품 팀의 릴리스를 추적한 두 개의 그래프다. 첫째, 릴리스를 거듭할수록 개발자 수는 꾸준히 우상향으로 늘어난다. 회사는 성장했고, 돈을 벌었고, 그래서 더 많은 엔지니어를 계속 투입했다. 여기까지는 건강한 성장 서사처럼 보인다.
둘째 그래프가 서사를 뒤집는다. 같은 기간, 개발자 한 명이 코드 한 줄을 만드는 데 드는 비용은 기하급수로 치솟는다. 초기 릴리스에서 거의 공짜에 가깝던 한 줄이, 후기 릴리스에서는 수십 배로 비싸진다. 인력을 열 배 늘렸는데 산출물은 조금밖에 늘지 않는다. 두 그래프를 겹치면 결론은 잔인하다 — 회사가 투입한 노력의 총량 대비 실제로 나온 기능, 즉 생산성은 릴리스를 거듭하며 0을 향해 수렴한다. 관리자의 눈에는 팀이 점점 더 많은 돈을 쓰면서 점점 더 적은 것을 만들어 내는 것으로 보인다.
이 그래프가 무서운 이유는 그것이 게으름이나 무능의 결과가 아니라는 데 있다. 이 팀은 유능했고 헌신적이었다. 그들을 무릎 꿇린 것은 사람이 아니라 엉망이 된 코드 구조 그 자체였다. 매 릴리스마다 앞선 릴리스의 어질러진 코드 위에 새 기능을 얹어야 했고, 그 어질러짐이 복리로 쌓여 결국 어떤 변경도 시스템 절반을 건드리지 않고는 불가능해졌다. 뒤엉킨 구조 앞에서는 개인의 재능이 무력하다.
판단 기준: 팀의 건강을 사람 수나 코드량이 아니라 “한 줄당 비용의 기울기”로 본다. 인력을 늘렸는데 산출이 그만큼 늘지 않는다면, 문제는 사람의 양이 아니라 코드의 구조다 — 사람을 더 붓는 것은 불을 기름으로 끄는 짓이다. 함정: 생산성이 떨어질 때 “손이 부족하다”고 진단해 채용으로 대응하면, 새 개발자마저 같은 진흙탕에 빠져 비용 곡선의 기울기만 가팔라진다.
”나중에 정리하자”는 오지 않는 나중
그 진흙탕은 어디서 시작되는가. 마틴은 개발자들이 스스로에게 거는 하나의 주문을 지목한다 — “일단 돌아가게 만들고, 나중에 깔끔하게 정리하자.” 마감은 급하고, 지저분한 코드라도 지금 동작하면 기능은 나가니까. 정리는 다음 스프린트로, 그다음 릴리스로 미룬다. 이 거래는 합리적으로 들린다. 급한 가치를 지금 취하고, 덜 급한 청소를 나중으로 미루는 것뿐이니까.
문제는 그 나중이 결코 오지 않는다는 데 있다. 시장의 압력은 첫 릴리스 이후에도 절대 느슨해지지 않는다. 다음 기능이 급하고, 그다음 기능이 또 급하다. 어질러 놓은 코드를 청소할 한가한 순간은 개발자 인생에 오지 않는다. 그래서 “나중에 정리하겠다”는 다짐은 실행되지 않는 약속으로 남고, 미뤄진 무질서는 이자를 붙여 다음 릴리스의 발목을 잡는다. 앞의 그래프에서 본 비용 폭증은 바로 이 갚지 않은 빚이 복리로 불어난 모습이다.
여기엔 더 뼈아픈 사실이 하나 더 있다. 지저분하게라도 빨리 만드는 것이 급할 때는 빠르고 나중에 정리하면 된다는 믿음 — 이것 자체가 신화다. 엉망으로 만드는 것은 깨끗하게 만드는 것보다 언제나 느리다. 단기에서조차 그렇다. 뒤엉킨 코드는 다음 기능을 얹을 때마다 개발자를 붙잡아 세우고, 사소한 변경에도 여기저기 깨진 곳을 수습하게 만든다. 빠르려고 질을 포기했는데 그 대가로 느려지는 것이다. 속도와 질 사이에 거래가 성립한다는 전제 자체가 틀렸다.
판단 기준: “지금은 빠르게, 정리는 나중에”라는 거래를 제안받으면(혹은 스스로에게 제안하면), 그 나중이 실제로 스케줄에 잡혀 있는지 물어라. 잡혀 있지 않다면 그것은 거래가 아니라 갚을 계획 없는 빚이다. 함정: 질을 낮추면 지금 빨라진다는 믿음은 측정된 적 없는 착각이다 — 엉망인 코드는 그것을 만든 그 릴리스 안에서 이미 개발자를 느리게 만든다.
자신의 속도를 과신한 토끼
개발자들은 왜 매번 같은 함정에 빠지는가. 마틴은 이솝의 토끼와 거북이 우화를 꺼낸다. 토끼는 자신의 압도적인 속도를 과신한 나머지 느긋하게 낮잠을 잤고, 묵묵히 걸은 거북이에게 졌다. 개발자의 자기 확신도 꼭 그렇다 — “나는 지금 빠르게 짜고 있다. 필요하면 언제든 돌아와서 정리할 수 있다.” 이 과신이 낮잠이다. 그사이 코드의 무질서는 거북이처럼 착실하게 전진해 결국 결승선에서 개발자를 앞지른다.
과신의 핵심은 깨끗함을 나중에 회복할 수 있다는 착각이다. 실제로는 무질서가 임계점을 넘으면 회복 비용이 처음부터 깨끗하게 짜는 비용을 아득히 초과한다. 낮잠에서 깨어났을 때 거북이는 이미 저만치 가 있고, 토끼의 빠른 다리는 따라잡기에 아무 소용이 없다. 유일하게 경주에서 이기는 길은 낮잠을 자지 않는 것 — 처음부터, 그리고 매 순간 코드를 깨끗하게 유지하며 꾸준히 나아가는 것뿐이다. 뒤늦은 전력 질주로는 복리로 벌어진 격차를 메우지 못한다.
판단 기준: “지금은 대충 가도 나중에 따라잡을 수 있다”는 자신감이 들 때, 그 자신감이 토끼의 낮잠인지 의심하라. 회복 가능성을 믿는 근거가 자신의 실력에 대한 과신뿐이라면 이미 자고 있는 것이다. 함정: 뛰어난 개발자일수록 이 함정에 더 취약하다 — 실력이 좋을수록 “나는 언제든 만회할 수 있다”는 확신이 강해지고, 그 확신이 낮잠을 정당화한다.
좋은 아키텍처는 나중이 아니라 지금 지불한다
두 그래프와 두 우화가 가리키는 결론은 하나로 모인다. 개발 조직이 저지르는 가장 값비싼 실수는 아키텍처를 나중으로 미룰 수 있는 사치품으로 취급하는 것이다. 마틴의 처방은 정반대다 — 좋은 아키텍처는 나중에 여유가 생기면 하는 것이 아니라, 지금 이 순간 진지하게 신경 써야 하는 지금의 일이다.
이 주장에는 흔한 오해에 대한 반박이 깔려 있다. 아키텍처에 공을 들이면 당장의 개발이 느려지고, 그래서 급할 때는 아키텍처를 희생해 속도를 사야 한다는 통념이다. 앞 절이 이미 이 통념을 무너뜨렸다 — 엉망은 언제나 느리다. 아키텍처를 챙기는 것은 속도를 포기하고 사는 보험이 아니라, 단기에도 장기에도 더 빠르게 가는 유일한 길이다. 깨끗한 구조 위에서는 다음 변경이 값싸고, 그 값싼 변경이 쌓여 팀의 속도를 지탱한다. 개발자가 진실을 직시해야 한다 — 질을 낮춰 속도를 얻는다는 거래는 존재하지 않으며, 유일하게 빠른 길은 언제나 잘 만드는 것이다.
이것이 이 책 전체를 여는 전제다. 뒤따르는 모든 장 — 두 가치의 우선순위(2장), 프로그래밍 패러다임, SOLID, 컴포넌트, 그리고 경계선 — 은 결국 이 하나의 목표를 위한 도구다. 시스템을 만들고 유지하는 데 드는 인력을, 시간이 지나도 낮게 유지하는 것. 그 목표를 지금 붙들지 않으면, 앞의 그래프가 어느 팀에게든 예외 없이 찾아온다.
판단 기준: 아키텍처에 쓸 시간을 “여유가 생기면”으로 미루려는 논의가 나오면, 그 미룸이 지금의 속도를 위한 투자가 아니라 미래 비용을 복리로 키우는 부채임을 분명히 하라. 지금 지불하지 않은 아키텍처 비용은 사라지지 않고 이자만 붙는다. 함정: “급하니까 아키텍처는 나중에”라는 논리는 속도와 질이 거래된다는 틀린 전제 위에 서 있다 — 그 전제를 받아들이는 순간 팀은 느려지면서 동시에 무너진다.
요점
- 설계와 아키텍처는 층위가 다를 뿐 끊긴 두 세계가 아니라 하나의 연속체다. 고수준의 형태와 저수준의 세부는 서로를 규정한다.
- 아키텍처의 목표는 아름다움이 아니라, 시스템을 만들고 유지하는 데 드는 인력을 최소로 유지하는 것이다. 척도는 기능이 아니라 비용의 추세다.
- 릴리스를 거듭하며 한 줄당 비용이 폭증하고 생산성이 0으로 수렴하는 것은 무능이 아니라 방치된 코드 구조가 부르는 필연이다.
- “일단 돌게 하고 나중에 정리하자”의 나중은 오지 않는다. 그리고 엉망으로 만드는 것은 깨끗하게 만드는 것보다 단기에도 느리다.
- 좋은 아키텍처는 나중의 사치가 아니라 지금의 일이다. 질을 낮춰 속도를 사는 거래는 존재하지 않는다.
다음장으로 2장