Eternity's Chit-Chat

aeternum.egloos.com



Domain-Driven Design의 적용-3.Dependency Injection과 Aspect-Oriented Programming 2부 Domain-Driven Design

객체 그리고 영속성(Persistence)

모든 객체는 생성자가 호출되는 시점에 생성된다. VALUE OBJECT 수명은 짧다. 생성된 잠시 다른 REFERENCE OBJECT 또는 VALUE OBJECT 의해 사용되다가 다른 VALUE OBJECT 대체된다. 길을 잃은 VALUE OBJECT 가비지 컬렉터에게 넘겨진 조용히 생을 마감한다. VALUE OBJECT 비해 REFERENCE OBJECT 수명은 상대적으로 길다. REFERENCE OBJECT 다양한 이벤트에 반응함에 따라 상태가 변한다. 일단 고객 객체가 생성되면 시스템은 고객이 탈퇴할 때까지 고객 객체를 참조하고 추적할 있어야 한다. 이를 위해 도메인 모델에 추가되는 PURE FABRICATION REPOSITORY이다.

 

이제 도메인 객체의 생명 주기라는 컨텍스트에 영속성이라는 개념을 추가해 보자.

 

메모리는 비싼 자원이다. CPU 어플리케이션을 실행하기 위해서는 우선 일차 저장소(primary storage) 메모리에 필요한 모든 것들을 주섬주섬 올려 놓아야만 한다. 메모리는 비싼 자원이기 때문에 크기 역시 작을 밖에 없다. 부족한 메모리 공간에 이것 저것 쑤셔 넣다 보면 결국 빈번한 스와핑(swapping)으로 인해 전체적인 성능이 저하될 밖에 없다. 따라서 시스템은 자기가 현재 처리해야 고객, 주문, 상품을 제외한 모든 다른 정보들은 최대한 빨리 잊어 버려야 한다. 단기 기억 상실증은 시스템으로 하여금 전체적인 성능을 유지하게 하는 훌륭한 질병인 셈이다.

 

메모리는 휘발성이다. 메모리는 전원이 꺼지는 순간 청문회에 출두한 정치인들의 뇌처럼 과거의 모든 기억을 깨끗하게 잊어 버린다. 따라서 시스템은 모든 도메인 객체를 메모리에 보관할 없으며 그렇게 해서도 안된다. 모든 사람들은 주문 시스템이 복구되었을 시스템 내에 보관되어 있던 모든 사용자, 주문, 상품 정보가 그대로 복구되기를 원한다. 단기 기억 상실증에 걸린 메모리에 모든 정보를 보관하고 있다가 뒤통수를 맞는 일을 바라지 않는다. 따라서 시스템 내에 지속적으로 보관되어야 하지만 지금 당장 필요하지 않은 정보를 이차 저장소(secondary storage) 옮겨 놓을 필요가 있다. 에드가 앨런 포우의 말처럼 당장 어떤 것을 잊고 싶다면, 기억할 있게 적어 두어야 한다.

 

이처럼 일차 저장소인 메모리에서 활발하게 뛰어 놀던 도메인 객체를 붙잡아 이차 저장소에 동면시키는 기법을 영속성(Persistence) 메커니즘이라고 한다. 도메인 객체 고객, 주문, 상품처럼 이차 저장소에 영구히 보관하는 객체를 영속 객체(Persistence Object)라고 한다.

 

다양한 형식의 직렬화(Serialization) 기법들 역시 영속성 메커니즘의 일종이라고 있다. java에서 제공하는 기본 직렬화는 메모리 내의 객체 상태를 이차 저장소인 파일 시스템에 저장한 필요 원래의 상태로 복원한다. 그러나 대용량 데이터를 처리하는 엔터프라이즈 어플리케이션의 경우 직렬화보다 견고하고 성능이 뛰어나며, 데이터 보안과 같은 다양한 지원 기능을 제공할 있는 인프라 스트럭처를 요구한다.

 

일반적으로 엔터프라이즈 어플리케이션은 대용량 데이터를 관리하기 위한 이차 저장소로 관계형 데이터베이스(Relation Database Management System) 사용한다. 대부분의 엔터프라이즈 어플리케이션이 관계형 데이터베이스를 사용한다는 사실은 어플리케이션 개발자들에게 가지 의미를 가진다.

 

첫째, 관계형 데이터베이스 기술은 수십 동안 점진적으로 성장하고 발전한 안정적인 기술이다. 많은 벤더들이 RDMS 개발하고 있으며 수많은 레거시(legacy) 시스템들이 관계형 데이터베이스를 영속성 저장소로 사용하고 있다. 수십 동안의 적용 경험과 축적된 노하우는 안정적인 어플리케이션 개발을 가능하게 한다.

 

둘째, 객체와 관계형 테이블 간의 거리는 너무 멀다. 관계형 데이터베이스는 수학적인 집합 개념을 기반으로 하며 정규화를 통해 데이터의 중복을 제거하는 것이 목적이다. 이에 비해 객체 지향은 객체 또는 객체들간의 응집도와 결합도를 고려한 책임 할당과 행위의 다형성을 기반으로 한다. 관계형 데이터베이스는 상속성, 캡슐화, 다형성과 같은 객체 지향의 핵심적인 개념을 지원하지 않는다. 객체 세계의 초창기 시절부터 사람들은 객체와 관계형 데이터베이스 간에 임피던스 불일치(impedance mismatch) 있음을 알고 있었다.

 

