.NET General2008. 3. 30. 22:39

최근에 현재 유지보수중인 솔루션의 에러 처리 로직 개선 작업을 하다가, 내가 아직도 Throw와 Throw ex의 차이를 모른다는 사실을 알게 되었다. -_-;; 그래서 구글신에게로 고고씽. ㅎ


역시 구글신께서 알려주신 Top 4개의 링크만으로 모든 궁금증이 풀렸다. 그 링크 목록은 다음과 같다.

Joteke's Blog - Difference: throw or throw ex?
Scott Dorman Blog - Difference between "throw" and "throw ex" in .NET
Mattness Encapsulated -  throw; vs. throw ex; Here's the difference!
BULLOG.NET - 즈믄의 C# 강좌 - throw  VS  throw ex


정리하자면..

  1. Throw는 이전 Exception의 모든 내용을 보존하지만, Throw ex는 보존하지 않는다. 따라서 단순히 이전에 발생한 예외를 전달만 한다면, Throw를 쓰는 것이 좋다.
  2. 새롭게 예외를 포장(?)한다면 - New ApplicationException등을 사용해서 - 이전 예외 객체를 innerException으로 같이 넘기는 것이 좋다.
Posted by kkongchi
.NET General2007. 4. 25. 19:44
현재 내가 근무하고 있는 회사는 BI 솔루션 업체이다. 그래서 이 솔루션이라고 하는 것이 현재 개발 중인 버전만 있는 것이 아니고, 기존에 고객들이 쓰던 예전 버전 또한 존재하기 때문에 기존 솔루션을 유지, 관리하는 일도 아주 중요한 업무 중의 하나이다.

얼마전에 이전 버전 중의 하나에서 이슈가 발견되어서, 처음으로 그 예전 버전을 디버깅할 일이 생겼다. 기존 버전은 Visual Studio.NET 2002를 가지고 개발되었기 때문에 VS.NET 2002 를 설치하고 웹 프로젝트를 열려고 하는데..
문제가 발생했다...

열리지 않는 것이다. 분명히 IIS에 제대로 경로를 잡아줬기 때문에 잘 열려야 하는데 안 열리는 것이었다. -_-;;

그리고 결국 Microsoft Support Sited에서 해결책을 찾았다.
Fix: You Cannot create web project on Windows server 2003 in Visual Studio.NET 2002

위 문서에서 제시하는 해결책은 다음과 같다.
1. Visual Studio 2003으로 개발한다
2. IIS 웹 사이트 속성에서 Mime Type에 확장자 tmp, 타입 text/plain 을 하나 추가한다. 비주얼 스튜디오 2002가 웹 프로젝트를 열기 전에 테스트할 목적으로 .tmp파일을 하나 생성해서 거기에 Request를 보내는데 IIS 6.0에서는 명시적으로 Mime Type에 추가시키지 않으면 블록을 해버린다고 한다. 나는 이 방법으로 해결했다.
3. 위 문서에 링크되어 있는 핫픽스를 설치한다.

아마도 나와 같은 특수한 경우가 아니라면 - 사실 나도 Windows 2003을 쓰고 있어서 그랬지만, 원래 우리 회사 솔루션의 예전 버전은 Windows 2000에 설치하는 것이 원칙이다 - 이런 문제를 만날 일이 없을 지도 모르겠다. 하지만 혹시라도 이런 일이 있다면, 참고하시길 바란다.
Posted by kkongchi
.NET General2007. 2. 12. 11:09
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cossdk/html/a59935de-6b8f-4c0a-8479-e30bc0509698.asp

COM+ 서버 애플리케이션에는 아래와 같은 Authentication Level을 설정할 수 있다.

사용자 삽입 이미지


None: No authentication occurs. 즉 어떤 인증도 수행하지 않는다.

Connect: Authenticates credentials only when the connection is made. 최초 연결할 때만 인증을 수행한다.

Call: Authenticates credentials at the beginning of every call. 매번 호출 시마다 Credential을 인증한다.

Packet: Authenticates credentials and verifies that all call data is received. This is the default setting for COM+ server applications. Credential을 인증하면서 모든 호출 데이터가 도착했는지 검사한다. 이것이 디폴트 설정이다.

