변경 증폭(영어: Change Amplification)은 스탠퍼드대학교 컴퓨터과학과 교수 존 오스터하우트(John Ousterhout)가 2018년 저서 『소프트웨어 설계의 철학』(A Philosophy of Software Design)에서 제시한 용어로, 소프트웨어 시스템에서 겉보기에는 단순해 보이는 하나의 논리적 변경이 실제로는 코드베이스의 여러 지점을 함께 수정해야만 완료되는 현상을 가리킨다. 오스터하우트는 이를 소프트웨어 복잡도가 개발자에게 겉으로 드러나는 세 가지 방식, 즉 복잡도의 세 가지 증상 가운데 하나로 규정했다.
오스터하우트가 제시한 틀에서 소프트웨어 복잡도는 변경 증폭 외에도 인지 부하(cognitive load), 알려지지 않은 미지수(unknown unknowns)라는 두 증상과 함께 나타나며, 이 세 증상은 각각 의존성(dependency)과 모호성(obscurity)이라는 두 가지 근본 원인에서 비롯된다고 설명된다. 그는 세 증상 가운데 변경 증폭을 상대적으로 덜 위험한 유형으로 평가했는데, 어디를 고쳐야 하는지가 분명하기만 하면 수정해야 할 곳이 여러 곳이더라도 결국 작업을 완료할 수 있다는 이유에서였다.
이 개념은 오스터하우트가 스탠퍼드대학교에 개설한 소프트웨어 설계 스튜디오 강의인 CS 190의 강의 내용을 정리하는 과정에서 정식화되었다. 『소프트웨어 설계의 철학』은 2018년 4월 야크냠 출판사(Yaknyam Press)에서 초판이 출간되었으며, 2021년에는 로버트 마틴의 저서 『클린 코드』와의 견해차를 다루는 절 등이 추가된 개정판이 출간되었다.
변경 증폭은 주로 하나의 설계 결정이 한 모듈 안에 갇히지 않고 여러 모듈로 새어 나가는 정보 유출(information leakage)이나, 처리 절차의 시간적 순서에 따라 모듈을 나누는 시간적 분해(temporal decomposition)로 인해 발생한다고 설명된다. 오스터하우트는 이에 대한 대응으로 단순한 인터페이스 뒤에 상당한 기능을 감춘 깊은 모듈(deep module)을 설계하고, 데이비드 파나스(David Parnas)가 1972년에 제안한 정보 은닉(information hiding) 원칙을 따를 것을 권고했다.
변경 증폭은 마틴 파울러가 1999년 저서 『리팩터링』에서 제시한 코드 냄새인 샷건 서저리(shotgun surgery)나, 앤디 헌트와 데이브 토머스가 같은 해에 제안한 반복 금지 원칙(DRY, Don’t Repeat Yourself)과 유사한 문제의식을 공유하는 개념으로 함께 거론되곤 한다. 한편 짧은 메서드를 지향하는 로버트 마틴의 『클린 코드』식 설계 원칙이 변경 증폭과 같은 문제를 줄이는지 오히려 늘리는지를 두고는 두 저자 사이에 공개적인 견해차가 드러난 바 있다.
정의와 이론적 배경
정의
오스터하우트는 『소프트웨어 설계의 철학』 2장에서 복잡도(complexity)를 시스템의 구조와 관련하여 그 시스템을 이해하고 수정하기 어렵게 만드는 모든 요소로 정의하고, 이 복잡도가 개발자에게 실제로 드러나는 방식을 세 가지로 구분했다. 그 첫 번째가 변경 증폭으로, 겉보기에는 단순한 변경이 코드베이스 여러 곳의 수정을 요구하는 상황을 가리킨다. 그는 예시로 사용자 인터페이스의 배경색과 강조색처럼 서로 밝기 차이를 일정하게 유지해야 하는 두 값이 코드 안의 서로 다른 위치에 독립적으로 정의되어 있는 경우를 들었다. 이런 구조에서는 개발자가 배경색만 변경하더라도 강조색을 함께 바꿔야 한다는 사실을 코드만 보고는 알아차리기 어려워, 결과적으로 하나의 논리적 변경이 여러 곳의 수정으로 이어지게 된다.
이론적 연원: 파나스의 정보 은닉 원칙
변경 증폭이라는 용어 자체는 오스터하우트가 새로 만들었지만, 그 바탕이 되는 문제의식은 데이비드 파나스가 1972년 학술지 《Communications of the ACM》에 발표한 논문 “시스템을 모듈로 분해하는 데 사용할 기준에 관하여”(On the Criteria to Be Used in Decomposing Systems into Modules)로 거슬러 올라간다. 파나스는 이 논문에서 KWIC(Key Word in Context) 색인 시스템을 예로 들어, 처리 절차의 흐름에 따라 시스템을 입력·처리·출력 단계로 나누는 전통적인 분해 방식과, 변경 가능성이 높은 설계 결정을 기준으로 모듈을 나누고 그 결정을 각 모듈 안에 감추는 정보 은닉 방식을 비교했다. 그는 절차 흐름에 따라 나뉜 모듈들은 하나의 설계 결정이 여러 모듈에 걸쳐 반복되어 있어 그 결정이 바뀌면 여러 모듈을 동시에 고쳐야 하는 반면, 정보 은닉 방식으로 나뉜 모듈들은 그러한 결정이 하나의 모듈 안에만 존재하므로 수정 범위가 좁아진다고 설명했다. 오스터하우트는 이러한 파나스의 정보 은닉 개념을 계승하여 정보 유출과 시간적 분해라는 용어로 다시 사용했다.
저서 『소프트웨어 설계의 철학』과 스탠퍼드 CS 190
오스터하우트는 툴(Tcl) 스크립팅 언어의 창시자이자 분산 운영체제와 저장 시스템 연구로 알려진 컴퓨터과학자로, 소프트웨어 설계가 가르칠 수 있는 기술인지, 그리고 무엇이 뛰어난 프로그래머와 평범한 프로그래머를 가르는지에 대한 오랜 의문을 품어 왔다고 밝혔다. 그는 이 질문에 답하기 위해 스탠퍼드대학교에 소프트웨어 설계 스튜디오 강의인 CS 190을 개설했고, 이 강의에서 다듬은 설계 원칙들을 정리하여 2018년 4월 178쪽 분량의 『소프트웨어 설계의 철학』 초판을 자비 출판했다. 이 책은 특정 프로그래밍 언어나 프레임워크가 아니라 모듈을 어떻게 나눌 것인가라는 설계 문제 자체를 다루며, 변경 증폭을 포함한 복잡도의 증상과 원인, 그리고 이를 줄이기 위한 설계 원칙들을 제시한다. 2021년에는 일반화된 모듈 설계를 다루는 장을 보강하고 로버트 마틴의 『클린 코드』와의 견해차를 다루는 절을 새로 추가한 개정판이 출간되었으며, 이후 독일어판과 중국어판 번역서도 출간되었다.
복잡도의 세 가지 증상과 두 가지 원인
세 가지 증상
오스터하우트는 복잡도가 개발자에게 드러나는 방식을 변경 증폭, 인지 부하, 알려지지 않은 미지수의 세 가지로 구분했다. 인지 부하는 어떤 작업을 수행하기 위해 개발자가 한꺼번에 머릿속에 담아 두어야 하는 정보의 양을 가리키며, 알려지지 않은 미지수는 무엇을 해야 하는지, 혹은 제시된 해법이 실제로 통할지조차 불분명한 상황을 가리킨다. 오스터하우트는 이 세 증상 가운데 알려지지 않은 미지수가 가장 다루기 어렵다고 평가했는데, 변경 증폭이나 인지 부하는 어떤 정보가 필요한지 알기만 하면 결국 그 정보를 모아 작업을 완료할 수 있는 반면, 알려지지 않은 미지수는 애초에 무엇을 알아야 하는지조차 알 수 없어 시스템의 코드를 폭넓게 읽어 보기 전에는 안전을 장담할 수 없기 때문이라는 것이다.
두 가지 원인
오스터하우트는 이 세 증상이 의존성과 모호성이라는 두 가지 근본 원인에서 비롯된다고 설명했다. 의존성은 한 부분의 코드를 독립적으로 이해하거나 수정할 수 없고 다른 부분과 함께 고려해야만 하는 상태를 뜻하며, 그는 의존성이 변경 증폭과 인지 부하를 함께 유발한다고 보았다. 모호성은 중요한 정보가 코드 안에서 뚜렷하게 드러나지 않는 상태를 뜻하며, 알려지지 않은 미지수와 인지 부하를 유발하는 원인으로 지목되었다. 그는 또한 시스템 전체의 복잡도를 각 부분의 복잡도에 개발자가 그 부분에 들이는 시간을 곱하여 모두 더한 값으로 개념화할 수 있다고 제안했는데, 이는 좀처럼 손대지 않는 부분에 몰려 있는 복잡도보다 자주 수정되는 부분에 있는 복잡도가 시스템 전체의 체감 복잡도에 더 크게 기여한다는 것을 뜻한다.
graph TD
A[의존성] --> B[변경 증폭]
A --> C[인지 부하]
D[모호성] --> C
D --> E[알려지지 않은 미지수]
발생 메커니즘
정보 유출
오스터하우트는 하나의 설계 결정이 여러 모듈에 걸쳐 반영되어 있는 상태를 정보 유출이라고 불렀다. 정보 은닉이 이루어진 모듈에서는 어떤 설계 결정에 변화가 생기더라도 그 결정을 감추고 있는 모듈 하나만 고치면 되지만, 정보가 유출된 상태에서는 같은 결정이 반영된 모든 모듈을 찾아 함께 고쳐야 하므로 변경 증폭이 발생한다. 그는 정보 유출이 인터페이스에 명시적으로 드러나는 경우뿐 아니라, 여러 모듈이 특정 파일 형식이나 통신 규약처럼 문서화되지 않은 가정을 암묵적으로 공유하는 경우에도 나타날 수 있다고 지적했다.
시간적 분해
시간적 분해는 정보 유출이 나타나는 대표적인 방식 가운데 하나로 꼽힌다. 이는 작업이 실제로 수행되는 시간적 순서를 그대로 모듈 구조에 반영하는 방식을 가리키며, 예컨대 읽기 담당 모듈과 쓰기 담당 모듈을 별도로 두었을 때 두 모듈이 동일한 파일 형식에 대한 지식을 각자 중복해서 지니게 되는 경우가 이에 해당한다. 오스터하우트는 모듈을 나눌 때는 작업이 일어나는 순서가 아니라 각 작업을 수행하는 데 필요한 지식이 무엇인지를 기준으로 삼아야 한다고 권고했다.
완화 방안
깊은 모듈과 얕은 모듈
오스터하우트는 모듈이 제공하는 기능에 비해 인터페이스가 복잡한 모듈을 얕은 모듈(shallow module), 반대로 단순한 인터페이스 뒤에 상당한 기능을 감추고 있는 모듈을 깊은 모듈(deep module)이라고 구분했다. 그는 얕은 모듈이 많아질수록 개발자가 익혀야 하는 인터페이스의 총량이 늘어나고, 하나의 논리적 기능이 여러 개의 작은 모듈에 걸쳐 나뉘어 있을수록 그 기능과 관련된 변경이 여러 모듈에 걸쳐 파급될 가능성도 커진다고 설명했다. 그는 이러한 경향을 클래스치증(classitis)이라는 표현으로 지칭하며, 작은 클래스를 지나치게 많이 만드는 관행이 시스템 수준의 복잡도를 키우는 원인이 될 수 있다고 지적했다.
전술적 프로그래밍과 전략적 프로그래밍
오스터하우트는 당장 동작하는 코드를 빠르게 만드는 데 치중하는 태도를 전술적 프로그래밍(tactical programming), 장기적인 시스템 구조를 함께 고려하는 태도를 전략적 프로그래밍(strategic programming)으로 구분했다. 그는 전술적 프로그래밍이 개별 변경 하나하나는 감당할 만해 보이지만, 여러 개발자가 이런 방식을 반복하면 의존성과 모호성이 조금씩 누적되어 결국 변경 증폭을 비롯한 복잡도 증상이 시스템 전반에 퍼지게 된다고 설명했다. 그는 이러한 누적을 되돌리기 어렵다는 점을 근거로, 복잡도를 특정 임계치 이하로만 관리하려는 태도 대신 작은 복잡도라도 그때그때 없애려는 무관용(zero tolerance) 태도가 필요하다고 주장했다.
실제 사례: 자바와 유닉스의 입출력 인터페이스
오스터하우트는 얕은 모듈이 변경 증폭과 유사한 문제를 일으키는 실제 사례로 자바 표준 라이브러리의 입출력(I/O) 클래스들을 들었다. 직렬화된 객체를 파일에서 읽어 들이려면 자바에서는 파일 접근을 담당하는 클래스, 버퍼링을 담당하는 클래스, 객체 직렬화를 담당하는 클래스를 각각 만들어 서로 감싸는 방식으로 조합해야 한다. 그는 이를 파일에 대한 버퍼링된 접근이라는 하나의 공통된 요구가 기본 클래스에 통합되어 있지 않고 여러 클래스에 걸쳐 나뉘어 있기 때문에 벌어지는 일이라고 설명하면서, 버퍼링을 기본 동작으로 제공하는 유닉스의 입출력 인터페이스와 이를 대조했다. 그는 이러한 구조에서는 파일을 다루는 대부분의 코드가 동일한 조합의 클래스들을 반복해서 작성해야 하므로, 인터페이스 수준에서 불필요한 복잡도가 누적된다고 평가했다.
관련 개념과의 비교
샷건 서저리와 이질적 변경
마틴 파울러(Martin Fowler)는 켄트 벡(Kent Beck)과 함께 쓴 1999년 저서 『리팩터링』(Refactoring: Improving the Design of Existing Code)에서 하나의 변경을 위해 여러 클래스나 모듈을 동시에 조금씩 고쳐야 하는 상황을 가리키는 코드 냄새로 샷건 서저리(shotgun surgery)라는 용어를 제시했다. 이 개념은 변경 증폭과 마찬가지로 하나의 논리적 변경이 여러 곳으로 흩어져 있는 상황을 가리키지만, 오스터하우트의 정의보다 앞서 제시되었고 리팩터링이라는 실천적 기법과 함께 소개되었다는 점에서 구별된다. 파울러는 샷건 서저리를 하나의 클래스가 서로 무관한 여러 이유로 수정되어야 하는 상황을 가리키는 이질적 변경(divergent change)과 대비했는데, 전자는 결합도(coupling)가 지나치게 높아서, 후자는 응집도(cohesion)가 지나치게 낮아서 발생하는 문제로 설명된다.
DRY 원칙
앤디 헌트(Andy Hunt)와 데이브 토머스(Dave Thomas)는 1999년 저서 『실용주의 프로그래머』(The Pragmatic Programmer)에서 시스템 안의 모든 지식은 단 하나의 권위 있는 위치에서만 표현되어야 한다는 반복 금지 원칙(DRY, Don’t Repeat Yourself)을 제시했다. 이 원칙이 다루는 지식의 중복은 오스터하우트가 말하는 정보 유출과 상당 부분 겹치지만, DRY 원칙은 주로 코드나 데이터 자체의 중복에 초점을 맞추는 반면 오스터하우트의 정보 유출 개념은 모듈 경계를 넘나드는 설계 결정의 공유에 초점을 맞춘다는 점에서 강조점이 다르다.
논쟁과 비판적 시각
메서드 길이를 둘러싼 논쟁: 『클린 코드』와의 비교
2024년 9월부터 2025년 2월 사이 오스터하우트와 로버트 마틴(Robert C. Martin)은 각자의 저서인 『소프트웨어 설계의 철학』과 『클린 코드』(Clean Code) 사이의 견해차를 놓고 공개 대담을 나누었으며, 그 내용은 오스터하우트의 깃허브 저장소를 통해 공개되었다. 두 사람은 메서드 길이를 둘러싸고 뚜렷한 견해차를 보였다. 마틴은 함수가 최대한 짧아야 하며 두세 줄 정도의 길이가 바람직하다고 주장한 반면, 오스터하우트는 메서드를 지나치게 잘게 나누면 각 메서드의 기능에 비해 인터페이스가 복잡해지는 얕은 모듈이 늘어나고, 서로의 내부 구현을 알아야만 이해할 수 있는 메서드들이 뒤엉키는 얽힘(entanglement) 현상이 나타난다고 반박했다. 오스터하우트는 이런 식으로 지나치게 잘게 나뉜 코드는 정보를 줄이는 것이 아니라 여러 메서드에 걸쳐 흩어 놓을 뿐이어서, 독자가 관련된 여러 메서드를 오가며 다시 하나로 짜맞추어야 하는 부담을 오히려 늘린다고 설명했다. 마틴은 이에 대해, 관련이 있는 코드라도 그 코드가 수행하는 일을 명확히 이름 붙일 수 있고 원래 메서드보다 하는 일이 적다면 별도의 메서드로 추출하는 편이 낫다는 이른바 단일 사물 원칙(One Thing Rule)을 근거로 들며, 세부적으로 나뉜 메서드들이 알고리즘의 각 단계를 더 잘 드러내 준다고 반박했다. 두 사람은 이 논쟁에서 모듈화 자체가 유익하다는 점과 지나친 분해가 가능하다는 점에는 합의했지만, 어느 지점부터를 지나친 분해로 볼 것인지에 대해서는 합의에 이르지 못했다고 밝혔다. 이 대담은 메서드 길이 외에도 주석의 역할과 테스트 주도 개발(TDD)을 둘러싼 견해차도 함께 다루었다.
같이 보기
- 소프트웨어 설계의 철학
- 깊은 모듈과 얕은 모듈
- 정보 은닉
- 샷건 서저리
- 결합도와 응집도
- 인지 부하
- 알려지지 않은 미지수
- DRY 원칙
- 리팩터링
참고 자료
- Ousterhout, John (2018), A Philosophy of Software Design, 1st ed., Palo Alto: Yaknyam Press, ISBN 978-1-7321022-0-0
- Ousterhout, John (2021), A Philosophy of Software Design, 2nd ed., Palo Alto: Yaknyam Press, ISBN 978-1-7321022-1-7
- Parnas, David L. (1972), “On the Criteria to Be Used in Decomposing Systems into Modules”, Communications of the ACM, 15(12), pp. 1053–1058
- Fowler, Martin; Beck, Kent (1999), Refactoring: Improving the Design of Existing Code, Boston: Addison-Wesley
- Hunt, Andrew; Thomas, David (1999), The Pragmatic Programmer: From Journeyman to Master, Boston: Addison-Wesley
- Ousterhout, John; Martin, Robert C. (2025), “A Philosophy of Software Design vs Clean Code”, GitHub, https://github.com/johnousterhout/aposd-vs-clean-code
- Ousterhout, John, “A Philosophy of Software Design” (공식 저서 안내 페이지), Stanford University, https://web.stanford.edu/~ouster/cgi-bin/aposd.php
- Ousterhout, John, “The Nature of Complexity” (CS 190 강의 자료), Stanford University, https://web.stanford.edu/~ouster/cgi-bin/cs190-winter18/lecture.php?topic=complexity