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)의 길 |