Using NHibernate: Introduction

2010.07.23 14:44 from ASP.NET
안녕하세요? 웹지니입니다.

최근 저는 회사에서 진행 중인 프로젝트에 유명한 ORM도구인 NHIbernate를 적용하고 있습니다. 사실 시작한지 얼마 되지 않아 많은 것을 알지는 못하지만 그래도 제가 경험했던 내용들을 토대로 간단하게 NHibernate를 소개하기 위해 짧은 연재를 진행하려고 합니다. 물론 초급 수준의 포스트가 되겠지만 그래도 많은 분들께 조그마한 도움이 될 수 있기를 바라면서 시작해 보겠습니다.

NHibernate란?

NHibernate는 이미 자바 진영에서는 오래전부터 활용되고 있는 Hibernate 프레임워크를 .NET 환경으로 포팅한 프레임워크입니다. NHibernate는 Linq To SQL이나 Entity Framework와 같은 ORM(Object-Relational Mapping) 프레임워크로 쉽게 말하자면 DB 스키마를 C# 객체로 매핑하여 개발자가 직접 SQL 쿼리를 작성하지 않고 객체 중심의 프로그래밍이 가능하도록 해주는 프레임워크입니다.

최근의 프로그래밍 개발 패턴을 살펴보면 종전처럼 DB 설계부터 시작하여 쿼리를 중심으로 애플리케이션을 구현해 나가는 Bottom-up 방식의 Data-First 패턴에서 모델 중심 혹은 데이터 중심으로 애플리케이션을 설계하고 이에 따라 애플리케이션과 DB를 구현해 나가는 Top-Down 방식의 Model-First 패턴이 주를 이루고 있습니다.

특히 DDD(Domain Driven Development) 방법론이 확산되면서 도메인 모델 패턴이 널리 알려지고 이와 같은 패턴을 통해 구현되는 애플리케이션의 수가 점차 늘어나면서 ORM 도구의 사용 역시 매우 활발하게 이루어지고 있습니다. 그렇다면 .NET 환경에서 선택할 수 있는 ORM 도구는 NHibernate가 유일했을까요? 물론 그렇지 않습니다. .NET 환경에서 ORM은 .NET 3.0의 Linq 기술과 함께 릴리즈된 Linq to SQL에 의해 알려지게 되었습니다.

또한 비교적 소규모의 단조로운 데이터베이스를 위한 Linq to SQL을 보완하기 위해 마이크로소프트는 Entity Framework(이하 EF)라는 또 다른 형태의 ORM 도구를 준비하여 릴리즈 하기도 했습니다. 그리고 EF는 .NET 4에 이르러 PI(Persistence Ignorance) 개념 등 진정한 의미의 도메인 모델 패턴을 지원하기 위해 큰 폭으로 발전하고 있습니다. 그럼에도 불구하고 제가 NHibernate를 선택한 까닭을 요약해 보면 다음과 같습니다.

1. Linq to SQL의 경우 1:1 관계만을 지원하여 복잡한 비즈니스 애플리케이션의 구현에 적합하지 않다.
2. Linq to SQL은 마이크로소프트 SQL Server만을 지원한다.
3. EF의 경우 1:N 관계를 지원하지만 마이크로소프트 .NET 프레임워크에서만 사용이 가능하다. (현재 Mono 프레임워크는 EF를 완벽하게 구현하고 있지 못합니다).
4. EF 역시 마이크로소프트 SQL Server만을 지원한다.  이 부분은 제가 잘못 알고있었기에 정정합니다. EF는 SQL Server 외의 다른 RDBMS벤더도 지원되고 있습니다. 제보(?)해주신 권효중님께 감사드립니다. ㅎㅎ
5. NHibernate는 이미 수 년 전부터 자바 진영에서 활용되어 온 이미 검증된 프레임워크이다.
6. NHibernate는 Mono 프레임워크를 지원한다.
7. NHibernate는 현존하는 거의 모든 RDBMS를 지원한다.
8. 아직 개발 중이긴 하지만 NHibernate의 3.0 버전에서는 HQL(Hibernate Query Language)를 기반으로 한 Linq 구문의 지원이 가능하다 (현재 릴리즈된 최신 버전은 2.1.2의 경우 Linq to NHibernate를 통해 부분적인 Linq 구문의 지원이 가능합니다. 그러나 Linq to NHibernate의 경우 HQL 기반이 아닌 NHibernate의 Criteria API를 기반으로 하고 있어 JOIN 등 여러 가지 구문을 지원하지 못합니다. 3.0 버전은 현재 알파 버전이지만 NHibernate의 소스 저장소에서 다운로드하여 빌드 후 사용이 가능합니다).

