-
DDD - Dependency Injection과 AOP 2부JAVA/DDD 2021. 1. 22. 21:41
객체 그리고 영속성(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의 적용
'JAVA > DDD' 카테고리의 다른 글
DDD - Dependency Injection과 AOP 4부 5부 (0) 2021.01.22 DDD - Dependency Injection과 AOP 3부 (0) 2021.01.22 DDD - Dependency Injection과 AOP 1부 (0) 2021.01.11 AGGREGATE와 REPOSITORY 5부 (0) 2021.01.08 AGGREGATE와 REPOSITORY 4부 (0) 2021.01.05