라이브러리
프로그래밍언어, 각종코드, 관련동향, 논문 등의 저장소
Programming/.Net (14)
ADO의 진화

ADO의 진화

 

ADO가 개발하는데 있어 얼마나 중요한지에 대해서는 이 글을 읽는 개발자 분들이 어느 누구보다 잘 알거라 생각한다. "VB 2005의 변화와 향상성"이란 주제로 기고하면서 ADO를 짚고 넘어가고자 하는 이유는 그 중요성으로 인하여 ADO를 조금이라도 소개하고 싶었던 충동이 강하게 작용하였기 때문이다.

이에 오늘은 너무 거창하지만 "ADO의 진화"라는 타이틀을 두어 ADO에서 ADO.NET으로의 발전에 대해 좀 더 다양하게 살펴보고자 한다. 지난 시간에 살펴 본 DataSet(DataTable)의 향상에 이어 Provider의 변화와 연결풀링 그리고, 배치업데이트에 대해 살펴보는 시간을 갖도록 하겠다.


Provider의 변화

ADO.NET 이전 버전에서는 Provider가 각각의 인터페이스 - 예를 들어 SqlClient, OracleClient - 에 기반하여 작성되었다. 이러한 특징으로 인해 각각의 Provider에 맞게 특정 속성과 메소드를 구현하는 방식을 취하였다. 물론 이것이 전혀 잘못된 방식을 아니지만 각각의 Provider에 맞게 계속적인 코딩을 해야 하는 문제를 내포하고 있었던 것 또한 사실이다. 이를 보완하기 위해 버전 2.0 에서는 새로운 공급자 모델을 제공하게 되는데 바로 System.Data.Common 에 있는 기본 클래스를 기반으로 작성될 수 있도록 한 부분이다. 하지만, 아쉽게도 비록 기본 클래스를 기반으로 작성은 가능하나 DB 서버에 특화된 SQL 구문 등은 지원하지 못한다는 단점 또한 내포하고 있다.

또한, 버전 2.0 에서는 Provider 객체를 생성하기 위하여 Provider Factory 클래스를 사용할 수 있게 되어 이전보다 나은 유연성을 제공하게 된다. ProviderFactory의 GetFactory 메소드를 사용하는 샘플코드를 확인해 보도록 하자.

사용자 삽입 이미지
<그림1> GetFactory 메소드 (출처: MSDN Library)


 

사용자 삽입 이미지
<그림2> GetFactory 메소드 사용 예 (출처: MSDN Library)


<그림 1>은 GetFactory 메소드에 대한 소개이며, <그림 2>는 샘플 소스이다. <그림 2>에 나온 것처럼 DataRow 와 String 을 이용하여 Provider Factory 를 알아내게 된다.

이처럼 버전 2.0 에서는 Provider에 대한 부분이 보다 유연성을 갖게 되었다는데 의미를 두고자 한다.



연결풀링(Conncetion Poolling)의 향상


연결풀링(Connection Pooling)이라는 개념은 ADO 때부터 꾸준히 중요한 위치를 차지하고 있다. 연결풀링이 어떤 향상을 가져왔는지에 대해 논하기 전에 연결풀링이 무엇인지 간단히 소개하고자 한다(필자가 현업에서 개발하면서 아쉽게도 연결풀링의 개념을 파악하지 못하는 개발자들을 보았기 때문에 이 기회를 통해 소개하고 싶기 때문이기도 하다.).

연결풀링이란 대체 무엇이길래 중요한 위치를 차지하는가? 일반적으로 우리는 코드 상에 데이터 베이스에 대한 연결을 생성할 때 다음과 같은 구문을 작성하게 된다.

Dim adoCon as new SqlConnection(연결문자열) : adoCon.Open()

이 때 ADO는 하나의 풀(Pool)을 생성하게 된다. 이 풀이 하는 일은 동일한 커넥션의 요청(여기서 동일하다는 의미는 단순히 동일한 DB에 대한 연결이 아닌 동일한 연결 문자열을 통한 요청을 말한다)이 들어왔을 때 새로운 커넥션을 생성하는 것이 아니라 기존에 생성되어 있던 풀을 반환하는 활용할 수 있게 하는 역할을 하게 된다. 이처럼 매번 요청 시마다 커넥션을 생성하는 것보다 작성된 풀을 활용한다는 것만으로 리소스의 활용도는 그만큼 높아지게 되는 것이다. 그리고, Connection이 Close나 혹은 Dispose가 될 때 풀에 다시 반환되게 된다. 만약 풀에 사용 가능한 자원이 없으면 새로운 연결을 생성하여 반환하게 된다. 이것이 연결풀링의 기본 개념이라 할 수 있다.

ADO.NET 에서는 연결풀링에 대한 보다 상세한 설정을 제공하게 된다. 예를 들어, 풀 크기와 연결 소멸 시간의 지정 등에 대한 설정이 가능하도록 향상되었다. 또한, ADO.NET 2.0에서는 ClearAllPools와 ClearPool 이라는 새로운 메소드를 제공하게 되는데, 이 메소드를 통해 특정 혹은 전체의 풀을 지울 수 있게 되었다.

데이터베이스 프로그래밍시 연결 풀링에 대한 이해를 통해 자신의 Product의 Quality를 높이도록 하자.



배치 업데이트의 지원


DataSet을 사용하여 둘 이상의 행을 변경(추가, 삭제, 수정)하게 되는 경우 DataAdapter는 각각의 행에 대한 처리를 하게 된다. 이때 변경하고자 하는 행의 수만큼 DataAdapter는 각 행위를 체크하여 실행하기 때문에 그만큼 라운드트립이 발생하여 성능을 저하시키게 된다. 이때 배치 업데이트를 통해 해당 네트워크의 라운드트립을 감소 시킬 수 있게 되었다. 배치 업데이트를 지정하는 구문은 다음과 같다.

DataAdapter.UpdateBatchSize = Int32

여기서 Size는 0, 1, 혹은 1이상을 지정하게 되는데 0 은 배치 업데이트의 최대를 나타내며 1은 예전과 같이 각각의 행을 처리하는 것과 동일하다. 1 이상인 경우에는 지정된 수만큼을 나타내게 된다.

좀 더 확실한 이해를 돕고자 MSDN에 나오는 배치 업데이트의 샘플 코드를 축약하여 발췌하였다.

사용자 삽입 이미지
<그림 3> 배치 업데이트 샘플 코드(출처: MSDN Library)


샘플코드를 살펴보면 BatchUpdate에 DataTable과 배치 사이즈를 ByVal로 전달하는 것을 확인할 수 있다. Sub 내에는 Using 블록으로 감싸 코드를 작성하였으며 (Using에 대해서는 "VB.NET 2005, 생산성과 성능이 향상되는 일곱가지 기능" 칼럼에 소개하였다) 블록 안에 DataAdapter를 생성 후 하단에 각각 Update, Insert, Delete Command 를 작성하였다. 그 후 DataAdapter의 UpdateBatchSize에 전달된 batchsize 를 지정하여 Update 처리를 하는 것을 알 수 있다. 이처럼 배치 업데이트를 사용하게 되면 그만큼 네트워크의 라운드트립을 감소시킬 수 있게 된다.

필자 심의준님은 MCSD .NET이며 웹젠에서 개발자로 근무 중이다.

 

저자 :[ 심의준(IT 테크라이터) 2005/11/28]

 

 

사용자 삽입 이미지

 

원문 :http://www.zdnet.co.kr/microsite/powerguide/techguide/solveit/0,39033240,39141825,00.htm

 

 

 

신고
0  Comments,   0  Trackbacks
댓글 쓰기
[기업 환경에 닷넷 적용하기] ⑤ 닷넷 개발에서 UML과 케이스 툴의 사용

[기업 환경에 닷넷 적용하기] ⑤ 닷넷 개발에서 UML과 케이스 툴의 사용

 

연재순서
1.
제대로 된 컴포넌트를 위한 프리젠테이션 레이어 설계하기
2.비즈니스 로직 레이어 설계와 물리적 구현을 위한 필요 사항
3.엔터프라이즈 솔루션 패턴 해부하기
4.닷넷의 웹 프리젠테이션 패턴
5.닷넷 개발에서 UML과 케이스 툴의 사용

 

얼마 전 필자는 한 통의 전화를 받았다. 통화 내용은 닷넷 환경에서 작성된 ASP. NET 웹 응용 프로그램이 클라이언트의 CLR 버전을 알 수 있느냐는 내용에 대한 질문이었다. 간단한 질문이라 Request 객체의 Brawser 속성 중 ClrVersion에 액세스하면 알 수 있다는 답변을 하고 전화를 끊었다. 전화를 끊고 나서 떠오른 의문은 ‘ASP.NET 웹 응용 프로그램에서 클라이언트의 CLR 버전을 알 필요가 있을까?’라는 것이었다. 윈폼으로 작성된 프로그램을 클라이언트로 다운받아 실행하는 것이 아니라면, ASP.NET 응용 프로그램이 동작하기 위해 CLR이 필요한 경우는 거의 없기 때문이다.

나중에 이어진 전화 통화에서, “ASP.NET 응용 프로그램이 동작하기 위해 클라이언트에 CLR이 필요한 경우는 거의 없다. 정말 없다고 봐도 무방하다”고 말했고, 전화를 받은 실무 담당자는 “우리 회사에는 윈도우 98이나 심지어 윈도우 95 운영체제가 설치된 여러 대의 컴퓨터가 동작하므로 안심할 수 없다”라고 했다. 필자는 아무런 문제가 없다고 했지만, 담당자는 “선생님께서는 책만 보고 공부하시니 실무에서 발생할 수 있는 여러 문제에 대한 이해가 부족하다. 실무에서 소프트웨어가 동작하다 보면 어떠한 문제가 발생할지 모른다”고 반박했다.

몇 년간 필드에서 근무하는 사람들을 만날 기회가 많았는데, 닷넷 환경에 대한 것이나 프로젝트 관련 이야기를 하다 보면 다음과 같은 이야기를 종종 듣게 된다.


“실무에서는 그렇게 못합니다.”
“그게 좋은 방법이긴 한데 실무에서는 그렇게 못하죠.”
“실무에서는…”
“실무에서는…”


이론적으로 부족하다보니 지기 싫어서 실무 핑계를 댄다고 생각할 수도 있지만, 어쩌다가 한 번씩은 무시당한다는 느낌이 들 때도 있다. 그럴 때 다음과 같이 반문한다.


“실무에서는 1+1이 3이 됩니까?”


정해진 아키텍처 기반으로 잘 정의되어 구성된 프레임워크, 이를 구성하는 디자인 패턴과 개발 방법론, 그리고 개발을 위한 케이스 툴 등 다 좋은 이야기라고 한다. 하지만 대부분 인력과 시간에 시달리는 실무 개발 환경에서 아직은 요원하다고 말한다. 하지만 훌륭한 이야기이고 좋은 말이며 그게 맞는지는 알고 있다면 왜 하지 않는가?

ASP.NET 응용 프로그램에서 코드 비하인드(Code-Behind) 파일의 코드가 5000라인을 넘어가는 재사용 불가능한 프로그램을 매번 작성하는 것보다는 바른 객체지향 기법으로 잘 설계된 프레임워크를 한 번 만들어놓고 그것을 사용하는 것이 장기적으로 볼 때 좋다. 아니 그렇지 않더라도 몇 번 정도의 프로젝트만 한다고 해도 훨씬 유리하다.

사용자 삽입 이미지
<화면 1> 비지오를 셋업하면 VS>NET 2003의 프로잭트 메뉴에 비지오 메뉴가 추가된다.


아키텍처 또는 프레임워크를 제대로 설계하기 위해서는 아무래도 코드를 직접 작성하면서 하는 것보다는 다이어그램으로 그려가면서 하는 것이 작업 효율도 높아지고 보기도 좋으며, 팀 단위 개발에 있어 많은 장점을 가져올 수 있다. 처음 비주얼 스튜디오 닷넷(이하 VS.NET)이 공개됐을 때 순공학과 역공학이 가능한 닷넷 기반에서의 케이스 도구는 비지오(Visio) 밖에 없었고 사실 너무 불편했다. 시간이 흐르면서 볼랜드 투게더, 래쇼날 로즈 등의 케이스 도구가 VS.NET에 플러그인 되었고, 비주얼 스튜디오 2005에서는 아예 케이스 도구가 기본 기능으로 추가되었다. 이제, 본격적으로 닷넷 환경에서 사용할 수 있는 케이스 도구들에 대해 알아보자.

비지오 2003
MS 비지오 2003은 닷넷 환경이 처음 공개됐을 때 코드 역공학과 순공학이 가능한 것만으로 여러 개발자들 사이에서 화제가 됐던 제품이다. 볼랜드 투게더 또는 래쇼날 로즈와 비교했을 때 그 기능이 단순하고 미비하기 짝이 없지만, MS는 장기적으로 닷넷 환경에서 사용되어야 하는 여러 다이어그램들을 구성하고 사용하기 위한 도구로 비지오를 선택했던 것 같다. 비즈토크 서버의 초기 버전들에서 오케스트레이션을 구성하기 위한 드로잉 도구도 비지오 인터페이스를 가지고 있었고, 여러 오피스 제품들에서 다이어그램을 작성하기 위한 도구도 비지오 인터페이스를 가지고 있었다.

볼랜드 투게더나 래쇼날 로즈 등의 도구는 코드의 변화 또는 다이어그램의 변화를 실시간으로 서로 적용시켜 주지만 비지오는 그렇지 않다. 비지오는 <화면 1>과 같이 작성된 역공학 작업에서 작성된 코드를 리버스 엔지니어링 하면 비지오 파일을 생성한다. 물론 실시간 동기화는 불가능하다.

사용자 삽입 이미지
<화면 2>비지오의 클래스 다이오그램 드로잉과 역공학 UML 관련 메뉴


비지오에서 작성된 다이어그램을 VS.NET로 순공학하는 것 역시 가능하다. 역공학에서와 마찬가지로 다이어그램과 소스코드 간의 실시간 동기화는 불가능하고, 작성된 다이어그램을 역공학하면 새 VS.NET 프로젝트를 생성하거나, 소스코드를 수동적으로 생성한다.

비지오는 이러한 역공학과 순공학 이외에도 표준 UML이 제공하는 거의 모든 다이어그램들을 제공하고 VS.NET과 병행 작업을 진행할 수 있게 한다. 또한 템플릿을 이용한 여러 다이어그램을 작성할 수 있도록 지원하는데, UML의 거의 모든 표준 다이어그램뿐만 아니라 데이터베이스 다이어그램(순공학과 역공학이 가능하다), 블럭 다이어그램 등을 작성할 수 있는 기능들을 제공한다.

비주얼 스튜디오 2005 팀 스위트
비주얼 스튜디오 2005가 베타 2를 통해 그 모습을 드러내고 있다. 6개월 전에 받았던 비주얼 스튜디오 위드비 팀 시스템(Visual Studio Whidbey Team System)이 비주얼 스튜디오 2005 팀 스위트 베타 2로 이름이 바뀌었는데 이전 버전의 VS.NET들과는 확연히 변했다. 비주얼 스튜디오 2005는 5년 전, ‘2001년에 개발 환경의 패러다임 시프트’라고 불리었던 VS.NET의 등장만큼이나 큰 변화를 가져올 듯하다. 여기서는 비주얼 스튜디오 2005에서 지원하는 케이스 도구들에 대해 한번 살펴보자.

사용자 삽입 이미지
<화면 3> 비주얼 스튜디오 2005의 클래스 다이어그램


반드시 필요한 도구만 제공한다
사실, 래쇼날 로즈나 볼랜드 투게더 같은 것을 케이스 도구라고 부를 수 있는데 이들 도구는 특정 개발 방법론(예를 들어 UP(Unified Process)와 같은)을 기반으로 한 요구사항 분석 등의 개념 설계 단계, 클래스 다이어그램 등의 논리 설계 단계를 자동화 도구로 분석하고 응용 프로그램에 적용할 수 있게 되어 있다. 하지만 단적으로 말하면 비주얼 스튜디오 2005 팀 스위트는 이러한 절차적인 설계 단계들을 지원하지 않는다. 비주얼 스튜디오 2005는 MS에 따르면 ‘꼭 필요한’ 도구들만을 제공한다.

필자도 많은 개발 프로젝트들을 수행하면서 문서화를 위해 여러 케이스 도구들을 사용했다. 케이스 도구들을 사용해 다양하게 그려진 여러 다이어그램들을 깔끔하게 문서화하려고 노력하고, 실제로 그렇게 했지만 프로젝트가 종료된 시점에서 보면 언제나 작성된 문서들과 실제 소프트웨어와의 차이는 있었다. 사용하는 여러 케이스 도구들이 다이어그램과 소스코드의 동기화를 지원하여 소스코드와 클래스 다이어그램이 다르다든지 하는 문제는 웬만해서는 발생하지 않았다.

하지만 유스케이스 다이어그램 또는 활동 다이어그램 등은 100% 분석된 요구사항으로 작업할 수 없는 환경에서 개발을 진행하다 보면 요구사항은 변하기 마련이다. 그리고 변한 요구사항을 소스코드에 먼저 적용한 다음 유스케이스에 반영하는 작업들을 반복하게 된다.

결국은 처음 작성할 때는 그렇게 자랑스럽고 훌륭해 보이던 다이어그램들이 프로젝트가 꽤 진행된 시점에서는 무용지물이 된다. 만약, 고집 센 PM이 있었다면 프로젝트의 진행을 조금 늦추는 한이 있더라도 작성된 문서와 코드를 일치시키는 작업을 따로 진행하겠지만 이는 소프트웨어 개발의 라이프 사이클을 지연하게 된다.

가슴에 손을 얹고 생각해보면, 필자 역시 유스케이스 다이어그램을 제대로 그리거나 메쏘드를 작성하기 위해 모든 메쏘드의 활동 다이어그램을 작성한 적은 없다. 적당히 프로젝트의 개요 정도만을 파악하기 위해 VS.NET이 아닌 다른 케이스 도구를 실행하여 다이어그램을 그리고(또는 연습장에 손으로 그려서 그려진 다이어그램을 여러 장 복사해두기도 했다) 그 다이어그램과 프로젝트를 동기화하는 것이 아닌 코드를 작성할 때 ‘참고’하는 정도로 진행한 프로젝트가 꽤 된다(정석은 아니겠지만 프로젝트의 빠른 진행에 꽤 도움은 됐다).

하지만 반드시 있어야 되는 것은 있는 법이다. 1+1은 항상 2이고, 꽁수를 쓰더라도 1+1의 결과로 나온 2를 기반으로 적당한 꽁수를 펼쳐야 제대로 된 소프트웨어가 만들어진다. 기업용 응용 프로그램을 작성하는 프로젝트라면 당연히 응용 프로그램의 아키텍처 정도는 작성해야 하고, 작성된 아키텍처는 활동 다이어그램이나 클래스 다이어그램처럼 프로젝트가 진행되면서 적당히 변경될 수 있는 성질의 것이 아니다. 응용 프로그램 아키텍처는 한 번 지정되면 반드시 그 아키텍처를 강제해야 소프트웨어의 재사용성과 가용성을 기대할 수 있게 된다. 하나의 컴포넌트라도 여러 계층에 걸쳐 작성된다면 전체 응용 프로그램을 재사용할 수 없게 되는 최악의 경우가 발생할 수 있다.

비주얼 스튜디오 2005는 이런 식으로 ‘반드시 필요한 도구만 제공하겠다’는 철학을 가지고 있는 듯하다. 즉 반드시 필요해서 작성했다면 작성된 다이어그램대로 소프트웨어의 개발이 진행되어야 한다는 것이다. 비주얼 스튜디오 2005는 새로운 여러 디자인 도구를 지원하는데, 새로운 디자인 도구는 클래스 디자이너(class designer)와 분산 시스템 디자이너(distributed system designers)로, 분산 시스템 디자이너는 긴밀하게 통합된 4개의 도구 그룹으로 구성된다.

사용자 삽입 이미지
<그림 1> 응용 프로그램 아키텍처


이들 4개의 도구는 응용 프로그램 연결 디자이너(application connection designer), 논리적 데이터센터 디자이너(logical datacenter designer), 시스템 디자이너(system designer), 배포 디자이너(deployment designers)로 구성되고, 이들 중 응용 프로그램 디자이너와 클래스 디자이너는 시스템과 구성 요소의 그래픽 디자인 지원과 코드 생성 지원 등 주요 특성을 공유한다. 모든 디자이너는 볼랜드 투게더와 래쇼날 로즈가 그러하듯이 양방향 동기화를 지원한다.

응용 프로그램 아키텍처의 정의
예를 들어, 지난 1회 연재에서 설명했듯이 응용 프로그램은 <그림 1>과 같은 구조를 가져야 한다고 하자. 그러면 응용 프로그램 작성을 위해 참여하는 모든 개발자들이 응용 프로그램의 구조를 따라 작성해야 한다(물론 이런 아키텍처를 지켜 나가려면 케이스 도구들보다 능력 있는 PM의 올바른 팀 구성이 우선된다).

아키텍처대로 응용 프로그램을 구성한다면, 프리젠테이션 계층을 구성하는 ASP.NET 웹 응용 프로그램, 비즈니스 컴포넌트를 구성하는 클래스 라이브러리 응용 프로그램, 데이터베이스 연결을 담당하는 응용 프로그램, 서비스 인터페이스를 구성하는 웹 서비스 응용 프로그램 등의 여러 응용 프로그램 솔루션이 구성되고, 이 솔루션 하나에 구성된 여러 응용 프로그램들은 연결을 가진다. 비주얼 스튜디오 2005는 닷넷 개발에 필요한 이런 응용 프로그램의 구성 연결들을 작성할 수 있는 다이어그램을 제공한다. 그 다이어그램이 바로 응용 프로그램 연결 디자이너 (application connection designer)이다.

사용자 삽입 이미지
<화면 4> 응용 프로그램 다이어그램 추가
사용자 삽입 이미지
<화면 5> 응용 프로그램 다아이어그램이 추가된 모습


비주얼 스튜디오 2005에서 솔루션을 하나 작성했다면, 가장 처음 만나게 되는 디자이너가 바로 이 응용 프로그램 연결 디자이너이다. 응용 프로그램 연결 디자이너는 솔루션을 오른쪽 클릭하고 「Add… New Item…」을 선택하여 구성할 수 있다. 솔루션에 응용 프로그램 다이어그램이 추가되면 <화면 5>와 같은 디자인 창을 보여준다.

<그림 1>의 응용 프로그램 아키텍처를 보면 웹 응용 프로그램은 웹 서비스인 서비스 인터페이스에 연결되어 동작한다. 응용 프로그램 디자이너는 다이어그램에 추가할 수 있는 여러 도구들을 제공하는데 제공되는 도구상자에서 ASP.NET 웹 서비스를 선택하고 디자인 창으로 드래그하여 응용 프로그램 간의 연결을 공유할 수 있게 한다. ASP.NET 웹 서비스를 선택하고 디자인 창으로 드래그&드롭한 후, 두 응용 프로그램의 엔드 포인트(end point)를 서로 연결해주면 두 응용 프로그램이 연결된다.

사용자 삽입 이미지
<화면 6> 연결된 두 응용 프로그램
사용자 삽입 이미지
<화면 7> 추가된 비지니스 로직 계층 컴포넌트 응용 프로그램


응용 프로그램 아키텍처를 계속 구성하기 위해 다음 절차를 계속 진행해보자. 응용 프로그램 아키텍처는 모델을 구성하기 위해 두 개의 컴포넌트를 사용한다. 하나는 비즈니스 컴포넌트이고, 다른 하나는 비즈니스 엔티티이다. 복잡한 전자상거래를 수행하는 기업용 응용 프로그램이라면 비즈토크 웹 서비스(Biztalk WebService)를 추가해서 사용할 수도 있다. <그림 1>은 두 응용 프로그램을 일반적인 클래스 라이브러리 응용 프로그램으로 작성하므로 도구 상자에서 Generic Application을 선택하여 다이어그램에 추가하고, Generic Endpoint를 삽입한 후, 같은 방법으로 연결하여 사용할 수 있다.

마지막으로 데이터 연결이 필요하다. 데이터 연결은 도구상자의 ExternalDatabase를 선택하고 다이어그램에 삽입하여 사용할 수 있다. ExternalDatabase 구성 요소를 다이어그램에 추가하면 비주얼 스튜디오 2005는 어떤 데이터베이스에 어떻게 연결할 것인지에 대한 정보를 요구한다. 적당한 정보를 입력해주면 데이터베이스와의 연결이 완성된다.

이러한 아주 간단한 방법으로 응용 프로그램의 아키텍처를 정의할 수 있는데, 완료된 응용 프로그램 다이어그램은 <화면 8>과 같다.

작성된 응용 프로그램 아키텍처는 여러 컴포넌트의 구성을 알려주는 여러 형태의 다이어그램을 대신할 수 있다. 적당히 주석을 붙여준다면, Business Context 다이어그램도 대체할 수 있다. 이러한 개발 방법은 개발자와 분석가/설계자의 활동 영역을 확연하게 구분해 줄 수 있다. 이런 도구는 반드시 여러 직종의 사람들이 모인 팀 단위의 기업용 설계에서 문서를 찾아 보관하고 문서의 버전을 일일이 확인하는 등의 작업을 확연히 줄여준다.

사용자 삽입 이미지
<화면 8> 작성된 응용 프로그램 다이어그램
사용자 삽입 이미지
<화면 9>시스템 다이어그램


이렇게 작성된 응용 프로그램 아키텍처를 응용해서 각 하위 시스템을 설계할 수 있게 한다. 비주얼 스튜디오 2005는 시스템 다이어그램을 지원하는데, <화면 8>에서와 같이 작성된 여러 응용 프로그램을 분산 응용 프로그램에서 하나의 배포 단위인 시스템을 구성하고 조직할 수 있도록 도와준다.

비주얼 스튜디오 2005에는 클래스 다이어그램이나 배포 다이어그램 같은 많은 새로운 기능들이 포함되어 있다. 필자가 원고를 작성하고 있는 중에, 모 학교에서 동작하는 응용 프로그램이 동작하지 않는다는 연락을 받고 에러를 해결하러 다녀온 적이 있다. 오류는 커넥션 풀(connection pool)이 꽉 차서, 더 이상의 데이터 연결을 작성할 수 없다는 오류였다.

정석대로라면 응용 프로그램의 아키텍처를 제대로 설계하고 커넥션 풀링을 하나의 컴포넌트에다 위임하여 위기 상황에 즉시 대처할 수 있도록 구조를 개선해야 한다. 하지만 우선 급한 불부터 끄고 봐야 한다고, 모든 페이지와 데이터 패치를 한 다음 닫히지 않는 데이터리더 개체들을 일일이 찾아 닫아야 했다. 제대로 된 아키텍처를 기반으로 설계됐다면 이런 오류는 발생하지도 않았을 것이고, 하나의 응용 프로그램을 수정하는 것만으로 전체 프로그램의 오류가 해결됐을 것이다.

다른 도구는 필요한가?
닷넷 개발에서 반드시 비주얼 스튜디오 2005를 사용해야 하는 것은 아니다. 케이스 도구라는 것은 자동차 수리 장비와 같은 것이다. 수 없이 많은 도구들 중에 자기 손에 가장 맞고 사용하기 편한 것 하나만을 골라 사용하면 된다. 래쇼날 로즈가 편하면 그것을 쓰면 되고, 개발 방법론이 UP가 편하다면 UP를 선택하여 사용하면 된다. 꼭 옮겨 올 필요가 있을까 하는 고민은 자바가 처음 등장했을 때 C++ 개발자들의 고민과 같은 맥락이다.

필자는 비주얼 스튜디오 2005가 있더라도 다른 도구 하나 정도는 필요하다고 생각한다. 하지만 그 도구가 꼭 래쇼날 로즈나 볼랜드 투게더 같이 UP 개발 방법에 필요한 모든 도구들을 다 제공하는 무거운 것일 필요는 없다. 몇 장의 종이와 연필, 지웠다 다시 쓰기 위한 지우개면 충분하다.

좋은 변화는 계속되야 한다
얼마 전 간단한 ATL 프로젝트를 수행하기 위해 비주얼 스튜디오 6.0을 설치하고 사용했는데, 5년간 VS.NET을 사용한 필자에게는 고역 같은 일이었다. 우선 인텔리센스 기술의 초기 시점이라 코드를 작성하기가 너무 불편했다(디버거 또한 불편했다). 세상 모든 것은 진화하기 마련이고, 개발 도구 또한 세상 어떤 개체들보다 빨리 진화한다.

비주얼 스튜디오 2005를 접해본 주위의 개발자들이나 학생들은 한숨부터 쉬고 시작한다. 완전히 새로 배워야 되는 것이 아니냐는 것이다. 가끔 필자도 너무 빨리 변화하는 IT를 업으로 삼은 것을 후회할 때도 있다. 『비주얼 스튜디오 2005 베타 2에서 변화한 8532가지』라는 문서를 받을 때면 다 그만두고 머리 깎고 산으로 들어가고 싶어지는 것이다. 하지만 등대가 보이는데 가까운 암초에 배를 댈 수는 없는 법. 그 등대가 구원의 길을 제공한다면 그 등대의 이름이 자바이건, 닷넷이건, 다른 기술이건 상관없다. 기술은 날이 갈수록 변화하고 개발은 갈수록 재미있어지고 있다. 부디, 이런 좋은 변화가 계속 되기를 바란다.@

* 이 기사는 ZDNet Korea의 제휴매체인마이크로소프트웨어에 게재된 내용입니다.

 

김상훈 (동명정보대학 정보기술원 연구원)

2005/09/21

 

사용자 삽입 이미지

 

 

 

 

원문 :http://www.zdnet.co.kr/builder/dev/dotnet/0,39031607,39139648,00.htm

신고
0  Comments,   0  Trackbacks
댓글 쓰기
[기업 환경에 닷넷 적용하기] ④ 닷넷의 웹 프리젠테이션 패턴

[기업 환경에 닷넷 적용하기] ④ 닷넷의 웹 프리젠테이션 패턴

 

연재순서
1.제대로 된 컴포넌트를 위한 프리젠테이션 레이어 설계하기
2.비즈니스 로직 레이어 설계와 물리적 구현을 위한 필요 사항
3.엔터프라이즈 솔루션 패턴 해부하기
4.닷넷의 웹 프리젠테이션 패턴
5.닷넷 개발에서 UML과 케이스 툴의 사용

 

현재의 웹 프로그래밍 환경은 HTML 태그로 하이퍼 링크와 그림만을 입력하던 예전과는 판이하게 틀리다. 변화가 없는 HTML 페이지가 사용자와 상호 작용하여야 하는 경우가 발생하자 CGI (Common Gateway Script)가 등장했다. Perl 또는 C언어로 작성되는 CGI는 사용자의 입력에 따라서 동적인 페이지를 생성했다. 하지만 재 사용 가능한 코드를 쓰기가 거의 불가능에 가까웠고, GGI 프로그래밍은 복잡한 프로그래밍 환경을 만족시키지 못했다. 그 후에 등장한 프로그래밍 모델은 페이지 기반 개발이었다.

ASP또는 PHP로 대표되는 페이지 기반 개발은 여러 계층으로 동작하던 CGI의 복잡성을 줄여주었다. 하지만, 페이지가 갈수록 늘어나고 작성해야 하는 페이지의 수가 말도 못하게 늘어남에 따라 페이지 기반 개발 방식은 프레임워크 기반 방식으로 발전했다. 튼튼하게 제작된 프레임워크는 페이지에 발생하는 복잡함을 줄이는 대신 자신이 대신해 주었다. 프로그래머가 해야 하는 일은 줄어들었다.

사용자 삽입 이미지
<그림 1> 웹 프로그래밍 환경의 변화


프레임워크가 등장함에 따라 페이지를 어떻게 작성할 것인지에 대한 프로그래머의 선택권은 한없이 넓어졌다. 페이지 내에 스크립트를 그대로 유지하는 페이지 기반 프로그래밍 모델을 그대로 사용할 수도 있고, Java의 태그 라이브러리와 ASP.NET의 코드-비하인드를 사용하여 페이지 수준에서 프리젠테이션 로직과 페이지 로직을 구분할 수도 있게 되었다. 소프트웨어의 아키텍처를 정립하고 튼튼한 설계를 기반으로 개발을 시작하는 것은 과도한 복잡성과 중복성을 줄이기 위해서 인데, 웹 응용 프로그램 개발에서 사실상 가장 많이 중복되는 부분은 페이지에서 표현되는 프리젠테이션 계층의 로직들이다. 이런 중복된 내용을 비즈니스 로직 계층으로 옮겨 표현할 수도 있지만, 그렇게 처리한다면 비즈니스 로직 계층의 복잡도가 너무 증가하게 된다.

가장 좋은 방법은 프리젠테이션 계층의 컴포넌트들을 설계하고 이를 재 사용하기 위한 적당한 정도의 복잡성을 가지게 설계하는 것이다. 마이크로소프트의 Enterprise Solution Pattern using Microsoft.net에서는 그 “적당한” 복잡도에 대한 6가지의 질문을 준비하고 그 질문에 대한 대답으로 패턴을 제시한다.

사용자 삽입 이미지
<표 1>


위의 <표 1>은 Enterprise Solution Pattern using Microsoft.net에서 제시하는 질문과 질문에 대한 답으로서의 디자인 패턴이다.

Enterprise Solution Pattern using Microsoft.net은 연구되고 발표된 거의 모든 디자인 패턴을 참고 한다. 디자인 패턴의 교본이라 불리는 GoF의 디자인 패턴을 이해하지 않고서는 웹 프리젠테이션 패턴을 이해하기 힘들다. MVC 패턴은 Observer 패턴을, Page Controller 패턴은 GoF의 패턴중 Template Method 패턴을, Front Controller 패턴은 GoF의 패턴중 Command 패턴을 응용하고 있기 때문이다. 이러한 패턴에 익숙하지 않은 독자들이라면 다시 한번 GoF의 디자인 패턴을 살펴 보기를 바란다. <그림 2>는 웹 프리젠테이션 패턴의 패턴 클러스터이다. (패턴 클러스터에 대해서는 지난 달 연재를 살펴보기 바란다.)

사용자 삽입 이미지
<그림 2> 웹 프리젠테이션 패턴의 패턴 클러스터


MVC (Model-View-Controller) 패턴
해결책의 쌍으로서 MVC 패턴을 생각해보면 질문은 다음과 같다.


“개별적인 영역을 쉽게 수정하기 위해서 웹 응용 프로그램의 사용자 인터페이스 기능을 어떻게 모듈화 할 것인가?”


질문이 너무 추상적인 것 같이 느껴진다. 질문을 해설해보면 주로 다음과 같은 문제라고 생각할 수 있다.

① HTML 페이지를 설계하는 것과 비즈니스 로직을 설계하는 것은 거의 모든 경우에 다른 기술이 필요하다. 이는 웹 디자이너와 프로그래머의 고질적은 의견 대립을 발생시키는 문제이기도 하다. 빼어난 웹 디자인 실력과 고급 프로그래밍 실력을 모두 갖춘 사람은 흔하지 않다. MVC 패턴은 두 가지 영역에 대한 개발을 분리할 수 있다.

② 같은 데이터에 대한 다른 표현이 종종 발생한다. MVC 패턴은 같은 데이터를 서로 다르게 보여지도록 디자인 할 수 있다.

③ 웹 기반 응용 프로그램은 비즈니스 로직 보다 사용자 인터페이스가 자주 바뀐다. (페이지의 리뉴얼이 일어날 경우 비즈니스 로직은 전혀 변화가 없는 경우가 허다하다) MVC 패턴은 비즈니스 로직의 변화 없이 사용자 인터페이스의 변화를 가능하게 해 준다.

④ 리치 클라이언트용 웹 응용 프로그램이 PDA용 웹 응용 프로그램으로 마이그레이션 될 경우, 사용자 인터페이스가 크게 변화한다. 이러한 장치 의존적인 작업이 일어날 경우, MVC 패턴은 비즈니스 로직의 변화 없이 작업을 완료할 수 있게 한다.

MVC 모델은 Model - View - Controller 3 가지 클래스로 역할을 구분하도록 프리젠테이션을 설계하는 기법이다. GoF의 디자인 패턴[1]에 의하면, MVC 패턴을 다음과 같이 설명한다.


“MVC는 세 가지 객체로 이루어진다. 모델은 응용 프로그램 객체이며, 뷰는 스크린에 모델을 디스플레이 하는 방법이며, 컨트롤러는 사용자 인터페이스가 사용자 입력에 반응하는 방법을 정의한다.”


사용자 삽입 이미지
<그림 3> MVC 클래스 구조
MVC 패턴에서 얻을 수 있는 가장 핵심적인 장점은 뷰와 컨트롤러는 모델의 의존하지만 모델은 뷰와 컨트롤러에 의존하지 않는다는 것이다. 이런 장점으로 인해 실제 객체들이 존재하는 모델 계층의 클래스들이 프레젠테이션과 별도로 작성되고 테스트 될 수 있다.

ASP.NET 에서의 구현
사실상, ASP.NET은 전형적인 이벤트 드리븐 방식을 사용한다. ASP.NET은 HttpHandler 클래스가 전방에서 동작하여 모든 페이지들에 대한 요청을 처리하고 발생하는 이벤트를 처리하는 이벤트 지향적인 방법을 선택하고 있어 Front Controller나 Page Controller등의 향상된 설계 기법을 이미 내장하고 있다고 봐도 무방하다. ASP.NET에서 MVC의 구현은 HttpHandler 같은 컨트롤러의 구현과 별 상관없이 (혹은 그 존재를 모르더라도), ASP.NET이 지원하는 Code-Behind 기능을 사용하여 할 수 있게 된다. 모델이 뷰에 의존하지 않게 설계하는 것이 MVC의 목적이라고 한다면, Code-Behind의 사용으로 그러한 목적을 훌륭하게 달성할 수 있다.

다음 그림과 같은 페이지를 디자인 한다고 하자. 페이지는 Page_Load 이벤트 핸들러에서 책의 타입을 로드하여 드롭다운 리스트에 보여주고, 버튼의 이벤트에 반응하여 데이터그리드컨트롤에 바인딩한다.

사용자 삽입 이미지
<그림 4> 예제 페이지


ASP.NET에서 <그림 4>와 같은 페이지를 제작하는 것은 아주 다양한 방법으로 할 수 있다. 우선, 가장 쉬운 방법은 <코드 1> 과 같이 In-Line 코드를 쓰는 것이다. 모든 내용을 하나의 파일안에 써서 로직과 뷰를 단순히 <Script> 태그로 구분한다.

<코드 1> 한 파일에 세 역할을 모두 집어넣은 단일 ASP.NET 페이지
사용자 삽입 이미지

<%@ Import Namesace=”System.Data.SqlClient” %>
  <body>
    <Script Language=”C#” Runat=”Serve” />
    void Page_Load(object sender, EventArgs e) {
      // 데이터베이스에 연결하여 데이터를 반환받음
    }
    void btn_Click(object sender, EventArgs e) {
      // 버튼 클릭 이벤트에 반응하여 데이터를 반환받음
    }
    </Script>
    <form id="Solution" method="post" Runat="Server">
      <h3>Titles</h3>
      Select a Titles:<br>
      <asp:DropDownList id="titlesSelect" runat="Server" />
      <asp:Button Runat="Server" Text="Submit" id="Button1" name="Button1" />
      <p>
        <asp:DataGrid id="myDataGrid" Runat="Server" />
  </form>
  </P>
</body>
사용자 삽입 이미지

위 코드는 패턴에 있는 Model, View, Controller 세 가지 역할을 모두 담당한다. 다만, 구분하지 않을 뿐이다. View의 역할은 HTML로 표시된다. 페이지는 잘 동작하고, 독립적이며 직관적이다. 작은 응용 프로그램이거나 페이지가 자주 변경되지 않는 경우라면 아주 권장할 만한 생산성 뛰어나고 쉬운 개발 방법이라 할 수 있다. 하지만, 여러명이 동시에 작업을 진행하는 경우, (대표적으로 웹 디자이너와 프리젠테이션 로직 개발자가 같이 작업을 병행하는 경우)와 사용된 데이터 액세스 코드를 재 사용하고 싶은 경우, 위와 같은 설계라면 거의 작업이 불가능하다. 이런 문제에 당면했다면, Code-Behind를 사용하여 리팩토링 할 수 있다. Visual Studio.net을 사용하지 않았기 때문에, Page 지시문에서 CodeBehind 대신 Src를 사용했다.

<코드 2> Code-Behind 리팩토링 한 View 페이지 (.aspx 페이지)
사용자 삽입 이미지

<%@ Page language="c#" Src="CodeBehind.aspx.cs" AutoEventWireup="false" Inherits="CodeBehind1.CodeBehind" %>
<HTML>
  <HEAD>
    <title>Solution
  </HEAD>
  <body>
    <form id="Solution" method="post" Runat="Server">
      // 동일한 View 코드
  </body>
</HTML>
사용자 삽입 이미지


<코드 3> CodeBehind 리팩토링한 코드 비하인드 코드
사용자 삽입 이미지

using System;
using System.Data;
using System.Data.SqlClient;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace CodeBehind1
{
  public class CodeBehind : System.Web.UI.Page
  {
    protected System.Web.UI.WebControls.DropDownList titlesSelect;
    protected System.Web.UI.WebControls.Button Button1;
    protected System.Web.UI.WebControls.DataGrid myDataGrid;

    private void Page_Load(object sender, System.EventArgs e)
    {
      f (!Page.IsPostBack) {
        // 데이터베이스에 연결하여 데이터를 반환받음
      }
    }

  // OnInit 이벤트 핸들러 및 InitializeComponent() 메소드

  public void SubmitBtn_Click(object sender, System.EventArgs e)
  {
    // 버튼 클릭 이벤트에 반응하여 데이터를 반환받음
  }
  }
}
사용자 삽입 이미지

위 리팩토링에서 <코드 2>에는 WebForm 컨트롤들과 HTML 태그만이 존재하여 View 와 다른 역할들을 구분한다. <코드 3>에는 Model과 Controller 역할을 수행하는 코드들이 들어있다. 이렇게 설계된 페이지에서는 페이지가 데이터베이스에 액세스하기 위한 어떠한 코드들도 가지고 있지 않기 때문에 데이터베이스 코드가 변경된다거나 페이지의 디자인이 변경된다 하더라도 서로 간섭받지 않게 된다.

코드-비하인드 기능이 3-Tire 구조 아키텍처를 사용하기 위한 프리젠테이션 계층과 비즈니스 로직 계층을 강제 구분하는데 사용된다는 말이 있었는데, 그렇게 정확한 이야기는 아니다. ASP.NET의 코드-비하인드는 위에서 보듯이 View 역할과 다른 역할들을 구분할 수 있도록 하는데 주로 사용될 수 있다.

주어진 질문에서 해결되지 않은 것은 로직을 재 사용하는 것이다. 기술적으로는 Code-Behind 코드의 재 사용이 가능하지만 현실적으로는 거의 불가능하다. 특히 Visual Studio.net을 사용해서 이런 작업을 해본 경험이 있는 개발자라면 하나의 코드-비하인드 파일을 여러 개의 뷰 파일이 공유해 쓰는 것은 거의 불가능하다는 것을 알 것이다. 이 경우에 대한 답이 바로 MVC 패턴을 사용하는 것이다.

위의 코드-비하인드 리팩토링에서 뷰를 표현하는 aspx 페이지는 수정할 부분이 없다. <코드 3>의 코드-비하인드 페이지가 모델과 컨트롤러 두 가지 역할을 담당하는데, 모델과 컨트롤러의 역할을 구분해 주어 모델의 코드를 재 사용할 수 있게 하는 것이다.

데이터베이스에 액세스하는 로직을 가지는 모델 클래스를 생성한다.

<코드 4> MVC 리팩토링에서 Model
사용자 삽입 이미지
using System;
using System.Data;
using System.Data.SqlClient;

public class Model {
  public static DataSet GetTypes() {
    // 데이터베이스에 액세스하여 책의 타입 정보를 데이터셋으로 반환한다.
  }

  public static DataSet GetTitles(string typeID) {
    // 데이터베이스에 액세스하여 타입에 해당하는 책 정보를 반환한다.
  }
}
사용자 삽입 이미지

Page 클래스를 상속하는 CodeBehind 클래스는 다음과 같이 역할이 수정된다.

<코드 5> MVC 리팩토링에서 Controller
사용자 삽입 이미지

public class CodeBehind : System.Web.UI.Page {
  protected System.Web.UI.WebControls.DropDownList titlesSelect;
  protected System.Web.UI.WebControls.Button Button1;
  protected System.Web.UI.WebControls.DataGrid myDataGrid;

  private void Page_Load(object sender, System.EventArgs e) {
    if (!Page.IsPostBack) {
// 모델 클래스의 GetTypes() 메소드 호출 결과를 컨트롤에 바인딩
    }
  }

    // OnInit 이벤트 핸들러 및 InitializeComponent() 메소드

  public void SubmitBtn_Click(object sender, System.EventArgs e)
  {
    // 모델 클래스의 GetTitles () 메소드 호출 결과를 컨트롤에 바인딩
  }
}
사용자 삽입 이미지

ASP.NET에서 MVC 모델을 고려하여 설계하면 다음과 같은 장점들을 얻는다.

  • 페이지 간의 의존성이 감소한다.

  • 메소드의 재 사용성이 증가한다.

  • 동시 작업을 진행할 수 있다.

  • 테스트가 용이하다.

    하지만 모든 장점에는 단점이 따라오는 법이다. MVC의 단점은 파일과 코드가 추가된다는 것이다. 필자가 참여했던 모 프로젝트에서, 경험 있는 닷넷 개발자가 다음과 같이 이야기 하는 것을 들은적이 있다. 당시 필자는 어차피 디자이너가 닷넷을 잘 모르니 M-VC로 프로젝트를 진행하는 것이 차라리 효율적이라고 주장하고 있었다.

    “제가 전에 참여했던 닷넷 프로젝트에서, VS.NET을 사용했었는데, 디자이너에게 1주일쯤 닷넷을 가르치고 Code-Behind로 개발하는 것이 아주 효율적이었습니다”

    필자도 수긍을 했고, 디자이너도 닷넷을 배우겠다고 자청하여 1주일쯤 디자이너에게 WebForm 사용법을 가르친 후 (DataGrid 컨트롤과 DataList 컨트롤의 사용법을 익히느라고 디자이너가 꽤 고생을 하긴 했다) VS.net을 사용하여 MVC 패턴을 적용하여 진행된 프로젝트는 꽤 성공적으로 진행되었다. 디자이너는 aspx 작업을 하고, 개발자는 컨트롤의 이름만 알면 동시 작업을 진행할 수 있었다. 기업형 응용 프로그램 개발에서 MVC 패턴의 장점을 잘 보여주는 단적인 예였다.

    Page Controller
    패턴 클러스터에서 Page Controller 패턴은 MVC 패턴과 같은 레벨에 놓여 있다. Page Controller 패턴은 MVC 패턴에 기반한다. Page Controller 패턴을 질문 ? 해결책의 쌍으로서 Page Controller 패턴을 생각해보면 질문은 다음과 같다.

    “코드를 복사하지 않으면서 재 사용이 가능하고 융통성있는 약간 복잡한 웹 응용 프로그램을 어떻게 작성할 것인가?”

    역시 질문이 너무 추상적이다. 질문을 해설해보면 주로 다음과 같은 문제라고 생각할 수 있다.

    ① 예를 들면, 게시판에 글을 쓰는 동작을 하고 나면 고쳐진 게시판의 리스트 페이지로 이동한다. 웹 기반의 전자메일 응용 프로그램에서 메일을 발송하고 나면 고쳐진 받은 편지함 페이지로 이동한다. 이러한 이동은 거의 정적이고, 같은 방식으로 동작한다. 세부적인 동작은 틀리지만, 사용자의 행위는 동일하다. 사용자의 행위가 동일함에도 불구하고 여러 개의 컨트롤러에 개별적인 코드를 써서 MVC 패턴의 단점인 복잡성을 그대로 둘 것인가?

    ② MVC 패턴의 단점중의 하나는 파일의 개수가 증가하여 여러 개의 파일을 따로 컨트롤러를 따로 테스트 해야 한다는 것이다. 여러 개의 사용자 인터페이스를 동일한 타입의 컨트롤러가 관리한다면 테스트가 훨씬 용이해 질 수 있다.

    ③ ASP.NET의 이벤트 모델은 고정되어 있다. 따라서, 거의 모든 페이지가 유사한 방식으로 렌더링 된다. 사용자 인증을 검증하고, 쿼리 문자열로부터 Request 정보를 얻어내고 같은 헤더와 꼬리말을 사용한다. 이러한 작업을 하나로 묶어 복잡성을 줄일 수 있을 것인가?

    이런 질문의 해결책으로 Page Controller 패턴이 제시된다. 만약, 다음과 같은 상황에 직면했다고 생각해 보자. 웹 응용 프로그램이 7개의 게시판을 가지고 있다. 게시판은 공지사항, 뉴스, QnA, 공개 게시판 등인데 동작하는 방식은 완전히 같다. 게시판의 디자인은 수시로 변하는 등의 이유로 MVC 패턴을 응용하여 설계 하였다.

    그렇다면, 각 게시판의 글 쓰기 페이지와 리스트 보기 페이지 등의 동작은 완전히 같다. 이런경우, 각 게시판별로 각각의 뷰 페이지와 컨트롤러를 작성하는 것은 부담이 되고 또한 테스트 하기 곤란해 진다. (물론, 하나의 페이지가 모든 게시판을 처리하도록 작성할 수 있으나, 웹 페이지 디자인 등의 문제로 그렇게 처리하기가 곤란한 상황이라고 가정하자) 이런 경우, Page Controller 패턴의 사용을 고려해 볼 수 있다는 이야기다.

    모든 게시판에서 글 수정하기 페이지를 작성할 때, 페이지의 모든 컨트롤러는 다음과 같은 기능들을 구현한다.

    <코드 6> Controller
    사용자 삽입 이미지

    public class Modify_Article : System.Web.UI.Page {
      // 전역변수 (WebForm 컨트롤들)
      int no;

      private void Page_Load(object sender, System.EventArgs e) {
        // 쿼리스트링으로 전달된 값 처리
        no = Int32.Parse(Request.Params["no"].ToString());
        GetArticle(no);
      }

      override protected void OnInit(EventArgs e) { ... }
      private void InitializeComponent() { ... }

      private void GetArticle(int no) {
        // 글을 가져와서 컨트롤에 바인딩
      }

      private void Modify_Article(object sender, System.EventArgs e) {
        Model.Modify_Article(no); // 글 수정
        Response.Redirect("ListPage.aspx"); // 리스트 페이지로 이동
      }
    }
    사용자 삽입 이미지

    위와 같이 같은 방식으로 동작하는 컨트롤러를 여러 개 작성하는 것은 좋지 않은 해결책이 된다. 이를 위해서, 공통적인 동작을 하는 페이지 컨트롤러를 작성하고, 같은 동작을 하는 컨트롤러를 집중화 해서 요청에 대한 중앙 집중적인 처리를 담당할 수 있도록 하는 것이 유리해진다. 개선된 컨트롤러들은 <그림 5>와 같은 방식으로 설계될 수 있다.

    사용자 삽입 이미지
    <그림 5> Page Controller 패턴을 이용한 설계 개선

    <그림 5>의 클래스 다이어그램에서 BoardController 클래스는 다음과 같은 코드로 구현된다.

    <코드 6> BoardController 클래스의 구현
    사용자 삽입 이미지

    public class BoardController : System.Web.UI.Page {
      protected void Page_Load(object sender, System.EventArgs e) {
        no = Int32.Parse(Request.Params["no"].ToString());
        GetArticle(no);
      }

      #region Web Form 디자이너에서 생성한 코드
      override protected void OnInit(EventArgs e) {
        InitializeComponent();
        base.OnInit(e);
      }

      private void InitializeComponent() {
        this.Modify_Article.Click +=
        new System.EventHandler(this.Modify_Article_Click);
        this.Load += new System.EventHandler(this.Page_Load);
      }
      protected virtual void GetArticle(int no) { }

      protected virtual void Modify_Article_Click(object sender, System.EventArgs e){}
    }
    사용자 삽입 이미지

    <그림 5>의 클래스 다이어그램에서와 같이, NoticeModify.aspx 페이지에 작성된 뷰와 모델을 컨트롤하는 컨트롤러 NoticeModify 클래스는 공통적인 구현을 포함하는 BoardController를 상속하고, GetArticle() 메소드와 Modify_Article_Click() 이벤트 핸들러를 오버라이드 하는 간단한 코드만으로 전체 컨트롤을 중앙 집중화 할 수 있다. BoardController 클래스의 Page_Load 이벤트 핸들러가 GoF 디자인 패턴[1]의 Template Method 역할을 하는 것이다. GoF의 디자인 패턴에서는, Template Medhod가 추상 메소드로 구현되고 기본 클래스가 추상 클래스이지만 ASP.NET에서는 Page를 상속하는 클래스가 추상 메소드가 될 수 없으므로, 가상 메소드로 구현하여야 한다.

    <코드 7> NoticeModify 컨트롤러
    사용자 삽입 이미지

    public class NoticeModify : BoardController {
      protected override void GetArticle(int no) {
        // Notice 모델에서 글을 가져와서 컨트롤에 바인딩한다.
      }

      protected override void Modify_Article_Click(object sender, System.EventArgs e) {
        // Notice 모델에 액세스하여 글을 업데이트 한다.
      }
    }
    사용자 삽입 이미지

    Page Controller 패턴을 사용하면 다음과 같은 장점을 얻을 수 있다.
  • 간단히 구현할 수 있다. 전체 컨트롤러를 중앙 집중화하는 Front Controller와는 달리 Page Controller 패턴은 하나의 동적인 페이지가 하나의 컨트롤러에 의해서 처리되므로, 간단함을 유지할 수 있다. 그러므로 Page Controller는 어느 정도 복잡한 웹 응용 프로그램에 적당하다.

  • ASP.NET이 제공하는 컨트롤러를 그대로 활용하여 일관된 개발 방향을 유지할 수 있다. 실저적으로 ASP.NET은 HttpHandler에 컨트롤러를 구현하고 있으므로, 기본적인 컨트롤러를 사용할 수 있다.

  • Template Method 패턴을 활용하므로 공통적인 구현에 대한 재사용성이 증가한다. 또한, 객체지향의 상속성을 이용하므로 쉽게 확장할 수 있다. 헬퍼 클래스를 사용하여 기능을 확장할 수도 있다.

    당연히, 단점도 있는법, Page Controller 패턴은 다음과 같은 단점을 가진다.

  • 객체 지향의 오랜 논란인 상속 트리가 깊어진다는 치명적인 단점을 가지고 있다.

  • 복잡한 응용 프로그램에 사용하면 감당할 수 없을 정도로 꼬인다는 단점이 있다.

    이런 문제를 해결하기 위해서, 전체 컨트롤러를 중앙 집중화 하는 Front-Controller 패턴을 사용할 수 있다. Front Controller 패턴과 Observer 패턴등은 조금 복잡한 클래스 구조를 가지게 되므로 다음 연재에서 닷넷 개발에서 UML과 케이스 툴을 사용하는 방법과 함께 생각해 보도록 하겠다.

    마치면서
    얼마 전, 마이크로소프트 리서치에서 F#이라는 새 언어를 본 적이 있다. (새 언어가 아니고 이전부터 연구되던 언어이긴 하다) 필자는 대학원 시절, 석사학위 논문 주제로 C#에서 Generics의 구현을 연구한 적이 있는데, 그때 많이 참조한 부분이기도 하다. F#은 ML을 기반으로 작성된 함수형 언어인데, 닷넷 환경에서는 COM을 위한 스크립트 언어 정도로 쓰이면 아주 강력할 것 같다는 느낌을 받았다.

    같이 근무하는 다른 연구원님들과 그런 이야기를 하다가, F#이라는 언어가 쓸모 있다고 해도 과연 C#이나 VB같은 언어들이 익숙한 개발자들에게 받아들여 질 수 있을까에 대해서 생각했다. 필자의 스승이기도 한 책임 연구원님은 특유의 어투로 “안 사용하면 말고.. 쓰고 싶으면 쓰고…” 라고 이야기 했지만 필자는 좋은 것이 있으면 반드시 사용해서 더 좋은, 제대로 된 응용 프로그램을 만들어야 한다는 쪽이다.

    개발자들도 의사고시 같은 시험이 생겨서 인턴, 레지던트 과정을 거쳐서 개발자 개업도 하고 하는 환경이 와야 우리나라 IT가 제대로 될 것 같다는 우스갯 소리도 했다. 새로운 피쳐가 등장하고 새로운 기법이 등장하였다고 반드시 그것을 사용해야 한다는 법은 없다. 하지만, 개발자들은 유수의 기업과 뛰어난 개발자 / 학자들이 연구한 산출물을 연구해 봐야 한다는 의무감을 가져야 한다고 생각한다. Enterprise Solution Pattern같은 뛰어난 결과들을 실제 개발에 응용하지는 않더라도 이러한 기법이 있더라 하는 것을 알고만 있는 것으로도 훨씬 더 훌륭한 구조를 가지는 뛰어난 프로그램을 작성할 수 있는 법이다.

    허준 같은 의원들의 의무가 환자들을 치료하고 보살피는 것이라면, 개발자들의 의무는 좋은 프로그램을 작성하는 것이다. 날로 떨어지는 개발자들에 대한 대우와 바쁜 일정이 그런 기본적인 의무감 마저 상실하게 하는 것 같아 씁쓸하긴 하다.@

    * 이 기사는 ZDNet Korea의 제휴매체인마이크로소프트웨어에 게재된 내용입니다.
  •  

    김상훈 (동명정보대학 정보기술원 연구원)

    2005/09/07

     

    사용자 삽입 이미지

     

     

     

     

    원문 :http://www.zdnet.co.kr/builder/dev/dotnet/0,39031607,39139339,00.htm

    신고
    0  Comments,   0  Trackbacks
    댓글 쓰기
    [기업 환경에 닷넷 적용하기] ③ 솔루션 패턴 해부하기

    [기업 환경에 닷넷 적용하기] ③ 솔루션 패턴 해부하기

     

    연재순서
    1.제대로 된 컴포넌트를 위한 프리젠테이션 레이어 설계하기
    2.비즈니스 로직 레이어 설계와 물리적 구현을 위한 필요 사항
    3.엔터프라이즈 솔루션 패턴 해부하기
    4.닷넷의 웹 프리젠테이션 패턴
    5.닷넷 개발에서 UML과 케이스 툴의 사용

     

    디자인 패턴은 양날의 검이다. 최근 들어 특히 패턴을 최대한 반영하지 않은 것이 차라리 좋은 설계라는 말이 공공연히 나돌고 있으며, 안티 패턴 웹 사이트도 생겨나고 있다.

    하지만 패턴은 엔터프라이즈 솔루션을 설계하고 작성할 때 그리고 결정 사항들을 효율적으로 공유하기 위한 목적으로 사용될 때 프로젝트의 성공에 기여할 수 있는 훌륭한 선물이 된다. 이번 호에서는 닷넷 기반 기업용 응용 프로그램의 설계와 구현에서 사용될 수 있는 디자인 패턴들에 대해 살펴보자.

    디자인 패턴은 버클리 대학 명예 교수이자 건축가인 크리스토퍼 알렉산더에 의해 처음 제안된 개념이다. 알렉산더 교수는 패턴을 다음과 같이 정의했다.

    “각각의 패턴은 우리를 둘러싸고 있는 환경에서 반복적으로 나타나는 특정한 문제와 그에 대한 해결책을 설명한다. 그리고 그 해결책은 계속 사용될 수 있기 때문에 동일한 과정을 반복할 필요가 없다.”

    알렉산더 교수는 여러 책을 저술했는데, 『The Timeless Way of Building』과 『A Pattern Language』등에서 그의 세계관을 철학적으로 풀어냈다. 소프트웨어 설계에서 나타나는 패턴은 결국 건축가인 알렉산더 크리스토퍼의 아이디어에서 나온 것이며, 켄트 벡과 커닝헌에 의해 소프트웨어 세계로 끌어들였고, 에릭 감마를 위시한 네 명의 일당들(Gangs of Four, 이하 GoF)이 전산에서의 디자인 패턴을 정리했다. 곧, 소프트웨어 전문가들은 패턴의 가치를 디자인 경험을 공유하기 위한 언어로 인식하였다.

    엔터프라이즈 솔루션들은 매우 복잡하다. 또한 솔루션이라도 시간과 의뢰인에 따라 시시각각 변화하는 요구사항을 모두 만족하기에는 거의 불가능하다. 지금 설계 또는 작성하고 있는 솔루션의 요구사항이 어떻게 변화할지 정확하게 예측하지는 못한다 하더라도 앞으로의 변화에 대해 적응하고 확장 가능할 수 있도록 작성되어야 한다. 그렇다면 설계자 또는 개발자는 어떻게 설계하고 코드를 작성하는 것이 좋은 설계인지에 대해 의문이 생기게 된다. 지금 작성하고 있는 설계 문서 또는 코드가 바른 설계인지 나쁜 설계인지 믿을 수 없다는 것이다.

    이런 경우, 설계자에게 오아시스 같은 해답을 내려줄 수 있는 것이 바로 ‘디자인 패턴’이다. 문제를 해결하기 위한 간단하고 작은 메커니즘에서 시작하여 크고 복잡한 시스템으로 결합되는 형태의 여러 디자인 패턴들은 경험 많은 개발자들과 설계자들의 노력 및 시행착오 속에서 정립된 것이고, 그들의 갖은 노하우에서 비롯된 귀중한 지식들이자 산출물이다.

    누군가 이름붙인 특정 디자인 패턴을 그대로 도입한다고 해서 문제가 곧 해결되는 경우는 드물지만, 디자인 패턴들은 좋은 설계와 코드 구현의 올바른 가이드가 되어줄 수 있다. 또한, 패턴은 간단한 메커니즘을 문서화할 수 있어 업데이트와 후임 개발자들의 소중한 교육 자료로 활용될 수 있다.

    디자인 패턴은 마이크로소프트(이하 MS) 플랫폼 기반 개발에서는 그다지 중요한 역할을 해오지 않은 것 같아 보였다. 하지만 주로 객체지향 환경에 맞춰진 디자인 패턴을 비주얼 베이직에서 활용하는 방법에 대한 연구 등이 활발하게 이뤄졌고, GotDotNET 등의 여러 커뮤니티에서는 몇 해 동안 시스템 아키텍처와 소프트웨어의 개발에 적용되는 패턴들을 발견해 왔다. 또한 MS는 여러 고객과 파트너 기업, 그리고 내부 개발자들의 피드백에 의해 MS 플랫폼에 특화된 디자인 패턴들을 정리할 필요가 있다고 느꼈다. 그 산물이 바로 ‘엔터프라이즈 솔루션 패턴(Enterprise Solution Patterns)’이다.

    MS는 몇 년 전에 닷넷 엔터프라이즈 아키텍처 센터(.NET Enterprise Architecture Center)를 통해 이 디자인 패턴들을 정리해서 공개했고, MSDN 웹 사이트의 「Enterprise Solution Patterns Using Microsoft.NET(참고자료)」을 통해 이를 확인해 볼 수 있다. 여기서는 단지 이 패턴들을 정리 요약하고, 이런 패턴들을 적용해 설계 및 작성해 본 경험을 풀어보고자 한다. 필자가 참여한 몇몇 기업용 응용 프로그램에서 이 패턴들은 솔루션의 재사용성과 확장 가능성을 높이는데 커다란 기여를 했다. 이번 호에서는 이러한 엔터프라이즈 솔루션을 작성하기 위한 패턴이 어떻게 구성되는지에 대해 알아보도록 한다.

    디자인 패턴 책을 달달 외운다?
    먼저 디자인 패턴과 관련해서 겪은 몇 번의 황당한 얘기들로 시작해 보자. 필자가 근무하는 기관에서 개발자를 고용하기 위해 공고를 내고 몇 번의 면접을 실시했다. 면접을 본 몇몇 개발자들에게 디자인 패턴에 대해 아느냐고 물어봤다. 한 개발자는 당연한 듯이 “그건 기본 아닙니까?”라고 당당하게 얘기하기에 패턴 기반 프로그래밍의 경험이 아주 풍부할 것으로 생각하고 이야기를 계속 진행하다보니, 그가 이야기하는 디자인 패턴은 웹 디자인을 이야기하는 것이었다. 다른 개발자는 디자인 패턴이라는 말이 나오자마자 GoF의 『디자인 패턴』에 나오는 패턴의 이름들을 좔좔 외워댔다. 디자인 패턴의 이름을 다 외우고 있는 건 좋은데, 어떤 경우에 어떤 패턴을 적용했느냐는 질문에는 대답하지 못하고, 다음과 같은 대답이 돌아왔다.


    “그냥 책 사서 책대로 코드만 짜봤습니다”


    패턴 기반 개발 경험이 많은 개발자들은 패턴을 익히는 것은 바둑에서 정석을 익히는 것과 같다고 이야기한다. 바둑에서 정석의 이름을 외우거나 내용을 암기하는 것은 실전에 아무런 도움이 되지 못하듯이 패턴의 기계적 학습은 실무에 아무런 도움을 주지 못한다고 이구동성으로 이야기한다. GoF는 소프트웨어 디자인 패턴을 다음과 같이 이야기한다.

    “설계 패턴은 객체지향 시스템 안에서 반복해 등장하는 설계와 관련된 문제들을 해결하기 위한 일반적인 기법에 이름을 붙이고 동기를 부여하고 설명을 한다. 그것은 문제와 해결책을, 그리고 그 해결책을 언제 적용해야 하는지, 적용한 결과는 무엇인지 등을 설명한다. 또한 실질적인 구현에 대한 힌트와 예제도 제공한다. 해결책은 문제를 해결하기 위한 필요한 객체와 클래스를 일반적인 방식으로 배치한다. 해결책은 주어진 문제를 특정한 문맥 안에서 해결하기 위해서 다듬어지고 구현된다(참고자료)”

    중요한 것은 패턴의 이름이나 구현된 코드가 아니라 그 이름이 담고 있는 내용이라는 것이다. 패턴은 소프트웨어의 설계에서 어떤 문제에 직면했을 때, 그 문제가 주어진 환경 내에서 반복하여 발생되는 것이라면, 그 문제를 기술하고 그 문제에 대한 솔루션을 제시해주는 역할을 한다. 패턴 기반 프로그래밍에서 가장 중요한 것은 특정 패턴이 어떻게 생겼느냐, 그 패턴의 이름은 무엇이냐, 그 패턴에 참여하는 객체들은 어떤 역할로 구성되느냐 하는 것이 아니고 당면한 문제가 무엇인지를 파악하는 것이다.

    패턴은 어떠한 환경에서 자주 발생하는 문제들을 해결하기 위한 솔루션을 제시하고, 그 솔루션은 문제를 해결하기 위해서 함께 동작하는 두 개 이상의 클래스, 객체, 서비스, 프로세스, 서비스, 쓰레드, 컴포넌트, 노드 등이 유기적으로 엮여 있는 간단한 메커니즘일 뿐이다.

    설계 패턴들은 ‘문제-해결책’의 쌍으로 제공되고 이해되어야 한다. 특히 디자인 패턴을 처음 접하는 개발자들은 어떠한 문제를 해결하건 간에 설계 패턴을 활용해야 한다는 강박증에 사로잡혀 있는 경우가 많다. 하지만 설계 패턴을 적용하지 않고도 해결할 수 있는 그것을 적용하지 않는 것이 바람직한 설계가 되는 경우가 대부분이다. 문제를 파악하는 것이 설계에서 가장 중요한 요소가 되고, 어떠한 패턴을 적용할 것인지는 그 다음에 생각할 문제가 되어야 한다.

    MS의 「Pattern & Practice」에서는 시스템 내의 모든 쿼트(Quote)들을 관리하는 프로그램의 예를 설명하면서singleton 패턴을 예로 들어 설명한다. 전체 시스템에서 인용부호는 수도 없이 등장한다. 쿼트 하나를 관리하기 위해서 하나의 인스턴스를 생성하는 것은 틀림없는 낭비이다. 이런 경우, 시스템 내의 모든 인용부호는 오직 하나의 클래스 인스턴스에서만 관리되도록 설계되어야 한다. 이 문제에 대한 간단한 해결책은 다른 클래스가 해당 클래스를 생성할 수 없도록 생성자가 Private인 QuoteManager 클래스를 생성하도록 설계하는 것이다. 이런 식의 ‘문제-해결책’의 쌍으로서 Singleton 패턴을 살펴보자.


    ◆ 상황 : 초기화 과정을 제어함으로써 클래스에 대한 액세스를 제어한다.
    ◆ 문제 : 응용 프로그램은 전역적으로 접근되거나 유지되어야 하는 특정한 형식의 데이터를 포함한다. 동시에, 종종 이 데이터 형식은 시스템 내에서 고유하다. 어떻게 하면 클래스에 대한 액세스 가능한 인터페이스를 제공하면서 시스템 내의 인스턴스의 수를 제어할 수 있을까?
    ◆ 솔루션 : 클래스는 단일 인스턴스를 생성하고 해당 인스턴스에 대한 전역적인 액세스를 제공해야 한다. GetInstance라는 정적 메쏘드가 반환하는 Singleton 클래스의 정적 인스턴스를 포함하는 클래스를 생성한다.


     

    사용자 삽입 이미지
    <그림 1> 클래스 설계


    여러 설계 패턴들은 이러한 문제-해결책 형태로서의 쌍으로 인식되어야 한다. 예로 보여준 Singleton 패턴을 닷넷 기반 개발에 적용하여 사용하는 방법은 무엇일까? 그것은 닷넷 개발자들이 알아서 해야 할 일이다. <그림 1>과 같이 설계된 구조라면 구현하는 것은 그리 어렵지 않다. 패턴 기반 개발에서 가장 중요한 것은 문제를 제대로 파악하는 것이다. 어떤 패턴을 적용하여 개발할 것인가 하는 것은, 문제가 제대로 파악된 다음에 생각해야 한다.

    패턴의 추상화 수준
    설계 패턴을 공부하기 위해 가장 많이 접하게 되는 책, 설계 패턴의 바이블이기도 한 GoF의 『디자인 패턴』은 주로 코드 차원에서의 설계 패턴들을 다루고 있다. 앞에서 예로 들었던 Singleton 패턴 역시 코드 수준에서 생각할 수 있는 패턴들이다. 그래서 설계 패턴이라고 하면 GoF가 정리한 패턴 위주의 코드 수준 활용을 생각하기가 쉬운데, 응용 프로그램의 추상화 수준이 여러 단계 이듯이 설계 패턴에서의 추상화 수준도 존재한다. 다음과 같은 상황에 처해있다고 하자.

    상황 :크고 복잡한 시스템을 다루고 있으며, 시스템을 분해하여 복잡성을 관리하고자 한다.

    이 상황에서 시스템 복잡성을 어떻게 관리할 것인가 하는 것이 문제로 던져진다. 솔루션을 잘 작성하기 위해 다음과 같은 문제를 제시할 수 있다.

    질문 :유지 보수 가능, 재사용성, 확장성, 견고성, 보안과 같은 기능적인 요구사항들을 만족하기 위하여 응용 프로그램을 어떻게 작성할 것인가?

    원망같이 들리는 저 ‘어떻게’를 위하여 수없이 많은 개발자들이 밤 새워가며 고민들을 했을 것이다. 이 문제를 해결하기 위해 제시되는 것은 의존성 관리와 상호 교환이 가능한 컴포넌트의 사용이라는 간단한 방법이다. 이 문제는 『Pattern & Oriented Software Architecture』에 소개된 Layers 패턴을 적용하여 해결할 수 있다.

    해결책 :솔루션을 계층 집합으로 구성한다. 각 계층은 반드시 응집되어야 하고 동일한 추상화 수준이어야 한다. 각 계층은 아래 계층과 느슨한 결합(Loosely Coupled)으로 이루어져야 한다.

    사용자 삽입 이미지
    <그림 2> Layers 패턴


    구현은, 물론 특정 플랫폼 하에서 개발하는 개발자들의 몫이 된다. 닷넷 플랫폼 기반 개발이라면 이러한 구현은 너무도 간편하게 할 수 있다. 이러한 높은 수준의 메커니즘은 앞에서 예제로 살펴본 Singleton 패턴의 메커니즘보다 훨씬 복잡하다(물론 GoF의 여러 패턴 중에서 Singleton 패턴이 가장 간단한 구조를 가지고 있긴 하다).

    Layers 패턴의 경우, 장점은 계층화된 조직이 소스 코드의 변경 효과를 코드가 속한 계층에 국한시켜, 전체 시스템에 영향을 주는 것을 막아준다. 이는 각 계층 간의 의존성 관계를 잘 설계함으로서 가능해진다. 각 계층 내의 독립적인 컴포넌트들이 시스템의 다른 영역들과의 충돌을 방지해 주는 메커니즘을 가지게 된다. Layers 패턴은 일반적으로 네트워크 프로토콜, 시스템 소프트웨어, VM 등과 같은 분야에 활용된다.

    하지만 Layers 패턴이 모든 문제를 해결해 주지는 못한다. 특히, 기업용 응용 프로그램 분야에서 개발자들은 비즈니스 로직을 효율적으로 관리할 수 있도록 해야 하고, 데이터베이스와 같이 복잡하고 가변적이며 비싼 리소스를 활용해야 한다. 비즈니스 솔루션들은 비즈니스 로직을 효율적으로 사용하고 데이터베이스 리소스를 관리하는 것이 관건이 되므로 Layers 패턴은 기업용 응용 프로그램을 작성할 때 당면하는 문제에 대한 해결책이 되어 줄 수가 없게 된다. 그러면 다음과 같은 상황에 직면한다.

    상황 :응용 프로그램을 구성하기 위해서 계층을 사용하는 비즈니스 솔루션을 작성하고 있다.

    상황에 직면하면 다음과 같은 문제가 제시된다.

    문제 :비즈니스 로직을 재사용하고 융통성 있는 배포를 제공하며 데이터베이스와 같은 리소스에 효율적으로 연결하기 위하여 응용 프로그램을 어떻게 구성할 것인가?

    해결책은 여러 가지 생각해 볼 수 있겠지만, 이러한 문제에 대한 해결책을 제시해 주는 패턴은 Therr-Layered Application 패턴이다.

    해결책 :프리젠테이션, 비즈니스 로직, 데이터액세스라는 3계층을 생성한다. 각 계층은 다음과 같이 구성한다.


    ◆ 프리젠테이션 계층 - 뷰와 관련된 모든 컴포넌트를 이 계층에 위치시킨다.
    ◆ 비즈니스 계층 - 비즈니스 로직을 구현하는 모든 컴포넌트들을 이 계층에 위치시킨다.
    ◆ 데이터 액세스 계층 - 데이터베이스 클라이언트 액세스와 헬퍼 클래스들을 포함한 모든 데이터베이스 관련 코드를 이 계층에 위치시킨다.


    각 계층을 구성할 때 주의 사항은 다음과 같다.


    ◆ 비즈니스 로직의 컴포넌트는 잘 알려진 인터페이스(닷넷의 예를 들면 리스트를 표현하는 IList 인터페이스 등)를 구현하게 구성하여 각 계층 간의 통합 가능성과 교체 가능성을 높이도록 설계한다.
    ◆ 데이터 액세스 계층은 리소스를 관리할 때 커넥션 풀링을 처리할 수 있어야 하며, 비즈니스 계층의 컴포넌트들과 상호의존 관계를 가져서는 안된다.


     

    사용자 삽입 이미지
    <그림 3> Three Layered Application 패턴


    이런 구현은 너무도 당연시 되는 구조이지만 문제를 생각하지 않고 무조건 이런 구조를 따라 설계하거나, 이런 문제가 제시됨에도 불구하고 이러한 구조를 따르지 않는 경우가 허다하다. 무조건 이러한 패턴을 따르는 것이 정답이라는 것은 아니지만, 경험 많고 능력 있는 개발자들이 정리한 이러한 패턴에 따라 문제를 해결하는 것이 대부분의 경우 정답이 되어준다.

    잊지 말아야 할 것은 패턴과 패턴 응용 프로그램을 잘 구분해야 한다는 것이다. 패턴 그 자체가 응용 프로그램일 수는 없다. 패턴은 문제-해결책 쌍으로서의 일반화된 해결책일 뿐이다. 그 문제의 해결책인 패턴을 응용하여 작성된 프로그램이 패턴 응용 프로그램이 된다. 패턴은 일반화된 문제 해결책 모음이고, 특정 요구사항을 특정 패턴을 사용하여 특정한 문제를 해결한 것이 패턴 응용 프로그램이라는 것을 알고 설계해야 한다.

    Three-Layered Application 패턴을 조금 응용하면 더 확장성 높은 응용 프로그램을 만들 수 있다. 최근 크게 이슈화되고 있는 웹 서비스 응용 프로그램을 생각해 보자. 작성한 응용 프로그램을 스마트 클라이언트에서 동작하게 한다거나 언제, 어디서든 실행될 수 있는 웹 서비스 응용 프로그램으로 확장해야 할 필요가 있을 때, Three-Layered Application 패턴을 활용하기가 곤란해진다. 그렇다면 다음과 같은 질문이 대두된다.

    문제 :응용 프로그램이 매우 유동적인 소스로부터 데이터와 논리적인 요소들을 제공하고 사용하기 위해서 응용 프로그램을 어떻게 구성해야 할까?

    해결책은 Three-Layered Service Application 패턴이 제시한다. 문제 해결을 위해서 비즈니스 계층이 서비스를 제공하는 Service Interface들을 제공하는 것이다. 또한, 유동적인 데이터 소스로부터 데이터를 제공받기 위해서 데이터 액세스 컴포넌트들이 아닌 서비스 에이전트 컴포넌트들로부터 소스를 제공받을 수 있도록 설계하는 것이 해결책이다.

    해결책 :응용 프로그램의 로직을 전체 시스템 기능의 일부를 제공하는 협력 서비스 집합으로 분해시킨다. 다음으로 도메인 계층에서 내부 구현에 독립적인 각각의 서비스에 대한 Service Interface를 명시한다. 마지막으로 다른 서비스 제공자와 커뮤니케이션하기 위하여 Service Agent를 사용하기 위해서 데이터 액세스 계층을 확장한다.

    사용자 삽입 이미지
    <그림 4> Three-Layered Services Application 패턴


    Three-Layered Service Application 패턴은 연재 첫 회에서 살펴보았던 응용 프로그램 아키텍처의 구조와 거의 일치한다. 물론, 응용 프로그램의 요구사항이 유동적인 소스로부터 데이터를 제공받거나 유동적인 클라이언트에 서비스를 제공하는 경우가 아니라면 Three-Layered Application 패턴으로 충분하다.

    패턴 클러스터
    지금까지 살펴본 바와 같이 Three-Layered Services Application 패턴은 Three-Layered Application 패턴에서 확장되었고, Three-Layered Application 패턴은 Layers 패턴에서 확장되었다. Layers 패턴의 변형은 응용 프로그램의 계층화에 대한 공통적인 접근 방법을 표현하는 패턴 클러스터를 구현한다. 패턴 클러스터링은 이러한 상황에서 그룹지어질 때 유사한 패턴 간의 논리적인 그룹화를 의미하게 된다. 패턴을 굳이 그룹화하여 분류할 필요는 없지만, 이런 클러스터된 패턴의 개념은 전체 응용 프로그램을 구성하기 위해 패턴 뷰를 확장하고 솔루션 영역에서 유사한 개념을 설명하는 패턴 클러스터를 명시할 때 상당히 유효할 뿐만 아니라, 프로젝트에 새로 투입되는 개발자의 교육 자료로도 훌륭히 활용된다.

    사용자 삽입 이미지
    <그림 5> Layers 패턴에서 확장되는 패턴 클러스터


    GoF가 정리한 디자인 패턴을 살펴보면 각 패턴들은 생성, 구조, 동작 등의 세 집합으로 분류된다. 객체를 생성하는 작업을 위해서라면 추상 팩토리 패턴이나 singleton 패턴을, 구조를 결정해야 한다면 Composite 패턴이나 Facade 패턴을, 동작을 결정하는 작업이라면 Visitor 패턴이나 Observer 패턴을 사용할 수 있다.

    또한 각각의 패턴들은 다른 패턴들과 관계를 가지고 여러 가지의 패턴을 묶어 다른 하나의 패턴으로 사용하기도 한다. Observer 패턴은 MVC(Model-View-Controller) 패턴의 일부분을 구현하기 위해서 사용되고, Command 패턴은 Front Controller 패턴의 일부 구현에 사용된다. 이런 패턴들 간의 관계가 없다면, 엄청난 패턴의 바다에서 표류하게 될 가능성이 높다. 객체지향 프로그램 개발자들이 패턴을 받아들인 이유는 패턴이 관계들을 기술할 수 있기 때문이다.

    이렇듯이 패턴 간의 관계를 도표화하면 하나의 패턴에서 그와 관련된 다른 패턴을 찾아 응용 프로그램을 구성하는데 큰 도움을 준다. 하지만 응용 프로그램을 작성하기 위해 어디에서 어떻게 시작해야 할지에 대해서는 알려주지 않는다. 하지만 단순히 분류에 그치지 않고 <그림 5>처럼 패턴을 클러스터링하면, 어떤 패턴에서 응용 프로그램을 시작하여야 할지를 잘 알 수 있게 된다. MS의 「Patterns & Practices」에서는 현재 크게 다섯 가지의 패턴들을 분류한다.


    ◆ Enterprise Solution Patterns Using Microsoft .NET
    ◆ Data Patterns
    ◆ Integration Patterns
    ◆ Describing the Enterprise Architectural Space Testing Software Patterns


    가장 유명하며, 가장 많이 활용되는 Enterprise Solution Patterns using Microsoft .NET에서는 현재 <표 1>과 같은 패턴 클러스터들을 구분하고 있다.

    사용자 삽입 이미지
    <표 1> Enterprise Solution Patterns using Microsoft .NET의 패턴 클러스터


    또 반드시 알아야 할 것은, 각 패턴들은 서로 다른 추상화 수준에 존재한다는 것이다. 개발자는 수없이 많은 페이지에 대한 요청을 중앙 집중화하기 위하여 Front Controller 패턴을 가장 효율적으로 구성하는데 관심이 많겠지만, 설계자는 Layers 패턴을 사용할 것인지 Three-Layered Application 패턴을 사용할 것인지에 관심이 많을 것이다. MS의 「Pattern & Practice」에서는 이러한 서로 다른 추상화 수준에서의 분류를 패턴 그래프를 이용해서 세 가지 계층으로 구분한다.

    사용자 삽입 이미지
    <그림 6> 추상화 수준(출처 :참고자료)


    Architecture 수준의 패턴은 MS의 「Architecture Center(참조자료)」을 참조하기 바란다.

    구현 수준 패턴
    패턴의 집합들을 <그림 6>과 같이 세 가지 추상화 수준으로 나누면 개발에 참여하는 설계자, 개발자 등의 다른 사용자 그룹이 자신의 전문적인 기술에 관련된 패턴을 쉽게 찾아볼 수 있게 된다.

    모든 언어 또는 플랫폼에서 사용할 수 있는 패턴들이 아닌, C#이나 닷넷 플랫폼 같은 특화된 언어 또는 환경 특화된 패턴을 idiom이라고 부른다. MS의 Enterprise Solution Patterns Using Microsoft .NET에서는 모든 응용 프로그램 개발 단계를 아우르기 위한 집약적인 시스템을 위해서 구현 수준 설계 패턴들을 정리했다. Enterprise Solution Pattern에 등장하는 거의 모든 패턴들은 구현 수준의 패턴에 해당한다. Enterprise Solution Pattern의 한 클러스터인 Web Presentation Pattens 다음 패턴들은 모두 구현 수준의 패턴들이다.


    ◆ MVC 패턴
    - 문제 : 개별적인 부분을 쉽게 수정하기 위해서 웹 응용 프로그램의 사용자 인터페이스 기능을 어떻게 모듈화 할 것인가
    ◆ Page Controller 패턴
    - 문제 : 코드 중복을 피하여 재사용과 융통성을 갖기 위해서 어느 정도 복잡한 웹 응용 프로그램에 대한 컨트롤러를 구성하기 위한 최상의 방법은 무엇인가?
    ◆ Front Controller 패턴
    - 문제 : 코드 중복을 피하여 재사용과 융통성을 갖기 위해서 아주 복잡한 웹 응용 프로그램에 대한 컨트롤러를 구성하기 위한 최상의 방법은 무엇인가?
    ◆ Intercepting Filer 패턴
    - 문제 : 웹 페이지 요청에 대하여 공통적인 선행 처리와 후행 처리 단계를 어떻게 구현할 것인가?
    ◆ Page Cache 패턴
    - 문제 : 자주 요청되지만 생성하기 위해서 엄청난 시스템 리소스를 소비하는 동적으로 생성되는 웹 페이지의 응답 시간을 어떻게 줄일 수 있을 것인가?
    ◆ Observer 패턴
    - 문제 : 다른 클래스에 의존하기 않고 다른 객체의 상태가 변경되었음을 어떻게 알릴 수 있을까?


    각 패턴의 상세한 사항들은 다음 호에서 상세히 알아보도록 한다.

    연구된 모든 패턴은 닷넷에서 구현된다
    경험 많은 개발자라면 프로그램을 설계할 때 예전에 했던 일을 그대로 반복하고 있다는 느낌을 받을 때가 많다. 경험이 축적되면, 그 경험을 살려서 다음 개발에 적용할 때가 있다. 설계 패턴(디자인 패턴)은 이러한 경험과 내공을 정리한 것에 지나지 않는다.

    학생들이 프로젝트를 진행할 때 if문으로 점철된 너무 복잡한 코드를 쓰는 경우가 많다. 그런 경우 필자는 “이런 경우에는 이런 패턴을… “ 이라는 말로 코드 개선을 요구한다. 보통 학생들은 디자인 패턴이라는 말이 나오면 한숨부터 쉬게 된다. 너무 어렵다는 것이다. 하지만 디자인 패턴은 결코 어려운 것이 아니다. 디자인 패턴이 어렵게 느껴지는 이유는 문제를 파악하려 하지 않고 패턴만을 외우려 하기 때문이다. 꼼꼼한 요구사항 분석으로 문제들을 파악했다면, 패턴 응용 프로그램을 작성하는 것은 전혀 어려운 일이 아니고, 조금 더 많은 생각으로 아주 재사용성과 활용성 높은 프로그램을 작성할 수 있게 된다.

    2년쯤 전, 필자는 어떤 솔루션을 구축하면서 Page Controller 패턴을 활용했다. 코드를 본 다른 회사의 개발자는 “이거 닷넷 구조가 아니고 자바 구조군요 이런 건 처음 봅니다. 아주 재미있네요”라고 이야기했다. 이상하게도 닷넷 개발자들은 디자인 패턴 같은 것은 자바 쪽에서 사용되는 것이라고 생각하는 경우가 많다.

    심지어 국내 굴지의 개발사 사장님은 “자바는 천재들이나 하는 것이고 닷넷은 아무나 할 수 있는 것이므로 닷넷을 하는 게 좋다”라는 망언(?)까지 하셨다.

    연구된 모든 패턴들은 닷넷 환경에서 제대로 구현하고 있고, MS는 커뮤니티를 운영하고 조합하면서 연구된 기술들을 활용하여 닷넷 플랫폼에 특화된 패턴들을 내 놓았다. 이런 패턴들은 별 다른 의심의 여지없이 닷넷 기반 응용 프로그램 개발에 사용될 수 있고, 좋은 성능과 높은 확장성을 기대할 수 있다. MS가 이번에는 제대로 하고 있는 것 같다.@

    * 이 기사는 ZDNet Korea의 제휴매체인마이크로소프트웨어에 게재된 내용입니다.

     

    김상훈 (동명정보대학 정보기술원 연구원)

    2005/08/24

     

    사용자 삽입 이미지

     

     

     

     

    원문 :http://www.zdnet.co.kr/builder/dev/dotnet/0,39031607,39136897,00.htm

    신고
    0  Comments,   0  Trackbacks
    댓글 쓰기
    [기업 환경에 닷넷 적용하기] ② 비즈니스 레이어 설계·구현

    [기업 환경에 닷넷 적용하기] ② 비즈니스 레이어 설계·구현

     

    연재순서
    1.제대로 된 컴포넌트를 위한 프리젠테이션 레이어 설계하기
    2.비즈니스 로직 레이어 설계와 물리적 구현을 위한 필요 사항
    3.엔터프라이즈 솔루션 패턴 해부하기
    4.닷넷의 웹 프리젠테이션 패턴
    5.닷넷 개발에서 UML과 케이스 툴의 사용

     

    기업용 응용 프로그램뿐 아니라 모든 컴포넌트 기반 프로그래밍에서 가장 중요한 비중을 차지하는 계층이 비즈니스 계층이다. 데이터나 프리젠테이션 계층의 컴포넌트는 응용 프로그램의 형태에 따라 존재하지 않을 수도, 프로세스가 해당 계층을 거치지 않고도 동작할 수 있다.

    하지만 비즈니스 계층의 컴포넌트는 어떠한 상황에서 실행되는 프로세스라도 결코 피해갈 수 없다. 비즈니스 계층의 컴포넌트를 설계하기 위해서는 '상태가 없는(Stateless) 동작으로서의' 의미로 비즈니스를 인식하는 것이 중요하다. 이번 글에서는 엔터프라이즈 솔루션 아키텍처에서 비즈니스 계층을 구성하는 컴포넌트를 제대로 설계하기 위한 여러 권장사항과 설계 기법들을 알아본다.

    프로젝트가 진행될 때 가장 크게 고려되는 사항은 ‘비즈니스 로직을 어떻게 설계할 것인가?’이다. 특히 프리젠테이션 계층에서 제공하는 사용자 컴포넌트들이 풍부한 닷넷 환경에서는 닷넷 프레임워크가 제공하는 컴포넌트들을 거의 그대로 사용하고, 요구사항 분석에 따른 업무의 흐름을 담당하는 비즈니스 로직 계층을 어떻게 구성할 것인가가 주 관건이 된다.

    MVC를 확연하게 구분할 수 있는 환경을 제공하는 프리젠테이션 계층과 달리, 닷넷에서는 비즈니스 로직 계층을 구성할 수 있는 어떤 자동화된 방법이나 구조를 특별히 제공하지는 않는다. 그렇다면 비즈니스 로직 계층에 존재하는 컴포넌트들을 어떻게 개발해야 하는지가 프로젝트의 성패를 가늠하는 가장 중요한 문제가 되는데, 이럴 때 컴포넌트를 ‘어떻게’ 구성해야 하는지에 대한 훌륭한 해답이 바로 닷넷 엔터프라이즈 아키텍처이다.

    닷넷 엔터프라이즈 솔루션 아키텍처 기반에서 비즈니스 로직 계층 컴포넌트들의 구성과 데이터 액세스 계층에서 컴포넌트의 구성을 알아보자.

    비즈니스 계층 컴포넌트의 구성
    사실상 기업용 응용 프로그램의 핵심은 응용 프로그램이 제공하는 비즈니스 기능이라 할 수 있다. 기업용 응용 프로그램의 존재 이유는 바로 이런 비즈니스들을 어떻게 자동화할 것인가에 있다고 해도 과언이 아니다(사실 컴포넌트의 공식 명칭은 ‘비즈니스 컴포넌트’이다). 3-티어 구조의 응용 프로그램에서 비즈니스 컴포넌트 계층에 존재하는 컴포넌트들은 프리젠테이션 계층의 사용자 프로세스 컴포넌트나 컨트롤러의 호출로 일단의 프로세스를 수행한다. 닷넷 엔터프라이즈 솔루션 아키텍처에서 비즈니스 컴포넌트 계층 컴포넌트는 <그림 1>과 같은 구조로 구성된다.

    사용자 삽입 이미지
    <그림 1> 비즈니스 계층 컴포넌트

    <그림 1>에서 알 수 있듯이 비즈니스 계층은 굳이 나누자면 세 종류의 역할을 하는 컴포넌트들로 구성된다. 비즈니스 엔티티 역할을 하는 컴포넌트는 표현되는 데이터를 포함하는 객체들로 이뤄진다. 비즈니스 컴포넌트 역할을 하는 컴포넌트는 비즈니스 엔티티 컴포넌트에 포함된 객체를 생성하고 동작들을 지정하며, 데이터 액세스 로직 컴포넌트를 호출하는 동작과 비즈니스 엔티티 객체의 상태를 변경하는 등의 오퍼레이션을 담당한다. 비즈니스 워크플로우 역할을 하는 컴포넌트는 분산 트랜잭션 또는 분산 시스템에서 프로세스의 수행이 완료될 때까지 비즈니스 작업을 조율하고 상태를 저장하는 등의 여러 동작을 수행한다. 서비스 인터페이스는 당연히 GOF 디자인 패턴에서의 전형적인 Facade 역할을 담당한다.

    <그림 1>의 비즈니스 계층에서 계층 구성이 가장 단순한 경우를 생각해 보자. 비즈니스 엔티니 컴포넌트와 비즈니스 워크플로우 없이 비즈니스 컴포넌트만 사용하는 경우다. 닷넷 환경이 도입되기 이전의 ASP 개발 환경에서 즐겨 사용하던 방법으로서, 비즈니스 엔티티 컴포넌트로 ADO가 제공하는 레코드셋 등의 개체를 사용한다. 비즈니스 컴포넌트에는 데이터베이스에 액세스하여 레코드셋을 만들어 내고, 프리젠테이션 계층 역할을 하는 ASP 페이지에 레코드 셋을 넘겨줘 페이지에 보이게 하는 경우였다.

    닷넷 프로그래밍이 국내에 처음 소개되던 무렵에는 비즈니스 컴포넌트를 COM 개체가 아닌 닷넷 어셈블리로 컴파일하여 사용하는 경우가 많았다. 필자 역시 웹 개발에서 레지스트리에 등록된 COM 개체를 유지 보수하기 위해 IIS를 내렸다 올렸다 했던 환경에서 운영 환경에 특정 컴포넌트를 물지 않는 닷넷 환경의 편리함에 감탄한 적이 있다.

    가장 단순한 경우의 컴포넌트 구성이 반드시 틀렸다는 것은 아니다. 항상 주장하는 말이지만 닭 잡는 데는 닭 잡는 칼을 써야 하고 소 잡는 데는 소 잡는 칼을 써야 한다. 간단한 구조의 응용 프로그램이라면 이와 같이 구성하는 것이 개발 사이클이나 유지 보수성 등의 측면에서 훨씬 뛰어날 수도 있다. 하지만 기업용 응용 프로그램이라면 이야기가 달라진다. 세션 또는 닷넷에서 제공하는 추상화된 개체인 HttpContext, HttpModule 등을 사용하여 사용자를 관리하고, 수시로 변하는 데이터를 수많은 클라이언트가 열고 있는 경우라면 어떨까? 앞에서 이야기한 가장 간단한 형태의 컴포넌트 구성은 개발 당시의 생산성 측면에서나 유지 보수성, 성능 등의 모든 면에서 복잡도가 증가하게 된다.

    가장 복잡한 경우는 여러 서비스를 이용하거나 분산 시스템 기반에서 응용 프로그램을 작성하는 것이다. 수없이 많은 클라이언트들이 응용 프로그램을 사용하고 분산 트랜잭션과 분산 서비스에서 비즈니스 워크플로우를 제어해야 한다면 비즈니스 엔티티 컴포넌트는 물론, COM+나 비즈토크 오케스트레이션(Biztalk Orchestration) 등을 사용하는 비즈니스 워크플로우를 모두 구성하는 것이 바람직하다. 물론, 모든 컴포넌트에는 서비스 인터페이스가 존재하여 프리젠테이션 계층 컴포넌트에서 직접 호출을 추상화하여 제공하는 창구가 필요하다.

    단순하게 생각해 보자
    새로운 기술이나 이론 등을 접할 때 가장 당황스러운 것은 새로운 용어를 접할 때이다. <그림 1>에서 등장하는 새로운 용어들로 인하여 장애를 느끼는 독자라면 <그림 2>를 보자. 컴포넌트의 구성은 그 컴포넌트가 어떠한 일을 해야 하는지를 결정하는(그 역할에 따라 구성하는) 것이 가장 바람직하다. <그림 2>는 비즈니스 계층의 컴포넌트들이 어떠한 역할을 해야 하는지를 잘 설명한다.

    사용자 삽입 이미지
    <그림 2> 비즈니스 계층 컴포넌트들의 역할

    응용 프로그램 망/흐름 제어로 설명된 비즈니스 워크플로우 프로세스의 역할부터 알아보자. 이 역할을 하는 컴포넌트는 가장 쉽게 생각해 여러 대의 다른 역할을 하는 엔터프라이즈 서버로 구성됐거나 다른 도메인에 존재하는 다른 기업 간의 프로세스 흐름에서(B2B 또는 EAI 프로젝트에서) 그 망을 구축하고 프로세스의 흐름을 제어한다. 언뜻 분산 처리를 담당할 수 있는 COM+와 MSDTC를 떠올릴 수 있지만 COM+ 또는 MSDTC는 동작의 역할을 하는 비즈니스 컴포넌트에서 사용되고(물론 COM+ 또는 MSDTC가 이런 역할을 할 수 없다는 것은 아니다. 하지만 엔터프라이즈 솔루션 아키텍처에서 비즈니스 워크플로우는 그런 분산 트랜잭션보다는 더 넓은 의미에서 비즈니스 워크플로우를 포함한다), 주로 이 역할을 담당하게 되는 것은 비즈토크 오케스트레이션이다.

    <그림 2>에서 동작으로 설명된 비즈니스 컴포넌트의 가장 주된 역할은 데이터를 받아들이고 반환하는 것이다. 비즈니스 컴포넌트는 캡슐화를 이용해 구현되는 높은 추상을 가지는 응용 프로그램의 동작을 구현한다. 비즈니스 컴포넌트를 통해 프리젠테이션 계층에서 응용 프로그램을 사용하는 사용자가 어떤 데이터 저장소를 사용하는지, 어떤 서비스를 이용하여 데이터를 처리하는지 등의 정보를 캡슐화해 좀 더 편리한 프로그래밍 인터페이스를 제공한다.

    중요한 것은 비즈니스 컴포넌트는 상태(state)를 가져서는 안 되며, 단순히 동작만을 제어해야 한다는 것이다. 프리젠테이션 계층의 컨트롤러나 사용자 프로세스 컴포넌트에서 호출되는 비즈니스 컴포넌트는 그 사용이 매우 빈번하고 복잡한 프로세스의 흐름을 가질 수 있으므로 비즈니스 컴포넌트가 특정 상태를 가지고 프로세스를 제어한다면 컴포넌트를 여러 사용자가 공유할 수 없게 된다.

    데이터는 반드시 각 사용자 별로 유지돼야 하므로 비 연결 지향의 ADO.NET 개체를 주로 사용하는 비즈니스 엔티티 컴포넌트가 상태를 가질 수 있거나 또는 반드시 가져야 하는 것과는 달리, 비즈니스 컴포넌트는 상태를 가질 수 없도록 설계돼야 한다. 비즈니스 컴포넌트는 데이터의 제어를 위한 동작이 주가 됨으로, 트랜잭션을 시작하고 관리할 수 있는 역할을 반드시 할 수 있어야 한다. 대부분의 응용 프로그램에서 트랜잭션의 시작은 주로 비즈니스 컴포넌트 역할의 개체들이 담당하게 되며, SQL 서버나 ADO.NET의 트랜잭션 지원 개체들이 트랜잭션 제어를 위해 사용되고, 분산 서버 환경이라면 엔터프라이즈 서비스를 이용하여 COM+와 MSDTC를 사용하게 된다.

    <그림 2>에서 데이터로 표현된 비즈니스 엔티티는 데이터를 표현하는데 사용된다. 비즈니스 엔티티 컴포넌트의 인스턴스는 비즈니스 컴포넌트의 호출로 생성되며, 호출된 비즈니스 컴포넌트의 트랜잭션이 종료되기 전까지 상태를 서버 또는 클라이언트에서 유지하면서 사용된다. 비즈니스 엔티티 컴포넌트가 데이터를 표현하는 것이므로 닷넷 기반 프로그래밍에서는 ADO.NET이 제공하는 여러 포맷, 즉 데이터 리더, 데이터 셋, 형식화된 데이터 셋, XML 문서 등을 주로 사용할 수 있다. 물론 프로그래머가 직접 디자인한 사용자 정의 개체도 사용될 수 있다.

    가장 권장되는 방법은 모든 데이터를 내부에 캡슐화하거나 데이터에 대한 특정한 행위를 필요로 하지 않는 경우 XML 문서나 ADO.NET이 제공하는 데이터 셋을 사용하는 것이다. 비즈니스 엔티티 컴포넌트는 스냅샷 데이터를 가져 정보의 로컬 캐시를 유지한다. 이러한 로컬 캐시를 데이터베이스의 데이터와 동기화하기 위한 Update 메쏘드 등을 제공해 줄 필요가 있다.

    마지막으로 서비스 인터페이스는 전형적인 Facade로 동작하게 디자인한다. 응용 프로그램의 비즈니스 계층 컴포넌트들이 서비스로서 노출시켜야 하는 경우라면 서비스 인터페이스 역할의 컴포넌트를 반드시 포함해야 한다. 서비스 인터페이스 컴포넌트를 추가했다면 다른 응용 프로그램의 서비스 에이전트들이 서비스를 이용할 수 있도록 할 수 있다. 서비스 인터페이스를 XML 웹 서비스로 구현하여 다양한 플랫폼의 응용 프로그램이나 다양한 장비에서 동작하는 응용 프로그램들이 같은 서비스를 사용할 수 있도록 할 수 있다.

    어떨 때, 어떻게 구현해야 하는가?
    앞서 언급했지만 100번을 강조해도 모자람이 없는 말이 바로 ‘닭 잡는 데는 닭 잡는 칼을, 소 잡는 데는 소 잡는 칼을’ 쓰는 것이다. 응용 프로그램의 아키텍처는 간단하면 간단할수록 좋다(그렇다고 모델 1 기법이 가장 좋은 방법이라는 말은 결단코 아니다. “응용 프로그램이 복잡해진다고 생각되는 그때 클래스를 추가하라”는 말을 기억하자). 엔터프라이즈 솔루션 아키텍처에서 <그림 1>과 같은 다이어그램을 제공한다고 해서 반드시 그 구조를 지켜야 한다는 것은 절대 아니다.

    응용 프로그램의 아키텍처를 설계하는 사람은 그 응용 프로그램의 역할과 복잡도를 충분히 파악하여 아키텍처를 구성해야 한다. 정답은 없다. 물론, 수학적인 공식을 사용해 요구사항 분석에 따른 역할을 파라미터로 복잡도를 분석하고 아키텍처를 설계하는 툴을 만들 수는 있다. 하지만 프로젝트라는 것이 시시각각으로 변하고 인프라의 환경에 따라 아키텍처는 유연하게 반응해야 하는 것이므로 적당한 관점에서 탄력적으로 운용될 수 있는 아키텍처를 설계하는 것이 중요하다.

    비즈니스 워크플로우 컴포넌트
    비즈니스 워크 플로우는 주로 비즈토크 오케스트레이션으로 구현되며, 다른 벤더의 솔루션이나 프로그래머가 개발한 사용자 정의 컴포넌트로도 구현될 수 있다. 다음과 같은 경우에 비즈니스 워크플로우를 포함하여 구성할 수 있다.

    ◆ 복잡한 단계의 비즈니스 트랜잭션을 처리하는 경우 :트랜잭션의 깊이가 너무 깊어지면 비즈니스 컴포넌트만으로는 감당할 수 없는 경우가 많아진다. 비즈니스 트랜잭션이 여러 서비스와 연동하는 경우에 프로세스의 각 단계를 내부에 캡슐화하는 비즈니스 컴포넌트를 작성하고 비즈니스 워크플로우가 비즈니스 컴포넌트를 조정하도록 하는 것이다. 소매 응용 프로그램에서 주문을 진행하는 프로세스의 경우가 대표적인 것이다.

    ◆ 장기 트랜잭션을 포함하는 프로세스를 관리하는 경우 :트랜잭션의 깊이가 깊지는 않더라도 처리되는 프로세스의 기간이 길어지는 경우가 있다. B2B 솔루션에서 파트너 업체와의 주문 처리 등이 이런 경우인데, 주문 처리에서 입고 처리까지가 하나의 트랜잭션으로 관리돼야 하는 경우, 즉 워크플로우의 상태를 장기간 유지해야 하는 경우에 비즈니스 워크플로우를 포함해 구성하는 것을 고려할 수 있다. 비즈토크 오케스트레이션은 이러한 비즈니스 워크플로우를 처리할 수 있도록 디자인되었다.

    ◆ 비즈토크 서버와 응용 프로그램간의 어댑터나 커넥터를 구성하여 서비스 에이전트와 통신하는 경우 :응용 프로그램이 비즈토크 서버와 통신해야 하는 경우 비즈토크 서버의 발신 데이터를 수신하여 비즈니스 엔티티를 생성하거나 데이터베이스에 입력하는 경우 등의 프로세스가 발생한다. 또한 여러 비즈토크와 통신하는 경우에 이러한 제어를 추상화하기 위한 비즈니스 워크플로우 프로세스가 필요하다.

    비슷한 절차가 필요하지만 다음과 같은 경우에는 비즈니스 워크플로우를 생략하고 비즈니스 컴포넌트만으로 구현할 수 있다.

    ◆ 비즈니스 흐름이 상태를 유지할 필요가 없는 경우 :상태를 유지하는 흐름이 아닌 단순 스탭으로만 이뤄지는 단일 서버의 프로세스라면 워크플로우 프로세스 없이 비즈니스 컴포넌트의 메쏘드를 순차적으로 호출함으로써 해결할 수 있다.

    ◆ 비즈니스 트랜잭션이 단일 트랜잭션으로 구성되는 경우 :하나의 트랜잭션으로 모든 절차를 완료할 수 있는 경우라면 비즈니스 워크플로우 프로세스를 구현할 필요가 없다.

    ◆ 데이터 구조를 직접적으로 액세스하는 경우 :비즈니스 워크플로우 프로세스는 자신이 상태를 가지고 비즈니스 컴포넌트를 컨트롤하는 절차를 수행하므로 비즈니스 컴포넌트가 사용하는 비즈니스 엔티티의 데이터에 직접 액세스하는 경우에는 사용이 까다로워진다.

    ◆ 장기적인 흐름 컨트롤이 아닌 로직에 대한 상세 컨트롤인 경우 :비즈니스 워크플로우는 비즈니스 컴포넌트가 운영하는 여러 절차를 추상화한 프로세스를 운영하므로 로직에 대한 상세 컨트롤에서는 사용하기가 어려워진다.

    비즈니스 워크플로우에서 반드시 고려해야 하는 점은 가격대 성능비적인 차원이다. 비즈토크 오케스트레이션은 어떠한 비즈니스 프레임워크보다 훌륭하게 동작하지만, 마이크로소프트(이하 MS)가 판매하는 엔터프라이즈 서버 제품군들 중 가장 가격이 높은 서버에 속하며, 그 전문가를 고용하는 가격 또한 가장 비싼 편에 속한다. 비즈니스 컴포넌트만을 사용하여 워크플로우를 구성하는 것이 서버를 도입하는 것보다 비용/기간 면에서 저렴하다면, 굳이 비즈니스 워크플로우를 포함하여 아키텍처를 설계하지 않아도 된다.

    비즈니스 컴포넌트
    비즈니스 컴포넌트는 어떠한 상황에서도 반드시 존재해야 하는 컴포넌트이다. 닷넷 환경이 처음 도입됐을 때 ASP.NET의 코드 비하인드 파일이 이런 비즈니스 컴포넌트 역할을 한다고 설명하는 경우가 많았으나 코드 비하인드 파일은 MVC 모델에서의 컨트롤러 역할을 수행해야 하고, 비즈니스 로직은 비즈니스 컴포넌트에서 구현해야 한다. N-티어 구조 응용 프로그램에서 각 계층은 느슨한 결합도로 조합되어 각 계층의 컴포넌트가 변화더라도 다른 계층의 컴포넌트에는 영향을 주지 않는 구조로 디자인되어야 한다. 코드 비하인드는 닷넷 아키텍처상 독립된 비즈니스 계층의 컴포넌트로 동작하는 것이 불가능하다.

    비즈니스 컴포넌트는 이미 존재하는 로직을 캡슐화하는 수준 높은 추상화를 제공하고, 변화 가능한 존재하는 비즈니스 기능들을 조합하는 등의 역할을 수행해야 한다. 객체지향 개발 방법에서 여러 디자인 패턴들을 응용하여 비즈니스 컴포넌트를 작성함으로써 이러한 빠른 변화에 능동적으로 대처할 수 있는 높은 추상성과 유지 보수성을 가지는 응용 프로그램을 작성할 수 있게 된다.

    비즈니스 컴포넌트를 작성할 때 절대로 간과하면 안 되는 것이 트랜잭션의 지원이다. 비즈니스 컴포넌트는 비즈니스 엔티티의 상태를 관리 및 수정하고 생성하는 역할을 담당할 수 있다. 따라서 비즈니스 엔티티 또는 데이터베이스에 존재하는 데이터의 일관성과 무결성을 지키기 위해 트랜잭션을 반드시 고려해서 작성해야 한다. 비즈니스 컴포넌트에서 트랜잭션 처리는 크게 두 가지로 고려될 수 있다. ADO.NET의 ITransaction 개체를 사용하여 트랜잭션을 처리하거나 또는 여러 서버로 구성된 응용 프로그램의 경우 COM+가 이용하는 MSDTC를 사용한다.

    비즈니스 컴포넌트를 작성할 때 주의해야 하는 것은 앞서 이야기했듯이 컴포넌트에 상태가 있어서는 안된다는 점이다. 비즈니스 컴포넌트 팩토리에서 언급한 컴포넌트 인스턴스의 3대 원칙을 그대로 준수해야 하는 진짜 컴포넌트가 이 비즈니스 컴포넌트가 된다. 상태가 없고 메시지 패싱을 원칙으로 하는 등의 비즈니스 컴포넌트의 기본 원칙에 따라 작성돼야 한다. 비즈니스 컴포넌트의 설계 권고 사항은 다음과 같다.

    ◆ 가급적이면 메시지 기반의 통신을 사용한다.

    ◆ 서비스 인터페이스로 노출된 프로세스에서 메쏘드가 두 번 호출되거나, 같은 인자 값을 가지며 같은 방식의 메시지가 전달되었을 때 데이터의 무결성을 유지할 수 있도록 설계되어야 한다 :서비스 인터페이스로 노출된 프로세스는 페이지의 리로드나 같은 서비스의 동시 사용 등으로 인해 같은 식별자를 가지는 데이터를 두 번 사용하거나 여러 명이 동시에 사용하게 되는 경우가 빈번하게 일어난다. 이럴 때를 대비할 수 있는 처리를 해야 하는데, 가장 좋은 방법은 아예 이런 프로세스를 원천적으로 봉쇄하거나 메시지 큐 등을 사용하여 직렬화하고 검증하는 등의 정책이 필요하다.

    ◆ 비즈니스 컴포넌트는 어떤 서비스 사용자의 컨텍스트에서도 사용될 수 있도록 한다 :펫샵 3.0을 설치해 본 독자라면 겪어봄직한 이야기이다. 펫샵은 데이터베이스 연결 문자열을 Web.Config 파일에 암호화하여 저장한다. 암호화된 연결 문자열에는 Trusted Connection을 사용하도록 설정되어 있다. 이런 설정으로 인해 데이터베이스 연결에서 오류가 발생하는 경우를 봤을 것이다. 이 때 impersonate 속성을 설정해 줘 응용 프로그램에 접근하는 사용자를 ASP.NET으로 인격화(Impersonation)하는 방법을 사용하면 데이터베이스에는 접근 가능하지만 필요한 어셈블리를 로드할 수 없다는 오류를 만나게 된다. 윈도우의 사용자 권한 정책과 데이터베이스의 연결 등의 여러 문제를 고려해 어떤 사용자라도 특별한 인격화 과정을 거치지 않고 비즈니스 컴포넌트에 접근할 수 있도록 설계해야 한다.

    ◆ 입력 매개변수와 반환 값은 일관성 있는 포맷으로 선택하고 유지한다 :반환 값으로 ADO.NET에 포함되어 있는 DataSet 개체 또는 스키마가 지정된 XML 파일 등을 사용하는 것이 가장 바람직하며, 비즈니스 엔티티에 사용자 정의 컴포넌트를 사용할 경우 일관된 정책 수립이 필요하다.

    ◆ 트랜잭션 격리 수준에 신경써라 :트랜잭션 격리 수준에는 정말 정답이 없다. 데이터베이스에서 데드락을 막을 수 없듯이 격리 수준은 파악된 요구사항에 따라 적절히 수립하는 수밖에 없다. 어이없는 경우는 트랜잭션 하에서 여러 명령이 수행되도록 작성하고, 수행되는 명령에서 오류가 발생하는 경우에 대한 처리를 잊어버리는 경우다. 이럴 때는 격리 수준이 ReadCommetted로 설정됐다면 데이터베이스에서 강제로 트랜잭션을 종료하기 전까지 데이터는 잠기게 된다. 어렵지 않고 기본적인 수준의 권고사항이지만 이 때문에 발생하는 어이없는 오류가 한 번씩 생기기 마련이다.

    펫샵의 예를 보자. 지난 글에서도 살펴봤듯이 펫샵은 잘 설계된 아키텍처에 따라 구성된다. 펫샵의 구조는 <그림 3>에서 살펴볼 수 있듯이 엔터프라이즈 솔루션 아키텍처의 원칙을 그대로 따른다(비즈니스 워크플로우는 존재하지 않는다).

    사용자 삽입 이미지
    <그림 3> 비주얼 스튜디오 닷넷의 속성창에서 본 펫샵 응용 프로그램 구조


    <그림 3>은 아키텍처 기반으로 구현된 응용 프로그램의 예를 들어 설명하기 위해 앞으로 계속 참조할 것이므로 유심히 봐두길 바란다. 전체 솔루션에 포함된 11개의 프로젝트 중 BLL 프로젝트가 비즈니스 컴포넌트에 해당한다. BLL 컴포넌트는 여러 개의 파일로 구성되어 있고, 작성된 클래스들은 비즈니스 컴포넌트 작성 권고사항에 따라 작성되었다. <그림 4>의 클래스 다이어그램에서도 알 수 있듯이 상태가 없는 오퍼레이션만을 가지고 있는 것을 알 수 있다.

     

    사용자 삽입 이미지
    <그림 4> BLL 컴포넌트의 클래스 다이어그램

    펫샵은 주문 처리를 위해 분산 데이터베이스를 사용한다. 분산 데이터베이스의 트랜잭션은 닷넷의 엔터프라이즈 서비스를 사용한다. <리스트 1>은 분산 트랜잭션을 위해 엔터프라이즈 서비스를 사용하는 OrderInsert 클래스의 소스코드이다. 주문을 수행하는 Insert 메쏘드에서 주문 처리를 위한 주문 정보 데이터베이스와 재고 관리를 위한 재고 정보 데이데이터 베이스 등 두 데이터베이스에서 분산 트랜잭션을 처리한다.

     <리스트 1> OrderInsert 클래스의 소스코드
    사용자 삽입 이미지
    using System;
    using System.Collections;
    using System.EnterpriseServices;
    using System.Runtime.InteropServices;
    using PetShop.Model;
    using PetShop.IDAL;

    namespace PetShop.BLL {
      [Transaction(System.EnterpriseServices.TransactionOption.Required)]
      [ClassInterface(ClassInterfaceType.AutoDispatch)]
      [ObjectPooling(MinPoolSize=4, MaxPoolSize=4)]
      [Guid("14E3573D-78C8-4220-9649-BA490DB7B78D")]
      public class OrderInsert : ServicedComponent {
        private const string ACID_USER_ID = "ACID";
        private const string ACID_ERROR_MSG = "ACID test exception thrown for distributed transaction!";

        protected override bool CanBePooled() {
          return true;
        }

        [AutoComplete]
        public int Insert(OrderInfo order) {
          // 주문 정보 데이터베이스 입력
          IOrder dal = PetShop.DALFactory.Order.Create();
          int orderId = dal.Insert(order);
          // 재고 정보 데이터베이스 처리
          Inventory inventory = new Inventory();
          inventory.TakeStock( order.LineItems);

          if (order.UserId == ACID_USER_ID)
            throw new ApplicationException(ACID_ERROR_MSG);

          return orderId;
        }
      }
    }
    사용자 삽입 이미지

    <리스트 2>는 주문 정보를 반환하는 아주 썰렁한 클래스 OrderRead 클래스의 소스코드이다. 어렵고 복잡하게 짠 코드가 잘 작성된 것은 아니라는 점을 확연히 보여준다. GetOrder 메쏘드는 잘 알려진 정수형의 파라미터를 받아들이고 주문의 정보를 표현하는 비즈니스 엔티티 컴포넌트에 포함된 OrderInfo 객체를 반환하도록 디자인되었다.

     <리스트 2> OrderRead 클래스 소스코드
    사용자 삽입 이미지
    using System;

    //References to PetShop specific libraries
    using PetShop.Model;
    using PetShop.IDAL;

    namespace PetShop.BLL {
      public class OrderRead{
        public OrderInfo GetOrder(int orderId) {
          if (orderId < 1)
            return null;
          IOrder dal = PetShop.DALFactory.Order.Create();
          return dal.GetOrder(orderId);
        }
      }
    }
    사용자 삽입 이미지

    <리스트 2>의 GetOrderInfo 메쏘드에는 if (ordered < 1)이라는 조건절이 포함되어 있다. 이는 주문 정보 번호가 유효한지 아닌지를 검사하는 유효성 검사를 수행하는 코드다. 비즈니스 컴포넌트는 프리젠테이션 계층의 컴포넌트가 아닌 다른 계층의 컴포넌트들, 즉 서비스 인터페이스, 다른 비즈니스 컴포넌트 등에서도 호출할 수 있으므로 이러한 유효성 검사는 반드시 필요하다. 다음은 비즈니스 컴포넌트의 구현에서 지켜야 하는 규칙들이다.

    ◆ 트랜잭션의 시작점이 된다. 비즈니스 컴포넌트가 참여하는 트랜잭션을 지원해야 한다.
    ◆ 입력과 출력에 대한 유효성을 검사할 수 있어야 한다.
    ◆ 데이터 액세스 로직을 호출하여 데이터를 가져오거나 갱신할 수 있어야 한다.
    ◆ 설치된 서비스 에이전트를 통하여 외부 서비스를 호출할 수 있어야 한다.
    ◆ 비즈니스 워크플로우를 초기화할 수 있어야 한다.

    <그림 5>는 다른 비즈니스 컴포넌트와 상호 작용하는 전형적인 비즈니스 컴포넌트의 모습을 보여준다.

    사용자 삽입 이미지
    <그림 5> 비즈니스 컴포넌트

    그리고 비즈니스 컴포넌트가 작성될 때는 흐름 제어를 위한 패턴인 순차 호출식의 파이프라인 패턴과 이벤트 호출식의 이벤트 패턴이 사용된다. 일반적으로 비동기적인 서비스를 포함하고 있으면 파이프라인 패턴을, 모든 활동의 초기 값이 동일하고 각 활동 간에 메시지 패싱이 필요 없을 때 이벤트 패턴을 사용한다.

    비즈니스 엔티티 컴포넌트
    비즈니스 엔티티는 전체 아키텍처를 고려할 때 반드시 필요한 사항은 아니다. 기업용 응용 프로그램에서 데이터가 존재하지 않는 경우는 없겠지만, 특히 ASP.NET 응용 프로그램에서 사용자 정의 비즈니스 엔티티를 작성하지 않고 ADO.NET에 포함된 데이터 셋이나 XML 문서를 사용하는 경우도 많다. 데이터 셋은 복잡한 정보를 포함할 수 있어 굳이 사용자 정의 비즈니스 엔티티를 포함하지 않아도 되며, 데이터 셋은 XML로 바로 변환할 수 있어 작업 및 문서 기반으로 프로젝트를 진행할 수 있기 때문이다.

    사실 거의 모든 기업용 응용 프로그램에서 비즈니스 엔티티를 사용한다. 일반적으로 상태를 표현하는 정보를 사용자 정의 엔티티에 포함한다. 사용자 정의 비즈니스 엔티티 컴포넌트 내의 객체는 상태를 표시하기 위한 전역변수 등의 데이터와 복잡한 데이터를 표현하기 위한 컬렉션이나 데이터셋을 포함한다. 이후 포함된 이들 컬렉션과 데이터셋 등의 개체를 프로퍼티로 지정하도록 설계하여 구현된 비즈니스 엔티티 컴포넌트가 자신을 호출하는 사용자 프로세스 컴포넌트 또는 비스니스 컴포넌트 등에 노출시켜 주는 기법을 사용한다.

    다시 <그림 3>의 펫샵 모델을 살펴보자. 펫샵에서는 Model 컴포넌트가 비즈니스 엔티티 컴포넌트로 사용된다. 전형적인 모델을 보여준다. <그림 6>은 Model 컴포넌트의 클래스 다이어그램이다.

    사용자 삽입 이미지
    <그림 6> Model 컴포넌트의 클래스 다이어그램

    <그림 6>의 클래스 다이어그램에서 알 수 있듯이 비즈니스 엔티티 컴포넌트는 단순히 자신을 생성하는 생성자만을 포함하고 있을 뿐 어떤 동작도 포함하고 있지 않다. 비즈니스 엔티티 컴포넌트는 MVC 모델에서 Model 역할을 담당하게 되는데, 모델은 단순히 데이터로서 존재해야지 데이터베이스에 직접 접근하거나 트랜잭션을 초기화해서는 안 된다. 비즈니스 컴포넌트에 의해 생성이 불가피하거나 비즈니스 컴포넌트의 로직이 불필요하게 복잡해 질 경우에는 데이터 액세스 로직 컴포넌트를 이용하는 것이 바람직하다. 비즈니스 엔티티는 어떤 잠재적인 행위를 가지고 단지 데이터를 표현하는 용도로서만 사용돼야 한다. 비즈니스 엔티티 컴포넌트의 설계 권고사항은 다음과 같다.

    ◆ 사용자 정의 엔티티 구현이 반드시 필요한지를 면밀한 요구사항 분석을 통해 파악한다 :사용자 정의 엔티티를 구현하는 것은 복잡성의 증가로 인한 개발 비용 상승을 가져올 수 있다. 필요하지 않다면 굳이 작성할 필요가 없지만, 작성하는 것이 비즈니스 컴포넌트의 코드 가독성과 복잡성을 떨어뜨리는 효과를 가져 오기도 한다.

    ◆ 사용자 정의 비즈니스 엔티티가 필요하다면 객체지향의 특성을 이용해서 다형적으로 구현한다 :공통 타입을 정의하고, 기본 클래스 또는 인터페이스의 서브타입으로 설계하여 비즈니스 컴포넌트의 개발 부담을 덜 수 있도록 설계해야 한다.

    ◆ 컬렉션이나 구조체 대신 데이터 셋이나 XML 문서를 내부적으로 유지한다 :데이터 셋이나 XML 문서는 복잡한 데이터를 표현할 수 있다. 또한, 닷넷 프레임워크의 Collections 프레임워크는 다형적으로 아주 잘 설계되어 있으므로 여러 사용자의 부담을 줄일 수 있다.

    ◆ 비즈니스 엔티티 인터페이스를 디자인하고 공용 속성을 제공한 후 구현은 서브 클래스에 위임하는 공통적인 다형성을 사용한다 :엔티티의 속성에 대한 프로퍼티, 엔티티가 포함하는 컬렉션 접근자, Load, Save, Validate등의 컨트롤 메쏘드와 속성을 정의하여 구현한다.

    ◆ 내부 데이터를 표현하는 메타데이터로부터 자유롭게 설계한다 :XSD 스키마 처럼 유효성 검사 규칙을 분리하여 외부 호출자가 규칙에 영향을 미치지 않도록 설계한다.

    ◆ 데이터베이스 액세스에 대한 일관성을 유지한다 :모든 데이터 액세스는 데이터 액세스 로직에 일임한다.

    제대로 된 소프트웨어를 먼저 생각하자
    필자가 코스매니저로 있는 정보기술원의 닷넷 5기 과정에서 최종 프로젝트로 닷넷 기반의 개인용 블로그 솔루션을 개발하고 있다. 욕심으로는 무버블 타입 같은 수준의 높은 추상성을 가지는 개인용 블로그를 독촉했지만 취업 등의 여러 이유로 인해 테터툴즈(Tatter tools) 수준의 블로그 솔루션이 개발될 듯하다.

    블로그에는 트랙백과 RSS를 포함해야 하는데 9개월 정도 공부한 한 학생이 이틀 만에 구현했다. 다른 사이트나 책을 참조하는 것 같지 않았고 수업 시간에 공부한 적도 없는데 금방 구현한 것이다. 닷넷은 워낙에 좋은 성능과 많은 기능들을 가진 플랫폼이라 RSS의 개념 정도만 파악하면 쉽게 구현할 수 있다.

    국내 닷넷 커뮤니티를 돌아다니다 보면 사용자 지정 컨트롤을 만들어서 배포도 하고 소스도 공개하는 것들을 많이 볼 수 있다. 하지만 공개되는 소스코드들의 수준이 그렇게 뛰어나지도 않을 뿐더러, 그렇게 만들어진 사용자 정의 컨트롤들이 어떻게 사용될 수 있을지 의심스럽다. 국내 유명한 닷넷 커뮤니티들을 돌아다니다가 외국의 오픈소스 커뮤니티와 비교해보면 한숨이 저절로 난다.

    닷넷 플랫폼에서 개발하고 있는 여러 개발자들은 다음과 같은 질문을 스스로 던져볼 필요가 있을 것 같다. ‘닷넷이 정말 뛰어난 플랫폼인가?’ 그렇다고 스스로에게 대답을 했다면 ‘왜 뛰어난 플랫폼인가?’를 다시 한번 생각해 봐야 한다. 단순히 생산성이 좋아서? 그렇다고 생각했다면 그 사람은 틀림없는 초보 개발자이거나 단순 코더 밖에 되지 않는다. “닷넷 플랫폼이 어떤 이유에서 뛰어나다고 말할 수 있는가?”라는 질문에 대한 대답을 이전의 ASP나 PHP 개발과 비교해 “편해서”, “개발 환경이 좋아서”라는 대답들이 머리에 먼저 떠오른다면 조금 더 깊이 있는 공부가 필요하다.

    어쩌면 내 게시판에서 RSS를 돌려볼 수 있을 것은 중요한 문제가 아니다. 잘 파악된 요구사항을 기반으로 이러한 요구사항을 만족하기 위해 RSS가 어떤 역할을 할 수 있는가? RSS가 전체 아키텍처에서 다른 컴포넌트들과 어떻게 유기적으로 조합될 수 있는가? 등 이런 것들이 훨씬 중요하다.

    소스포지(sourceforge.net)에서 Liferay 엔터프라이즈 포탈이라는 오픈소스 솔루션을 검색하고 웬만하면 한번 써보기 바란다. 3년간 다섯 명의 개발자가 개발했다는 이 솔루션을 보면 닷넷의 최전방에 서 있다는 필자로서는 저절로 한숨이 난다.

    닷넷 환경에서는 왜 이런 솔루션이 나오지 않는가? 이런 환경을 쉽게 구축하기 위한 모든 인프라는 이미 닷넷 플랫폼에 모두 들어 있다. “국내에서는 솔루션을 만들어 봤자 안 팔려”라는 말을 하기 전에 먼저 소프트웨어를 제대로 만들어 보겠다는 생각을 해야 한다. 물론, 그런 솔루션은 튼튼한 기반 아키텍처 위에 구축될 수 있고, 닷넷 엔터프라이즈 솔루션 아키텍처는 튼튼한 반석이 되어준다.@

    * 이 기사는 ZDNet Korea의 제휴매체인마이크로소프트웨어에 게재된 내용입니다.

     

    김상훈 (동명정보대학 정보기술원 연구원)

    2005/08/10

     

    사용자 삽입 이미지

     

     

     

     

    원문 :http://www.zdnet.co.kr/builder/dev/dotnet/0,39031607,39137358,00.htm

    신고
    0  Comments,   0  Trackbacks
    댓글 쓰기
    「오픈소스 닷넷」모노 설치와 구동

    「오픈소스 닷넷」모노 설치와 구동

     

    사용자 삽입 이미지
    오픈소스 모노 프로젝트는 비 윈도우 시스템에서도 닷넷 개발을 가능하도록 해줬다. 이로써 윈도우 시스템 뿐 아니라 유닉스와 맥 OS X에서도 동작하는 코드를 개발할 수 있게 됐다. 모노를 설치하고 간단하게 이용해보면서 이 개발 플랫폼에 대해 좀더 알아보도록 하자.

    모노는 닷넷 프레임워크에 기반한 오픈소스 개발 플랫폼이다. 닷넷 플랫폼은 윈도우 뿐 아니라 맥 OS X와 여러 유닉스·리눅스 운영체제에서 동작하는 애플리케이션을 개발할 수 있도록 하기 때문에 선택의 폭이 한층 넓어졌다.

    모노는 무엇인가?
    모노는 C# 언어와 CLI(Command Language Infrastructure)가 유럽 컴퓨터 제조연합(ECMA)의 표준으로 받아들여졌기에 만들어질 수 있었다.

    모노 라이브러리에는 닷넷 호환 라이브러리(ADO.NET, System.Windows.Forms, ASP.NET)와 모노에만 들어있는 써드파티 클래스 라이브러리가 포함돼 있다. 또한 모노 런타임을 애플리케이션에 내장시킴으로써 패키징과 배포를 간단하게 하는 것도 가능하다. 게다가 모노 프로젝트는 IDE, 디버거, 문서 브라우저도 제공한다.

    모노 설치법
    모노는 프로젝트웹사이트에서 자유롭게 다운로드 받아 설치할 수 있다. 현재 리눅스, 윈도우, OS X 세가지 운영체제별로 다운로드할 수 있으며 리눅스용은 일반 설치, 수세, 레드햇으로 세분화돼 있다. 소스코드를 다운로드 받아서 컴파일할 수도 있으며-현재 사용중인 플랫폼이 지원되지 않는다면 유일한 선택이다-적당한 설치 패키지를 다운로드할 수 있다. 이 글에서는 설치 패키지를 다운로드 받아서 이용한다고 가정한다.

    플랫폼에 맞는 적절한 패키지를 다운로드 했다면 이제 설치해보자. 설치 과정은 운영체제에 따라 다를 수 있다. 현재 나는 윈도우 XP와 수세 리눅스 9.2에서 모노를 구동하고 있다. 윈도우에서는 쉽게 설치할 수 있지만 다른 경우에는 그리 만만하지 않다.

    리눅스에서 설치하려면 모노 플랫폼을 지원하기 위해 여러 파일이 필요하다. 예를 들어 수세용으로 다운로드받아야 하는 파일들은 다음과 같다.

    • mono-devel-1.0.6-1.ximian.9.1.i586.rpm - C# 컴파일러가 포함된 모노 코어 패키지
    • mono-core-1.0.6-1.ximian.9.1.i586.rpm - 모노 코어 런타임
    • mono-data-1.0.6-1.ximian.9.1.i586.rpm - 데이터베이스 코어

    각 파일들은 모두RPM형식이다. rpm 명령어를 사용해 리눅스에서 설치할 수도 있다. 예를 들어 코어 모노 런타임은 다음과 같이 설치할 수 있다.

    rpm -i mono-core-1.0.6-1.ximian.9.1.i586.rpm



    모노를 설치한 이후 시스템 경로에 위치를 추가해야 한다. 그래야 전체 경로를 입력하지 않고 쉽게 명령어를 입력해 이용할 수 있다. 윈도우의 경우 제어판으로 들어가서 할 수 있으며 리눅스의 경우 export PATH 명령을 사용할 수 있다.

    : 모노 설치에 애를 먹고 있다면Got Mono? 웹사이트에서 설치 문제를 해결할 수 있는 팁들을 찾아보길 추천한다.

    모노 툴셋
    모노를 설치하고 나면 다양한 툴들을 이용할 수 있다. 몇 가지를 살펴보자.

    • 모노 - JIT를 사용하지 않고 애플리케이션을 실행하는 모노 인터프리터. 이걸 이용해 명령줄에서 애플리케이션을 구동할 수 있다. MS 닷넷 프레임워크에는 이런 툴이 없다

    • mcs - MS C# 컴파일러(csc.exe)와 동일한 명령줄 옵션을 모두 받아들이는 C# 컴파일러

    • monodies - 애플리케이션을 중간단계 언어(IL)로 디스어셈블하는 툴. MS의 ildasm.exe와 유사한 기능을 제공한다

    포함된 툴들의 목록과 각 명령어 옵션에 대해 자세히 알고 싶다면 모노 문서를 참조하기 바란다.

    모노 애플리케이션 개발하기
    이제 이 툴들을 어떻게 사용하는지 보기 위해 간단한 모노 애플리케이션을 만들어보자. 아래는 콘솔에 메시지를 출력하는 코드이다.


    using System;

    namespace Builder.Samples {

    public class MonoDemo {

    public static void Main(string[] args) {
    Console.WriteLine("Check out TechRepublic.com");

    } } }


    MonoDemo.cs라는 이름으로 저장하자. 이제 C# 컴파일러를 이용해서 컴파일하자.

    mcs MonoDemo.cs



    컴파일하면 MonoDemo.exe 파일이 생성된다. .exe 파일 확장자는 윈도우 시스템에서는 일반적인 것이지만 리눅스 시스템에서는 좀 이상하게 보일 수도 있다. 명령 줄에서 예제 파일을 실행시켜 보자.

    mono MonoDemo.exe



    이 예제를 통해 나타내려 했던 건 모노나 윈도우 닷넷 프레임워크가 동작하는 윈도우, 리눅스, 맥 OS X 등 어떤 플랫폼에서라도 컴파일된 파일이 구동될 수 있다는 점이다. 바로 모노 컴파일러가 IL이라는 중간 형태의 코드로 C# 코드를 컴파일하기 때문이다.

    MS C# 컴파일러도 동일한 작업을 수행한다. 그러나 모노에서는 닷넷 클래스 라이브러리가 아직 완벽하게 구현되지 않은 상태이며 모노에만 있는 라이브러리도 있다. 결과적으로 모노로 개발된 모든 애플리케이션이 MS 닷넷 프레임워크에서 동작할 수는 없다는 의미이며 그 반대도 마찬가지다.

    양자간 호환성을 유지하려면 대상 플랫폼과 향후 요구 사항을 이해해야 하며 개발 기간동안 계속 이 부분을 염두에 두면서 작업해야 할 것이다. 또한 모노 웹사이트를 자주 방문해 프로젝트의 진행 상황을 숙지해야 한다. 왜냐하면 클래스 라이브러리와 같은 새로운 내용이 계속 추가되고 있기 때문이다. 이런 상황은 MS 닷넷 프레임워크도 마찬가지다.

    우려되는 일들
    모노는 윈도우 플랫폼에 대해 갖고 있는 C# 관련 지식을 리눅스와 여타 플랫폼에도 적용할 수 있다는 장점을 제공한다. 그러나 윈도우를 제외한 다른 플랫폼에서 닷넷을 사용해 본격적으로 개발을 하는 건 주저할 수밖에 없다. MS는 C# 뿐 아니라 CLI도 공동체에 기증했지만 ADO.NET과 ASP.NET 같은 여타 기술은 그렇게 하지 않았기 때문이다.

    이렇다보니 MS가 ASP.NET과 ADO.NET 엔진도 모노에서 이용할 수 있도록 할지는 여전히 의문이다. 그리고 IIS와 윈도우가 아닌 다른 웹서버에서 애플리케이션이 운용되는 상황은 MS에 타격을 줄 것이다.

    어쩌면 명확한 근거가 없는 이야기일지도 모르겠지만 나는 이 점에 주목하고 있다. 그리고 마지막으로 지적하고 싶은 문제는 C# 말고 다른 언어에 대한 지원이 없다는 것이다. 이 때문에 VB.NET 프로그래머들은 모노에 시큰둥한 반응을 보이고 있다.

    한번 빠져봅시다!
    모노 프로젝트는 오픈소스 프레임워크에 기반한 인상깊은 결과물이라 할 수 있다. 모노 프로젝트는 닷넷 프레임워크의 많은 기능을 지원하며 2.0의 기능도 현재 지원하거나 지원할 예정에 있다. 또한 GNOME 인터페이스와 같은 리눅스 기반 애플리케이션을 개발할 때 모노에만 존재하는 라이브러리를 사용하는 경우도 있기 때문에 리눅스 개발에 힘을 실어주고 있다. 게다가 모노는 윈도우 개발자들이 리눅스를 접해볼 수 있는 좋은 기회이기도 하다. @

     

    Tony Patton (TechRepublic)

    2005/05/18
    원문보기

     

    사용자 삽입 이미지

     

    원문 :http://www.zdnet.co.kr/techupdate/lecture/dotnet/0,39024986,39136472,00.htm

    신고
    0  Comments,   0  Trackbacks
    댓글 쓰기
    [기업 환경에 닷넷 적용하기] ① 프리젠테이션 레이어 설계

    [기업 환경에 닷넷 적용하기] ① 프리젠테이션 레이어 설계

     

    연재순서
    1.제대로 된 컴포넌트를 위한 프리젠테이션 레이어 설계하기
    2.비즈니스 로직 레이어 설계와 물리적 구현을 위한 필요 사항
    3.엔터프라이즈 솔루션 패턴 해부하기
    4.닷넷의 웹 프리젠테이션 패턴
    5.닷넷 개발에서 UML과 케이스 툴의 사용

     

    닷넷은 아직도 ‘정말 큰 규모의 응용 프로그램의 동작은 어려운’ 환경으로 인식되고 있다. 하지만 실제로는 그렇지 않다. 닷넷은 거대한 기업에서도 힘을 발휘할 수 있는 환경이다.

    이 연재에서는 닷넷 플랫폼에서 기업형 환경을 쉽게 구축할 수 있도록 해주는 구조와 그 구조에 맞는 설계를 도와주는 기업형 응용 프로그램 패턴에 대해 기업형 구조와 설계 패턴을 중심으로 기업형 아키텍처와 엔터프라이즈 디자인 패턴에 대해 설명하는 것을 목적으로 한다.

    IT 기술은 다른 어떤 공학 기술과 비교할 수 없을 정도로 빠르게 진화한다. 객체지향 기술이 끝인가 싶더니, 컴포넌트 기반 기술, MDA(Model Driven Architecture), SOA(Service Oriented Architecture) 등 수없이 많은 새로운 것이 등장하고 또 없어지기를 반복한다. 현재로서는 실무에 가장 잘 적용되는 기술로 CBD(Component Based Development)가 각광받고 있고, 실무에서도 CBD를 개발에 적용하려 하지만, 경험이 부족한 많은 개발자들은 이런 CBD를 어떻게 개발에 적용해야 할지 막막한 경우가 대부분이다.

    제대로 된 CBD를 위해서는 기반 아키텍처를 구성하는 것이 제일 중요하다. 기업형 응용 프로그램에서 CBD를 제대로 하기 위한 아키텍처를 설계하는 방법이 제일 좋다. 하지만, 아키텍처 설계에는 많은 비용과 시간이 소모되므로 신뢰할 만한 기업에서 미리 설계해 놓은 아키텍처를 기반으로 새 아키텍처를 구성하거나 또는 기 설계된 아키텍처를 기반으로 응용 프로그램을 구성하는 것이 일반적이다.

    ‘어떤 컴포넌트를 만들어야 하는가?’에 대한 올바른 가이드라인을 제시해주는 아키텍처를 찾아 제대로 적용하는 것이 중요하다 할 수 있는데, MS에서 제시하는 엔터프라이즈 솔루션 아키텍처(Enterprise Solution Architecture)는 닷넷 기반 기업형 응용 프로그램을 작성할 때 기반이 될만한 가장 좋은 구조라 할 수 있다.

    자바의 아성에 대한 도전
    지난 98년, 썬 마이크로시스템즈는 당시 각광받던 자바의 여러 기술들을 확장해 기업 환경에서 신뢰성 있게 동작할 수 있는 기업형 분산 트랜잭션 지원 시스템인
    EJB를 발표했다.

    EJB는 거대한 기업형 응용 프로그램에서 반드시 필요한 기술들인 분산 트랜잭션, 이기종 데이터베이스 분산질의, 원격 프로시저 호출 등의 구현을 지원하는 기업 환경이었고, 자바가 주로 동작하는 운영체제인 유닉스가 탁월한 안정성을 보장하는 신뢰성 있는 운영체제였다. 이런 여러 장점들과 경쟁상대로 꼽을만한 기업형 응용 프로그램 개발 환경이 당시로서는 드물었으므로 EJB는 IT 시장에서 독보적이기까지 한 존재로 성장했다.

    MS의
    ASP는 서버 사이드 스크립트 역사상 가장 성공한 개발 환경이다. 1998년 윈도우 NT의 옵션팩에 포함되어 배포된 ASP 2.0은 세계적으로 3000만 명의 프로그래머들을 양산하며 웹 프로그래밍 환경에서 가장 많이 사용되는 서버 사이드 프로그래밍 환경이 되었다.

    하지만 ASP와
    MTS,COM등 3가지 프로그래밍 환경이 주를 이루던 MS의 개발 환경은 기업 시장에서 힘을 발휘하기에는 자바와 비교하여 역부족이었다. 간단하지만 재사용성이나 가용성적인 측면에서 객체지향 언어를 기본으로 하고 컴포넌트 기술을 기반으로 하는 자바와 비교할 때, 그리고 MS의 개발 환경이 동작하는 윈도우 NT가 유닉스와 비교할 때 안정성과 신뢰성 측면에서 많은 불안 요소와 개발 지연성을 가지고 있었기 때문이다.

    MS는 이에 대응하여 닷넷이라는 새로운 프로그래밍 환경을 발표했다. IT 시장의 흐름에 발 빠르게 대응해 기업 시장에서 자바의 아성에 도전하려는 듯 재사용성 및 가용성, 교체 가능성 등 자바의 장점들을 모두 가지려는 시도였다. 더 쉬운 프로그래밍과 변화하는 비즈니스 환경에 좀 더 손쉽게 대응할 수 있는 컴포넌트를 가진 닷넷은 패키지 응용 프로그램이나 소규모의 웹 응용 프로그램 등에 사용되던 이전 환경에서 벗어나 기업에서 MS 로고가 힘을 발휘할 수 있는 여건을 마련했다.

    이는 MS가 2000년에 발표한 윈도우 2000 서버 제품군의 탁월한 성능이 큰 힘을 발휘했다. 닷넷 환경은 자바에 대응할 수 있는 대규모 기업형 응용 프로그래밍에 적합하게 설계되었고, 신뢰성 있게 동작하며, 쉬운 프로그래밍 인터페이스와 발전된 프레임워크를 가지고 있는 기업형 응용 프로그램 제작/배포 환경이다.

    닷넷은 거의 모든 코드를 관리되는 환경에서 작성할 수 있기에 운영체제의 API에 직접 액세스하는 등의 위험요소를 줄일 수 있고, 컴포넌트 기반 프로그래밍 환경으로 구성되어 높은 재사용성과 교체 가능성 및 유지 보수성을 기대할 수 있게 구성되었다. 항상 하는 말이지만 닷넷 환경은 MS가 실로 오랜만에 만들어낸 ‘작품’이다.

    하지만 환경이 제아무리 훌륭하다 하더라도, 그것에 걸 맞는 훌륭한 응용 프로그램의 작성은 힘들기 마련이다. 기반 아키텍처를 구성하고, 그 기반으로 프로그램을 작성한다는 것은 몇 권 분량의 책이나 몇 주 분량의 기사로 설명할 수 있는 것이 아니다.

    또한 CBD라는 것이 양날의 검이 될 수 있는 것이기에 실제 프로그램을 작성하는 시간이나 비용보다 기반 프레임워크가 아키텍처를 구성하는 데 걸리는 시간이 훨씬 많이 소모될 수 있다. 이런 문제에서 본다면 프로그래밍 환경에서 중요한 것은 기반 구조가 아니라 생산성이 될 수 있다.

    닷넷은 그 어떠한 프로그래밍 환경보다 생산성이 뛰어나지만 그것만으로는 한계가 있다. 한정된 인력이 거대한 규모의 프로젝트를 진행할 때, 또는 한정된 인력으로 구성된 회사가 여러 프로젝트를 동시에 진행할 때가 대표적인 경우다. 제대로 설계된 아키텍처는 프로그래밍의 길잡이 노릇을 해 줄 뿐만 아니라, 프로젝트를 성공적으로 이끌 수 있는 이정표 역할을 해 준다.

    컴포넌트는 '어떻게' 구성돼야 하는가?
    시작한 프로젝트가 CBD라고는 하는데, 이 CBD라는 것이 애매모호한 경우가 많다. 특히 ASP 개발자라면 페이지에다 로직을 프로그래밍하고 실행해보고 테스트해보고 성공하면 배포하고 돌아가지 않는다면 디버깅하고 하는데 익숙하다. 그리고 작성한 페이지의 데이터베이스 액세스 로직 등을 비주얼 베이직 등을 이용해 COM 컴포넌트로 컴파일해서 ASP 페이지에서 CreateObject 메쏘드를 호출해서 사용하는 것 정도도 익숙하다.

    하지만 이 CBD라는 것이 어떤 컴포넌트를 어떻게 만들어서 어떻게 조립해서 사용해야 하는 것인지에 대한 경계가 모호하다. N-티어 구조니,
    MVC모델이니 하는 말은 지겹도록 많이 들었지만, 막상 프로그래밍에 그런 구조를 응용하려면 생각대로 잘 되지 않는 경우가 많다.

    이런 경우에 필요한 것은 컴포넌트를 ‘어떻게’ 만들어야 할지가 문제가 아니다. ‘어떤’ 컴포넌트를 만들어야 할지에 대한 결정이 급선무가 된다. 정립되어 있는 아키텍처는 이런 질문에 대한 답을 보여준다. 일반적으로 거의 모든 엔터프라이즈 아키텍처는 <그림 1>과 같은
    3단계 계층으로 구성된다. 지겹도록 보아왔지만 실제 응용 프로그램 작성에는 그다지 도움이 되지 않았던 그림이다.

    사용자 삽입 이미지
    <그림 1> 3-티어 아키텍처


    사실, <그림 1>은 CBD 기반 개발에서 어떠한 컴포넌트를 작성해야 하는지를 명확하게 보여준다. 애플리케이션 개발에서 약식 구조도로 가장 많이 사용되는 <그림 1>은 응용 프로그램이 재사용성을 가지기 위해 어떻게 설계되어야 하는 지에서부터, 컴포넌트의 동작범위, 컴포넌트의 종류, 컴포넌트의 개수까지도 개념 차원에서 정리할 수 있는 아키텍처 구조이다. 응용 프로그램 작성에서 그다지 도움이 되지 못했던 이유는 개발자들이 각 레이어에 존재하는 컴포넌트들의 역할을 명확하게 파악하지 못해서이다.

    개발자들은 각각의 레이어가 소프트웨어 컴포넌트의 논리적인 구분이라는 것을 알고 있다. 하지만 그 ‘논리적인’ 이라는 것의 사전적 의미(특히 한글로 번역했을 때의 모호함)와 조금의 거리가 있기 때문에 이러한 구조에 처음 접해보는 개발자는 <그림 1>의 아키텍처에서 프리젠테이션 레이어에 위치하는 컴포넌트를 어떻게 작성해야 하는지 감이 잘 잡히지 않기 마련이다.

    역할 구분이 모호한 컴포넌트 문제
    어떤 컴포넌트가 어디까지의 역할을 담당해야 하는지에 대한 구분이 모호할 때, 다음과 같은 컴포넌트가 나올 수도 있다. 실제로 <리스트 1>과 같이 작성되어 동작하는 컴포넌트를 본 적이 있고 사용도 하고 있다.

     <리스트 1> 프리젠테이션, 비즈니스 엔티티, 데이터 서비스가 혼재된 UI 컴포넌트
    사용자 삽입 이미지

    using System;
    using System.Data;
    using System.Data.SqlClient;
    using System.Web.UI.WebControls;

    // 전체 프로젝트에서 공용으로 사용하는 컨트롤 네임스페이스
    namespace CommonControls {
    // 이름을 보면 알 수 있다. 학과 정보를 표시하는 드롭다운 리스트이다.
    // 드롭다운 리스트 클래스를 상속하여 확장했다.
      public class DepartmentDropDownList : DropDownList {
        DataSet myDataSet = new DataSet();
        // 객체 생성자
        // 데이터베이스에 액세스하여 데이터를 자신에 바인딩한다.
        public DepartmentDropDownList () : base() {
          SqlDataAdapter myAdapter = new SqlDataAdapter("Select objectID, objectValue from objects", new SqlConnection());
           myAdapter.Fill(myDataSet);

           this.DataSource = myDataSet.Tables[0];
           this.DataBind();
        }

        protected override void OnSelectedIndexChanged(EventArgs e) {
           ...
        }
      }
    }
    사용자 삽입 이미지

    작성한 컴포넌트를 눈여겨 살펴보면 3계층의 모든 요소들이 하나의 논리적/물리적인 컴포넌트에 모여 있음을 알 수 있다. 이렇게 작성된 컴포넌트를 웹 페이지에 끼워 넣고 동작시켜도 전혀 문제가 없다. 이런 기법은 많이 쓰여 왔고, 하나의 컴포넌트가 모든 동작을 다 구현함으로서 구조가 간단해지고 사용자 인터페이스(이하 UI) 컨트롤을 가져다 쓰는 페이지의 코드를 줄일 수 있다는 장점 등도 가질 수 있다.

    간단한 프로그램을 작성할 때, 확장성을 고려하지 않은 소규모의 UI 중심 응용 프로그램을 작성할 때는 이런 프로그래밍 방식도 고려해 볼만하다. 하지만 기업형 응용 프로그램이라면 당연히 이야기가 달라진다. 기업형 응용 프로그램에서 앞의 구조로 프로그램을 진행한다는 것은 위험요소가 아주 많은, 재사용성을 전혀 고려하지 않은 위험한 방법이다.

    이와 같은 드롭다운 리스트 컨트롤을 네임 스페이스 이름에 걸맞게 공용 컴포넌트로 선언했다고 가정해 보자. 필자가 본 실제 동작하며 현업에 사용되는 <리스트 1>과 같은 구조의 UI 컴포넌트가 사용된 시스템은 꽤 큰 규모의 사원 관리 시스템이었는데, 새 사원이 가입했을 때 사원의 급여를 책정하는 페이지에는 사원의 국민연금 가입여부, 사학 연금 가입 여부, 의료 보험 등급 등을 결정하는 10여 개의 드롭다운 리스트가 포함되어 있었다.

    문제점을 살펴보자. 우선, 데이터베이스에 연결하는 부분이다. 각각의 드롭다운 리스트 컨트롤은 직접 데이터베이스에 연결하는 코드를 가지고 있다.

    한 페이지에 10개의 드롭다운 리스트 컨트롤이 삽입됐다는 페이지는 사원의 상세 정보를 가져오는 두세 개의 쿼리를 실행하는 연결 이외에 각각의 드롭다운 리스트가 가진 데이터베이스 연결을 가지고 있다. 최소한 하나의 페이지가 11개의 데이터베이스 연결을 가지고 있다는 뜻이 된다.

    <리스트 1>과 같이 구성된 컴포넌트가 페이지에 삽입됐다면 하나의 데이터베이스 연결이 여러 개의 쿼리를 실행하여 각각의 컨트롤에 바인딩하는 아주 당연한 연결 기법을 사용할 수 없게 된다. 데이터베이스 연결이 커넥션 풀링을 사용하고 있다면, 10명 정도의 사용자가 같은 페이지에 액세스하여 여러 개의 페이지 리로드를 10번씩만 하면 100개의 커넥션이 생기게 된다. 커넥션 풀에 각각의 커넥션이 30초 동안 유지된다고 하면, 각 사용자가 드롭다운 리스트의 항목을 바꾸면서 작업을 계속하게 되면, 웬만한 커넥션 풀은 꽉 찬 커넥션을 감당하지 못하고 뻗게 된다.

    다음 문제는, 각각의 컨트롤이 상호작용하도록 프로그램을 구성하기가 힘들다는 점이다. 만약 사용자가 국민연금에 가입하고 있다면 사학연금에는 가입하지 못한다. 하나의 드롭다운 리스트가 사용자의 연금 종류를 표시하고 있다. 다른 드롭다운 리스트가 국민연금의 연금 보험료를 표시하고 있다면, 또는 연금 종류를 표시하는 드롭다운 리스트의 항목이 변경되면 컨트롤을 통째로 바꿔야 한다.

    실제로 동작하는 프로그램은 페이지에 드롭다운 리스트를 40개쯤 포함시켜 놓고 컨트롤의 항목이 변경되면 컨트롤의 Visible 속성을 변경하여 숨기고 보여주고 하는 기법을 사용했다. 페이지가 무거워질 뿐더러, 데이터베이스 커넥션 풀에서의 문제는 더욱 심각해지고, 리소스를 낭비하게 된다.

    전체 응용 프로그램에서 드롭다운 리스트가 표현해야 하는 항목이 한두 개 밖에 되지 않는다면 <리스트 1>과 같은 기법을 사용해 볼 수도 있겠지만, 수많은 항목을 표현하는 드롭다운 리스트가 필요한 기업형 응용 프로그램에서는 이와 같은 방법을 써서는 전체 응용 프로그램이 너무 무거워지고, UI 컴포넌트의 개수가 너무 많아질 뿐더러 여러 문제가 발생하게 된다. <리스트 2>는 문제를 조금 개선한 드롭다운 리스트이다.

     <리스트 2> 개선된 드롭다운 리스트 컨트롤
    사용자 삽입 이미지

    public class DepartmentDropDownList : DropDownList {
      string tableName = "";
      DataSet myDataSet = new DataSet();
    // 객체 생성자
    // 객체가 생성될 때 페이지에서 지정한 테이블에 액세스할 수 있도록 코드가 수정되었다.
      public DepartmentDropDownList () : base() {
        SqlDataAdapter myAdapter = new SqlDataAdapter("Select objectID, objectValue from "+ this.tableName, new SqlConnection());
        myAdapter.Fill(myDataSet);

        this.DataSource = myDataSet.Tables[0];
        this.DataBind();
    }

    // 컨트롤이 액세스할 테이블의 이름을 컨트롤이 삽입될 페이지에서 지정할 수 있도록 한다.
    public string TableName {
      get {return this.tableName;}
      set {this.tableName = value;}
    }
      ...
    }
    사용자 삽입 이미지

    이 코드를 수정했다고 해도, 근본적인 문제는 해결되지 않는다. 데이터베이스 연결 및 커넥션 풀 문제는 여전히 지속되며, 컨트롤 간의 상호작용을 구성하기 위해서는 상당히 많은 라인의 코드를 작성해야만 한다. 하고 싶은 말은 이와 같은 방법으로 프로그래밍하면 안 된다는 것이다.

    역할 구분은 분명히 해야 한다
    엔터프라이즈 솔루션 아키텍처는 여기서 출발한다. 조금 냉정하게 말하자면, 지금까지 언급한 코드를 쓴 개발자라면 객체지향의 기본부터 다시 시작해야 할 것이다. 엔터프라이즈 아키텍처는 기본적으로 MVC의 구조를 가지고 있어서 모델(객체)과 뷰(컨트롤)의 역할이 완벽하게 구분돼야 한다.

    3-티어 아키텍처를 기반으로 프로그래밍한다면, <리스트 1>과 <리스트 2>에서 작성한 컨트롤의 동작은 3단계 계층에 존재하는 컴포넌트를 모두 사용해야 한다는 결론이 나온다. 각 레이어에는 <그림 2>와 같은 개체(컴포넌트)들이 동작해야 한다.

    사용자 삽입 이미지
    <그림 2> 3계층 구조로 개선한 프로그래밍


    보기에 컴포넌트 구조가 복잡해지고 컴포넌트 토폴로지가 증가할 것 같지만 이 구조를 따라 프로그래밍을 한다면 앞서 언급한 모든 문제가 해결된다. 우선 데이터베이스 연결 문제는 모든 데이터베이스의 연결을 데이터 레이어 계층의 컴포넌트에 위임함으로써 하나의 연결을 사용한다거나 또는 풀링을 사용하지 않는 등 일관된 정책을 유지할 수 있다. 또한 모든 드롭다운 리스트는 바인딩되기 전까지 데이터를 표현하는 DataSet 개체로부터 자유로우므로 드롭다운 리스트 간의 상호작용을 구성할 수 있다.

    이런 3-티어 아키텍처는 응용 프로그램의 구성에 있어 많은 탄력성을 제공해 줄 수 있다. 페이지의 변경을 감시하는 옵저버(observer)나 UI 컴포넌트들의 상호작용을 관리해주는 메디에이터(mediator)를 구성한다거나 하는 등의 설계 계선을 꾀할 수 있다. 따라서 유연한 구조의 재사용성과 교체 가능성, 유지 보수성이 뛰어난 응용 프로그램을 만들 수 있게 된다.

    엔터프라이즈 솔루션 아키텍처를 기반으로 한 응용 프로그램을 개발하기 위해 개발자는 다음 사항을 반드시 지켜야 한다.


    ◆ 수직적 관계의 모든 컴포넌트들은 느슨한 결합 관계를 가져야 한다. 예를 들면, 프리젠테이션 계층에 존재하는 특정 컨트롤이 자신을 표현하는 데이터를 가지고 있거나 다른 특정한 컴포넌트를 반드시 필요로 하는 구조여서는 안 된다.

    ◆ 비즈니스 컴포넌트는 자신을 보여줄 수 있는 공통된 방법을 가지고 있어야 한다. 비즈니스 계층의 컴포넌트에 포함된 개체가 프리젠테이션 계층에서 보여져야 할 경우 특정한 일관된 규칙을 가져 같은 방법으로 보여질 수 있어야 한다.

    ◆ 데이터베이스 연결은 일관되며 공통된 규칙을 지킬 수 있도록 집중화되어야 한다. 모든 비즈니스 컴포넌트들은 일관된 규칙으로 데이터베이스에 액세스할 수 있도록 구성되어야 한다.


    사용자 삽입 이미지
    컴포넌트란?
    사용자 삽입 이미지
     
    사용자 삽입 이미지
    이전 버전의 MS 환경에서는 OCX이건 액티브X이건 모듈이건 간에 독립적으로 컴파일된 유닛은 모두 컴포넌트라고 불러서 현재 문맥에서 말하는 컴포넌트가 어떤 것을 말하는지 헷갈릴 때가 많았다. 닷넷 환경이 나오면서 이러한 혼란을 줄이기 위해 어셈블리(assembly)라는 용어를 등장시켜 문맥상에서 말하는 컴포넌트의 종류를 쉽게 구분할 수 있도록 했다.

    일반적으로 컴포넌트라는 용어는 전체 솔루션에서 일부분이거나 또는 각각의 조각(부품)이라는 의미로 사용된다. 어셈블리나 액티브X 같은 컴파일된 유닛, 웹 페이지, 웹 서비스, 비즈토크 오케스트레이션 등 모든 결합될 수 있는 응용 프로그램의 부품을 컴포넌트라고 부른다.
    사용자 삽입 이미지
    사용자 삽입 이미지

    어떤 컴포넌트를 만들어야 하는가?
    3-티어 아키텍처로는 2% 부족하다고 느낄 것이다. 응용 프로그램 또는 서비스는 다른 종류의 작업을 수행하는 여러 컴포넌트들로 구성된다. 복잡한 기업형 응용 프로그램이라면 수백 개의 컴포넌트로 구성된다. 하지만 앞에서 살펴봤듯이 수없이 많은 컴포넌트는 사용자의 요구와 관계없이 비슷한 종류의 컴포넌트로 구성되는 경우가 대부분이다. 3-티어 아키텍처는 그런 비슷한 종류의 컴포넌트를 구별할 수 있게 하지만, 조금 더 세분화하여 분류할 수 있다.

    <그림 3>은 완벽히 분류되지는 않았지만, 대부분의 대규모 응용 프로그램에서 공통적으로 사용되는 일반적인 컴포넌트의 유형을 보여준다. 그다지 친절해 보이지는 않지만, 자세히 들여다보면 응용 프로그램의 아키텍처를 어떻게 구성해야 하는지를 한눈에 보여주는 그림이라 할 수 있다(MSDN 웹사이트에서는 이러한 그림이나 문서를 쉽게 찾아볼 수 있다).

    사용자 삽입 이미지
    <그림 3> 컴포넌트의 종류


    <그림 3>은 대규모의 응용 프로그램에서 공통으로 사용되는 일반적인 컴포넌트의 유형을 잘 설명하고 있다. 한 장의 그림이긴 하지만 각각의 컴포넌트가 어떻게 동작해야 하느냐에 대한 물음, 예를 들면 UI 프로세스 컴포넌트 단계를 구성하는 컴포넌트는 어떤 동작을 해야 하는지, 어떻게 구성돼야 하는지에 관련된 의문을 명확하게 설명해 주지는 못한다. MSDN 웹사이트나 gotdotnet 웹사이트에서 설명을 찾아볼 수 있다. UI 컴포넌트가 어떤 구성을 가져야 하는지, 어떤 컴포넌트여야 하는지에 대한 설명은 다음과 같다.

    사용자 삽입 이미지



    "대부분의 솔루션들은 사용자가 애플리케이션과 상호작용할 수 있는 방법을 제공할 필요가 있다. 소매 애플리케이션의 예제에서 고객들은 웹 사이트를 통해 상품을 보고 주문할 수 있다. 판매 대리인은 윈도우 운영체제 기반의 애플리케이션을 이용해 회사로 전화를 건 고객의 주문 데이터를 입력할 수 있다. 사용자 인터페이스는 사용자를 위한 데이터 포맷을 지정하고 제시하며 사용자들로부터 입력될 데이터를 요구하고 검증하기 위해 윈도우 폼, ASP.NET 페이지, 컨트롤 혹은 그 밖의 다른 기술을 이용해서 구현된다."

    아키텍처에 대한 기본 지식이 있는 개발자라면 이 간단한 설명으로도 이해할 수 있겠지만, 아키텍처 기반 개발 경험이 없는 개발자이거나 처음 공부하는 사람이라면 더 헷갈릴 수 있는 가능성이 크다. 필자가 강의를 진행할 때(특히 디자인 패턴이나 추상화 기법들을 강의할 때) 수강자들이 어려운 이론을 들으면 반드시 하는 말이 "코드를 보여주세요"라는 것이다. 정말, ‘백문이 불여일견’이라는 속담이 여기서도 통하게 되는데, 백번 말로 설명해도 이해 안가는 경우에는 아키텍처를 기반으로 작성된 애플리케이션의 예제를 한번 보는 것이 설명을 백번 듣는 것보다 훨씬 더 도움이 된다.

    MS는 이전에 J2EE 기술과 성능 비교에서 펫샵(Petshop) 응용 프로그램을 사용해 자사의 환경 성능을 테스트했는데, 이 펫샵이라는 응용 프로그램은 엔터프라이즈 솔루션 아키텍처에 기반하여 작성되었다. 말이나 그림으로 잘 이해되지 않는 독자라면 당장에 MS 웹사이트에 접속해 펫샵 3.0을 컴퓨터에 설치하고 코드를 살펴보기 바란다.

    이해가 가는 독자라도 코드를 보는 것이 훨씬 도움이 된다. 물론, 코드만 본다고 되는 것은 아니고 그림과 코드를 비교해가면서 살펴보는 것이 좋다.

    사용자 삽입 이미지
    <화면 1> 닷넷 펫샵


    펫샵 3.0을 설치하고 비주얼 스튜디오 닷넷을 사용해 코드를 볼 준비가 됐다면, 이제부터 아키텍처에 기반한 애플리케이션이 어떻게 작성되고 동작하며, 각 컴포넌트는 어떻게 작성되고 구성되며 어떤 역할을 해야 하는지를 알아보도록 하자. 이번 연재에서는 프리젠테이션 계층 컴포넌트가 어떻게 구성되는지에 대해 알아본다(비즈니스 컴포넌트와 데이터 액세스 컴포넌트는 다음 호에 알아보도록 한다)

    프리젠테이션 계층 구조와 설계
    <그림 2>에 나타나 있는 구조에서 프리젠테이션 계층을 구성하는 부분은 <그림 4>와 같다. 프리젠테이션 계층에는 UI 컴포넌트와 UI 프로세스 컴포넌트, 두 종류의 컴포넌트가 존재한다.

    사용자 삽입 이미지
    <그림 4> 프리젠테이션 계층 컴포넌트


    UI 컴포넌트는 말 그대로 사용자와 상호 작용하는 객체들이 모인 물리적 객체 집합이다. 이 계층에는 System.Windows.Forms 네임스페이스의 개체들과 System.Web.UI 네임스페이스의 개체들이 존재한다. 웹 기반 응용 프로그램이라면 TextBox 컨트롤, Button 컨트롤, DropDownList 컨트롤, DataGrid 컨트롤 등 ASP.NET 페이지에 직접 붙여 넣는 컨트롤들이 모두 이 범주에 속한다고 볼 수 있다.

    UI 컴포넌트
    UI는 크게 세 가지 역할을 수행해야 한다. 첫 번째 역할은 사용자에게 데이터를 보여주는 것이다. 예를 들면 현재 로그인한 사용자의 이름을 보여주기 위해 Label 컨트롤을 사용하거나 상품의 목록을 보여주기 위해 DataGrid 컨트롤을 사용하는 등이다.

    여기서 주의해야 할 점은 Label 컨트롤에 로그인한 사용자의 이름을 보여주기 위해 Label 컨트롤을 수정해 Label 컨트롤이 직접 HttpContext 개체나 Cookie 등에 액세스하지 않는다는 것이다. Label 컨트롤이나 DataGrid 컨트롤은 단지 어떤 데이터를 받아들여서 표시할 수 있는 역할만을 해야 한다.

    두 번째는 사용자의 입력을 받아들이고 입력된 데이터를 하위 컴포넌트에 전달하는 역할이다. 입력된 데이터를 하위 컴포넌트에 전달하기 위해서는 함수를 호출해야 한다. 하지만 사용자의 이벤트를 받아들이는데 있어 가장 많이 사용되는 버튼 컨트롤이 이러한 함수를 직접 호출하는 형태여서는 안된다. 사용자의 입력을 받아들이는 UI 컴포넌트는 단지 속성과 이벤트만을 가지고 있을 뿐, 직접적인 함수의 호출 로직을 가지는 것은 금물이다.

    세 번째는 입력된 데이터를 사용자가 검증하는 역할이다. 사용자가 입력한 데이터가 정수형인지, 날짜인지 등의 애플리케이션 내에서 유효한 값인지를 검증할 수 있는 클라이언트 수준에서의 로직이 필요하다. 종합해 보면, 로그인한 사용자의 이름을 웹 페이지에 보여주는 UI는 <그림 5>와 같이 작성되어야 한다.

    사용자 삽입 이미지
    <그림 5> 사용자 인터페이스 설계


    UI 컴포넌트는 사용자에게 데이터를 보여주고 사용자 입력 데이터를 검증하고 백앤드로 요청하며 사용자가 데이터에 수행하고자 하는 작업을 알려주는 등 사용자 행위를 검증하는 역할을 담당한다. 그리고 또 중요한 것은 UI는 사용자가 특정 시점에 특정 작업만을 수행하도록 행위를 제한할 수 있어야 한다. 다시 종합하여 생각해보면 UI 컴포넌트는 다음과 같은 사항들을 준수해야 한다.


    ◆ 트랜잭션을 생성하거나 또는 트랜잭션에 참여하거나 트랜잭션을 지원해서는 안된다.

    ◆ 데이터를 표시하기 위해서는 UI 프로세스 컴포넌트를 참조하거나 하위 계층의 컴포넌트를 참조해야 하지 자신이 직접 데이터를 포함하고 있으면 안된다.

    ◆ 사용자에게 데이터를 받아들이는 작업을 위한 시각화된 신호와 검증을 지원해야 하며 사용자의 요구에 적절한 컨트롤을 제공한다.

    ◆ 사용자 이벤트가 발생됐을 때 이를 컨트롤러에 전달하여 컨트롤러의 함수를 호출할 수 있어야 한다.


    참조 구현 모델인 펫샵에서 UI가 어떻게 구성되어 있는지 살펴보도록 하자. 펫샵은 <그림 6>과 같은 로그인 사용자 인터페이스를 가지고 있다.

    사용자 삽입 이미지
    <그림 6> 닷넷 펫샵의 로그인 UI


    로그인 사용자 인터페이스를 구성하는 Signin.aspx 페이지의 뷰를 구성하는 html 소스의 일부는 <리스트 3>과 같다.

     <리스트 3> Signin UI의 View를 구성하는 html 코드
    사용자 삽입 이미지

    <%@ Register TagPrefix="PetsControl" TagName="NavBar" Src="Controls/NavBar.ascx" %>
    <%@ Page Language="c#" CodeBehind="SignIn.aspx.cs" Inherits="PetShop.Web.SignIn" EnableSessionState="true" AutoEventWireup="false" %>
    <HTML>
      <HEAD>
        ....
      <!--사용자 입력을 받아들이는 Form -->
    <form id="frmSignIn" runat="server" method="post">
        <table cellpadding="1" cellspacing="0">
          <tr>
          <td class="label">User ID:</td>
            <td>
            <! -- 적절한 사용자 입력 컨트롤 -->
    <asp:textbox id="txtUserId" runat="server" text="DotNet" columns="15" maxlength="20" />
    <!-- 입력된 값 검증 -->
    <asp:requiredfieldvalidator id="valUserId" runat="server" controltovalidate="txtUserId" errormessage="Please enter user ID." enableclientscript="False" />
            </td>
           </tr>
           <tr>
           <td class="label">Password:</td>
            <td>
    <asp:textbox id="txtPassword" runat="server" value="DotNet" columns="15" maxlength="20" textmode="Password" />
    <asp:requiredfieldvalidator id="valPassword" runat="server" controltovalidate="txtPassword" errormessage="Please enter password." enableclientscript="False" />
            </td>
          </tr>
        </table>
        <!-- Controller의 함수 호출 -->
      <p><asp:imagebutton id="btnSubmit" runat="server" onclick="SubmitClicked" imageurl="Images/buttonSubmit.gif" alternatetext="Submit" />
    </form>
    사용자 삽입 이미지

    닷넷 펫샵의 로그인 UI의 컨트롤러는 Signin.aspx.cs 페이지에 구성되었다. 페이지는 View에 포함된 버튼 컨트롤이 클릭 이벤트를 발생하여 컨트롤러의 이벤트 핸들러 함수를 호출하면 사용자가 입력한 아이디와 패스워드를 알맞은 문자열로 검증하고 Business Process Component의 함수를 호출하여 로그인을 처리한다. 아키텍처에 기반한 '제대로 된' 처리를 보여준다.

     <리스트 4> Signin UI의 컨트롤러(Page 객체를 상속하는 코드 비하인드 코드이다)
    사용자 삽입 이미지

    protected void SubmitClicked(object sender, ImageClickEventArgs e) {
        if (Page.IsValid) {
        // Get the user info from the text boxes
        string userId = WebComponents.CleanString.InputText(txtUserId.Text, 50);
        string password = WebComponents.CleanString.InputText(txtPassword.Text, 50);

        // Hand off to the account controller to control the naviagtion
        ProcessFlow.AccountController accountController =
    new ProcessFlow.AccountController();

        if (!accountController.ProcessLogin(userId, password)){
            // If we fail to login let the user know
            valUserId.ErrorMessage = MSG_FAILURE;
            valUserId.IsValid = false;
        }
    }
    }
    사용자 삽입 이미지

    UI 프로세스 컴포넌트
    UI 프로세스 컴포넌트는 사용자와의 상호작용이 단계적인 흐름을 예측할 수 있도록 구성될 때 유용하다. 로그인 UI의 경우 로그인을 시도한 사용자가 유효한 회원이 아닌 경우 에러 메시지를, 유효한 회원이 로그인 했을 경우 요청한 페이지로 이동한다는 단계적인 흐름을 간단히 예측할 수 있다.

    또 사용자가 물품을 구매하는 프로세스의 경우 쇼핑카트에 물품을 입력하고, 전체 가격을 보여주고, 지불에 관한 정보를 입력하도록 한다. 그런 다음 배송 주소 정보를 입력하도록 요구하고 쇼핑 카트에 담긴 상품을 마이그레이션한 후 주문 정보를 입력한다.

    프로세스 내에서 단계가 유지될 때 주문된 상품이 무엇이고 주문한 사용자는 누구이며 신용카드의 정보는 어떤 것인지에 대한 프로세스의 상태를 유지 관리할 필요가 있다. 이런 경우 UI 프로세스 컴포넌트를 작성하여 사용자의 프로세스 조절을 중앙 집중화할 수 있다. 특히, 다중 UI 페이지일 경우 더욱 유용하게 사용될 수 있다.

    UI 프로세스 컴포넌트는 UI처럼 HTML로 구성되거나 페이지를 상속받는 개체로 구성되지 않는다. 일반적으로 UI에서 호출되는(주로 컨트롤러에서 호출되는) 메쏘드를 지닌 닷넷 클래스로 구성된다.

    UI 프로세스 컴포넌트의 작성은 상당히 어렵다. UI 프로세스 컴포넌트가 제공할 만한 추상화가 필요한지를 주의 깊게 생각하지 않으면 UI 프로세스 컴포넌트의 사용은 오히려 프로젝트의 진행에 장애 요소가 될 수 있다. 하지만 주의 깊은 추상화로 UI 프로세스 컴포넌트를 구성하면, 다음과 같은 여러 장점들을 꾀할 수 있다.


    ◆ 사용자 상호작용의 상태를 지속할 수 있다.

    ◆ 다중 사용자 인터페이스를 쉽게 디자인하고 구성할 수 있다.

    ◆ 같은 사용자 프로세스가 여러 사용자 인터페이스에 재사용될 수 있다.

    ◆ 애플리케이션의 유지 관리 탄력성을 얻을 수 있다.

    ◆ 다른 복잡한 작업들을 쉽게 추가할 수 있게 해 준다.


    UI 컴포넌트는 일반적으로 다음과 같은 기능을 구현해야 한다. 대규모 기업형 애플리케이션이라면 대부분이 반드시 필요한 기능들이며, 아키텍처에 기반하지 않고 개발된 응용 프로그램들은 이런 반드시 필요한 기능들을 여러 계층에 분산시켜 놓기 마련인데, 이런 기능들을 가지는 컴포넌트를 생성하여 중앙 집중과 관리함으로서 얻을 수 있는 이점은 무궁무진하다 할 수 있다.


    ◆ UI 컴포넌트는 UI와 연동되는 데이터의 흐름이다. 컨트롤의 로직들을 재개발하지 않고 상호작용 흐름을 연동할 수 있는 제어를 제공해야 한다.

    ◆ 논리적인 사용자와 시스템의 상호작용 흐름을 제어 추상화하여 UI 프로세스 컴포넌트를 사용하는 구현으로부터 분리되도록 작성돼야 한다.

    ◆ 예외 발생시에 사용자 프로세스의 흐름을 제어할 수 있어야 한다.

    ◆ 사용자의 상태에 대한 현재 상태를 유지해야 한다.

    ◆ 일반적으로 비즈니스 컴포넌트 또는 데이터 액세스 로직과 연동하여 내부 상태를 초기화하도록 한다.

    ◆ 사용자 상호작용에 의해서 영향을 받는 비즈니스 엔티티를 저장하는 비즈니스 상태를 유지할 수 있도록 한다.

    ◆ 엔터프라이즈 서비스로 구성하지 않는다.


    UI 프로세스 컴포넌트는 <그림 7>과 같이 설계돼야 한다. 그럼 닷넷의 구현 모델을 살펴보도록 하자. <리스트 5>는 닷넷 펫샵의 UI 프로세스 컴포넌트 중 로그인를 처리하는 프로세스 컴포넌트의 소스코드이다.

    사용자 삽입 이미지
    <그림 7> UI 프로세스 컴포넌트 디자인


     <리스트 5> 펫샵의 로그인 UI 프로세스 컴포넌트 코드의 일부
    사용자 삽입 이미지

    private const string ACCOUNT_KEY = "ACCOUNT_KEY";
    private const string URL_DEFAULT = "default.aspx";
    private const string URL_SIGNIN = "SignIn.aspx";
    private const string URL_ACCOUNTCREATE = "MyAccount.aspx?action=create";
    private const string URL_ACCOUNTSIGNIN = "MyAccount.aspx?action=signIn";
    private const string URL_ACCOUNTUPDATE = "MyAccount.aspx?action=update";

    ...

    public bool ProcessLogin(string userId, string password){
        // 비즈니스 로직 레이어 개체를 사용하여 로그인을 처리한다.
        Account account = new Account();
        AccountInfo myAccountInfo = account.SignIn(userId, password);

        // 로그인이 성공하면 상태를 세션에 저장하고 요청 페이지로 리디렉션한다.
        if (myAccountInfo != null) {
            HttpContext.Current.Session[ACCOUNT_KEY] = myAccountInfo;

            // 사용자를 어떤 페이지로 보낼 것인지를 결정한다.
            If (FormsAuthentication.GetRedirectUrl(userId,
    false).EndsWith(URL_DEFAULT)) {
                FormsAuthentication.SetAuthCookie(userId, false);
                HttpContext.Current.Response.Redirect(URL_ACCOUNTSIGNIN, true);

            }else{
                // 사용자를 페이지로 되돌려 보낸다.
                FormsAuthentication.SetAuthCookie(userId, false);
                HttpContext.Current.Response.Redirect(
    FormsAuthentication.GetRedirectUrl(userId, false), true);
            }
            return true;

        }else {
            // 로그인이 실패했을 경우
            return false;
        }
    }
    사용자 삽입 이미지

    사용자가 로그인 프로세스를 거친 후 어떤 동작을 제어하는 <리스트 5> 이외에도 UI 프로세스 컴포넌트가 수행해야 하는 동작들에 대한 구현 코드가 들어 있다. 독자들은 펫샵 3.0을 설치했을 것이므로 상세 구현 코드는 생략하겠다.

     <리스트 6> 로그인 UI 프로세스 컴포넌트의 구현
    사용자 삽입 이미지

    // 사용자 객체 생성
    public bool CreateAccount(AccountInfo newAccountInfo){}

    // 사용자 상태 갱신
    public void UpdateAccount(AccountInfo updatedAccountInfo){}

    // 로그인한 사용자의 정보를 알아냄
    public AccountInfo GetAccountInfo(bool required){}

    // 사용자가 자주 이용하는 카테고리를 알아냄
    public string GetFavouriteCategory(){}

    // 로그아웃 처리
    public void LogOut(){}
    사용자 삽입 이미지

    아키텍처 설계는 쉬운 일이 아니다
    이 글을 읽은 독자는 다음과 같이 반문할 지도 모르겠다.


    "결국은 객체지향에서 이야기하는 추상화이고 디자인 패턴이네요?"


    답은 다음과 같다.


    "그렇죠. 사실 추상화 수준과 디자인 패턴을 모르고서는 이를 이해하기 힘듭니다."


    아키텍처를 설계한다는 것은 정말 쉬운 일이 아니다. 잘못 설계된 아키텍처는 언젠가 문제를 일으키기 마련이고, 프로젝트를 겉잡을 수 없는 방향으로 이끌게 된다. 아키텍트를 꿈꾸는 개발자라면, 당장에 아키텍처를 설계해 보겠다고 겁 없이 덤비기보다는 신뢰성 있는 기업에서 작성해서 발표한 아키텍처 구조를 잘 살펴보고 이해한 후 차근차근히 공부하는 자세가 필요하다. 한강의 기적이 하루아침에 이루어진 것이 아니듯이, 실력 있는 아키텍트와 제대로 된 아키텍처는 하늘에서 뚝 떨어지는 것이 아니다.

    다음 글에서는 비즈니스 로직 컴포넌트와 데이터 액세스 로직 컴포넌트의 구성과 사용에 대해 알아볼 것이다. 마지막으로 이번 연재를 토대로 ‘닷넷 엔터프라이즈 솔루션 아키텍처’를 주제로 한 세미나를 준비 중에 있다. 좀 더 상세한 자료를 원한다면,
    http://www.nogatech.net에서 다운받을 수도 있다.@

    * 이 기사는 ZDNet Korea의 제휴매체인
    마이크로소프트웨어에 게재된 내용입니다.

     

    김상훈 (동명정보대학 정보기술원 연구원)

    2005/05/03

     

    사용자 삽입 이미지

     

     

     

     

    원문 :http://www.zdnet.co.kr/techupdate/lecture/etc/0,39024989,39135761,00.htm

    신고
    0  Comments,   0  Trackbacks
    댓글 쓰기
    [메타 사이트 만들기] ② RSS 수집 로봇 구현·분석

    [메타 사이트 만들기] ② RSS 수집 로봇 구현·분석

     

    연재순서
    1회. 블로거들의 집합소「메타 사이트 구현」
    2회. RSS 수집 로봇 구현과 문제점 분석

     

    이번 글은 지난번에 이은 메타 사이트 만들기 강좌 마지막 편으로 XML 파일을 이용하여 RSS 주소들의 목록을 관리하는 클래스의 제작, RSS 파일들로부터 읽은 정보들을 데이터베이스에 저장하는 방법에 대해 알아보겠습니다. 그리고 그를 구현하는 테이블, 저장 프로시저, 클래스들을 제작하고, 간단한 RSS 수집 로봇 프로그램을 제작해 보도록 하겠습니다.

    자동차는 수많은 부품들을 각각 생산하여 설계도에 맞게 각각을 연결하고 조립하는 과정을 통해 만들어집니다. 우리가 만들고자 하는 메타 사이트도 핵심 부품들을 하나하나 만들고 마지막에 그러한 각각의 부품들을 조립하여 우리가 원하는 하나의 기능을 수행하는 프로그램을 완성하는 단계로 진행되고 있습니다. 지난 글을 통해 우리는 다음과 같은 내용을 진행하였습니다.


    [1] 메타 사이트는 RSS 파일로부터 블로그의 정보를 얻는다는 사실을 이해한다.
    [2] RSS 파일의 구조에 대해서 공부한다.
    [3] RSS 파일의 내용을 저장할 클래스를 제작한다.
    [4] RSS 파일로부터 내용을 읽어오는 RssReader 클래스를 제작한다.


    이번 글은 지난 시간에 이은 메타 사이트의 부품 만들기 강좌 마지막 편으로 RSS 주소들을 저장하는 클래스와, XML 파일을 이용하여 RSS 주소들의 목록을 관리하는 클래스의 제작, RSS 파일들로부터 읽은 정보들을 데이터베이스에 저장하는 방법과 그를 구현하는 테이블, 저장프로시저, 클래스들을 제작하고 간단한 RSS 수집 로봇 프로그램을 만들어 보도록 하겠습니다.

    RSS 파일들의 주소들을 관리하자
    지난 호를 통해 한 개의 파일 또는 주소로부터 RSS 정보를 읽을 수 있는 RssReader 클래스가 완성되었습니다. 남은 문제는 여러 RSS 주소들을 관리하는 작업입니다. 이러한 작업은 데이터베이스를 이용하면 손쉽게 제작할 수 있지만, 데이터베이스를 이용하는 방법은 이후 RSS 파일의 내용들을 기록할 때 접할 예정이니, 우선은 XML 파일을 이용하여 저장하는 방법으로 RSS 주소들의 리스트를 관리해 보도록 하겠습니다.

    RSS 주소들을 관리하기 위해서는 RSS 주소와 더불어 사이트에 대한 간략한 설명과 부가적인 자료들이 포함되면 됩니다. 예를 들어 블로그의 이름 또는 블로그의 종류 등 RSS 주소를 보고 이해하기 쉽도록 추가할 수 있습니다. 지면상 가장 간단하게 RSS 파일의 경로와 블로그의 제목 정도만 가지고 있는 클래스를 만들어 보도록 하겠습니다.

    Public Class RssAddress
        Public RssURL As String
        Public BlogName As String

        Public Sub New()
        End Sub

        Public Sub New(ByVal RssURL As String, ByVal BlogName As String)
            Me.New()
            Me.RssURL = RssURL
            Me.BlogName = BlogName
        End Sub
    End Class

    아무런 작업을 하지 않는 기본 생성자와 데이터를 입력하며 객체를 생성하기 편리하게 하기 위해 RSS 파일의 주소와 블로그의 이름을 인자로 받는 생성자가 있습니다. 여기서는 아무런 작업도 하지 않는 기본 생성자를 굳이 선언한 이유가 있습니다.

    우리는 RSS 정보들을 저장하기 위해서 XML 파일을 사용하며 아주 간편하게 XML 파일로 만들기 위해 직렬화(serialization)를 사용하려고 합니다. 이를 위해 닷넷 프레임워크에서 직렬화를 지원하는 System.Xml.Serialization.XmlSerializer 클래스를 이용하려고 하는데, 어떤 객체를 직렬화하기 위한 조건 중 하나가 객체는 반드시 기본 생성자를 가지고 있어야 한다는 것입니다. 일반 생성자에 Optional을 사용하여 기본 값을 지정해 주는 생성자를 만들어도 직렬화는 되지 않습니다.

    이렇게 한 개의 RSS 파일의 정보를 가지고 있는 RssAddress 클래스가 완성되었습니다. 이제 다수의 RssAddress들을 저장할 컬렉션 클래스를 만들어야 합니다. CollectionBase 클래스를 상속받고, 인덱서와 메쏘드 등을 구현하여 컬렉션 클래스를 만드는 방법은 지난 호에서 RssItemCollection 클래스를 통해 소개했습니다. 그와 같은 방법으로 RssAddressCollection 클래스를 만들어줍니다. 그리고 여기에 XML 파일로부터 손쉽게 데이터를 불러오고, XML 파일로 손쉽게 저장할 수 있는 2개의 메쏘드를 추가하려고 합니다.

     <리스트 1> RssAddressCollection 클래스
    사용자 삽입 이미지

    Imports System.IO
    Imports System.Xml.Serialization

    Public Class RssAddressCollection
        Inherits CollectionBase

        Public Shared Function LoadFromXml(ByVal XmlFileName As String) As RssAddressCollection

            Dim serializer As New XmlSerializer(GetType(RssAddressCollection))
            Dim rssAddrs As RssAddressCollection
            Dim sr As New StreamReader(XmlFileName)
            rssAddrs = serializer.Deserialize(sr)
            sr.Close()

            Return rssAddrs

        End Function

        Public Shared Sub SaveToXml(ByVal XmlFileName As String, ByVal RssAddrs As RssAddressCollection)

            Dim serializer As New XmlSerializer(GetType(RssAddressCollection))
            Dim sw As New StreamWriter(XmlFileName)
            serializer.Serialize(sw, RssAddrs)
    sw.Close()

        End Sub
        ...
        Collection 구현 관련 내용은 생략
        ...
    End Class
    사용자 삽입 이미지

    추가한 메쏘드들은 Shared 키워드를 이용하여 객체를 생성하지 않아도 사용할 수 있도록 선언하고 있습니다. SaveToXml 메쏘드는 인자로 파일명과 RssAddressCollection을 받아 이를 해당 파일로 클래스의 직렬화 결과를 저장합니다. 그리고 LoadFromXml 메쏘드는 인자로 받은 파일로부터 역직렬화된 RssAddressCollection 클래스를 반환해 줍니다.

    이들을 이용해서 손쉽게 객체를 XML 파일로 만들거나, 이미 저장되어 있는 XML 파일로부터 객체를 생성할 수 있습니다. 이렇게 만들어진 클래스들은 다음과 같은 방법으로 사용해볼 수 있습니다.


    ' RSS 주소들을 추가하고, XML 파일로 저장
    Dim rssaddrs As New RssAddressCollection
    rssaddrs.Add(New RssAddress("http://php.chol.com/~ppk314/tt/index.xml", "하늘이네 블로그"))
    rssaddrs.Add(New RssAddress("http://namida.pe.kr/tt/index.xml", "나미다님의 블로그"))
    RssAddressCollection.SaveToXml("MyRssAddressCollection.xml", rssaddrs)

    ' XML 파일로부터 객체를 생성
    Dim loadedRssAddrs As RssAddressCollection = RssAddressCollection.LoadFromXml("MyRssAddressCollection.xml")


    이제 RssReader 클래스를 함께 이용하여 RSS 주소들로부터 내용을 읽어와서 콘솔에 표시하는 간단한 프로그램을 제작해 보도록 하겠습니다. 테스트에 사용할 RSS 주소들은 앞의 RSS 주소들을 XML 파일로 저장하는 예제에서 생성한 MyRssAddressCollection.xml을 이용하도록 하겠습니다.

     <리스트 2> RSS 파일들로부터 내용을 읽어 표시하는 프로그램
    사용자 삽입 이미지

    Dim rssAddrs As RssAddressCollection = RssAddressCollection.LoadFromXml("MyRssAddressCollection.xml")

    Dim rssReader As New RSSReader
    For addrIndex As Integer = 0 To rssAddrs.Count - 1
        Console.WriteLine(rssAddrs(addrIndex).BlogName + " 블로그의 글 목록입니다.")
        rssReader.XmlAddress = rssAddrs(addrIndex).RssURL
        rssReader.readItems()

        For itemIndex As Integer = 0 To rssReader.Items.Count - 1
            Console.WriteLine(rssReader.Items(itemIndex).PubDate.ToString("[MM:dd HH:mm] ") + rssReader.Items(itemIndex).Title)
        Next
    Next
    사용자 삽입 이미지

    <리스트 2>를 실행하면 각각의 주소들로부터 RSS 파일을 불러와서 다음과 같이 결과를 표시해 주게 됩니다.


    하늘이네 블로그 블로그의 글 목록입니다.
    [11:09 11:25] 생각만으론 바뀌지 않는다.
    ... 생략 ...
    나미다님의 블로그 블로그의 글 목록입니다.
    [11:09 15:14] BRIDGET JONES: THE EDGE OF REASON
    ... 생략 ...


    여기까지의 과정을 통해서 우리는 RSS 파일 주소들로부터 모든 정보를 얻어오는 과정까지 완성하게 되었습니다. RSS 수집 로봇 제작에 있어서 가장 바탕이 되는 처리 부분을 완성한 것입니다.

    RSS의 내용을 정리하자
    RSS 파일들로부터 블로그의 모든 내용들을 가져오는 과정까지 완성하게 되었습니다. 이제 이러한 블로그의 내용들을 하나로 정리하는 작업만을 남겨두고 있습니다.

    정리한다는 것의 의미는 이렇게 볼 수 있습니다. 내용들 중에서 새롭게 업데이트된 내용과 이전의 내용들을 분류해내고, 각각의 데이터들을 각각 다른 기준으로 저장하는 것과 많은 블로그들의 각 글들의 남다른 기준은 무엇일까요? 그 글만이 가지는 유일한 정보 말입니다. 날짜나 제목도 있을 수 있겠지만 그것들은 다른 글이라고 하더라도 같을 수 있는 가능성이 있습니다. 하지만 웹에서 그 글을 표시하는 주소는 단 1개뿐이겠지요?

    그리고 혹시라도 RSS 주소들의 리스트에 같은 RSS 파일이 여러 개가 저장되는 문제가 생기더라도 주소를 기준으로 저장한다면 같은 글이 2개로 저장되는 문제는 발생하지 않게 됩니다. 이러한 내용들을 바탕으로 RSS 파일의 내용들을 저장할 데이터베이스 테이블을 만들어보도록 하겠습니다.

    사용자 삽입 이미지
    <표 1> RSS 내용을 저장할 Rss_Datas 테이블


    테이블의 구조는 RssItem과 비슷한 모양을 가지고 있습니다. 여기에 Link와 PubDate에 인덱스를 걸어주도록 하겠습니다. 차후에 주소를 기준으로 데이터를 자주 불러오고, 날짜순으로 정렬을 많이 시도할 예정이기 때문입니다. 여기에 차후 부가적인 내용들을 추가하면 되지만 이 시간에는 가장 기본적인 내용들을 기준으로 만들어 보았습니다.

    이제 이렇게 만들어진 테이블에 간편히 데이터를 동기화할 수 있는 저장 프로시저 한 개를 만들어 보도록 하겠습니다. 이 저장프로시저는 인자 값으로 RssItem의 내용을 주면 데이터베이스와 동기화하게 됩니다. 즉 데이터베이스에 이미 존재하는 경우 내용을 업데이트하고, 존재하지 않는 경우 새로운 글을 추가하게 됩니다. 차후 동기화에 따른 몇 가지 조건들을 추가하고자 할 때에도 이 저장 프로시저를 통해 만들면 됩니다. 우선은 가장 기본적인 동기화 프로시저를 만들어보도록 합시다.

     <리스트 3> RSS 정보를 데이터베이스와 동기화하는 저장 프로시저
    사용자 삽입 이미지

    CREATE PROCEDURE sp_Rss_DataSync
    @Link varchar(200),
    @PubDate smalldatetime,
    @Title varchar(200),

    @Author varchar(50),
    @Description text
    AS
        DECLARE @OldLink varchar(200)
        SELECT @OldLink = Link FROM Rss_Datas
        WHERE Link = @Link

        IF @OldLink IS NULL
            BEGIN
                INSERT INTO Rss_Datas(Link, GroupIdx, PubDate, Title, Author, Description)
                VALUES (@Link, @GroupIdx, @PubDate, @Title, @Author, @Description)
            END
        ELSE
            BEGIN
                UPDATE Rss_Datas SET
                    PubDate = @PubDate,
                    Title = @Title,
                    Author = @Author,
                    Description = @Description
                WHERE Link = @Link
            END
    GO
    사용자 삽입 이미지

    해당 링크와 같은 글이 있는지를 체크하고 결과에 따라서 글을 저장하거나, 업데이트하는 간단한 쿼리 문장들을 사용한 저장 프로시저입니다. 차후에 동기화에 대한 여러 가지 기능들을 추가하고자 할 때 이 저장 프로시저만을 수정하면 됩니다.
    간단한 예를 들면, 블로그에는 글을 쓰고 삭제하는 경우가 있습니다. 같은 내용인데 다시 정리해서 새롭게 쓰고자 하는 경우이지요.

    이런 경우 같은 도메인이나 같은 블로그 주소이지만, 링크가 약간 달라집니다. 이런 경우 제목과 주소의 일부가 같은 경우 기존 글의 주소를 업데이트한다거나, 또는 시간대별로 동기화를 제한하는 기능 등을 들 수 있습니다. 이제 이렇게 만든 저장 프로시저를 쉽게 사용할 수 있는 RssItemSync 클래스를 만들어보도록 하겠습니다.

     <리스트 4> RssItemSync 클래스
    사용자 삽입 이미지

    Imports System.Data.SqlClient

    Public Class RssItemSync
        Private sqlCon As SqlConnection

        Public Sub New(ByVal ConnectionObject As SqlConnection)
            sqlCon = ConnectionObject
        End Sub

        Public Sub ItemSync(ByVal Item As RSSItem)
            Dim isClosed As Boolean = False

            If sqlCon.State = ConnectionState.Closed Then
                isClosed = True
                sqlCon.Open()
            End If

            Dim sqlCmd As New SqlCommand("sp_Rss_DataSync", sqlCon)
            With sqlCmd
                .CommandType = CommandType.StoredProcedure
                .CommandTimeout = 180
                .Parameters.Add(New SqlParameter("@Link", SqlDbType.VarChar)).Value = Item.Link
                .Parameters.Add(New SqlParameter("@PubDate", SqlDbType.SmallDateTime)).Value = Item.PubDate
                .Parameters.Add(New SqlParameter("@Title", SqlDbType.VarChar)).Value = Item.Title
                .Parameters.Add(New SqlParameter("@Author", SqlDbType.VarChar)).Value = Item.Author
                .Parameters.Add(New SqlParameter("@Description", SqlDbType.Text)).Value = Item.Description
            End With
            sqlCmd.ExecuteNonQuery()

            If isClosed Then
                sqlCon.Close()
            End If
        End Sub
    End Class
    사용자 삽입 이미지

    우선 이 클래스는 생성자로 SqlConnection을 받습니다. 그리고 ItemSync 메쏘드에서는 연결 객체가 닫혀 있는 경우 열고 작업을 하고 다시 닫아주고, 열려 있다면 열린 상태로 유지하도록 코드를 만들었습니다. 이는 이 메쏘드가 데이터 동화에서 여러 번 반복 사용되므로 연결?닫기의 작업을 반복하지 않게 하기 위해서 간단하게 구현해 보았습니다.

    이제 여기까지의 완성된 각각의 클래스들을 이용하여 RSS 파일들로부터 데이터베이스와 동기화하는 프로그램을 간단히 만들어 보도록 하겠습니다.

     <리스트 5> RSS 정보를 읽어 데이터베이스와 동기화하는 RSS 수집 로봇
    사용자 삽입 이미지

    Dim rssAddrs As RssAddressCollection = RssAddressCollection.LoadFromXml("MyRssAddressCollection.xml")
    Dim rssReader As New RSSReader
    Dim sqlcon As New SqlClient.SqlConnection("[데이터베이스 연결 문자열]")
    Dim ris As New RssItemSync(sqlcon)

    Console.WriteLine(rssAddrs.Count + "개의 블로그의 싱크를 시작합니다.")
    sqlcon.Open()
    For addrIndex As Integer = 0 To rssAddrs.Count - 1
        Console.WriteLine(rssAddrs(addrIndex).BlogName + " 블로그를 싱크 시작")
        rssReader.XmlAddress = rssAddrs(addrIndex).RssURL
        rssReader.readItems()

    For itemIndex As Integer = 0 To rssReader.Items.Count - 1
    ris.ItemSync(rssReader.Items(itemIndex))
        Next
        Console.WriteLine(rssAddrs(addrIndex).BlogName + " 블로그 싱크 완료!")
    Next
    sqlcon.Close()
    Console.WriteLine("전체 싱크가 완료되었습니다.")
    사용자 삽입 이미지

    여기에 시간대별로 반복해서 작업을 수행하게 하거나, MyRssAddressCollection.xml 파일을 메모장이 아닌 좀 더 쉽게 수정할 수 있는 방법만 만들어주고, 표현 계층을 멋지게 꾸미는 건 여러분들에게 맡기도록 하겠습니다. 멋진 RSS 수집 로봇을 완성해 주세요.

    RSS 수집 로봇의 문제점
    이번 강좌를 통해서 만들어본 RSS 수집 로봇은 RSS 파일을 읽고 관리하는 최소한의 기능들을 비교적 쉽게 구현하기 위해서 만들어진 프로그램입니다. 덕분에(?) 이 RSS 수집 로봇을 만들면서 여러 문제점들을 발견할 수 있었을 것입니다. 바로 RSS 파일을 일정 시간 간격으로 계속해서 읽는다면 네트워크 트래픽과 그것을 데이터베이스에 저장하는 과정에서 데이터베이스 처리량이 상당히 증가한다는 점인데요.

    이러한 문제점들을 해결하기 위해서는 RSS 파일을 지금과 같이 RssTextReader 클래스를 이용하지 않고, HttpRequest, HttpResponse 클래스를 이용해서 RSS 파일을 읽는 방법을 사용하면 됩니다. 이 경우 파일을 요청할 때 HTTP 프로토콜에 있는 If-Modified-Since 필드를 사용하면 변경되지 않은 파일의 경우 데이터의 내용 대신에 헤더의 값만 넘어오게 되므로 트래픽은 물론 처리해야 할 데이터도 줄어들게 됩니다.

    사용자 삽입 이미지
    <그림1> RSS 내용을 저장할 Rss 수집로봇의 원리


    그리고 RSS 파일의 주소가 몇 개 안 되는 지금 상태에서는 상관이 없지만, 100개가 넘어가는 경우 전체 RSS 파일을 싱크하는 시간은 점점 길어지게 됩니다. 하지만 자세히 살펴보면 데이터베이스를 처리하는 시간보다는 네트워크에서 파일을 불러오는 것에 상당한 시간이 소요되는 것을 볼 수 있습니다. 이 부분은 쓰레드를 이용하여 처리하면 더욱 빠른 속도로 싱크 작업을 할 수 있는 RSS 수집 로봇을 만들 수 있을 것으로 생각됩니다.

    이밖에도 일정 시간 간격으로 올라오는, 흔히 ‘도배’라고 불리는 글들에 대해서는 싱크하지 않게 하는 방법 등 여러 가지 기능들에 대해서 생각해 보기 바랍니다. 여기까지 완성되었다면 ASP.NET을 이용하여 메타 사이트의 모습을 만드는 마지막 과정은 여러분에게 맡겨도 되겠지요?


    메타 사이트 완성을 위해서 앞으로 해야 할 일들
    [1] RSS 파일을 읽어오는 부분의 보완
    [2] 싱크 기능을 멀티 쓰레드를 이용하여 처리하기
    [3] 데이터베이스 싱크 기능의 강화(도배 방지 등의 기능)
    [4] ASP.NET으로 웹 사이트 제작하기


    더 멋진 메타 사이트를 꿈꾸다
    아쉽게도 국내 3개 메타 사이트들의 기능은 모두 비슷합니다. RSS 파일을 읽고 그것을 표시해 주는 기본적인 기능들이죠. 메타 사이트의 등장은 오래 되었지만 아직도 메타 사이트는 걸음마 수준이라고 말하고 싶습니다. 이 말은 아직도 이 부분은 많은 실험과 도전 정신을 테스트해 볼 수 있는 미개척지란 말입니다.

    이 강좌를 통해 메타 사이트를 만들기 위한 아주 기본적인 기술들을 익혔다면 이제 그것을 활용하여 지금까지 없었던 새로운 메타 사이트를 설계해 보는 것은 어떨까요? 저는 인터넷 강국 대한민국이 블로그에서도 강국이 되기를 바라며 오늘도 더 멋진 메타 사이트를 꿈꾸고 있습니다. 이제 여러분의 상상력을 보여주세요.@

    * 이 기사는 ZDNet Korea의 제휴매체인마이크로소프트웨어에 게재된 내용입니다

     

    박영욱 (Allblog.net 운영자)

    2005/03/21

     

    사용자 삽입 이미지

     

    원문 :http://www.zdnet.co.kr/techupdate/lecture/dotnet/0,39024986,39134054,00.htm

    신고
    0  Comments,   0  Trackbacks
    댓글 쓰기
    웹 애플리케이션 개발의 진화「ASP.NET 2.0」

    웹 애플리케이션 개발의 진화「ASP.NET 2.0」

    ASP.NET 2.0, 웹 애플리케이션 개발의 진화

     

    연재순서
    1회.
    닷넷 개발의 새로운 변화, 비주얼 스튜디오 2005 맛보기
    2회.닷넷 프레임워크 2.0과 개발 언어의 변화
    3회. 웹 애플리케이션 개발의 진화, ASP.NET 2.0

     

    액티브 서버 페이지(ASP) 1.0이 세상에 처음 모습을 드러냈을 때, 개발자들의 반응은 냉담했었다. ASP라는 기술은 그다지 주목받지 못했으며, 그 기술이 훗날 전세계에서 가장 폭넓게 사용되는 웹 개발 기술이 될 것이라고는 누구도 예상하지 못했다.

    그리고 얼마간의 시간이 흐른 뒤, 웹 프로그래밍 계에 한 획을 긋게 될 ASP 2.0이 세상에 그 모습을 드러냈다. 그 시기는 인터넷이라는 것이 서서히 일상의 문화로서 한 자리를 찾아가는 시기이기도 했다. 전자상거래가 화두로 떠오르면서 전세계의 웹 개발자들은 기존 버전과는 달리 막강하게 변모한 ASP 2라는 기술에 관심을 보이기 시작했고, 눈 깜짝할 사이에 ASP는 세계에서 가장 효과적인 웹 애플리케이션 개발 기술로서 인정받게 되었다.

    그리고 기술은 계속 진화하여 ASP 3까지 발전하였으며, 종국에는 ASP와 닷넷 기술이 결합하여 ASP.NET까지 등장하게 되었다.

    ASP.NET 2.0 또 한 번의 놀라운 진화
    ASP.NET 1.0이 처음 ASP 개발자들에게 그 모습을 드러냈을 때, 사실 평가는 그다지 좋은 편이 아니었다. 그만큼 기대가 컸기 때문일까? 획기적인 개발 편의성을 기대했던 개발자들에게 ASP.NET은 단지 이벤트 지향 프로그래밍 방식으로 코드를 작성할 수 있다는 부분 이외에는 크게 눈길을 끄는 부분이 없어 보였다. 게다가 포스트백(Postback)이라는 새로운 페이지 처리 방식과 다소 복잡하게 느껴지는 코드 비하인드 모델에 몇몇 개발자들은 오히려 혼란스러움을 느끼기도 하였다.

    이는 대부분의 국내 웹 개발자들이 OOP 언어와 함께 프로그래밍을 시작하기 보다는 스크립트 언어와 함께 프로그래밍을 배웠기에 일어나게 된, 어쩌면 자연스러운 불만일 수 있다. 사실 객체지향적인 프로그래밍 방식에 대한 이해와 웹 프로그래밍의 처리 방식에 대한 이해를 모두 가져야만 제대로 이해할 수 있는 것이 ASP.NET이다. 둘 중 하나라도 지식이 부족하면 이 기술은 단지 쉬운 기술을 복잡하게 꼬아놓은 것으로 밖에 보이지 않을 수 있다. 그렇기에 ASP.NET이 인정을 받기 시작하는 데에는 그만한 시간이 필요했다.

    개발자들이 ASP.NET을 더 이상 ASP와 비교하지 않게 되자 제대로 된 ASP.NET의 모습을 이해할 수 있게 되었고, ASP.NET은 서서히 주변에 쓸만한 기술이라는 입소문을 내게 되었다. 하지만 기술 자체는 획기적이었지만 아무래도 1.0 버전의 새내기 기술은 기존 웹 개발자들이 기대한 만큼의 만족은 주지 못했던 것이 사실이다.

    버전 1.0이 나온 이후 4년. 상당히 오랜 기간이 흘러왔다. 그리고 아직 의견은 분분하지만 개발자들의 은근한 기대 속에서(다음 버전에 대한 기대) 그 사이 ASP.NET도 어느 정도 자신만의 자리를 차지하기 시작했다. 그리고 이러한 상황을 아는지 모르는지 ASP.NET 2.0이 드디어 그 모습을 드러내고 있다. 기대 반, 우려 반 속에서 말이다.

    ASP.NET 2.0, 날씨로 표현하면 ‘해 뜸’
    ASP.NET 2.0 알파, 베타 1 버전을 만나보고 난 필자의 느낌을 날씨로 이야기하라면 ‘해 뜸’이라고 표현하고 싶다. 대부분의 ASP.NET 개발자들이 서운해 했던 부분들에 대한 보완과 개선이 상당 부분 이루어져 있었기 때문이다(이번 버전을 준비하면서 아마도 MS 본사의 ASP.NET 팀은 웹 개발자들의 목소리에 귀를 상당히 많이 기울인 것 같다). 그리고 각 기능에 대한 구체적인 내용들을 살펴보면서는 다소 흥분되기 시작했다. “이건 뭐야? 개발자들을 다 없애버릴 작정인 건가?”라는 말이 나올 정도였으니 말이다.

    데이터베이스와 연동되는 그리드(일종의 게시판)를 작성하고, 사용자 로그인/로그아웃을 처리하고, 비밀번호 복구 및 사용자 추가/관리 기능, 사이트 탐색 메뉴 기능과 입력 값의 유효성 검사, 사이트의 테마와 스킨 등 기본적인 웹 사이트에서 필요한 공통 기능들을 프로그래밍 코드 한 줄 작성할 필요 없이 이룰 수 있다면, 여러분은 그런 생각이 들지 않겠는가?

    ASP.NET 2.0이 제공하는 새로운 기능들이 놀랍게도 바로 그러하다. ASP.NET 2.0이 새롭게 제시하는 프로바이더 디자인 모델 패턴(Provider Design Model Pattern)과 그와 관련된API들, 그리고 기존의 두 배가 넘는 서버 컨트롤들의 지원은 웹 개발 플랫폼의 또 한번의 진화라는 말이 무색하지 않을 정도로 획기적이라 할 수 있다. 더욱 놀라운 것은 그 기능적인 발전이 ‘기존 ASP에서 ASP.NET으로의 진화’에 필적할만한 수준임에도 불구하고, 학습하기에 그리 많은 비용(시간과 노력)을 요구하지 않는다는 점이다.

    ASP.NET 2.0은 그러한 혁신적인 기능들을 익히기 위해서 개발자에게 많은 시간을 요구하지 않는다(이는 다소 주관적인 판단일 수 있음을 밝힌다). 특정 기술의 새로운 버전이 나올 때마다 수많은 새로운 것들을 익혀야 한다는 압박 속에서 힘겨워했던 개발자들 입장에서 보면 이는 매우 기쁜 소식일 것이다.

    ASP.NET 2.0과 처음 인사를 나누게 되면 개발자들은 그 대단한 기능들에 감탄함과 동시에 그 간결한 사용법에 대해서도 감탄을 하게 된다. ASP.NET 2.0의 개발 코드 중 하나가 Codeless(코드가 필요 없는 개발)라는 것을 안다면, MS의 ASP.NET팀이 얼마나 개발자 편리성에 중점을 두어 ASP.NET 2.0을 준비하고 있는지를 간접적으로나마 느낄 수 있을 것이다.

    본론을 시작하기에 앞서 다소 안타까운 부분은 이번 글에서 ASP.NET 2.0의 모든 기능들을 세세하게 들여다보기는 어려울 것 같다는 것이다. 지면의 압박이 있기에 그렇기도 하지만 ASP.NET 2.0은 현재 기준 베타 1 버전이어서 차후 일부 변경될 소지도 있기에 그러하다.

    그래서 이번 컬럼에서는 개별적이고 세세한 기능적인 부분에 대한 논의보다는 전반적인 ASP.NET 2.0의 모습을 살펴보는 쪽으로 진행하도록 하겠다. ASP.NET 개발자 입장에서 보았을 때, 눈길을 크게 끄는 기능들을 중심으로 해서 말이다(ASP.NET 2.0에서 제공하는 새로운 기술들을 더욱 구체적으로 알아보고 싶다면이 웹페이지를 참고해 보기 바란다. 이는 ASP.NET 2.0의 새로운 기능들을 일목요연하게 정리해 놓은 MSDN의 컬럼 구역이다. <화면 1> 참조)

    사용자 삽입 이미지
    <화면 1> MSDN의 ASP.NET 2.0 컬럼들


    ASP.NET 2.0의 새로운 기능들
    ASP.NET 2.0 버전은 모든 기능 측면에 있어서 비약적인 발전과 강화가 있었다. 웹 페이지 개발 측면에서 바라보면 ASP.NET 2.0은 기능적으로 강화된 새로운 컨트롤들을 제공하고 있어서, 기존에 반복적으로 작성해야 했던 로직 및 기능들을 반복해서 작성할 필요 없이 매우 간단하게 ASP.NET 페이지에 그러한 기능들을 추가할 수 있다. 예를 들면, 인증 처리와 관련된 Login, PasswordRecovery, ChangePassword 컨트롤을 비롯하여, 다양한 스킨을 지원하는 Treeview 컨트롤, 사이트 메뉴 컨트롤, 데이터베이스 관련 작업을 위한 GridView, DetailView 컨트롤 등이 그것이다.

    게다가 지금 나열한 이러한 컨트롤들은 자체 처리 기능까지 내장하고 있어서, 단 한 줄의 코드 작성 없이도 자신의 역할을 수행해낸다. 예를 들면 Login 컨트롤은 단 한 줄의 코드도 없이 사용자 인증 처리를 스스로 처리하며, GridView 컨트롤도 웹 페이지 상에서 데이터를 쉽게 출력하고, 편집할 수 있는 기능을 단 한 줄의 코드 작성 없이도 가능하게 한다.

    프로바이더 디자인 모델 패턴의 도입
    이러한 편의성의 이면에는 프로바이더 디자인 모델 패턴이라는 추상적인 패턴의 도입이 있다. 프로바이더 개념은 처음에는 다소 어려운 개념처럼 느껴질 수 있지만 알고 보면 사실 크게 어렵지 않은 내용이며, 이미 대부분의 개발자들이 알고 있어왔던 개념이기도 하다.

    하지만 프로바이더라는 개념에 대한 이해가 없어도 그를 이용하여 ASP.NET 웹 애플리케이션을 개발하는 데에는 전혀 문제가 없다. 이는 마치 기존에 OLEDB 프로바이더에 대한 지식이 없어도 그를 이용해서 데이터베이스를 대상으로 맘껏 쿼리를 실행할 수 있었던 것과 같다. 프로바이더 디자인 모델 패턴은 기술적인 복잡함을 추상화하고 있기에 개념자체는 다소 복잡하게 보일지 몰라도 사용하는 측면에서 보면 상당히 쉽고 편리하다(<화면 2>).

    사용자 삽입 이미지
    <화면 2> 프로바이더 모델 디자인 패턴


    예를 들면 ASP.NET 2.0에서는 사용자 인증 및 관리를 위한 보안 관련 서버 컨트롤들이 새롭게 제공되는데, 이 컨트롤들은 프로바이더 디자인 모델 패턴과 멤버쉽(Membership)이라는 API를 통해서 실제 인증처리에 관한 모든 로직을 자체 제공 및 처리한다. 쉽게 말하면 Login, LoginView, CreateUserWizard, ChangePassword 등의 컨트롤이 보안과 관련된 대표적인 컨트롤인데, 이러한 컨트롤들은 내부적으로 액세스(Access) 데이터베이스를 자동으로 생성하여 그를 기반으로 인증을 처리한다는 것이다.

    기본적으로 ASP.NET 2.0은 MS 액세스 데이터베이스 파일을 인증 관련 요청이 처음 접수되는 경우, 동적으로 데이터베이스 파일을 만들어서(이미 존재하지 않을 경우에만) 그곳에 데이터를 저장하고, 그곳으로부터 필요한 데이터를 불러온다.

    이러한 내부적인 처리 프로세스는 이미 해당 컨트롤과 API 그리고 프로바이더를 통해서 구현되어져 있기에, 개발자는 코드 한 줄 작성할 필요 없이 적절한 서버 컨트롤을 사용하여 새로운 사용자를 추가하거나, 인증·관리할 수 있는 것이다. 물론 원한다면 데이터베이스 서버의 종류를 바꿀 수도 있다.

    ASP.NET 2.0이 기본적으로 제공해주는 프로바이더에는 AspNetAccessProvider와 AspNetSQLProvider가 있지만 정식 버전에서는 조금 더 늘어날 수도 있을 것 같다. 만일 정식 버전에서 여러분이 사용해야 하는 특정 데이터베이스 서버에 대한 프로바이더가 지원되지 않아도 크게 걱정할 것은 없다. 필요하다면 오라클이나, 인포믹스 등의 데이터베이스 서버를 이용하게끔 직접 설정할 수 있기 때문이다. 이를 위해서는 단지 별도로 프로바이더를 제작해주기만 하면 된다(별도의 작업이 요구되긴 하지만, 그리 어려운 작업이 아니다).

    하지만 대부분의 경우 개발자가 프로바이더들을 직접적으로 건드릴 일은 없을 것이다. 개발자들은 그보다는 주로 ASP.NET 2.0에서 새롭게 제공하는 편리한 API들을 즐기는 것으로 시간을 보내게 될 것이다.

    마스터 페이지 기능
    그리고 무엇보다 ASP.NET 개발자들이 기뻐할만한 소식은 UI 페이지 디자인 측면에서의 획기적인 지원, 마스터 페이지의 도입 소식이다. 마스터 페이지 기능은 기존 ASP.NET 1.x에서는 사용자 정의 컨트롤과 같은 것을 이용해서 다소 복잡하게 처리해야 했던 공통 UI의 재사용을 획기적으로 개선한 것으로, 웹 폼에서 비주얼 상속(Visual Inheritance)을 가능하게 하는 기술이다. 마스터 페이지의 논리적인 모습은 <화면 3>을 보면 이해가 쉬울 것이다.

    사용자 삽입 이미지
    <화면 3> 비주얼 상속을 가능케 하는 마스터 페이지


    <화면 3>에서 보이는 것처럼, 마스터 페이지는 최종 UI 페이지에 반복적으로 재사용하게 될 내용들을 별도의 파일로써 정의해 둔 페이지를 말한다. 이렇게 마스터 페이지로 작성해 두고, 각각의 최종 UI에서 이러한 마스터 페이지를 이용한다면 공통적인 UI를 그대로 물려받게 됨으로써 개발 생산성이 크게 향상될 수 있다. 이는 마치 MS 파워포인트에서의 마스터 슬라이드를 연상하면 쉽게 이해가 될 것이다. <화면 4>는 비주얼 스튜디오 닷넷 2005(이하 VS.NET 2005)에서 마스터 페이지를 사용하여 페이지를 개발하고 있는 모습이다.

    사용자 삽입 이미지
    <화면 4> VS.NET에서의 마스터 페이지 사용


    ASP.NET 2.0의 또 다른 진화는 바로 향상된 코드 비하인드 모델이다. 코드 비사이드(code-beside)라고도 불리는 이 기술은 Partial이라는 새로운 확장 클래스 개념을 통해서 코드 비하인드 클래스가 System.Web.UI.Page를 직접적으로 상속하지 않고, Page 클래스를 별도로 확장하는 개념을 적용하고 있다(<화면 5> 참고).

    사용자 삽입 이미지
    <화면 5> ASP.NET 코드 비하인드 모델의 비교


    이러한 변경으로 인해 기존 ASP.NET 1.x에서 개발자의 실수로 간혹 발생하곤 했던 런타임시의 타입 불일치 문제는 명쾌하게 해결된다. 예를 들면 그러한 문제의 전형적인 시나리오는 다음과 같다. 기존 ASP.NET 1.x 시절에는 UI 페이지와 코드 비하인드 페이지가 명시적으로 연계된 구성을 가지고 있었다. 즉 UI 페이지에 서버 컨트롤이 추가되면 그에 따라 코드 비하인드 페이지에도 해당 컨트롤의 객체 선언이 추가되어야 해당 객체를 인식할 수 있는 구조로 되어져 있었으며, 빌드 및 배포 후에 컨트롤의 ID가 변경된다거나 UI 단에서 서버와의 연계성을 가진 특정 값들에 변경이 일어나면 서버에서 ‘예기치 않은 오류’가 발생할 수 있는 구조를 가지고 있었다.

    ASP.NET 2.0은 이러한 문제를 원천적으로 해결하기 위해서 코드 비하인드 파일을 상속되는 형식이 아닌 확장되는 형식으로 바꿈으로써 UI 페이지의 서버 컨트롤과 코드 비하인드의 실제 코드 간의 연결이 ASP.NET 런타임에 의해서 실제 런타임시에 관리되도록 내부 구조를 변경하였다. 그 결과 개발자가 작성해야 할 코드(VS.NET이 자동으로 생성해주는 코드를 포함하여)도 혁신적으로 줄어들게 되었으며, 안전성 및 개발 생산성 측면에서도 상당한 진일보를 이룰 수 있게 되었다.


    <리스트 1>과 <리스트 2>는 각각 ASP.NET 1.x 시절의 코드 비하인드 파일과 ASP.NET 2.0 버전의 코드 비하인드 파일의 일반적인 소스를 보여주고 있다. 두 리스트는 모두 페이지가 로드될 때, 라벨(Label) 컨트롤에 인사 메시지를 출력하는 코드를 포함하고 있다. 두 코드를 비교해 봄으로써 코드 비하인드의 내부적인 처리 구조 변화가 어떻게 개발 생산성을 높여주는 지 확인해 보기 바란다.

     <리스트 1> ASP.NET 1.x의 코드 비하인드 파일
    사용자 삽입 이미지

    namespace WebApplication1
    {
            public class WebForm1 : System.Web.UI.Page
            {
                     protected System.Web.UI.WebControls.Label Label1;
                     private void Page_Load(object sender, System.EventArgs e)
                     {
                             Label1.Text = "Hello ASP.NET 1.x";
                     }

                     #region Web Form Designer generated code
                     override protected void OnInit(EventArgs e)
                     {
                             InitializeComponent();
                             base.OnInit(e);
                     }

                     private void InitializeComponent()
                     {
                             this.Load += new System.EventHandler(this.Page_Load);
                     }
                     #endregion
            }
    }
    사용자 삽입 이미지

     <리스트 2> ASP.NET 2.0의 코드 비하인드 파일
    사용자 삽입 이미지

    namespace WebApplication1
    {
            public partial class Webform1_aspx
            {
                     void Page_Load(object sender, EventArgs e)
                     {
                             Label1.Text = "Hello ASP.NET 2.0";
                     }
            }
    }
    사용자 삽입 이미지

    눈에 띄는 변화, 캐싱
    ASP.NET 2.0에서 눈에 띄게 개선된 또 다른 기능은 바로 캐싱(Caching)이다. 기존의 캐싱 기능들을 성능적으로 개선한 것에 더하여 캐시를 위한 새로운 방안들도 추가되었는데, 이 들 중 개발자들의 눈길을 가장 크게 끄는 기능은 바로 SQL 서버 데이터베이스의 테이블에 캐시 종속성을 지정할 수 있는 기능이다. 이 기능을 이용하면 개발자는 테이블의 데이터가 변경되는 그 즉시 캐시가 갱신되도록 캐싱 정책을 세울 수가 있게 된다.

    또한 ASP.NET 2.0에서는 개발자가 다양한 방식으로 웹 사이트와 웹 페이지를 사용자 정의할 수 있다. ASP.NET 2.0에서 제공하는 프로필(Profile) API를 사용하면 개별 사용자용 속성 값들을 자동적으로 할당 및 추적할 수 있는 기능을 제공할 수 있기 때문이다. 프로필 클래스는 기존 세션(Session) 변수의 역할과 다소 비슷하다고 생각하면 이해가 용이하다. 하지만 세션에 비해 성능적으로도 뛰어나고, 개발자가 다루기에도 훨씬 직관적이기에 더욱 매력적으로 느껴질 것이다.

    프로필 클래스는 또한 ASP.NET 사용자 개별화(Personalization)의 일부이기에 이를 적절히 이용하면 ASP.NET 2.0에서 새롭게 제공되는 포탈 프레임워크 기능인 웹 파츠(Web Parts)와 연계할 경우 놀랄만한 사용자 정의 기능을 제공할 수 있게 된다. 즉 ASP.NET 2.0의 프로필과 웹 파츠를 이용하여 사이트를 제작할 경우에는 사용자가 브라우저 내에서 그들만의 페이지 구성 및 레이아웃을 꾸밀 수 있게끔 웹 애플리케이션을 구성할 수 있다는 이야기이다.

    별로 놀랍지 않은가? 아마도 그럴 것이다. 그렇게 작성된 결과가 구체적으로 어떤 모습일지가 머리 속에 잘 그려지지 않았을 테니 말이다. 그렇다면 백문이 불여일견이다. 그렇게 꾸며진 사이트를 직접 눈으로 본다면 아마 이해하기가 더 쉬울 것이다. MS MSN 사이트에 접속하여, My MSN 기능을 이용해보라. 바로 그와 동일한 기능을 ASP.NET 포탈 프레임워크와 프로필을 이용하면 대단히 쉽게 제작할 수 있다는 것이니 말이다(<화면 6>).

    사용자 삽입 이미지
    <화면 6> My MSN 기능은 ASP.NET 포탈 프레임워크 기능과 유사한 모습


    www.msn.com에서 로그인을 하고, My MSN으로 가면 각 사용자는 자신이 원하는 대로 컬럼 창을 추가하거나, 위치시킬 수 있다. 뿐만 아니라 각 창을 드래그 앤 드롭으로 이동시킬 수도 있다.

    클라이언트 스크립트를 즐겨 다루는 이들은 알겠지만 이 기능은 직접 개발자가 작성할 경우, 스크립트로 상당히 복잡한 로직을 작성해서 처리해야만 한다. 이로 인해 스크립트를 상당히 잘 다루지 못하면 구현하기가 대단히 어려운 기능이기에 개발 중인 웹 애플리케이션에 이러한 기능을 적용한다는 것은 대부분의 경우 마음만인 경우가 많았을 것이다.


    ASP.NET 2.0의 포탈 프레임워크와 개별화 기능을 이용하면 이 또한 쉽게 구현이 가능하다. 뒷단에 존재하고 있을 수많은 클라이언트 스크립트 기법과 기반 구조를 이해하지 않고서도 말이다.

    이를 위한 기반 구조를 제공해 주는 것이 ASP.NET 포탈 프레임워크이며, 그 중 사용자마다의 설정을 유지할 수 있도록 도와주는 기능이 개별화의 프로필 클래스이다. 앞에서도 잠깐 이야기했지만 프로필 클래스가 제공하는 기능은 기존에 세션 객체를 통해서 개발자가 각 개인의 정보를 유지했던 것과 유사한 것이라 할 수 있다. 하지만 성능적으로나 사용성 측면에서 보았을 때 세션을 이용하는 것보다 상당히 낫다(물론 이 부분은 논란이 있을 수 있으므로, 상황에 따라 다를 수도 있다는 전제를 추가적으로 덧붙여 두도록 하겠다).

    트리뷰와 메뉴 컨트롤
    ASP.NET 2.0에서는 또한 상당히 많은 신인 컨트롤들이 새로이 데뷰하고 있기도 하다. 그 중 우리의 눈길을 끄는 대표적인 컨트롤로는 트리뷰(TreeView) 컨트롤과 메뉴 컨트롤이 있는데, 이들은 사용하기도 매운 쉬울 뿐만 아니라 자체 스타일 기능이 내장되어져 있어서 꾸미기에도 매우 쉽다는 장점을 갖고 있다.

    트리뷰의 경우는 ‘자동 속성’ 기능을 이용해서 디자인을 최신의 MS 스타일로 쉽게 작성할 수 있으며, 메뉴 컨트롤의 경우는 클라이언트 스크립트에 대한 부담 없이 쉽게 동적으로 나타나는 메뉴를 구성할 수 있다(<화면 7>). 모든 복잡한 내부 처리는 ASP.NET 2.0이 대신해 주고 있는 것이다.

    사용자 삽입 이미지
    <화면 7> 트리뷰 컨트롤과 메뉴 컨트롤의 모습


    ASP.NET 2.0에서 개발자들이 반가워할 만한 또 다른 소식은 2.0부터는 다른 페이지로의 전송(페이지 교차 포스팅, Cross-Page Posting)이 가능하게 된다는 것이다. 물론 ASP.NET 1.x 버전에서도 다른 페이지로 데이터를 전송하는 것이 불가능하지는 않았었다. 웹 폼을 이용하지 않고 Html 폼을 이용한다면 말이다.

    하지만 그렇게 하게 되면 ASP.NET의 기반 서비스를 전혀 이용하지 않는 것이 되므로(ASP.NET을 도입하는 의미가 전혀 없게 되기에) 사용이 권장되지 않았다. 이로 인해 특별한 이유가 있지 않은 한 ASP.NET 1.x에서는 기본적으로 웹 폼은 포스트백(자기 자신 페이지로의 전송)을 기본 원칙으로 했다. 이는 ASP.NET 2.0에서도 달라지지 않았지만, 2.0은 개발자의 목소리에 경청을 한 덕분인지 추가적으로 교차 페이지 전송도 지원한다. 이로써 웹 개발자는 여러 페이지에 걸쳐서 어떤 프로세스를 수행할 수 있게 된 것이다.

    페이지 교차 포스팅을 하기 위한 간단한 방법은 버튼 컨트롤의 PostBackUrl 속성을 이용하는 것이다. 버튼의 PostBackUrl 속성에 이동할 페이지 명을 지정하면, 해당 버튼이 클릭될 경우에는 그 페이지로 교차 전송이 일어나게 된다. <리스트 3>은 페이지 교차 포스팅을 요청하는 버튼 컨트롤의 소스를 보여주고 있다. 소스 코드 중 굵은 부분에 주목하라(샘플에서의 현재 페이지 이름은 PageOne.aspx이다).

     <리스트 3> PageOne.aspx
    사용자 삽입 이미지

    < %@ Page Language="VB" AutoEventWireup="false" CompileWith="PageOne.aspx.vb"
    ClassName="PageOne_aspx" %>
    < html>
    < head runat="server">
    < link href="site.css" type="text/css" rel="stylesheet" />
    < /head>
        < body>
            <form id="form1" runat="server">
                     < asp:DropDownList ID="Friends" Runat="server" >
                     < asp:ListItem >김태영</asp:ListItem>
                     < asp:ListItem >최용기</asp:ListItem>
                     < /asp:DropDownList >
                     < asp:Button ID="btnCrossPage" Runat="server" Text="Cross-Page Posting" PostBackUrl="PageTwo.aspx" / >
                     < p >선택 항목 : >asp:Label ID="Msg" Runat="server" Text="">< /asp:Label >< /p >
            < /form >
        < /body >
    < /html >
    사용자 삽입 이미지

    페이지 교차 포스팅의 대상이 되는 페이지(샘플의 경우 PageTwo.aspx)는 반드시 지시문(Directive) 구역에 @PreviousPage를 지정해 주어야 한다. 자신이 참조할 이전 페이지의 형식이나 경로를 지정해 줘야만 현재의 페이지에서 이전 페이지의 멤버들에 접근이 가능하게 되기 때문이다. <리스트 4>는 @PreviousPage 지시문을 추가적으로 설정하고 있는 두 번째 페이지의 HTML 소스를 보여주고 있다.
     <리스트 4> PageTwo.aspx
    사용자 삽입 이미지
    <%@ Page Language="VB" AutoEventWireup="false" CompileWith="PageTwo.aspx.vb" ClassName="PageTwo_aspx" %>
    <%@ PreviousPageType VirtualPath="~/PageOne.aspx" %>
    <html>
    <head runat="server">
        <link href="site.css" type="text/css" rel="stylesheet" />
    </head>
    <body>
            <form id="form1" runat="server">
                     <p>PageOne에서 선택한 항목 : <asp:Label ID="Msg" Runat="server" /></p>
            </form>
    </body>
    </html>
    사용자 삽입 이미지

    그리고 <리스트 5>는 두 번째 페이지(PageTwo.aspx)의 코드 비하인드에서 어떻게 이전 페이지(PageOne.aspx)의 DropDownList 컨트롤에 접근하는지 그 방법을 보여주고 있는데, 이는 Page 개체의 PreviousPage 속성 객체를 통해서 가능하다. <화면 8>은 이러한 동작의 결과를 보여준다.
     <리스트 5> PageTwo.aspx의 코드 비하인드 소스
    사용자 삽입 이미지
    Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            Dim ddl As New DropDownList
            ddl=CType(Page.PreviousPage.FindControl("Friends"), DropDownList)
            Msg.Text = ddl.SelectedValue
    End Sub
    사용자 삽입 이미지

    사용자 삽입 이미지
    <화면 8> 페이지 교차 포스팅의 실행 모습


    ASP.NET 2.0이 제공하는 편리함은 개발 측면에만 한정된 것이 아니다. 관리적인 측면에서도 ASP.NET은 진보된 편리성을 제공하는데, 이전 ASP.NET 1.x 버전의 경우는 웹 애플리케이션 관리를 위해서 Web.config라는 XML 파일을 직접적으로 변경하여야 했던 반면, ASP.NET 2.0에서는 IIS 내에 ASP.NET 설정 구성을 위한 UI가 포함됨으로써 더욱 쉽게 사이트를 관리할 수가 있게 되었다(<화면 9> 참고).

    사용자 삽입 이미지
    <화면 9> IIS와 통합된 ASP.NET 2.0 구성 윈도우


    또한 웹 어드미니스트레이션 툴(Web Administration Tool)이라는 웹 애플리케이션 관리 사이트를 제공해 줌으로써 여러 웹 사이트 관련 관리를 용이하게 해 준다. 여기서 제어할 수 있는 것들로는 보안, 프로필, 애플리케이션 환경 설정, 프로바이더 환경 설정 등이 있다(<화면 10> 참고).

    사용자 삽입 이미지
    <화면 10> ASP.NET 웹 사이트 관리도구


    지금까지 간략하게 ASP.NET 2.0의 몇몇 특징들을 살펴보았는데, 앞에서 설명한 많은 기능들은 ASP.NET 2.0에서 제공되는 진보된 기능들의 일부에 불과할 뿐이다. 지금까지의 이야기로 새로운 기술에 대한 기대감과 반가움이 교차하는 사람들은 이 글을 모두 읽은 뒤에 MSDN 사이트로 이동하여, 그 멋진 모습들을 더 구체적으로 살펴보길 권한다. 비록 영어의 압박이 느껴진다 해도 내용 자체는 매우 재미있을 것이다. 필자가 꼭 읽어보라고 권하고 싶은 컬럼은 ASP.NET 인터널(Internals)이다.

    VS.NET 2005, 웹 개발자 중심의 개발 도구로 진화
    현재 필자는 이 글을 작성하는 것에 더하여, 11월과 12월에 걸쳐 MSDN 세미나를 통해서 ASP.NET 2.0에 대한 내용을 발표하고 있기도 하다. 세미나에서는 이 글에서는 간략하게 소개할 수밖에 없었던 내용들을 실제 데모와 함께 조금은 구체적으로 파고들어 진행했는데, 세미나를 경청한 개발자들 대부분의 피드백은 ‘기대가 된다’였다. 그리고 ASP.NET 2.0의 이러한 진보에 맞춰 VS.NET은 어떤 편리한 기능들을 제공하려고 준비 중에 있는지 궁금해 하는 사람들이 많았다. 그래서 그 부분에 대한 이야기도 이 자리에서 조금 같이 나누어 볼까 한다.

    최고의 집을 짓기 위한 자재와 기반은 ASP.NET 2.0이 모두 준비해 주었다. 그렇다면 이제 개발자의 입장에서 남은 것은 어떤 도구로 집을 지을 것인가 일 것이다. 맨 손으로 집을 짓는 것은 아무래도 무모해 보인다. 그렇게 여유로운 프로젝트는 사실 현실 세계에서는 존재하지 않을 테니 말이다. 그러한 이유로 많은 개발자들이 닷넷(ASP.NET 포함) 프로그래밍을 위해서 VS.NET을 선택해 왔다. VS.NET의 새로운 버전은 2005로써 ASP.NET 2.0의 등장과 발맞추어 출시될 예정에 있다. 현재는 베타 버전이 인터넷을 통해서 배포되고 있다.

    VS.NET 2005에서도 웹 개발자들을 위한 많은 보강이 있었다. 개발자들이 불편하다고 생각했던 많은 부분들이 개선되었으며, 개발자 각각이 자신의 취향에 맞게 툴을 설정할 수 있는 옵션들도 상당히 많이 제공되고 있다. 무엇보다 가장 크게 눈에 띄는 부분은 더 이상 VS.NET이 웹 서버에 의존적이지 않다는 부분이다. VS.NET은 웹 페이지 실행시 자체적으로 보유하고 있는 가상 웹 서버(이전 버전의 카시니와 유사)를 먼저 구동시키고 그 가상 서버에서 웹 페이지를 실행하게 한다. 그리고 가상 웹 서버는 VS.NET을 닫는 순간 모두 같이 해제된다.

    이것은 큰 의미를 지닌다. 왜냐하면 이제 개발자는 더 이상 IIS에 의존적이지 않아도 되며, 그에 따라 웹 파일들의 관리도 상당히 간단해지고 용이해지기 때문이다.

    예전에는 프로젝트 파일과 실제 웹 파일들이 서로 다른 폴더에 형성됨으로 해서(설정을 바꾸지 않았다면, 웹 파일들은 VS.NET에 의해 자동적으로 C:\inetpub\wwwroot에 놓여진다) 관리 측면에서 다소 혼란스러움이 있었지만, 이제는 반드시 가상 웹 애플리케이션으로 특정 디렉터리를 설정하지 않아도 특정 폴더를 웹 폴더처럼 만들어 개발할 수 있게 되었기 때문에 더 이상 웹 애플리케이션을 위한 파일들을 C:\inetpub\wwwroot에 올릴 필요도, 각 파일들을 관리하기 위해서 폴더를 이리 저리 돌아다닐 필요도 없게 되었다(<화면 11> 참고).

    사용자 삽입 이미지
    <화면 11> VS.NET에서 가상 웹 개발 서버를 자체 보유 및 가동하는 모습


    초보자를 위한 스타터 킷 사이트
    또한 초보 개발자를 위해서 스타터 킷 사이트가 템플릿으로 제공되는데, <화면 12>처럼 『새 웹 사이트 | Personal Web Site Starter Kit』을 선택하면 자동으로 자신의 소개 및 이미지 갤러리를 제공하는 심플한 수준의 웹 사이트가 자동으로 생성된다. 겉으로 보기엔 단순해 보일 수 있지만, 기능적으로는 제법 쓸만하게도 사용자 가입·인증·보안처리까지 다 되어있는 훌륭한 사이트이다.

    자동 생성된 사이트의 소스를 살펴보면서 소스 분석을 해보는 것은 초보자에게 상당한 도움이 될 것이다. 장담컨대 소스 분석을 하다 보면 여러분은 반드시 놀라게 될 것이다. 왜냐하면 갖출 것은 어느 정도 갖춘 규모의 개인 사이트임에도 전체 소스 코드는 단 30 줄도 안 되기 때문이다. 퍼스널 웹 사이트 스타터 킷은 ASP.NET 2.0팀의 Codeless 목표가 ASP.NET 전반적으로 상당 부분 녹아있음을 입증해 주는 좋은 예이다.

    사용자 삽입 이미지
    <화면 12> Personal Web Site Starter Kit


    또한 VS.NET 2005부터는 하나의 프로젝트에서 다중 언어를 사용하는 것도 지원된다(사실 하나의 애플리케이션에서 다중 언어를 사용하는 것은 이전 1.x 버전에서도 가능하였다. 단지, VS.NET이 그것을 지원하지 않았을 뿐이다). 뿐만 아니라 프로젝트에서 페이지 단위로 컴파일을 하는 것도 가능하다. 하나의 프로젝트는 반드시 하나의 DLL로 빌드 되었던 이전의 불합리함을 완전히 개선한 것이다.

    디자인 측면의 보완
    디자이너 측면에서도 많은 부분이 보완되었는데, VS.NET 2005는 더 이상 개발자가 작성해 놓은 HTML을 자동으로 재정렬하여서, 기껏 들여쓰기를 한 개발자의 마음을 더 이상 아프게 하지 않는다. 또한 도구 상자로부터 컨트롤을 드래그 앤 드롭 하여 웹 폼에 컨트롤을 올려놓는 방식이 코드 뷰에서도 가능하게 되었다는 점도 재미있다.

    또한 기쁜 소식은 VS.NET 2005에서는 인텔리센스 기능이 완전하게 제공된다는 것이다. HTML 뷰에서도, Web.Config에서도 이제는 인텔리센스 기능이 지원된다. ASP.NET 1.x 시절에는 많은 개발자들이 이러한 부분에서 인텔리센스 기능이 지원되지 않아 불편해 했었다. 더욱 인텔리센스 기능이 지원되도록 직접 작업을 한 개발자들도 있었다.

    또한 VS.NET 2005에서는 웹 애플리케이션의 쉬운 복사 및 배포를 위한 기능들도 제공된다. <화면 13>과 <화면 14>에서 볼 수 있듯이, 로컬 파일 시스템이나 FTP, IIS, 원격 웹 사이트로의 배포가 클릭만으로 가능하도록 편리한 방법들을 제공하고 있는 것이다.

    사용자 삽입 이미지
    <화면 13> 웹 사이트 복사하기


    사용자 삽입 이미지
    <화면 14> 웹 애플리케이션 퍼블리싱하기


    그 외에도 소스 작성과 관계되어 수많은 편리한 기능들을 VS.NET 2005는 제공하고 있지만, 세세한 부분은 차후 정식 버전이 발표된 다음에 알아보는 것이 좋을 듯 하여 말을 아끼려 한다. 아직은 베타 1 버전이기에 베타 2와 RTM을 거치면서 사소한 기능적인 변경이 있을 수 있기 때문이다.

    이번 글은 ASP.NET 베타 1을 기반으로 하여 작성된 것이기에, 정식 버전이 나오면서 이 글에서 설명한 기능들 중 일부에 변화가 있을 수 있다는 점은 기억하도록 하자. 현재의 일정대로라면 내년 중반 즈음에 ASP.NET 2.0은 정식으로 세상에 등장하지 않을까 싶다.

    게으른 모습을 경계하라
    ASP.NET 2.0은 다소 불안하게 느껴지기도 했던 ASP.NET의 미래에 대한 확실한 청사진을 제시하고 있다. 스마트 클라이언트가 세상을 지배하고 곧 ASP.NET은 사라지게 될 것이라는 루머 속에서 자신의 강화된 모습을 제시하여 ASP.NET의 역할이 어떤 것인지를 강하게 피력하고 있는 것이다.

    인터넷을 하기 위해서 브라우저를 사용하고, 인터넷을 위한 데이터 기반이 HTML인 이상 ASP.NET은 웹 애플리케이션 개발에서 빠질 수 없는 기술이다. 그리고 그러한 자신의 위치에서 모든 웹 개발자들이 필요로 했던 대부분의 공통적인 기능들을 ASP.NET 2.0은 제공하고 있다.

    어쩌면 웹 개발자들이 해야 할 일이 없어지는 것은 아닐까 우려하는 목소리도 나오겠지만, 그것은 우려해야 할 소식이 아니라 기뻐해야 할 소식이다. 반복적인 UI 작업으로 인해, 자신이 코더인지 개발자인지에 대한 정체성 혼란을 한번이라도 느껴봤던 개발자라면 이번 ASP.NET 2.0을 통해서 진정한 개발자로 거듭날 수 있는 기회를 붙잡게 된 것이다.

    물론 모든 것은 자신의 마음에 달려있고, 자신이 많은 부분을 노력해야 하겠지만, 이젠 페이지의 UI, 컨트롤의 특정 기능지원 여부로 끙끙대는 시간보다는 비즈니스 로직의 개발 및 클래스 설계, 패턴 분석 쪽으로 더 많은 시간을 가질 수 있게 될 것이다. 코더의 역할은 ASP.NET 2.0이 상당 부분 책임져 줄 것이기 때문이다.

    다만 ASP.NET 2.0이 제공하는 편리함이 오히려 개발자를 나태하게 만들 수도 있다는 부분은 다소 우려스러운 부분이다. 그 점에서 우리는 나태한 개발자가 되지 않도록 노력해야 한다. 기술의 편리함, 도구의 편리함은 인간을 돕기도 하지만, 그만큼이나 게으르게도 하니 말이다. 꾸준한 노력을 마음에 품고, 시야를 조금씩 더 넓혀 나가자.

    ASP.NET 2.0은 웹 개발자에게 그러한 시야를 가질 수 있도록 도와줄 것이다. 그리고 기술적인 고민의 시간들을 통해서 여러분은 진정한 개발자로 거듭날 수 있을 것이다.@


    * 이 기사는 ZDNet Korea의 제휴매체인마이크로소프트웨어에 게재된 내용입니다

     

    김태영 (Taeyo.net 사이트 운영자)

    2005/03/04

     

    사용자 삽입 이미지

     

    원문 :http://www.zdnet.co.kr/techupdate/lecture/asp/0,39024946,39133971,00.htm

    신고
    0  Comments,   0  Trackbacks
    댓글 쓰기
    닷넷 프레임워크 2.0과 개발 언어의 변화

    닷넷 프레임워크 2.0과 개발 언어의 변화

    개발 환경의 새로운 변화, 비주얼 스튜디오 2005 분석

     

    연재순서
    1회.닷넷 개발의 새로운 변화, 비주얼 스튜디오 2005 맛보기
    2회.닷넷 프레임워크 2.0과 개발 언어의 변화
    3회. 웹 애플리케이션 개발의 진화, ASP.NET 2.0

     

    2000년 봄 NGWS(Next Generation Windows Services)라는 이름으로 소개됐던 MS의 차세대 개발 환경이 오랜 베타 기간의 높은 관심을 뒤로 하고, 2002년 닷넷 프레임워크 1.0·비주얼 스튜디오 닷넷 2002와 함께 세상에 나타났다.

    그 후 마이너 업그레이드인 닷넷 프레임워크 1.1과 비주얼 스튜디오 2003으로 안정화됐고, 이제는 2005년 출시를 위해 현재 닷넷 프레임워크 2.0과 비주얼 스튜디오 2005 베타1이 출시됐다. 베타 시절의 열기가 실제 출시 시점의 IT 경기 급랭으로 다소 부진하지 않느냐는 의견이 있었지만 기업 환경을 중심으로 2년간 성장세를 올리고 있다. 비록 북미 지역으로 제한되어 있지만 2003년말을 기준으로 닷넷 개발자가 자바 개발자를 넘어서고 있다(<그림 1>).

    국내에서는 아직 닷넷의 점유율이 자바에 비해 낮지만 빠른 시간에 바뀔 것으로 예상되고 있다. 이제 본격적으로 MS의 개발 환경의 변화에 대해 알아보겠다.

    사용자 삽입 이미지
    <그림 1> 닷넷 플랫폼 채택률(2002.2/4분기~2003년 2/분기)


    닷넷 프레임워크 2.0의 변화
    최근 들어 많은 개발자들이 MS의 개발 환경은 닷넷 프레임워크와 비주얼 스튜디오 닷넷 개발 툴만으로는 2% 부족하다는 것을 이야기하고 있다. 이 2%에 어떤 것이 포함되어 있기 때문에 닷넷 프레임워크와 비주얼 스튜디오만으로는 힘들다는 것인지 한 번 살펴보겠다.

    닷넷은 단순한 개발 프레임워크라기보다는 빈틈없는 컴퓨팅 환경을 구축하기 위한 웹 서비스 인프라 시스템이다. 윈도우와 엔터프라이즈 서버를 통해 운영 인프라 구조를 제공하고, 기존 웹 서비스인 ASMX와 WSE(Web Services Enhancements), 롱혼의 인디고(Indigo)를 위해 연결된 시스템 환경이 된다. 그리고 서비스, 아키텍처 가이던스(Patterns & Practices,
    msdn.microsoft.com/architecture/patterns/default.aspx), 디바이스, 비즈니스 응용, 정보 근로자 도구와 인프라를 종합적으로 지원하고 있다.

    이렇게 복잡한 환경을 지원하니 개발자들이 닷넷 개발 환경에 대해 혼란을 느끼게 되고 닷넷이 도대체 무엇인지 잘 모르겠다는 이야기를 많이 하게 된다.

    혼란(?)을 줄이기 위해 우선 닷넷 프레임워크에 대해서만 살펴보자. 닷넷 프레임워크는 CLS(Common Language Specification)를 지원하는 언어(C#, VB.NET, J#, 매니지드 C++ 등)로 만들어진 IL(Intermediate Language)로 작성된 코드를 실행하는 환경이다.

    닷넷 프레임워크 2.0은 크게 CLR 2.0, 윈도우 폼(Windows Forms) 2.0, ASP.NET 2.0, 닷넷 컴팩트 프레임워크 2.0, ADO.NET 2.0으로 구분할 수 있다. CLR 2.0을 제외한 다른 내용은 BCL에 포함되는 라이브러리 성격이 강하므로 여기서는 CLR 2.0을 중심으로 살펴보겠다. 닷넷 2.0의 큰 변화를 살펴보면 다음 세 가지 영역으로 구분할 수 있다.

    ◆ 플랫폼 확장 : SQL 서버와 통합, 64비트 프레임워크 지원

    ◆ 플랫폼 개선 : 성능 향상, RAD 디버깅, CLR 보안 강화

    ◆ 플랫폼 혁신 : 제너릭(Generics) 지원, BCL 강화


    먼저 SQL 서버와의 통합으로 가질 수 있는 장점은 다음과 같다.

    ◆ 닷넷 프레임워크의 개발 모델을 데이터베이스 층에도 바로 적용할 수 있다.

    ◆ 비즈니스 로직을 개발 층으로 쉽게 마이그레이션할 수 있다.

    ◆ 데이터베이스 확장을 안전하고 쉽게 진행할 수 있다.


    결론적으로 저장 프로시저와 트리거(Triggers), 데이터 타입의 정의를 관리되는 코드(managed code)로 할 수 있으므로 훨씬 개발 지향적인 데이터베이스 환경을 제공해준다.

    사용자 삽입 이미지
    <그림 2> SQL 내의 CLR 기능


    64비트 프레임워크 지원으로 가질 수 있는 장점으로는 x86-64와 IA-64 아키텍처·관리되는 실행 환경·WoW64 지원을 들 수 있다. 현재 64비트 프레임워크 역시 베타1이 나와 있는 상태이고 비주얼 스튜디오 2005를 설치할 때 인텔과 AMD CPU를 선택해 설치할 수 있다. WoW64 지원으로 64비트 환경에서 32비트 환경 구동이 가능하며 개발, 배포, 디버깅 또한 64비트와 32비트를 선택할 수 있다.

    성능 역시 크게 향상됐다. 기존 CLR 1.1에 비해 CLR 2.0은 애플리케이션 구동 시점의 IL 코드 병합과 구동에서 좋은 성능을 보여주며, 한 번 JIT(Just In Time) 컴파일된 코드를 디스크에 저장한 후 사용함으로써 성능이 향상됐다. 그리고 APPDomain Remoting에서 수십 배 이상, 그리고 델리게이트(delegate) 처리에서 두 배의 성능을 보여준다. UTF-8 인코딩은 여덟 배 정도의 차이를 보이고 있다.

    또한 디버깅 모드로 실행시 코드 편집(클래스 내의 필드와 메쏘드)과 계속 기능을 통해 디버깅 환경이 더욱 개선됐으며, CLR 보안 역시 강화됐다. PKCS7과 XML 암호화 기능이 추가됐으며 X509 인증이 추가됐다. 그 외에도 권한 허가 계산기 기능이 ClickOnce와 통합되어 사용할 수 있다.

    이와 같은 변화가 있지만 다음에 소개할 제너릭 기능이 가장 큰 변화이며 기능 또한 강력하다 할 수 있겠다. 제너릭 기능에 대해서는 좀 더 자세히 살펴보겠다.

    제너릭
    2002년에 열린 OOPSLA(Object-Oriented Programming, Systems, Language, and Applications)에서 C#의 아버지인 Anders Hejlsberg가 다음 버전의 C#에 추가될 새로운 특징들로 제너릭, 익명 메쏘드(anonymous method), 이터레이터(iterator), Partial Types에 대해 이야기했고 이러한 기능들이 C# 2.0(Generic C#)에서 구현됐다(닷넷 프레임워크 1.×에서도 제너릭은 이용할 수 있으며 이는 CLIX라는 이름으로 배포되고 있다). 잠시 C#의 디자인 목표에 대해 알아보자. C#의 대부분의 기능은 네 가지 디자인 목표를 기반으로 만들어졌다.

    ◆ 언어에서 값 및 참조 형식을 사용하는 방식을 간소화하며 통합된 형식의 시스템

    ◆ XML 주석, 특성, 속성, 이벤트 및 델리게이트와 같은 기능을 통해 구축된 구성 요소 기반의 디자인

    ◆ 안전한 포인터 조작, 오버플로 검사 등과 같은 C# 언어의 고유한 기능을 통해 구축

    ◆ 개발자의 생산성을 향상시키는 실용적인 언어 구문(예 : foreach, using 명령문) 사용

     

    그럼 이제 이 네 가지 요소에 대해 제너릭을 중심으로 알아보겠다.

    사용자 삽입 이미지
    <그림 3> 2004년 샌 디에고(San Diego)에서 있었던 테크애드 2004(TechEd 2004)에서 C#의 아버지인 Anders Hejlsberg를 만나다.


    재사용성 높인 제너릭
    애플리케이션의 복잡도가 심해질수록 개발자에게는 기존 객체 기반 코드를 최대한 다시 사용해야 할 방법이 중요해진다. C# 2.0에서는 제너릭이라는 기능을 사용한다. C#에는 형식이 안전한 제너릭이 포함되어 있다. 이 제너릭은 C++의 템플릿과 유사하지만 구문이 약간 다르며 구현 방식도 크게 다르다.

    C# 1.0에서의 클래스 작성
    C# 1.0에서는 개발자가 기본 개체 형식의 인스턴스에 데이터를 저장해 미약한 기능의 제너릭 형식을 만들 수 있다. C#의 모든 개체는 기본 개체 형식에서 상속되고 통합된 닷넷 형식 시스템의 박싱(boxing : 자동 변환) 및 언박싱(unboxing) 기능이 있으므로 프로그래머는 참조 및 값 형식 모두를 개체 형식의 변수에 저장할 수 있다.

    하지만 참조 형식, 값 형식 및 기본 개체 형식 사이를 변환하는 데 심각한 성능 저하가 발생하게 된다. 이러한 기능을 설명하기 위해 예를 하나 들어 보겠다. 다음 예는 마이크로소프트 연구소의 공식 Generics for C# 팀의 홈페이지인 Gyro(
    research.microsoft.com/projects/clrgen)에 있는 Andrew Kennedy와 Don Syme이 작성한 「Design and Implementation of Generics for the .NET Common Language Runtime」(research.microsoft.com/projects/clrgen/generics.pdf)의 예를 사용했다(<리스트 1, 2>).

     <리스트 1> 객체 기반의 스택 예
    사용자 삽입 이미지

    class Stack {
       private object[] store;
       private int size;
       public Stack()
          store=new object[10]; size=0;
       }
       public void Push(object x) {
          if (size>=store.Size) {
             object[] tmp = new object[size*2];
             Array.Copy(store,tmp,size);
             store = tmp;
          }
          store[size++] = x;
       }
       public object Pop() {
          return store[--size];
       }
       public static void Main() {
          Stack x = new Stack();
          x.Push(17);
          Console.WriteLine((int) x.Pop() == 17);
       }
    }
    사용자 삽입 이미지


     <리스트 2> 제너릭 스택 예
    사용자 삽입 이미지

    class Stack<T> {
       private T[] store;
       private int size;
       public Stack()
          store=new T[10]; size=0;
       }
       public void Push(T x) {
          if (size>=store.Size) {
             T[] tmp = new T[size*2];
             Array.Copy(store,tmp,size);
             store = tmp;
          }
          store[size++] = x;
       }
       public T Pop() {
          return store[--size];
       }
       public static void Main() {
          Stack<int> x = new Stack<int>();
          x.Push(17);
          Console.WriteLine(x.Pop() == 17);
       }
    }
    사용자 삽입 이미지

    앞의 코드에서는 Push 및 Pop의 두 가지 작업을 수행하는 간단한 스택 형식을 만든다. Stack 클래스는 개체 형식의 배열에 해당 데이터를 저장하고 Push 및 Pop 메쏘드는 기본 개체 형식을 사용하여 각각 데이터를 받고 반환하게 된다. 사용자 지정 형식을 스택에 푸시할 수 있다.

    하지만 프로그램에서 데이터를 검색해야 하는 경우 기본 개체 형식인 Pop 메쏘드의 결과를 명시적으로 캐스팅해야 한다. 정수 등과 같은 값 형식이 Push 메쏘드에 전달되면 런타임은 이 형식을 참조 형식으로 자동 변환(boxing)한 다음 내부 데이터 구조에 저장한다.

    정수 등과 같은 값 형식을 스택에서 검색하려면 Pop 메쏘드에서 얻은 객체 형식을 값 형식에 명시적으로 캐스팅(unboxing)해야 한다. 값 및 참조 형식 사이의 박싱 및 언박싱은 특히 부담되는 작업이 될 것이다.

    C#의 제너릭은 내부 알고리즘이 동일하게 유지되고 내부 데이터 형식이 최종 사용자 설정에 따라 다를 수 있도록 매개 변수 있는 형식을 통해 구현한다. 만약 C++의 템플릿 기능을 사용해 본 독자라면 C++와 거의 동일한 방식으로 C#의 제너릭이 선언되므로 쉽게 이해할 수 있을 것이다. 일반적으로 기존 클래스 및 구조와 똑같이 만들 수 있으며 꺾쇠 괄호 표기법(< 및 >)을 사용하여 형식 매개 변수를 지정할 수 있다. 그렇다면 실제 위의 두 코드가 IL 코드로는 어떻게 다른지 한번 살펴보겠다(<리스트 3, 4>).

     <리스트 3> 객체 기반의 스택 IL 코드
    사용자 삽입 이미지


    .class Stack {
       .field private class System.Object[] store
       .field private int32 size
       .method public void .ctor() {
          ldarg.0
          call void System.Object::.ctor()
          ldarg.0
          ldc.i4 10
          newarr System.Object
          stfld class System.Object[] Stack::store
          ldarg.0
          ldc.i4 0
          stfld int32 Stack::size
          ret
       }
       .method public void Push(class System.Object x) {
          .maxstack 4
          .locals (class System.Object[], int32)
          .
          .
          .
          ldarg.0
          ldfld class System.Object[] Stack::store
          ldarg.0
          dup
          ldfld int32 Stack::size
          dup
          stloc.1
          ldc.i4 1
          add
          stfld int32 Stack::size
          ldloc.1
          ldarg.1
          stelem.ref
          ret
       }
       .method public class System.Object Pop() {
          .maxstack 4
          ldarg.0
          ldfld class System.Object[] Stack::store
          ldarg.0
          dup
          ldfld int32 Stack::size
          ldc.i4 1
          sub 

          dup
          stfld int32 Stack::size
          ldelem.ref
          ret
       }
       .method public static void Main() {
          .entrypoint
          .maxstack 3
          .locals (class Stack)
          newobj void Stack::.ctor()
          stloc.0
          ldloc.0
          ldc.i4 17
          box System.Int32
          call instance void Stack::Push(class System.Object)
          ldloc.0
          call instance class System.Object Stack::Pop()
          unbox System.Int32
          ldind.i4
          ldc.i4 17
          ceq
          call void System.Console::WriteLine(bool)
          ret
       }
    }

    사용자 삽입 이미지


     <리스트 4> 제너릭 스택 IL 코드
    사용자 삽입 이미지

    .class Stack<T> {
       .field private !0[] store
       .field private int32 size
       .method public void .ctor() {
          ldarg.0
          call void System.Object::.ctor()
          ldarg.0
          ldc.i4 10
          newarr !0
          stfld !0[] Stack<!0>::store
          ldarg.0
          ldc.i4 0
          stfld int32 Stack<!0>::size
          ret
       }
       .method public void Push(!0 x) {
          .maxstack 4
          .locals (!0[], int32)
          .
          .
          .
          ldarg.0
          ldfld !0[] Stack<!0>::store
          ldarg.0
          dup
          ldfld int32 Stack<!0>::size
          dup
          stloc.1
          ldc.i4 1
          add
          stfld int32 Stack<!0>::size
          ldloc.1
          ldarg.1
          stelem.any !0
          ret
       }
       .method public !0 Pop() {
          .maxstack 4
          ldarg.0
          ldfld !0[] Stack<!0>::store
          ldarg.0
          dup
          ldfld int32 Stack<!0>::size
          ldc.i4 1
          sub
          dup
          stfld int32 Stack<!0>::size
          ldelem.any !0
          ret
       }
       .method public static void Main() {
          .entrypoint
          .maxstack 3
          .locals (class Stack<int32>)
          newobj void Stack<int32>::.ctor()
          stloc.0
          ldloc.0
          ldc.i4 17
          call instance void Stack<int32>::Push(!0)
          ldloc.0
          call instance !0 Stack<int32>::Pop()
          ldc.i4 17
          ceq
          call void System.Console::WriteLine(bool)
          ret
       }
    }
    사용자 삽입 이미지

    IL 코드 내에서 명시적으로 형식을 사용해 줌으로써 필요 없는 박싱과 언박싱을 줄여 주고 있는 것이 확연히 구분될 것이다. Generic 클래스가 컴파일되면 이 클래스는 일반 클래스와 실제로 차이가 없다. 결과는 메타 데이터 및 중간 언어(IL)일 뿐이다. 제너릭 형식의 IL은 제공된 형식 매개 변수가 값 형식 또는 참조 형식인지에 따라 다르다.

    이외에도 제너릭 형식은 다양한 매개 변수를 지원하며 애플리케이션에서 형식 매개 변수의 멤버를 사용하여 프로그램의 제너릭 형식 내에서 명령문을 실행하도록 제약 조건을 주는 것도 가능하다. 그럼 C#의 제너릭과 다른 언어의 차이를 한번 알아보겠다.

    C++ 템플릿은 C# 제너릭과는 표현 형식은 비슷하지만 실제는 현저히 다르다. C# 제너릭은 IL로 컴파일되므로 각각의 값 형식에 대해서는 런타임에, 참조 형식에 대해서는 한 번만 발생하게 된다. C++ 템플릿은 템플릿에 제공된 각 형식 매개 변수에 대한 특수화된 형식을 생성하는 코드 확장 매크로다. 따라서 C++ 컴파일러는 정수의 스택과 같은 템플릿을 발견하면 기본 형식으로서 정수를 내부적으로 포함하는 Stack 클래스로 템플릿 코드를 확장한다.

    형식 매개 변수가 값 또는 참조 형식에 관계없이 코드 양을 감소시킬 수 있도록 링커를 디자인하지 않으면 C++ 컴파일러는 매번 특수화된 클래스를 만든다. 따라서 C# 제너릭에 비해 코드 양이 상당히 증가한다. 그리고 C++ 템플릿에서는 제약 조건을 정의할 수 없다. 그렇지만 C++ 템플릿은 그 자유로움이나 다양함에서 고급 C++ 개발자들의 총애를 받고 있다. C# 제너릭은 위에서 이야기한 C#의 디자인 목표를 충실히 이행하면서 C++의 템플릿보다 통합되고 실용적인 모습으로 구현됐다.

    자바의 경우는 JDK 5.0에서 제너릭 기능을 추가하기로 했지만 성능 문제를 어떻게 극복할 것인지가 관건이 될 것 같다. 그리고 조금 늦은 감이 있지만 JDK 5.0에는 C#에서 볼 수 있는 박싱과 같은 기능이 추가로 들어가며, ADO.NET의 DataSet과 같은 비연결지향적인 DataSet 또한 추가한다고 한다.

    닷넷 2.0에서는 C# 이외도 VB.NET과 매니지드 C++에서도 제너릭 기능을 지원하고 있다. 그 외의 제너릭의 장점으로는 다음과 같은 요소들을 들 수 있다.

    ◆ 코드 작성, 테스트 및 배포를 한 번에 수행할 수 있으므로 다양한 데이터 형식에 해당 코드를 재사용할 수 있다.

    ◆ 제너릭은 컴파일시 검사된다. 프로그램이 제공된 형식 매개 변수로 generic 클래스를 인스턴스화하는 경우 형식 매개 변수는 프로그램에서 클래스 정의에 지정한 형식으로만 사용할 수 있다.

    ◆ 제너릭 구현은 다른 형식의 구현과 비교해 보면 코드 양을 감소시킨다. 제너릭으로 형식화된 컬렉션을 만들면 각 클래스의 특정 버전을 만들 필요가 없으며 성능을 그대로 유지할 수 있다.

    ◆ 코드를 더 쉽게 읽을 수 있다.


    이외에도 BCL(Base Class Library)에서의 Generic 컬렉션에 대해 알아보도록 하겠다. BCL에서는 다음과 같이 이미 구현된 클래스와 인터페이스를 제공하고 있다.

    ◆ System.Collections.Generic 클래스 : List<T>, Dictionary<K, V>, Stack<T>, Queue<T>

    ◆ System.Collections.Generic 인터페이스 : IList<T>, IDictionary<K, V>, ICollection<T>, IEnumerable<T>, IEnumerator<T>, IComparable<T>, IComparer<T>


    이터레이터
    이터레이터는 해당 요소에서 foreach 문이 반복되는 방식을 형식이 간단하게 선언할 수 있게 만들어 주는 것으로 이터레이터는 foreach 루프 구문의 논리적 구문으로 foreach 키워드 다음에 여는 괄호 및 닫는 괄호를 사용하여 함수와 유사하게 정의된다.

    이터레이터는 프로그램 대신에 열거자 패턴을 구현하여 번거로운 작업을 처리한다. 클래스를 만들고 상태 시스템을 작성하는 것이 아니라 C# 컴파일러는 열거자 패턴을 사용하여 이터레이터에 작성한 코드를 적절한 클래스 및 코드로 변환한다. 이렇게 함으로써 이터레이터는 개발자의 생산성을 상당히 높여준다.

    익명 메쏘드
    익명 메쏘드는 유용한 언어 구문으로 프로그래머는 델리게이트에 캡슐화하고 나중에 수행할 수 있는 코드 블록을 만들 수 있다. 이 메쏘드는 lambda라는 함수형 언어의 개념을 기반으로 하며 LISP 및 파이썬과 개념적으로 비슷하다.

    델리게이트는 메쏘드를 참조하는 객체로 C에서 이야기하는 함수 포인터다. 델리게이트가 실행될 때마다 이 델리게이트가 참조하는 메쏘드가 호출된다. 별도의 함수가 만들어지고 델리게이트에 의해 참조되고 델리게이트가 호출될 때마다 프로그램이 해당 함수를 호출한다. 함수 내에서 일련의 실행 단계가 수행된다.

    익명 메쏘드를 추가하면 프로그램은 클래스에 대해 완전히 새로운 메쏘드를 만들 수 있으며 델리게이트에서 그 안에 포함된 실행 단계를 직접 참조할 수 있다. 익명 메쏘드는 실행 영역을 나타내는 중괄호 쌍이 있는 인스턴스화 문과 명령문 다음에 델리게이트를 인스턴스화하여 선언한다.

    사용자 삽입 이미지
    데이터 중심적 분산 프로그래밍을 위한 언어 Cω
    사용자 삽입 이미지
     
    사용자 삽입 이미지
    사용자 삽입 이미지
    Cω(코메가, COmega,
    research.microsoft.com/Comega)는 실험실 언어이지만 현재 컴파일러를 구해 사용할 수 있다. Cω는 근래의 대표적 프로그래밍 분야인 데이터 중심적인 분산 프로그램을 위한 데이터 구조와 제어 구조를 제공하기 위해 설계됐으며, 동기적 혹은 비동기적 메쏘드를 지원하며, 언어에 데이터 지향적인 기능이 포함되어 있다. Cω가 C#이나 닷넷의 언어에 어떤 형태로 반영이 될지는 현재로서는 미지수이며, 앞으로 지켜봐야 할 것 같다.
    사용자 삽입 이미지
    사용자 삽입 이미지


    익명 메쏘드는 클래스에서 선언한 변수뿐만 아니라 클래스가 상주하는 메쏘드에 선언된 지역 변수 또는 매개 변수를 참조할 수 있다. 또한 익명 메쏘드 문은 sender 및 e라는 매개 변수 두 개를 포함한다. 윈도우 폼의 Button 컨트롤 클래스의 Click 델리게이트의 정의를 찾아보면 델리게이트가 참조하는 모든 함수는 첫 번째는 형식 객체, 두 번째는 EventArgs 형식인 매개 변수 두 개를 포함해야 한다는 것을 알 수 있다.

    익명 델리게이트가 발견되면 C# 컴파일러는 해당 실행 범위의 코드를 고유한 이름의 클래스 내에서 고유한 이름의 함수로 자동 변환한다. 코드 블록에 있는 델리게이트가 저장된 다음 참조(컴파일러가 생성한 개체 및 메쏘드)로 설정된다. 델리게이트가 호출되면 익명 메쏘드 블록은 컴파일러가 생성한 메쏘드를 통해 실행하게 된다.

    Partial Types
    Partial Types를 사용하면 대량의 소스 코드를 여러 개의 다른 소스 파일로 나눌 수 있다. 또한 시스템이 생성한 형식과 사용자가 작성한 형식을 분리할 수 있으므로 도구에서 생성한 코드를 간단하게 보충하거나 수정할 수 있다.

    다음에 나타날 새로운 기술은 어떤 것일까

    지금까지 간략하게나마 닷넷 2.0의 새로운 기능과 닷넷 2.0에서의 언어의 변화에 대해 살펴봤다. 언어나 개발 환경 또한 유기체와 같아서 지속적으로 변화하며 모방을 통해 새롭게 진화해 나간다는 것을 볼 수 있다. 결국 이러한 변화에 대응하지 못하게 되면 없어지지는 않지만 대중과 멀어지는 과거의 기술로 전락할 수밖에 없는 것이다. 지금 예측하기에는 무리겠지만 그럼 그 다음 변화는 어떻게 올 것인지 한 번 생각해 보는 것도 재미있을 것이다. @

    * 이 기사는 ZDNet Korea의 제휴매체인마이크로소프트웨어에 게재된 내용입니다.

     

    강성재 (한국MS)

    2005/01/24

     

    사용자 삽입 이미지

     

    원문 :http://www.zdnet.co.kr/techupdate/lecture/dotnet/0,39024986,39133022,00.htm

    신고
    0  Comments,   0  Trackbacks
    댓글 쓰기
    [메타 사이트 만들기] ① 닷넷으로 구현하는「블로거 집합소」

    [메타 사이트 만들기] ① 닷넷으로 구현하는「블로거 집합소」

     

    연재순서
    1회. 블로거들의 집합소「메타 사이트 구현」
    2회. RSS 수집 로봇 구현과 문제점 분석

     

    메타 사이트는 블로그에 새롭게 업데이트된 내용을 다른 블로거들에게 알려주고, 블로거에게 더 많은 블로깅을 할 수 있는 일종의 항해일지 역할을 하는 사이트입니다. 거대한 네트워크에서 블로그들을 순회하며 새롭게 업데이트된 내용들을 찾아내 알려주는 메타 사이트는 거대한 웹 검색 엔진의 축소판이라고 부르기에 알맞지요.

    이번 연재를 통해 이러한 블로그 정보를 수집하는 메타 사이트를 개발하는 과정에 대해 알아보도록 하겠습니다.

    ‘사람이 모이는 장소에는 장터가 생기고, 블로거들이 모이는 곳에는 메타 사이트가 생겨난다’는 정체불명의 명언(?)에서 볼 수 있듯, 메타 사이트는 블로거들에게 아주 중요한 커뮤니케이션 수단이 되고 있습니다. 메타 사이트는 블로그에서 지원하는 RSS 정보로부터 메타 정보를 읽어서 종합적인 블로그의 소식을 전해준다는 의미로 메타 사이트라 불립니다. 하지만 개인적으로는 그와 비슷한 의미를 가지고 있는 블로그 센터라는 좀 더 직관적인 단어를 좋아합니다.

    이러한 메타 사이트의 작동 방식은 마치 작은 크기로 줄여놓은 검색 엔진 사이트와도 비슷하게 생각할 수 있습니다. 이번 시간에는 메타 사이트에 대한 소개와 메타 사이트와 수집 로봇 구성, 그리고 수집 로봇에 대한 여러 가지 방법들에 대해서 이야기해 보고자 합니다.

    블로그의 정보를 수집하는 로봇
    메타 사이트에서 블로그의 최신 정보를 알아내기 위해서는 우선 블로그와 메타 사이트간에 데이터 교환을 위한 방식이 필요하게 됩니다. 검색 엔진에서 사용하는 검색 로봇의 경우 이미 웹이라는 매체가 오래된 HTML 방식으로 구성되어 있었기 때문에 그에 맞는 검색이 가능하도록 로봇을 설계했습니다.

    하지만 블로그의 경우 블로그의 내용을 손쉽게 읽을 수 있는 파일 규약을 지원하고 있으며 그러한 규약 중 대표적으로 사용되고 있는 것이 바로 RSS입니다. 덕분에 우리가 만들고자 하는 로봇은 단순히
    XML형식으로 되어 있는 이 RSS 파일을 자유롭게 읽고 해석할 수 있으면 손쉽게 해결할 수 있습니다.

    검색 로봇과 다른 점이라면 인터넷에 떠도는 많은 웹 페이지들 전체를 대상으로 하지 않는다는 점입니다. 인터넷에 있는 하나의 문서, 자료들도 각자의 저작권이 있는 저작물이며 이를 함부로 수집해서는 안 된다는 것입니다. 물론 이미 이용되고 있는 검색 엔진은 이를 간단히 검색 거부할 수 있는 기능을 지원한다는 명목 하에 대부분의 웹 사이트에서 정보를 수집하고 있지만, 최근 이러한 검색 엔진의 무분별한 자료 수집으로 인한 개인 정보 노출 등의 문제점을 보더라도 이러한 문제는 신중히 생각해야 한다고 생각합니다.

    메타 사이트에서는 이러한 이유로 사이트에서 가입되어 있는 블로그의 정보만을 수집하며 언제든 수집을 원하지 않는 게시물에 대해서 수집을 거부할 수 있는 권한을 가지고 있어야 합니다. 물론 수집되는 블로그의 범위를 지금의 검색 엔진처럼 거대한 인터넷 전체로 확대한다면 앞으로 웹 사이트보다 더 많은 컨텐츠를 보유하게 될 블로그의 검색 엔진으로써 활약할 수 있는 프로그램을 만들 수 있지 않을까 합니다.

    RSS 파일을 정복하자
    블로그의 정보 수집에 있어서 가장 중요한 내용 중 하나인 RSS에 대해 이야기해 보도록 합시다. 이 RSS는 알고 있는 것과 같이 블로그의 정보와 최근 등록된 글들의 정보가 포함되어 있는 XML 파일입니다.

     <리스트 1> RSS 파일의 구조
    사용자 삽입 이미지

    <?xml version="1.0" encoding="euc-kr" ?>
    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
        <channel>
            <title>하늘이의 생각나무</title>
            <link>http://www.in1983.com</link>
            <description>사랑하는 주영이와 알콩달콩 이야기</description>
            <item>
                <title>머리속 가비지 컬렉터 파워 온!!</title>
                <link>http://php.chol.com/~ppk314/tt/index.php?pl=386</link>
                <description> 글의 내용이 들어가나, 생략함 </description>
                <pubDate>Tue, 19 Oct 2004 23:54:00 GMT</pubDate>
            </item>
            ...
            <item>의 반복
    ...
        </channel>
    </rss>
    사용자 삽입 이미지

    이 RSS 파일은 rss라는 루트 엘리먼트로 시작됩니다. 그리고 채널이라는 하위 엘리먼트를 가지고 있는 이곳에 블로그의 대한 정보들(블로그의 이름, 주소, 설명, 기타 정보들)이 포함됩니다. 그리고 여러 개의 아이템 엘리먼트들을 포함하고 있는데, 이들이 바로 블로그의 글에 대한 정보를 담고 있습니다.

    메타 사이트에서 필요한 정보는 대부분 아이템 엘리먼트에 있으니 아이템 엘리먼트의 구조에 대해서 자세히 살펴보도록 하겠습니다.

    사용자 삽입 이미지
    <그림 1> RSS 파일의 구조 - item들의 구성


    <그림 1>을 보면 RSS 파일의 구조에 아이템들의 구성을 볼 수 있습니다. 아이템에 있는 각각의 엘리먼트들은 <표 1>과 같은 의미를 가지고 있습니다.

    사용자 삽입 이미지
    <표 1> RSS 파일의 엘리먼트들의 의미


    이러한 엘리먼트의 이름들은 RSS 버전에 따라서 약간의 차이들이 있으며 <표 1>에 표시한 몇 가지 종류의 엘리먼트 이외에도 많은 종류의 엘리먼트들이 존재하게 됩니다. 그리고 이미 여러 종류의 블로그 툴들이 개발되어 있고, 각자 조금씩 다른 엘리먼트를 조합하여 사용하고 있습니다.

     <리스트 2> 각각 다른 이름의 엘리먼트를 사용하는 item 엘리먼트들
    사용자 삽입 이미지

    <item>
        <title>머리속 가비지 컬렉터 파워 온!!</title>
        <link>http://php.chol.com/~ppk314/tt/index.php?pl=386</link>
        <description> 글의 내용이 들어가나, 생략함 </description>
        <pubDate>Tue, 19 Oct 2004 23:54:00 GMT</pubDate>
    </item>

    <item>
        <title>머리속 가비지 컬렉터 파워 온!!</title>
        <link>http://php.chol.com/~ppk314/tt/index.php?pl=386</link>
        <description> 글의 내용이 들어가나, 생략함 </description>
        <pubDate>2004-10-19 23:54:00</pubDate>
        <author>하늘이</author>
    </item>

    <item>
        <title>머리속 가비지 컬렉터 파워 온!!</title>
        <link>http://php.chol.com/~ppk314/tt/index.php?pl=386</link>
        <description> 글의 내용이 들어가나, 생략함 </description>
        <dc:date>2004-10-19T23:54:00+09:00</dc:date>
        <dc:creator>하늘이</dc:creator>
    </item>
    사용자 삽입 이미지

    각각의 블로그 툴마다 다른 엘리먼트 이름을 사용하고 있습니다. 하지만 메타 사이트의 RSS 수집 로봇이 그러한 RSS의 모든 태그의 정보가 필요한 것은 아닙니다. 메타 사이트에서 필요한 일부 정보들만을 사용하게 되므로 <표 1>에서 정리한 정도의 정보들만을 수집하면 됩니다.

    하지만 여기서 문제가 발생하게 되는데, 과연 각기 다른 엘리먼트들의 조합으로 되어 있는 RSS 파일들을 어떻게 처리하면 될까요? 각 블로그 툴의 종류별로 약간 다른 방식으로 RSS 파일을 읽어들이는 방법을 가장 첫 번째로 생각해볼 수 있을 것입니다.

    하지만 그럴 경우 잘 알려지지 못해서 RSS 구조의 정보를 잘 모르고 있던 블로그들의 경우에는 어떤 방식으로 처리할까요? 바로 이러한 문제들을 해결하기 위해서 가장 효과적인 방법으로 여러 가지 엘리먼트를 동시에 지원하는 방식을 사용하고자 합니다.

    예를 들어 pubDate와 의미가 비슷한 dc:date와 author는 dc:creator와 같은 엘리먼트로 간주하고 처리하는 방식입니다. 이러한 방법을 이용하여 모든 종류의 RSS 파일에서 필요한 내용들로 정리할 수 있습니다.

    이러한 RSS 파일의 처리를 위해서 RSS 아이템 한 개를 표현하는 아이템 클래스와 그러한 아이템들을 집합을 표현할 컬렉션 클래스, 그리고 XML 파일로부터 이들의 클래스를 생성하는 RSS 리더 클래스를 각각 구현하여 보도록 하겠습니다. RSS 아이템 클래스의 경우 <표 1>에 나와 있는 내용들을 기억하는 간단한 클래스이기 때문에 그다지 구현에 큰 어려움은 없습니다.


    Public Class RSSItem
    Public Title As String
    Public Link As String
    Public Author As String
    Public Description As String
    Public PubDate As Date
    End Class


    멤버 변수들 이름으로는 RSS 파일의 엘리먼트 이름과 동일하게 처리했습니다. 지면상 간단한 방식으로 줄였으나, 변수들은 프라이비트(Private)로 선언하고, 퍼블릭(Public)으로 선언된 프로퍼티들을 사용하여 처리하는 방식으로 구현하는 것이 좋습니다. 이 클래스는 날짜 처리 등을 위해서 다음 글에서 수정할 예정이니, 우선은 이대로 사용하기로 하겠습니다.

    RSS의 아이템 하나를 저장하는 클래스를 만들었으니, 그러한 다수의 아이템들을 편하게 접근할 수 있는 컬렉션 클래스를 만들어보도록 합시다. 닷넷 프레임워크에서는 간단하게 강력한 컬렉션을 구현할 수 있는 CollectionBase 추상 클래스를 지원하고 있습니다.


    MustInherit Public Class CollectionBase
    Implements IList, ICollection, IEnumerable


    우리가 만들었던 RSSItem 컬렉션 클래스는 바로 이 추상 클래스를 상속받아 만들게 됩니다. CollectionBase에 대한 자세한 설명은 닷넷 프레임워크 SDK 설명서를 참고하길 바랍니다. 이 추상 클래스를 상속받아서 간단하게 RSSItem들을 추상화하는 클래스를 만들어보도록 하겠습니다. 이 클래스에는 우리가 컬렉션 클래스에서 흔히 사용하는 멤버 변수들도 같이 구현하도록 하겠습니다.

     <리스트 3> RSSItemCollection 클래스
    사용자 삽입 이미지

    Public Class RssItemCollection
    Inherits CollectionBase

        Default Public Property Item(ByVal index As Integer) As RssItem
            Get
                Return CType(list(index), RssItem)
            End Get
            Set(ByVal Value As RssItem)
                list(index) = Value
            End Set
        End Property

        ' 삽입, 검색, 삭제 등의 메쏘드
        Public Function Add(ByVal itemObject As RssItem) As Integer
            Return list.Add(itemObject)
        End Function

        Public Function IndexOf(ByVal itemObject As RssItem) As Integer
            Return list.IndexOf(itemObject)
        End Function

        Public Sub Insert(ByVal index As Integer, ByVal itemObject As RssItem)
            list.Insert(index, itemObject)
        End Sub

        Public Sub Remove(ByVal itemObject As RssItem)
            list.Remove(itemObject)
        End Sub

        Public Function Contains(ByVal index As Integer, ByVal itemObject As RssItem) As Boolean
            Return list.Contains(itemObject)
        End Function
    End Class
    사용자 삽입 이미지

    이제 남은 것은 RSS 파일로부터 데이터를 읽어서 이들의 클래스를 반환해주는 RSS 리더 클래스를 만드는 것입니다. 이번 호에서는 네트워크의 XML 파일에도 편하게 접근할 수 있는 XmlTextReader 클래스를 이용하도록 하겠습니다. XML 파일 처리에는 다양한 방법들이 있으니 자신에게 편리한 방법을 선택하여 구현하면 됩니다.

     <리스트 4> RSSReader 클래스
    사용자 삽입 이미지

    Public Class RSSReader
        Private xmlUrl As String
        Private rssItems As RssItemCollection

        Public Sub New()
            rssItems = New RssItemCollection
        End Sub

        Public Sub New(ByVal xmlAddress As String)
            Me.New()
            xmlUrl = xmlAddress
        End Sub

        Public Property Items() As RssItemCollection
            Get
                Return rssItems
            End Get
            Set(ByVal Value As RssItemCollection)
                rssItems = Value
            End Set
        End Property

        Public Property XmlAddress() As String
            Get
                Return xmlUrl
    사용자 삽입 이미지


            End Get
            Set(ByVal Value As String)
                xmlUrl = Value
            End Set
        End Property

        Private Function findValue(ByVal rssXML As XmlTextReader) As String
            Try
                While (True)
                    rssXML.Read()
                    If (rssXML.NodeType = XmlNodeType.CDATA) Or (rssXML.NodeType =                 XmlNodeType.Text) Then
                    Return rssXML.Value
                    ElseIf (rssXML.NodeType = XmlNodeType.EndElement) Then
                        Return ""
                    End If
                End While
            Catch ex As Exception
                Return ""
            End Try
        End Function

        Public Sub readItems()
            rssItems.Clear()

            Dim isInItem As Boolean

            Dim rssXML As XmlTextReader
            Dim tempItem As RSSItem
            Try
                rssXML = New XmlTextReader(xmlUrl)
                While rssXML.Read()
                    Select Case rssXML.NodeType
                    Case XmlNodeType.Element
                        If rssXML.Name = "item" Then
                        tempItem = New RSSItem
                        isInItem = True
                    ElseIf isInItem Then
                        Select Case rssXML.Name.ToLower
                            Case "title"
                                tempItem.Title = findValue(rssXML)
                            Case "link"
                                tempItem.Link = findValue(rssXML)
                            Case "author", "dc:creator"
                                tempItem.Author = findValue(rssXML)
                            Case "pubdate", "dc:date"
                                tempItem.PubDate = findValue(rssXML)
                            Case "description"
                                tempItem.Description = findValue(rssXML)
                        End Select
                    End If

                Case XmlNodeType.EndElement
                        If rssXML.Name = "item" Then
                            isInItem = False
                            rssItems.Add(tempItem)
                         End If
                    End Select
                End While
                rssXML.Close()
            Catch ex As Exception
                rssItems.Clear()
            Finally
                rssXML = Nothing
            End Try
        End Sub

    End Class
    사용자 삽입 이미지

    <리스트 4>의 몇 개의 메쏘드를 간단하게 설명하자면, findValue는 XMLTextReader로부터 데이터만을 찾아서 반환해 줍니다. 데이터의 경우 텍스트 형식이나 CDATA 형식으로 지정하는데 이러한 형식 또한 RSS 파일마다 각기 다른 방법을 사용하고 있어서 편리하게 데이터를 읽을 수 있도록 구현했습니다.

    ReadItems 메쏘드가 우리가 하고자 했던 XML 파일로부터 데이터를 읽어들이는 이 클래스에서 가장 중심이 되는 작업을 수행하게 됩니다. 간단하게 XML 파일을 읽으며 엘리먼트의 시작 부분에서 아이템 엘리먼트가 시작되는 경우 새로운 RSSItem의 인스턴트를 생성해주고, 이후 아이템 엘리먼트의 각각의 엘리먼트들을 돌며 값을 읽어 저장하고, 아이템 엘리먼트가 끝나면 컬렉션 클래스에 넣어주게 됩니다. 이렇게 만들어진 클래스들은 다음과 같이 사용해볼 수 있습니다.


    Dim myRss As New RSSReader("http://php.chol.com/~ppk314/tt/index.xml")
    myRss.readItems()

    If myRss.Items.Count > 0 Then
    Console.WriteLine("첫번째 글의 제목 : " + myRss.Items(0).Title)
    End If


    네트워크에서 데이터베이스까지
    이렇게 해서 모든 종류의 RSS 파일을 읽을 수 있는 클래스가 준비됐습니다. 이제 남은 건 RSS 파일들을 읽고, 그것을 데이터베이스에 정리하는 작업입니다.

    간단히 네트워크와 데이터베이스에 대해서 생각하여 보겠습니다. RSS 수집 로봇은 분명 블로그들을 떠돌며 새로운 정보들을 데이터베이스에 저장하는 작업을 거치게 됩니다. 그렇다면 과연 어떤 방식으로 블로그의 RSS 파일이 업데이트되었다는 정보를 알 수 있을까요? 그리고 읽은 RSS 파일의 내용 중 어떻게 새로 추가된 내용을 찾아 그 부분만 데이터베이스에 저장할 수 있을까요?

    웹 검색 엔진의 핵심이 이렇게 수집하는 방법과 정리하여 저장하는 방식이 큰 핵심 중 하나라고 말한 것과 같이 이 부분에서 많은 생각과 아이디어들을 떠올려 볼 수 있습니다.

    우선 RSS 로봇이 업데이트된 정보를 어떻게 알 수 있는지는 HTTP 프로토콜 헤더에 If-Modified-Since 필드를 사용하여 요청하는 방법을 사용할 수 있습니다. 이 필드에 일정 시간 이후에 수정되어 있는지 여부에 따라서 수정되었다면 정상적으로 XML 파일을 반환할 것이며, 만약 수정되지 않은 상태라면 304 Not Modified 응답을 돌려주게 됩니다. 이 결과를 통해 첫 번째로 서버에서 RSS 파일이 수정되었는지를 확인하고 파일을 읽어온다면 네트워크의 트래픽 감소는 물론 좀 더 효율적인 처리를 할 수 있게 됩니다.

    그리고 이제 XML 파일을 읽고 데이터베이스에 저장하게 됩니다. 하지만 RSS 파일에는 새롭게 저장된 글의 내용만을 포함하는 것은 아닙니다. 최근 몇 개의 글을 포함하고 있기 때문에 이미 이전에 데이터베이스에 저장되어 있는 내용을 또다시 저장하는 문제가 발생할 수 있습니다.

    이 문제는 해당 글의 링크는 유일하다는 가정을 내려서 쉽게 해결할 수 있습니다. 즉 데이터베이스에 저장할 때의 글의 기준은 링크라는 것입니다. 데이터베이스에 같은 링크 값을 가진 글이 있다면 이미 저장되어 있으므로 넘어가고, 저장되어 있지 않은 글들만 저장하면 됩니다.

    이외에도 이전에 RSS 파일의 정보를 이미 데이터베이스에 저장했다고 가정하고 최근 1개의 정보만을 업데이트하는 방법도 있을 수 있습니다. 수시로 RSS 파일의 변경 여부를 체크하는데 이 시간 간격 내에 동시에 여러 개의 글을 올리지 않는다는 가정 하에 사용될 수 있는 방법입니다. 그밖에 성능을 고려한 여러 가지 방법들이 있을 수 있으며 그러한 방법들에 대한 생각은 이 글을 읽는 여러분들께 맡기도록 하겠습니다.

    사용자 삽입 이미지
    "블로그에서 스팸이?"
    사용자 삽입 이미지
     
    사용자 삽입 이미지

    한때 인터넷에 있는 게시판에 자동으로 광고 글을 등록해주는 스팸 프로그램이 떠돌면서 많은 게시판 관리자들과 게시판 프로그래머들을 골치 아프게 했지만, 이제는 블로그까지 이러한 스팸의 사악한 기운들이 손을 뻗고 있습니다. 이중에는 블로그의 트랙백 기능을 사용하여 광고 내용의 페이지를 많은 블로그 사이트에 대량으로 등록시켜 버리는 신종 광고도 등장했습니다.

    거기에 메타 사이트에 등장한 스팸으로는, 저도 지난번에 처음 경험한 광고 블로그 형태였습니다. 이 블로그는 겉으로 보면 일반 블로그처럼 보이지만 메타 사이트에 등록하고 사이트에 클릭할 때마다 적립금이 부여되는 배너들을 달고 있는 포스트를 집중적으로 올리게 됩니다. 이러한 정보들은 그대로 블로깅하는 블로거들에게 노출되며, 메타 사이트에는 광고 글, 도배 글 등으로 다른 글을 읽기 더욱 힘들어지게 합니다.

    모든 서비스를 어떻게 하면 광고의 기능으로 사용할 수 있을지를 연구하는 스팸 개발자와 어떻게 수많은 광고성 글들을 차단할 수 있을지를 연구하는 서비스 개발자와의 대립은 미래의 어떤 인터넷 환경이 온다고 해도 끊임없이 계속될 것 같습니다.
    사용자 삽입 이미지
    사용자 삽입 이미지


    다음 시간에는 RSS 수집 로봇 구현
    사실 메타 사이트를 만들기 위한 기본적인 설계는 이번 연재에서 대부분 마쳤다고 볼 수 있습니다. 다음 연재에서는 이번에 구현한 클래스들과 이야기한 방법들을 토대로 RSS 수집 로봇을 구현하고, 거기서 발생할 수 있는 여러 가지 문제들에 대해서 이야기하도록 하겠습니다.

    그리고 필자의 블로그에 들어오면 ‘창작’이라는 카테고리에 메타 사이트를 제작하면서 간단히 적어둔 몇 가지 관련 내용들이 있으니 관심 있는 독자들이라면 참고하고, 궁금증이나 더 나은 아이디어가 있다면 답글로 이야기해 주기 바랍니다. 이밖에 메타 사이트 개발에 관심 있는 사람이 있다면 이름이 거창한(?) ‘올블로그 개발 연구실(
    lab.allblog.net)’의 기술 연구실 게시판에서 메타 사이트에 대한 여러 가지 이야기를 함께 나눌 수 있었으면 좋겠습니다. @

    * 이 기사는 ZDNet Korea의 제휴매체인마이크로소프트웨어에 게재된 내용입니다

     

    박영욱 (Allblog.net 운영자)

    2005/03/04

     

    사용자 삽입 이미지

     

    원문 :http://www.zdnet.co.kr/techupdate/lecture/dotnet/0,39024986,39133977,00.htm

    신고
    0  Comments,   0  Trackbacks
    댓글 쓰기
    최신 기술 닷넷과「통성명 하는 법」
    최신 기술 닷넷과「통성명 하는 법」

     

    나날이 새로운 기술들이 쏟아지는 가운데 닷넷도 수년이 흘렀다. 벌써 많은 프로젝트들이 닷넷 기술을 적용해서 수행되었지만, 아직도 왠지 닷넷을 낯설게 보는 개발자들을 주변에서 쉽게 찾아볼 수 있다.

    필자는 이전 기술에 대한 이해를 바탕으로 과감히 새로운 기술을 받아들이되 충분히 자기의 것으로 소화시켜 실무에 적용하라고 조언하고 싶다. 또한 단순한 개발 기술에만 집중하지 말고 패턴과 아키텍처에 대한 이해에도 관심을 가지는 것이 중요하다고 생각한다.

    필자가 본격적으로 프로그래밍을 시작하게 된 것은 D조선 연구소에 근무하게 되면서부터이다. 당시 생산관리 부서에서 생산계획을 하는 시스템이 DOS 기반으로 되어 있어 GUI 지원이 부족하기 때문에 업무 수행에 어려움이 있으니 연구소에서 윈도우 기반으로 시스템을 개발해 달라는 요청이 있었다.

    당시만 해도 윈도우 환경에서 프로그램을 개발할 수 있는 사람이 일반 제조업체에는 많지 않았던 때였다. PC 성능은 그리 좋지 않은데 생산계획 업무에서 사용하는 데이터의 양은 많고 UI는 복잡한 터라, 개발은MFC를 사용하기로 하였다.

    1년간의 개발을 통해 시스템을 현업에 배포했다. 많은 개발 프로젝트들이 그렇듯이 프로젝트의 어려움은 그 때부터 시작이었다. 많은 요구사항 변경이 있었고 수많은 버그들과의 싸움이 있었다. 어렵사리 현업 적용에 성공을 하고, 2차, 3차 후속 프로젝트를 수행했지만 서서히 회의가 들기 시작했다.

    기업 내부에서 진행하는 프로젝트니 기간이 연장되고 현업 요구사항이 바뀌어도 그대로 수용하면서 갈 수 있었지만, 만약 외부에 프로젝트를 줘서 진행했다면 성공할 수 있었을까? 한사람의 개발자요 프로젝트 리더로서 충분한 생산성을 내고 있으며 경쟁력을 가지고 있나? 이런 의문과 장래에 대해 고민하면서, IT 업계로 이직을 하게 되었다.

    최신 기술에 과감히 도전하라
    이직한 업체는 CBD 등의 방법론과 아키텍처 컨설팅을 전문으로 하는 회사였다. 규모는 30여명 되었지만, 업계에서는 나름대로 인정받는 회사였다. 회사에서 수행하는 프로젝트는 주로 금융권 시스템에 대한 컨설팅이었고 기술 기반도 대부분 자바를 사용하는 것들이었다. 자바에 대해서는 언어 정도만 알고 있는 상태였기 때문에J2EE쪽을 집중적으로 스터디하고 있었는데 회사에서의 첫 번째 미션은 엉뚱하게도 닷넷을 사용해야 하는 일이었다.

    회사의 홈페이지와 인트라넷은 ASP.NET으로 개발되어 있었는데 인트라넷 기능에 일일업무 보고를 위한 기능을 추가하라는 것이 필자에게 내려진 첫 번째 임무였다. 주어진 시간은 일주일. 필자는 그때까지 MS 기술을 사용한 개발을 주로 하기는 했지만 MFC와 COM 기반의 윈도우 애플리케이션 개발이 주였기 때문에 닷넷을 사용하거나 웹 기반 애플리케이션 개발을 해본 경험이 없었다.

    그저 흥미삼아 책을 보면서 홈페이지 정도 만들어본 것이 전부인 데다 닷넷이라면 왠지 어렵고 복잡한 딴 세상의 물건인가보다 하고 살았기 때문에 당장 일주일 안에 닷넷으로 회사 사람들이 모두 사용할 기능을 만들라는 것은 상당히 부담스러운 일이었다.

    C#은 이전에 보아둔 적이 있는 터라 ASP.NET 기본서를 놓고 인트라넷 코드를 살펴보니 의외로 내가 너무 겁을 내고 있었다는 생각이 들었다. ASP.NET에서는 디자인과 코드를 분리해서 작업할 수 있게 되어 있기 때문에 디자이너가 만들어준 페이지와 별도로 필요한 기능을 하는 코드를 해당 클래스에 구현하고 간단히 연결만 해주면 되었다.

    선임자가 만들어둔 다른 기능들을 참고해서 진행을 하니 그리 어렵지 않게 필요한 기능을 주어진 기간 안에 완성할 수 있었다. 필자와 닷넷과의 인연은 이렇게 뜻하지 않게 시작되었다.

    하루가 멀다 하고 새로운 기술들이 쏟아져 나오고 있고 기존에 알고 있던 기술들도 계속해서 변화를 거듭하고 있다. 어떤 사람들은 이것들을 다 따라가는 것은 불가능하다며 새로운 기술을 습득하기를 포기하기도 하고, 혹은 자신이 가지고 있는 지식이 최고의 것이라 생각하여 새로운 것들을 무시하고 받아들이지 않는 경우도 있다.

    새로운 기술이 늘 좋은 것은 아니며 시간이 지남에 따라 오히려 옛 것을 선택하는 것이 바람직한 경우도 있겠지만, 그러한 기존의 기술과 새로운 기술에 대한 이해를 바탕으로 정확한 취사선택을 할 수 있는 상황에서 판단할 문제일 것이다.

    하지만 변화가 생명인 IT 업계에서 생존하기 위해서는 새로운 것에 대해 도전하고 이를 받아들이는 것을 두려워할 필요도 없으며 더더욱 게을리해서는 안된다. 엄청나게 많은 기술에 대해 한번에 이해하고 익히려고 하면 엄두가 나지 않을 것이다. 하지만 새로운 기술이라 해도 어느 날 아침에 하늘에서 뚝 떨어지는 것이 아니고, 기존 기술을 기반으로 진화해 나가는 것이기 때문에 하루하루 열린 마음으로 도전해간다면 많은 기술들을 진정 자신의 것으로 소화해낸 개발자가 될 수 있을 것이다.

    COM이 닷넷을 이해하는 데 도움이 된다
    MS의 빌게이츠를 립 서비스 전문가라고 혹평하는 이들이 있다. 물론 빌게이츠가 말한 것 중에 이루어지지 않은 것도 있고 출시 기한을 넘기는 것은 비일비재하기 때문에 그런 말을 들을 만하다는 생각이 들기도 하다. 하지만 필자는 빌게이츠가 비전을 제시하고 자신이 제시한 비전대로 업계를 이끌어나가는 사람이라고 생각한다.

    MS의 기술들은 현재 상황에서는 완전히 이루어지지 않았지만 미래에 대한 로드맵을 제시하고 한 단계씩 이루어나가는 방식으로 만들어진다. 로드맵 상에서 새로운 기술로 만들어내지 못한 부분들은 기존의 기술을 확장하거나 경우에 따라서는 말도 안 되게 이름만 바꾸어서 집어넣어 두기도 한다. MS의 닷넷 기술 역시 이제 막 걸음마를 떼고 성숙하려고 하는 단계라고 생각하고, 많은 부분들이 기존 기술을 활용하고 있다(물론 로드맵에 따르면 언젠가는 새로운 기술로 대체될 것이지만).

    이직한 회사에서의 첫 번째 프로젝트는 K통신사에서 COM/DCOM기반으로 ARS 시스템을 구축하는 프로젝트에서 기술 컨설팅을 하는 것이었다. 기존 ARS 시스템들은 장비에서 제공하는API와 라이브러리를 사용하고 소켓을 사용하여 통신하는 방식으로 돼 있었다.

    기존 라이브러리들을 COM 래퍼(Wrapper)를 만들어 컴포넌트화하고COM+로 컴포넌트 서비스를 제공하며 시스템간 통신은 DCOM 통신을 하도록 하는 것이 주된 내용이었다. 이 프로젝트를 수행하기 위해서ATL을 사용해서 COM+ 컴포넌트를 만들기 위한 기술들을 다시 점검하고 프로토타입을 만들었다. 프로젝트가 끝나고 닷넷의 COM+ 컴포넌트 서비스를 들여다보니 기본적인 사항들은 완전히 동일하다는 것을 알게 되었다.

    현재 버전의 닷넷 프레임워크는 CLR에 완전히 통합된 미드티어 서비스를 제공하지 못하고 있다. 닷넷의 미드티어 서비스는 <그림 1>에서 닷넷의 미드티어 서비스에 나타낸 것 같이 언매니지드 코드를 사용하는 COM+,IIS, 그리고MSMQ를 기반으로 제공된다. COM+는 닷넷에서는 엔터프라이즈 서비스(Enterprise Service)로 이름을 바꾸었지만 실제 동작은 COM+ 서비스를 사용하기 때문에 닷넷의 컴포넌트 서비스인 엔터프라이즈 서비스를 이해하기 위해서는 COM과 COM+에 대한 이해가 필수적이라고 할 수 있다.

    사용자 삽입 이미지
    <그림 1> 닷넷의 미드티어 서비스


    COM에서 컴포넌트나 인터페이스를 식별하기 위해서는 CLSID와 IID 등의 GUID를 사용한다. 그러나 닷넷에서는 GUID를 사용해서 컴포넌트나 인터페이스를 식별하지는 않기 때문에 닷넷에서 컴포넌트를 만들 때는 COM에서처럼 GUID를 생성하고 관리할 필요가 없다.

    이에 따라 원칙적으로는 닷넷의 엔터프라이즈 서비스를 사용하여 서비스드 컴포넌트(Serviced Component)를 만들 때 COM에서처럼 GUID를 신경 쓸 필요가 없다. 하지만 COM+가 COM 기반의 컴포넌트 서비스이기 때문에 실제 COM+에서 동작하는 컴포넌트가 되기 위해서는 GUID를 부여해야 할 필요가 있다.

    닷넷 엔터프라이즈 서비스에서는 사용자가 이를 지정하지 않아도 COM+에서 동작할 수 있도록 자동으로 컴포넌트에 GUID를 부여해준다. 그런데 이 경우 GUID가 매번 변경됨에 따라 클라이언트에 배포된 프록시를 재배포해 줘야 하는 문제가 발생할 수 있다. 따라서 이러한 배치 문제를 제거하려면 모든 COM+ 컴포넌트에 GUID를 지정해야만 한다. COM에 대한 이해가 전혀 없는 상태라면 이와 같은 상황을 이해하고 대처하는 데 어려움이 있을 수 있다. 이와 같은 상황은 미들티어 서비스들이 완전히 닷넷 프레임워크에 포함될 때까지는 유지될 것 같다.

    개발자 커뮤니티를 적극 활용하라
    닷넷으로 분산 애플리케이션을 개발하는 경우 분산 객체간의 통신을 위한 방법은 전통적인 DCOM 통신을 이용할 수도 있고, 닷넷 리모팅(.Net Remoting), 그리고 XML 웹 서비스를 사용할 수도 있다.

    DCOM 통신은 닷넷 이전의 COM 기반의 분산 아키텍처에서부터 사용되던 방법으로 언매니지드 코드로 작성된 객체들과 통신할 수 있다는 장점이 있는 반면 바이너리 프로토콜이기 때문에 방화벽이 있는 환경에서는 방화벽의 보안 정책과 맞물려 문제를 야기하는 경우가 종종 있다.

    이에 반해XML웹 서비스는 HTTP 기반의SOAP프로토콜을 사용함으로써 방화벽에 별도의 포트를 개방하지 않고도 원하는 서비스를 제공할 수 있으며, 서비스를 사용하는 클라이언트가 다른 플랫폼이어도 무관하다는 장점을 가지고 있다. 닷넷 리모팅은 닷넷 애플리케이션간 통신을 위해 만들어진 기술로서 일반적으로 XML 웹 서비스보다 좋은 퍼포먼스와 기능을 제공해준다.

    필자가 얼마 전에 수행한 프로젝트는 국내 D조선소의 생산 계획 시스템을 닷넷 기반으로 개발하는 것이었다. 아키텍처를 수립하면서 클라이언트 티어는 윈폼(WinForm)을 사용하고 비즈니스 티어에는 엔터프라이즈 서비스를 사용하되 티어간 통신에는 닷넷 리모팅을 사용하기로 했다. 티어간 데이터 전달 객체(Data Transfer Object)는 Strongly Typed DataSet을 사용하는 것으로 했다.

    원칙에 충실하게 초기 아키텍처를 수립하고 프로토타입 시스템을 개발하여 아키텍처를 검증하는데 문제가 발생했다. 원격 객체에 대해서 Strongly Typed DataSet을 반환하는 메쏘드를 호출할 때는 문제가 없었는데, 반대로 Strongly Typed DataSet을 파라미터로 넘기는 메쏘드를 호출할 때는 보안 관련 예외사항(Exception)이 발생하는 것이었다.

    틀림없이 뭔가 코딩을 잘못했을 것이라 생각하고 닷넷 리모팅 관련 서적을 다시 다 뒤져보았지만 원칙을 벗어나게 코딩한 부분은 전혀 없었다. 아키텍처 단계를 마무리해야 하는 시점은 다가오는데 원격 호출이 제대로 되지 않아서야 나머지 테스트를 진행할 수도 없는 상황이라 마음은 너무 조급했다.

    일주일을 고민했는데 의외로 해법은 아주 쉽게 발견됐다. 구글의 뉴스그룹(groups.google.com/groups?hl=en&lr=&group=microsoft.public.dotnet)을 조회해보니 이미 많은 사람들이 이 문제를 고민하고 해법까지도 친절히 나와 있는 것이었다.

    문제는 닷넷 프레임워크가 1.1로 업그레이드되면서 보안을 강화하였고 이 때문에 이와 같은 상황에서 보안 오류가 발생하는 것이었다. 해법은 다음과 같이 서버측과 클라이언트측 각각에 대해 "typeFilterLevel"을 설정해주면 되는 것이었다.


    ◆ 서버 측 리모팅 설정
    <serverProviders>
    <provider ref="wsdl" />
    <formatter ref="soap" typeFilterLevel="Full" />
    <formatter ref="binary" typeFilterLevel="Full" />
    </serverProviders>

    ◆ 클라이언트 측 리모팅 설정
    <configuration>
    <system.runtime.remoting>
    <serverProviders>
    <formatter ref="binary" typeFilterLevel="Full" />
    </serverProviders>


    문제를 해결하기 위해 혼자 고민하면서 일주일을 보내는 동안 잠을 자려고 누워도 온통 이 문제에 대한 생각뿐이었고, 관련 레퍼런스를 뒤져보면서 문제와 상관없는 부분까지 많이 배울 수 있었던 것은 좋았으나 필자와 동일한 문제를 고민한 사람들의 결과를 먼저 찾아보았더라면 바쁜 프로젝트 일정을 많이 아낄 수 있었으리라는 아쉬움이 남았었다.

    이 문제를 해결한 이후로는 기술적인 문제가 발생하면 우선 관련 뉴스 그룹을 검색해서 나와 유사한 문제가 있었는지를 확인하고 있다. 필자가 자주 사용하는 개발자 커뮤니티는 <화면 1>과 같다.

    <화면 1> 필자가 자주가는 커뮤니티

    사용자 삽입 이미지
    뉴스그룹(microsoft.public.dotnet)


     

    사용자 삽입 이미지
    GotDotNet(www.gotdotnet.com)


     

    사용자 삽입 이미지
    데브피아(www.devpia.com)


     

    사용자 삽입 이미지
    TheServerSide.Net(www.theserverside.net)


    최근 개발자 커뮤니티를 통해 얻을 수 있는 것은 개발 중에 부딪힐 수 있는 단편적인 문제에 대한 해결 방법뿐 아니라, 많은 경험들의 집약체라 할 수 있는 패턴과 엔터프라이즈 프로젝트에서 자주 사용되는 닷넷 코드들을 클래스 라이브러리 형태로 만들어서 제공하는 애플리케이션 블럭(Application Block), 그리고 견고한 시스템을 만들기 위한 아키텍처에 관한 기사들에 이르기까지 많은 선임자들의 고민과 경험을 얻을 수 있다.

    MS에서는 ‘Patterns & Practices’ 사이트(www.microsoft.com/resources/practices/default.mspx)를 통해 닷넷에서 사용할 수 있는 패턴과 애플리케이션 블럭, 그리고 아키텍처에 관한 좋은 기사와 서적, 그리고 클래스 라이브러리를 배포하고 있다. 약간의 관심과 노력을 기울인다면 시중에서 구할 수 있는 어떤 책보다도 양질의 정보를 담고 있는 정보를 얻을 수 있다.

    사용자 삽입 이미지
    <화면 2> Patterns & Practices 사이트


    엔터프라이즈 애플리케이션들은 갈수록 복잡한 업무 프로세스를 반영하고 있고, 이를 구현하기 위해서 여러 기술을 복합적으로 사용하고 있다. 복잡한 시스템을 구축할 때 한 분야에만 시야를 고정시키고 구현 기술에만 포커스를 두게 되면 프로젝트 전체를 망치게 될 수 있다.

    최근의 프로젝트에서는 체계적인 방법론과 아키텍처 수립을 기본으로 요구하는 경우도 많아지고 있고, 따라서 개발자들도 이에 대한 이해가 부족한 경우 고급 인력으로 인정받지 못하게 된다. 다행히도 우리 주변에는 우리가 노력하기에 따라서 이에 대한 이해를 하기에 충분한 정보가 제공되고 있다. 아직 이에 대해서 관심을 갖지 못했던 개발자라면 오늘이라도 관련 사이트를 돌아보며 마음가짐을 새로 하는 것도 좋을 것이다.

    닷넷으로 개발하면 퍼포먼스가 나쁘다?
    D조선 프로젝트가 진행되면서 개발이 마무리되어갈 무렵 현업 담당자들로부터 UI 퍼포먼스에 대한 이슈가 제기되었다. 이전에 사용하던 시스템에 비해 반응 속도가 너무 느리다는 것이었다.

    이전 시스템은 C++로 작성되었고 GDI를 직접 사용하는 것이었기 때문에 당연히 퍼포먼스가 좋은 데다 데이터베이스만 원격에 있고 나머지는 모두 클라이언트에서 구현된 팻 클라이언트(Fat Client)이기 때문에 퍼포먼스가 동일하기를 바라면 안 된다고 반은 구슬리고 반은 협박을 하였다.

    그리고 개발자들 노트북에서는 그럭저럭 쓸만해 보이는데 현업이 이전 시스템에 너무 익숙해져서 불만을 표시한다고 생각하고 넘어가려 했는데 현업의 불만이 쉽게 수그러들지 않는 것이었다. 예전 같으면 2시간이면 처리할 일을 시스템이 느려서 이틀은 걸리게 생겼다고 아주 난리가 났다.

    도대체 왜 그런가 하고 내려가 보았더니, 아뿔사! 현업 담당자의 PC가 펜티엄3 800㎒였던 것이었다. 프로젝트 초기에 계획한 하드웨어 사양에 한참 미치지 못하는 사양이라 많은 데이터를 올리는 경우 클라이언트단에 무리가 갔던 모양이었다. 사용자 환경을 면밀히 확인하지 못했던 것이 화근이었다. 부랴부랴 하드웨어 업그레이드를 요청하고 프로젝트팀에서도 UI 퍼포먼스 향상을 위한 조처를 강구하기로 하였다.

    시간 여유를 들여 UI 프레임워크를 들여다보니 닷넷의 코드가 네이티브 코드보다야 당연히 느리기는 하겠지만 그래도 너무 느리다는 생각이 들었다. 메쏘드별로 수행 시간을 측정해보니 가장 많이 호출되는 메쏘드에서 검색을 하는 부분이 시간을 많이 소요하게 되어 있는 것을 발견하게 되었다.

    이 부분에 Hashtable 클래스를 사용하여 검색하는 것으로 변경했더니 UI 반응 속도가 놀라울 만큼 빨라졌다. 자료구조를 적절하게 사용하는 것은 어찌 보면 아주 기본적인 것이지만 늘 기본을 지키지 않는데서 문제가 발생하는 법이다. 또한, 닷넷으로 개발하면 이전에 비해서 당연히 퍼포먼스가 떨어진다는 안이한 생각에 퍼포먼스에 대한 고려를 충분히 하지 못했던 것도 잘못된 점이었다.

    프로젝트를 진행하다 보면 이와 유사한 경험을 종종 하게 된다. 또한, 이러한 문제는 대부분 프로젝트 후반에 일어나는 것이 일반적이다. 그런 경우에 흔히 사용하는 변명이 “운영 시스템에 문제가 있다”라거나 “이 기술은 아직 문제가 많은 기술이야”라는 것이다.

    그러나 필자의 경우와 같이 문제는 운영 시스템이나 사용한 기술에 있는 것이 아니고, 설계와 개발시 기능 외적인 요소들에 대해 세심하게 고려하지 못하고 부분적인 기능만 만족시킨 채 자기 할 일을 다 했는데 나머지가 문제라고 생각하는 경우가 많다는 것이다. 프로젝트 중에 문제가 발생할 경우 자신이 담당한 부분이 단순한 기능 이외의 요소들을 충분히 반영했는지, 개념에 충실하게 코드를 작성했는지, 좀 더 넓은 시각으로 살펴보는 습관을 가지도록 하자.

    변화를 따라가 보는 즐거움
    최근 들어 닷넷으로도 많은 프로젝트들이 만들어지고 있어 닷넷 기술도 시장에서 어느 정도 받아들여지고 있는 것 같다. 많은 기술들이 그렇듯이 닷넷도 어느 날 하늘에서 뚝 떨어진 것이 아니고 기존의 기술을 기반으로 주변 기술들의 장점을 수용하면서 만들어지고 발전해가는 과정에 있다.

    따라서 기존 기술들에 대한 이해가 새로운 기술의 깊은 면을 이해하는데 많은 도움이 된다고 생각한다. 이제 처음 개발자로 시작을 하는 입장에서 기존의 기술까지 이해하면서 새 기술까지 익히는 것은 어려운 일이겠지만 기존 기술을 이해하고 있는 개발자라면 새로운 기술을 받아들일 때 기존 기술과 비교해가면서 기술의 진화 과정을 살펴보면 좀 더 깊은 이해를 할 수 있으리라 생각한다.

    닷넷 프레임워크 2.0 베타가 발표되고 또 많은 기술들이 적용되었다. 변화의 과정에서 어떤 점들이 달라지고 기술이 진화해가는지 따라가 보는 일도 즐거운 일일 것 같다. @

    * 이 기사는 ZDNet Korea의 자매지인마이크로소프트웨어에 게재된 내용입니다.

     

    조성원

    2005/02/07

     

    사용자 삽입 이미지

     

    원문 :http://www.zdnet.co.kr/techupdate/lecture/dotnet/0,39024986,39132995,00.htm

    신고
    0  Comments,   0  Trackbacks
    댓글 쓰기
    개발 환경의 새로운 변화「비주얼 스튜디오 2005 맛보기」

    닷넷개발 환경의 새로운 변화「비주얼 스튜디오 2005 맛보기」

     

    연재순서
    1회.닷넷 개발의 새로운 변화, 비주얼 스튜디오 2005 맛보기
    2회.닷넷 프레임워크 2.0과 개발 언어의 변화
    3회. 웹 애플리케이션 개발의 진화, ASP.NET 2.0

     

    비주얼 스튜디오 2005는 새로운 기능으로 무장하여 닷넷 개발자들의 최대 관심 대상으로 부각되고 있다. 특히 ‘비주얼 스튜디오 2005’ 제품군의 최상위 제품인 ‘비주얼 스튜디오 2005 팀 시스템’은 설계, 개발, 배포 주기 등을 지원하며 명실상부한 IT 라이프사이클 개발 도구임을 내세우고 있다.

    응용 시스템 모델링부터 코드 구현 및 테스트 관리까지 비주얼 스튜디오 2005에서 지원되는 모든 기능을 한 눈에 확인해 볼 수 있는 엔터프라이즈급 응용 시스템 구현을 위한 ‘비주얼 스튜디오 2005 팀 시스템’을 눈여겨 보자.

    XML 웹 서비스, 데스크탑, 모바일 및 웹 기반 응용 프로그램 등 모든 종류의 응용 프로그램 개발, 구축 및 실행을 가능케 해주는 MS의 새로운 프로그래밍 모델인 닷넷 프레임워크를 처음 소개했던 비주얼 스튜디오 닷넷은 기존의 InterDev를 알고 있던 개발자들에게는 가히 충격이 아닐 수 없었다.

    그리고 비주얼 스튜디오 닷넷 2003 이후 닷넷 개발자들의 최대 관심의 대상으로 부각되고 있는 ‘비주얼 스튜디오 2005(코드명 ‘위드비(Whidbey)’)는 코드 커버리지, 전문적인 소스코드 제어, 64비트 컴파일러, 배포 도구, 테스트 케이스 관리 및 프로젝트 관리 기능 등으로 무장하여 또 한번의 충격을 예고하고 있다.

    과거 InterDev와 비주얼 스튜디오 닷넷 2003은 응용 시스템 자체를 구현하는 소프트웨어 개발 부분에 보다 초점을 맞춘 개발 환경을 제공했다. 이에 비해 비주얼 스튜디오 2005는 아직 닷넷을 접해보지 못한 초보 닷넷 개발자는 물론 취미 삼아 소프트웨어를 개발하는 사람들을 위한 제품, 응용 시스템 자체를 구현하기 위한 소프트웨어 개발 환경만을 지원하는 제품, 엔터프라이즈급 응용 시스템 구현을 위한 제품까지 다양한 환경의 개발자를 위한 폭 넓은 제품 구성을 제시하고 있다.

    IT 라이프사이클 도구, 비주얼 스튜디오 2005
    비즈니스 환경이 복잡하고 빠르게 변화하는 오늘날의 기업들은 보다 다양한 응용 시스템을 보유하게 되었고, 신규로 구축되는 응용 시스템들은 기존 시스템과의 연계, 통합 등 더욱 향상된 서비스를 기대하는 사용자의 요구를 고려해야만 한다. 이러한 응용 시스템의 개발 프로젝트는 종종 복잡하고, 대규모로 진행됨에 따라 많은 인력들이 개발팀에 합류하게 되고 이들 구성원간의 정보 공유와 향상된 품질 및 비용 감소를 추구하는 시스템 설계는 성공적인 응용 시스템 구축을 위한 기본 요건이 되었다.

    이러한 시대적 변화에 대응하며 개발자들이 필요로 하는 보다 효율적인 응용 시스템 개발을 위한 ‘비주얼 스튜디오 2005’ 제품군의 최상위 제품인 ‘비주얼 스튜디오 2005 팀 시스템(이하 팀 시스템)’은 응용 프로그램의 복잡성 증대를 해결하고, 빠르게 변화하는 개발 환경 및 기술에 대처할 수 있는 능력을 제공한다.

    팀 시스템은 IT 라이프사이클 도구로 설계(디자인), 개발, 배포 주기 등을 지원해 생산성 향상 및 개발팀원간의 협업 환경을 제공하며, MS의 DSI(Dynamic Systems Initiative) 전략의 중요한 부분을 제공한다.

    비주얼 스튜디오 2005 Team System
    팀 시스템은 윈도우 서버 시스템 환경에서 조직이 핵심 솔루션 제공의 예측 가능성과 안정성을 향상시킬 수 있도록 검증된 프로세스 지침, 규범적 아키텍처 지침 및 솔루션 액셀러레이터를 포함한다. 팀 시스템은 전체 소프트웨어 개발팀을 지원하는 다음과 같은 도구를 제공한다.


    ◆ 비주얼 스튜디오 2005 Team Architect 에디션 : 설계자는 비주얼 디자이너를 사용하여 운영 환경에 대해 초기부터 디자인하고 유효성을 검사할 수 있으며, 서비스 지향 솔루션을 디자인하기 위한 통합된 효율적 도구들을 제공한다.

    ◆ 비주얼 스튜디오 2005 Team Developer 에디션 : 향상된 정적 분석, 코드 프로파일, 코드 검사 그리고 유닛 테스트 도구 등 고급 개발 도구를 사용하여 라이프사이클 전체에서 신속하고 주기적으로 품질을 통합 관리할 수 있다.

    ◆ 비주얼 스튜디오 2005 Team Test 에디션 : 고급 로드 테스트 도구 및 다양한 분야의 테스트들을 관리하고 실행하기 위해 필요한 도구들을 제공하며 응용 프로그램의 배포 전에 다양한 성능 확인을 수행할 수 있다.

    ◆ 비주얼 스튜디오 2005 Team Foundation : 프로젝트 매니저는 익숙하게 잘 사용하고 있는 엑셀, Microsoft Project, 윈도우 셰어포인트 서비스와 같은 도구를 기반으로 일련의 프로젝트 관리 업무를 효율적으로 수행할 수 있다. 프로젝트 포탈 사이트는 프로젝트 상태를 일목요연하게 보여주고 각 팀별로도 볼 수 있도록 하며, 팀에서 작업하는 동안 모아진 측정 값들을 다양한 리포트로 보여준다.

    더불어 업계에서 증명된 방법에 기초한 재정의 가능한 프로젝트 프로세스를 이용하여 라이프사이클을 운영할 수 있다. 또한 개발팀의 협업을 위해 서버 기반의 팀 공동 작업 도구를 제공하며, 이를 통해 프로젝트의 진행과 상태를 간단하게 관리 및 추적할 수 있다. 포트폴리오 탐색기는 프로젝트 포탈 사이트에 있는 것과 같은 프로젝트 작업을 비주얼 스튜디오
    IDE에 통합하여 팀이 쉽게 접근할 수 있도록 했으며, 확장 가능한 작업 목록 추적 시스템과 엔터프라이즈 급을 위한 소스코드 제어를 제공한다.


    사용자 삽입 이미지

    <그림 1> 비주얼 스튜디오 2005 팀 시스템 제품 구성


    궁극적으로 팀 시스템을 통해 설계자나 개발자는 ‘운영을 위한 디자인(design for operations)’을 수행할 수 있고, 개발 환경에서 동일한 기반 구조에 대한 정보를 사용할 수 있다. 이를 통해 실제 배포할 때 발생할 수 있는 문제점들을 초기 디자인 단계부터 실질적으로 파악할 수 있다. 또한 서비스 지향 솔루션을 제공할 때 발생하는 복잡성을 감소할 수 있다.

    비즈니스 사용자, 프로젝트 관리자, 작업 관리자, 설계자, 개발자 및 테스터를 비롯한 모든 소프트웨어 개발팀원은 구성원간의 공동 작업을 촉진할 수 있다. 이것이 팀 시스템을 통해 얻을 수 있는 이점이며 팀 시스템이 추구하는 목표이기도 하다. 이제 각각에 대해 좀 더 자세한 내용을 살펴보자.

    Team Architect
    일반적으로 모델링 도구를 사용하여 소프트웨어 시스템을 설명하려 할 때마다 막대한 시간과 비용 투자 문제에 직면하게 된다. 그리고 대개 결과로 만들어지는 다이어그램은 처음에는 매우 훌륭하게 보이지만 개발이 한창 진행됨에 따라 코드와의 비동기화로 무용지물이 되거나 번거로운 추가 작업을 필요로 하게 된다.

    일부 다이어그램과 코드간의 동기화를 제공하는 도구가 이용되기도 하지만 이러한 도구를 익히기 위해 드는 비용과 시간 때문에, 다이어그램을 제작하는 일이 주 업무가 아닌 경우를 제외하면 대개의 많은 사용자들이 모델링 도구 사용법을 익히는 것을 미루고 있다. 이 외에도 시스템 디자인과 이것이 배포되는 환경 특성 사이의 불일치 문제가 있다.

    언제나 그러하듯 솔루션이 다이어그램에서 훌륭하게 표현되고 코드화된 다음 배포 시점이 다가올 때쯤이면, 모델이 운영 환경에 정확하게 맵핑되지 않아 발생하는 문제들을 해결하기 위한 작업들이 새로 추가되곤 한다. 또한 설계자, 디자이너, 개발자 및 IT 인프라 운영 부서 직원의 견해 차이로 인해 충돌이 발생할 수도 있다.

    이러한 경우 대개 충돌에 대한 제약 조건은 시작 단계에서 조정되는 것이 바람직하며, 실제 서버 보안과 같은 제약 조건은 새로운 시스템을 성공적으로 배포?구현하는 데 장애가 되기도 한다. 중앙의 메인프레임 전용 시스템에서 클라이언트/서버 모델 및 분산 시스템으로 발전해 현재의 IT 환경을 더욱 복잡하게 만든 것도 이러한 문제를 증폭시키고 있다.

    다양한 플랫폼과 네트워크 환경에서 사용자의 높은 요구 수준을 충족시키기 위해 응용 프로그램들은 서로 상호작용하며 효율적으로 운영되기 위해 하나의 완전한 서비스로서 존재하는 동시에 메시지 교환을 통하여 서로 연결될 수 있어야 한다. 이러한 서비스 지향 애플리케이션을 만들기 위해 오늘날 매우 널리 사용되고 있는 환경은 서비스 지향 아키텍처(SOA)이며, 이 SOA는 서비스 제공, 메시지 사용 통신 및 종종 신뢰할 수 있는 경계선을 넘나드는 느슨한 결합으로 구성된 자체 응용 프로그램으로 구축된다.

    팀 아키텍트는 기술이 발전함에 따라 사용자가 손쉽게 SOA 기반의 시스템을 구축하고 관리하며 기본 플랫폼의 능력을 확장할 수 있는 다양한 기술 및 새로운 그래픽 디자인 도구를 제공한다.

    새로운 그래픽 디자인 도구 제공
    새로운 디자인 도구는 클래스 디자이너(Class Designer)와 분산 시스템 디자이너(Distributed System Designers)로, 분산 시스템 디자이너는 긴밀하게 통합된 네 개의 도구 그룹으로 구성된다. 이들 네 개의 도구는 응용프로그램 연결 디자이너(Application Connection Designer), 논리적 데이터센터 디자이너(Logical Datacenter Designer), 시스템 디자이너(System Designer), 배포 디자이너(Deployment Designers)이다.

    네 개의 도구 중 응용 프로그램 디자이너와 클래스 디자이너는 시스템 및 구성 요소의 그래픽 디자인 지원과 코드 생성 지원 등 주요 특성을 공유한다. 이러한 디자이너들은 양방향 동기화를 지원하므로, 다이어그램이 시스템 및 구성 요소를 나타내지 않는다고 해도 염려할 필요가 없으며, 기존 모델링 시스템의 전형적인 문서 중심의 보기를 능가하는 점에서 모델링 분야에서의 르네상스 시대를 열었다고 할 수 있다.

    이러한 디자이너 도구의 사용이 주는 또 다른 이점은 응용 시스템 개발 완료 후 배포 단계에서 발생할 수 있는 오류 또는 변경 사항을 시스템을 설계하는 초기 단계부터 발견하고 대처함으로써 예상치 못한 추가 비용의 발생을 제거하는 것이다.

    서비스 지향 시스템을 디자인하고 즉각적으로 이 시스템의 운영 인프라에 대한 유효성 검사를 실행할 수 있는 능력을 ‘운영을 위한 디자인(Design for Operations)’이라고 한다. 응용 프로그램은 대개 하나의 환경에서 디자인되는 경우가 많지만, 그 밖의 다른 환경이나 여러 환경에 배포되도록 설계된다. 대상 데이터센터 모델과 대조하여 디자인 유효성 검사를 수행하는 능력은 배포 과정을 더욱 매끄럽게 만들어 주며, 동시에 연결된 시스템의 개발, 배포, 운영의 단순화 및 자동화를 추구하여 설계자의 관점에 맞추어 작업을 수행할 수 있다.

    또한 제약 조건은 양쪽 부분에서 모두 강제 실행될 수 있으므로, 프로젝트 시작 단계부터 유효성 검사 메커니즘을 통해 의사소통을 강제함으로써 시스템이 성공적으로 배포되도록 보장할 수 있다. 그럼 분산 시스템 디자이너를 사용하여 간단한 시스템을 작성하면서 디자인 도구에 대해 살펴보자.

    응용 프로그램 연결 디자이너
    새로운 솔루션을 만들 때 접하게 되는 첫 번째 디자이너가 응용 프로그램 연결 디자이너로, 웹 서비스 응용 프로그램 및 클라이언트 웹 또는 윈도우 기반 응용 프로그램을 정의하기 위한 디자인 화면을 제공한다. 이 디자이너를 사용하면 응용 프로그램을 연결할 수 있고 코드 내에서 지원돼야 하는 통신 경로를 정의할 수 있다. 또한 구현을 위해 개발자용 기본 胄?구현을 생성하기 전에 응용 프로그램 설정 및 디자인으로 자유롭게 시험해 볼 수 있다.

    응용 프로그램 연결 디자이너가 제공하는 비주얼 스튜디오 도구 상자는 윈도우 기반 응용 프로그램, 웹 서비스 및 데이터베이스를 나타내는 구성 요소 집합을 제공한다(<화면 1>). 드래그 앤 드롭 기능을 적용하여 쉽게 시스템을 배치할 수 있다.

    예를 들어, 데이터베이스 연결이 필요하다고 지정하려면 ExternalDatabase 구성 요소를 디자인 화면으로 끌어서 놓은 다음 udio의 표준 속성 창에서 데이터베이스에 대한 연결 문자열을 설정한다. 데이터 소스가 결정된 경우에는 웹 서비스의 형식으로 데이터 액세스 층을 추가한다. 웹 서비스를 디자인 서비스로 끌어온 다음에는 둘 사이의 연결을 끌어와 웹 서비스를 이전에 정의한 데이터 소스로 바인딩할 수 있다.

    사용자 삽입 이미지
    <화면 1> 도구상자
    다음 단계는 웹 서비스 인터페이스를 통해 데이터를 표시하는 것으로, 이렇게 하려면 기본으로 생성된 웹 서비스의 종점을 클릭한 다음 종점 정보 창에서 공용 진입점을 정의한다. 새 웹 서비스 프로젝트가 솔루션에 추가되고, IIS의 로컬 인스턴스가 구성되며 언어별 소스 집합과 구성 파일이 생성된다.

    솔루션 탐색기에서 코드 폴더를 열면 두 개의 클래스 파일이 표시되는데, 하나는 웹 서비스 구현을 위한 것이고 다른 하나는 web.config 파일에 생성되는 데이터베이스 연결 문자열을 검색하는 데 유용한 유틸리티 클래스이다. 이 시점에서 코드의 공용 진입점에 대해 수정 또는 조정 작업이 이루어질 경우 수행된 변경 사항은 시스템 다이어그램과 자동으로 동기화된다. 초기 디자인을 테스트하는 작업은 비주얼 스튜디오의 초기 버전에서 수행된 것처럼 간단히키만 누르면 된다.

    모든 것이 잘 작동되었다면 이제 프론트 엔드를 웹 서비스에 추가해 보자. 응용 프로그램 연결 디자이너의 도구상자에서 ‘ASP.NET 웹 응용 프로그램’을 디자이너 화면으로 끌어서 놓는다. 이전과 마찬가지로 구성 요소를 모두 바인딩해야 하며, 표시된 웹 서비스의 진입점을 클릭하고 웹 서비스 및 웹 응용 프로그램 사이의 연결 링크를 끌어오면 된다.

    그런 다음 웹 응용 프로그램에서 마우스 오른쪽 단추를 클릭하고 구현을 선택한다. 그러면 비주얼 스튜디오가 새 웹 응용 프로그램 프로젝트를 솔루션에 추가하고 웹 서비스에 대한 웹 참조를 생성한다. 그런 다음 새 항목 추가 명령을 사용하여 이전 버전에서와 마찬가지로 기본 웹 페이지를 추가한다.

    웹 폼 디자이너를 사용하여 웹 서비스를 UI(웹 페이지의 GridView 컨트롤)에 연결하는 ObjectDataSource 구성 요소를 추가한다. ObjectDataSource는 웹 서비스의 표시된 메쏘드 호출을 처리하며, 이 경우 어떠한 코드도 작성할 필요가 없다. 단지 GridView 컨트롤의 속성을 약간 조정한 다음 웹 브라우저에 있는 웹 서비스에서 데이터를 표시하기 위해키를 누르기만 하면 된다. <화면 2>는 응용 프로그램 연결 디자이너에서 완료된 응용 프로그램이다.

    사용자 삽입 이미지
    <화면 2> 분산 솔루션의 응용 프로그램


    논리적 데이터센터 디자이너
    다음으로는 배포 환경 내 네트워크의 논리 모델과 실제적인 서버 유형을 정의해야 하는데, 이 단계는 이미 운영 팀에서 완료했을 수 있다. 이러한 경우, 데이터센터의 응용 프로그램 호스팅 기능에 대한 논리 모델을 표현하는 다이어그램을 만드는 데 이용되는 논리적 데이터센터 디자이너를 사용할 수 있다.

    이 디자이너를 사용하면 인프라 설계자가 데이터베이스 서버, 웹 서버, 논리 보안 영역 및 통신 끝점과 같은 시스템 엔터티를 표시하여 데이터센터 토폴리지를 지정할 수 있다. 또한 제약 조건은 데이터센터의 요구 사항을 기반으로 한 응용 프로그램 구성에 대해 적용될 수 있다.

    사용자 삽입 이미지
    <화면 3> 유형
    그럼 논리적 데이터센터 디자이너 도구 상자에 표시된 특정 요소를 사용하여 새로운 논리 데이터센터 다이어그램을 만들어 보자. <화면 3>은 현재의 논리 서버 목록 및 지원되는 끝점 유형을 보여준다. 이제 다이어그램에 DMZ(DeMilitarized Zone)를 나타내고 네트워크의 보안 내부 영역을 나타내는 두 개의 영역을 추가해 보자. 그런 다음 DMZ에 견고한 IIS 웹 서버를 정의하고, 내부 영역에는 ‘AppServer’라는 IIS 웹 서버와 SQL 서버를 실행하는 컴퓨터를 추가하자.

    IIS 웹 서버의 경우 미리 정의된 입력 및 출력 끝점이 있다. 연결 도구를 사용하면 AppServer와 SQL 서버 컴퓨터 사이의 연결을 포함한 다양한 입출력 채널을 연결할 수 있다. <화면 4>는 완료된 논리 데이터센터 다이어그램이다. 다이어그램을 정의하고 나면 논리 서버에 제약 조건을 추가할 수 있다. 예를 들어 AppServer가 SSL(Secure Socket Layer)을 사용하도록 해야 할 수도 있는데, AppServer를 선택한 후 Settings and Constraints 편집기를 열어 작업하면 된다.

    사용자 삽입 이미지
    <화면 4> 완료된 논리 시스템 아키텍처


    시스템 디자이너
    시스템 디자이너를 활용하여 응용 프로그램 연결 디자이너에서 이미 정의된 응용 프로그램의 시스템을 조직하고 구성할 수 있다. 분산 시스템 디자이너에서 시스템은 배포의 기본 단위이고, 하나 이상의 응용 프로그램이나 다른 시스템의 구성 단위로 인식된다. 하나의 시스템은 다른 시스템의 하위 시스템으로 구성될 수도 있기 때문에 매우 큰 분산 시스템을 정의할 수 있다.

    응용 프로그램 설계자는 시스템의 nested 구조를 이용하여 복잡한 다중 시스템정의를 만들 수 있으며, 이러한 시스템 정의의 경우 응용 프로그램 연결 디자이너에서 표기된 개발 구성과 별도로 배포 구성을 정의할 수 있다. 즉 시스템 정의는 솔루션에 정의된 응용 프로그램 구성과 서로 다르게 디자인될 수 있고, 각기 다른 데이터센터 구성, 다른 지리적 배포 환경, 다른 고객에 대해서 계획된 다른 배포 구성을 정의할 수 있다.

    사용자 삽입 이미지
    <화면 5> 다중 시스템 정의 다이어그램


    배포 디자이너
    프로세스의 마지막 단계는 이전에 정의한 응용 프로그램을 새로 정의한 논리 시스템 아키텍처로 맵핑하는 작업이다. 개발 환경에서 사용된 구성이 배포에 필요한 구성이라 전제하고 시험 배포(Trial Deployment)가 되는 대상을 정의할 수도 있고, 계획한 배포에 맞는 특정한 설정을 구성할 수 있는 새로운 시스템을 명시적으로 만들 수도 있다.

    대부분의 경우 먼저 시험 배포를 통하여 심각한 문제들을 제거한 다음 구성을 고정시키는 최종 단계로 시스템을 만든다. 그러면 시스템이 좀 더 안정적인 정의로 구성될 수 있어 대규모의 아키텍처 디자인에서 다시 사용될 수 있다.

    이제 시험 배포를 만들어 보자. 응용 프로그램 연결 다이어그램에서 시험 배포 정의(Define Trial Deployment)를 선택한 다음, 팝업 대화 상자에서 이전에 만든 논리적 데이터센터 디자인을 선택한다. 논리적 데이터센터를 배경으로 나타내는 새로운 배포 다이어그램에서 배포 디자이너를 사용해 각 응용 프로그램을 논리 서버로 바인딩하고 배포할 서버의 유형을 나타낼 수 있다.

    이렇게 하려면 간단하게 개요 컨트롤 또는 응용 프로그램 연결 다이어그램에서 직접 응용 프로그램을 끌어서 놓으면 된다. 만약 바인딩하려는 응용 프로그램과 서버가 호환되지 않는다면 no-drop 기호가 표시될 것이고, 프로세스가 각 응용 프로그램에서 반복되면서 시스템의 가상 배포를 만든다. 일단 모든 구성 요소를 해당 호스트로 맵핑하면 <화면 6>에 나타난 대로 맵핑의 유효성을 검사할 수 있다.

    유효성 검사는 모든 바인딩을 검사하여 양쪽 다이어그램에 정의된 제약 조건을 확인하고, 응용 프로그램에 필요한 경로와 프로토콜을 지원하는 논리적 데이터센터에 통신 경로가 있는지를 확인한다. 오류가 발생할 경우 작업 항목이 비주얼 스튜디오 작업 목록에 추가되며, 오류 목록에서 해당 항목을 두 번 클릭하면 오류가 발생한 다이어그램과 구성 요소로 이동하게 된다.

    예를 들어, AppServer가 ASP.NET을 사용하도록 하기 위해 논리적 데이터센터 디자이너에 제약 조건을 설정한다. 이 때 유효성 검사를 실행하면 오류가 발생하는데, 오류 항목을 두 번 클릭하면 선택한 끝점이 잘못되어 있는 응용 프로그램 연결 다이어그램으로 이동하게 된다. Settings 편집기에서 정확한 속성을 조정한 후, 값이 자동으로 web.config 파일에 기록되고 유효성을 다시 검사하면 모든 작업이 완료된다.

    개발한 응용 프로그램을 실제로 운영하기 전 극도의 압박감에 시달리는 대신, 이러한 과정을 통해 배포하기 전(가능하면 핵심 개발이 시작되기 전)에 배포 관련 문제점을 발견할 수 있는 이점을 얻을 수 있다.

    사용자 삽입 이미지
    <화면 6> 하위 시스템 맵퍼


    클래스 디자이너
    이제 시스템의 외부와 내부를 세밀하게 계획하기 위해 클래스 디자이너를 사용하여 작업할 수 있는 개발자에게 디자인 작업을 넘겨줄 차례이다.

    대부분의 객체지향 개발자들은 응용 프로그램 디자인을 위한 다이어그램을 만들고자 할 때
    UML문서 양식을 종종 사용한다. UML은 응용 프로그램을 모델링하는 데 사용할 수 있는 여러 유형의 다이어그램을 정의한다. 일반적으로 가장 많이 사용되는 다이어그램 유형은 응용 프로그램의 각 클래스와 함께 다른 클래스에 대한 관계를 표시하는 클래스 다이어그램이며, 각 클래스는 필드와 메쏘드가 나열된 상자에 표시된다.

    하지만 불행히도 UML은 닷넷 프레임워크와 같은 현재 기술에 뒤쳐지는 경향이 있다. 예를 들어, UML에는 비주얼 베이직 닷넷 및 C#의 내부 범위와 Friend에 대한 규정이 없다. 또한 닷넷 클래스에 대한 인터페이스의 핵심적인 부분인 속성 메쏘드 또는 이벤트를 나열하기 위한 적절한 방법도 없다.

    클래스 디자이너는 비주얼 스튜디오 2005를 사용하는 객체지향 디자이너와 개발자를 위한 아주 좋은 도구이다. 클래스 디자이너는 닷넷 환경에서 비주얼 베이직 닷넷 및 C#의 모든 언어 기능을 반영할 수 있는 UML과 유사한 클래스 다이어그램을 제공한다. 이 클래스 디자이너를 사용하면 정확한 다이어그램을 만들 수 있을 뿐만 아니라 실시간으로 다이어그램과 코드의 동기화를 유지할 수 있다.

    <화면 7>은 다이어그램을 위해 생성된 코드와 함께 비주얼 스튜디오 2005의 클래스 다이어그램 도구를 보여준다. 다이어그램이나 코드 중 어떤 것을 변경해도 양쪽 모두 자동으로 동기화 상태로 유지된다. 클래스 디자이너를 사용하려면 비주얼 스튜디오 2005에서 클래스 다이어그램을 프로젝트에 추가해야 하며, 이렇게 하려면 새 항목을 프로젝트에 추가하고 클래스 다이어그램 템플릿을 선택하면 된다.

    Class Details 창에서 클래스의 인터페이스를 보고 변경할 수 있다. 이러한 작업에는 메쏘드, 필드, 속성 및 이벤트의 추가와 제거가 포함된다. 또한 이러한 요소들의 범위, 매개변수 및 반환 형식을 변경할 수도 있다. Class Details 창에서 이루어진 모든 변경 사항은 코드에 즉시 적용된다.

    사용자 삽입 이미지
    <화면 7> 클래스를 Class View에서 클래스 다이어그램으로 끌기


    Team Developer
    팀 디벨로퍼는 개발자가 제품의 개발 주기 내 초기 단계 또는 주기 내내 언제라도 품질 향상을 위해 코드 버그나 성능 문제들을 발견하고 보완할 수 있도록 통합된 분석 도구들을 제공한다. 개발팀은 이를 통해 SDLC(Software Development Life Cycle)를 효과적으로 관리할 수 있다.

    분석 도구의 필요성
    여러 다양한 분석 도구들 중에서 소프트웨어 분석 요건을 충족하는 동시에 예산 범위를 벗어나지 않는 도구를 선택하는 것은 항상 쉬운 일만은 아니다. 게다가 이러한 도구는 비주얼 스튜디오 IDE에 통합되지 않을 수도 있고, 능숙하게 사용할 수 있으려면 일반적으로 별도의 시간을 투자해 사용 방법을 습득해야 한다.

    별도의 사용자 지정 분석 도구를 구현하는 작업도 쉽지 않은 작업으로 이를 위해서는 자원, 기술 및 경험이 요구된다. 하지만 현실적으로 대부분의 개발팀이 이 모든 것을 갖추기란 어려운 일이며, 이러한 방법으로 분석 도구를 선택할 수 있는 회사는 거의 없을 것으로 생각된다.

    촉박한 마감 시간과 한정된 예산을 핑계로 분석을 수행하지 않고 코드를 제공하는 것 또한 현실적으로 타당한 방법처럼 보일 수 있으나, 응용 프로그램이 배포된 후에 오류가 발생하면 이를 수정하기 위해 필요한 비용은 배포 전 소요되는 비용보다 더 많은 비용이 들어갈 수 있다. 견고하고 안정적인 응용 프로그램 개발을 위해 팀 디벨로퍼는 다음 두 가지 범주의 분석 도구를 제공한다.

    ◆ 코드 분석 도구
    ◆ 성능 도구


    코드 분석 도구
    코드 분석 도구의 목표는 개발자가 응용 프로그램 개발 중 정적 분석을 통해 코드 결함을 발견하고 수정할 수 있도록 하는 것으로, 이를 위해 PREfast와 FxCop이라는 두 가지 도구가 제공된다.

    Prefast는 C/C++ 소스코드에서 있을 수 있는 결함에 대한 정보를 개발자에게 제공해 주는 정적 분석 도구이다. Prefast가 보고하는 일반적인 코딩 결함에는 버퍼 오버런, 초기화되지 않은 메모리, null 포인터 역참조, 메모리 및 리소스 누수 등이 있으며, 개발자의 생산성 증대 측면에서 보다 편리하고 자연스럽게 분석 도구를 사용할 수 있도록 Prefast는 IDE 내에 통합된다.

    <화면 8>에서 보는 바와 같이 개발자는 프로젝트의 ‘Property Pages’에서 ‘Yes(/prefast)’를 선택하여 Prefast를 간단하게 활성화할 수 있다.

    FxCop는 관리되는 코드 어셈블리를 분석하고 어셈블리에 대한 정보(예 : 닷넷 프레임워크 디자인 지침 명시된 프로그래밍 및 디자인 규칙의 위반)를 보고하는 정적 분석 도구이다. FxCop는 분석 도중에 수행하는 검사를 규칙으로 나타낸다. 규칙은 어셈블리를 분석하고 발견된 사항에 대한 메시지를 반환하도록 관리되는 코드이다. 규칙 메시지는 관련된 모든 프로그래밍 및 디자인 문제를 식별하고, 가능한 경우 문제를 수정하는 방법에 대한 정보를 제공한다.

    사용자 삽입 이미지
    <화면 8> PREfast 활성화



    사용자 삽입 이미지
    <화면 9> FxCop활성화


    성능 분석 도구
    성능 도구를 사용하여 코드에 존재하는 성능 관련 문제들을 측정, 평가, 해결할 수 있다. 이러한 도구들은 IDE에 통합되어 사용자가 편리하고 원활하게 사용할 수 있으며, 샘플링 및 계측이라는 두 가지 프로파일링 방법을 지원한다.

    샘플링 동안 데이터 수집 인프라는 실행되는 응용 프로그램을 정기적으로 중단하여 실행 중인 함수를 확인한 후 해당 함수의 샘플 계산을 증가시키며, 함수 호출에 이르기까지의 호출 스택에 대한 정보를 저장한다. 응용 프로그램이 종료하면 수집된 모든 데이터가 보고서 파일로 생성되며, IDE에 통합된 보고 기능을 사용하여 이 보고서를 편리하게 볼 수 있다.

    샘플링은 응용 프로그램이 정기적으로만 중단되기 때문에 오버헤드가 적다는 이점이 있다. 따라서 응용 프로그램이 실제 사용에서와 흡사하게 동작할 수 있으나 이 방법은 샘플링된 함수에 대한 상대적인 성능 데이터만 얻을 수 있다는 단점도 있다.

    계측은 응용 프로그램의 특정 부분에 대한 정확한 성능 데이터를 얻을 수 있다는 이점을 제공한다. 계측 도중에 응용 프로그램의 함수에 ‘시작’ 및 ‘종료’ 프로브(probe)가 삽입되는데, 이러한 프로브는 데이터 수집 인프라에 다시 보고됨으로써 함수를 실행하는 데 걸린 시간과 다른 수치를 사용자가 정확하게 파악할 수 있게 해준다.

    응용 프로그램을 프로파일링하기 위해 선호되는 방법은 먼저 샘플링을 수행한 다음 샘플링으로 생성된 결과를 기반으로 응용 프로그램의 특정 측면을 계측하는 것이다. 응용 프로그램을 프로파일링하는 절차는 새 성능 세션을 만드는 간단한 방법으로 시작할 수 있으며, 성능 세션 마법사(Performance Session Wizard)를 사용하여 새 성능 세션을 손쉽게 만들 수 있다. 새 성능 세션은 수작업으로도 생성 가능하며 메뉴에서 ‘New Performance Session’ 명령을 사용하면 된다.

    성능 세션을 만든 결과는 <화면 11>과 같이 성능 익스플로러(Performance Explorer)에 시각적으로 표시된다.

    성능 익스플로러는 계층적 구조로 사용자에게 제공되며, 계층의 루트 노드는 성능 세션을 나타낸다. 이 노드의 속성은 성능 세션을 만들 때 사용자가 설정한 속성으로 사용자가 성능 세션 마법사를 사용하여 세션을 만든 경우 이러한 속성은 사용자가 마법사를 진행하면서 선택한 값이 반영된다. 사용자가 성능 세션을 수동으로 만든 경우 이러한 속성은 기본 값을 포함한다.

    응용 프로그램 실행이 끝나면 성능 세션 보고서가 Reports 노드에 자동으로 추가되며, 보고서는 응용 프로그램을 실행하는 동안 가장 비용이 많이 드는 함수를 표시한다. 보고서는 요약 보기, 함수 보기, 호출자/호출 수신자 보기, 호출 스택 보기, 형식 보기 등을 통해 세부 정보를 제공한다.

    사용자 삽입 이미지
    <화면 10> Performance Wizard 시작


    Team Test
    팀 테스트는 새로운 테스트 도구 그룹으로 MS 내부에서 사용됐던 테스트 도구들이다. 이 새로운 테스트 도구들은 비주얼 스튜디오에 통합되어 자체 테스트 프레임워크뿐 아니라 완전한 SDLC 솔루션이 제공하는 확장된 프레임워크에도 사용될 수 있다.

    품질 보증
    모든 응용 프로그램과 웹 페이지의 품질 및 성능 목표치 달성을 위해서는 엄격한 테스트가 우선 선행돼야 한다. 최근 들어 많은 관심을 받고 있는 테스팅 분야는 과거 고급 개발자보다는 초급 개발자의 업무 영역으로 분류되어 가치를 제대로 평가받지 못했으나, 소프트웨어 공학의 전문화와 품질의 중요성이 부각되며 전 개발 공정 중 제일 비용을 효율화할 수 있는 과정으로 인식되고 있다.

    사용자 삽입 이미지
    <화면 11> Performance Explorer
    비주얼 스튜디오는 소프트웨어 개발자를 위주로 하는 제품으로 개발 과정의 테스트 지원 기능을 중점적으로 제공하지는 않았다. 테스터로서 비주얼 스튜디오를 활용해 본인이 원하는 테스트를 수행하기 위한 코드를 작성할 수도 있겠으나, 특별한 목적의 테스트나 테스트를 관리하기 위해서는 써드파티의 전문 테스트용 제품을 필요로 했을 것이다.

    더욱이 전문 테스터로서 자료 모델링, 발표, 지원 문서 체계화, 버그 트랙킹, BVT(Build Verification Test) 같은 테스트 세트를 생성해야 한다면 문제는 더욱 복잡해질 것이다. 테스트 툴셋들이 제공하는 결과물은 일반적으로 다양한 도구와 정보 공유를 위한 저장소간에 공유되지 못하는 불편을 준다.

    팀 테스트는 비주얼 스튜디오 IDE에 통합되어 테스트를 생성하고 운영하는 데 보다 높은 생산성을 보장한다. 또한 테스트 결과물의 데이터베이스 저장, 경향 분석, 기록 보고서 생성 및 결과 자료의 차이를 비교할 수 기능을 지원한다.

    팀 테스트가 지원하는 테스트 형식은 다음과 같다. 팀 테스트는 기존의 테스트 방식을 계속해서 사용할 수 있게 하거나 비주얼 스튜디오에 플러그인해 커스텀 형식의 테스트를 진행할 수 있도록 충분한 확장성을 제공한다.

    ◆ 단위 테스트 : 프로젝트의 함수나 메쏘드를 실행시키는 코드들로 구성되어 작은 단위의 소스코드를 테스트하는 데 사용됨

    ◆ 웹 테스트 : 브라우저 세션에서 만들거나 레코딩된 일련의 HTTP URL을 테스트함

    ◆ 일반 테스트 : 팀이 기존에 쓰고 있던 자동화 테스트와 도구를 사용할 수 있도록 함

    ◆ 부하 테스트 : 많은 사용자를 시뮬레이트하여 자동화 테스트를 실행함

    ◆ 매뉴얼 테스트 : 자동화하지 않은 테스트 과정을 단계적으로 수행하는 테스트

    테스터 인터페이스
    ◆ 테스트 뷰 창 : 테스트 네비게이션 및 편집 기능 제공으로 테스트 작성 지원

    ◆ 테스트 탐색기 창 : 각각의 테스트를 분류하여 관리하는 기능 제공

    ◆ 실행 환경 설정 대화창 : 정확한 테스트 방법을 정의(<화면 13>)

    ◆ 테&#