그렇습니다. 아시는 분은 아시겠지만 저는 Windows 서버 환경 뿐 아니라 리눅스 서버 환경도 고려한 제품을 개발 중이며 이에 따라 Mono 프레임워크의 지원 여부가 선택에 가장 큰 영향을 미쳤습니다. 그러나 실상 NHibernate 프레임워크는 Mono 프레임워크를 지원한다는 것 외에도 많은 장점을 가진 프레임워크입니다.

왜 ORM 도구를 사용해야 하는가?

.NET 개발자들에게 있어 ORM이라는 도구는 아직은 다소 생소한 도구라고 할 수 있습니다. 해외 개발자들은 그렇지 않겠지만 국내 개발자 중 대부분은 Linq to SQL을 통해 ORM이라는 개념을 처음 접하게 된 경우가 생각보다 많았습니다. 더군다나 Linq to SQL이 처음 .NET 개발자들에게 공개되었을 때 ORM 도구를 반대하던 - 보다 정확히 말하자면 Linq to SQL을 반대하던 - 개발자들은 크게 다음과 같은 점들을 ORM 도구의 단점으로 지적했습니다.

1. ORM 도구가 생성하는 SQL 구문의 변경이나 최적화가 불가능하다.
2. ORM 도구를 사용하게 됨으로써 DataSet과 같은 기존의 범용 클래스를 사용하는 대신 테이블의 각 컬럼과 매핑되는 속성을 가진 별도의 클래스를 구현해야 한다. 애플리케이션의 볼륨이 커질수록 이러한 클래스들의 수 역시 늘어날 것이며 이는 결과적으로 애플리케이션의 실행 성능에 영향을 미칠 수 있다.

여기에서 모델 객체를 추가로 구현해야 하는 부담에 대한 지적이 없었던 이유는 대부분의 ORM 도구들은 데이터베이스 테이블을 기반으로 모델 객체를 자동으로 생성하는 코드 자동 생성 기능을 제공하고 있기 때문입니다. 특히 Linq to SQL과 Entity Framework는 자동 객체 생성 기능을 훌륭하게 지원하고 있습니다. 그에 반해 NHibernate 프레임워크는 개발자가 직접 모델을 구현하고 모델과 테이블 사이의 매핑을 별도의 XML 파일로 구성해야 한다는 단점이 존재합니다. 사실 이런 부분은 생산성의 저하를 가져오게 마련입니다. 그러나 다행히 이런 문제는 Visual NHibernateFluent NHibernate와 같은 도구를 함께 사용하면 얼마든지 극복이 가능합니다.

다시 본론으로 돌아가 앞서 언급했던 단점들이 존재함에도 불구하고 왜 ORM 도구를 사용해야 하는지에 대해 다시 생각해 보겠습니다. 확실히 많은 수의 모델 객체와 이에 대한 매핑 정보를 유지해야 하는 것은 애플리케이션의 실행 성능에 부담을 줄 수 있습니다. 물론 쿼리 자체를 개발자가 임의로 최적화할 수 없다는 점도 단점이 될 수 있습니다. 그럼에도 불구하고 ORM 도구를 사용해야 하는 이유를 저는 다음과 같이 생각합니다.

1. 데이터베이스에 대한 추상화: 대부분의 ORM 도구는 여러 가지 RDBMS를 지원하며 각각의 RDBMS 벤더에 적합한 쿼리를 자동으로 생성합니다. 따라서 개발자는 여러 DBMS를 지원하는 소프트웨어를 개발하기 위해 DBMS에 특화된 쿼리를 매번 작성할 필요없이 객체 기반의 코드를 통해 어떤 DBMS든 사용이 가능하게 됩니다. 또한 데이터베이스에 대한 액세스가 추상화됨으로 인해 TDD(Test Driven Development) 방법론에 따른 테스트 용이성(Testability)을 확보하기가 쉽습니다.

2. 강력하게 형식화된 데이터 액세스: 예전에 DataSet 객체를 사용하는 경우 새로운 데이터를 추가하거나 기존 데이터를 수정하기 위해서는 반드시 해당 컬럼의 데이터 형식에 대해 알고 있어야 했습니다. 그러나 ORM 도구를 사용하게 될 경우 해당 객체의 속성을 통해 강력하게 형식화된 데이터 액세스 API를 구현할 수 있게 됩니다. 또한 이를 통해 비즈니스 규칙에 대한 유효성 검사를 보다 효율적으로 실행할 수 있습니다.

3. 개발 생산성의 향상: 상기 두 가지 항목만 보더라도 이미 개발 생산성이 몰라보게 향상될 수 있음을 깨달을 수 있습니다. 뿐만 아니라 개발자가 잘못된 타입의 데이터를 사용하거나 Null 값이나 객체에 액세스하는 등의 자잘한 실수를 보완할 수 있어 예기치 않은 버그의 발생 및 디버깅에 대한 노력을 최소화할 수 있습니다.

