깊은 모듈 대 작은 함수: 오스터하우트와 마틴의 소프트웨어 설계 철학 및 커뮤니티 수용에 대한 비교 분석
본 연구 보고서는 오스터하우트와 마틴이 제시하는 두 가지 상이한 소프트웨어 설계 철학을 심층적으로 비교 분석하는 것을 목표로 한다. 두 철학은 단순히 기법의 차이를 넘어, 문제의 정의 자체에서부터 근본적인 시각차를 드러낸다. 오스터하우트는 시스템적 복잡성을 주된 적으로 간주하며, 이를 인지 부하(cognitive load)와 변경 증폭(change amplification)이라는 구체적인 지표로 측정한다.[1] 반면, 마틴은 코드의 지역적 불명확성을 가장 경계해야 할 대상으로 보며, 이를 가독성(readability)과 이해 용이성(ease of comprehension)으로 평가한다.[2, 3]
Ousterhout 와 Martin 의 소프트웨어 설계 철학의 공통점, 차이점 및 충돌 부분에 대한 여러 의견과 관점들에 대해 gemini 2.5 pro 에게 요청한 연구 결과입니다.
제 1장: 서론#
1.1. 소프트웨어 복잡성이라는 영원한 과제#
소프트웨어 공학의 역사에서 중심을 관통하는 단 하나의 과제를 꼽는다면, 그것은 바로 복잡성(complexity)의 관리다. 시스템이 진화하고 기능이 추가됨에 따라 복잡성은 필연적으로 누적되며, 이는 개발 속도를 저하시키고 버그 발생률을 높이며 유지보수 비용을 기하급수적으로 증가시키는 주된 원인이 된다. 이 본질적인 문제에 대응하기 위해 수많은 방법론과 패러다임이 등장하고 사라졌지만, 복잡성과의 싸움은 오늘날에도 소프트웨어 개발의 핵심에 자리 잡고 있다. 이러한 지적 투쟁의 최전선에 있는 두 인물이 바로 스탠퍼드 대학의 존 오스터하우트(John Ousterhout) 교수와 소프트웨어 장인 정신 운동의 대부로 불리는 로버트 C. 마틴(Robert C. Martin, 이하 ‘엉클 밥’)이다.
오스터하우트는 그의 저서 “소프트웨어 설계의 철학(A Philosophy of Software Design, 이하 APoSD)“을 통해 시스템 수준의 복잡성을 근본적으로 줄이는 설계 원칙을 제시한다. 반면, 마틴은 그의 기념비적인 저서 “클린 코드(Clean Code, 이하 CC)“와 관련 저작들을 통해 코드 수준의 가독성과 명확성을 극대화하는 실천적 기법들을 설파한다. 이 두 거장은 소프트웨어를 더 이해하기 쉽고 유지보수하기 좋게 만들어야 한다는 궁극적인 목표를 공유하지만, 그 목표에 도달하는 경로와 철학적 기반은 현저한 차이를 보이며 때로는 정면으로 충돌하기까지 한다.
1.2. 논문 개요#
본 연구 보고서는 오스터하우트와 마틴이 제시하는 두 가지 상이한 소프트웨어 설계 철학을 심층적으로 비교 분석하는 것을 목표로 한다. 두 철학은 단순히 기법의 차이를 넘어, 문제의 정의 자체에서부터 근본적인 시각차를 드러낸다. 오스터하우트는 시스템적 복잡성을 주된 적으로 간주하며, 이를 인지 부하(cognitive load)와 변경 증폭(change amplification)이라는 구체적인 지표로 측정한다.[1] 반면, 마틴은 코드의 지역적 불명확성을 가장 경계해야 할 대상으로 보며, 이를 가독성(readability)과 이해 용이성(ease of comprehension)으로 평가한다.[2, 3]
이처럼 문제 진단이 다르기 때문에, 함수 분해의 적정 수준, 주석의 역할, 설계 방법론 등 소프트웨어 개발의 핵심적인 실천 방안에 대해 서로 상충하는 처방을 내놓게 된다. 본고는 이러한 충돌 지점들을 상세히 조명하고, 두 철학이 실제 개발 현장에서 어떻게 받아들여지고 있는지 레딧(Reddit)과 같은 온라인 커뮤니티의 논쟁을 통해 분석할 것이다. 최종적으로는 이 두 가지 강력한 사상 체계를 현대 소프트웨어 개발자가 어떻게 조화롭게 수용하고 실천할 수 있는지에 대한 종합적인 프레임워크를 제시하고자 한다.
1.3. 보고서 구조#
본 보고서는 다음과 같은 구조로 전개된다. 제 2장에서는 오스터하우트의 철학을 복잡성 관리의 관점에서 심도 있게 분석하고, 그의 핵심 개념인 ‘깊은 모듈’과 ‘전략적 프로그래밍’을 탐구한다. 제 3장에서는 마틴의 철학을 코드 장인 정신의 관점에서 조명하며, ‘작고 집중된 함수’와 ‘보이 스카우트 규칙’의 의미를 살펴본다. 제 4장에서는 두 철학이 정면으로 충돌하는 지점들—특히 함수 분해, 주석의 역할, 설계 방법론—을 상세히 비교 분석한다. 제 5장에서는 온라인 개발자 커뮤니티에서 벌어지는 활발하고 때로는 격렬한 논쟁을 종합하여, 두 철학의 현실적 수용 양상과 그 이면에 담긴 의미를 고찰한다. 마지막으로 제 6장 결론에서는 전체 논의를 종합하고, 이 두 가지 중요한 사상 체계를 실무에서 통합적으로 활용하기 위한 실천적 프레임워크를 제안하며 마무리한다.
제 2장: 복잡성 관리의 철학 (존 오스터하우트, APoSD)#
오스터하우트의 철학은 소프트웨어 개발의 가장 큰 적이 ‘복잡성’이라는 단 하나의 명제에서 출발한다. 그에게 좋은 설계란 복잡성을 최소화하는 기술이며, 이를 위해 개발자는 단기적인 성과에 매몰되지 않는 장기적이고 전략적인 사고방식을 갖추어야 한다.
2.1. 복잡성의 본질#
오스터하우트는 복잡성을 추상적인 개념으로 남겨두지 않고, 그것이 개발 과정에서 드러나는 세 가지 구체적인 증상으로 정의한다.[1]
- 변경 증폭 (Change Amplification): 간단해 보이는 요구사항 변경 하나가 시스템의 여러 곳에 걸쳐 수많은 코드 수정을 유발하는 현상이다. 이는 시스템의 각 부분이 과도하게 얽혀 있음을 시사한다.
- 인지 부하 (Cognitive Load): 개발자가 특정 작업을 완료하기 위해 머릿속에 기억하고 있어야 하는 정보의 총량이다. 인지 부하가 높을수록 개발자는 실수를 저지르기 쉽고, 새로운 기능을 추가하거나 기존 코드를 이해하는 데 더 많은 시간을 소요하게 된다.
- 미지의 불확실성 (Unknown Unknowns): 어떤 변경사항을 적용하기 위해 어느 부분을 수정해야 하는지 명확하지 않은 상태를 의미한다. 이는 시스템의 구조가 불투명하고 문서화가 부족할 때 발생하며, 잠재적인 버그의 온상이 된다.
이 세 가지 증상은 단순히 코드의 ‘나쁜 냄새(code smell)‘를 넘어, 장기적인 개발 생산성을 저해하는 핵심적인 요인으로 지목된다. 따라서 오스터하우트 철학의 모든 원칙은 이 세 가지 지표를 낮추는 방향으로 수렴한다.
2.2. 핵심 명제: 깊은 모듈#
복잡성을 해결하기 위한 오스터하우트의 핵심 처방은 ‘깊은 모듈(Deep Modules)‘이라는 개념으로 요약된다. 깊은 모듈이란, 강력하고 풍부한 기능을 제공하면서도 외부에는 극도로 단순한 인터페이스를 노출하는 모듈을 의미한다. 이상적인 모듈은 ‘기능성 대 인터페이스 복잡성’의 비율을 최대화해야 한다.
이를 이해하기 위해 ‘얕은 모듈(Shallow Modules)‘과 비교할 수 있다. 얕은 모듈은 제공하는 기능에 비해 인터페이스가 복잡한 경우를 말한다. 예를 들어, 수많은 설정 옵션을 가진 함수나 자잘한 헬퍼 함수들로만 구성된 클래스는 얕은 모듈에 해당한다. 이러한 모듈은 그 자체로 새로운 인지 부하를 유발하며, 시스템 전체의 복잡성을 줄이는 데 기여하지 못하고 오히려 복잡성을 사용자에게 전가시킨다.
깊은 모듈을 만드는 가장 중요한 기법은 정보 은닉(Information Hiding) 이다. 이는 모듈의 내부 구현 방식이나 설계 결정을 인터페이스 뒤로 완전히 숨겨, 모듈 사용자가 알 필요가 없는 정보에 노출되지 않도록 하는 원칙이다. 잘 설계된 정보 은닉은 모듈의 인터페이스를 단순화할 뿐만 아니라, 향후 내부 구현을 변경하더라도 모듈 사용자에게 미치는 영향을 최소화하여 시스템의 유연성을 높인다.
2.3. 경제적 당위성: 전략적 프로그래밍 대 전술적 프로그래밍#
오스터하우트는 프로그래밍에 임하는 두 가지 근본적으로 다른 사고방식을 제시하며, 좋은 설계를 경제적 활동의 관점에서 조명한다.
- 전술적 프로그래밍 (Tactical Programming): 당장의 목표는 가능한 한 빨리 기능을 동작하게 만드는 것이다. 이 접근 방식은 단기적으로는 빠를 수 있지만, 그 과정에서 기술 부채(technical debt)를 지속적으로 축적하게 된다.
- 전략적 프로그래밍 (Strategic Programming): 일차적인 목표는 동작하는 코드이면서 동시에 훌륭한 설계를 만들어내는 것이다. 이를 위해서는 ‘투자 마인드셋(investment mindset)‘이 필수적이다.
그는 특히 총 개발 시간의 10-20%를 설계 개선, 리팩토링, 문서화 등과 같은 ‘투자’에 지속적으로 사용해야 한다고 구체적으로 권고한다.[1, 4] 이러한 투자는 단기적으로는 개발 속도를 늦추는 것처럼 보이지만, 몇 달 내에 그 효과가 나타나기 시작하여 미래의 개발 속도를 10-20% 향상시킴으로써 투자 비용을 빠르게 회수하고 장기적인 생산성을 극대화한다고 주장한다. 이 관점에서 소프트웨어 설계는 일회성 단계가 아니라, 코드베이스라는 자산의 가치를 장기적으로 관리하고 증대시키는 지속적인 경제 활동으로 재정의된다. “사용자의 고통을 줄이기 위해 스스로 약간의 고통을 감수하라"는 그의 조언은 이러한 철학을 단적으로 보여준다.[5]
2.4. 주요 실천 원칙#
오스터하우트의 철학은 다음과 같은 구체적인 실천 원칙들을 통해 구현된다.
- 일반성 (Generality): 그는 매우 특수한 목적의 모듈보다는 ‘어느 정도 범용적인(somewhat general-purpose)’ 모듈을 설계하는 것이 더 간단하고 견고한 시스템을 만든다고 주장한다. 지나치게 특수화된 모듈은 재사용이 어렵고, 약간의 요구사항 변경에도 큰 수정이 필요할 수 있기 때문이다.
- 오류 처리 (Error Handling): 그는 “오류를 존재하지 않도록 정의하라(define errors out of existence)“는 독창적인 원칙을 제시한다. 이는 API를 설계할 때 흔히 발생하는 예외적인 상황들이 더 이상 예외로 취급되지 않도록 만드는 것이다. 예를 들어, 자바의
substring
메서드는 유효하지 않은 인덱스에 대해 예외를 발생시키지만, 자바스크립트의substring
은 범위를 벗어난 인덱스를 문자열의 시작이나 끝으로 간주하여 처리한다. 후자의 방식은 API 사용자의 예외 처리 부담을 덜어주어 모듈의 인터페이스를 근본적으로 단순화시킨다. - 주석 (Comments): 오스터하우트는 “좋은 코드는 스스로를 문서화한다"는 격언을 “맛있는 신화(delicious myth)“라고 부르며 강력하게 비판한다.[1] 그는 코드가 ‘무엇을(what)’ 하는지는 보여줄 수 있지만, ‘왜(why)’ 그렇게 하는지는 설명할 수 없다고 주장한다. 따라서 주석은 설계의 근거, 인터페이스의 비공식적인 계약, 그리고 코드만으로는 드러나지 않는 고차원적인 의도를 담는 필수적인 도구로 간주된다. 그는 심지어 코드를 작성하기 전에 주석을 먼저 작성하여 추상화와 인터페이스에 집중하는 방식을 권장하기도 한다.[1, 5]
제 3장: 코드 장인 정신의 철학 (로버트 C. 마틴, Clean Code)#
로버트 C. 마틴의 철학은 소프트웨어를 만드는 행위를 고도의 기술과 직업윤리가 요구되는 ‘장인 정신(craftsmanship)‘으로 규정하는 데서 시작한다. 그에게 좋은 코드, 즉 ‘클린 코드’는 단순히 동작하는 코드가 아니라, 팀의 모든 구성원이 쉽게 읽고, 이해하고, 수정할 수 있는 예술 작품과 같다.
3.1. ‘깨끗함’의 본질#
마틴에게 코드 품질을 측정하는 유일하게 유효한 척도는 “코드 리뷰 중 분당 발생하는 WTF(What The F***)의 횟수"이다.[6] 즉, 코드를 읽는 동료 개발자가 얼마나 자주 좌절하고 혼란을 느끼는지가 나쁜 코드의 직접적인 지표라는 것이다. 따라서 ‘깨끗함’이란 개발자의 독창성이나 기교가 아니라, 동료와의 소통을 위한 배려와 명확성에 그 본질이 있다. 깨끗한 코드는 가독성(readability), 변경 용이성(changeability), 확장성(extensibility), 그리고 유지보수성(maintainability)을 모두 포함하는 포괄적인 개념이다.[2, 7]
이러한 철학은 소프트웨어 개발을 개인의 창작 활동이 아닌, 유기적인 팀의 협업 활동으로 바라보는 관점에서 비롯된다. 코드의 주된 독자는 컴파일러가 아니라 미래의 나 자신과 동료 개발자들이기 때문에, 모든 코드는 이들을 위해 작성되어야 한다.
3.2. 핵심 명제: 작고 집중된 함수#
마틴 철학의 가장 근본이 되는 규칙은 “함수는 한 가지 일만 해야 한다. 그 일을 잘해야 한다. 오로지 그 일만 해야 한다(Functions should do one thing. They should do it well. They should do it only)“는 원칙이다.[8, 9, 6]
이 원칙은 매우 극단적인 수준의 세분화를 요구한다. 함수는 가능한 한 작아야 하며, 이상적으로는 5-10줄, 길어도 20줄을 넘지 않아야 한다고 강조된다.[6, 8] 함수가 길어진다는 것은 그 함수가 한 가지 이상의 일을 하고 있다는 신호로 간주되며, 즉시 더 작은 함수들로 분리되어야 한다.
이렇게 분리된 함수들은 ‘단계 내림 규칙(Stepdown Rule)‘에 따라 구성되어야 한다.[8, 7] 이는 코드가 마치 잘 쓰인 신문 기사처럼 위에서 아래로 자연스럽게 읽혀야 한다는 의미다. 상위 수준의 함수는 전체적인 흐름을 보여주는 추상적인 서술문처럼 작성되고, 그 함수의 각 라인은 다음 수준의 추상화를 담당하는 더 작은 헬퍼 함수를 호출하는 형태가 된다. 독자는 이 함수들의 계층을 따라 내려가면서 점진적으로 세부 사항을 파악할 수 있다. 이 방식은 독자가 한 번에 하나의 추상화 수준에만 집중할 수 있도록 하여, 코드의 즉각적인 이해를 돕는다.
3.3. 문화적 당위성: 보이 스카우트 규칙#
마틴의 철학은 개인의 실천을 넘어 팀의 문화로 확장된다. 이를 대표하는 것이 바로 ‘보이 스카우트 규칙’이다: “캠프장은 처음 왔을 때보다 더 깨끗하게 해놓고 떠나라(Leave the campground cleaner than you found it)”.[3, 9]
이 규칙은 개발자가 코드를 수정할 때마다, 원래의 목적이었던 기능 추가나 버그 수정 외에 최소한 한 가지 이상의 작은 개선(예: 변수 이름 변경, 함수 분리)을 함께 수행할 것을 권장한다.[7, 10] 이는 대규모 리팩토링에 대한 부담 없이, 코드베이스의 품질을 점진적이고 지속적으로 향상시키는 강력한 문화적 장치다. 모든 팀원이 이 규칙을 따른다면, 시스템은 시간이 지남에 따라 썩어가는 것이 아니라 오히려 점점 더 깨끗해진다. 이는 코드베이스에 대한 집단적 책임 의식과 주인의식을 고취시키는 핵심적인 원칙이다.
3.4. 주요 실천 원칙#
마틴의 철학은 코드의 모든 측면에 걸쳐 구체적이고 실천적인 지침들을 제공한다.
- 의미 있는 이름 (Meaningful Naming): 변수, 함수, 클래스의 이름은 그 존재 이유, 기능, 사용법을 모두 설명해야 한다.[2, 9, 6] 이름은 발음하기 쉽고, 검색하기 쉬워야 하며, 의도를 명확하게 드러내야 한다. “이름에 주석이 필요하다면, 그 이름은 의도를 드러내지 못한 것이다"라는 그의 말은 이름 짓기의 중요성을 강조한다.[2] 또한, 이름의 길이는 그 이름이 사용되는 범위(scope)에 비례해야 한다.[6, 5]
- 함수 설계 (Function Design): 함수는 가능한 한 적은 수의 인수(argument)를 가져야 하며, 이상적으로는 0개, 1개, 또는 2개여야 한다.[8, 7, 6] 특히 함수의 동작을 제어하는 플래그 인수는 함수가 두 가지 이상의 일을 하고 있다는 명백한 증거이므로 피해야 한다. 또한 함수는 부수 효과(side effect)가 없어야 하며, 명령(상태를 변경)과 조회(정보를 반환)의 역할을 명확히 분리해야 한다(Command-Query Separation).[8, 10]
- 주석 (Comments): 마틴은 주석을 코드만으로 의도를 표현하는 데 ‘실패’한 결과물로 간주한다.[8] 그의 목표는 좋은 이름과 명확한 구조를 통해 코드를 충분히 ‘자기 서술적(self-documenting)‘으로 만들어 대부분의 주석을 불필요한 잡음으로 만드는 것이다.[2, 8, 7] 그는 주석이 시간이 지남에 따라 코드와 동기화되지 않아 오히려 오해를 불러일으키는 लायबिलिटी가 될 수 있다고 경고한다.
- 테스트 주도 개발 (TDD)과 점진적 설계: 마틴에게 TDD는 단순히 테스트 전략이 아니라 핵심적인 설계 실천법이다. “실패하는 단위 테스트를 작성하기 전에는 제품 코드를 작성하지 않는다"는 등의 TDD 3원칙은 설계가 점진적으로 드러나게(emergent design) 만들며, 모든 코드가 기본적으로 테스트 가능하도록 강제하는 훈련법이다.[9]
마틴의 철학은 근본적으로 사회적이고 인지적인 측면에 최적화되어 있다. ‘발음 가능한 이름’과 같은 규칙은 컴파일러가 아닌, 코드에 대해 논의하는 동료 개발자들을 위한 것이다. 보이 스카우트 규칙은 코드베이스에 대한 집단적, 사회적 책임을 강조한다. 작고 집중된 함수와 단계 내림 규칙은 개발자가 시스템 전체에 대한 거대한 정신 모델을 유지하지 않고도 코드의 특정 부분을 즉시 소화할 수 있도록 설계된 인지적 휴리스틱(heuristic)이다. 따라서 클린 코드는 유동적인 소유권을 가진 개발팀이라는 사회적 맥락에서, 코드의 특정 부분을 읽고 수정하는 행위의 마찰을 최소화하기 위해 고안된 실천 체계라고 할 수 있다.
표 1: 핵심 교리 비교 분석#
원칙 / 주제 | 소프트웨어 설계의 철학 (오스터하우트) | 클린 코드 (마틴) |
---|---|---|
주요 목표 | 시스템적 복잡성과 인지 부하 최소화 | 지역적 가독성과 팀 전체의 유지보수성 극대화 |
분해 단위 | ‘깊은 모듈’ (단순한 인터페이스, 복잡한 기능) | ‘작은 함수’ (한 가지 일만 수행, 고도로 집중) |
메서드/함수 크기 | 단순한 시그니처와 높은 응집도를 유지한다면 길어질 수 있음 | 매우 작아야 함 (이상적으로 10줄 미만, 최대 20줄) |
주석의 역할 | 필수적. 의도, 근거, 비공식적 계약을 포착. “좋은 코드는 스스로 문서화한다"는 것은 “맛있는 신화” | ‘실패’의 산물. 코드가 스스로를 표현할 수 있어야 하며, 대부분의 주석은 불필요 |
설계 접근법 | 전략적. 선행 및 지속적 설계에 대한 ‘투자 마인드셋’ 옹호 | 점진적. 테스트 주도 개발(TDD)과 지속적인 리팩토링을 통해 설계가 드러남 |
나쁜 설계의 핵심 지표 | 복잡성 (변경 증폭, 인지 부하, 미지의 불확실성) | 비가독성과 인지적 마찰 (“WTFs/minute”) |
추상화에 대한 관점 | 단순하고 강력한 추상화 뒤에 복잡성을 숨김 (정보 은닉) | 작고 이름이 잘 지어진 여러 추상화를 통해 로직을 노출하여 단일 개념 수준에서 작업 |
제 4장: 거대한 분열: 쟁점별 충돌 분석#
오스터하우트와 마틴의 철학은 동일한 목표를 지향함에도 불구하고, 그 방법론에 있어서는 근본적인 차이를 보이며 여러 지점에서 정면으로 충돌한다. 이 충돌은 단순히 스타일의 차이가 아니라, 무엇이 진정으로 소프트웨어를 이해하기 쉽게 만드는지에 대한 근본적인 시각차에서 비롯된다.
4.1. 분해와 입자도: 깊은 모듈 대 아주 작은 함수#
두 철학의 가장 크고 명백한 충돌 지점은 코드 분해의 적정 수준에 대한 견해차이다. 이는 단순히 함수를 얼마나 길게 쓸 것인가의 문제를 넘어, 시스템의 복잡성을 어떻게 구성하고 관리할 것인가에 대한 핵심적인 논쟁이다.
- 핵심 충돌: 오스터하우트는 마틴과 같은 인물들이 주창하는 ‘작은 함수’에 대한 업계의 집착이 종종 ‘얕은 모듈’의 확산으로 이어진다고 비판한다. 수많은 작은 함수들은 그 자체로 학습하고 관리해야 할 인터페이스의 수를 늘려, 오히려 시스템 전체의 복잡성을 증가시킨다는 것이다.
- 오스터하우트의 비판 - ‘얽힘(Entanglement)’: 그는 ‘얽힘’ 또는 ‘결합된 메서드(conjoined methods)‘라는 개념을 통해 과도한 분해의 문제점을 지적한다. 이는 여러 개의 작은 함수들이 너무 밀접하게 결합되어 있어, 하나의 함수 내부를 이해하기 위해 다른 함수들의 코드를 계속해서 넘나들며 읽어야 하는 현상을 말한다. 개발자가 두세 개의 파일을 계속해서 오가며 코드를 읽어야 하는 상황은 마틴이 목표로 하는 가독성 향상에 정면으로 위배되며, 오히려 인지 부하를 극도로 증가시킨다고 그는 주장한다.
- 마틴의 방어 - ‘한 가지 일’ 규칙: 마틴은 자신의 접근법을 ‘한 가지 일(One Thing)’ 규칙으로 방어한다. 명확한 이름을 부여할 수 있는 독립된 개념은 그 자체로 하나의 함수가 되어야 한다는 것이다. 그는 이러한 분해가 비록 파일 간의 이동을 요구할지라도, 각 함수가 단일 추상화 수준에서 명확한 역할을 수행하므로 개념적 명확성과 가독성을 향상시킨다고 믿는다.
- 직접적인 토론: 이 논쟁은 두 저자가 GitHub에서 직접 벌인 공개 토론에서 더욱 명확하게 드러난다. 이 토론에서 오스터하우트는 마틴의 ‘한 가지 일’ 규칙이 너무 모호하고, 과도한 분해를 막을 수 있는 안전장치가 부족하다고 지적했다. 이에 마틴은 “클린 코드” 초판이 이 부분에 대해 더 많은 지침을 제공할 수 있었음을 일부 인정하면서도, 원칙 자체의 유효성은 견지했다.
이 논쟁의 핵심은 복잡성 비용을 어디에서 지불할 것인가에 대한 선택이다. 오스터하우트는 모듈의 내부에 복잡성을 감추고, 모듈을 사용하는 외부 개발자의 인지 부하를 최소화하고자 한다. 반면 마틴은 각 함수의 내부 구현을 극도로 단순하게 만들고, 복잡성을 여러 함수들 사이의 관계로 분산시켜 관리하고자 한다. 오스터하우트의 ‘얽힘’은 마틴 접근법의 잠재적 비용을, 마틴이 비판하는 ‘여러 일을 하는 함수’는 오스터하우트 접근법이 잘못 적용되었을 때의 비용을 지적하는 셈이다.
4.2. 문서화의 역할: 필수적인 근거 기술 대 표현의 실패#
주석의 가치에 대한 두 사람의 견해는 거의 정반대에 가깝다. 이는 코드가 어디까지 스스로를 설명할 수 있는지에 대한 근본적인 신념의 차이를 반영한다.
- 핵심 충돌: 오스터하우트는 주석이 코드가 표현할 수 없는 중요한 정보를 담는 모듈 인터페이스의 핵심적인 부분이라고 믿는다.[1] 반면 마틴은 주석이 코드를 명확하게 작성하는 데 실패했음을 인정하는 행위라고 본다.[8]
- 오스터하우트의 입장: 주석은 ‘어떻게(how)‘가 아닌 ‘왜(why)‘를 문서화해야 한다. 즉, 특정 설계 결정을 내린 이유, 매개변수에 대한 암묵적인 계약, 그리고 고차원적인 의도를 설명하는 데 사용되어야 한다. 그는 코드를 작성하기 전에 주석을 먼저 작성함으로써 추상화 자체에 집중할 것을 권장한다.[1]
- 마틴의 입장: 주석을 쓰고 싶은 충동이 든다면, 그것은 코드를 더 표현력 있게 리팩토링해야 한다는 신호다. “이름에 주석이 필요하다면, 그 이름은 의도를 드러내지 못한 것이다"라는 그의 말은 이 철학을 압축적으로 보여준다.[2] 또한 주석은 코드 변경 시 함께 업데이트되지 않아 오래되고 오해의 소지가 있는 정보가 될 위험이 크다. 이 지점에 대해 오스터하우트는 코드 리뷰 과정에서 해결해야 할 문제라고 반박한다.[1, 10]
- 커뮤니티의 중론: 온라인 토론에서는 종종 절충안이 제시된다. 이름 짓기와 코드 구조 개선이 많은 주석을 대체할 수 있다는 점에는 동의하지만, 복잡한 비즈니스 로직, 알고리즘의 수학적 근거, 또는 특정 기술적 타협의 배경 설명 등은 주석이 필수적이라는 의견이 지배적이다.
4.3. 설계 방법론: 전략적 투자 대 TDD를 통한 점진적 설계#
소프트웨어 설계를 언제, 어떻게 수행해야 하는지에 대한 접근 방식에서도 두 철학은 뚜렷한 차이를 보인다.
- 핵심 충돌: 오스터하우트는 어느 정도의 선행 설계와 그 설계의 질을 유지하기 위한 지속적인 투자를 포함하는 ‘전략적’ 사고방식을 옹호한다. 반면 마틴은 테스트를 먼저 작성하고 이를 통과시키는 과정을 통해 설계가 상향식(bottom-up)으로 점진적으로 드러나야 한다는 TDD의 강력한 지지자다.[9]
- 오스터하우트의 TDD 비판: APoSD에서 오스터하우트는 TDD에 대해 비판적인 시각을 보인다. 그는 TDD가 단기적인 목표(테스트 통과)에 집중하는 전술적인 접근으로 흐를 수 있으며, 이로 인해 응집력 있는 고차원적 구조 없이 수많은 얕은 모듈만 양산하는 결과를 낳을 수 있다고 우려한다.[4]
- 마틴의 TDD 옹호: 마틴과 애자일 커뮤니티에게 TDD는 깨끗하고 유연하며 유지보수 가능한 설계를 보장하는 핵심적인 메커니즘이다. TDD의 3원칙은 개발자가 테스트 불가능하거나 과도하게 복잡한 코드를 작성하는 것을 원천적으로 방지하는 훈련법으로 여겨진다.[9]
이러한 차이는 설계를 바라보는 관점의 차이에서 기인한다. 오스터하우트는 설계를 먼저 고민하고 그 설계를 구현하는 하향식(top-down) 접근을 선호하는 반면, 마틴은 작은 단위의 검증 가능한 코드 조각들을 쌓아 올리면서 전체적인 설계가 자연스럽게 형성되는 상향식 접근을 신뢰한다.
제 5장: 커뮤니티 담론: 온라인 논쟁의 종합#
오스터하우트와 마틴의 철학은 책 속에만 머무르지 않고, 레딧, 해커뉴스 등 전 세계 개발자들이 모이는 온라인 공간에서 활발하게 논의되고 있다. 이 담론을 분석하면 두 철학이 현장에서 어떻게 해석되고 적용되며, 어떤 비판에 직면하는지를 생생하게 파악할 수 있다.
5.1. 클린 코드에 대한 ‘카고 컬트’ 비판#
마틴의 “클린 코드"는 특히 주니어 개발자들에게 강력한 영향을 미치지만, 그 명확한 규칙들이 오히려 부작용을 낳는다는 비판이 광범위하게 제기된다.[11]
- 교조주의적 적용의 함정: 많은 개발자들은 마틴의 규칙을 맥락에 대한 이해 없이 맹목적으로 따르는 ‘카고 컬트(cargo cult)’ 현상을 지적한다. 특히 경험이 부족한 개발자들이 “함수는 무조건 작아야 한다"는 규칙에 집착하여, 논리적으로 함께 있어야 할 코드를 불필요하게 분리하고 “쓸모없는 추상화"를 남발한다는 것이다. 그 결과, 코드베이스는 수백 개의 미세한 함수들로 파편화되어 전체적인 흐름을 파악하기가 극도로 어려워진다. “클린 코드는 매우 이상하며, 극단적으로 적용하는 것은 현명하지 않다"는 한 레딧 사용자의 의견은 이러한 정서를 잘 요약한다.[12]
- 초심자를 위한 위험성: 일부 비평가들은 마틴의 조언 중 일부가 초심자에게는 “위험할 정도로 잘못되었다"고까지 주장한다.[11] 좋은 조언과 나쁜 조언을 구분할 능력이 없는 초심자들이 모든 규칙을 금과옥조처럼 여기면서 오히려 나쁜 설계 습관을 형성할 수 있다는 우려다.
5.2. APoSD의 실제 적용: 학문적 이상주의인가, 실용적 지혜인가?#
오스터하우트의 APoSD는 “클린 코드"의 대안으로 많은 지지를 받고 있지만, 이 책 역시 비판에서 자유롭지 않다.
- 프로젝트 규모의 한계: 일각에서는 오스터하우트의 원칙들이 그가 경험한 학술적 환경의 비교적 작고 통제된 프로젝트에는 적합할 수 있으나, 여러 시스템이 복잡하게 얽힌 거대하고 분산된 엔터프라이즈 애플리케이션의 현실을 충분히 반영하지 못할 수 있다는 비판이 제기된다.
- 추상성과 실천성의 간극: 일부 개발자들은 이 책이 “거창하고 모호하며”, “지나치게 철학적"이라고 평가한다.[13] 즉, 고차원적인 사고의 틀을 제공하는 데는 훌륭하지만, “클린 코드"처럼 매일의 코딩 작업에 바로 적용할 수 있는 구체적이고 실행 가능한 지침은 부족하다는 것이다.
- 경험 많은 개발자들의 지지: 그럼에도 불구하고, 수많은 숙련된 개발자들은 APoSD를 “클린 코드"의 교조주의에 대한 절실한 해독제로 평가한다.[14, 15, 13] 이들은 APoSD가 단순히 ‘무엇을 할 것인가’가 아닌, ‘왜 그렇게 해야 하는가’에 대한 깊이 있는 통찰과 설계의 트레이드오프를 고민하는 고차원적인 프레임워크를 제공한다고 칭송한다.
5.3. 절충점 찾기: 맥락 의존적 종합#
온라인 담론에서 가장 지배적인 견해는 두 철학이 상호 배타적인 것이 아니라, 서로 다른 맥락에서 적용되어야 할 보완적인 도구라는 것이다.
- 거시적 관점 대 미시적 관점: 가장 널리 받아들여지는 절충안은 오스터하우트의 원칙을 거시적 수준(시스템 아키텍처, 서비스 경계, 모듈 인터페이스 설계)에 적용하고, 마틴의 원칙을 미시적 수준(클래스나 모듈 내부의 구현)에 적용하는 것이다. 즉, 오스터하우트의 원칙에 따라 ‘깊은 모듈’의 경계를 설정한 뒤, 그 모듈의 내부는 마틴의 원칙을 따라 수많은 작고 깨끗한 함수들로 구성할 수 있다.
- 대상과 생애주기: 어떤 접근법을 선택할지는 코드의 사용자(내부 팀원 대 외부 라이브러리 사용자)와 프로젝트의 단계(프로토타이핑 대 성숙한 시스템)에 따라 달라져야 한다는 의견도 많다. 외부 개발자가 사용할 API는 학습 곡선을 낮추기 위해 단순하고 깊은 인터페이스를 제공하는 것이 유리하지만, 내부 팀이 사용하는 코드는 유연성을 위해 더 세분화된 인터페이스를 노출하는 것이 허용될 수 있다.
이러한 온라인상의 논쟁은 소프트웨어 산업이 집단적으로 성숙해가는 과정을 보여주는 중요한 지표다. “클린 코드"가 제공하는 것과 같은 보편적이고 규범적인 규칙(rules) 에 대한 믿음에서 벗어나, APoSD가 강조하는 맥락 의존적인 원칙(principles) 과 트레이드오프(trade-offs) 의 중요성을 인식하는 방향으로 나아가고 있는 것이다. 이는 마치 드레이퍼스 기술 습득 모델에서, 규칙에 의존하는 ‘상급 초심자’ 단계를 지나, 원칙을 이해하고 상황에 맞는 미묘한 판단을 내릴 수 있는 ‘숙련자’ 또는 ‘전문가’ 단계로 나아가는 것과 같다. 이 논쟁 자체가 혼란의 증거가 아니라, 건강하게 성숙해가는 전문 분야의 자화상인 셈이다.[16]
제 6장: 결론#
6.1. 핵심적 긴장의 요약#
존 오스터하우트의 “소프트웨어 설계의 철학"과 로버트 C. 마틴의 “클린 코드"는 현대 소프트웨어 개발에 대한 두 가지 가장 영향력 있는 사상 체계를 대표한다. 본 보고서에서 분석한 바와 같이, 두 철학의 핵심적인 긴장은 소프트웨어의 복잡성을 관리하는 우선순위의 차이에서 비롯된다. 오스터하우트는 ‘깊은 모듈’을 통해 시스템 수준의 복잡성을 최소화하는 데 집중한다. 이는 모듈 인터페이스를 사용하는 개발자의 인지 부하를 줄이는 것을 최우선으로 삼는 접근법이다. 반면 마틴은 ‘작은 함수’를 통해 지역적인 코드의 가독성을 극대화하고자 한다. 이는 특정 구현부를 읽는 개발자의 즉각적인 이해를 돕는 데 최적화된 방식이다. 결국 이 논쟁은 인터페이스의 사용자를 위해 최적화할 것인가, 아니면 구현부의 독자를 위해 최적화할 것인가라는 근본적인 트레이드오프에 대한 것이다.
6.2. 현대 개발자를 위한 통합적 프레임워크#
두 철학을 적대적인 관계로 볼 필요는 없다. 오히려 가장 효과적인 접근법은 두 가지를 서로 다른 추상화 수준에서 적용하는 다층적인 전략을 취하는 것이다.
- 거시적 설계 (오스터하우트의 원칙 적용): 시스템의 주요 컴포넌트, 마이크로서비스, 라이브러리 등의 경계와 공용 API를 설계할 때는 오스터하우트의 원칙을 우선적으로 고려해야 한다. 즉, 강력한 정보 은닉을 통해 ‘깊은 모듈’을 구축하고, 인터페이스를 가능한 한 단순하게 만들어 사용자의 인지 부하를 최소화하는 데 집중해야 한다.
- 미시적 구현 (마틴의 원칙 적용): 일단 모듈의 경계와 인터페이스가 잘 정의되었다면, 그 모듈의 내부를 구현할 때는 마틴의 원칙이 매우 유용하다. 즉, 단일 책임 원칙에 따라 작고, 이름이 명확하며, 한 가지 일만 하는 함수들로 내부 로직을 구성하여 가독성과 유지보수성을 높일 수 있다.
궁극적으로 ‘올바른’ 선택은 항상 맥락에 따라 달라진다. 어떤 저자를 맹목적으로 따르기보다는, 그들이 조명하는 트레이드오프를 깊이 이해하는 것이 중요하다. 팀의 경험 수준, 프로젝트의 예상 수명, 코드의 주된 사용자(내부 팀인가 외부 고객인가), 그리고 해결하려는 문제 영역의 본질적인 복잡성 같은 요소들이 어떤 원칙을 더 강조해야 할지를 결정하는 기준이 되어야 한다.
6.3. 최종 고찰: 논쟁의 가치#
결론적으로, “소프트웨어 설계의 철학"과 “클린 코드” 어느 쪽도 성경처럼 떠받들어서는 안 된다. 이 두 책은 개발자에게 소프트웨어 설계를 분석하고 토론하기 위한 풍부한 정신 모델과 어휘를 제공하는 필수적인 교재로 보아야 한다.
두 철학을 둘러싼 활발하고 지속적인 논쟁은 소프트웨어 커뮤니티의 혼란을 의미하는 것이 아니라, 오래 지속되는 소프트웨어를 구축하는 근본적이고 영원한 과제와 씨름하는 건강하고 성숙한 산업의 증거다. 진정한 가치는 어느 한쪽의 승자를 가리는 데 있는 것이 아니라, 이 두 가지 강력한 철학을 모두 깊이 있게 탐구하는 과정에서 얻게 되는 더 깊은 이해에 있다. 이 논쟁에 참여하고 고민하는 것 자체가 더 나은 소프트웨어 엔지니어가 되는 길이다.
References#
- https://dev.to/jimysheepman/clean-code-book-summary-i-1a69
- https://josealobato.com/bookshelf/
- https://blog.codacy.com/what-is-clean-code
- https://www.reddit.com/r/coding/comments/1jo2efe/john_ousterhout_and_robert_uncle_bob_martin/
- https://www.reddit.com/r/programming/comments/1bjgsfs/my_learnings_from_the_book_a_philosophy_of/
- https://printrado.com/book-summary-clean-code-a-handbook-of-agile-software-craftsmanship-by-robert-c-martin/
- https://www.reddit.com/r/programming/comments/e0zxt8/a_philosophy_of_software_design_john_ousterhout/
- https://gist.github.com/wojteklu/73c6914cc446146b8b533c0988cf8d29
- https://gist.github.com/cedrickchee/55ecfbaac643bf0c24da6874bf4feb08
- https://www.reddit.com/r/programming/comments/1jo2dxr/john_ousterhout_and_robert_uncle_bob_martin/
- https://dev.to/thawkin3/in-defense-of-clean-code-100-pieces-of-timeless-advice-from-uncle-bob-5flk
- https://www.reddit.com/r/programming/comments/1d6gu6k/a_philosophy_of_software_design_a_mustread_for/
- https://github.com/johnousterhout/aposd-vs-clean-code
- https://sobrief.com/books/clean-code
- https://dev.to/markadel/a-philosophy-of-software-design-summary-pk9
- https://masalmon.eu/2023/10/19/reading-notes-philosophy-software-design/
- https://carstenbehrens.com/a-philosophy-of-software-design-summary/
- https://www.pathsensitive.com/2018/10/book-review-philosophy-of-software.html
- https://reedodeneal.medium.com/takeaways-from-john-ousterhouts-a-philosophy-of-software-design-ab9e5bc64c8c
- https://www.reddit.com/r/programming/comments/lb8zrn/an_alternative_to_clean_code_a_philosophy_of/
- https://news.ycombinator.com/item?id=43166362
- https://www.reddit.com/r/programming/comments/1iwlgzq/a_discussion_between_john_ousterhout_and_robert/
- https://web.stanford.edu/~ouster/cgi-bin/aposd.php
- https://www.reddit.com/r/programming/comments/1jo2dxr/john_ousterhout_and_robert_uncle_bob_martin/
- https://www.reddit.com/r/programming/comments/hjasqj/an_alternative_to_clean_code_a_philosophy_of/
- https://www.reddit.com/r/ExperiencedDevs/comments/1g2l3wc/book_club_i_dont_understand_why_philosophy_of/
- https://news.ycombinator.com/item?id=45074248
- https://freshman.tech/philosophy-of-software-design-summary/
- https://news.ycombinator.com/item?id=42686034
- https://www.reddit.com/r/softwarearchitecture/comments/1l01moi/clean_code_vs_philosophy_of_software_design_deep/
- https://github.com/johnousterhout/aposd-vs-clean-code
- https://groups.google.com/g/software-design-book/c/Kb5K3YcjIXw/m/qN8txMeOCAAJ
- https://tryingthings.wordpress.com/2025/02/25/aposd-vs-clean-code-a-debate/
- https://www.pathsensitive.com/2022/09/bet-you-cant-solve-these-9-dependency.html
- https://marcobacis.com/blog/philosophy-of-software-design/
- https://www.reddit.com/r/programming/comments/hjasqj/an_alternative_to_clean_code_a_philosophy_of/
- https://community.webshinetech.com/t/comparing-software-design-philosophies-ousterhouts-vs-martins-approaches/1391
- https://news.ycombinator.com/item?id=43289023
- https://www.youtube.com/watch?v=3Vlk6hCWBw0
- https://news.ycombinator.com/item?id=27276706
- https://ianhopkinson.org.uk/author/ianhopkinson/page/6/
- https://deva-data.co.uk/2024/02/book-review-a-philosophy-of-software-design-by-john-ousterhout/
- https://hacker-recommended-books.vercel.app/category/0/all-time/page/1/3
- https://community.webshinetech.com/t/should-i-choose-simple-interfaces-or-small-functions-clean-code-vs-deep-modules-debate/3191
- https://groups.google.com/g/software-design-book/c/Kb5K3YcjIXw/m/qN8txMeOCAAJ
- https://www.youtube.com/watch?v=1bg1w2gBha8
- https://www.reddit.com/r/programming/comments/1eo2lo5/uncle_bob_martin_i_am_in_the_midst_of_writing_the/
- https://www.reddit.com/r/ExperiencedDevs/comments/zuxq0k/how_do_you_improve_your_designer_skills_as_the/
- https://news.ycombinator.com/item?id=41081237
- https://news.ycombinator.com/item?id=45074248