Midnight Peach의 필드 테스트와 개봉 박두

Midnight Peach 2009. 11. 1. 04:31

[주의]
이 글은 MP의 현재 버전 (3.X)에 맞지 않습니다.

단순 참고용으로만 활용하십시오

2009.7.20 일이 마지막 포스팅 날짜니, 근 백일 만의 포스팅이 되네요.

물론 짐작하시다시피, 화끈한 프로젝트에 한 발 수준이 아니라 온 몸을 푸욱 담그고 있었던 게 백일 간의 은둔의 변명이 맞습니다.

 

그 동안 로피스 플러스라는 제품을 만들었었는데요. 대형 로펌 (물론 개인 법률 사무소도)의 거의 모든 법률 업무를 처리할 수 있는 일종의 ERP 솔루션입니다.

개발 과정에서 프로그래밍에 대하여 좀 더 알게 된 부분도 많고, 몇 가지 디자인 패턴과 라이브러리를 개발하기도 하는 등, 나름 뜻 깊은 프로젝트였습니다만, 그 중 가장 큰 의미가 있는 것은 아무래도 Midnight Peach의 필드 테스트를 성공적으로 수행한 것이 아닌가 싶습니다.

 

테이블이 백여개 정도 되는 제법 규모가 있는 솔루션임에도 불구하고 LINQ와 MP를 사용하니, 데이터베이스 핸들링 작업, 즉 데이터 액세스 레이어는 날로 먹다시피 했습니다.

예를 들어 아래는 사건 검색 컨트롤 입니다.

각각 AND 조건으로 결합되는 14가지의 검색 조건이 있습니다. 그리고 결과는 8개의 테이블에서 뽑아 오는데, 이 중 일부는 두 단계 혹은 세 단계의 조인을 거쳐야 합니다.

LINQ를 사용할 수 없다면, 각각의 검색 조건을 매개변수로 받아 동적으로 쿼리를 조립하는 프로시저(동적 쿼리 프로시저)를 만드는 게 최선(어쩌면 유일?)일 것 같은데요.

아마도 이 프로시저의 길이는 족히 몇 백 라인, 어쩌면 천 라인이 넘을 것 같습니다.

 

이런 끔찍한 동적 쿼리 프로시저는 생각만 해도 예전 기억이 떠올라 경기를 일으킬 분이 많으실 것 같은데요, 굳이 상처를 헤집어 소금을 뿌리는 심정으로 문제점들을 이야기해보자면,

  1. 유지보수가 극히 어렵습니다. 특히 작성자가 다른 사람이라면 불가능에 가깝다고도 할 수 있습니다.
  2. 코드의 가독성이 무척 낮아, 코드 파악이 힘듭니다.
  3. 동적으로 쿼리를 조립하는 형태이므로, 컴파일 타임의 체크가 불가능합니다. 특히나 인텔리센스의 도움을 받을 수 없기 때문에 몇 천 라인 중에 오타 한 글자만 있더라도 실행 전까지는 알 수 없습니다.
  4. 디버깅이 불가능하거나 극히 어렵습니다.
  5. 저장 프로시저임에도 불구하고 실행계획을 저장할 수 없기 때문에, 동적 쿼리가 아닌 프로시저나 parameterized 쿼리에 비해 성능이 좋지 않습니다.
  6. 따로 방비를 하지 않으면 SQL injection 공격에 취약합니다.

 

하지만 이 모든 문제가 LINQ를 사용하면 해결이 됩니다.

물론 LINQ 자체가 가진 장단이 있고, LINQ에 대한 각 개발자의 호오가 분명 있을 테지만, 적어도 위에서 말한 말 그대로 ‘끔찍한’ 동적 쿼리 프로시저를 만들지 않아도 된다면, LINQ는 충분히 고려해볼 만한 가치가 있는 기술이라는 생각이 듭니다.

 

