직접 만들지 않는 소프트웨어는 설계할 수 없다
목차
개요
Sean Goedecke의 글 “You can’t design software you don’t work on”은 소프트웨어 설계에서 실제 구현 경험의 중요성을 강조한다. 핵심 주장은 명확하다. 도메인 지식만 있고 기존 코드베이스를 모르는 상태에서 제공되는 설계 조언은 실무에서 거의 쓸모가 없다는 것이다. 대형 시스템에서는 이상적인 설계 원칙보다 일관성 유지와 구체적인 맥락 이해가 훨씬 더 중요하다.
일반적 설계 vs 구체적 설계
소프트웨어 설계는 크게 두 가지로 나눌 수 있다.
일반적 설계(Generic Design)
도메인 지식은 갖추고 있지만 기존 코드베이스에 대한 이해가 부족한 상태에서의 설계를 의미한다. DRY, WET, SOLID 같은 추상적 원칙에 기반한 접근 방식이다. 일반적인 소프트웨어 엔지니어링 원칙을 적용하려는 시도이지만, 실제 시스템의 복잡성을 반영하지 못하는 경우가 많다.
구체적 설계(Concrete Design)
시스템의 난해한 세부사항을 중심으로 이루어지는 설계를 의미한다. 데이터가 실제로 어떻게 흐르는지, 현재 리팩토링이 어디까지 진행되었는지, 어떤 부작용이 있는지 등 구체적인 맥락에 기반한다. 매일 해당 코드베이스에서 작업하는 엔지니어만이 이런 수준의 설계를 수행할 수 있다.
두 설계 방식 비교
| 구분 | 일반적 설계 | 구체적 설계 |
|---|---|---|
| 기반 | 추상적 원칙 | 코드베이스 맥락 |
| 지식 요구 | 도메인 지식 | 코드 세부사항 |
| 적용 범위 | 범용적 | 특정 시스템 한정 |
| 실무 효용 | 제한적 | 높음 |
| 수행 가능자 | 누구나 | 실제 작업 참여자 |
일반적 설계 조언이 실패하는 이유
대규모 코드베이스에서 일반적인 설계 조언이 실패하는 이유는 여러 가지가 있다.
일관성이 원칙보다 중요하다
대형 시스템에서는 이론적으로 더 나은 설계보다 기존 코드와의 일관성이 더 중요하다. 새로운 패턴을 도입하면 코드베이스에 두 가지 스타일이 공존하게 되어 오히려 복잡성이 증가한다.
예측 불가능한 부작용
복잡한 시스템에서는 변경 하나가 예상치 못한 곳에 영향을 미친다. 이런 부작용은 코드베이스를 직접 다루는 사람만이 파악할 수 있다.
중간 상태의 현실
현실의 코드베이스는 여러 설계 방식 사이의 중간 상태에 존재한다. 과거의 설계와 현재의 설계가 혼재되어 있으며, 이 상태에서의 최선의 선택은 이상적인 원칙과 다를 수 있다.
일반적 설계가 유용한 경우
일반적 설계 원칙이 유용한 상황도 분명히 존재한다.
새로운 프로젝트 시작
기존 제약 조건이 없는 완전히 새로운 프로젝트에서는 일반적 원칙이 유용한 출발점이 된다. 레거시 코드와의 일관성을 고려할 필요가 없기 때문이다.
동등한 선택지 사이의 판단
현실적으로 수용 가능한 여러 옵션이 있을 때, 일반적 원칙이 최종 결정의 기준이 될 수 있다. 이 경우 원칙은 타이브레이커(tie-breaker) 역할을 한다.
회사 전체 기술 결정
클라우드 vs 데이터센터, 프로그래밍 언어 선택 등 회사 전체에 영향을 미치는 광범위한 기술 결정에서는 일반적 설계 원칙이 적합하다.
아키텍트 역할의 문제점
저자는 구현에 참여하지 않는 아키텍트 역할의 근본적인 문제를 지적한다.
책임감의 부재
아키텍트는 설계만 하고 구현은 다른 사람에게 넘기기 때문에 “스킨 인 더 게임(skin in the game)”이 없다. 프로젝트가 성공하면 자신의 설계 덕분이라 주장하고, 실패하면 구현이 잘못되었다고 회피할 수 있다.
로컬 미니멈의 함정
실제 구현을 담당하지 않는 설계자는 시스템의 현재 상태를 정확히 파악하지 못한다. 이로 인해 이론적으로는 최적이지만 현실에서는 적용하기 어려운 설계를 제안하게 된다.
설계와 구현의 분리 불가
저자의 핵심 주장은 설계와 구현이 분리될 수 없다는 것이다. 실제 코드베이스에서 매일 작업하는 엔지니어만이 의미 있는 설계 결정을 내릴 수 있다. 설계자가 구현에 참여하지 않으면 책임감 부재 문제가 필연적으로 발생한다.
결론
이 글의 메시지는 소프트웨어 개발에서 자주 간과되는 진실을 상기시켜 준다. 좋은 소프트웨어 설계는 추상적 원칙의 적용이 아니라, 코드베이스에 대한 깊은 이해에서 나온다. 일반적 설계 조언을 일상적인 업무에 적용할 때는 신중해야 하며, 구체적인 맥락을 항상 우선시해야 한다. 설계자가 직접 구현에 참여하는 것이 가장 효과적인 소프트웨어 설계 방법이라는 주장은 실무 경험이 있는 개발자라면 공감할 수 있을 것이다.