Packet Integrity: Authenticates credentials and verifies that no call data has been modified in transit. Credential의 인증과 함께 모든 호출 데이터가 도중에 변조되지 않는지를 검사한다.

Packet Privacy: Authenticates credentials and encrypts the packet, including the data and the sender's identity and signature. Credential의 인증도 하면서, 데이터와 호출자의 Identity와 Signature를 포함하는 모든 데이터를 암호화한다.

대부분 디폴트 레벨을 그냥 쓸 것이다. 나도 그랬고.. 하지만 이 인증 부분은 사실 각 애플리케이션 별로 고려되어야 할 사항임에는 분명하다. 더 중요하고 크리티컬한 애플리케이션에 대해서는 Packet Integrity나 Packet Privacy까지도 고려되어야 할 것이다. 특히 원격에서 COM+ 컴포넌트를 호출할 수 있도록 구성되어 있다면 더더욱! 그리고 그렇게까지 보안에 신경 쓸 필요없다면 더 낮은 레벨로 낮추는 것도 생각해 볼 수 있다. 보안 레벨이 낮아지면 낮아질 수록 성능이 더 좋아지기 때문이다.

Posted by kkongchi
.NET General2007. 2. 6. 15:05
윈도우즈 서비스로 만든 닷넷 모듈에 문제가 생겨서 디버깅할 일이 있었다. 알다시피 윈도우 어플리케이션은 일반 닷넷 어플리케이션처럼 확장자는 exe이지만, 독립적으로는 실행되지 않고, 서비스에 등록되어서 실행되게 된다.

그래서 디버깅을 하기 위해서는 Visual Studio의 프로세스 디버깅 기능을 이용해야 한다. 즉 아래 그림처럼 서비스의 프로세스를 비주얼 스튜디오 디버깅 메뉴에서 직접 연결해서 디버깅하는 것이다.

사용자 삽입 이미지


그런데 오늘은 위 방법을 쓰기가 힘든 상황이 발생했다. 왜냐하면, 초기 작업에 문제가 있었던지 서비스 시작이 아예 되질 않는 거다..-_-;; 서비스 시작이 되질 않으니 프로세스를 디버깅할 수가 없는 문제가 발생했다.

결국 난감한 상황에서 언제나 한줄기 빛을 던져주시는(^^;;) 구글님에게 문의를 해보았고, 원하던 답을 찾을 수가 있었다. http://weblogs.asp.net/paulballard/archive/2005/07/12/419175.aspx 즉, 윈도우 서비스 초기화 코드에 아예 아래 코드처럼 디버깅을 시작할 수 있는 코드를 삽입하는 것이다.

<MTAThread()> _
Shared Sub Main()

#If DEBUG Then
        System.Diagnostics.Debugger.Launch()
#End If


이렇게 컴파일된 모듈을 서비스 MMC에서 시작시키면, 아래 그림처럼 디버깅 윈도우가 뜨고 비주얼 스튜디오를 이용해서 디버깅할 수가 있다.

사용자 삽입 이미지


내가 참조한 포스트의 저자는 Debugger.Break()을 사용해서 중단점을 걸면 된다고 말하고 있지만, 물론 컴파일할 때에 비주얼 스튜디오에서 중단점을 걸어놓는다면, 그것도 작동된다.
Posted by kkongchi
.NET General2006. 11. 3. 14:32

어제, 오늘 아주 깜짝 놀랄만한 뉴스가 연이어 터지고 있다.
어제는 MS가 PHP Zend와 기술 제휴를 하더니, 오늘은 Suse Linux의 노벨과 전격 제휴를 했다고 한다.

Zend의 경우, .NET Framework에서 PHP 소스가 한 줄의 코드 변경도 없이 완벽하게 동작하는 것이 목표라고 한다. PHP.NET? 그러면 ASP.NET은?

Suse Linux의 경우, MS에서 공식적으로 밀어주기로 한 모양이다. 즉, MS 제품 고객들이 윈도우즈 서버와 함께 리눅스 서버를 함께 쓰길 원하는 경우에 Suse Linux를 추천하게 될거라고 한다. 그리고 공동 개발을 통해서 한 대의 머신에서 두 OS를 같이 쓸 수 있도록 한다는데...

