도메인 스토리텔링 응용 11
지난 시간에 인용한 Loosely-coupled 위키피디아 정의로부터 시작하자.
In computing and systems design a loosely coupled system is one
1. in which components are weakly associated (have breakable relationship) with each other, and so, changes in one component least affect existence or performance of another component.
2. in which each of its components has, or makes use of, little or no knowledge of the definitions of other separate components. Subareas include the coupling of classes, interfaces, data, and services. Loose coupling is the opposite of tight coupling.
Loosely-coupled 라고 수식한 시스템은 서로 약하게 연관된(weakly associated) 구성요소 구성되어 있는 시스템을 말한다. 약한 연관에 대한 부연으로 have breakable relationship 즉, 나눌 수 있는 관계라고 설명한다. 90년대에는 컴포넌트를 은유적으로 설명할 때, 오디오 컴포넌트를 예로 드는 일이 잦았다. 초기 오디오 시스템이 하나의 물리적 덩어리였다가, 턴테이블과 스피커 그리고 테이프, CD 플레이어가 구분된 제품이 나오기 시작했기 때문이다.
그리고 우리나라에서는 CBD(Component Based Development)라는 표현이 유행할 때, Component가 범용적인 '구성요소'라는 의미보다는 특정 기술이 정의하는 구성 단위(EJB 혹은 .NET 컴포넌트)를 뜻하거나 UML 표기를 배경으로 하는 방법론으로 제한하는 시각이 지배적이었다.
하지만, 컴포넌트는 그저 우리가 시스템을 나누는 단위일 뿐이다. 사실 단위를 정의하거나 인식하지 못하는 개발자들이 훨씬 다수이다. 그렇지만, 설계를 능숙하게 하고 싶다면, 단위에 대한 감각을 키워야 한다.
이제는 절대 다수 개발자의 도구라고 할 수 있는 스프링 프레임워크 등장 초기에 Dependency Injection 패턴이 유행했다. 2004년에 마틴 파울러가 쓴 글 Inversion of Control Containers and the Dependency Injection pattern을 찾을 수 있다. 지금은 패턴을 배우기 보다 스프링을 배우며 자기도 모르게 익히는 방법이다.
당시 널리 쓰이던 UML 표기(클래스도)다. UML에서 관계를 표현하는 선 중에 실선은 연관(association)이라고 한다. 그런데 위키피디아 Loosely-coupled 정의에서 본 약한 연관(weakly associated)은 어떻게 표현할 수 있을까? 점선으로 표현할 수 있다. 점섬은 UML에서 의존(dependency) 혹은 의존관계라고 한다. 자연어 정의는 엄밀하기 어렵다. 그래서, 그 차이를 프로그램 적으로 설명해보면, 바로 dependency injection에 대한 설명이 된다.
위 그림에서 MovieLister가 자동하기 위해서는 MovieFinder에 의존한다. 영화 목록을 보려면 검색 기능을 써야 한다는 의미로 이해할 수 있다. 그런데, 검색 기능을 구현하는 방법이 다양해서 그때마다 MovieLister를 수정하지 않고 재사용할 수는 없을까? 위키피디아 정의를 설명할 때 have breakable relationship란 표현을 인용했다. 관계를 끓어버릴 수 있느냐가 약함의 판단 기준이다. 자바 프로그램은 Interface라는 요소를 만들어서 이런 관계를 지원한다. MovieFinder는 구동할 기능을 지칭할 이름과 구성요소(입력값, 출력값 등)만 정의하고 실제 기능 구현 내용은 구동할 때 확장할 수 있게 해준다. 그게 위 클래스도에서 MovieFinderImpl 이고, Assembler가 이들이 하나로 어우러진 프로그램 덩어리가 되게 해준다.
스프링 프레임워크에서 그 이름은 Application Context이다. 훌륭한 이름이다. 여러분이 <시스템 구동의 맥락(context) 파악하기>편을 이해했다면 내 견해에 동의할 것이다. MSA 유행과 무관하게 스프링은 맥락을 구분하고 관리할 수 있는 방법을 아주 오래전부터 제공했다.
dependency injection으로 프로그램 결과물과 구동하는 맥락 구성방법을 구분하여 실행할 때 주입하는 방법은 탁월한 Loosely-coupled 실현법으로 역사적으로 무려 20년 가까운 세월동안 쓰임새를 입증하고 있다. 스프링을 남들이 써서 그냥 쓰고 있던 분이라면 이 글을 꼭 이해하시길 바란다.
dependency injection을 설명하면서 Loosely-coupled 시스템 정의에서 두 번째 특징은 아직 다루지 않았다.
in which each of its components has, or makes use of, little or no knowledge of the definitions of other separate components. Subareas include the coupling of classes, interfaces, data, and services. Loose coupling is the opposite of tight coupling.
앞서 클래스도를 보면서 dependency injection를 설명할 때 했던 말을 인용해본다.
검색 기능을 구현하는 방법이 다양해서 그때마다 MovieLister를 수정하지 않고 재사용할 수는 없을까?
MovieFinder가 복잡해질 때, MovieLister에 옮기지 않는 방법이 바로 dependency injection 이었다. 하나의 패턴인데, Loosely-coupled 시스템을 만드는 방법 중에 하나다. 우리가 살아가는 사회의 변화는 막을 수 없다. 그래서 시스템이 꾸준히 쓰이려면 프로그램도 마찬가지로 바뀌어야 한다. 변화에 대한 적응은 마치 생존과도 같다. 변화를 막을 수는 없지만, 변화할 부분을 최소화 할 수는 있다.
시스템이 꾸준히 변할 수 있어야 지속한다는 사실을 믿으면 Loosely-coupled 는 복잡한 시스템의 생존 방식이다.
6. 도메인 모델, Ongoing 설계 그리고 정원관리