효율적인 테스터의 7가지 습관

효율적인 테스터의 7가지 습관
(The Seven Habits of Highly Effective Testers)

원문 URL (URL of the original article): http://www.qaguild.com/weekly_article.php?id=35

이 글은 글의 원 저자인 Steve Miller의 구두 허락 하에 한국어로 번역되고, 개인 블로그에 포스팅되었습니다.
This article has been translated into Korean language with the permission of the original auther, Steve Miller.

Stephen R. Covey가 1989년에 쓴 성공하는 사람들의 7가지 습관이라는 책이 있습니다. 이 책은 수백만명의
사람들이 일과 인생의 효율성에 있어서 진정한 상호 의존성(interdependent effectiveness)을 성취하는데 많은
도움을 주었습니다. 이 글을 통해 효율적인 테스터가 취할 수 있는 7가지 좋은 습관에 대해 제시하고자 합니다. 이 7가지 습관을
요약하자면 다음과 같습니다.

  1. 적극적인 자세를 가질 것 (Be proactive)
  2. 끝을 염두에 두고 시작할 것 (Begin with the end in mind)
  3. 기본적인 것들을 먼저 시작할 것 (Put first things first)
  4. 윈/윈 전략을 취할 것 (Think Win/Win)
  5. 이해받으려 하기 보다 먼저 이해하십시오. (Seek First to Understand, Then to be Understood)
  6. 시너지를 낼 것 (Synergize)
  7. 날을 날카롭게 할 것 (Sharpen the Saw)

습관 1 – 적극적인 자세를 가질 것 (Be proactive)

떤 소프트웨어 프로젝트에 있어서든, 테스터의 목표는 소프트웨어가 높은 수준의 품질로 릴리즈되는 것입니다. 소프트웨어 프로젝트가
낮은 품질로 인해서 실패한다면, 그 요인이 무엇인지 분석을 해야 합니다. 이 때 테스터는 적극적으로 분석을 할 수도 있지만
소극적인 자세를 취할 수도 있습니다. 만약 소극적인 자세를 취한다면 아마도 비난할 다른 사람 또는 그렇게 될 수밖에 없었던
상황과 환경을 찾을 것입니다. 반대로 적극적인 자세를 취한다면 우선 그 실패에 대한 책임을 지고 미래의 프로젝트들에서 그 문제가
재발하지 않도록 하기 위한 방법을 찾을 것입니다.
모든 프로젝트는 종료 시점에 “포스트 모텀 (Post mortem)”
또는 “Retrospective”를 수행함으로서 그 프로젝트에서 무엇이 성공적으로 이루어졌고 무엇이 많이 부족했었는지를
공개적으로 토론합니다. 미래의 프로젝트에 있어서 적극적인 자세를 취할 수 있는 몇가지 아이디어를 제시합니다.

1.
소프트웨어 요구사항에 대해 책임감을 가지십시오. – 빈약한 요구사항 정의와 관련하여 다른 사람을 비난하지 마십시오. 대신 관련
팀과 함께 요구사항 정의가 완벽하게, 정확하게, 그리고 테스트 가능하게 작성되었는지 적극적으로 확인하십시오.
2. 추적성을
확보하십시오. – 테스트 케이스를 작성할 때 어떤 요구사항에 대해 어떤 테스트 케이스가 만들어졌는지 추적할 수 있는 매트릭스를
만들면 테스트 케이스의 커버리지, 테스트 적합성 (testability), 완전성을 분석하는데 많은 도움이 됩니다. 테스트
케이스 작성자가 요구사항을 정확하게 이해했는지 그리고 작성된 테스트 케이스가 적절한 커버리지를 갖는지 리뷰하기 위해 적극적으로
팀 미팅을 주최해야 합니다.
3. 효율적으로 커뮤니케이션 하십시오. – 테스팅 기간 동안 프로젝트 구성원 모두가 테스트
작업의 진행 상황을 공유해야 하는 것은 매우 중요합니다. Email이나 포럼을 통해 매일 매일의 테스트 진행 상황을
공유하십시오. 결함 건수, 요구사항 커버리지, 수행된 테스트 케이스 건 수, Passed/Failed된 테스트 케이스 건 수 등
사용 가능한 다양한 메트릭(Metrics)을 사용하십시오.
4. 발견한 결함을 효율적으로 설명하십시오. – 결함을 설명할
때는 결함 재현 절차와 예상 결과 등을 포함하여 훌륭한 결함 설명을 작성하기 위해 공을 들여야 합니다. 스크린샷이나 기타 사용
가능한 정보는 모두 사용하여 결함에 대해 설명하십시오. 이를 잘 지키면 QA와 관련된 재작업을 최소화할 수 있습니다.