아무튼, 굉장히 충격적인 소식이다. 이건 마치 한나라당과 열린우리당이 손을 잡았다는 얘기와 똑같은 게 아닐런지...-_-;;


Posted by kkongchi
.NET General2006. 7. 25. 23:40

FxCop은 MS에서 만든 코드 분석 툴이다. 닷넷 코드를 분석해서 표준적인 규칙에 맞는지, 성능에 문제가 없는지 등을 검사해주는 도구로, 많은 프로젝트에서 코드 리뷰를 위한 툴로 많이 사용되고 있다.


이번 Visual Studio Team System에서는, 이 FxCop이 아예 Visual Studio 내부에 내장되어서, 아주 간단하게 코드 분석을 해볼 수 있게 되었다. 솔루션 탐색기에서 프로젝트를 오른쪽 클릭해서 나오는 컨텍스트 메뉴에서 "코드 분석 실행"이라는 것을 클릭하면 바로 FxCop을 이용한 코드 리뷰를 실행하고 그 결과를 얻을 수 있다.


솔루션 탐색기에서 코드 리뷰 실행




코드 리뷰 결과 화면




이 코드 분석 툴에는 200개 정도의 기본 규칙들이 있다. 디자인, 명명, 보안, 사용, 상호 운용성, 성능, 안정성, 유지 관리, 이동성, 이식성, 전역화 등으로 분류된 이런 규칙들은 MS에서 제시하는 닷넷의 매우 표준적인 규칙에 의거해서 제작되었기 때문에 이 규칙들을 적용해서 코드를 분석해보고 규칙에 따르도록 코드를 고치는 것은 전체적인 코드의 질을 높이고 결과물의 퀄리티와 성능, 유지 관리성 등을 높이는데 매우 도움이 된다.


그런데, 실제 SI 프로젝트에서는 아무래도 Custom Rule이 필요하다. 많은 사람들이 참여하는 프로젝트에서 이런 자동화된 툴을 사용해서 개발 표준 준수여부를 분석하는 것은 시간과 리소스의 절약을 가져오기 때문에, 그 프로젝트에만 있는 규칙에 대한 준수 여부를 체크할 수 있는 규칙을 만들어서 사용한다면 아주 유용하다.


그리고, 이 FxCop은 Custom Rule을 작성할 수 있는 구조를 지원한다. FxCop의 규칙은 닷넷 어셈블리(DLL) 형태로 만들어져 있는데, 이 DLL을 만들 수 있도록 FxCopSdk.dll, Microsoft.Cci.dll 등의 참조할 수 있는 어셈블리를 제공하고 있다. 이 FxCop은 코드를 분석하는데 reflection을 쓰지 않고 introspection이라는 것을 사용한다. 이 introspection은 reflection과 같이 MSIL 코드를 분석해서 어셈블리(내부의 클래스 등의 모든 정보 또한)의 정보를 추출하는데, reflection보다 더 빠르다.


Custom Rule을 만드는 절차는 다음과 같다.


1. Visual Studio 2005에서 클래스 라이브러리 프로젝트를 만든다.


2. FxCopSdk.dll 과 Microsoft.Cci.dll을 참조해야 한다. 이 DLL들은 비주얼 스튜디오가 설치된 프로젝트 아래에 \Team Tools\Static Analysis Tools\FxCop 폴더에 있다.


3. 먼저 BaseRule 클래스를 만들어야 한다. 이 Base 클래스는 현재 만드는 프로젝트 내부의 모든 Rule 클래스들이 상속하게 될 클래스로, 리소스 XML파일을 로딩하는 역할을 한다. 이 Base 클래스는 Microsoft.FxCop.Sdk.Introspection.BaseIntrospectionRule 클래스를 상속해서 만들어야 하고, 아래의 샘플 코드와 똑같이 만들면 된다. (물론 두번째 파라미터의 XML 리소스 이름, 세번째 파라미터 내부의 클래스 자신의 이름은 바꿔주어야 한다)


using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.FxCop.Sdk.Introspection;
using Microsoft.FxCop.Sdk;
using Microsoft.Cci;


