성급한 설계는 설계가 아니다

Premature Design Is Not Design - Pragdave

작성자
발행일
2025년 04월 22일

핵심 요약

  • 1 성급한 설계는 불필요한 복잡성을 초래하며, 이는 코드의 변경 용이성을 저해합니다.
  • 2 설계는 초기에 완벽하게 정의하는 것이 아니라, 실제 필요가 발생했을 때 점진적으로 발전시켜야 합니다.
  • 3 DRY(Don't Repeat Yourself) 원칙은 단순히 코드 중복을 피하는 것이 아닌, '지식의 중복'을 방지하는 데 중점을 둡니다.

도입

도널드 크누스의 '성급한 최적화는 모든 악의 근원'이라는 유명한 격언처럼, 소프트웨어 개발에서 '성급한 설계' 또한 유사하게 해로운 결과를 초래할 수 있습니다. 저자는 과거 자신의 경험을 통해, 완벽을 추구하며 미리 모든 것을 설계하려 했던 시도가 오히려 불필요한 복잡성을 야기하고 개발 과정을 지연시켰음을 고백합니다. 오늘날의 저자는 설계가 코드와 함께 반복적으로 발전하며, 오직 필요할 때만 도입되어야 한다는 신념을 가지고 있습니다. 이 글은 이러한 '필요할 때 설계'하는 접근 방식의 중요성을 구체적인 예시를 통해 설명합니다.

저자는 과거에 Bookshelf에서 책 작업자들 간의 정보 공유를 위한 위키와 유사한 기능을 개발할 때 겪었던 경험을 예시로 듭니다. 초기에는 시스템 관리자, 관리자, 편집자, 저자 등 다양한 사용자 수준에 따른 복잡한 계층적 접근 권한 시스템(Role-Based Access Control)을 미리 설계하려 했습니다. 사용자-역할 매핑 테이블, 리소스 유형 테이블, 재귀적 SQL 쿼리 등을 구상하며 방대한 설계를 시도했으나, 이는 단순한 노트 저장 기능에서 시작된 프로젝트를 과도하게 복잡하게 만들었습니다. 그러나 ‘오늘날의 데이브’는 이러한 성급한 설계를 지양하고, 대신 인메모리 해시를 사용하여 최소한의 기능부터 구현했습니다. 이후 데이터 영속성과 접근 제어가 필요해졌을 때, User 모델에 간단한 can_edit_wiki_page? 메서드를 추가하는 방식으로 점진적으로 기능을 확장했습니다. 놀랍게도, 복잡한 설계 없이도 self.admin? || page.owner == self와 같은 단순한 로직만으로 실제 요구사항을 충족시킬 수 있었음을 깨달았습니다.

또한, 저자는 ‘Don’t Repeat Yourself (DRY)’ 원칙에 대한 오해를 지적합니다. DRY는 단순히 코드의 물리적 중복을 제거하는 것이 아니라, ‘지식의 중복’을 피하는 것에 관한 원칙입니다. 즉, 서로 다른 지식을 나타내는 코드가 우연히 동일한 형태를 띠더라도 이는 DRY 위반이 아니며, 성급하게 하나의 코드로 통합하는 것은 오히려 설계를 복잡하게 만들 수 있습니다. 저자는 커피와 차를 만드는 기계의 예시를 통해 이를 명확히 설명합니다. 초기에는 커피와 차 제조 과정에서 공유되는 단계들을 묶어 하나의 dispense 메서드 내부에 case 문으로 처리하려 했으나, 이는 새로운 음료나 옵션이 추가될 때마다 메서드를 비대화시키고 유지보수를 어렵게 만들었습니다. 대신, 커피 레시피와 차 레시피가 각각 독립적인 ‘지식’임을 인식하고, dispense_coffeedispense_tea와 같이 개별 메서드로 분리하는 것이 훨씬 더 명확하고 확장 가능한 설계임을 보여줍니다. 이는 각 ‘지식’이 한 번만 표현되도록 하여 진정한 DRY 원칙을 따르는 것입니다. 저자는 코드가 변경하기 어려워진다는 ‘발견된 필요’가 있을 때 비로소 설계를 개선해야 한다고 강조하며, 당장 해롭지 않은 코드 중복은 ‘TODO’ 주석으로 남겨두고 나중에 해결할 것을 제안합니다.

결론

결론적으로, 단순성을 유지하는 핵심은 '실제로 필요할 때까지 어떤 작업도 하지 않는 것'입니다. 코드 두 줄이 같다고 해서 즉시 리팩토링해야 한다는 규칙은 없습니다. 좋은 설계는 코드의 변경 용이성이 떨어진다는 '발견된 필요'에서 자연스럽게 비롯됩니다. 때로는 이러한 필요를 미리 예측할 수 있지만, 그렇지 않더라도 개발 과정에서 점진적으로 발견하고 해결해나가는 것이 중요합니다. 설계는 따라야 할 고정된 규칙이 아니라, 코드를 더 쉽게 변경할 수 있도록 돕는 유연한 도구입니다. 이 글은 개발자들이 성급한 디자인 결정보다는 실용적이고 점진적인 접근 방식을 채택하여 보다 견고하고 유지보수하기 쉬운 코드를 작성할 것을 권장합니다.

댓글 0

댓글 작성

0/1000
정중하고 건설적인 댓글을 작성해 주세요.

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!