도메인 모델링 세미나 10
<모델 저장소의 의미와 구현> 편에 달린 페이스북 댓글을 계기로 쓴 글이다.
Normal Developer님이 언급한 repository는 앞선 글에서 다룬 모델 저장소가 아니라 Domain-driven design의 빌딩 블록인 Repository를 말한다. 원서인 Eric Evans의 책 147쪽에 사서의 이미지가 나온다. 그 아래 문구를 인용하면,
Associations allow us to find an object based on its relationship to another. But we must have a starting point for a traversal to an ENTITY or VALUE in the middle of its life cycle.
연관(Associations)이 제공하는 관계에 기초하여 객체를 찾는다. 객체지향에서 데이터의 복잡성을 다루는 방식이다. 그리고 그 연관은 인간이 사회를 조직화하는 방식이 투영되며, 관계형 데이터베이스라는 기술에 기초하여 구현될 수 있다.
이때, 연관을 이용하여 객체를 찾을 수 있는 시작점을 제공해야 한다. 왜냐하면 시스템은 끝없이 변모하기 때문이다. 변모하는 사항을 객체로 조직화시키는데, 어떤 데이터 값(Value)이나 우리가 정체성을 부여한 단위나 현재 상태에 따라 끊임없이 변모하는 값을 담는 엔티티(Entity) 등의 형태로 활용할 수 있다. 장 제목은 Respotories인데, Repository에 대한 정의로 시작하지 않는다. 하지만, Repository가 필요한 배경을 기술하는 방식이 더욱 매력적인 설명이다.
추정하건대 Normal Developer님은 내가 둘로 나눠서 제시한 저장소의 핵심 기능에서 영감을 얻지 않았을까 싶다.
모델링 결과물의 보관
모델링 결과물 찾기
Normal Developer님이 언급하신 대로 DAO를 Repository라고 이름만 바꿔서 쓰던 일은 내가 개발을 하던 10여 년 전에도 있던 일이다. (지금도 계속되는 모양이다.)
DAO는 자바 1.4가 등장하던 시절 산물로 기억하는데 기업용 자바 SDK를 J2EE라는 이름으로 제공하고 기술자 대상 홍보를 하던 시대의 SUN의 산물이다. 당시 DAO 등을 Core J2EE Patterns라고 불렀다. 대략 20년 전 내용인데 다행히 아직 페이지가 남아 있다. 패턴에 대한 설명은 고전인 GoF의 형식을 따왔다.
DAO 패턴이 풀고 싶은 문제는
You want to encapsulate data access and manipulation in a separate layer.
데이터 다루는 코드를 별도 층으로 분리해서 수정하기 쉽게 하고 싶다는 것이다.
그래서 내놓은 해결책은
Use a Data Access Object to abstract and encapsulate all access to the persistent store. The Data Access Object manages the connection with the data source to obtain and store data.
DAO라는 층에 데이터 접근이나 데이터 보관, 획득 등을 위한 코드를 분리하자는 것이다. 그리고 내가 경험한 실전에서는 보통 실수에 대한 대가가 큰 데이터 접근이나 트랜젝션 처리 등의 코드는 Spring 등의 프레임워크에 맡기고 DAO를 작명 규칙에 넣어서 실제 데이터를 조작하는 부분만 해당 클래스의 메소드에서 다루는 식으로 코드를 구성했다.
이후에는 iBatis(MyBatis) 등의 기술을 이용하여 DAO 층 구현을 할 때, SQL을 별도로 저장하고 DAO로 작명한 객체의 메소드가 호출될 때 연결하여 사용하는 이른바 SQL Mapper가 널리 쓰였고, 뒤이어 ORM 개념을 선호하는 개발자들은 Hibernate(JPA)를 다루는 방향으로 발전했다.
앞서 인용한 DAO 정의를 보자.
Use a Data Access Object to abstract and encapsulate all access to the persistent store. The Data Access Object manages the connection with the data source to obtain and store data.
DAO는 DBMS와 같은 영속적 저장소 접근(all access to the persistent store)을 층으로 묶은 개념이다.
비교해서 위키피디아의 Repository 정의를 보자.
A repository, for instance, is an object with methods for retrieving domain objects from a data store (e.g. a database).
반면 Repository는 도메인 객체 추출(for retrieving domain objects)을 목표로 한다.
대략의 기능과 코드의 모양은 굉장히 유사하다. 반면에 지향점이나 목표가 다르다고 할 수 있다. 한 마디로 요약하면, DAO는 객체에 대한 고민이 덜 담겨 있다. 어떻게 객체를 설계할 것이냐를 다루는 본격 담론인 Domain-driven design의 산물답게 Repository를 데이터 접근 자체가 아니라 도메인 객체 추출(for retrieving domain objects)을 담당하는 빌딩 블록으로 정의한다.
이 글 역시 전편과 마찬가지로 글을 쓰고 난 후에 벌어진 사건에 반응하여 쓴 즉흥적인 글이다. 하지만, 인 <Repository 의미 더 찾아보기> 편과 마찬가지로 나를 여기로 이끈 욕망을 의식적으로 재해석할 수 있다. 저장소의 본질적인 기능 관점으로 DDD 빌딩 블록도 바라볼 수 있다.
아래는 <모델 저장소의 의미와 구현>에서 언급한 모델링 저장소의 핵심 기능이다.
모델링 결과물의 보관
모델링 결과물 찾기
도메인 객체의 저장소의 핵심 기능으로 단순 치환해보자.
도메인 객체의 보관
도메인 객체 찾기
이렇게 쓰고 나니 앞서 DAO와 차이를 설명할 때 설명하지 못한 2%를 찾은 듯하다. 이 글 시작 부분에서 인용한 DDD 책 내용 일부 해설을 다시 인용한다.
연관(Associations)이 제공하는 관계에 기초하여 객체를 찾는다.
연관을 어떻게 보관하느냐의 문제는 DAO가 다루지 않는다. 영속 저장소 기술인 RDBMS에 의존하면 SQL에 맡기면 그만이다. 그런데, SQL이 아닌 방식으로 비즈니스 규칙을 꺼내서 코드 화하고 싶다면 어떻게 해야 할까?
객체지향 기법에서는 객체의 연관을 몇 가지 관계로 구성하는 방법을 사용한다. DDD 책에서는 이런 문제를 다루기 위해 추가로 Aggregate를 설명한다. Entity를 조합 형태로 인지할 때 활용할 수 있는 사고법이자 설계 방안이다. 하지만, 데이터의 구성 형태나 크기에 따라 RDBMS로만 구현할 수 없는 일이 생긴다. 다시 말해 연관은 객체지향 기법의 한계 속에서만 구현하는 일은 현실성이 떨어진다.
그래서 DDD 책에는 담겨 있지 않는 내용들이 DDD 커뮤니티에서 다뤄지는 모습을 인터넷 공간에서 찾을 수 있다. 한편, QCon 2014에서 들은 Spark 세션에서도 데이터 스트리밍 기술을 구현한 동기를 Aggregate root 구성의 어려움이라고 설명했다. 요즘 기사를 보면, 보편 기술로 떠오르고 있다는 GraphQL 역시 RDBMS와 다른 방식의 도메인 객체 추출(for retrieving domain objects) 방법을 제공하는 기술로 볼 수 있다.
5. 아주 이상적인 아키텍처