namespace FxCopSampleRule
{
// 반드시 BaseIntrospectionRule 클래스를 상속해야 한다.
public abstract class BaseFxCopSampleRule : Microsoft.FxCop.Sdk.Introspection.BaseIntrospectionRule
{
protected BaseFxCopSampleRule(string ruleIdentifier)
  : base(ruleIdentifier, "FxCopSampleRule.FxCopSampleRule", typeof(BaseFxCopSampleRule).Assembly)
{
}
}
}


4. 리소스 XML 파일을 만든다. 이 리소스 파일에는 이 어셈블리의 규칙 클래스들이 사용하게 될 메시지(규칙을 어긴 문제에 대한 이름, 설명, 해결책 등)들이 들어가게 된다. 만들 때는 리소스 파일이 아니라 XML 파일로 만들어야 하며, 중요한 것은 이 XML 파일의 속성에서 반드시 빌드 작업을 "포함 리소스"로 해야 한다는 것.




<Rules FriendlyName="AARule">
<Rule TypeName="ShouldHaveAANameSpace" Category="AA.Naming" CheckId="AA0001">
<Name>Should Have AA NameSpace</Name>
<Description>Should Have SK NameSpace</Description>
<Url></Url>
<Resolution Name="Namespace">네임스페이스는 반드시 AA.BB로 시작해야 합니다. {0} 네임스페이스를 고치세요</Resolution>
<Email>kkongchi@interdev.co.kr</Email>
<MessageLevel Certainty="95">Error</MessageLevel>
<FixCategories>Breaking</FixCategories>
<Owner>kkongchi</Owner>
<GroupOwner>AA</GroupOwner>
<DevOwner>kkongchi</DevOwner>
</Rule>
</Rules>


5. 이제 규칙을 만들 차례이다. 규칙은 하나의 클래스로 만드는데, 3번에서 만든 BaseRule 클래스를 상속해서 만든다. 이름은 규칙을 잘 나타내도록 만드시기 바란다. 생성자에서 Base 생성자를 상속할 때에 현재 만드는 규칙이 사용할 메시지의 RuleName을 파라미터로 넣어서 그 메시지를 로드할 수 있도록 해야 한다.


