Sharp Architecture는 ASP.NET MVC와 NHibernate를 이용하여 유지보수가 용이하고 견고한 웹 애플리케이션을 위한 뼈대를 제공해주는 일종의 reference architecture라 할 수 있다. Sharp Architecture가 어떠한 구조로 ASP.NET MVC와 NHibernate를 엮고 있는지 살펴보면서, 만든 이 Billy McCafferty가 어떤 아이디어로 이를 제안했는지, 혹은 내가 만약 향후에 다른 프레임웍의 조합을 통해 프로젝트를 진행할 경우 활용할 수 있는 프랙티스는 없는지 알아보기로 하자.

1. Sharp Architecture

그림에서 보듯이 Sharp Architecture (#arch)는 두 개의 애플리케이션 한 개의 워드 문서로 구성되어 있다.

- ProjectBase Project : #arch의 기본이 되는 기능 제공하는 기반 구조
- NorthWindMvc Project : ProjectBase 기반의 일종의 샘플 애플리케이션
- Base_Architecture_and_Development_Guidelines.doc : 설치 및 개발을 위한 가이드 문서로 구성되어 있다.

NorthwindMvc에서 ProjectBase를 referece 참조해서 개발된 것이며, 여기에 새로운 기능을 어떻게 TDD (Test-driven Development) 기반하에 개발할 수 있는지 차근차근 설명한 문서가 위에 언급한 워드 문서이다.
 

2. ProjectBase

ProjectBase는 크게 세 개의 서브 프로젝트로 구성된다.

2.1 ProjectBase.Core : 엔티티 객체 및 프레임웍 기본 기능 구현
   * ConcreteTypeAttribute.cs : IoC (Inversion of Control) 기능을 제공하며 #arch 0.6.x 버전까지 있었던 Spring.NET이 #arch 0.7.x 버전부터 빠지면서 IoC를 #arch 내에서 자체 구현하기 위해 제공하는 Attribute이다. 실제 사용법은 ProjectBase.Web의 ControllerFactory.cs에서 설명하기로 한다.
   * DesignByContract.cs : design by contract 방법론에 근거하여 코드를 작성하도록 이를 강제하기위해 조건 체크하는 로직을 제공한다.
   * IDao.cs : DAO 패턴을 따라서 data access 로직을 작성할 경우 공통적인 로직을 추상화시켜 담고 있는 최상위 인터페이스이며, Load(), Save(), Delete() 등 기본적인 CRUD에 관련된 메소드를 선언하고 있다. DAO 패턴의 인터페이스 역할을 하는 IDao를 왜 ProjectBase.Core에 넣은 이유는 마틴 파울러가 정리해 놓은 Separated Interface 패턴을 참조하면 좋을 듯 하다. 이유는 DAO 패턴을 구현한 ProjectBase.Data와 엔티티들에 관여하는 ProjectBase.Core 사이의 의존성을 해소하기 위해서 ProjectBase.Data의 DAO에 대한 인터페이스를 따로 분리하여 ProjectBase.Core에 넣음으로 인해 ProjectBase.Data에 대한 직접적인 의존성을 해소하고 있다. (의존성 해소가 목적이라면 분리한 인터페이스를 꼭 ProjectBase.Core에 넣어야 했을까... ) IDao 인터페이스는 ProjectBase.Data에 있는 GenericDao 클래스가 구현하고 있다. 내가 작성할 DAO를 MyCustomerDao라고 가정했을 때 이들 사이의 관계는 아래와 같습니다. 점선은 인터페이스 구현을, 실선은 클래스간 상속을 의미합니다. 
    * PersistentObject.cs : 엔티티 객체들은 모두 PersistentObject를 상속받아 작성한다. PersistentObject에는 모든 엔티티들이 대부분 사용하게되는 ID, Equals(), GetHashCode() 등이 구현되어 있다.

2.2 ProjectBase.Data : DAO 패턴과 NHibernate 세션 관리
   * GenericDao.cs : IDao 인터페이스를 구현하고 있는 base class로서 내부적으로는 NHibernate의 Session을 이용하여 데이터베이스 작업을 진행한다. 그림에서 보듯이 개발자가 작성하는 모든 Dao 클래스 구현의 기본 뼈대를 제공한다.
   * NHibernateSession.cs : NHibernate를 쉽게 사용할 수 있도록 하는 일종의 Utility 클래스로서 내부적으로 NHibernate SessionFactory와 Session 사용한다. 
  * DaoTests.cs : Dao 클래스의 단위 테스트를 위한 Helper 클래스로서 모든 Dao 클래스의 단위 테스트 클래스들은 DaoTests 클래스를 상속 받아 작성한다. DaoTests 클래스는 내부적으로 위에서 언급한 NHibernateSession 클래스를 이용하여 NHibernate Session이 제공하는 Transaction 기능을 사용한다. NUnit 단위 테스트의 [Setup] 과 [TearDown] 속성을 제공하여 Dao의 단위 테스트 시 초기 세팅과 테스트 후 리소스 정리 등을 제공하며 NHibernate의 트랜잭션 롤백 기능과 맞물려 단위 테스트 끝난 후에 데이터베이스를 롤백 시켜 테스트 이전 상태로 되돌리는 기능을 제공한다. 또한 NUnit의 Category Attribute에 "DB Test"를 추가하여 NUnit이 일괄적으로 테스트 케이스를 실행할 때 이 부류의 테스트는 DB 테스트임을 알려주어 단위 테스트시 제외하도록 하여 데이터베이스 관련 부가 작업으로 인한 전체적인 단위 테스트 소요 시간을 절약할 수 있다.

2.3 ProjectBase.Web : 웹 일반적인 기능 확장 및 ASP.NET MVC Controller Factory 제공
   * WebSessionStorage.cs : HttpContext에 NHibernate Session을 저장하여 이를 통해 세션 관리해주는 기능을 제공한다.
   * TransactionAttribute.cs : ASP.NET MVC의 Controller action method에서 사용할 수 있는 Action Filter로 작성하여 NHibernate 트랜잭션을 선언만으로 적용할 수 있도록 제공되는 Attribute
   * ControllerFactory.cs : ASP.NET MVC가 기본적으로 제공한는 DafaultControllerFactory를 상속받아 작성된 커스텀 Controller Factory로써, 예전에 Spring.NET이 제공했던 IoC 기능을 ProjectBase.Core의 ConcreteTypeAttribute의 도움을 받아 직접 구현하고 있다. 방식은 원시적일 정도로 심플하다. 모든 Controller 구현시 생성자에 IDao 타입의 파라메터를 받도록 하여 전달되어 지는 IDao 타입의 인터페이스를 검사하여 여기에 Attribute으로 명시되어 있는 ConcreteType을 조사한다. 이 같은 방식으로 생성하여야 할 구체적인 Dao 클래스를 알아낸다. 또한 생성해야할 Controller 클래스는 전달되어지는 controllerType을 통해 알 수 있다. 아래는 ControllerFactory 소스 코드의 일부로써 IoC가 행해지는 부분이다.

Sharp Architecture의 근간이 되는 세 개 서브 프로젝트의 구성 요소와 이들의 역할을 간단히 살펴보았다. 시장에 나와 있는 ASP.NET MVC와 NHibernate라는 잘 만들어진 프레임웍들의 조합이기에 구조 자체는 간단하며 이 두 프레임웍을 효과적으로 엮는 부분이 코드의 주된 내용이다.

다음 시간에는 ProjectBase를 이용하여 구현된 샘플 애플리케이션인 NorthwindMvc의 구조에 대해 간단히 살펴보기로 하자.

Posted by 장현춘