습관 2 – 끝을 염두에 두고 시작할 것 (Begin with the end in mind)

프트웨어 프로젝트와 관련하여 여러분의 최종 목표는 고객의 요구를 만족하는 좋은 품질의 소프트웨어를 제공하는 것일 것입니다.
코딩이 시작되기 전에 반드시 이 프로젝트가 성공했다고 결정할 수 있는 결정 기준 (success criteria)을 만들어야
합니다. 예를 들어, 다음과 같은 기준을 설정할 수 있습니다. – 소프트웨어가 특정 결과물을 생성해내는가, 알려진 결함이
해결되었는가(또는 소수의 중요도 낮은 결함은 허용), 문서화가 잘 되었는가, 사용하기 쉬운가, 기타 등등. 초기 단계에 결정
기준을 설정함으로서 프로젝트 진행 도중에 수시로 프로젝트가 성공적으로 수행되고 있는지 검토할 수 있습니다. 결정 기준을 정의할
때에는 모든 팀 멤버 (PM, 테스터, 자동화 엔지니어, 개발자, 문서화 전문가 등)로 부터 도움을 구하십시오. 개인이 아닌
팀으로서의 시각으로 성공 결정 기준을 확립한다면 더 훌륭하고 많은 정량적인 기준을 확보할 수 있을 것입니다.

습관 3 – 기본적인 것들을 먼저 시작할 것 (Put first things first)

양한 작업들에 대해 우선순위를 부여하는 것은 매우 중요합니다. 일을 할 때는 가장 중요한 작업부터 시작해서 덜 중요한 작업들로
진행해야 합니다. 예를 들어, 네거티브 테스팅(Negative Testing)이 일반적인 소프트웨어 사용자의 사용 패턴이 아닌
특수한 사용 시나리오의 경우에 대해 … 한다는 것은 모두가 동의하고 인정합니다. 그러나 포지티브 테스팅(Positive
Testing)과 비교해봤을 때 네거티브 테스팅은 훨씬 덜 중요합니다.따라서 테스트를 시작할 때에는 미리 설계된 시나리오대로 잘
동작하는지에 대한 테스트를 먼저 시작하고, 또 이러한 테스트를 더 집중적으로 수행하십시오. 이 작업이 완료된 후에 네거티브
테스팅을 진행하는 것이 좋습니다. (경계 테스팅, 부적절 데이터 입력, 오버플로우, 인젝션 등)

습관 4 – 윈/윈 전략을 취할 것 (Think Win/Win)

은 조직에서 개발팀과 테스팅팀은 서로간에 비난하고 책임 소재를 돌리면서 팀간의 긴장감을 조성한다. 이는 상당히 파괴적이며
소프트웨어의 품질과 UX(User Experience)에 좋지 않은 영향을 미칠 수 있다. 개발팀과 테스팅팀은 공동의 목표를
가져야 한다. (고객이 최상의 품질의 소프트웨어를 가질 수 있게 하는 것) 이것이 공동의 목표가 될 때 모든 팀 멤버는 서로를
도울 수 있는 마인드를 가질 수 있게 되고 결국 훌륭한 품질의 소프트웨어가 완성되어 고객도 행복해지고 그로 인해 팀 멤버들도
성취감을 얻을 수 있다. 상호 신뢰의 분위기를 조성하고자 한다면 윈/윈할 수 있는 팀을 육성해야 한다. 이에 대한 몇가지 팁이
있다.

