트랜잭션 스크립트
내용 추가 예정....😗
도메인 모델
작동 원리
비즈니스 영역을 모델링하는 객체로 구성된 계층을 구성하는 과정이다. 이 객체 중에는 비즈니스 데이터를 나타내는 객체도 있고 비즈니스 규칙을 나타내는 객체도 있다. 이러한 데이터와 프로세스는 프로세스와 작업 대상 데이터를 가깝게 배치하기 위한 클러스터를 형성한다.
객체지향 도메인 모델과 데이터베이스 모델은 비슷해보이지만 차이점이 많다. 모데인 모델은 데이터와 프로세스가 혼합된 구조이고, 상속을 사용하고 다중 값 속성과 복잡한 연결망을 가지고 있다. 이러한 이유로 주로 두 가지 형식의 도메인 모델이 사용된다. 단순 도메인 모델은 대부분의 도메인 객체가 각 데이터베이스 테이블과 일치하므로 외형상 데이터베이스 설계와 거의 비슷해 보인다. 반면 리치 도메인 모델은 상속, 전략, 다양한 패턴, 그리고 복잡하게 상호연결된 객체의 연결망을 포함한다. 리치 도메인 모델은 복잡한 논리를 나타내는 데 적합하지만 데이터베이스 매핑이 어렵다. 단순 도메인 모델은 활성 레코드를 사용하지만 리치 도메인 모델은 데이터 매퍼가 필요하다
비즈니스 동작은 자주 변경해야 하기 때문에 도메인 모델과 다른 계층 간의 결합을 최소화해야 한다. 도메인 모델에는 여러 다양한 범위를 사용할 수 있다. 가장 단순하게는 파일에서 전체 객체 그래프를 읽어 메모리에 저장하는 단일 사용자 애플리케이션이 있다. 테스크톱 앱에서 이렇게 작동할 수 있지만 다중 계층 IS 앱에는 객체가 너무 많아 이러한 방식을 도입하기는 어렵다. 모든 객체를 메모리에 저장하는건 자원과 시간이 많이 든다. 객체 지향 데이터베이스의 장점은 실제로는 메모리와 디스크 사이에서 객체를 이동하면서 모든 객체가 메모리에 있는 것처럼 사용할 수 있다는 것이다.
객체지향 데이터베이스를 사용할 수 없으면 필요한 일을 직접 해야 한다. 이 경우 보통 한 세션이 연관된 모든 객체 그래프를 가져오는 일을 한다. 당연히 모든 객체가 포함되지 않으며 보통은 모든 클래스가 포함되지도 않는다. 어떤 객체를 메모리로 가져오는지는 데이터베이스 매핑 객체에 의해 좌우된다.
도메인 논리에서 고민은 객체가 과하게 비대해지는 것이다. 이러한 문제를 예방하기 위해 사람들은 어떤 동작이 일반적인지 여부를 먼저 고려하고 일반적인 동작과 특정한 동작을 분리하는 방법을 생각했다. 그런데 특정한 동작도 중복으로 발생할 우려가 있다. 중복은 복잡성과 일관성 문제를 일으키지만 객체가 비대해지는 문제는 우려하는 것만큼 자주 발생하지 않는다. 그리고 비대한 객체는 눈에 쉽게 띄며 수정하기도 쉽다. 따라서 특정 사례를 분리하지 않는게 좋다. 그리고 객체가 비대해지고 문제가 생기면 그때 해결하면 된다.
사용 시점
가장 중요한 것은 시스템이 수행하는 동작의 복잡도다. 끊임없이 변하는 비즈니스 규칙을 구현해야 한다면 객체 모델을 사용해서 처리하는 것이 현명하다. 도메인 모델을 사용하는 경우 데이터 매퍼를 사용하면 데이터베이스에 대해 독립적으로 유지할 수 있다. 도메인 모델은 간단한 작업을 할 때도 여러 클래스가 상호작용한다. 그래서 객체지향 프로그램에서는 특정 클래스를 찾느라 너무 돌아다녀야한다고 불평하는 사람들도 많다. 그러나 어떤 항목이 더 복잡해질 때 그리고 다른 객체들도 이를 알아야 할 때 도메인 모델의 장점이 드러난다. 알아야 할 동작을 해당 객체 안에 유지하는 방법으로 중복을 방지하고 객체 간 결합을 줄일 수 있다.
테이블 모듈
데이터베이스 테이블이나 뷰의 모든 행에 대한 비즈니스 논리를 처리하는 단일 인스턴스
객체지향의 핵심 개념 중 하나는 데이터, 그리고 이를 사용하는 동작을 하나로 묶는 것이다. 기존 객체지향 방식은 도메인 모델과 비슷한 맥락으로 식별자가 있는 객체에 기반을 두고 있다. 도메인 모델의 문제점 중 하나는 관계형 데이터베이스와의 인터페이스가 까다롭다라는 것이다. 때문에 데이터를 주고받는 작업이나, 데이터의 두 가지 다른 표현 사이를 변환하는 기본적인 작업에도 많은 노력이 필요하다.
테이블 모듈은 데이터베이스의 테이블당 클래스 하나로 도메인 논리를 구성하며, 클래스의 한 인스턴스가 해당 데이터에 대해 수행하는 여러 프로시저를 포함한다. 도메인 모델과의 가장 큰 차이점은 주문이 여러 개인 경우 도메인 모델은 주문의 수만큼 객체를 사용하고, 테이블 모듈은 모든 주문을 객체 하나가 처리한다.
작동 원리
테이블 모듈의 장점은 데이터와 동작을 하나로 묶으면서 동시에 관계형 데이터베이스의 강력함을 그대로 활용할 수 있다는 것이다. 테이블 모듈은 표면적으로 보통 객체와 아주 비슷하다. 핵심적인 차이는 작업 대상 객체의 식별자 개념이 없다는 것이다. 따라서 항상 일종의 식별자 참조를 전달해야 한다. 이 식별자는 데이터베이스에 사용되는 기본 키인 경우가 많다.
테이블 모듈은 인스턴스 하나이거나 정적 메서드의 컬렉션일 수 있다. 인스턴스 하나인 경우 기존의 레코드 집합으로 테이블 모듈을 초기화할 수 있다는 장점이 있다. 그런 다음 이 인스턴스를 사용해 레코드 집합의 행을 조작할 수 있다. 또한 상속을 적용할 수 있으므로, 추가 동작을 더해서 작업이 가능하다.
테이블 모듈은 쿼리를 팩터리 메서드로서 포함할 수 있다. 다른 방법은 테이블 데이터 케이트웨이를 사용하는 것이다. 이 경우 설계 안에 추가적인 테이블 데이터 게이트웨이 클래스와 매커니즘이 포함된다는 단점이 있다. 장점은 각 데이터 원본에 다른 테이블 데이터 게이트웨이를 사용하므로 테이블 모듈 하나를 다른 데이터 원본의 데이터에 사용할 수 있다는 것이다.
테이블 데이터 게이트웨이를 사용하면 애플리케이션은 이걸 사용해서 데이터로 레코드 집합을 만든다. 그런 다음 레코드 집합을 이용해 테이블 모듈을 만든다.
테이블 모듈에서 테이블은 데이터베이스의 테이블당 테이블 모듈이 하나씩 사용된다는 의미가 있다. 항상 그렇지만은 않다. 일반적으로 사용되는 뷰나 다른 쿼리에 대한 테이블 모듈을 만들어도 유용하다. 실제 테이블 모듈의 구조는 데이터베이스의 테이블 구조보다는 애플리케이션이 인식하는 뷰와 가상의 테이블에 더 가깝다.
사용 지점
레코드 집합을 사용해 테이블 형식의 데이터에 접근할 때 가장 적합한 패턴이다. 또한 자료구조를 코드에서 가장 중요한 요소로 다루므로 자료구조에 직관적으로 접근할 수 있다.
그러나 테이블 모듈은 복잡한 논리를 구성하는 객체의 강력함을 완전하게 활용하지 못한다. 인스턴스-인스턴스 관계를 만들 수 없고, 다형성이 제대로 작동하지 않는다. 따라서 복잡한 도메인 논리를 처리해야 한다면 도메인 모델을 선택해야 한다.
도메인 모델의 객체와 데이터베이스 테이블이 상대적으로 비슷하다면 활성 레코드를 이용하는 도메인 모델을 사용하는 것도 방법이다. 또한 앱의 다른 부분이 일반적인 테이블 기반 자료구조에 바탕을 두고 있다면 테이블 모듈을 사용하는 것이 좋다. 이 패턴을 활용하는 가장 적합한 환경은 .NET 환경이 있다. 이 환경에서는 레코드 집합이 앱의 주요 데이터 리포지토리로 사용된다.
서비스 계층
사용 가능한 작업의 집합을 설정하고 각 작업에 대한 애플리케이션의 반응을 조율하는 서비스의 계층으로 애플리케이션의 경계를 정의한다.
-랜디 스태퍼드-
서비스 계층은 클라이언트 계층을 인터페이스하는 관점에서 애플리케이션의 경계와 사용 가능한 작업의 집합을 정의한다. 작업을 구현할 때 트랜잭션을 제어하며 응답을 조율하면서 애플리케이션의 비즈니스 논리를 캡슐화한다.
작동 원리
도메인 논리는 순수하게 문제 도메인을 집중적으로 처리하며, 애플리케이션 논리는 애플리케이션 역할을 처리한다.
도메인 모델은 전통적인 디자인 패턴을 사용해 복잡성을 관리하고 도메인 논리 중복을 예방하는 면에서 트랜잭션 스크립트보다 나은 방법이다. 그런데 애플리케이션 논리를 순수 도메인 객체 클래스에 넣으면 두 가지 부작용이 있다.
1. 도메인 객체 클래스가 특정 애플리케이션 논리를 구현하고 특정 애플리케이션 패키지를 사용하면 도메인 객체 클래스를 다른 애플리케이션에서 재사용하기 어렵다.
2. 두 가지 종류의 논리를 동일한 클래스에 넣으면, 나중에 분리할 필요가 있을 때 다시 구현하기 어렵다.
이러한 이유로 서비스 계층은 각 유형의 비즈니스 논리를 별도의 계층으로 분리함으로써 계층화의 일반적인 장점을 제공하고 순수 도메인 객체 클래스를 애플리케이션 간에 재사용을 쉽게 만들어준다.
서비스 계층 구현 방법 두 가지
1. 도메인 파사드 방식
- 서비스 계층을 도메인 모델 위에서 씬 파사드의 집합으로 구현한다.
- 파사드를 구현하는 클래스는 비즈니스 논리를 전혀 구현하지 않는다.
- 도메인 모델이 모든 비즈니스 논리를 구현한다.
2. 작업 스크립트
- 서비스 계층을 리치 클래스 집합으로 구현한다.
- 애플리케이션 논리를 직접 구현하지만, 도메인 논리는 캡슐화된 도메인 객체 클래스로 위임한다.
- 클라이언트에 제공되는 작업은 여러 스크립트로 구현되며, 이러한 스크립트는 연관된 논리의 특정 주제 영역을 정의하는 한 클래스에 포함된다.
원격 호출에 대한 고려
서비스 계층 클래스의 인터페이스는 클라이언트 계층에 제공되는 애플리케이션 작업의 집합을 선언하므로 정의상 거의 굵은 입자 인터페이스다. 따라서 인터페이스 세분성의 관점에서 보면 원격 호출에 적합하다.
원격 호출은 먼저 객체 분산이라는 비용을 치러야 사용할 수 있다. 서비스 계층 메서드 시그니처를 데이터 전송 객체를 받게 변경하려면 상당히 부담스러운 추가 작업을 해야 할 수 있다. 특히 도메인 모델이 복잡한 경우에는 이 추가 작업을 절대 과소평가해서는 안 된다.
우선은 로컬로 호출할 수 있고 도메인 객체를 받는 메서드 시그니처를 사용하는 방식으로 시작하는 것이 좋다. 원격이 꼭 필요하면 서비스 계층에 원격 파사드를 넣거나 아니면 서비스 계층 객체에서 원격 인터페이스를 구현하면 된다.
자바 구현
서비스 계층 클래스는 도메인 파사드 방식과 작업 스크립트 방식에서 모두 POJO나 상태비저장 세션 빈으로 구현할 수 있다. 두 방법은 테스트하기 쉽다는 장점과 트랜잭션 제어가 용이하다는 장점이 있다. J2EE 상에서 서비스 계층을 만들 때 선호하는 방법은 EJB 2.0 상태 비저장 세션 빈과 로컬 인터페이스를 사용하고 작업 스크립트 방식으로 POJO 도메인 객체 클래스에 위임하는 것이다. EJB가 분산된 컨테이너 관리 트랜잭션을 제공하기 때문에 상태 비저장 세션 빈으로 서비스 계층을 구현하면 아주 편리하다.
서비스 계층과 세션 파사드 패턴의 차이를 명확하게 해둘 필요가 있다. 세션 파사드는 엔터티 빈에 원격 호출이 너무 많을 때 성능 저하를 방지하는 방법으로 고안됐다. 반면 서비스 계층의 역할은 팩터링으로 분리해 중복을 방지하고 재사용성을 향상하기 위해 만들어졌으며, 특정 기술에 얽매이지 않는 아키텍처 패턴이다.
사용 지점
서비스 계층의 장점은 여러 종류의 클라이언트에 제공하는 작업의 공통 집합을 정의하고 각 작업에 대한 애플리케이션의 응답을 조율한다는 것이다. 따라서 비즈니스 논리를 사용하는 클라이언트 종류가 둘 이상이고, 유스 케이스의 복잡한 응답에 여러 트랜잭션 리소스가 포함하는 경우에는 서비스 계층을 활용하는게 좋다.
사용할 필요가 없는 경우는 비즈니스 논리를 사용하는 클라이언트가 한 종류밖에 없고 이 유스 케이스 응답에 여러 트랜잭션 리소스가 포함되지 않은 경우이다.
'Study > 엔터프라이즈 애플리케이션 아키텍처 패턴' 카테고리의 다른 글
제12장 객체-관계형 구조 패턴 : 포함 값 (0) | 2023.03.28 |
---|---|
제12장 객체-관계형 구조 패턴 : 연관 테이블 매핑 (0) | 2023.03.28 |
05장 - 동시성 (0) | 2023.02.14 |
03장 - 관계형 데이터베이스 매핑 02 - 데이터 읽기 / 구조적 매핑 패턴 (0) | 2023.02.08 |
03장 - 관계형 데이터베이스 매핑 01 - 아키텍처 패턴 / 동작 문제 (0) | 2023.02.07 |