6. 그리고 그 규칙 클래스에서는 Check 메소드를 오버라이드해서 체크할 규칙을 구현하면 된다. Check 메서드에는 많은 오버로드된 버전이 있기 때문에 만들려고 하는 규칙에 맞는 것을 선택해야 한다. 아래의 샘플은 어셈블리의 네임스페이스를 체크하는 것이기 때문에 Module이 파라미터인 것을 선택했다. 체크해야 할 규칙에 어긋나는 케이스가 발생했을 때, Problems 프로퍼티에 새로운 Problem 객체를 Add시키면 된다. 그리고 그 Problem 객체에는 XML에서 로드하는 Resolution 객체가 필요하다. (코드를 보면 알겠지만, {0} 등의 형태로 메시지 내부의 문자열에 현재 검사한 모듈의 이름 등을 넣을 수가 있도록 되어 있다.


using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.FxCop.Sdk.Introspection;
using Microsoft.FxCop.Sdk;
using Microsoft.Cci;

namespace FxCopSampleRule
{
// 먼저 만든 Base 클래스를 상속한다.
public class ShouldHaveAANameSpace : BaseFxCopSampleRule
{
//리소스 XML파일에 있는 규칙들 중에서 ShouldHaveAANameSpace (이름)이 반드시 있어야 한다.
public ShouldHaveAANameSpace() : base("ShouldHaveAANameSpace")
{
}

/// <summary>
/// 네임스페이스가 AA.BB로 시작하는지를 체크하는 규칙이다.
/// </summary>
/// <param name="module"></param>
/// <returns></returns>
public override ProblemCollection Check(Module module)
{
for (int i = 0; i < module.GetNamespaceList().Length; i++)
{
  if (!module.GetNamespaceList()[i].FullName.StartsWith("AA.BB"))
  {
   //Problem 객체를 만들어서 base.Problems에 더해야 한다.
   //GetResolution 함수의 파라미터는 XML에 정의된 Resolution에서 {0}, {1} 로 표시된 문자열을 채우는 값이다.
   base.Problems.Add(new Problem(GetResolution(new string[1] { module.GetNamespaceList()[i].FullName })));
  }
}

return base.Problems;
}
}
}


7. 코드가 완성되면 컴파일을 하면 된다. 컴파일된 DLL을 비주얼 스튜디오가 설치된 디렉토리 아래의 Team Tools\Static Analysis Tools\FxCop\Rules 폴더에 복사하면, 바로 그 후부터 코드 분석 시에 새로 만든 규칙을 사용할 수가 있다.


Posted by kkongchi
.NET General2006. 7. 22. 02:29

1. SQL Injection 이란?


a. SQL Injection은 SQL 쿼리에 사용되는 사용자의 입력값에 대해서 제대로 유효성 검사를 하지 않았거나 타입 체크를 하지 않아서, 쿼리가 제대로 동작하지 않거나 시스템에 문제를 일으킬 수 있는 다른 코드가 실행될 수 있게 만드는 애플리케이션 상의 보안 취약점이다.



2. SQL Injection의 예


a. 사용자 정보가 DB에 있으며, 로그인 페이지에서 다음과 같은 쿼리를 호출해서 인증을 처리한다고 생각해보자

SELECT * FROM USERS WHERE USERID = '" + UserIDTextBoxValue + "' AND PASSWORD = '" + PasswordTextBoxValue + "'"


b. 여기서 UserIDTextBoxValue에 a' or 1=1 -- 이라는 값을 넣는다면, or 1=1 부분에 의해서 참이 되고, -- 에 의해서 그 다음부터는 주석처리가 되기 때문에 전혀 쿼리에 영향을 주지 않는다. 그러므로, 실제로 실행되는 쿼리는 다음과 같다.

SELECT * FROM USERS WHERE USERID = 'a' or 1=1 -- AND PASSWORD = ''


3. 해결책


a. ADO.NET에서 제공하는 SqlCommand, SqlParameter 객체를 사용하면, 이 SQL Injection 공격으로부터 안전한 코드를 작성할 수 있다. SqlParameter 객체를 통해서 전달된 값은 쿼리 자체에 영향을 끼치지 못하고 문자열로만 취급되기 때문이다. 즉, 위의 쿼리에 Parameter로 a or 1=1 -- 이란 값을 넣어도 'a or 1=1 --" 이라는 문자열과 USERID를 비교하게 되기 때문에 일치하는 값이 없는 것으로 결과가 나오게 될 것이다. 이런 방식을 Parameterized Query라고 한다.

//SqlCommand 객체 생성
System.Data.SqlClient.SqlCommand oCom = new System.Data.SqlClient.SqlCommand();
oCom.CommandText = "SELECT * FROM USERS WHERE USERID = @param1";
oCom.CommandType = CommandType.Text;

//SqlParameter 객체 생성
System.Data.SqlClient.SqlParameter oParam = new System.Data.SqlClient.SqlParameter();
oParam.DbType = DbType.String;
oParam.Value = "value";
oParam.ParameterName = "param1";

//SqlCommand객체에 SqlParameter를 적용한다.
oCom.Parameters.Add(oParam);


b. Stored Procedure를 사용하게 되면 반드시 SqlParameter객체를 사용해야 하기 때문에 Sql Injection으로부터 안전할 수 있다.


c. 하지만 Stored Procedure 내부에서 문자열과 파라미터를 더해서 쿼리를 구성한다면, SQL Injection에 취약한 코드가 된다. 그래서, 이런 Dynamic Query로 이루어진 Stored procedure를 사용할 때는, 아주 엄격하게 Validation을 해야 할 것이다.

Posted by kkongchi
.NET General2006. 5. 4. 21:20

비주얼 스튜디오 닷넷 2003 을 사용할 때, 디버깅 시에 가장 유용하게 사용했던 도구라고 한다면, 내 경우는 직접 실행 창이었다. 물론 자동, 지역, 조사식 등의 도구들도 있지만, 난 대부분의 경우 직접 실행 창을 사용했다. 인텔리센스 기능도 지원하기 때문에, 코드 외의 여러 가지를 실행시켜보면서 작업할 수 있기도 하고, 변수에 담긴 값이 꽤 클 때도 보기가 편하다는 장점이 있어서, 디버깅을 할 때 코드를 step by step으로 실행시키면서 직접 실행창만을 가지고 작업을 했었다.

비주얼 스튜디오 2003(그리고 그 이전 버전)에서는 메뉴중에서 디버그->창->직접실행 을 선택하면 디버그 중에서 직접 실행 창을 볼 수 있었다. 그런데, 이번에 새로 출시된 Visual Studio 2005에서는 (내가 못 찾은 것인지 아니면 어딘가 숨어 있는지는 모르겠지만) 디버그->창 까지는 있는데 거기에 직접실행창을 띄우는 메뉴는 없다.

이 직접 실행 창을 띄우는 방법은 다음과 같다.

1. 기본적으로 명령 창은 디버그 시에 자동으로 나오게 된다. 이 명령 창에서 immed를 입력하고 엔터를 누른다




2. 그러면 직접 실행 창이 나오게 된다. 여기서 이전처럼 사용하면 된다.


Posted by kkongchi
.NET General2006. 3. 5. 00:42

지난 주와 지지난 주 토요일, 그러니까 2월 18일, 25일에 MCPD Beta Exam에 응시해서, 시험을 치뤘다. MCPD는 Microsoft Certified Professional Developer 의 약자로, 이번에 MS에서 닷넷 프레임워크 2.0의 출시와 함께, 새롭게 만들어진 자격증이다. 저는 MCAD를 갖고 있는데, 어느날 beta exam에 무료로 응시해보라는 메일이 왔다. 나중에 어차피 한번 쳐볼까 하는 시험이라서, 공부도 많이 못 했고, 결정적으로…^^;; 기출문제 덤프도 없어서 많이 불안했지만 뭐 불합격해도 본전이라는 생각으로 쳐봤다.


18일에 친건 MCPD Web Application Developer 였고, 25일에는 MCPD Windows Application Developer였다. (MS 자격증 홈페이지를 보면 이것 말고도 Distributed Application Developer라는 게 하나 더 있는데 그건 이번에는 없었다.) 18일에 첫 시험을 쳤을 땐 상당히 당황했다. 처음에 30문제가 나오길래 문제 수가 줄어든 줄 알고 좋아했었는데, 알고보니 30문제/1시간씩 총 3개의 섹션이 있는 것이었다. 그렇게 3시간. 그리고 처음 섹션의 1시간이 끝나면, 그 섹션의 시험문제는 다시 재검토할 수가 없다. 즉 3과목 시험을 연속으로 치는 거랑 비슷하다고 보면 된다.


1,2번째 섹션은 두 시험 다 기존 MCSD, MCAD 시험과 유사한 형태라고 보시면 된다. 언어와 기술에 대한 기본적인 이해가 필요한 문제들이 나온다. 좀 치사하게 나오기 때문에 주의가 필요하다는 것은 기존 시험 쳐보신 분들은 다들 알 것이다. (이게 바로 덤프가 반드시 필요한 이유이기도 하다) 그리고 좀 특기할 것은 이번에 C#에서 (처음에 시험 start 버튼을 누르면 언어 선택 화면이 나오고 거기서 VB, C#, C++ 중에서 고를 수 있다) 추가된 제네릭 (public class GenericList<T> 이런 형태로 쓰는거) 에 대한 문제가 꽤 나왔다. 그리고 두 시험 다 UI에서 데이터를 비동기 형식으로 가져오는 부분에 대한 문제도 여러 개 나왔던 것으로 기억한다.


그리고, 좀 기존에 비해서 특이했던 것이 마지막 섹션이다. 마지막 섹션 30문제는 말하자면, 디자인에 관한 문제들이다. 애플리케이션, 시스템 배포 등에 대해서 상황을 설명하고 그 중 최적의 솔루션, 혹은 문제를 해결하는 방안에 대해서 질문한다. 예를 들면 분산 시스템 환경에서 firewall에서 어떤 포트를 열어야 클라이언트에서 웹 서버에 접속할 수 있는지, 또는 특정 환경에서 클라이언트 배포 방법으로 Windows Installer 가 나은지 아니면 click once 기술이 나은지 등등의 문제가 출제되었다.


시험 방식도 새롭고, 문제도 새로운 스타일의 문제가 많이 나와서 조금은 개선되었다고 말할 수 있을 것 같다. 특히 좀전에 언급한 마지막 섹션같은 경우는 지식도 중요하지만 경험이 있다면 더 쉽게 풀수 있지 않을까 생각이 된다. 아무래도 진정한 실력 평가는 그런 것이 되어야 한다라고 생각했기 때문에, 올바른 방향으로 시험이 발전되었다고 생각한다. 물론 덤프가 나온다면, 뭐 똑같아 지겠지만 말이다.

* 일단 시험은 봤는데, 결과는 바로 나오지는 않았다. 아마 beta라서 그런 것 같은데, 성적은 메일로 준다고 마지막에 나와서 차라리 다행이라고 생각했다..^^;;

Posted by kkongchi
.NET General2006. 2. 20. 18:27

NAnt를 혹시 사용해보셨는지?

Ant는 원래 Java에서 사용하던 빌드 툴이다. C에서 사용하는 Make와 같은 역할을 하지만 역시 Java답게 운영체제나 시스템에 독립적인 빌드환경을 제공하기 위해서 Apache그룹에서 만든 빌드 프레임워크인데, NAnt는 SourceForge 커뮤니티에서 제작한 Ant의 .NET 버전이라고 생각하면 된다.

아래와 같은 빌드정의 파일(.build)을 XML포맷으로 만들고 그 파일이 있는 디렉토리에서 NAnt라고 Command-Line 명령을 실행하기만 하면 된다. 비주얼 스튜디오를 열지않고도 빌드를 할 수 있고, Nightly Build(Daily)도 가능하며, 서비스 형태로 몇 시간 혹은 몇 분마다 빌드를 하는 것도 가능하다. 그리고 컴파일뿐만 아니라 여러가지 부가적인 작업들도 실행을 시킬 수가 있다. 밑의 예제처럼 NUnit 테스트, FxCop을 이용한 코드 리뷰 등도 가능하다.


  1. <?xml version="1.0"?>
  2. <!- 프로젝트 이름 지정 -->
  3. <project name="AntTest" default="build">
  4. <target name="build">
  5.   <echo message="Building AntTest ...."/>
  6.   <tstamp property="build.date" pattern="yyyyMMdd" verbose="true" />
  7.   <echo message="{build.date}"/>
  8.    <!-- 프레임워크 버전을 지정 -->
  9.    <available type="FrameworkSDK" resource="net-1.1" property="net-1.1.frameworksdk.present" />
  10.    <!-- 빌드할 솔루션을 지정. 이 솔루션을 컴파일하게 된다 -->
  11.    <solution configuration="debug" solutionfile="AntTestSln\AntTestSln.sln">
  12.    <!-- 웹 프로젝트는 웹경로를 지정해야 한다-->
  13.    <webmap>
  14.    <map url="http://localhost/AntTestWeb/AntTestWeb.csproj" path="..\WEB\AntTestWeb.csproj" />
  15.    </webmap>
  16.    </solution>
  17.     <!-- NUnit 을 사용해서 유닛테스트를 수행한다. 물론 NUnit 테스트용으로 만든 어셈블리에 한해서 -->
  18.     <nunit2>
  19.     <formatter type="Xml" usefile="true" extension=".xml" outputdir="TEST\results" />
  20.     <test assemblyname="TEST\bin\debug\TEST.dll"/>
  21.     </nunit2>
  22.     <!-- FxCop 으로 코드리뷰를 수행한다 -->
  23.     <exec program="FxCopCmd" commandline="/file:COM\bin\Debug\com.dll /out:review\review.xml" />
  24.     <!-- NUnit Report를 사용해서 NUnit 유닛테스트 결과를 리포트에 기록한다 -->
  25.     <nunit2report out="TEST\results\NUnitReport(No-Frame).html" >
  26.     <fileset>
  27.         <includes name="TEST\results\TEST.dll-results.xml" />
  28.     </fileset>
  29.     <summaries>
  30.         <includes name="TEST\bin\debug\TEST.xml" />
  31.     </summaries>
  32.     </nunit2report>
  33.     <mail
  34.               from="buildmaster@project.com"
  35.               tolist="buildmaster@project.com"
  36.               subject="{build.date} 빌드가 완료되었습니다"
  37.               mailhost="mail.project.com">
  38.     </mail>
  39. </target>
  40. </project>
 
Posted by kkongchi