본문 바로가기

IT 살이/04. 기술 - 프로그래밍

개발 프레임워크 만들기 대장정 34 - Spring.NET 트랜잭션 관리(Strategy 패턴)

연수 떠나기 전에 다 하지 못했던, Spring.NET 프레임워크 연재를 계속하기 위해서 다시 공부를 시작했다.

이번에는 Spring.NET이 트랜잭션을 지원하는 방식을 정리하려고 하고 있다. 그러나 이번 포스트의 토픽은 이것이 아니다. Spring.NET이 미들 티어의 트랜잭션 관리를 어떻게 하고 있는지를 설명하기 전에 패턴을 하나 미리 정리하는 것이 나을 것 같았다.

 

Strategy 패턴이 뭐여

 

달봉이도 이렇게 사용하는 것이 Strategy 패턴이구나 하고 이제서야 알게 되었다. 사실은 이런 패턴을 사용했던 것은 달봉이가 학교 다닐 때부터였다. 다음은 달봉이의 논문에 포함되어 있는 그림이다.

다른 것은 볼 필요없고, 붉은 박스 안을 보자. 교량을 건설하다 보면 어떤 특정 부분의 재료가 ‘빔(beam)’이라는 것이 사용될 수도 있고, ‘트러스바(trussbar)’라는 것이 사용될 수도 있다. 이런 부품으로는 어떤 것도 올 수 있다는 것이다. 그림에서 부품의 종류를 나타내는 마지막 박스는 점점(…)으로 채워져있는 것은 아직 개발되지 않은 부품이 나중에 사용될 수도 있다는 것이다.

이런 부품에 따라서 교량을 설계 또는 안정성 해석의 프로그램에 입력되는 값들이 달라지고 계산의 구체적인 로직이 조금씩 달라진다. 이 설계의 목적은 해석 모델의 부품은 언제든지 교체될 수 있어야 한다는 것이다.

요는 이렇다. 이런 부품들은 언제든지 변할 수 있으니 부품이 바뀌더라도 다른 부분의 코드는 수정이 없어야 한다는 것이다. 이런 시나리오가 바로 Strategy 패턴이 적용될 수 있는 부분이다.

근데 왜 Strategy라는 이름이 붙었을까? 검색을 해 보면 어딘가에 그 사연이 있겠지만 지금으로서는 달봉이도 모른다. 그러나 Strategy란 것이 교체 가능한 부품 하나 하나를 말한다고 한다. Strategy 패턴을 설명하는 wikipeadia의 설명에 따르면 Strategy를 policy라고도 한단다. 전체적인 컨셉(인터페이스)은 고정되어 있더라도 구체적인 전략이나 정책은 언제든지 바뀔 수 있는 것이다.

Spring.NET에서 다시 설명할 기회가 있겠지만, Spring.NET의 트랜잭션 관리를 예로 들어서 알아보자. Spring.NET의 트랜잭션 관리란 말은 새로운 트랜잭션 기술을 구현해서 제공하고 있다는 것은 아니다. 이미 구현되어 있는 기술들을 Strategy 패턴을 이용해서 언제든지 필요한대로 각 기술들을 사용할 수 있는 환경( 컨텍스트 )를 제공한다는 것이다. 트랜잭션을 처리할 수 있는 이미 구현된 기술들은 어떤 것들이 있나. 우리가 흔히 사용해온 COM+( Enterprise Services), ADO.NET, System.TransactionScope를 이용하는 방법들이 있겠고, NHibernate라는 것을 이용하는 방법도 있다. 그외 다른 방법도 있을 것이다. 각 트랜잭션 처리 구현 방법들은 각각의 장단점이 있을 수 있겠고 그 장단점에 맞게 사용해야 하는 환경이 있을 수 있다.

즉 트랜잭션을 처리해야 한다는 컨셉은 동일하나 그것을 구현하기 위해서 구현한 기술들은 여러 가지가 있을 수 있다. 그리고 프레임워크가 실제 기업에 적용되었을때는 어떤 기술을 사용될지는 알 수 없다. 이런 경우 프레임워크를 준비하는 입장에서 생각해 볼 수 있는 패턴이 바로 Strategy 패턴이라 하겠다. 익숙한 플러그인 개념과도 상통한다고 볼 수 있겠다.

만약 프레임워크단에서 if문이나 switch문을 이용한다면 문제가 아닐 수 없다. 다음과 같은 프레임워크 코드가 있다고 해보자.