임피던스 불일치의 어려움은 엔터프라이즈 어플리케이션의 아키텍처에 영향을 끼쳤다. 임피던스 불일치를 극복하지 못했던 초창기 개발 커뮤니티의 선택은 데이터베이스 테이블에 매핑하기 쉬운 구조로 도메인 레이어를 설계하는 것이었다. 불에 기름을 붓는 격으로 엔티티 빈의 제약 사항은 이런 설계를 장려하는 결과를 나았다. 결과적으로 객체 지향 언어로 개발된 절차적 방식의 어플리케이션 아키텍처라는 사생아가 탄생했으며 J2EE 엔터프라이즈 어플리케이션의 주도적인 아키텍처로 자리잡고 말았다. 영향으로 현재까지도 행위가 없이 상태만 가지는 Anemic Domain Model가지는 TRANSACTION SCRIPT 패턴엔터프라이즈 어플리케이션 아키텍처의 주를 이루고 있다.

 

행위와 상태를 함께 가지는 객체를 사용하여 도메인 레이어를 설계하는 방식을 DOMAIN MODEL 패턴이라고한다. DOMAIN MODEL 패턴은 상속성, 캡슐화, 다형성과 같은 모든 객체 지향 기법들을 활용하기 때문에 임피던스 불일치 문제를 해결하기 위한 하부 인프라 스트럭처의 지원 없이는 적용하기가 쉽지 않다.

 

임피던스 불일치를 해결하는 가장 쉬운 방법은 객체 지향 데이터베이스를 사용하는 것이다. 그러나 객체 지향 데이터베이스 기술은 상업적으로 성공하지 했고 결과적으로 대부분의 프로젝트에서 고려사항이 아니다. 비록 객체 지향 데이터베이스를 사용할 없다고 하더라도 방법은 있다. 객체 계층과 관계형 데이터베이스 계층 사이에 가상의 객체 지향 데이터베이스를 구축하는 것이다. 이처럼 객체와 관계형 데이터베이스 테이블 간의 불일치를 소프트웨어적으로 해결하는 것을 객체 관계 매핑(Object-Relation Mapping)이라고 하며 객체 관계 매핑을 수행하는 소프트웨어를 객체 관계 매퍼(Object-Relation Mapper, ORM)라고 한다.

 

ORM 내부적으로 DATA MAPPER 패턴을 사용한다. DATA MAPPER 객체 지향 도메인 객체와 관계형 데이터베이스 테이블, 그리고 매퍼 자체의 독립성을 유지하면서 도메인 객체와 테이블 간의 데이터를 이동시키는 객체이다. 일반적으로 DATA MAPPER METADATA MAPPING 패턴을 사용하여 객체와 테이블 간의 매핑 정보를 어플리케이션 외부의 설정 파일로 관리한다. DATA MAPPER 메커니즘에 관해서는 Martin Fowler 엔터프라이즈 어플리케이션 아키텍처 패턴 참고하라.

 

다시 주문 도메인을 살펴보자. Customer 클래스는 고객의 상태와 상태를 변경시키기 위한 행위를 함께 가지고 있다. Order 클래스는 주문의 상태와 상태를 변경시키기 위한 행위를 함께 가지고 있다. , 주문 도메인 어플리케이션의 도메인 로직은 DOMAIN MODEL 패턴으로 구성되어 있다. 따라서 임피던스 불일치 문제를 해결하기 위한 가장 쉬운 방법은 DATA MAPPER 패턴을 사용한 ORM 적용하는 것이다. 이제 주문 어플리케이션에 영속성을 부여하기 위해 ORM 적용해야 때가 왔다.

 

지금까지 어플리케이션의 생명 주기 동안 지속적으로 추적해야 하는 객체들을 REFERENCE OBJECT 모델링하고 연관된 REFERENCE OBJECT들을 AGGREGATE라고 하는 하나의 객체 클러스터로 식별했다. AGGREGATE 대해 ENTRY POINT 선정하고 ENTRY POINT 별로 REPOSITORY 할당한 REPOSITORY 통해 AGGREGATE 생명 주기를 관리하도록 했다. 이제까지는 단순히 REPOSITORY REFERENCE OBJECT 메모리 컬렉션을 관리하는 객체로만 바라 보았다. 이제 REFERENCE OBJECT 영속성을 관리하는 객체로 REPOSITORY 개념을 확장해 보도록 하자.


핑백

  • Domain-Driven Design | Jongmin Kim's Blog 2014-09-02 01:18:26 #

    ... ion과 Aspect-Oriented Programming 3부 2008/12/09 Domain-Driven Design의 적용-3.Dependency Injection과 Aspect-Oriented Programming 2부 2008/12/05 Domain-Driven Design의 적용-3.Depe ... more