Step 05. 자연 상태 — Big Ball of Mud

만화로 보는 요약 — 먼저 읽어보세요
진흙공은 마감 아래 쌓인 합리적 국소 변경의 결과이며, 동작을 지키면서 변경 속도가 다른 부분을 조금씩 분리해야 한다.
면접 실전 질문: ① 진흙공은 왜 자주 이기는가? ② 복잡성은 왜 자연스럽게 증가하는가? ③ 전단층은 어떤 문제를 푸는가?
이 장의 질문: 왜 방치된 소프트웨어는 반드시 진흙 덩어리가 되는가? 그리고 더 불편한 질문 — 왜 진흙공은 그렇게 자주 이기는가?
1. 사실상의 표준 아키텍처
Part 2는 역사다. 그런데 역사를 레이어드부터 시작하면 거짓말이 된다 — 마치 인류가 어느 날 “이제 계층을 나누자”고 합의하고 출발한 것처럼 읽히기 때문이다. 실제 출발점은 구조가 있는 곳이 아니라 없는 곳이다.
1997년, Brian Foote와 Joseph Yoder는 패턴 학회(PLoP)에 「Big Ball of Mud」라는 논문을 낸다. 첫 문단의 정의가 유명하다:
“빅볼 오브 머드란 아무렇게나 구조화된, 제멋대로 뻗어나간, 허술한, 덕트테이프와 철사로 이어붙인 스파게티 코드 정글이다.”
그리고 곧바로 도발이 이어진다. 이것이야말로 **“사실상의 표준 소프트웨어 아키텍처(the de facto standard software architecture)“**라는 것이다. 학회에서는 우아한 스타일들이 발표되지만, 현장에서 실제로 굴러가는 시스템의 지배적 구조는 진흙공이다. 논문의 진짜 질문은 여기서 나온다: “우리가 설교하는 것과 실천하는 것의 간극은 왜 이렇게 큰가?”
한 가지를 분명히 하자. 이 글은 “이렇게 하지 마라”는 훈계문이 아니라 패턴 논문이다. 패턴이란 “반복되는 힘(forces)들이 빚어내는 반복되는 해법”이다. 즉 Foote와 Yoder는 진흙공을 비웃으려고 쓴 게 아니라, 왜 이 형태가 반복해서 나타나는지를 힘의 역학으로 설명하려고 썼다. 이 관점의 전환 — 진흙공을 무능의 증거가 아니라 힘의 산물로 보는 것 — 이 이 장의 전부다.
2. 자연 상태의 물리학 — 왜 방치하면 반드시 이렇게 되는가
“우리 팀은 다르다”고 믿고 싶겠지만, 진흙화(化)에는 물리학에 가까운 필연성이 있다. Manny Lehman이 1970년대부터 정식화한 소프트웨어 진화 법칙이 그 골격이다. 두 개만 기억하면 된다.
- 제1법칙 (지속적 변경): 실사용되는 시스템은 계속 변경되거나, 아니면 점점 쓸모없어진다. — 변경은 선택이 아니라 생존 조건이다.
- 제2법칙 (복잡성 증가): 변경되는 시스템의 복잡성은, 그것을 줄이는 작업을 따로 하지 않는 한 증가한다. — 구조는 기본값이 아니라 비용을 치러야 유지되는 상태다.
둘을 합치면: 성공한 소프트웨어는 반드시 변하고(1법칙), 변할 때마다 엔트로피가 쌓인다(2법칙). 여기에 Foote와 Yoder가 열거한 현장의 힘들이 가세한다 — 마감(이번 주까지), 비용(구조에 쓸 예산은 없다), 경험 부족(도메인을 아직 모른다 — Step 02의 Cunningham을 기억하라, 첫 코드는 언제나 불완전한 이해로 쓰인다), 가시성(구조는 데모에 안 보인다), 이직과 교체(설계를 아는 사람이 떠난다), 변화 그 자체(어제의 옳은 구조가 오늘의 어긋난 구조가 된다).
주목할 것: 이 힘들 중 무능이나 악의는 하나도 없다. 개별 변경 하나하나는 그 시점에 국소적으로 합리적이다. 지금 여기만 고치는 것이 이번 티켓에는 항상 최선이다. 진흙공은 어리석은 결정의 산물이 아니라 합리적인 국소 결정들의 합이다 — 그래서 그토록 보편적이다.
3. 진흙공은 왜 이기는가
여기서 논문의 가장 불편한 통찰이 나온다. 진흙공은 그냥 “생기는” 게 아니라, 종종 경쟁에서 이긴다.
- 싸다. 구조 설계에 쓸 시간을 전부 기능에 쓴다.
- 빠르다. 시장에, 데모에, 마감에 먼저 도달한다.
- 적응한다. 지켜야 할 경계가 없으므로 어떤 요구사항 변화에도 “일단 어딘가에 붙이면” 된다.
- 그리고 결정적으로 — 동작한다. 동작하는 것을 이길 수 있는 것은 동작하는 것뿐이다.
Foote와 Yoder는 이 역학을 하위 패턴들로 세분한다. 일회용 코드(Throwaway Code): 버릴 생각으로 대충 짠 프로토타입이 — 동작한다는 바로 그 이유로 — 살아남아 시스템의 심장이 된다. 점진적 성장(Piecemeal Growth): 전면 설계 없이 필요할 때마다 조금씩 자란다. 이것들은 조롱이 아니다. 논문은 오히려 인정한다 — 불확실성이 높고 자원이 부족한 국면에서는 이 전략들이 실제로 옳다.
그래서 이 책의 프레임이 정확해진다. Part 1에서 배운 아키텍처의 도구들은 “진흙공을 만들지 않는 법”이 아니라, 진흙의 이자율이 감당할 수 없어지는 시점에 대한 대비다. Step 02의 언어로: 진흙공은 이자율을 계산하지 않은 전액 차입 경영이다. 작을 때는 이자가 안 보인다. 시스템과 팀이 커지는 순간 — 모든 변경이 모든 곳을 건드리고, 아무도 전체를 이해하지 못하게 되는 순간 — 복리가 시작된다.
4. 논문이 남긴 진짜 무기 — 전단층(Shearing Layers)
「Big Ball of Mud」에서 가장 저평가된 부분은 진단이 아니라 처방 쪽에 있다. Foote와 Yoder는 Stewart Brand의 『How Buildings Learn』(1994)에서 전단층(shearing layers) 개념을 수입한다. (Brand는 건축가가 아니라 작가다 — 건축가 Frank Duffy의 층 개념을 여섯 개 층으로 확장해 대중화한 것이 이 책이다.)
Brand의 관찰: 건물은 하나의 속도로 늙지 않는다. 부지(site)는 영원하고, 구조(structure)는 수십수백 년, 외피(skin)는 20년, 설비(services)는 715년, 공간 배치는 3년, 가구(stuff)는 매일 바뀐다. 좋은 건물이란 바뀌는 속도가 다른 층들이 서로를 붙들지 않도록 — 벽지를 바꾸는 데 벽을 헐지 않도록 — 지어진 건물이다. 층들이 서로 미끄러질(shear) 수 있어야 한다.
이것을 소프트웨어로 번역하면: 변경 속도가 다른 것들을 서로 묶지 마라. 변경 속도가 같은 것들끼리 묶어라. 어디서 들어본 문장이다 — Parnas의 “바뀔 법한 결정을 숨겨라”(Step 02), 그리고 “함께 바뀌는 것은 가깝게”(응집)의 재발견이다. 도메인 규칙(수십 년), 업무 절차(년 단위), UI(월 단위), 설정(일 단위)이 한 덩어리로 굳어 있는 것 — 그것이 진흙공의 정확한 병리다. 그리고 다음 장부터 만날 모든 아키텍처 스타일은, 이 전단층을 어디에 설정했는가로 읽을 수 있다.
처방이 셋 더 있다. 양탄자 밑으로(Sweeping It Under the Rug): 당장 정리하지 못할 진흙은 깨끗한 인터페이스 뒤로 격리하라 — 훗날 안티커럽션 레이어의 원형이다. 동작 유지(Keep It Working): 고치는 동안에도 시스템은 계속 살아 있어야 한다 — 훗날 스트랭글러 이행 전략의 씨앗이다. 재건(Reconstruction): 전면 재작성은 존재하는 선택지지만 최후의 것이다 — 버리는 순간 코드에 축적된 (문서화된 적 없는) 도메인 지식도 함께 버려지기 때문이다.
5. 반대편의 묘지 — 사라진 시도들
진흙공의 반대편에도 실패의 묘지가 있다. 구조가 없어서가 아니라 구조가 과잉이어서, 혹은 잘못된 곳에 있어서 죽은 것들이다. 세 개의 비석만 읽자.
CORBA (1991~). 이기종 분산 객체의 표준을 꿈꿨다. 언어 중립 인터페이스 정의, 벤더 간 상호운용 — 야심은 완벽했다. 죽은 이유: 사양의 무게. 명세는 수천 페이지로 불었고, 벤더 구현은 서로 안 맞았고, 개발자는 원격 호출을 로컬 호출처럼 보이게 만든 분산 투명성의 거짓말 — 지연과 부분 실패라는, 뒤에서 다룰 분산의 근본 제약을 감춘 — 에 데었다. 2000년대 웹의 단순한 HTTP가 그 자리를 차지했다.
EJB 엔티티 빈 (1998~). 엔터프라이즈 컴포넌트의 표준을 꿈꿨다. 트랜잭션·보안·영속성을 컨테이너가 다 해주는 무거운 컴포넌트 모델. 죽은 이유: 배보다 큰 배꼽. 여러 인터페이스와 클래스, 그리고 XML 배포 서술자를 작성해야 빈 하나가 돌아갔고, 테스트는 컨테이너 없이 불가능했다(테스트가능성의 결핍 — 앞 장의 언어다). Rod Johnson의 『J2EE Development without EJB』(2004)가 사망 선고문이었고, 그 대안 — POJO와 가벼운 컨테이너 — 이 지금의 Spring이다. 지금 스프링으로 개발하고 있다면, 이 무덤 위에서 일하고 있는 것이다.
무거운 SOA/ESB (2000년대). 서비스 지향은 옳은 직관이었다. 죽은 이유: 중앙 집중. 모든 서비스 간 통신이 하나의 지능형 버스(ESB)를 통과하게 만들자, 버스가 곧 전 시스템이 공유하는 결합점이자 병목이 됐다 — 결합을 없애려던 장치가 최대의 공통 결합(Step 02의 표, 둘째 줄)이 된 것이다. WS-* 사양의 폭발은 CORBA의 재방송이었다. 훗날 마이크로서비스 진영의 “지능은 끝점에, 파이프는 멍청하게(smart endpoints, dumb pipes)“라는 구호는 정확히 이 무덤을 향한 비문이다.
세 죽음의 공통 사인(死因)을 확인하라. 구조의 양이 문제가 아니라, 구조가 힘(변경, 도메인, 팀)과 어긋난 것이 문제다. 진흙공과 과잉 구조는 반대말처럼 보이지만 같은 병의 두 증상이다 — 기제는 다르다(하나는 방치의 엔트로피, 다른 하나는 투기적 과설계). 그러나 병명은 같다: 힘과 형태의 불일치. 이것이 “고통이 만든 진화”가 선형 진보가 아닌 이유이기도 하다: 고통에서 도망친 방향이 다음 고통이 되곤 한다.
6. 흔한 오해 바로잡기
오해 1: “진흙공은 무능한 팀의 산물이다.” 2절의 힘 목록에 무능은 없다. 마감, 비용, 불완전한 이해, 이직 — 전부 유능한 팀에도 작용하는 힘이다. 진흙공을 도덕 문제로 취급하면 처방도 도덕(“더 잘하자”)이 되고, 그 처방은 반드시 실패한다. 힘의 문제에는 구조적 처방이 필요하다.
오해 2: “좋은 팀은 진흙공을 만들지 않는다.” Lehman 제2법칙을 다시 보라 — 복잡성 감소는 따로 비용을 치르는 작업이다. 리팩터링·경계 정비에 예산을 배정하지 않는 한, 어떤 팀의 시스템도 진흙을 향해 미끄러진다. 차이는 “만드느냐 안 만드느냐”가 아니라 “이자를 갚는 주기”다.
오해 3: “진흙공의 반대는 정교한 아키텍처다.” 5절의 묘지가 반례다. 과잉 구조는 진흙의 해독제가 아니라 또 다른 사인이다. 진흙공의 반대는 “많은 구조”가 아니라 힘과 정렬된 구조 — 변경 속도의 결을 따라 놓인 전단층이다.
오해 4: “진흙공은 다 밀고 새로 짜는 게 답이다.” Reconstruction은 논문에도 있는 정당한 최후 수단이지만, 코드에만 축적된 도메인 지식(그 이상한 if문이 막고 있는 실제 사고)이 함께 버려진다는 비용을 치른다. 기본 전략은 동작 유지(Keep It Working) 속의 점진 개선이고, 이 책의 실전 파트에서 스트랭글러 패턴이라는 이름으로 돌아온다.
7. 요약, 그리고 다음 장으로
- Big Ball of Mud(Foote & Yoder, 1997)는 훈계가 아니라 패턴 논문이다: 진흙공은 “사실상의 표준 아키텍처”이며, 반복되는 힘들의 산물이다.
- 진흙화는 필연이다 — 변경은 생존 조건이고(Lehman 1법칙), 복잡성은 따로 줄이지 않는 한 증가한다(2법칙). 개별 변경은 국소적으로 합리적이다.
- 진흙공은 이긴다 — 싸고, 빠르고, 적응하고, 동작한다. 문제는 시스템과 팀이 커질 때 시작되는 복리 이자다.
- 논문의 진짜 무기는 전단층: 변경 속도가 다른 것들을 묶지 마라. Parnas의 재발견이자, 이후 모든 스타일을 읽는 눈이다.
- 반대편 묘지(CORBA, EJB 엔티티 빈, 무거운 ESB)의 교훈: 병은 구조의 부재가 아니라 힘과 형태의 불일치다. 과잉 구조도 같은 병이다.
다음 장 예고: 이제 인류가 진흙에 맞서 세운 최초의 정형화된 구조를 만난다 — 레이어드 아키텍처. 뿌리는 생각보다 깊고(Dijkstra의 THE 시스템, 1968), 미리 말해두면 이 장의 결론과 정확히 이어진다: 레이어드의 성공도 실패도, 전단층을 수평으로 그었다는 한 문장에서 나온다.
원전
| 연도 | 문헌 | 이 장에서의 역할 |
|---|---|---|
| 1980 | Lehman, Programs, Life Cycles, and Laws of Software Evolution (Proc. IEEE; 법칙의 최초 정식화는 1974) | 진화 법칙 — 지속적 변경, 복잡성 증가 |
| 1991 | OMG, CORBA 1.0 | 묘지 1호 — 사양 과잉의 실패 |
| 1994 | Brand, How Buildings Learn | 전단층 개념의 원산지 |
| 1997 | Foote & Yoder, Big Ball of Mud (PLoP; PLoPD4 수록, 2000) | 이 장의 주 텍스트 |
| 1998 | Sun, EJB 1.0 | 묘지 2호 — 무거운 컴포넌트 모델 |
| 2004 | Johnson, J2EE Development without EJB | EJB 사망 선고, POJO·경량 컨테이너(Spring)의 길 |