string 트랜잭션 = 설정된트랜잭션기술


switch( 트랜잭션 )


    case : EnterpriseService
        EnterpriseService용 API를 이용한 트랜잭션 처리


    case( ADO.NET )
        ADO.NET API를 이용한 트랜잭션 처리


    case( TransactionScope )
        TransactionScope API를 이용한 트랜잭션 처리
    ...

 

만약 이 프레임워크가 case문에 없는 다른 트랜잭션 관리 기술을 지원해야 한다는 필요성이 제기된다면 프레임워크 코드를 수정해야 하나? 이미 이 프레임워크가 기업들에 배포된 경우라면?

 

UML 다이어그램

 

이제 현실적인 문제점과 이 패턴의 필요성에 대한 동기 부여는 되었을 것으로 보인다. 그럼 이 패턴을 좀더 이론적으로 정리해보자. 다음 그림은 wikipeadia에 있는 이 패턴의 UML 다이어그램이다.

오른쪽 상단에 Strategy라는 인터페이스가 있다. 이 인터페이스에는 필요한 컨셉 예를 들어서 트랜잭션을 처리할 수 있는 기술들이라면 최소한 이런 것들은 구현될 필요가 있다는 전체적인 컨셉을 미리 정의해 놓고 있다. 트랜잭션 시작, 트랜잭션 커밋, 트랜잭션 롤백 등. 구체적인

그리고 하단에 그 인터페이스를 구현하고 있는 실제적인 전략 구현 클래스들( ConcreteStrategyA, ConcreteStrategyB )이 있다. 이 클래스들은 인터페이스에서 정의한 기본 약속들을 자신들에 맞게 실제로 구현한다. 이 전략 구현 클래스들은 언제든지 필요하다면 확장될 수 있다.

좌측 상단 부분의 Context라는 것은 전략들의 기능을 사용하는 클라이언트 코드이다. 그러나 이 클라이언트 코드가 바라보는 것은 실제적인 구현 전략들이 아니라 인터페이스만을 참조하고 있다. 즉 클라이언트 코드 입장에서는 실제 구현 전략들에는 관심도 없고 그것들의 각각에 의해 영향을 받을 일도 없다는 것이다. 걔들이 하기로 한 일들( 인터페이스에서 정의한 약속)만 잘 해주면 되는 것이다. 참고로 만약 그림의 Context도 여러 종류가 있을 수 있다면 이것도 실제로 구현된 클래스가 되어서는 안될 것이다. 이것 또한 일부 구체적으로 구현될 부분은 빈 껍데기(?)로 되어 있는 타입이 되어야 할 것이다. 이때 인터페이스를 사용할것인가? 추상 클래스를 사용할 것인가? 추상 클래스 !
이것에 인터페이스와 클래스, 어떤 타입을 사용할 것인가에 대해서 이전 포스트에서 달봉이 나름대로 정리했었다. 참조할 수 있을 것이다.

앞의 UML 다이어그램에 맞는 예제 코드도 역시 wikipeadia에서 볼 수 있다.

 

Spring.NET의 적용

 

Spring.NET은 다음과 같은 방식으로 이 패턴을 적용하고 있을 것이다.

 

인터페이스 IPlatformTransactionManager가 전략 클래스들이 구현해야 하는 약속을 정의하고 있다. 

그림에서 보이는 실제 전략 클래스들의 이름은 Spring.NET의 실제 클래스명과는 다르다. 실제는 이 이름들보다 훨씬 길어서 간략하게 줄였다.

Spring.NET 프레임워크에서는 어떤 전략 트랜잭션 관리자를 사용할 것인가를 설정할 수 방법( configuration 설정 방법 또는 프로그램적인 방법 제공)을 제공하고 있다. 그럼 Spring.NET 프레임워크는 그 설정에 맞는 적절한 관리자를 로딩해서 트랜잭션 처리에 사용하게 된다. Spring.NET 프레임워크의 사용자는 어떤 트랜잭션 관리자를 사용할 것인가에 대한 설정만 하면 된다.

몇 시간의 여유가 있어서 근무 시간에 약간의 눈치를 보며 지금까지 머리속으로만 정리했던 것을 후다닥 작성한 포스트다. 잘못된 곳이 있을 수 있다. 이해하고 있는 부분이라면 그냥 넘어가도 좋고, 영 걸린다 싶으면 댓글 남겨주면 다시 한번 더 보도록 하겠다.