1. 지식 공유 – 여러분의 지식을 혼자 갖고 있지 말고 다른 사람들과 적극적으로 나누십시오.
2. 소셜라이즈(Socialize)하십시오 – 회사의 다른 팀 멤버들과 함께 점심 식사를 하십시오. 그들에 대해 더 배우고, 그들의 취미나 개인적인 목표 등에 대해 관심을 가지십시오.
3.
다른 사람들을 격려하십시오 – 타인이 훌륭하게 업무를 해내었다면 그 사람을 칭찬하고 격려하는데 인색하지 마십시오. 여러분의
(또는 그 사람의) 조직장에게 그 사람이 얼마나 잘 하고 있는지 말하십시오. 그 사람의 노력에 대해 얼마나 감사해하고 있는지
말하십시오.
4. 바쁜 팀 멤버들에게 도움을 주십시오 – 업무로 인해 많이 바쁜 팀 멤버들을 보면 그 일에 함께 뛰어
들어서 도움을 주십시오. 아마도 여러분이 나중에 도움이 필요할 때가 있을 것이므로 도움을 배푸는 것은 윈/윈 관계를
만들어나가는데 큰 도움이 됩니다.

습관 5 – 이해받으려 하기 보다 먼저 이해하십시오. (Seek First to Understand, Then to be Understood)

리 대부분은 우리 의견이 전달되기를 너무나 원하는 나머지 대화를 끊어버리고 상대방으로 부터 들으려하지 않는 아주 나쁜 습관을
갖고 있습니다. 모든 테스터와 팀 멤버는 서로 다른 다양한 경험과 시야(perspectives), 동기(motivations)를
갖고 있습니다. 어떤 문제를 해결하기 이전에 해결해야 할 문제를 완벽하게 이해하기 위해서 주의깊고 적극적으로 듣는 자세가
필요합니다. 모든 사실(facts)을 충분히 갖게 되었다고 느끼면 다양한 해결 방법을 생각해내십시오. 선택 가능한 몇가지 옵션을
가져감으로서 다양한 상황에서 여러가지 대안을 생각할 수 있고 더 낳은 협의를 할 수 있습니다. 만약 어떤 접근법에 대해 동의하지
않는다면 그 접근법을 제안한 사람을 공격하지 마십시오. 대신 여러분의 과거 경험에 기반해서 왜 더 낳은 접근법이 존재할 수
있는지 설명하십시오.

습관 6 – 시너지를 내십시오 (Synergize)
팀의 시너지를 발휘하는데 있어서 가장 중요한 것은 팀 협업입니다. 시너지를 낼 수 있는 팀은 서로 다른 능력과 서로 다른
백그라운드와 서로 다른 시야를 가진 다양한 멤버들로 구성됩니다. 이런 다양성 가운데서 최대한의 시너지를 내려면 도구의 사용이
중요합니다. 고도로 협업적인 (Highly Collaborative) 팀은 그들의 달력 (스케줄)를 공유하고 각 구성원의 현
상황을 적극적으로 포럼에 올려서 모두가 다른 사람들이 지금 무엇을 하고 있고 무엇을 성취하고 있는지 알게 하는 것으로서
커뮤니케이션합니다. 이런 팀은 각 구성원이 각 날짜마다 수행한 작업들과 업무를 수행한 시간, 그리고 어떤 작업을 수행하기까지
계획되었던 시간에 대해 남은 시간 등을 기록합니다. 또한 이러한 팀에서는 각 구성원들이 업무를 수행하면서 배우게 된 것들을
최대한 잘 설명할 수 있는 문서를 생산해내고 이를 공유합니다.

