추상화를 조심스럽게 선택하라

요즘에 "도메인 주도 설계 핵심(Domain-Driven Design Distilled)"라는 책을 읽고 읽다. DDD를 주제로 하는 책은 이것까지 총 4-5권은 읽은 것 같다. 그중에 몇 권은 두 세번은 넘게 읽은 듯한데, 볼 때마다 새롭고 어렵다. 알듯하다가도 온라인에서 고수들이 하는 이야기를 듣고 있노라면 아직 내가 DDD를 잘 모르는구나 싶을 때가 종종 있다.

이 책은 어려운 주제를 딱딱하게 설명하는 전형적인 재미없는 책이다. 한 가지 다른 책들과 달리, 프로세스 관점에서 이야기를 풀어나가는 점은 흥미로웠다. 책으로는 이해하기 어려웠던 실무 관점의 이야기를 이 책에서 약간이나마 간접 경험을 할 수 있었다.

DDD는 단순한 패턴의 모음이나 설계 기법이 아닌, 개발 전 과정을 관통하는 프로세스를 담고 있다. DDD의 개념을 얼추 이해해도 실무에 적용하기는 쉽지 않았던 것이 그 때문이었을까.

동료와 설계 논의를 하다 보면 추상화의 수준을 놓고 설왕설래할 때가 많다. 결국 코딩이라는 게 추상화로 시작해서 추상화로 끝나는 것 같다는 생각을 요즘 가끔 한다. 그만큼 추상화는 개발자에게 중요한 문제다. 추상화 수준이 너무 높으면 오버엔지니어링이 되어 비효율을 만들고, 추상화 수준이 너무 낮으면 유지보수가 힘들어진다. 적정 수준을 찾으라는데, 대체 그 적정 수준이란 어느 지점을 말하는 건지. 늘 곤란하다.

DDD는 적정 수준의 기준을 보편 언어(Ubiquitous Language)에서 찾는다. 물론 만능 키는 아니겠지. 좋은 설계를 고민하는 개발자라면 한 번쯤 읽어볼 만한 내용인 듯해서 한 섹션을 발췌했다.

--

추상화를 조심스럽게 선택하라

효과적인 소프트웨어 모델은 항상 일을 하는 비즈니스의 방식을 고려한 일련의 추상화에 기반을 두고 있다. 이때 모델링하는 각 개념마다 적절한 수준의 추상화를 선택해야 한다. 만일, 보편 언어와 관련된 가이드를 따른다면 적절한 추상화를 설정할 수 있다. 적어도 모델링 언어의 기반에 지식을 전달해주는 도메인 전문가가 있기 때문에 훨씬 정확하게 추상화를 모델링할 수 있다.

하지만 가끔은 잘못된 문제를 푸는 것에 지나치게 몰두한 나머지, 소프트웨어 개발자가 지나칠 정도로 추상화를 적용하기도 한다. 예를 들면, 애자일 프로젝트 관리 컨텍스트에서의 스크럼 관련 사항을 돌이켜보자. 전에 논의했던 Product, BacklogItem, Release 그리고 Sprint 개념을 모델링하는 것은 타당하다. 

그렇지만 소프트웨어 개발자가 스크럼의 보편언어를 모델링하는 것에 그다지 관심을 기울이지 않은 채, 현재와 미래의 모든 스크럼 관련 개념을 모델링하는 것에 더 많은 관심을 갖고 있다면 어떻게 될까?

이런 관점이 계속되면, 개발자들은 ScrumElement, ScrumElementContainer와 같은 개념을 생각해낼 것이다.  ScrumElement는 Product와 BacklogItem에 대한 현재의 요구를 만족시키고, ScrumElementContainer는 Release와 Sprint의 명확한 개념을 분명히 표현해줄 것이기 때문이다. ScrumElement는 typeName 프로퍼티를 가질 것이고, 아마도 그 값은 상황에 맞게 "Product"나 "BacklogItem"으로 설정될 것이다. ScrumElementContainer에 대해서도 같은 종류의 typeName 프로퍼티를 설계하고, 이를 "Release"나 "Sprint"로 설정할 것이다.

이런 방식에서 나타나는 여러 문제점들이 보이는가? 여기에는 적지 않은, 그러나 반드시 고려해야 하는 것들이 있다.

1. 소프트웨어 모델의 언어가 도메인 전문가의 멘탈 모델과 일치하지 않는다.

2. 추상화 수준이 너무 높아서 각 개별적인 형태의 세부 사항을 모델링하기 시작하면 어려운 상황에 빠질 것이다.

3. 이것은 각각의 클래스마다 특수한 경우를 정의할 것이고, 명백한 문제들에 대한 일반적인 접근을 통해 복잡한 클래스 계층 구조를 만들 것이다.

4. 우선적으로 중요하지 않은 문제를 해결하려다가 필요한 것보다 훨씬 많은 코드를 생산할 것이다.

5. 잘못된 추상화 수준은 심지어 사용자 인터페이스까지 영향을 미쳐 사용자에게 혼란을 주는 경우도 종종 발생한다.

6. 이로 인해 상당한 시간과 비용을 낭비할 수 있다.

7.  프로젝트 초반에 미래의 모든 요구를 생각하고 반영할 수는 없다. 새로운 스크럼 개념들은 앞으로도 계속 추가될 것이고, 기존 모델은 그 요구사항을 예견하는 데 실패할 수밖에 없기 때문이다.

이런 잘못된 방식을 따르는 상황이 나타날지 의문을 갖는 사람들도 있겠지만, 이런 부적절한 추상화 수준은 기술적인 측면으로 구현을 생각하는 상황에서 자주 등장한다.

...(이하 생략)