은행의 계좌 이체 서비스를 생각해보면 '잔고 확인 -> 받는 사람 확인 -> 이체 실행 -> 잔고 감소'의 로직 순서가 하나의 로직으로 처리되어야 하고, 이 과정에서 한번이라도 오류가 발생하면 모든 처리가 취소되고, 모든 과정이 성공해야 비로서 처리가 완료된다. 즉, All-or-Nothing 개념의 트랜잭션 처리가 되는 것이다.
트랜잭션 스크립트(Transaction Script) 패턴은 이렇게 하나의 트랜잭션으로 구성된 로직을 단일 함수 또는 단일 스크립트에서 처리하는 구조를 갖는다. 그래서 패턴의 이름이 트랜잭션 스크립트이다. 트랜잭션 스크립트는 JSP를 처음 공부하는 사람들이 가장 먼저 몸에 습득하는 패턴으로서 모델 1 구조가 가장 간단한 트랜잭션 스크립트 패턴에 해당한다.
public class SomeTransactionScript {
public Result do(...) {
try {
SomeTransaction tx = ...;
tx.begin();
// 1. 잔고확인
...
// 2. 받는 사람 확인
...
// 3. 이체 실행
...
// 4. 잔고 감소
...
tx.commit();
} catch(..) {
tx.rollback();
...
} finally {
...
...
}
}
}
트랜잭션 스크립트 방식의 최대 장점은 구현이 매우 쉽다는 것이다. ASP.NET이나 JSP 등이 프로그래밍 언어에 기반하고 있는 스크립트 언어임에도 불구하고 사람들은 ASP나 JSP가 프로그래밍 언어보다 쉽다고 느끼는데, 그 이유는 트랜잭션 스크립트 방식의 구현 방법의 단순함 때문이다. 스트러츠와 같이 MVC 패턴과 커맨드 패턴을 함께 사용하더라도 이러한 단순함은 그대로 유지되기 때문에, 스트러츠 코드에 조금만 익숙해지면 손쉽게 스트러츠로도 트랜잭션 스크립트 패턴을 구현할 수 있게 된다.
하지만, 트랜잭션 스크립트로 구성된 어플리케이션은 비즈니스 로직이 복잡해질수록 난잡한 코드를 만들게 된다. 특히, 트랜잭션 스크립트 코드는 애초에 도메인에 대한 분석/설계 개념이 약하기 때문에 코드의 중복 발생을 막기 어려워진다. 또한, 트랜잭션 스크립트를 사용하게 되면 쉬운 개발에 익숙해지기 때문에 공통된 코드를 공통 모듈로 분리하지 않고 복사&붙이기 방식으로 중복된 코드를 만드는 유혹에 빠지기 쉽다.
도메인 모델을 사용할 때 최대 관건은 도메인 모델과 데이터베이스 테이블 사이의 매핑을 어떻게 처리할 것인가 하는 것이다. 웹 어플리케이션의 (대부분의) 비즈니스 로직은 데이터 삽입, 데이터 조회, 데이터 변경 그리고 데이터 삭제와 관련되어 있기 때문에, 비즈니스 로직을 자바 객체로 표현한 도메인 모델에 알맞은 데이터베이스 매핑 패턴을 사용하는 것이 좋다. (데이터 매퍼를 사용함으로써 데이터베이스로부터 도메인 모델을 독립적으로 유지할 수 있으며, 유지보수도 간단하게 만들 수 있다.)
객체 지향 설계와 더불어 익혀야 할 것은 도메인 모델과 테이블 사이의 매핑을 처리해주는 기법이다. 이 매핑 처리 기법은 '단일객체-단일테이블'의 1-1 매핑에서 '다수객체-다수테이블'의 n-n 매핑까지 다양하게 존재하며, 또한 데이터베이스 매핑을 지원해주는 API도 상업용에서 오픈소스까지 다양하게 존재한다.
아직까지 널리 사용되는 도메인 모델은 EJB의 엔티티빈과 세션빈과 같은 단순 도메인 모델이다. 즉, 테이블과 1대 1로 매핑되는 엔티티가 존재하고 엔티티를 사용해서 로직을 수행하는 세션이 존재하는 단순 도메인 모델이 대세를 이루고 있다. 특히 EJB의 경우 CMP와 EJB QL(Query Language)을 통해서 데이터베이스 매핑을 처리할 수 있기 때문에 도메인 모델의 비즈니스 로직에 집중할 수 있도록 도와주는 장점이 있다.
도메인 모델(Domain Model)은 흔히 말하는 객체 지향 분석 설계에 기반해서 구현하고자 하는 도메인(비즈니스 영역)의 모델을 생성하는 패턴이다. 도메인 모델은 비즈니스 영역에서 사용되는 객체를 판별하고, 객체가 제공해야 할 목록을 추출하며, 각 객체간의 관계를 정립하는 과정을 거친다. 명사와 동사를 구분해서 명사로부터 객체를 추출해내고, 동사로부터 객체의 기능 및 객체 사이의 관계를 유추해낸다.
객체를 기반으로 하는 도메인 모델의 주요 특징은 데이터와 프로세스가 혼합되어 있다는 것이며, 객체 간의 복잡한 연관 관계를 갖고 있고, 상속 등을 통해서 객체의 기능과 역할을 확장할 수 있다.
<%
...
try {
SomeTransaction tx = ...;
tx.begin();
...
DB에 데이터 기록
...
tx.commit();
// 성공하면 이메일 발송
...
} catch(..) {
tx.rollback();
...
} finally {
...
...
}
%>
도메인 모델의 장점은 역시 객체 지향에 기반한 재사용성, 확장성, 그리고 유지 보수의 편리함에 있다. 일단 도메인 모델을 구축하고나면 (필요에 따라 약간의 수정이 필요하겠지만) 언제든지 재사용할 수 있다. 예를 들어, 한번 커뮤니티(클럽, 게시판 등) 도메인 모델을 구축하고 나면 비슷한 커뮤니티 시스템에 대해서 도메인 모델을 재사용할 수 있게 된다. 또한, 상속/인터페이스, 더 나아가 컴포넌트 개념을 바탕으로 도메인 모델을 개발하게 되면 무한한 확장성을 갖게 된다.
도메인 모델의 단점은 하나의 도메인 모델을 구축하는 데 많은 노력이 필요하다는 것이다. 객체를 판별해내야 하고 객체들 간의 관계를 정립해야 하며, 더 나아가 객체와 데이터베이스 사이의 매핑에 대해서 고민해야 하기 때문이다. 이는 이론과 경험을 함께 겸비하지 않으면 쉽게 풀수 없는 문제이기 때문에, 도메인 모델에 능숙한 개발자가 팀에 없을 경우 도메인 모델을 구축하는 것 자체가 힘들어질 수도 있다.