습관 7 – 날을 날카롭게 할 것 (Sharpen the Saw)
생산적인 테스터들은 계속해서 테스팅 기술들을 연마하고 새로운 기술과 베스트 프랙티스와 다양한 접근법들을 배우는 것을 좋아합니다.
그들은 지식에 대한 목마름을 갖고 가능한 모든 테스팅에 대한 책들을 읽습니다. 그들은 자신들의 업무를 쉽게 할 수 있는 방법을
배웁니다. (테스트 케이스를 자동화하고, 베스트 프랙티스를 적용함으로서 QA타임을 최소화하는 한편 소프트웨어 품질을 최대화함.)
이들은 QA Guild나 Sticky Minds 또는 다른 테스팅 커뮤니티에 계속적으로 참여합니다. 그러나 역시 이들은 언제
인생을 즐길지도 압니다. 훌륭한 휴가나 좋은 취미나 활동을 함으로서 방전된 배터리를 충전합니다.

저자에 대하여 (About the author)
Steve Miller는 Pragmatic Software의 사장이자 CEO이며 회사의 전략적 목표를 설정하고 이끌어가는 역할을
수행합니다. Pragmatic Software의 주력 제품은 소프트웨어 개발 생명 주기의 모든 phase를 관리할 수 있는
어플리케이션 라이프사이클 매지니먼트 (ALM) 도구인 Software Planner입니다.

SharpDevelop: 닷넷 무료 IDE


(클릭하면 원본 이미지 뜸..!!)

닷넷 기반 프로젝트에 있어서 고가의 MS Visual Studio 환경이 필수적이라는 고정관념을 깨주는 아주 훌륭한 무료 IDE입니다.
닷넷과 자바는 아주 닮아서 닷넷도 자바처럼 자신의 취향에 맞는 IDE를 선택할 수 있는… 심지어는 단지 텍스트 에디터만으로도 간단한 닷넷 어플리케이션을 만들 수 있겠다 생각했는데 역시 무료 IDE가 있다는걸 발견했습니다.
아직 써보진 않았지만 그냥 스크린샷만 보더라도 웬만한 프로젝트에서는 그냥 가져다 써도 될만큼은 되는것 같은..
물론 한글 버전이 없다는건 어쩔 수 없겠죠..

얼마전 자바 기반 ORM 프레임워크인 Hibernate를 그대로 닷넷으로 포팅한 NHibernate를 접해봤는데 NHibernate에 이어서 IDE까지.. 닷넷도 점점 오픈 소스 프로젝트들이 많아져 가고 있는것 같아 기대가 됩니다.

http://www.icsharpcode.net/OpenSource/SD/
SharpDevelop은 위 URL에서 다운받을 수 있음…

#develop (short for SharpDevelop) is a free IDE for C# and VB.NET projects on Microsoft’s .NET platform.


NHibernate 가이드

본 블로그 글의 출처는
http://network.hanbitbook.co.kr/view.php?bi_id=1118

이며 저자는 한동훈 입니다.
This blog entry is from http://network.hanbitbook.co.kr/view.php?bi_id=1118





ASP.NET 뿐만 아니라 다양한 웹 프로그래밍 환경에서 가장 반복적인 부분은 화면상의 컨트롤에 값을 설정하고, 값을 가져오는 일이다. 이와 같은 작업을 보다 편리하게 할 수 있는 방법은 없을까? 웹 페이지상의 각 요소에 값을 자유자재로 넣으려면 전체 HTML 문서 구조를 해석해서 어느 요소에 어떤 값을 넣을지를 결정해주는 작업을 해야한다. 이렇게 복잡하게 할 바엔 직접 코딩할래!라는 개발자가 대부분이다.

또한, DB에 값을 가져오거나 저장하는 일을 단순하게 할 수 있는 방법은 없을까? 라는 물음이다. 물론, Data Access Layer를 담당하는 클래스를 작성해서 DB작업을 단순하게 해주지만 쿼리 작성, 값의 유효성과 같은 것들을 자동화해주지는 못한다.

MS가 Data Access Bulilding Block을 제공한다해도 여전히 반복적인 작업을 해야한다. 이에 대한 대안은 과연 없을까?

컨트롤 처리