참고로, 단순 비교하기에는 무리가 있겠지만, 위의 검색 메서드를 MP가 생성한 프레임웍의 도움을 받아 LINQ로 구현하는 데 한 시간이 채 걸리지 않았습니다. 라인 수도 70 라인 정도로 짧았고요.

(사족이지만, 이는 제가 평생 만든 메서드 중 가장 긴 것인데, 사실 70 라인도 개발자가 직관적으로 코드를 장악하기에는 긴 편입니다.)

 

DataReader를 이용한 저수준(수동) 구현, 형식 있는 (혹은 없는) 데이터셋의 사용, 데이터셋 대신 비지니스 오브젝트 (엔터티)를 사용하되 Data Access Application Block과 같은 라이브러리나 NetTiers 같은 코드 생성기의 도움을 받는 방법, CSLA.NET과 같은 프레임웍의 도입, NHibernate 같은 ORM 툴 까지, 그간 데이터 액세스 레이어를 구축하는 데 있어 참 많은 기술들을 사용하여 보았습니다.

하지만 이번 프로젝트에서의 적용을 통해 저는 LINQ가 이 모든 기술의 정점에 있다는 확신을 가지게 되었습니다.

정점에 있다니까 ‘유사한 것 중 최고’ 라는 느낌이 드는데, LINQ는 다른 기술들과 본질적으로 다릅니다. 그래서 ‘더 좋다’가 아니라 패러다임 자체가 다르다고 표현해야 되지 않을까 싶습니다.

 

아주 추상화시켜서 이야기하자면, 프로그램 언어는 데이터와 이에 대한 연산으로 이루어져 있습니다.

이 중 데이터는 메모리의 휘발성 때문에 저장소에 영속화(persistent) 되어야 할 필요가 있는데, 이 저장소에는 여러가지가 있습니다.

우리가 필드에서 개발하는 대부분의 응용 프로그램들은 DBMS를 저장소로 사용하지만, 이는 파일 시스템이 될 수도 있고, 네트웍을 통해 들어오는 스트림이 될 수도 있습니다.

그렇다면 프로그램이 데이터를 연산하기 위해서는 저장소에 있는 데이터를 메모리로 가져와야 하는데(쿼리), 저장소가 무엇이냐에 따라 이 쿼리 방법이 너무나 상이하고, 또 프로그램 언어 자체에는 이 기능이 없다는 것이 문제가 됩니다.

(예컨데, DataSet을 통해 DB의 데이터를 가져오는 것은 C#의 기능이 아닙니다. FileStream 라이브러리를 통해 파일의 데이터를 가져오듯이, DataSet 클래스 라이브러리를 통해 DB에 접근하는 것이지요)

 

LINQ의 목표는 이 상이한 데이터 쿼리 방법들을 언어 자체의 기능으로 통합하는 것이고, LINQ의 정식 명칭인 Language INtegrated Query가 의미하는 바도 바로 이것입니다.

그리고 C#의 설계자인 Anders Hejlsberg가 LINQ에 대해 인터뷰하면서 ‘(LINQ는) 쿼리와 집합(역주:데이터) 연산을 닷넷 언어의 주요 구성 요소로 만든다’고 한 말도 이런 맥락에서 이해할 수 있겠습니다.

(http://channel9.msdn.com/posts/scobleizer/Anders-Hejlsberg-LINQ/)

 

필드 테스트를 통해 MP의 안정성이라던가 사용편의성 같은 것들을 체크해 보았으니, 이제 MP를 발표할 때가 된 것 같습니다.

여태까지는 블로그에만 포스팅을 하고 외부에는 일절 알리지 않고 있는데, 블로그에도 아직 MP의 기능 반 정도가 소개되지 않았습니다.

모든 기능에 대한 매뉴얼과 MP를 사용한 샘플 애플리케이션 정도만 준비되면 공식적으로 발표를 할 생각입니다.

기대해 주세요.

: