왜 과잉 설계는 실제로 요구 사항 문제인가
왜 과잉 설계는 실제로 요구 사항 문제인가
과잉 설계는 증상이지 미덕이 아니다
핵심: 과잉 설계는 팀이 잘못된 문제를 해결하려 할 때 발생하는데, 이는 보통 요구 사항이 불분명하거나 정렬되지 않았기 때문이며, 완벽을 지나치게 추구해서가 아니다.
var0xyz가 쓴 원본 에세이는 흔히 쓰이는 "완벽을 추구하지 말라"는 교훈을 반박한다. 완벽 자체가 적이 아니라 모호하거나 불완전한 요구 사항이 적이라는 것을 보여준다. 모든 제약 조건이 명시적으로 나열될 때, 해결 공간은 종종 그 상황에 맞는 하나의 완벽한 답으로 수축한다.
완벽한 해결책은 엄격한 제약에서 나온다
핵심: 모든 관련 제약을 열거하면 보통 하나의 설계만이 이를 만족시키며, 그 설계가 완벽한 적합이 된다.
- 예시: 새로운 서버리스 Python 웹 앱을 위한 스택 선택. 팀이 Python을 사용하고, AWS Lambda에 배포하며, 빠른 반복이 필요하다는 것을 안다면, 그 제약을 만족하는 조합이 “완벽한” 해결책이다. 다른 제약(예: 저지연 C++ 서비스)이 있다면 전혀 다른, 동일하게 완벽한 해결책이 도출된다.
에세이는 완벽이 보편적으로 최적이라는 뜻이 아니라 잘 정의된 특정 문제에 최적이라는 뜻임을 강조한다.
시스템은 제품이며, 순수 기술 산물이 아니다
핵심: 라이브러리, API, 내부 도구를 제품으로 대우하면 엔지니어가 실제 사용자 요구를 드러내게 되고, 이는 요구 사항을 명확히 하며 불필요한 복잡성을 방지한다.
시스템을 독립적인 기술 과제로만 볼 경우, 팀은 종종 우아해 보이지만 구체적인 사용자 필요를 충족시키지 못하는 레이어(마이크로서비스, 맞춤 프로토콜)를 추가한다. 누가 시스템을 사용할 것이며 무엇을 진정으로 필요로 하는지를 묻는다면 설계 공간은 크게 좁혀진다.
과잉 설계된 코드를 식별하는 방법
핵심: 과잉 설계의 특징은 설계 결정의 이유와 실제 해결되는 문제 사이의 불일치이다.
에세이는 구체적인 시나리오를 제시한다: 세 명의 엔지니어가 다섯 개의 마이크로서비스를 유지보수하는데, 이 서비스들은 외래키 대신 느슨한 문자열 ID로 데이터를 공유한다. 비용(데이터 불일치, 운영 오버헤드)은 독립 배포라는 사소한 이점보다 크다. 팀이 이 아키텍처를 선택한 이유를 묻는다면 만족스럽지 않은 답이 나오고, 이는 요구 사항이 맞지 않음을 드러낸다.
근본 원인: 잘못된 요구 사항 수집
핵심: 과잉 설계는 본질적으로 올바른 요구 사항을 수집하지 못한 결과이며, 요구 사항이 정확해지면 “완벽한” 해결책이 명확해진다.
저자는 문제를 제품 엔지니어링으로 재구성한다: 코드를 작성하기 전에 모든 제약(성능, 팀 역량, 마감일, 운영 비용)을 수집한다. 제약이 명시적이면, 이를 모두 만족하는 설계가 유일한 실현 가능한 옵션이 되어 불필요한 레이어를 추가하려는 유혹을 없앤다.
커뮤니티 시각
과잉 설계가 잘못된 문제를 해결한다는 의견에 동의
"‘과잉 설계는 잘못된 문제를 해결한다’고 말하고 싶지는 않아요. 아이디어 자체는 맞을 수 있지만, 사람들은 존재하지 않는 제약에 최적화하고 있거든요…" – qsort
이 댓글은 원래 주장을 다듬어, 팀이 존재하지 않는 제약을 쫓아가면서 핵심 문제는 타당하지만 과잉 설계된 해결책을 만들게 된다고 지적한다.
제품‑마인드셋 논쟁
"제품 마인드셋은 독성이다… 최고의 소프트웨어는 ‘도구’ 카테고리에 가깝고 ‘제품’ 카테고리에는 덜 가깝다." – MatrixMan
반대 의견은 소프트웨어를 제품으로 바라보면 이익 중심 동기가 사용자 중심 목표와 충돌할 수 있다고 주장한다. 이는 실제 사용자 요구를 반영하지 않는, 비즈니스 지표에만 초점을 맞춘 요구 사항 수집의 위험을 강조한다.
과잉 설계 vs. 과잉 복잡화 정의
"과잉 복잡화는 기능을 너무 많이 추가하는 것이고, 과잉 설계는 요구 사항을 도움이 되지 않게 초과하는 것이다." – titzer
이 구분은 기술적으로 복잡하지만 요구 사항을 충족하는 솔루션과, 가치에 비해 노력을 낭비하는 과잉 설계를 구분한다.
“완벽” vs. “충분히 좋은” 트레이드‑오프
"Worse is better… 모멘텀이 100 % 완벽보다 종종 더 중요하다." – shevy-java
일부 댓글러는 100 % 완벽을 추구하면 전달 속도가 저하될 수 있다고 주장하며 실용적인 ‘충분히 좋은’ 접근을 제안한다. 원본 에세이 역시 제약이 빠른 출시라면, 그 제약을 만족하는 가장 간단한 것이 완벽한 해결책이라고 강조한다.
과잉 설계를 피하기 위한 실용 체크리스트
핵심: 요구 사항이 설계를 주도하도록 아래 구체적인 단계를 활용하라.
- 모든 제약을 나열 – 성능 목표, 팀 역량, 배포 모델, 마감일, 예산, 규정 준수 등.
- 이해관계자와 제약 검증 – 각 항목이 실제 사용자 혹은 비즈니스 요구를 반영하는지 확인.
- 각 아키텍처 결정에 “왜?” 묻기 – 답이 나열된 제약과 연결되지 않으면 재검토.
- 조기에 프로토타입 – 제약을 만족하는 가장 작은 시스템을 구축하고, 제약이 바뀔 때만 반복.
- 트레이드‑오프 측정 – 추가 복잡성(운영 오버헤드, 지연, 유지보수)의 비용을 제공되는 가치와 정량화.
결론
핵심: 완벽이 좋은 소프트웨어의 적이 아니라, 모호하거나 잘못된 요구 사항이 적이다. 제약을 명시하고 모든 시스템을 실제 사용자가 있는 제품으로 대하면 엔지니어는 해당 문제에 대한 완벽한 해결책에 수렴하고 과잉 설계의 숨은 비용을 피할 수 있다.
저자는 논점을 영상으로도 제공한다: Perfection is not over‑engineering.