ASP.NET에서는 웹 페이지의 각 요소를 컨트롤로 다루기 때문에 각 요소에 접근해서 값을 설정하거나 변경하는 작업을 비교적 쉽게 할 수 있다. 게다가, 앞에서 다룬 것처럼 ASP.NET의 전체 컨트롤 트리를 해석하는 코드를 손쉽게 작성할 수 있기 때문에 페이지 내의 모든 컨트롤 값을 알아내는 작업도 쉽게 할 수 있다.

페이지에 있는 모든 컨트롤의 값을 출력하기 위해 BasePage 클래스에 GetFormVariables() 함수를 추가하였다. 이 함수는 모든 컨트롤값을 해시로 저장한다. 값을 이용하기 위해서는 hash["ControlName"]의 형식으로 이용할 수 있고, 전체 컨트롤 값을 얻기 위해서는 다음과 같이 Iterator 패턴을 사용하면 된다.(닷넷에서는 Enumerator라는 용어를 사용하고 있지만 C++/Java 등에서는 이와 같은 형태에 대해 Iterator라는 용어를 사용하고 있다)

화면에 출력되는 값들을 보면 컨트롤 내의 모든 요소들의 값을 잘 가져오는 것을 알 수 있다. GetFormVariables() 함수는 Hashtable 형태로 값을 가져오는 버전과 필드 구분자를 이용해서 값을 가져오는 형태로 나뉘어져있다. GetFormVariables()에서 값을 가져오지 않는 몇가지가 있다. 그 중에는 DataGrid, DropDownList, RadioButtonList, CheckBoxList 컨트롤들이 있다. 이들은 그 안에 포함된 데이터를 다루기 위한 방법들이 별도로 필요하기 때문에 생략하였다.

다음으로 컨트롤에 값을 설정하는 경우를 살펴보자. 요즘 업무용 웹 응용프로그램의 경향을 보면 다양한 탭을 사용하고, 각 탭마다 적게는 30개에서 많게는 300개 이상의 컨트롤을 올려놓고 작업하고 있다. 이런 상황에서 ControlName.Text = “Value”;와 같은 형태의 코드를 각 컨트롤마다 사용한다는 것은 심각한 시간낭비라 할 수 있다.

첫번째 SetFormVaribles() 함수는 컨트롤 이름 목록과 컨트롤 값 목록을 각각 배열로 받아서 순서대로 값을 찾아서 컨트롤의 값을 매핑해주는 예이며, 두번째 SetFormVariables() 함수는 Hashtable에 설정된 값을 컨트롤에 매핑해주는 형태이다. 예제에서 볼 수 있는 것처럼 다양한 컨트롤에 값을 매핑할 수 있다. DataGrid와 List 컨트롤의 값 설정과 매핑은 별도의 주제로 다룰 것이기 때문에 그 주제는 다음 기회로 미룰 것이다. ^^;

일단, 값을 설정하는 컨트롤의 형태에서 간파할 수 있는 것이 몇가지 있을 것이다. 조회성 화면을 작성하는 경우에 DB로부터의 결과를 Hashtable의 형태로 가져온다면 그 값을 바로 페이지상의 컨트롤에 매핑할 수 있을 것이다. DB Field 명을 컨트롤 명으로 사용하는 방법도 생각할 수 있고, 중간에 XML 파일 형식을 만들어서 DB Field와 컨트롤 이름 사이의 매핑을 작성할 수 있을 것이다. 아마, 필자라면 와 같은 형태의 매핑 파일을 작성해서 이를 이용할 것 같다.

VS.NET에서 XML 파일을 추가한 경우에 XML 파일을 컴파일된 DLL 파일에 포함시킬 수 있기 때문에 XML 파일을 관리한다거나 누군가가 XML 파일을 변경하는 문제는 발생하지 않는다. 누군가가 DLL에서 XML을 추출해서 변경하고 다시 DLL에 합치는 경우도 강력한 키(Strong Key) 서명을 이용해서 DLL을 배포했다면 예방할 수 있다. DLL에 XML을 포함시키는 방법은 NHibernate을 설명하면서 같이 살펴보도록 하자.

지금은 GetFormVariables와 SetFormVariables의 내부에 대해 좀 더 자세히 살펴보자. 내부구조에 관심없는 분은 살포시 다른 페이지로 이동하면 된다.