4. 유지보수성의 향상: ORM 도구를 사용하게 된다면 비즈니스 로직이 명확해 집니다. 기존의 방식대로라면 비즈니스 로직 중간에 SQL 쿼리나 저장 프로시저 호출이 포함되고 따라서 이러한 부분에 대한 추가 분석이 따라줘야 전체 로직을 분석할 수 있게 되는 반면 ORM 도구를 사용할 경우에는 DB 관련 로직이 비즈니스 로직에 개발 언어 형태로 포함되기 때문에 코드 분석이 보다 용이해 집니다. 특히 Linq 구문을 활용하게 된다면 더욱 명확해 지겠지요. 이렇게 비즈니스 로직이 명확해지면 코드를 유지보수하기도 매우 쉽고 편리합니다.

물론 저는 이 글을 통해 모든 애플리케이션에 ORM을 반드시 탑재해야 한다고 주장하는 것은 아닙니다. 어떤 도구든지 마찬가지겠지만 필요한 곳에 적절한 활용이 무엇보다 중요합니다. 특히 ORM을 통해 해결할 수 없는 방대한 양의 쿼리나 프로세스가 많은 국내 개발 현실을 비추어볼 때 ORM 도구를 활용하는 것이 적합한지에 대해서는 의구심을 품을 수도 있습니다. Linq to SQL이나 EF가 저장 프로시저를 객체의 메서드 형태로 사용할 수 있도록 하는 것이나 NHibernate가 HQL(Hibernate Query Language)이나 Native SQL을 직접 호출할 수 있도록 구현되어 있는 것도 바로 이런 문제를 보완하기 위해서가 아닐까요. 결론적으로는 이런 도구를 활용하는 여러분의 선택이 무엇보다 중요하다고 할 수 있겠습니다.

NHibernate 다운로드하기

그러면 본격적으로 NHibernate 프레임워크를 사용하기 위한 준비를 시작해 보겠습니다. 이 글을 작성하는 현재 NHibernate는 2.1.2 버전이 가장 최신 버전이며 NHibernate 프레임워크의 공식 웹사이트에서 다운로드가 가능합니다.

그림 1: NHibernate 프레임워크의 공식 웹사이트 (http://nhforge.org)

그림에서 표시된 [Download Now NH 2.1.2] 링크를 클릭하면 NHibernate 2.1.2 버전을 다운로드할 수 있습니다. ZIP 형식으로 압축된 파일이 다운로드되면 별도의 설치 과정은 필요치 않으므로 프로젝트에 어셈블리만 참조하면 곧바로 사용할 수 있습니다. 다운로드된 압축 파일을 풀어보면 아래와 같은 폴더가 존재하는 것을 볼 수 있습니다.

그림 2: NHibernate 프레임워크를 다운로드한 후 압축을 해제한 폴더의 모습

  • Configuration_Templates: NHibernate 프레임워크가 지원하는 DBMS별로 데이터베이스 연결을 위한 설정 예제 파일들이 제공되는 폴더입니다. 이 폴더의 파일들로 알 수 있듯이 NHibernate 프레임워크는 FireBird, Microsoft SQL Server, MySql, Oracle, PostgreSQL, SQLite 등의 RDBMS를 지원합니다.

  • Required_Bins: NHibernate 프레임워크를 사용하기 위한 필수 어셈블리 파일들이 제공되는 폴더입니다. 특히 이 폴더에는 Visual Studio에서 NHibernate의 Configuration 파일들을 작성할 때 인텔리센스를 지원하기 위한 XSD 파일들도 포함되어 있습니다.

  • Required_For_LazyLoading: Lazy-loading을 구현하기 위해 필요한 추가 어셈블리들이 제공되는 파일이 제공되는 폴더입니다. NHibernate의 Lazy-loading은 Castle의 DynamicProxy, LinFu, Spring.NET 등 세 가지 프레임워크를 지원합니다. 이러한 어셈블리들은 세 가지 중 원하시는 것을 선택적으로 사용하실 수 있습니다.
NHibernate 프레임워크와 Linq

앞서 다운로드한 NHibernate 2.1.2에서는 Linq 구문이 지원되지 않습니다. 따라서 2.1.2를 사용한다면 NHibernate의 Criteria API를 이용한 형태의 코드를 작성하여 모델 객체를 조작하게 됩니다. 그러나 Linq to NHibernate를 사용하면 제한된 범위 내에서 Linq를 사용할 수 있습니다. 또한 현재 개발 중인 NHibernate 3.0의 경우에는 HQL 기반의 Linq 기능을 구현하고 있어 Linq to NHibernate에 비해 더 폭넓은 범위의 Linq 구문을 지원받을 수 있습니다.

언제나 그렇듯 개발과 관련된 포스트는 예제 위주의 포스트로 구성하는게 쵝오-ㅅ-b지요. 다음 포스트부터는 간단한 예제 애플리케이션의 구현을 통해 NHibernate 프레임워크의 사용법을 차근히 익혀보겠습니다.







Posted by 웹지니 트랙백 0 : 댓글 12