Get/SetFormVariables 함수 분석

ASP.NET 페이지의 컨트롤 트리 해석에 대해서는 ASP.NET 가이드 2. 숫자/문자 입력 텍스트 박스 만들기 에서 살펴보았지만 전체 컨트롤 트리를 해석할 필요는 없었다. 여기에 전체 컨트롤 트리를 해석하게 만들기 위해서는 간단하게 재귀를 사용할 수 있다. 하지만, ASP.NET 페이지에 한 탭에 30-100개의 컨트롤이 5-6개의 탭에 올라가는 응용 프로그램을 생각해보면 재귀는 현명한 선택이 아니다. 따라서 재귀버전을 비재귀버전으로 작성할 필요가 있다.

흥미가 있는 분들은 두번째 글을 참고해서 재귀버전을 작성해보고 그에 대한 비재귀버전을 작성해보기 바란다.


비재귀버전으로 작성한 컨트롤 트리 해석

여기서는 비재귀버전으로 작성하기 위해 스택을 사용했다. 스택을 이용해서 작성했기 때문에 컨트롤 트리의 순서는 반대로 출력되지만 사용하기에는 아무 문제가 없다.(순서를 다시 원위치로 복귀해주는 역정렬을 해주는 구현이라든가 이런 예는 인터넷에서 손쉽게 찾아볼 수 있을 것이다)

GetFormVariables() 함수도 Hashtable을 이용한 버전과 구분자로 되어 있는 문자열을 반환하는 형태의 두 가지 버전이 있다.

GetValue() 함수는 실제 컨트롤의 값을 가져오는 역할을 수행하며, GetValue도 Hashtable인 경우와 문자열인 경우의 두 가지 버전을 제공한다.

SetFormVariables() 함수도 GetFormVariables() 함수와 마찬가지로 같은 코드로 작성되어 있으며 GetValue 대신에 SetValue 함수가 사용되었다는 점만 다르다.

이 두 가지 함수면 대부분의 경우에 컨트롤의 값을 편하게 설정하고 제어할 수 있을 것이다. 원한다면 GetValue, SetValue 함수를 사용해서 일부 컨트롤의 값을 변경할 수도 있을 테지만, 그런 경우에도 SetFormVariables에 변경하고 싶은 컨트롤의 목록과 값을 전달하면 충분히 변경할 수 있을 것이다. 30개 중에 3개의 컨트롤 값을 변경하고 싶은 경우에도 SetFormVariables를 유용하게 사용할 수 있으며, 이런 작업에는 Hashtable을 이용하는 버전보다는 배열 형태를 이용하는 SetFormVariables가 더 유용하게 느껴질 것이다. – 실제로, 두 가지 모두 나름대로의 장단점을 갖고 있기 때문에 상호보완하며 혼용하면 손쉽게 문제를 해결할 수 있을 것이다.

컨트롤과 관련해서 개발자를 괴롭히는 또다른 문제는 DB에서 가져온 값을 손쉽게 컨트롤에 매핑할 수 없을까? 라는 문제다. SetFormVariables 함수와 XML 형태의 매핑 함수를 개발하는 방법은 각자가 얼마든지 개발할 수 있을 것이다. 따라서, 여기서는 그런 간단한 문제 대신에 DB의 요소들을 객체로 편하게 다룰 수 있는 방법에 대해 보여줄 것이다.

NHibernate 간편 가이드

이 부분은 전적으로 NHibernate Quick Guide를 토대로 작성할 것이며, 번역판이라 생각해도 될 것이다.

Hibernate은 본래 Java에서 쓰이는 프레임워크로 ERD(Entity-Relationship Diagram) 로 그려진 관계형 데이터가 표현할 수 있는 영역과 객체지향 언어가 표현할 수 있는 영역이 일치하지 않는 부분을 중간에서 매핑 시켜주는 프레임워크다. 이러한 매핑툴을 ORM(Object-Relational Mapping) 도구라 부른다. 자바 버전의 Hibernate을 닷넷 버전으로 포팅한 것을 NHibernate이라 한다. VS 2005에서는 이러한 툴을 자체적으로 내장할 예정이며, ObjectSpaces라는 이름으로 제공될 것이다. ORM은 종종 ORM(Object-Relationship Modeling) 으로 쓰이기도 한다.

NHibernate은 http://nhibernate.org 에서 자세한 정보를 얻을 수 있고, http://nhibernate.sourceforge.net 에서 다운받을 수 있다.

다운로드를 받고, 설치를 했으면 VS.NET에서 새로운 프로젝트를 시작한다.

SQL Server에서는 다음과 같은 테이블을 작성한다.

CREATE TABLE [dbo].[users] (
[LogonID] [nvarchar] (20) COLLATE Korean_Wansung_CI_AS NOT NULL ,
[Name] [nvarchar] (40) COLLATE Korean_Wansung_CI_AS NULL ,
[Password] [nvarchar] (20) COLLATE Korean_Wansung_CI_AS NULL ,
[EmailAddress] [nvarchar] (40) COLLATE Korean_Wansung_CI_AS NULL ,
[LastLogon] [datetime] NULL
) ON [PRIMARY]

프로젝트 참조에 NHibernate.dll을 추가하고, 클래스에는 using NHibernate.Cfg;와 using NHibernate;을 추가한다.

DB의 테이블을 클래스와 매핑시킬 것이기 때문에 먼저 User 클래스에 대한 정의가 있어야한다.


User 클래스 정의

NHibernate은 클래스와 DB 사이의 매핑을 XML 파일로 구성한다. 이 XML 파일은 “클래스명.hbm.xml”을 사용한다. 여기서 작성한 user.hbm.xml의 정의는 다음과 같다.


user.hbm.xml 정의

여기서 알 수 있는 것처럼 DB의 컬럼명, 데이터 타입, 데이터의 길이까지 지정할 수 있다는 것을 알 수 있다. CLASS 태그는 중요하다. 필자는 Mona.Web.Samples라는 프로젝트를 생성했고, 컴파일된 DLL은 Mona.Web.Samples.DLL이 된다. 네임 스페이스 또한 Mona.Web.Samples이며 User 클래스의 전체 이름은 Mona.Web.Samples.User가 된다. class의 이름은 “클래스명, DLL명”이 되어야 한다. table 속성은 DB에서 사용할 테이블의 이름을 지정한다. 이 XML 파일은 DLL안에 포함되어야만 NHibernate에서 오류없이 XML 파일의 내용을 읽어들일 수 있다.

XML 파일을 DLL에 포함시키기

XML 파일 위에서 마우스 오른쪽 버튼을 클릭하고 [속성]을 선택한다.

빌드 작업을 보면 “포함 리소스”를 선택할 수 있다. [포함 리소스]를 선택하면 컴파일시에 XML 파일에 DLL에 자동으로 포함된다. 이제, NHibernate을 이용할 준비가 되었으니 사용법을 살펴보자.

NHibernate 사용하기

NHibernate에서는 먼저 XML 설정 파일을 읽어들인다. 설정 파일을 읽어들이고, 각 세션을 유지하기 위해 factory를 생성한다. factory는 각 세션을 유지하고, 세션에서는 트랙잰션을 처리할 수 있다. 다음은 새로운 사용자를 추가하는 예제이다.

cfg.AddXmlFile()은 XML 파일을 DLL에 포함시키지 않은 경우에 사용할 수 있는 코드인데 개발중일 때를 제외하면 잘 사용하지 않는다. SQL 쿼리를 사용하지 않고 새로운 사용자를 DB에 성공적으로 집어넣었다. 작업이 끝나면 반드시 해당 세션을 저장해야하고, 변경사항을 DB에 반영하기 위해 Commit을 수행하면 된다.

이 코드는 factory에서 새로운 세션을 열고, “joe_cool”로 검색되는 사용자를 가져와서 로긴 시간만 변경하는 예이다. Flush()를 호출해서 해당 데이터의 변경사항을 반영할 수 있다.

이 예제는 범주를 만들어서 사용자를 검색하는 예제이며, 각 사용자 목록을 어떻게 처리할 수 있는지를 보여주기 위한 예제이다. SQL 쿼리문에서는 WHERE 절에 해당하는 부분을 NHibernate에서는 CreateCriteria()를 사용해서 대신 처리할 수 있는 것이다. Expression.Gt()는 WHERE 절에서 >를 대신하는 것이다. Gt는 “Greater than”을 뜻하며 Ge는 “Greater than or equal”을 뜻한다. 이런 의미로 Lt, Eq와 같은 다양한 메서드들이 존재한다.

NHibernate은 테이블과 클래스의 1:1 매핑 뿐만 아니라 1:N, M:N과 같은 다양한 관계의 매핑도 처리할 수 있으므로 사용법을 참고하면 좋을 것이다.

마치며

이제, 독자에게 남겨진 작업은 Get/SetFormVariables() 같은 메서드를 이용해서 컨트롤 값을 가져오고, NHibernate과 같은 프레임워크를 이용한 객체 사이를 자동으로 처리할 수 있게 해주는 부분이다. Hashtable로 가져온 컨트롤의 이름과 NHibernate 객체의 속성을 매핑해주는 부분을 작성한다면 ASP.NET 페이지에서 DB 까지의 처리를 보다 빠르고 편하게 할 수 있을 것이다. Hibernate 프레임워크를 이용한다고 위의 예제처럼 Hibernate 코드를 직접 조작하는 것은 결국 웹 프로그래밍에서의 무의미한 반복과 별차이가 없지않은가? 그러니, 반복작업을 줄여줄 함수나 도구를 독자 스스로 만들어서 사용해보기 바란다.

본문 소스코드 다운로드

참고자료

NHibernate 공식사이트(http://nhibernate.org) : 소스 다운로드에서 관련 설명서, 기사 모음까지 제공하고 있어 NHibernate 출발점으로 굉장히 유용하다.

NHibernate( http://www.theserverside.net/articles/showarticle.tss?id=NHibernate ): 1:N, M:N에서의 Hibernate 사용법등에 대한 설명이 자세히 되어 있다.

High Performance Timer

Kernel32.dll의 기능을 직접 가져다 쓰는 타이머로서 0.0001ms 단위까지 정확한 시간 측정이 가능한 타이머입니다. 과거 데브피아에 올렸던 글과 소스코드를 다시 블로그에 포스트합니다..

사용 방법:
1. 아래 소스 코드를 별도의 클래스로 생성한다.

2. 타이머를 사용하는 소스 코드 상에서 HiPerfTimer MyTimer = new HiPerfTimer(); 로 인스턴스 하나를 생성한다.

3. MyTimer.Start(); 와 MyTimer.Stop(); 을 소스 코드에 삽입하고 이 두 명령줄 사이에 시간을 측정하고자 하는 내용의 코드를 삽입한다.

4. 컴파일하고 실행한다.

———————————-

using System;

using System.Runtime.InteropServices;

using System.ComponentModel;

using System.Threading;

namespace YourNameSpaceHere

{

internal class HiPerfTimer

{

[DllImport("Kernel32.dll")]

private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);

[DllImport("Kernel32.dll")]

private static extern bool QueryPerformanceFrequency(out long lpFrequency);

private long startTime, stopTime;

private long freq;

// Constructor

public HiPerfTimer()

{

startTime = 0;

stopTime = 0;

if (QueryPerformanceFrequency(out freq) == false)

{

// high-performance counter not supported

throw new Win32Exception();

}

}

// Start the timer

public void Start()

{

// lets do the waiting threads there work

Thread.Sleep(0);

QueryPerformanceCounter(out startTime);

}

// Stop the timer

public void Stop()

{

QueryPerformanceCounter(out stopTime);

}

// Returns the duration of the timer (in seconds)

public double Duration

{

get

{

return (double)(stopTime – startTime) / (double) freq;

}

}

}

}