달력

22025  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

2005년 7월 27일 새벽에 있었던 일..

주차를 하려면 연락처를 적어놔~~!!!

 

7월 중순에 아버지가 돌아가셨다.

그래서 오마니가 외로워 하셔서.. 저녁마다 거의 가서 같이 저녁 먹고 , TV 보고..

우스개 소리 하면서 자정 가까이 되어서 집에 온다.

 

내가 사는 집은 면목동인데, 이 동네는 다세대 주택이 거의 대부분이며 골목도 굉장히 좁은 편이다.

딱히 주차할 곳도 없고, 거주자 우선 주차제는 신청 해두 탈락될 확률이 굉장히 높기 때문에,

그냥 집앞에 어찌저찌 낑겨넣고 해서 주차를 한다.

 

상계동 오마니 집에서 밤 12시 정도에 와보니 다른차가 주차되어 있다.

분명 이 골목에서 몇번 봤던 차인데 누구네집 차인지는 모르겠다.

전화번호도 없고 밤도 늦고 해서, 근처 빈 자리에 세워놨다.

빈자리라고 하면 남의집 앞인데 ㅎㅎ

그리고 앞유리창 근처에 전화번호 큼직하게 적어놓고 새벽 5시 정도까지 이것저것 하며

전화오면 차빼줘야겠다~ 라고 생각하고, 새벽에 담배피면서 동네도 한바퀴 돌았다.

 

아침(한 8시 됐나?) 에 문앞에 나가보니 집앞에 주차된 차가 없어졌다.

그래서 내 차를 다시 대문앞으로 옮겨놓고 밥을 먹는데, 문자 메세지가 왔다.

앞으로 차대면 연락을 받으란다. ㅡㅡ;  밤 늦게라도 자기네 들어오니까 차 대지 말란다 ㅡㅡ;

 

그럼 새벽에 전화를 하던지 하시지.. 차 빼주잖아.

 

문자메세지 받고 기분이 나빴던 거는 ...

그집 사람들은 내가 차대는 곳에 가끔 연락처도 없이 자기네 친척이나 손님들 차를

대놓고, 내가 그집에 문 두드리고 가서 XXXX 번호 차가 이집 차냐~ 물어보면 아니란다 .

그래서 대충 차 세워놓고 문앞에서 담배피고 차주인 기다리면 그집에서 나온다.

 

아까 여기차 아니냐고 물어봤을때 아니라면서요. 라고 물으면 어물어물 얼버무린다.

이것때문에 5월달에 불법주차 딱지까지 띠었는데..

이웃 사촌 맞는지 참 ㅡㅡ;

 

앞집 아줌마는 내가 차 빼라고 했더니 바닥에 주저앉아 울면서 자기차는 어디다 대냐구

통곡을 하더니만..

참 골때리는 동네임에는 분명하다. ㅎㅎ

 

하여간에 연락처 안적어놓은 갤로퍼 숏바디 아저씨!!

다른데 가서 그러지 마시고... 연락처좀 적고 다닙시다.

'이것저것 > 낙서장' 카테고리의 다른 글

10000 히트 이벤트!!!  (2) 2005.07.29
문좀 고쳐주세요 ㅡㅡ;  (0) 2005.07.28
컴백...  (2) 2005.07.22
포맷;;  (0) 2005.07.15
신고해부렀다~  (0) 2005.07.14
Posted by tornado
|

원본글 : http://www.microsoft.com/korea/msdn/library/ko-kr/dev/dotnet/entsvcperf.aspx

죄다 깨지냐 ㅡㅡ;

 

 

.NET Enterprise Services 성능

Richard Turner, 프로그램 관리자, XML Enterprise Services
Larry Buerk, 프로그램 관리자, XML Enterprise Services
Dave Driver, 소프트웨어 디자인 엔지니어, XML Enterprise Services

Microsoft Corporation

2004년 3월

적용 대상:
   COM+ 구성 요소
   Microsoft .NET Enterprise Services

요약: 다른 활성화 및 호출 패턴에 적용될 때의 원시 COM+ 및 .NET Enterprise Services 구성 요소 성능을 확인합니다. .NET Enterprise Services 구성 요소를 C++의 COM+ 구성 요소처럼 빨리 실행하기 위한 지침과 함께 고성능 .NET Enterprise Service 구성 요소를 만드는 데 도움이 되는 주요 권장 사항을 살펴봅니다(45페이지/인쇄 페이지 기준).

관련 EnterpriseServicesPerf.exe 코드 샘플을 다운로드하십시오.

목차

소개
관리되는 코드로 마이그레이션해야 하는 이유
코드 변경 정도 지정
.NET Enterprise Services에 COM+ 연결
.NET Enterprise Services와 COM+ 성능 비교
테스트 결과 및 분석
결론
부록 1: 성능 권장 사항
부록 2: "Indigo" 및 .NET의 동향
부록 3: 분산 트랜잭션이 성능에 미치는 영향
부록 4: 참고 자료
부록 5: 성능 테스트 소스 코드
부록 6: 테스트 결과

소개

COM+ 코드를 "원시" Visual C++ 또는 Visual Basic 6에서 관리되는 .NET Enterprise Services 구성 요소로 이동할 것을 고려 중인 개발자는 다음과 같은 고민 사항이 있을 수 있습니다.

  • 왜 관리되는 코드로 전환해야 하는가?
  • 코드를 얼마나 변경해야 하는가?
  • Enterprise Services 구성 요소는 어떻게 수행되는가?
  • COM+ 및 .NET Enterprise Services가 제시하는 미래는 어떠한가?

이 문서에서는 특히 성능에 대한 질문을 위주로 위 주제를 다룰 것입니다. 이러한 주제에 대한 자세한 내용은 부록 4: 참고 자료에 있는 리소스를 참조하십시오.

이 문서는 COM+ 구성 요소를 개발하고 코드를 .NET Enterprise Services로 마이그레이션할 것을 고려 중인 개발자와 설계자를 대상으로 합니다.

관리되는 코드로 마이그레이션해야 하는 이유

개발자가 .NET에서 코드를 개발해야 하는 이유는 여러 가지입니다. 다음은 코드 개발의 몇 가지 이점입니다.

  • 향상된 개발자 생산성: 개발자들은 종종 .NET을 사용하여 개발할 때 작성해야 하는 "통로 코드"가 훨씬 적기 때문에 응용 프로그램 논리를 작성하는 데 더 많은 신경을 쓸 수 있습니다. 또한 대부분의 개발자는 .NET에서 제공하는 명확하고 일관되게 구성된 풍부한 리소스 라이브러리 덕분에 다른 기술과 비교하여 훨씬 빨리 배울 수 있습니다.
  • 향상된 코드 안정성 및 보안: 개발자는 원시 코드보다는 .NET을 사용할 때 안정적이고 보안된 코드를 더욱 쉽게 작성할 수 있습니다. 그 이유는 코드 액세스 보안 및 CLR(공용 언어 런타임) 같은 기능 때문입니다. 이러한 기능은 NET 코드가 다른 실행 중인 코드에 의도하지 않은 영향을 미치는 것을 방지하고 해커가 .NET 코드를 사용하여 환경을 방해하거나 제어할 수 있는 기회를 줄이는 데 도움이 됩니다.
  • 향상된 성능 및 확장성: 개발자는 .NET으로 마이그레이션할 때 코드의 성능과 확장성이 향상되는 것을 알 수 있습니다. 모든 .NET 언어가 다중 스레딩 같은 기능을 지원하고 활용하기 때문입니다.
  • XCOPY 배포: 대부분의 .NET 응용 프로그램에서는 필요한 파일을 하드 드라이브의 폴더로 복사하고 공유 구성 요소를 운영 체제에 선택적으로 등록하기만 하면 배포가 이루어집니다. 이는 다른 응용 프로그램에서 일반적으로 사용하는 것보다 훨씬 명쾌한 배포 전략입니다.

개발자가 .NET으로 마이그레이션하기를 원하는 10가지 이유에 대해서는 Top 10 Reasons for Developers to Use the .NET Framework 1.1 을 참조하십시오.

.NET은 시스템 관리자에게도 이점을 제공합니다. 관리자가 .NET으로 이동하기를 원하는 10가지 이유가 기록된 목록을 보려면 Top 10 Reasons for Systems Administrators to Use the .NET Framework 1.1 을 참조하십시오.

일반 C++ 코드를 관리되는 C++로 마이그레이션하는 방법에 대한 소개는 Managed Extensions for C++ Migration Guide의 Introduction to Wrapping C++ Classes 를 참조하십시오.

코드 변경 정도 지정

대부분의 경우 COM+ 코드를 .NET Enterprise Services에 연결하려면 COM+ 구성 요소가 어떠한 언어로 개발되었는지를 비롯한 다수의 요인에 따라 몇 가지 수동 작업이 필요합니다. 예를 들어, Visual Basic 6 개발자는 앞으로 나올 Visual Studio 2005의 도구에서 서브루틴 및 함수의 본문을 수정하지 않고도 클래스 정의 및 메서드 서명을 변환할 수 있는 몇 가지 지원을 받게 됩니다(다른 변환된 메서드에 대한 호출은 제외).

C++ 개발자는 COM+ 코드에서 .NET 코드로 변환하는 작업을 대부분 수동으로 수행해야 하지만, 대부분의 통로가 ATL(Active Template Library) 같은 클래스 라이브러리 대신 CLR에 구현되기 때문에 변환된 코드가 좀 더 간결해지는 것을 확인할 수 있습니다. C++ 개발자는 응용 프로그램을 연결할 언어를 선택할 수도 있습니다. 예를 들어, 기존 코드 기반을 최대한 활용하기 위해 관리되는 C++를 선택하거나, 더욱 간결한 코드를 위해 C#을 선택할 수 있습니다.

.NET Enterprise Services에 COM+ 구성 요소 연결

기존 COM+ 코드를 Visual Basic 6 및 Visual C++ 같은 원시 프로그래밍 언어와 도구로부터 마이그레이션하는 개발자는 .NET 코드로 완벽하게 변환하기 위해 몇 가지 기존 코드를 수정해야 합니다. 여기에 동반되는 작업 양은 사용할 수 있는 기존 코드 기반 및 도구에 따라 다릅니다. 다음 표에는 코드를 .NET으로 마이그레이션할 때 고려할 옵션이 요약되어 있습니다.

변환하기 전의 언어변환한 후의 언어코드 변환 도구 사용 가능 여부필요한 코드 변환 작업
Visual Basic 6Visual Basic .NET예(Visual Studio 2005)대부분의 Visual Basic 6 코드는 Visual Basic .NET에 직접 연결됩니다. Visual Studio 2005의 Visual Basic 6 코드 마이그레이션 도구는 대부분의 클래스와 메서드 선언 및 형식을 Visual Basic .NET 구문으로 변환합니다.
Visual C++Visual C++ .NET아니요C++ .NET은 특히 원시 코드와 .NET 사이에서 상호 작동하는 코드를 작성하는 데 유용합니다.
Visual C++Visual C#아니요C# 구문은 많은 면에서 C++와 비슷합니다. 변환을 수행하려면 개발자의 특정 작업이 필요합니다.

.NET 특성

COM+ 구성 요소를 설치한 후에는 구성 요소 서비스 스냅인 도구를 사용하여 수동으로 구성하거나 스크립트 또는 코드를 통해 구성해야 합니다.

예를 들어, 구성 요소에 트랜잭션 지원이 필요하다고 표시하고 각 구성 요소의 AddSale() 메서드가 오류 없이 완료될 경우 트랜잭션을 자동으로 커밋하도록 지정하는 상황을 가정합니다. 그러기 위해서는 구성 요소 및 필요한 메서드의 속성을 COM+ 구성 요소 서비스 관리 콘솔에서 수동으로 구성해야 합니다.

  1. 구성 요소 서비스 관리 콘솔을 열고 올바른 응용 프로그램 및 구성 요소를 탐색합니다.

  2. 이 구성 요소의 속성을 열고 트랜잭션 탭을 클릭한 다음 필수를 클릭합니다.

  3. 확인을 클릭하고 구성 요소 탐색기를 통해 ATLPerfTests 개체의 AddSale() 메서드를 찾습니다.

  4. AddSale() 메서드를 마우스 오른쪽 단추로 클릭하고 메서드의 속성을 연 다음 이 메서드가 반환하면 자동으로 이 개체 비활성화 확인란을 선택합니다.

관리자는 일반적으로 보안 및 ID 설정 같은 배포 지향 설정이나 역할 구성원 및 재활용 같은 런타임 지향 설정을 구성합니다. 개발자는 트랜잭션 지원과 같은 구성 요소의 개발 지향 기능을 구성합니다. 그러나 COM+에서는 개발자가 코드 내에서 구성 요소의 구성 방법을 지정하기가 어렵습니다. Visual Basic 개발자는 구성 요소에 필요한 트랜잭션 지원을 어느 정도 지정할 수 있지만 C++ 개발자는 그렇지 못합니다. COM+ 구성 요소를 안정적이면서 반복적으로 설치하기 위해서는 스크립트, 설치 관리자 응용 프로그램 또는 설치 지침을 작성해야 합니다.

.NET은 개발자가 구성 요소의 코드 내에서 구성 요소에 필요한 서비스와 해당 서비스의 구성 방법을 지정할 수 있도록 함으로써 구성 요소 구성을 단순화합니다. 구성 요소가 설치되면 플랫폼에서 구성 설정을 자동으로 구성하지만, 이러한 구성 설정은 설치 후에 변경할 수 있습니다.

COM+에서는 설치 후에 구성 설정을 변경할 수 있기 때문에 이러한 속성을 다수 변경할 때는 매우 주의를 기울여야 합니다. 예를 들어, 보안 설정을 변경하면 개체를 인스턴스화하고 개체의 메서드를 호출할 수 있는지의 권한 지정에 영향을 미칠 수 있습니다. 반면에 트랜잭션 지원을 제거하면 구성 요소가 안정적이지 못하고 예측 불가능해질 수 있으며 구성 요소의 데이터가 손실되거나 손상될 수도 있습니다.

개발자는 특성(C# 및 C++에서는 [attribute]와 같이 대괄호 안에 표시되고, Visual Basic .NET에서는 <attribute>와 같이 꺾쇠괄호 안에 표시됨)을 사용하여 어셈블리, 응용 프로그램, 구성 요소 또는 메서드의 요소를 구성합니다. 예를 들어, 아래 코드에서는 SimpleTest 구성 요소에 트랜잭션이 필요하며, AddSale() 메서드가 오류 없이 완료될 경우 트랜잭션이 자동으로 완료된다는 것을 보여줍니다.

C#

 [Transaction(TransactionOption.RequiresNew)] public class SimpleTest: ServicedComponent { ... [AutoComplete] public void AddSale(int orderNumber, int storeID, int titleID, int qty) { ... } ... }

Visual Basic .NET

<Transaction(TransactionOption.RequiresNew)> _ Public Class VBTestObject : Inherits ServicedComponent ... <AutoComplete> _ Public Function Sum(ByVal number1 As Integer, ByVal number2 As Integer) As Integer ... End Function ... End Class

다음 표에는 Enterprise Services 구성 요소에 적용할 수 있는 주로 사용되는 특성이 들어 있고, 설치 후에 특성을 안전하게 변경할 수 있는지 여부가 표시되어 있습니다.

특성범위기본 소유자실행 중에 안전하게 수정 가능한지의 여부
ApplicationAccessControl 어셈블리개발자아니요.
개발자가 응용 프로그램의 보안 방법에 대한 하드 종속성 또는 묵시적 종속성을 사용하여 코드를 작성했을 수 있습니다.

액세스 제어를 낮추면 시스템 보안이 손상될 수 있습니다.

ApplicationActivation 어셈블리관리자예. 그러나 주의해야 합니다.
라이브러리 또는 서비스로 변경하거나 이로부터 변경하면 성능에 영향을 미칠 수 있으며 대기 중인 구성 요소가 손상될 수 있습니다.
ApplicationID 어셈블리개발자예. 그러나 주의해야 합니다.
이 특성을 변경하면 하드 코딩된 구성 요소 등록 도구에 영향을 미칠 수 있습니다.
ApplicationName 어셈블리개발자예. 그러나 주의해야 합니다.
이 특성을 변경하면 하드 코딩된 구성 요소 등록 도구에 영향을 미칠 수 있습니다.
ApplicationQueuing 어셈블리개발자아니요.
AutoComplete 메서드개발자아니요.
아래의 "Transaction"을 참조하십시오.
ComponentAccessControl 클래스개발자아니요.
개발자는 구성 요소의 보안 방법에 대한 하드 종속성 또는 묵시적 종속성을 사용하여 코드를 작성했을 수 있습니다.

액세스 제어를 낮추면 시스템 보안이 손상될 수 있습니다.

ConstructionEnabled 클래스관리자예.
생성자 문자열을 변경할 수는 있지만, 설정/해제 상태를 전환하지는 마십시오.
Description 어셈블리
클래스
메서드
인터페이스
관리자예.
EventTrackingEnabled 클래스관리자예.
InterfaceQueuing 클래스
인터페이스
개발자아니요.
JustInTimeActivation 클래스개발자아니요.
MustRunInClientContext 클래스개발자아니요.
구성 요소가 클라이언트의 컨텍스트와 호환되지 않을 수도 있습니다.
ObjectPooling 클래스개발자예. 풀 설정은 변경할 수 있습니다.
구성 요소가 손상될 수 있기 때문에 개체 풀링 설정/해제 상태를 전환하지는 마십시오.
PrivateComponent 클래스개발자아니요.
이 구성 요소를 공개적으로 호출할 수 없도록 개발자가 특별히 지정한 것입니다. 구성 요소가 알 수 없는 사용 패턴을 지원하는지에 대한 테스트를 받지 않았을 수도 있습니다. 공개되는 경우 심각한 보안 위협을 초래할 수 있습니다.
SecurityRole - 역할 이름  어셈블리
클래스
인터페이스
개발자아니요. 역할을 제거하지 마십시오.
개발자가 지정된 역할에 대한 명시적 종속성 또는 역할 존재에 대한 묵시적 예외를 사용하여 코드를 작성했을 수 있습니다.
SecurityRole - 역할 구성원  어셈블리
클래스
인터페이스
관리자예. 그러나 주의해야 합니다.
액세스 제어를 너무 광범위하게 공개하면 시스템의 보안이 손상되고, 너무 제한되게 공개하면 액세스가 과도하게 제한될 수 있습니다.
Synchronization  클래스개발자아니요.
Transaction 클래스개발자아니요.
구성 요소의 트랜잭션 지원을 수정하면 시스템의 안정성과 무결성이 손상될 수 있습니다.

위 표는 구성 요소 개발자가 기본적으로 소유하는 구성 요소와 관리자가 기본적으로 소유하는 구성 요소도 보여 줍니다. 코드에 미치는 영향을 자세히 알고 있는 경우가 아니라면 개발자의 설정을 변경하지 않는 것이 좋습니다. 개발자가 지정한 보안 관련 특성을 관리자가 변경할 수는 있지만, 이 경우에는 구성 요소 또는 응용 프로그램에 대한 액세스를 충분히 제한하되 너무 과도하게 제한하지는 않도록 주의를 기울여 보안을 구성해야 합니다.

특성을 통해 개발자는 자신의 구성 요소에 대한 구성 요구 사항을 간단하고 효율적으로 지정하면서 설치 후에 관리자가 구성 설정을 변경할 수 있도록 합니다. Enterprise Services가 제공하는 특성에 대한 자세한 내용은 .NET Framework Class Library 를 참조하십시오.

.NET Enterprise Services와 COM+ 성능 비교

Enterprise Services의 성능을 COM+와 비교하여 측정하기 위해 다음 언어로 구성 요소를 만들었습니다.

  • Visual C++ .NET 및 ATL COM+
  • Visual Basic 6 COM+
  • C# 및 .NET Framework 1.1 Enterprise Services
  • Visual Basic .NET 및 .NET Framework 1.1 Enterprise Services

각 구성 요소에는 두 개의 공용 메서드가 포함되어 있습니다.

  • Sum(): 이 간단한 메서드는 두 숫자를 합해 디스크 또는 데이터베이스 액세스 작업을 수행하지 않는 간단한 작업을 시뮬레이트합니다.
  • AddSale(): 이 일반적인 메서드는 트랜잭션되며, 테이블에 레코드를 삽입하고 반환 전에 트랜잭션을 완료하는 개인 메서드인 InsertSale()을 호출합니다. 이 메서드는 일반적인 비즈니스 응용 프로그램 작업을 수행하는 "실제" 메서드의 성능 특징을 보여 줍니다.

그 다음에는 각 구성 요소에 대해 다음 테스트를 수행한 테스트 프로그램을 만들었습니다.

  • 반복적인 만들기/호출/릴리스: 이 테스트는 개체를 만들고 호출하고 릴리스하는 과정을 반복적으로 수행합니다.
  • 만들기/반복 호출/릴리스: 이 테스트는 개체를 인스턴스화하여 수천 번 호출한 다음 마지막에 개체를 릴리스합니다.

테스트 프로그램에서는 각 구성 요소에 대해 두 가지 테스트를 모두 실행했으며 결과를 쉼표로 분리된 파일에 작성하는 고해상도 타이머를 사용하여 각 테스트를 수행하는 데 걸린 시간을 측정했습니다. 이 파일의 결과를 Microsoft Excel로 가져와서 분석했습니다. 각 구성 요소에 대한 코드 목록은 부록 5: 성능 테스트 소스 코드를 참조하십시오.

테스트는 다음 표에 표시된 구성으로 설정된 컴퓨터에서 실행되었습니다.

 컴퓨터 1: 서버 컴퓨터컴퓨터 2: 클라이언트 컴퓨터/단일 컴퓨터
CPUDual Pentium 4 Xeon 3.06GHzDual Pentium 4 Xeon 2.8GHz
RAM1GB1GB
디스크로컬 SCSI로컬 SCSI
네트워크기가비트 이더넷기가비트 이더넷
OS 및 .NETWindows Server™ 2003
.NET Framework 1.1
Windows Server 2003
.NET Framework 1.1

다른 하드웨어에서 테스트 응용 프로그램을 실행할 때 나타나는 특정 결과는 아래에 보고된 결과는 물론, 서로 간에도 다를 수 있습니다. 그러나 각 결과는 여기에 소개된 결과와 비례해야 합니다.

테스트 결과 및 분석

다음 절에서는 이전에 논의한 코드에 대해 실행한 성능 테스트의 결과를 분석합니다. 이 결과는 위에 나열된 하드웨어와 소프트웨어에서 테스트를 실행하여 얻은 것입니다. 모든 결과의 목록은 부록 6: 테스트 결과에 포함되어 있습니다.

결과를 보여 주는 다음 차트에서 차트 막대 길이가 길거나 숫자가 클수록 성능이 뛰어난 것입니다.

개체 활성화 및 삭제 성능

먼저 C++ 및 Visual Basic 6을 사용하여 개발한 원시 COM+ 구성 요소의 성능을 통해 COM+ 인프라가 어떻게 수행되는지를 살펴보겠습니다. 아래 차트는 개체 만들기, 간단한 메서드 호출 및 개체 릴리스를 반복적으로 수행함으로써 얻은 초당 호출 수를 보여 줍니다.

MTS(Microsoft Transaction Server) 1.0의 원래 디자이너는 이와 비슷한 데이터를 보고서 호출을 배달하는 데 필요한 인프라, 즉 프록시, DCOM(또는 프로세스간) 채널, 스텁 및 컨텍스트를 설정함으로써 프로세스 간 및 컴퓨터 간 활성화 시간에 큰 영향을 미칠 수 있다는 것을 깨달았습니다. 이 점이 다음을 수행하는 JIT(Just In Time) 활성화를 디자인하게 된 기본적인 동기였습니다.

  • 서버 구성 요소가 반환 이전에 SetComplete() 또는 SetAbort()를 호출하여 자체 수명 주기를 제어할 수 있도록 합니다.
  • 여러 메서드 호출을 사용하여 DCOM 통로를 설정하는 부담을 줄입니다.

다음 차트는 JIT 활성화를 활용하는 수정된 테스트를 단일 개체를 만들고 두 숫자를 합하는 간단한 메서드를 반복적으로 호출한 다음 마지막에 개체를 릴리스하는 방법으로 실행할 경우 발생하는 상황을 보여 줍니다.

이 결과는 JIT 활성화를 사용할 때 초당 호출 수 면에서 성능이 크게 향상되는 것을 보여 줍니다. JIT 활성화 및 Visual Basic 6을 사용하면 JIT 활성화를 사용하지 않는 C++보다 거의 33배 빠른 결과를 얻을 수 있습니다. JIT가 활성화된 Visual Basic 6에서는 초당 호출 수가 약 8600인 반면 JIT가 활성화되지 않은 Visual C++에서는 초당 호출 수가 약 261입니다.

작업을 수행하는 데 필요한 통로를 설정한 이후 컴퓨터 간 호출을 수행하면 네트워크가 성능에 큰 영향을 미치게 됩니다. 이 경우 Visual Basic 6 및 C++는 성능이 거의 비슷하지만, 그래도 Visual Basic 6가 C++보다 88% 빨리 수행됩니다.

Enterprise Services에서는 필요한 통로를 설정하는 추가 작업이 수행됩니다. 특히 개체를 생성하고 릴리스하기 위한 추가 호출이 필요합니다. 따라서 개체에서 아무런 작업을 수행하지 않고 단순히 개체를 만들었다 제거하는 경우를 비교할 때 이러한 추가 왕복 부담이 성능 비교에 큰 영향을 미치게 됩니다. Visual Studio 2005에서는 Enterprise Services가 향상되어 이러한 활성화 왕복 중 하나가 제거되었기 때문에 "활성화/단일 호출/릴리스" 패턴을 사용할 때 .NET Framework 1.1과 비교하여 성능이 20-30% 향상됩니다. 그러나 가능하면 이러한 패턴은 사용하지 않는 것이 좋습니다.

JIT 활성화를 사용할 때 C++ 및 Visual Basic 6의 성능이 비슷하다는 것을 고려하면 C# 및 Visual Basic .NET을 사용하는 Enterprise Services도 대략 같은 성능을 보일 것으로 예상할 수 있습니다. 아래 그림은 간단한 메서드를 호출하는 위 테스트를 실행한 결과를 보여 줍니다.

이 데이터는 단순히 두 정수를 합하고, 개체의 컨텍스트에 SetComplete()를 호출하고, 결과를 반환하는 간단한 메서드에 대해 수행한 초당 호출 수를 보여 줍니다. 개체를 활성화하고 릴리스하는 부담은 거의 사라졌지만 버퍼를 마샬링하고 호출 스택으로 변환하는 등의 작업으로 인해 호출을 수행하는 부담은 아직 남아 있습니다.

이처럼 매우 간단한 메서드에서도 프로세스 간 호출의 경우 Enterprise Services는 Visual Basic 6과 성능이 거의 비슷합니다. 컴퓨터간에 호출할 경우에는 모든 언어의 성능이 거의 비슷합니다.

그러나 일반적인 비즈니스 응용 프로그램은 메서드에서 이보다 더 복잡한 작업을 수행합니다. 다음 차트는 일반적인 메서드를 호출하여 분산 트랜잭션 내에서 데이터베이스 연결을 열고 간단한 SQL 문을 실행하는 동일한 응용 프로그램을 네 가지 언어로 작성했을 때 각각의 상대적인 성능을 보여 줍니다.

앞의 결과는 메서드 내에서 많은 작업을 수행할 경우 모든 언어의 결과가 실험 오차 범위 내에서 동등하다는 것을 보여 줍니다. ADO를 사용하는 C++ 및 Visual Basic 6을 통해 작성한 COM+ 원시 응용 프로그램은 Enterprise Services를 사용하는 C# 또는 Visual Basic .NET 응용 프로그램과 동일한 속도로 수행됩니다. 프로세스 간 작업을 실행하거나 컴퓨터 간 작업을 실행하는 경우 성능 면에서는 거의 차이가 없습니다.

결과 요약

위 결과는 구성 요소를 최대한 효율적으로 수행하는 데 있어서 JIT 활성화 및 "만들기/반복 호출/릴리스" 패턴이 매우 중요하다는 것을 보여 줍니다.

결론

코드를 .NET으로 마이그레이션하는 것이 유리한 몇 가지 주요 이유를 설명했습니다. 다른 활성화 및 호출 패턴에 적용될 때의 원시 COM+ 및 .NET Enterprise Services 구성 요소 성능에 대해서도 논의했습니다. 또한 지침을 따라가면서 .NET Enterprise Services 구성 요소가 C++ COM+ 구성 요소만큼 빨리 실행된다는 것을 보여 주었습니다. 부록 1: 성능 권장 사항에는 고성능 .NET Enterprise Service 구성 요소를 만드는 데 도움이 되는 주요 권장 사항이 나와 있습니다.

여기에 설명된 기술을 일관되게 적용하면 기존 COM+ 코드를 .NET Enterprise Service 구성 요소로 바로 변환하고 아무런 성능 저하 없이 .NET Framework의 사용성, 보안 및 개발자 생산성 등의 이점을 누릴 수 있습니다.

지금 COM+ 구성 요소를 Enterprise Services 구성 요소로 변환해 놓으면 나중에 코드를 "Indigo"로 더욱 쉽게 마이그레이션할 수 있다는 점도 중요합니다. 부록 2: "Indigo" 및 .NET의 동향에서는 이 주제에 대해 간략히 논의합니다.

부록 1: 성능 권장 사항

다음 절에서는 높은 수준의 성능을 제공하는 빠른 COM+ 및 Enterprise Services 구성 요소를 만드는 방법에 대한 팁과 안내를 제공합니다. 대부분의 제안은 .NET Enterprise Services 구성 요소와 원시 COM+ 구성 요소에 동일하게 적용됩니다.

해당하는 경우 개체 풀링 및 JIT 활성화 사용

위의 테스트 결과가 보여주듯이 메서드 호출이 구성 요소 활성화보다 빠르며 관리되지 않는 구성 요소의 활성화가 Enterprise Services 구성 요소의 활성화보다 빠릅니다. 따라서 구성 요소 기반 응용 프로그램의 속도를 최대한 높이려면 코드에서 구성 요소 활성화 및 삭제의 수를 최소화하는 것이 중요합니다.

COM+에서는 개체 활성화를 최소화할 수 있는 두 가지 서비스를 제공합니다.

  1. 첫 번째는 앞에서 설명했듯이 호출자가 개체에 대한 활성 참조를 보관하고 있는 동안 해당 개체를 원활하게 비활성화할 수 있는 COM+ 서비스인 JIT(Just-in-time) 활성화입니다. 클라이언트가 개체에 메서드를 호출하기만 하면 COM+가 개체의 할당을 동적으로 관리하여 요청을 처리합니다.
  2. 두 번째는 해당 형식의 구성 요소 인스턴스를 요청하는 클라이언트가 바로 사용할 수 있도록 개체를 풀에서 활성 상태로 유지하는 개체 풀링입니다. COM+는 풀을 자동으로 관리하며, 개체 활성화 정보를 처리하고 사용자가 지정한 기준(예: 풀 크기)에 따라 다시 사용합니다.

풀링된 구성 요소 및 JIT 활성화된 구성 요소에 대한 참조를 보관하고 다시 사용함으로써 구성 요소 활성화 및 삭제를 최소화하고 높은 수준의 성능을 얻을 수 있습니다.

COM+ JIT 활성화 및 개체 풀링에 대한 자세한 내용은 Platform SDK: COM+ (Component Services) 설명서 를 참조하십시오.

왕복 회피

COM+ 구성 요소의 성능을 최적화하려면 호출자와 구성 요소 사이에 수행되는 프로세스 간 또는 컴퓨터 간 호출의 수를 최소화하는 것이 중요합니다. COM+ 구성 요소에서 만들어진 모든 메서드는 프로세스 간 호출 전환은 물론 컴퓨터 간 호출 전환도 초래하며, 매번 전환할 때마다 시간이 걸립니다. 따라서 COM+ 개체에서 만들어지는 메서드 호출을 최소한으로 유지하는 것이 필수적입니다. 그러기 위해 단일 호출에서 최대한 많은 작업을 수행하는 메서드를 사용하여 COM+ 구성 요소를 디자인하는 것도 좋은 방법입니다. 단, 이 경우에는 순수 아키텍처에서 변형된 구성 요소도 디자인해야 합니다.

COM+ 서비스 사용 최적화

COM+가 중요한 서비스를 다수 제공하기는 하지만 이러한 서비스를 현명하게 사용하는 것이 중요합니다. COM+가 구성 요소에 필요한 서비스를 제공하는 경우에는 대개 이 서비스가 가장 높은 성능을 제공하므로 반드시 사용하도록 하십시오. 그러나 서비스가 필요하지 않은 경우에는 구성 요소가 불필요한 작업을 수행하여 실행 속도도 느려질 수 있으므로 해당 서비스를 사용할 필요가 없습니다.

COM 마샬링 가능 매개 변수 사용

호출자가 데이터를 전달할 때 사용하는 매개 변수를 Enterprise Services 구성 요소의 메서드가 받아들이는 경우 다음과 같이 COM과 .NET 사이에 쉽게 마샬링할 수 있는 형식을 사용할 것을 매우 강력히 제안합니다.

  • Boolean
  • Byte, SByte
  • Char
  • DateTime
  • Decimal
  • Single, Double
  • Guid
  • Int16, UInt16, Int32, UInt32, Int64, UInt64
  • IntPtr, UIntPtr
  • String

이러한 형식만 사용하고 다른 복잡한 형식(예: 구조 또는 배열)은 전달하지 않으면 .NET serializer가 호출 처리 스택을 최적화하고 호출을 유선(RPC의 경우) 또는 가상 유선(LRPC의 경우)에 일렬로 직렬화할 수 있습니다. 그러면 호출이 더욱 빨리 실행됩니다. 그러나 메서드에 복잡한 형식이 필요한 경우에는 코드가 일반 DCOM 호출 스택을 통해 호출되므로 추가 처리 과정이 발생합니다.

파이널라이저 사용하지 않기

Enterprise Services 구성 요소에서 파이널라이저(C# 및 C++의 ~Classname() 소멸자)를 구현하지 마십시오. 파이널라이제이션은 가비지 수집기의 단일 스레드 작업입니다. Enterprise 구성 요소를 파이널라이제이션할 경우 완료되는 데 상당한 시간이 걸리므로 가비지 수집기 성능이 저하됩니다. 가비지 수집기 엔진이 실행 중인 동안에는 응용 프로그램에서 다른 작업을 수행할 수 없으므로 가비지 수집기가 완료되는 데 오랜 시간이 걸리면 전체 응용 프로그램의 성능이 저하됩니다.

대신 개체에서 Dispose(bool)을 재정의하고 Dispose(true)가 호출될 때 파이널라이제이션 형식 작업을 수행하는 것을 고려해 보십시오. 또한 이러한 종료 코드를 최대한 정돈되고, 안전하고, 간단하게 유지하도록 하십시오.

단일 스레드 COM+ 구성 요소 만들지 않기

여러 스레드의 동시 액세스를 지원하지 않는 개체는 STA(단일 스레드 아파트) 기능을 지원하는 것으로 표시되어 있습니다. 여러 스레드가 같은 인스턴스에 동시 액세스할 수 있도록 지원하는 구성 요소는 MTA(다중 스레드 아파트) 인식으로 표시되어 있습니다.

.NET Enterprise Services 구성 요소는 항상 STA 및 MTA를 모두 지원하는 것으로 표시되어 있기 때문에 더 이상 이 논의에 포함시키지 않겠습니다.

모든 Visual Basic 6 COM+ 구성 요소는 STA입니다. C++ COM+ 개발자는 구성 요소를 STA, MTA 또는 둘 다로 표시할 수 있습니다.

STA COM+ 구성 요소의 잠재적인 문제는 개체가 단일 스레드에서만 실행될 수 있으므로 해당 스레드가 개체의 메서드를 실행하는 유일한 스레드라는 것입니다. 이 직렬화를 통해 개발자는 STA 구성 요소를 더욱 쉽게 작성할 수 있지만, 도메인 간 마샬링이 종종 필요해서 성능이 저하되고 STA에서 한 스레드만 계속 실행됨으로 인해 확장성이 떨어지는 것은 피할 수 없습니다.

가능하면 STA 구성 요소를 만들거나 사용하지 않을 것을 제안합니다. 특히 확장성이 중요한 곳에서는 더욱 그렇습니다. 구성 요소가 다른 COM+ 구성 요소를 호출하는 경우 특히 STA 스레딩을 피해야 합니다. 이러한 호출에는 종종 스레드 전환이 필요한데, 스레드 전환은 해당 아파트에 있는 다른 모든 COM+ 구성 요소를 차단합니다.

설상가상으로 가비지 수집기의 파이널라이저도 개체를 소유한 STA 스레드를 호출할 때 차단됩니다. 그러면 파이널라이제이션 프로세스가 단일 스레드에 직렬화되며, 이는 이전 주제에서 설명했듯이 시스템 성능을 크게 저하시킬 수 있습니다.

부록 2: "Indigo" 및 .NET의 동향

Microsoft에서 현재 개발 중인 연결된 응용 프로그램을 위한 새로운 플랫폼, 코드 이름 "Indigo"에 대해 들어 보셨을 것입니다. 그렇다면 "Indigo"란 과연 어떤 제품일까요?

"Indigo"는 서비스 지향 연결 응용 프로그램을 위한 Microsoft의 전략적 기술 플랫폼으로서, 로스앤젤레스에서 개최된 2003 PDC(Professional Developers Conference)에서 소개되었습니다.

"Indigo"는 다음 기술의 개념, 특징 및 기능을 하나의 기술 스택으로 통합합니다.

  • COM
  • DCOM
  • COM+/Enterprise Services
  • ASMX/Web Services
  • .NET Remoting
  • 향상된 웹 서비스
  • MSMQ의 요소

"Indigo"는 서비스를 호출자에게 노출하는 데 필요한 프로토콜 및 전송으로부터 서비스의 개념을 추상화하는 다계층 플랫폼입니다. 최대한 많은 시스템과 상호 작동하기 위해 "Indigo"는 HTTP, TCP 및 IPC를 통한 고급 웹 서비스(WS-*)를 완벽하게 지원합니다. 현재 Microsoft는 코드 이름이 "Longhorn"인 Microsoft Windows의 출시 시기에 맞춰 "Indigo"를 배포할 예정입니다. Windows XP 및 Windows Server 2003에 대한 "Indigo" 지원도 함께 배포될 것입니다.

향후 "Indigo"가 발표된다고 하니 .NET Enterprise Services(또는 이 경우 ASMX 및 Remoting) 같은 기존 기술이 오늘날의 연결된 응용 프로그램을 개발하는 데 아직 유효한 것인지 걱정할 수도 있습니다. ASMX & WSE, Enterprise Services, Remoting 및 MSMQ는 오늘날의 엔터프라이즈 수준 솔루션에 가장 적합한 기술입니다. 적절하게 사용하면 "Indigo"가 릴리스되고 널리 사용될 때까지 훌륭한 응용 프로그램 개발 플랫폼을 제공해 줄 것입니다.

.NET을 사용하여 새 응용 프로그램을 작성하고 기존 응용 프로그램을 .NET으로 마이그레이션하면 향상된 보안, 안정성, 관리 및 확장성의 혜택을 누릴 수 있습니다. 또한 "Indigo"로 업그레이드하는 것이 원시 코드보다 훨씬 쉬워질 것입니다. 응용 프로그램의 "Indigo" 업그레이드를 준비하는 방법과 기존 기술을 사용하여 "Indigo"와 상호 작동하는 방법에 대한 자세한 내용은 나중에 MSDN을 참조하십시오.

"Indigo"에 대한 자세한 소개는 MSDN Magazine 기사, Code Name Indigo: A Guide to Developing and Running Connected Systems with Indigo 를 참조하십시오. 이 기사에 제공된 아키텍처 개요를 통해 이후의 Microsoft 응용 프로그램 플랫폼을 미리 살펴볼 수 있습니다.

"Indigo"에 대한 일반적인 내용은 Microsoft "Indigo" Frequently Asked Questions 를 참조하십시오.

부록 3: 분산 트랜잭션이 성능에 미치는 영향

위 테스트를 진행하면서 "COM+ 분산 트랜잭션이 이러한 구성 요소에 얼마나 많은 영향을 미칠까?"라는 질문이 생길 수도 있습니다. 이 질문의 답을 찾기 위해 각 구성 요소에 대해 COM+에서 "트랜잭션 필요" 설정을 끄고 테스트를 다시 실행해 보았습니다. 그 결과는 다음 차트에 표시되어 있습니다.

위 차트에서 볼 수 있듯이 COM+ 트랜잭션 지원이 없는 구성 요소의 성능과 트랜잭션이 켜져 있는 구성 요소의 성능은 거의 동일합니다. 이 결과는 테스트에서 COM+ 트랜잭션의 영향을 무시해도 상관없다는 것을 분명하게 보여 줍니다.

부록 4: 참고 자료

Upgrading Microsoft Visual Basic 6.0 to Microsoft Visual Basic .NET 

Visual Basic 6.0 응용 프로그램을 Visual Basic .NET으로 업그레이드하는 내용을 다루며 프로그래밍 팁, 요령 및 단계별 코드 비교 내용을 함께 제공합니다.

Programming with Managed Extensions for Microsoft Visual C++ .NET 

Visual C++ .NET 2003에 맞춰 업데이트된 이 책은 개발자를 위해 컴파일러의 새 기능과 언어에 대한 링커 확장을 심층적이고 전문적으로 다룹니다.

.NET Enterprise Services and COM+ 1.5 Architecture 

Microsoft .NET 및 Enterprise Services가 어떻게 조화를 이루는지 보여 주고 COM+/Enterprise Services 구성 요소를 빌드, 제어, 관리 및 보안하는 방법을 설명합니다.

.NET Framework Developer Center의 Performance 페이지 

고성능 코드를 작성하는 방법과 발생하는 문제를 진단하는 방법에 대해 심도있게 다루는 여러 링크와 리소스가 제공됩니다.

Performance Tips and Tricks in .NET Applications 

.NET 응용 프로그램이 제대로 수행되도록 하기 위한 팁과 힌트를 모아 놓았습니다.

Writing Faster Managed Code: Know What Things Cost 

.NET 코드에서 다양한 작업이 시스템에 어떤 부담을 주는지 자세히 분석한 내용입니다.

Garbage Collector Basics and Performance Hints 

가비지 수집기의 작동 방법, 가비지 수집기가 코드에 미치는 영향, 가비지 수집의 영향을 최소화하도록 코드를 작성하는 방법 등에 대해 설명합니다.

Performance Considerations for Run-Time Technologies in the .NET Framework 

가비지 수집 및 메모리 사용, JIT, 스레딩, .NET Remoting, 보안 등의 주제를 다룹니다.

부록 5: 성능 테스트 소스 코드

C++\ATL 구성 요소

헤더 파일

// ATLPerfTestObj.h : CATLPerfTestObj의 선언 #pragma once #include "ATLPerfTests.h" #include "resource.h" // 주 기호입니다. #include <comsvcs.h> #include <mtxattr.h> // CATLPerfTestObj class ATL_NO_VTABLE CATLPerfTestObj : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CATLPerfTestObj, &CLSID_ATLPerfTestObj>, public IDispatchImpl<IPerfTestObj, &IID_IPerfTestObj, &LIBID_ATLPerfTestsLib, /*wMajor =*/ 1, /*wMinor =*/ 0> { public : CATLPerfTestObj() { } DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct() { return S_OK; } void FinalRelease() { } DECLARE_REGISTRY_RESOURCEID(IDR_ATLPERFTESTOBJ) DECLARE_NOT_AGGREGATABLE(CATLPerfTestObj) BEGIN_COM_MAP(CATLPerfTestObj) COM_INTERFACE_ENTRY(IPerfTestObj) COM_INTERFACE_ENTRY(IDispatch) END_COM_MAP() // IPerfTestObj public : STDMETHOD(Sum)(LONG number1, LONG number2, LONG* result); STDMETHOD(AddSale)(LONG orderNumber, LONG storeID, LONG titleID, LONG qty); private : HRESULT InsertSaleRecord(LONG orderNumber, LONG storeID, LONG titleID, LONG qty); }; OBJECT_ENTRY_AUTO(__uuidof(ATLPerfTestObj), CATLPerfTestObj)(참고: 프로그래머 코멘트는 샘플 프로그램 파일에는 영문으로 제공되며 기사에는 설명을 위해 번역문으로 제공됩니다.)

소스 파일

// ATLPerfTestObj.cpp : CATLPerfTestObj의 구현 #include "stdafx.h" #include "ATLPerfTestObj.h" #include ".\atlperftestobj.h" #include "atlstr.h" #import "c:\Program Files\Common Files\System\ADO\msado15.dll" rename_namespace("ADO") rename("EOF", "EndOfFile") using namespace ADO; // CATLPerfTestObj // 여기에서 간단한 작업을 수행하여 간단한 메서드를 시뮬레이트합니다. STDMETHODIMP CATLPerfTestObj::Sum(LONG number1, LONG number2, LONG* result) { // 개체 컨텍스트를 가져옵니다. IObjectContext* ctx = NULL; HRESULT hr = CoGetObjectContext(IID_IObjectContext, (LPVOID*)&ctx); if(SUCCEEDED(hr)) { // 계산을 수행합니다. *result = number1 + number2; // 트랜잭션을 커밋합니다. ctx->SetComplete(); ctx->Release(); } return hr; } STDMETHODIMP CATLPerfTestObj::AddSale(LONG orderNumber, LONG storeID, LONG titleID, LONG qty) { // COM+ 개체 컨텍스트를 가져옵니다. IObjectContext* ctx = NULL; HRESULT hr = CoGetObjectContext(IID_IObjectContext, (LPVOID*)&ctx); // COM+ 컨텍스트가 있는지 확인합니다. if(SUCCEEDED(hr)) { // 기본 작업은 중단하는 것입니다. ctx->SetAbort(); // 데이터베이스에 레코드를 삽입합니다. hr = InsertSaleRecord(orderNumber, storeID, titleID, qty); // 삽입 작업의 결과를 확인합니다. if(SUCCEEDED(hr)) { // 모든 것이 올바르면 트랜잭션을 완료로 // 표시합니다. ctx->SetComplete(); } // 컨텍스트 포인터를 정리합니다. ctx->Release(); ctx = NULL; } // 전체 결과를 반환합니다. 삽입 작업이 오류 없이 // 실행되는 경우에만 결과가 S_OK입니다. return hr; } // 데이터베이스에 판매 레코드를 삽입합니다. HRESULT CATLPerfTestObj::InsertSaleRecord(LONG orderNumber, LONG storeID, LONG titleID, LONG qty) { // 기본 결과는 실패를 반환하는 것입니다. HRESULT hr = E_FAIL; try { // 서버에서 실행할 SQL을 포맷합니다. CString str; str.Format("insert into sales (order_no, store_id, \ title_id, order_date, qty) values (%i, %i, %i, \ GetDate(), %i)", orderNumber, storeID, titleID, qty); // 데이터베이스에 대한 연결을 엽니다. _ConnectionPtr cn("ADODB.Connection"); cn->Open("Provider=SQLOLEDB;SERVER=localhost;Integrated \ Security=SSPI;DATABASE=ESPERFTESTDB", "", "", adConnectUnspecified); // 명령을 실행합니다. _variant_t rs; rs = cn->Execute(_bstr_t(str), &rs, adCmdText); hr = S_OK; // 연결을 명시적으로 닫습니다. cn->Close(); } catch(_com_error e) { // 문제가 있으면 오류가 반환됩니다. hr = e.Error(); } return hr; }

Visual Basic 6 구성 요소

Private Function IPerfTestObj_Sum(ByVal nA As Long, ByVal nB As Long) As Long IPerfTestObj_Sum = nA + nB GetObjectContext.SetComplete End Function Sub IPerfTestObj_AddSale(ByVal OrderNumber As Long, ByVal StoreID As Long, ByVal TitleID As Long, ByVal Qty As Long) ' 기본값은 오류가 throw될 경우 중단하는 것입니다. GetObjectContext.SetAbort Call InsertSaleRecord(OrderNumber, StoreID, TitleID, Qty) ' 실패하지 않았기 때문에 트랜잭션을 완료할 수 있습니다. GetObjectContext.SetComplete End Sub Sub InsertSaleRecord(ByVal OrderNumber As Long, ByVal StoreID As Long, ByVal TitleID As Long, ByVal Qty As Long) Dim command As String connDB.Open ("Provider=SQLOLEDB;SERVER=localhost;Integrated" + _ "Security=SSPI;DATABASE=ESPERFTESTDB") command = "insert into sales (store_id, order_no, order_date, qty, title_id) values (" & StoreID & ", " & OrderNumber & ", GetDate(), " & Qty & ", " & TitleID & ")" connDB.Execute (command) connDB.Close End Sub 

C# 구성 요소

using System; using System.EnterpriseServices; using System.Data.SqlClient; using System.Reflection; using System.Runtime.InteropServices; using perftestsinterop; [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyKeyFile("..\\..\\sign.key")] [assembly: ApplicationName("PerfTest")] [assembly: ApplicationActivation(ActivationOption.Server)] [assembly: ApplicationAccessControl(false)] namespace CSPerfTests { [Guid("0BA5534E-8544-42e2-A909-3265105BEA09")] [Transaction(TransactionOption.Required)] public class CSPerfTestObj : ServicedComponent, IPerfTestObj { public CSPerfTestObj() { } // 여기에서 간단한 작업을 수행하여 간단한 메서드를 // 시뮬레이트합니다. public int Sum(int number1, int number2) { int result = 0; // 계산을 수행합니다. result = number1 + number2; // 트랜잭션을 커밋합니다. ContextUtil.SetComplete(); return result; } // 트랜잭션에 새 판매 항목을 추가합니다. public void AddSale(int orderNumber, int storeID, int titleID, int qty) { try { // 데이터베이스에 레코드를 삽입합니다. InsertSaleRecord(orderNumber, storeID, titleID, qty); // 모든 것이 올바르면 트랜잭션을 완료로 // 표시합니다. ContextUtil.SetComplete(); } catch(Exception) { ContextUtil.SetAbort(); throw; } } // 데이터베이스에 판매 레코
            




                    
Posted by tornado
|
6. GC 관련 Parameter


GC관련 설정값을 보기전에 앞서서 ?X와 ?XX 옵션에 대해서 먼저 언급하자. 이 옵션들은 표준 옵션이 아니라, 벤더별 JVM에서 따로 제공하는 옵션이기 때문에, 예고 없이 변경되거나 없어질 수 있기 때문에, 사용전에 미리 JVM 벤더 홈페이지를 통해서 검증한다음에 사용해야한다.

1) 전체 Heap Size 조정 옵션

전체 Heap size는 ?ms와 ?mx로 Heap 사이즈의 영역을 조정할 수 있다. 예를 들어 ?ms512m ?mx 1024m로 설정하면 JVM은 전체 Heap size를 application의 상황에 따라서 512m~1024m byte 사이에서 사용하게 된다. 그림2의 Total heap size

메모리가 모자를때는 heap을 늘리고, 남을때는 heap을 줄이는 heap growing과 shirinking 작업을 수행하는데, 메모리 변화량이 큰 애플리케이션이 아니라면 이 min heap size와 max heap size는 동일하게 설정하는 것이 좋다. 일반적으로 1GB까지의 Heap을 설정하는데에는 문제가 없으나, 1GB가 넘는 대용량 메모리를 설정하고자 할 경우에는 별도의 JVM 옵션이 필요한 경우가 있기때문에 미리 자료를 참고할 필요가 있다.

※ IBM AIX JVM의 경우
%export LDR_CNTRL=MAXDATA=0x10000000
%java -Xms1500m -Xmx1500m MyApplication

2) Perm size 조정 옵션

Perm Size는 앞에서도 설명했듯이, Java Application 자체(Java class etc..)가 로딩되는 영역이다. J2EE application의 경우에는 application 자체의 크기가 큰 편에 속하기 때문에, Default로 설정된 Perm Size로는 application class가 loading되기에 모자른 경우가 대부분이기 때문에, WAS start초기나, 가동 초기에 Out Of Memory 에러를 유발하는 경우가 많다.

PermSize는 -XX:MaxPermSize=128m 식으로 지정할 수 있다.
일반적으로 WAS에서 PermSize는 64~256m 사이가 적절하다.

3) New 영역과 Old 영역의 조정New 영역은 ?XX:NewRatio=2 에 의해서 조정이 된다.
NewRatio Old/New Size의 값이다. 전체 Heap Size가 768일때, NewRatio=2이면 New영역이 256m, Old 영역이 512m 로 설정이 된다.
JVM 1.4.X에서는 ?XX:NewSize=128m 옵션을 이용해서 직접 New 영역의 크기를 지정하는 것이 가능하다.

4) Survivor 영역 조정 옵션
-XX:SurvivorRatio=64 (eden/survivor 의 비율) :64이면 eden 이 128m일때, survivor영역은 2m가 된다.

5) -server와 ?client 옵션
JVM에는 일반적으로 server와 client 두가지 옵션을 제공한다.
결론만 말하면 server 옵션은 WAS와 같은 Server환경에 최적화된 옵션이고, client옵션은 워드프로세서와 같은 client application에 최적화된 옵션이다. 그냥 언뜻 보기에는 단순한 옵션 하나로보일 수 있지만, 내부에서 돌아가는 hotspot compiler에 대한 최적화 방법과 메모리 구조자체가 아예 틀리다.

○ -server 옵션

server용 application에 최적화된 옵션이다. Server application은 boot up 시간 보다는 user에 대한 response time이 중요하고, 많은 사용자가 동시에 사용하기 때문에 session등의 user data를 다루는게 일반적이다. 그래서 server 옵션으로 제공되는 hotspot compiler는 java application을 최적화 해서 빠른 response time을 내는데 집중되어 있다.

또한 메모리 모델 역시, 서버의 경우에는 특정 사용자가 서버 운영시간동안 계속 서버를 사용하는게 아니기 때문에 (Login하고, 사용한 후에는 Logout되기 때문에..) 사용자에 관련된 객체들이 오래 지속되는 경우가 드물다. 그래서 상대적으로 Old영역이 작고 New 영역이 크게 배정된다. <그림 7. 참조 >

○ -client 옵션

client application은 워드프로세서 처럼 혼자 사용하는 application이다. 그래서 client application은 response time보다는 빨리 기동되는데에 최적화가 되어 있다. 또한대부분의 client application을 구성하는 object는GUI Component와 같이 application이 종료될때까지 남아있는 object의 비중이 높기 때문에 상대적으로 Old 영역의 비율이 높다.


<그림 7. ?server와 ?client 옵션에 따른 JVM Old와 New영역>


이 두옵션은 가장 간단한 옵션이지만, JVM의 최적화에 아주 큰부분을 차지하고 있는 옵션이기 때문에, 반드시 Application의 성격에 맞춰서 적용하기 바란다.
(※ 참고로, SUN JVM은 default가 client, HPJVM는 default가 server로 세팅되어 있다.)

○ GC 방식에 대한 옵션

GC 방식에 대한 옵션은 앞에서도 설명했지만, 일반적인 GC방식이외에, Concurrent GC,Parallel GC,Inceremental GC와 같이 추가적인 GC Algorithm이 존재한다. 옵션과 내용은 앞장에서 설명한 “다양한 GC알고리즘” 을 참고하기 바란다.


7.JVM GC 튜닝


그러면 이제부터 지금까지 설명한 내용을 기반으로 실제로 JVM 튜닝을 어떻게 하는지 알아보도록 하자.

STEP 1. Application의 종류와 튜닝목표값을 결정한다.

JVM 튜닝을 하기위해서 가장 중요한것은 JVM 튜닝의 목표를 설정하는것이다. 메모리를 적게 쓰는것이 목표인지, GC 횟수를 줄이는것이 목표인지, GC에 소요되는시간이 목표인지, Application의 성능(Throughput or response time) 향상인지를 먼저 정의한후에. 그 목표치에 근접하도록 JVM Parameter를 조정하는것이 필요하다.

STEP 2. Heap size와 Perm size를 설정한다.

-ms와 ?mx 옵션을 이용해서 Heap Size를 정한다. 일반적으로 server application인 경우에는 ms와 mx 사이즈를 같게 하는것이 Memory의 growing과 shrinking에 의한 불필요한 로드를 막을 수 있어서 권장할만하다.

ms와mx사이즈를 다르게 하는 경우는 Application의 시간대별 memory 사용량이 급격하게 변화가 있는 Application에 효과적이다.
PermSize는 JVM vendor에 따라 다소 차이가 있으나 일반적으로 16m정도이다. Client application의 경우에는 문제가 없을 수 있지만, J2EE Server Application의 경우 64~128m 사이로 사용이 된다.

Heap Size와 Perm Size는 아래 과정을 통해서 적정 수치를 얻어가야한다.

STEP 3. 테스트 & 로그 분석.

JVM Option에 GC 로그를 수집하기 위한 ?verbosegc 옵션을 적용한다. (HP의 경우 ?Xverbosegc 옵션을 적용한다.)

LoadRunner나 MS Strest(무료로 MS社의 홈페이지에서 다운로드 받을 수 있다.)와 같은 Strest Test툴을 통해서 Application에 Strest를 줘서. 그 log를 수집한다. 튜닝에서 있어서 가장 중요한것은 목표산정이지만, 그만큼이나 중요한것은 실제 Tuning한 Parameter가 Application에 어떤 영향을 주는지를 테스트하는 방법이 매우 중요하다. 그런 의미에서 적절한 Strest Tool의 선정과, Strest Test 시나리오는 정확한 Tuning을 위해서 매우 중요한 요인이다.

○ Perm size 조정
아래 그림8.은 HP JVM에서 ?Xverbosegc 옵션으로 수집한 GC log를 HP Jtune을 통해서 graph로 나타낸 그래프이다. 그림을 보면 Application이 startup되었을때 Perm 영역이 40m에서. 시간이 지난후에도 50m 이하로 유지되는것을 볼 수 있다. 특별하게 동적 classloading등이 수십m byte가 일어나지 않는등의 큰 변화요인이 없을때, 이 application의 적정 Perm 영역은 64m로 판단할 수 있다.


<그림 8. GC 결과중 Perm 영역 그래프>


○ GC Time 수행 시간 분석

다음은 GC에 걸린 시간을 분석해보자. 앞에 강좌 내용에서도 설명햇듯이. GC Tuning에서 중요한 부분중 하나가 GC에 소요되는 시간 특히 Full GC 시간이다.

지금부터 볼 Log는 모社의 물류 시스템의 WAS 시스템 GC Log이다. HP JVM을 사용하며, -server ?ms512m ?mx512m 옵션으로 기동되는 시스템이다.

그림 9를 보면 Peak 시간 (첫번째 동그라미) 14시간동안에 Full GC(동그란점)가 7번일어난것을 볼 수 있다. 각각에 걸린 시간은2.5~6sec 사이이다.
여기서 STEP 1.에서 설정한 AP Tuning의 목표치를 참고해야하는데.

Full GC가 길게 일어나서 Full GC에 수행되는 시간을 줄이고자 한다면 Old 영역을 줄이면 Full GC가 일어나는 횟수는 늘어나고, 반대로 Full GC가 일어나는 시간을 줄어들것이다.

반대로 Full GC가 일어나는 횟수가 많다면, Old 영역을 늘려주면 Full GC가 일어나는 횟수는 상대적으로 줄어들것이고 반대로 Full GC 수행시간이 늘어날 것이다.

특히 Server Application의 경우Full GC가 일어날때는 JVM자체가 멈춰버리기 때문에, 그림 9의 instance는 14시간동안 총 7번 시스템이 멈추고, 그때마다 2.5~6sec가량 시스템이 response를 못하는 상태가 된것이다. 그래서 멈춘 시간이 고객이 납득할만한 시간인지를 판단해야 하고, 거기에 적절한 Tuning을 해야한다.

Server Application에서 Full GC를 적게일어나게하고, Full GC 시간을 양쪽다 줄이기 위해서는 Old영역을 적게한후에, 여러개의 Instance를 동시에 뛰어서 Load Balancing을 해주면, Load가 분산되기 때문에 Full GC가 일어나는 횟수가 줄어들테고, Old 영역을 줄였기 때문에, Full GC에 드는 시간도 줄어들것이다. 또한 각각의 FullGC가 일어나는동안 하나의 서버 instance가 멈춰져 있어도, Load Balancing이 되는 다른 서버가 response를 하고 있기때문에, Full GC로 인한 Application이 멈추는것에 의한 영향을 최소화할 수 있다.


<그림 9. GC 소요시간>


데이타에 따라서 GC Tuning을 진행한후에는 다시 Strest Test를 진행해서 응답시간과 TPS(Throughput Per Second)를 체크해서 어떤 변화를 주었는지를 반드시 체크해봐야한다.


<그림 10. GC후의 Old 영역>


그림 10은 GC후에 Old 영역의 메모리 변화량을 나타낸다.

금요일 업무시간에 메모리 사용량이 올라가다가. 주말에가서 완만한 곡선을 그리는것을 볼 수 있다. 월요일 근무시간에 메모리 사용량이 매우 많고, 화요일에도 어느정도 메모리 사용량이 있는것을 볼 수 있다. 월요일에 메모리 사용량이 많은것을 볼때, 이 시스템의 사용자들이 월요일에 시스템 사용량이 많을 수 있다고 생각할 수 있고, 또는 다른 주의 로그를 분석해봤을때 이 주만 월요일 사용량이 많았다면, 특별한 요인이나 Application 변경등이 있었는지를 고려해봐야할것이다.

이 그래프만을 봤을때 Full GC가 일어난후에도 월요일 근무시간을 보면 Old 영역이 180M를 유지하고 있는것을 볼 수 있다. 이 시스템의 Full GC후의 Old영역은 80M~180M를 유지하는것을 볼 수 있다. 그래서 이 시스템은 최소 180M이상의 Old 영역을 필요로하는것으로 판단할 수 있다.

STEP 4. Parameter 변경.
STEP 3에서 구한 각 영역의 허용 범위를 기준으로 Old영역과 New 영역을 적절하게 조절한다.
PermSize와 New영역의 배분 (Eden,Survivor)영역등을 조정한다.
PermSize는 대부분 Log에서 명확하게 나타나기 때문에, 크게 조정이 필요가 없고 New영역내의 Eden과 Survivor는 거의 조정하지 않는다. 가장 중요한것은 Old영역과 New 영역의 비율을 어떻게 조정하는가가 관건이다.

이 비율을 결정하면서, STEP1에서 세운 튜닝 목표에 따라서 JVM의 GC Algorithm을 적용한다. GC Algorithm을 결정하는 기본적인 판단 내용은 아래와 같다.



이렇게 Parameter를 변경하면서 테스트를 진행하고, 다시 변경하고 테스트를 진행하는 과정을 거쳐서 최적의 Parameter와 GC Algorithm을 찾아내는것이 JVM의 메모리 튜닝의 이상적인 절차이다.


지금까지 JVM의 메모리 구조와 GC 모델 그리고 GC 튜닝에 대해서 알아보았다.

정리하자면 GC 튜닝은 Application의 구조나 성격 그리고, 사용자의 이용 Pattern에 따라서 크게 좌우 되기때문에, 얼마만큼의 Parameter를 많이 아느냐 보다는 얼마만큼의 테스트와 로그를 통해서 목표 값에 접근하느냐가 가장 중요하다
Posted by tornado
|

 

<select name="language">
    <optgroup label="선택하세요" style="color:orange"></optgroup>
    <optgroup label="Web" style="color:green">
        <option>ASP</option>
        <option>PHP</option>
        <option>JSP</option>
    </optgroup>
    <optgroup label="Window" style="color:blue">
        <option>VB</option>
        <option>C++</option>
        <option>JAVA</option>
    </optgroup>
</select>

'DHTML' 카테고리의 다른 글

[js] 블로그 읽어오기 ㅡㅡ; 허접함..  (0) 2005.08.11
[펌] autoHTML / smartRmHTML / listAllLinks Function  (0) 2005.08.09
참고할 만한 곳  (0) 2005.07.13
스크립트 잘만든곳...  (0) 2005.07.04
브라우저별로 테스트할때...  (0) 2005.07.01
Posted by tornado
|

컴백...

이것저것/낙서장 2005. 7. 22. 09:48

지난 일주일간 많은 일이 있었다..

아버님 하늘나라 가셨고.. 못뵈던 어르신 부터... 연락 안되던 친구들 만나보고..

참 바쁘게 한주가 지나갔다.

아직 실감은 안나지만..

앞으로.. 낚시좀 자제하고... 주어진 임무와.. 앞으로의 발전을 위해 매진할 생각이다.

 

7월 23 일부터 9일간 휴가다..

그동안 개인 홈피 하나 만들어 놔야겠다.

 

 

'이것저것 > 낙서장' 카테고리의 다른 글

문좀 고쳐주세요 ㅡㅡ;  (0) 2005.07.28
세상 사는 이야기??  (0) 2005.07.28
포맷;;  (0) 2005.07.15
신고해부렀다~  (0) 2005.07.14
tortoise svn 사용할때.. 이거 아쉽다.. ㅡㅡ;  (0) 2005.07.13
Posted by tornado
|

포맷;;

이것저것/낙서장 2005. 7. 15. 11:57

중국사이트 몇군데 다니다가... DLL 을 설치 안하면 다운로드가 안된단다.

그래서 그거 깔구.. 닷넷관련 PDF 받았다..

으흐흐.... 피시가 점점 맛이 가기 시작하면서..

탐색기 한번 띠우는데 3분 이상 걸린다.

 

바로 포맷..

 

'이것저것 > 낙서장' 카테고리의 다른 글

세상 사는 이야기??  (0) 2005.07.28
컴백...  (2) 2005.07.22
신고해부렀다~  (0) 2005.07.14
tortoise svn 사용할때.. 이거 아쉽다.. ㅡㅡ;  (0) 2005.07.13
ace framework ,....  (0) 2005.07.07
Posted by tornado
|

지갑 분실관계로 인해.. 주민증 면허증 다 잊어버림 ㅡㅡ;

맨정신에 잊어버려서 더 열받음

 

주민등록증 신청하고 재발급 날짜는 7월 11 일 이니 그때 오라고 함.

신청 날짜는 6월 29일 오전 9시.

 

7월 12일 오전 9시 동사무소 방문.

 

나 : "주민증 주세요"

직원 : "안나왔는데요 -.-"

나 : "왜 안나왔지요?"

직원 : "7월 4일부로 주민등록증 재발급은 매주 수요일에 한번만 합니다"

나 : "저는 7월 4일 이전에 신청했잖아요"

직원 : "미안합니다~ 그래도 어쩔수 없어요"

나 : "아니.. 7월 4일날 바뀌었으면 7월 4일부터 적용해야지요"

직원 : "미안합니다. 그래도 어쩔수 없어요"

나 : " 뉘미.. ..."

 

7월 13일 수요일 오전 9시 동사무소 방문

나 : " 주민증 주세요"

직원 : "(-.-); 주민증 안나왔는데요"

나 : " 왜 안나와요!! 수요일날 발급한다며!!"

직원 : " 지금 구청에 가지러 갔대요"

나 : " 뉘미... 일좀 똑바로 하쇼.."

직원 : "(-.-;;) 가족이 대신 좀 받으러 오시죠"

나 : "장난하쇼... 울 아부지 식물인간됐소.. 다들 병간호 하느라 못와!!"

직원 : "죄송..."

나 : " 책임자 나오라 하쇼"

직원 : "(허걱) 죄송합니다.. 죄송합니다"

나 : (맘약해져서 그냥 감)

 

7월 14일 목요일 오전 9시 동사무소 방문

 

나 : "주민증 주쇼"

직원 : "(-.-) 여기써욧!"

 

얼라? 인사도 안하고?? 완전 개 싸가지네?

 

"책임자 나오쇼"

 

다른 직원들이 봐달라는 식으로 미안합니다만 연발 ㅡㅡ;

개늠 시키덜...

 

그리고 회사 출근..

면허증은 신청 30분만에 발급받았구만..

뉘미.. 뭣같은것들이 증말..

 

회사와서 하두 열받아서...

민원 고충처리 위원회에 그인간덜 이름하고 해서 접수함 ㅡㅡ;

 

내 주변에도 공무원 많지만.. 니들같은 개쉑은 없다 ㅡㅡ;

 

포장마차두 오늘 장사할꺼는 미리 준비한다 이 개늠들아.

수요일 일할꺼를 수요일에 준비하믄 되냐 .....

시말서 한장 쓰고 정신좀 차려라 -.-

 

아.. 열받어

 

'이것저것 > 낙서장' 카테고리의 다른 글

컴백...  (2) 2005.07.22
포맷;;  (0) 2005.07.15
tortoise svn 사용할때.. 이거 아쉽다.. ㅡㅡ;  (0) 2005.07.13
ace framework ,....  (0) 2005.07.07
9000 히트 이벤트!!!  (3) 2005.07.06
Posted by tornado
|

출처 : http://network.hanbitbook.co.kr/view.php?bi_id=1090

 

저자: 한동훈 / traxacun@gmail.com

[지난기사보기]
ASP.NET 가이드 4. 통합 예외처리
ASP.NET 가이드 3. UI 향상 및 사용자 템플릿 만들기
ASP.NET 가이드 2. 숫자/문자 입력 텍스트 박스 만들기
ASP.NET 가이드 1. 자바 스크립트 사용하기


프로젝트 진행시에 겪게되는 어려움 중에 하나는 코드 문서화에 대한 것이다. 거의 모든 회사들은 일정이 빠듯하다고 여기며 코딩이 끝난 구현물을 토대로 문서화를 만들게 된다.

[코딩후 문서화]는 여러가지 문제점을 갖고 있다. 개발자가 구현시에 고려했던 내용들을 문서화하는 시점에서는 잊혀지기 때문에 문서화에서 누락되는 경우가 발생한다. 나중에 문제가 발생한 경우 문서만으로 문제를 해결하지 못하고, 원 코드 제작자에게 문의하여 해결하게 되는 것도 이런 탓이다.

코딩후 문서화가 갖는 다른 문제는 개발 문서, 사용자 설명서, 사용자 시나리오 문서를 구분하지 못한채 문서화되는 경우가 많다는 점이다. 대체로 개발 문서에서 코드만 제거하고 사용자 설명서가 되는 경우도 많다.

여기서는 코딩을 하면서 바로바로 문서화할 수 있는 것을 도와주는 NDoc에 대해 살펴볼 것이다. Visual Studio .NET에는 [도구] → [주석 웹페이지 빌드]를 통해 XML 문서화된 내용을 도움말로 빌드해주는 기능을 갖고 있지만 부족한 부분이 많다. 웹 페이지 뿐만 아니라 윈도우 도움말(.CHM, .HLP)까지 함께 빌드해 줄 수 있는 NDoc 사용법을 살펴볼 것이다.

오픈소스 문서화 도구중에 DoxyGen은 C#의 XML 주석을 이용하지 않고 자체 태그를 사용하고 있기 때문에 .NET 코드 문서화에는 사용하지 않기 때문에 다루지 않는다. 관심있는 분은 DoxyGen 사이트를 참고하기 바란다.

XML 주석 작성하기

.NET에서는 XML 문서화를 지원하고 있으며 사용할 수 있는 태그목록은 다음과 같다. 보다 자세한 사항은
Recommeded Tags for Documentation Comments를 참고하기 바란다.




[표1] XML 문서화 태그 목록


XML 태그 이름에서 알 수 있는 것처럼 대충의 사용 용도는 알 수 있으며 Visual Studio.NET에서는 해당 태그를 입력하면 자동으로 태그의 형식을 입력해준다. Visual Studio .NET이 완성해주는 XML 문서화 태그 입력이 부족하다고 여겨진다면 GhostDoc을 사용하자. 영어로 문서화를 해야하는 경우엔 유용하게 사용할 수 있다. 다음은 BasePage에 필자가 BR 태그를 개행문자로 변환하기 위해 만든 메서드와 그에 대한 주석이다.




[그림1] XML 문서화 사용 예


SUMMARY 태그는 해당 클래스나 메서드의 내용을 요약해서 보여주기 위해 사용한다. REMARKS 태그는 그에 대한 간단한 설명을 덧붙이기 위해 사용하며 EXAMPLE 태그는 예제설명이 시작이라는 것을 나타내며, 예제 코드에 대한 제목 역할을 한다. CODE 태그는 다른 사람이 참고할 수 있는 예제코드를 작성하는 부분이다. PARAM 태그는 각 메서드의 매개변수에 대한 설명이며, RETURNS는 반환값에 대한 주석을 작성할 수 있다. 이렇게 작성된 코드는 컴파일시에 XML 부분만 별도로 작성되는데 이를 위해서는 프로젝트 설정을 해야한다. 명령줄에서 csc.exe를 사용하여 직접 컴파일시에는 /doc 옵션으로 지정할 수 있다.

XML 문서화 옵션 지정

Visual Studio.NET에서 [프로젝트] - [BasePage 속성(P)]를 클릭한다.




[그림2] XML 문서화 설정하기


[XML 문서 파일]에 그림2와 같이 입력한다. 이제 [빌드] - [솔루션 다시 빌드]를 선택하면 전체 프로젝트를 다시 빌드하면서 XML 문서를 생성한다. 개발환경에서 빌드시에는 소스 코드 전체를 빌드하는 대신 수정한 부분만 다시 빌드한다. 이러한 부분 빌드시에는 XML 문서 파일이 갱신되지 않기 때문에 위와 같이 다시 빌드를 해야한다.
이렇게 생성한 XML 문서 파일과 NDoc을 이용해서 문서파일을 자동으로 생성해보자.

NDoc 문서화

NDoc을 받아서 설치했다고 가정하고 NDoc 사용법을 바로 살펴보자.




[그림3] NDoc 시작화면


[Add] 버튼을 클릭한다.




[그림4] 어셈블리와 XML 문서 추가


BasePage.dll과 앞에서 생성한 XML 문서, Mona.Web.UI.BasePage.xml을 추가하고 [OK]를 클릭한다.

다시 NDoc 메인화면으로 돌아오면 화면 중간에 다양한 속성을 설정할 수 있는 부분이 있다. 이 설정을 제대로 해야만 한글이 깨지지 않고 문서화가 된다. NDoc에서 설정할 필요가 있는 속성들만 다음에 나열하였다.




[표2] NDoc 속성 설정


언어 설정을 위해서는 SdkDocLanguage와 LangID를 변경하면 되며, DocumentInherited로 되어 있는 속성들은 기본값이 True인데 False로 변경하였다. 그렇지 않으면 .NET Framework의 기본 멤버들이 모두 문서화되어 여러분이 작성한 메서드보다 프레임워크에서 상속한 메서드에 대한 설명이 더 많아지게 된다. 실제로, .NET Framework 멤버에 대한 설명은 MSDN을 참고해야할 부분이지 여러분이 작성할 문서에서 참고할 것은 아니다.

Internals와 Privates는 클래스내의 내부 데이터나 메서드에 대한 참조용으로 문서화를 하기 위해 True로 하였다. 만약, 다른 업체를 위한 외부용 문서라면 이 부분은 False로 설정하기 바란다.

NDoc 프로젝트도 BasePage 프로젝트 디렉터리와 같은 곳에 저장하고, VS.NET에서도 BasePage.ndoc 파일을 추가한다. ndoc 확장자를 NDoc 프로그램과 연결해두면 언제든지 VS.NET에서 NDoc을 불러서 설정할 수 있다. 여기까지 설정을 모두 마쳤으면 NDoc에서 [Documentation] - [Build]를 선택해서 문서를 빌드한다. 최종 컴파일이 끝나면 doc 디렉터리에 생성된 .CHM 도움말을 볼 수 있으며, NDoc에서는 [Documentation] - [View]를 선택해서 볼 수 있다.




[그림5] BasePage 도움말


[그림5]에서 볼 수 있는 것처럼 Br2Nl 메서드에 대한 설명이 잘 정리되어 나타나는 것을 볼 수 있다. [그림1]과 [그림5]를 비교하면 XML 문서태그의 어떤 부분이 어떤식으로 보여지는지 알 수 있다.
NDoc에서 문서화 옵션을 HTML & CHM으로 선택했기 때문에 웹 사이트에 바로 올려놓고 참조할 수 있는 HTML 페이지도 doc 디렉터리에 작성되어 있다. doc\index.html 파일을 열어보면 HTML 형식의 도움말이 어떻게 작성되었는지 살펴볼 수 있다.

NDoc을 이용한 문서화에서 한가지 걸리는 부분이 있는데, 클래스나 메서드 설명에서 공백문자가 ?로 표시되는 부분이다.

이를 위해서는 처음 NDoc을 실행해서 CHM 파일의 원본이 되는 HTML 파일을 만들고, 모든 HTML 파일에서 ?를 공백문자로 변환하고, 다시 NDoc에서 CHM 파일을 작성하는 편법을 이용한다.

? 제거하기

윈도우 환경에서는 mreplace와 같은 유틸리티를 이용하여 해결한다. Visual Studio .NET 2003에도 텍스트 파일의 내용을 한 번에 변경하는 기능을 제공하지만 프로젝트에 포함된 파일에 대해서만 사용할 수 있다. 파일안의 텍스트를 변경하기 위해 엄청나게 많은 수의 HTML 파일을 프로젝트에 등록하는 것은 번거롭다. 따라서 윈도우 환경에서는 mreplace와 같은 유틸리티를 쓰거나 필자와 같이 UNIX 계열 운영체제 명령어에 대한 배경지식이 있는 사람은 Cygwin을 이용할 수 있다. 또는 Mono를 사용하는 분들도 sed를 이용해서 간단하게 변경할 수 있다.




[그림6] mreplace 유틸리티


?를 공백문자로 변경해야 하는데 HTML 형식으로 변경하기 때문에 변경할 문자열에  를 입력한다. HTML 파일에 대해서만 적용할 것이므로 File mask에는 *.html을 입력한다. [OK]를 클릭하면 모든 파일의 내용이 변경된다. Cygwin이나 UNIX 계열에서 이와 같은 작업을 하려면 다음과 같이 하면 된다.


root@ns2:~/doc# find *.html -print |
> while read file
> do  sed -e 's/\?/\ /g' "$file"  > "$file.new"
>     mv "$file.new" "$file"
> done


HTML 파일을 정리했으면 doc 디렉터리로 이동한다. 여기에 보면 Mona.Web.UI.BasePage.hhp 파일이 있다. HTML Help Workshop의 프로젝트 파일이며, NDoc에서 자동으로 생성한 것이다. HTML Help Workshop을 설치했다면 이 파일을 클릭해서 열 수 있다.




[그림7] HTML Help Workshop 실행화면


[File] - [Compile]을 선택해서 CHM 도움말을 빌드하면 ?등이 사라진 깨끗한 도움말을 볼 수 있다.

Br2Nl과 Nl2Br 함수

사용자가 웹에서 여러 줄을 입력할 때 각 줄의 끝에는 개행문자가 붙지만, HTML 웹 페이지를 볼 때 줄 바꿈을 하려면 개행문자가 아니라 BR 태그를 사용해야 한다. BR 태그는 각 줄을 잘라내는 BReak를 뜻한다.
반대로 BR 태그가 들어간 문서를 수정할 때는 BR 태그가 아닌 개행문자로 보여주어야만 화면에 여러줄로 제대로 표시된다.


String.Replace( "\r\n", "" );
String.Replace( "", "\r\n" );


위와 같은 코드를 사용하면 Br2Nl이나 Nl2Br 함수를 만들 수 있다고 생각하기 쉽지만 실제로 웹 페이지는 <BR>, <br>, <BR/>, <BR  />, <Br>, <br  />, <br       />과 같이 얼마든지 다양한 형태로 쓰일 수 있다. 따라서 문자열 형태의 치환이 아닌 정규식을 사용하여 제대로 치환하여야 한다.
마찬가지로 윈도우 환경에서는 개행문자를 \r\n으로 사용하지만 비윈도우 환경에서는 개행문자를 \n으로 사용한다. Linux 환경의 Apache에서 mod_mono를 이용하거나 xsp를 이용하는 경우와 윈도우 IIS 환경에서 동작하는 경우에도 문제없이 변환하려면 \r\n이나 \n 어느 한쪽으로만 변환해서는 안된다. 이런 경우에는 Environment.NewLine 상수를 사용해야 한다.

Replace 함수

Br2Nl과 Nl2Br 함수에서는 Replace를 사용했는데 이는 System.Text.RegularExpressions.RegEx 클래스를 이용해서 만든 함수다.




[그림8] Replace 함수


Replace 함수는 위 코드처럼 모두 5개의 매개변수로 되어 있으며, 마지막 2개는 몇 개나 일치시킬 것인가를 나타내는 count와 정규식 패턴 매치를 시작할 위치를 나타내는 startPos로 되어 있다.

5회까지 걸쳐 작성된 전체 소스는 이곳에서 다운받기 바란다.

참고자료

HTML Help Workshop
  MS에서 제공하는 무료 도움말 제작도구이며 CHM 형식의 도움말을 제작하거나 해제할 수 있다.

• 유닉스 파워 풀(UNIX POWER TOOLS), 9.9 찾아낸 파일에 대해 원하는 명령을 실행하는 방법
  UNIX 환경에서 파일의 내용을 치환하는 스크립트 작성에 사용했다.

• C# Cookbook, O'Reilly, Recipe 8.5 - Replacing Characters or Words in a String
  정규식을 이용한 손쉬운 문자열 치환을 수행하는 Replace 함수는 Recipe 8.5에서 인용했다.

Ndoc
  .NET의 XML 문서화를 자동화하기 위한 도구로 Java의 XML 문서화를 자동화하는 JDoc과 같은 이름을 따르는 문서화 도구다.

DoxyGen
  C/C++을 위한 문서화 도구로 개발되었고, 현재는 Java, PHP, C#과 같은 다양한 언어들을 지원합니다. C/C++ 문서화 도구가 필요하다면 DoxyGen을 권합니다.

GhostDoc
  VS.NET 환경에서 개발언어에 관계없이 XML 문서화를 자동화해주는 도구입니다. 특히, 메서드 이름을 잘 지은 경우에는 그것을 토대로 요약까지 자동으로 작성합니다. 메서드 이름 위에서 오른쪽 클릭해서 선택하면 자동으로 필요한 XML 태그를 작성해줍니다.

mreplace
  Modula-2용으로 만든 유틸리티로 여기서는 파일 텍스트의 내용을 일괄적으로 변경하기 위해 사용했습니다. 윈도우 사용자가 사용하기에 가장 간단하고 편리합니다. 마지막에 사용한 설정을 기억하므로 프로젝트 작업시에 반복하는 일은 많지 않습니다.
Posted by tornado
|

 http://phpschool.com/bbs2/inc_view.html?id=12307&code=tnt2&start=0&mode=&field=&search_name=&operator=&period=&category_id=&s_que=

 

 

UNICODE :

http://www.unicode.org/standard/translations/korean.html

유니코드에 대해 ?

어떤 플랫폼,
어떤 프로그램,
어떤 언어에도 상관없이
유니코드는 모든 문자에 대해 고유 번호를 제공합니다.



UCS-2 :

대부분의 흔히 쓰는 문자들을 정의한 규격입니다.
2bytes 범위라서 UCS-2 입니다.
이걸 bit 로 표현하여 UTF-16 입니다.
UTF-16LE, UTF-16BE 가 동일한 규격으로 Little Endian, Big Endian 은 단지 byte order (바이트 순서)가 다를뿐 입니다.
iconv --list 를 해보면 쓸데없이 많이 나오는데,
UTF-16LE, UCS-2LE 가 같은거고 BE 끼리 같은거라고 보면 됩니다.
그냥 UTF-16은 UTF-16LE 와 동일하나 앞에 BOM 헤더가 붙습니다.
UCS-2 는 헤더가 붙지 않습니다.


UCS-4 :

UCS-2 의 확장입니다.
뒤의 2bytes 는 UCS-2 와 완전히 호환됩니다.
즉, UCS-2 의 0xFFFF 는 UCS-4 의 0x0000FFFF 와 같은 코드입니다.
UTF-32 로 말만 바꾸어 위의 내용과 동일합니다.
인터넷 브라우저 내부에서 이것이 사용되며,
js 등에서 indexOf() 로 가져오면 UCS-4 코드가 10진수로 반환됩니다.
10진수 이므로 65535 까지는 UCS-2 와 완전 호환 됩니다.


UTF-8 :

UCS-2, UCS-4 는 영어권에서는 분명한 낭비가 있습니다.
ascii 만으로도 충분히 표현 가능한데, 한글자에 쓰지도 않는 바이트가 낭비되지요.
그런점도 있고, 문자열로 뭘 하기에 UTF-7 보다는 편리해서 가장 보편적으로 사용됩니다.
가변길이를 가지는 특징이 있습니다.
단지 계산만으로 UCS-2, UCS-4 규격으로의 상호변환이 가능합니다.
한국어는 UCS-2 규격 내에 있기 때문에 3bytes 내에서 표현 가능합니다.


UTF-7 :

이메일 등 ascii 만으로 표현해야 할 필요성에 의해 만들어졌습니다.
한 글자당 8bit 씩 할당하지만 사용은 7bit 만 합니다.
UTF-8 과 같은 특징을 가지고 있으나,
모든 ascii 값이 실제 ascii 와 같은 의미가 아니기 때문에 이것으로 무엇을 하기는 좀 힘듭니다.



BOM (Byte Order Mark) :

유니코드 종류가 많기 때문에 앞에 이런 헤더를 붙여서 구분하기도 합니다.
EmEditor, UltraEdit, Vim 등의 에디터에서 인식합니다.



코드표

http://www.unicode.org/charts/

각 나라별 코드범위와 정의된 문자를 볼 수 있습니다.
앞에 0 을 적지 않았기 때문에 (Zerofill 이 아니기 때문에) 4자리까지는 UCS-2 려니 하시고,
5 자리 부터는 UCS-4 려니 하십시오.


resy우리말로 된 유니코드 튜토리얼이 있었으면 좋겠다 했는데..
이런 자료라도 참 절실하군요. 아직도 유니코드 = UTF-16(or 다른 인코딩) 으로 착각하는 사람이 많은 현실에...

누군가 총대를 매긴 해야하는데... 거참... ^^:
07/13 2:23:12 코멘트 지우기
resy보충 내용으로...
UCS 는 코드값의 테이블이라고 생각하면 됩니다. UTF 는 인코딩의 방법(즉, 바이트의 연속된 순서를 어떻게 표현할 것이냐 하는 정의)이고, UCS 는 미리 정의되어 있는 각 글자 코드를 테이블 화 해놓은 것입니다. 가령 글자 '가' 는 유니코드에서 U+AC00 에 해당하는데, UCS2 에서는 0xAC00 테이블 좌표에 위치하고 있습니다. 이것을 UTF-8 인코딩하면, 0xEAB080 이 됩니다.

누구도 이런 식으로 설명해주는 사람이 없어서 예전엔 UCS2 = UTF16?? 이라고 헷갈리고 헤맸는데, 이게 정확한 설명인지 모르겠습니다. 잘못된 점이 있으면 누가 지적해주시길... ^^;

문자 집합(Character Set)이랑 인코딩(Encoding)에 대한 차이도 뭐 속시원히 가르쳐주는 데가 없더군요. 결국 시간이 지나다보니 스스로 알게 되었습니다만.. 확실히 외국 자료 빼면 국내는 -_-;

그러고보니 예전에 누군가가 국가 코드표와 인코딩이 가지는 의미에 대해 글 올렸던 거 같은데, locale 에 대한 내용이 그 후로 안올라오는 거 같기도...
07/13 5:19

 

 

Posted by tornado
|

IBM 에서 본 글인데... 블로그에 담으면 옆으로 퍼져서 안담았었는데..

DBGuide 에서 깨끗이 정리해놨네 ㅎㅎ

 

AOP와 메타데이터: 완벽한 조합, Part 1

메타데이터로 강화된 AOP의 개념과 구조

Ramnivas Laddad│IBM

J2SE 5.0의 일부인, 새로운 자바 메타데이터 장치는 지금까지 자바에 추가된 것 중 가장 중요한 것이다. 프로그램 엘리먼트에 추가 데이터를 첨부하는 표준 방식을 제공함으로서 메타데이터 장치는 설정 관리, 프레임웍 구현, 코드 생성 등 애플리케이션 개발의 많은 영역들을 단순화하고 향상시킬 수 있게 된다. 이 장치는 Aspect 지향 프로그래밍(AOP)에 중요한 영향을 끼친다.

메타데이터와 AOP의 결합은 중요한 질문들을 만들어낸다:

  • 메타데이터 장치가 AOP에 미치는 영향은 무엇인가?
  • 메타데이터로 강화된 AOP는 선택인가? 아니면 필수인가?
  • 메타데이터와 AOP를 효과적으로 사용하는 가이드라인은 무엇인가?
  • 이 두 결합이 AOP의 채택에 어떻게 영향을 주는가?

위 질문에 대한 대답을 AOP@Work 시리즈를 통해 설명하겠다. Part 1에서는 메타데이터의 개념과 새로운 자바 메타데이터 장치를 설명하겠다. 또한, 메타데이터를 제공하는 것과 이를 소비하는 것 사이의 차이를 설명하고 메타데이터 주석을 도입한 프로그래밍 시나리오도 소개하겠다. 그런 다음, AOP의 join point의 기초를 살펴보고 메타데이터 강조를 통해 얻을 수 있는 유익이 무엇인지를 설명하겠다. 마지막으로 실용 예제를 설명하면서 Part 1을 끝맺도록 하겠다. Part 2에서는, 다차원 비지니스 공간에서 하나의 신호로서 메타데이터를 보는 새로운 방식을 설명하겠다. 또한 AOP 채택에 메타데이터가 어떤 영향을 끼치는 지와 AOP와 메타데이터를 효과적으로 결합하는 가이드라인을 설명할 것이다.

이 글 전반에 걸쳐 제시된 모든 개념들은 세 가지 유명한 AOP 구현을 통해 현실화 될 것이다: AspectJ, AspectWerkz, JBoss AOP

메타데이터 개념

메타데이터는 데이터에 대한 데이터이다. 프로그래밍 언어라는 정황 속에서, 메타데이터는 메소드, 필드, 클래스, 패키지 같은 프로그램 요소들에 첨부된 추가 정보이다. 메타데이터는 주석(annotation)이라고 하는 프로그램 요소를 사용하여 표현된다. 메타데이터와 관련된 문법은 단순한 문서에서부터 실행-작동의 변경 까지 적용된다. 예를 들어, 클래스의 작성자와 저작권 소유자를 설명하는데 메타데이터를 사용할 수 있다. 프로그램 실행에 아무 영향이 없는 경우에 사용할 수 있고 또는 메소드의 작동을 변경할지도 모르는 트랜잭션 특성 같은 메소드 속성을 설명할 때도 이를 사용할 수 있다.

자바에는 다양한 메타데이터 툴들이 있는데(XDoclet은 가장 잘 알려져 있다), 메타데이터 주석은 Java 5.0과 함께 핵심 자바로 통합되었다. 자바 메타데이터 장치(JSR 175; 참고자료)에는 커스텀 주석을 자바 코드에 추가하는 장치가 포함되어 있고 리플렉션을 통해 메타데이터 주석으로 프로그래밍 방식의 접근을 제공한다.

메타데이터를 이해하고 사용하는 핵심은 공급과 소비의 개념이다. 메타데이터 공급자는 주석 인스턴스들과 프로그램 요소들을 제휴시키는 장치인 반면, 소비자는 주석 인스턴스를 읽고, 해석하고, 이에 대해 실행하는 것이다. 다음 섹션에서 이 개념들을 자세히 설명하겠다.

메타데이터 공급하기

메타데이터 장치는 주석을 프로그램 엘리먼트에 공급하는 장치를 정의한다. 선택적으로 메타데이터 장치는 주석 유형을 정의하는 방식을 지정할 수 있다. 주석 유형은 템플릿을 지정하여 주석 인스턴스를 만든다. 클래스가 템플릿을 지정하여 객체들을 생성하는 것과 많이 비슷하다. 메타데이터 장치는 주석을 소비하는 일반적인 방식을 지정하기도 한다. 다만 한가지, 주석과 연관된 해석과 문법을 정의하지 않는다. 이 일은 소비자의 몫이다.

메타데이터 장치들의 기능은 다양하다. 예를 들어, Javadoc 스팩은 프로그램 요소와 연관된 코멘트에 주석을 정의한다. 어떤 메타데이터 장치들은 개별 문서(주로 XML 문서)를 사용하여 메타데이터를 표현한다. 예를 들어, EJB 전개 디스크립터는 엔터프라이즈 빈의 추가 특성을 지정한다. Javadoc 장치와는 달리 이 접근방식은 프로그램 요소들과 메타테이터를 약결합한다. 단점은 개발자들이 같은 엘리먼트를 설명할 때 많은 소스들을 변경해야 한다.

자바 메타데이터 장치는 메타데이터에 새로운 언어 지원을 추가하여 주석 유형을 선언하고 프로그램 요소에 주석을 단다. 또한 클래스 파일의 소스 코드 레벨에 메타데이터를 보유하는 것도 가능하다. 런타임 시 보유 정책으로 제어된다.

메타데이터 공급자는 다중 엘리먼트에 주석을 개별적으로 공급하기 보다 크로스커팅 방식으로 특정 주석을 첨부하는 장치를 포함하고 있다. 이러한 특징 때문에 AOP는 주석을 잘 공급할 수 있다.

메타데이터 장치의 선택은 메타데이터를 표현하는 방식에 영향을 미치지만 추가 데이터들을 프로그램 엘리먼트에 연결시키는 근본적인 개념은 모든 메타데이터 장치들에 모두 일반적이다.

메타데이터 소비하기

메타데이터 주석에서 값을 만들기 위해서는 이를 소비하는 것이 필요하다. 메타데이터는 다양한 방식으로 소비될 수 있고 이러한 사용법을 이해하면 AOP와 메타데이터를 올바르게 결합할 수 있다. 다음의 사용 케이스들은 비 AOP 목적으로 제공된 주석이 AOP 구현에서 소비되는 방법을 이해하는데 도움이 된다.

코드 생성
코드 생성은 메타데이터를 사용하는 가장 익숙한 방식이다. XDoclet 같은 툴을 사용하여 Javadoc 태그로 지정된 주석을 소비하여 XML 문서 또는 자바 코드 같은 객체들을 만들 수 있다. 생성된 코드는 주석이 달린 엘리먼트의 런타임 작동에 영향을 준다. 자바 메타데이터 장치를 지원하는 새로운 XDoclet가 개발되고 있다. 명령행 유틸리티인 apt (Annotation Processing Tool)- Java 2 SDK 5.0의 일부-는 플러그인을 작성하여 주석을 처리하는 방식을 제공한다. 예를 들어, 최근에 발표된 Contract 실행 툴인 Contract4Jsms apt를 사용하여 design-by-contract (DBC) 콘트랙트를 실행하는 Aspect를 만든다.

프로그래밍 방식의 작동 변경
표준 메타데이터 장치는 런타임 시 사용할 수 있는 방식을 제공한다. 또한 프로그래밍 방식으로 리플렉션을 사용하여 주석 인스턴스에 접근할 수 있도록 한다. 주석 인스턴스는 다른 객체들 처럼 사용되어 프로그램의 작동을 변경한다. 이 같은 프로그래밍 방식의 소비는, 생성된 객체들이 이 주석에서 인코딩된 정보를 읽힐 수 있는 곳에서, 프로그래머들이 애플리케이션의 코드 생성 루트를 지나치도록 한다.

프레임웍의 소비
메타데이터는 프로그램 엘리먼트와 프레임웍 간 통신, 또는 EJB, EMF, TestNG 같은 툴을 활용하는데 일반적으로 사용된다. 프레임웍 자체는 코드 생성, 리플렉션을 사용한 접근, 또는 AOP를 사용하여 특정 로직을 실행에 적용한다. @Remove@Session같은 EJB 3.0에서의 주석의 사용은 프로그램 엘리먼트의 역할인 프레임웍과 통신한다. Eclipse Modeling Framework은 주석을 사용하여(현재 Javadoc 태그로 표현됨) UML 모델을 만들고 XML 영속성을 지원한다. TestNG는 메타데이터를 테스트 케이스와 테스트 실행 툴들 간 통신에 사용한다.

언어 확장
메타데이터의 사용은 기저의 프로그래밍 언어와 컴파일러로 확대된다. 문법 속성들을 메타데이터와 제휴 시킨다는 것은 제휴하지 않은 것과는 다른 구조와 작동을 갖게 된다는 것을 의미한다. (참고자료) 최근에 발표된 Pluggable Annotation Processing API (JSR 269 )는 표준 방식으로 주석을 처리한다. 자바를 확장하는 메타데이터의 사용은 강력하면서도 위험하다: 주석은 핵심 언어를 변경하지 않고 자바 언어에 새로운 기능을 추가할 수 있도록 해주어 이를 개방 언어로 만든다. 최고의 시나리오에서 원리를 갖춘 확장은 호스트 언어의 몇 가지 한계를 극복 할 수 있다. 한편 비표준 또는 통일성 없는 주석들은 이해가 안되는 코드를 만들 뿐이다.

평범한 객체 지향 언어에서 AOP를 실행시키는 것은 언어 확장에 메타데이터를 사용하는 한 가지 예이다. AspectWerkz와 JBoss AOP는 메타데이터를 사용하여 Aspect로서 클래스의 문법을, pointcut으로서 데이터 필드를, 어드바이스로서 메소드를 변경한다. AspectJ 5는 @AspectJ 문법을 지원하는데 이는 AspectJ와 AspectWerkz 프로젝트의 합병 결과이다. 다른 AOP 구현과 자바 언어 확장에 대한 자세한 정보는 참고자료를 참조하라.

다음 섹션에서는 AOP의 join point 모델의 기초를 설명하고 메타데이터로 강화하는 것의 효용을 설명하겠다.

메타데이터와 join point 모델

A join point는 시스템 실행 시 구분 포인트이다. AOP의 가장 근본적이면서 독창적인 개념인 join point model모델은 시스템에서 어떤 join point가 노출되고 이들이 어떻게 잡히는지를 정의한다. Aspect를 사용하여 크로스커팅 기능을 구현하려면 pointcut이라고 하는 프로그래밍 구조를 사용하여 필요한 join point를 잡아야 한다.

Pointcuts은 join point를 선택하고 선택된 join point에서 콘텍스트를 모은다. 모든 AOP 시스템은 pointcut을 정의하는 언어를 제공한다. pointcut 언어의 난해함은 다양한 AOP 시스템들 간 요소를 차별화한다. pointcut 언어가 성숙할수록 강력한 pointcut을 작성하기는 더 쉽다.

join point 잡기

pointcut은 프로그램의 기존 엘리먼트의 속성을 지정한다. 이 작업의 주요 부분과 좋은 Aspect를 작성하는 원리는 강력한 pointcut을 작성하는데 있다; 다른 요소로는 설계가 잘 된 Aspect이다. 기대했던 것보다 더 많은 join point를 잡거나 기대했던 join point를 놓치는 pointcut은 시스템 진화의 걸림돌이다. 좋은 pointcut을 작성하는 것이 AOP를 파악하는 핵심이다.

현재 join point를 잡는 가장 일방적인 방식은 프로그램 엘리먼트의 임의의 속성들을 활용하는 것이다. 서명(signature) 같은 정적 속성들(유형과 메소드 이름, 인자 유형, 리턴 유형과 예외 유형 등)과 어휘 배치와 제어 흐름 같은 동적 속성들이 이에 포함된다. join point 서명의 와일드 카드들을 공정하게 사용하면 훌륭한 pointcut 정의가 된다. 개별 pointcut 들을 합성하여 보다 복잡한 것을 만들 수 있다. 프로그램 엘리먼트의 임의 속성에 기반한 join point 모델은 강력하고 유용하다. 여러 제품에서 AOP의 성공이 이를 증명하고 있다.

프로그램 엘리먼트의 서명에 사용할 수 있는 임의의 정보는 필요한 join point를 잡기에 충분하다. 이 모델에서 동적 크로스커팅이라고 하는 임의 데이터의 결합인 와일드카드와 제어 흐름 같은 동적 속성들은 잡힌 프로그램 엘리먼트를 변경하지 않고 join point를 잡을 수 있다. 예를 들어 Remote 인터페이스를 구현하는 클래스에서 RemoteException을 던지는 연산을 지정하여 모든 RMI 호출을 잡을 수 있다. (AspectJ에서 정의된) execution(* Remote+.*(..) throws RemoteException) 같은 pointcut은 프로그램 엘리먼트를 변경하지 않고 모든 RMI 연산을 깔끔하게 잡고 강력한 pointcut도 보장한다. 가장 큰 장점은 RMI 인프라가 필요로 하는 것 외에 추가 협업 없이 join point를 잡을 수 있다는 점이다.

메타데이터로 join point 잡기

서명 기반의 pointcut은 특정 크로스커팅 객체를 구현하는데 필요한 join point를 잡을 수 없다. 예를 들어, 트랜잭션 관리 또는 권한을 필요로 하는 join point를 어떻게 잡겠는가? RMI 예와는 달리, 엘리먼트의 이름 또는 서명에 내재된 어떤 것도 트랜잭션 또는 권한 특성을 암시하지 않는다. 이 상황에 필요한 pointcut은 다음 예제에서 직접 보겠지만 다루기 힘들다. (이 예제는 AspectJ에 있지만 다른 시스템의 pointcut은 개념상 동일하다.)

pointcut transactedOps()     : execution(public void Account.credit(..))      || execution(public void Account.debit(..))      || execution(public void Customer.setAddress(..))        || execution(public void Customer.addAccount(..))      || execution(public void Customer.removeAccount(..));

이 같은 상황은 메타데이터 사용을 도입하여 필요한 join point를 잡는다. 예를 들어, 아래에서 보는 것 처럼 pointcut을 작성하여 @Transactional 주석을 실행하는 모든 메소드의 실행을 잡을 수 있었다.

pointcut execution(@Transactional * *.*(..));

메타데이터와 모듈성

위 예제에서 메타데이터를 사용하여 join point를 잡는 것이 어리석은 것 처럼 보이지만 그 같은 사용 방식의 함축성을 생각하는 것은 중요하다. 특히 모듈성에 적용될 때는 더욱 그렇다. 일단 pointcut에 메타데이터를 사용하기 시작하면 메소드는 해당 주석을 실행하여 이들을 사용하는 Aspect의 크로스커팅 구현에서 협업해야 한다:

public class Account {    ...    @Transactional(kind=Required)    public void credit(float amount)  {        ...    }    @Transactional(kind=Required)    public void debit(float amount)  {        ...    }	    public float getBalance() {        ...    }    ...}

이와 비슷하게, Customer클래스의 addAccount(), removeItem(), setAddress() 메소드는 이제 @Transactional 주석을 실행해야 한다.

대부분의 AOP 사용자들은 Aspect 특성을 활용하는 디자인 패턴을 통해 현재 기존 AOP 지원에 트랜잭션과 권한부여 부분을 구현하고 있다. 이 글에서 보듯, AOP 시스템에 메타데이터를 추가하면 시스템을 놀랍게 향상시킬 수 있다. 추가된 메타데이터가 AOP 시스템의 모듈성에 어떻게 영향을 미치는 지와 메타데이터가 가장 유용하게 사용될 시나리오는 Part 2에서 다루겠다. 다음 섹션에서는 AOP 구현이 결합 메타데이터로 확장되는 방법을 구체적으로 설명하겠다.

메타데이터로 강화된 AOP

AOP 시스템과 이들의 join point 모델은 메타데이터 주석을 소비함으로서 증가할 수 있다. JBoss AOP, Spring AOP, AspectWerkz, AspectJ는 메타데이터를 활용하는 메커니즘을 제공하고 있거나 제공할 계획이다. JBoss AOP와 AspectWerkz는 현재 버전에 메타데이터를 지원한다. Spring AOP는 pointcut을 프로그램방식으로 작성할 수 있도록 하고 org.springframework.aop.Pointcut 인터페이스를 구현하는 것으로 메타데이터를 지원한다. AspectJ의 차기 버전은 AspectJ 언어를 변경함으로서 메타데이터를 지원할 것이다.

이전 섹션에서 @Transactional 주석으로 메소드를 집어내는 예제를 사용하여 AOP 시스템이 메타데이터를 소비하는 방법의 기초를 설명했다. 이제 부터는 AOP와 메타데이터를 결합하는 부분에 초점을 맞춰 설명하겠다.

이 글의 예제가 메타데이터를 지원하는 AOP 구현에 초점을 맞추고는 있지만 핵심 AOP 시스템이 직접 이를 지원하지 않을 때도 메타데이터를 소비하는 것이 가능하다. 코드 생성 지원에 피기백을 활용한다. 예를 들어, Barter는 오픈 소스 툴로서, 주석과 코드 생성 사전 단계를 사용해서, Javadoc 태그에 기반한 join point 캡쳐를 지원하지 않는 AspectJ의 구 버전과의 DBC 콘트랙트를 실행한다. 요즘, Contract4J는 자바 메타데이터 장치 스타일의 주석을 사용하여 이와 비슷한 일을 수행한다.

AOP 시스템의 메타데이터 지원

메타데이터 기반의 크로스커팅을 지원하려면 AOP 시스템은 주석을 소비하고 공급하는 방식을 제공해야 한다. 여기에서 두 가지 지원 유형의 기초를 설명하겠다. 다음 섹션에서 보다 자세히 설명하겠다.

주석 소비 지원
주석 소비를 지원하는 AOP 시스템에서는 프로그램 엘리먼트와 제휴된 주석에 기반하여 join point를 선택할 수 있다. 이 같은 지원이 되는 현재 AOP 시스템에서는 다양한 서명 패턴의 정의를 확장하여 주석 유형과 속성들이 지정되도록 한다. 예를 들어, pointcut은 Timing유형의 주석을 실행하는 모든 메소드를 선택한다. 게다가 25를 초과하는 속성값을 지닌 메소드만 하위로 선택할 수 있다. 주석 유형과 속성에 의존한 어드바이스를 구현하려면 시스템은 join point와 제휴된 주석 인스턴스를 잡는 pointcut 신택스를 추가할 수 있다. 마지막으로, 시스템은 어드바이스가 반사적인 API를 통해 주석 인스턴스에 접근할 수 있도록 한다.

주석 공급 지원
표준 자바 메타데이터 장치를 사용하여 하나의 주석 인스턴스는 주석이 달리고 있는 각 프로그램 엘리먼트를 위해 선언된다. 하지만 다중의 프로그램 엘리먼트들에 같은 주석 선언이 나타난다면 불필요한 것이 되고 만다. AOP 크로스커팅 메커니즘을 사용하여 모든 효력이 적용되는 엘리먼트에 한번만 주석을 선언하도록 할 수 있다. 주석 공급을 지원하는 AOP 시스템에서는 크로스커팅 방식으로 프로그램 엘리먼트에 주석을 붙일 수 있다. 예를 들어, @Secure 주석을 간단한 선언과 함께 Account 클래스의 모든 메소드에 붙일 수 있다. 모든 메소드에 걸쳐 주석을 낭비할 필요가 없다.

모든 AOP 시스템이 앞서 언급한 모든 기능들을 지원하는 것은 아니다. 이어지는 섹션을 통해 보다 자세히 배우게 될 것이다. 여러 AOP 시스템들이 어떻게 주석 소비를 지원하는지 볼 것이다.

AOP에서 주석 소비하기

pointcut 신택스는 다양한 메타데이터가 강화된 AOP 시스템과는 다르다. @Transactional 주석 인스턴스를 수반하는 모든 메소드를 잡는 pointcut을 각 시스템이 어떻게 핸들하는지를 연구하면 그 차이를 알 수 있다. 이 예제에서는, 주석 유형 별로 join point를 선택하는 것에 초점을 맞추겠다; 그런 다음 join point 선택에 영향을 미치는 다른 요소들을 설명하겠다.

AspectJ5
AspectJ 5 신택스는 유형, 메소드, 필드에 대한 서명의 정의를 확장하여 메타데이터 주석을 서명의 일부로 포함시킨다. 다음과 같다:

pointcut transactedOps(): execution(@Transactional * *.*(..)); 

AspectJ 5에서 @AspectJ 스타일의 정의를 사용한다면 같은 pointcut이 다음과 같이 정의된다:

@Pointcut("execution(@Transactional * *.*(..))")void transactedOps();

AspectWerkz
대부분의 다른 AOP 툴과 마찬가지로, AspectWerkz의 pointcut 신택스는 AspectJ의 그것과 닮았다. XML 스타일이 동일한 pointcut 식을 갖고 있지만 다음 코드에서 pointcut 선언은 메타데이터 유형의 주석을 사용한다:

@Expression("execution(@Transactional * *.*(..))")Pointcut transactedOps;

AspectWerkz는 메타데이터를 사용하여 AOP를 지원하도록 자바를 확장한다. 따라서 AspectWerkz는 프로그래밍 엘리먼트의 문법을 확장하기 위해서 그리고 메타데이터에 기반한 크로스커팅을 구현하기 위해서 메타데이터를 사용한다. 위 예제에서 후자의 용법에 초점을 맞추었다.

JBoss AOP
JBoss AOP는 다른 신택스를 사용하지만 기타 AOP 시스템들과 개념적으로는 많이 다르지 않다. 이곳에 나타난 pointcut은 다른 예제와 동일하지만 Jboss의 XML 신택스로 표현된다:

<pointcut name="transactedOps" expr="* *->@Transactional(..)"/>

다른 AOP 시스템들이 첨부된 메타데이터 주석에 근거하여 join point를 잡는 방법은 개념적으로 차이가 별로 없다.

주석 속성별로 선택하기

join point를 선택할 때 유형만 고려해서는 안된다. 속성 역시 고려되어야 한다. 예를 들어, 다음의 pointcut은 RequiredNew로 설정된 속성 값을 가진 @Transactional 주석을 가진 모든 메소드들을 잡는다:

execution(@Transactional(value==RequiredNew) *.*(..)) 

작성할 때, 어떤 AOP 시스템도 주석 속성에 기반한 pointcut을 지원하지 않고 대신 각 시스템은 어드바이스 내부의 동적 결정에 근거하여 속성들을 검사하고 해당 로직을 호출한다. (또는 적어도 if() pointcut을 사용하여 동적 체크를 사용한다.) 주석 속성 기반의 pointcut은 컴파일 시간 체크와 정적 선택에 특히 유용하다. AOP 시스템의 차기 버전들은 이러한 종류의 pointcut을 지원할 것이다.

주석 인스턴스 노출하기

어드바이스 로직이 메타데이터 주석 유형인스턴스 속성에 의존하기 때문에 각 주석 인스턴스는 join point의 다른 콘텍스트와 같은 방식으로 콘텍스트로서 노출되어야 한다. (예를 들어, 객체, 메소드 인자 등). AspectJ 5는 기존 pointcut을 확장하고 새로운 것을 추가하여 주석을 노출한다. 예를 들어, 다음의 pointcut은 캡쳐된 join point와 제휴된 Transactional유형의 주석 인스턴스를 모은다:

pointcut transactedOps(Transactional tx)    : execution(@Transactional * *.*(..)) && @annotation(tx);

일단 캡쳐되면, 주석 인스턴스는 다른 콘텍스트와 같은 방식으로 사용된다. 예를 들어, 다음 어드바이스에서 캡쳐된 주석은 이것의 속성을 묻고있다:

Object around(Transactional tx) : transactedOps(tx) {    if(tx.value() == Required) {        ... implement the required transaction behavior    } else if(tx.value() == RequiredNew) {        ... implement the required-new transaction behavior    }    ...}

대부분의 AOP 시스템은 반사적인 API만을 사용하여 캡쳐 된 join point에서 주석 인스턴스를 노출하고 주석들을 join point 콘텍스트로서 바인딩하지 못하도록 한다. 이 경우, 이러한 제휴 주석들에 대한 권장 join point를 나타내는 객체를 쿼리할 수 있다. AspectJ는 반사 액세스와 전통적인 join point 콘텍스트를 제공한다.

AOP에서 주석 공급하기

AOP 구조를 사용하여 주석을 공급하는 기본 개념은 프로그램 엘리먼트의 정의를 주석으로 어지럽히지 않는다는 것이다. 개념상, 그와 같은 구조에서는 크로스커팅 방식으로 프로그램 엘리먼트에 주석을 붙일 수 있다. 언뜻 보기에, AOP 구조를 사용하여 주석을 공급하고 그런 다음 그 주석을 사용하여 join point를 잡는 것은 불필요한 것 처럼 보인다. 결국 주석을 필요로 하는 join point를 구별할 수 있다면 pointcut을 작성하고 이들에게 join point를 직접 권고할 수 있다. 하지만 크로스커팅 방식으로 주석을 공급하는 것은 매우 도움이 된다. 우선, 그 같은 선언은 비 AOP 클라이언트들과 통신할 때 연결관으로서 작동한다. 더욱이, 크로스커팅 메커니즘으로 주석을 공급하면 주석 클러터(clutter)를 피하면서 약결합 시스템을 설계할 수 있다.

AOP 구조를 사용하는 다른 디자인에 대해서는 이 글 말미에 설명하도록 하겠다. 이제는 크로스커팅 방식으로 주석을 공급하는 기본 신택스를 설명하겠다.

주석 신택스 공급하기

AspectJ의 제안 신택스는 현재 정적 크로스커팅 구조를 확장하여 새로운 declare annotation 신택스를 만든다. 다음 코드는 Authenticated 유형의 주석을 banking으로 설정된 permission 속성과 함께 붙인다:

declare annotation : * Account.*(..)                    : @Authenticated(permission="banking");

@AspectJ pointcut은 같은 선언이 다음과 같이 작성되는 곳에서 @DeclareAnnotation 사용하여 같은 기능을 지원한다:

@DeclareAnnotation("* Account.*(..)")@Authenticated(permission="banking") void bankAccountMethods();

JBoss AOP의 경우, XML 스타일의 aspect를 사용할 때 annotation-introduction 엘리먼트를 사용하여 주석을 붙인다. 주석이 런타임시 보유되지 않는다면 invisible 속성이 지시한다. (표준 자바 메타데이터의 RetentionPolicy.SOURCE에 해당).

<annotation-introduction expr="method(* Account->*(..))"                         invisible="false">      @Authenticated(permission="banking")</annotation-introduction>

주석 공급의 원리는 신택스가 다르더라도 다양한 AOP 시스템 두루 비슷하다.

메타데이터를 이용한 AOP 디자인

메타데이터와 AOP를 결합하는 것은 매우 단순하다. 중요한 것은 메타데이터 기반 크로스커팅을 어디에 적용하고 어디에 적용하지 않아야 하는지를 아는 것이다. join point의 임의의 속성들을 사용하는 AOP 구현에서 메타데이터 기반의 pointcut을 결합하는 것 까지 시스템이 어떻게 진화하는지를 설명하는 것으로 위 질문에 대한 답을 하겠다. Part 2에서는 메타데이터 중심의 접근 방식을 선택할 때의 고려 사항들을 자세히 설명하겠다.

이 섹션의 논의는 두 가지 측면에서 유용하다. 우선, 메타데이터를 사용하는 것이 언제나 AOP 사용자들의 우선순위는 아니라는 것을 이해해야 한다. 둘째, 이 글의 예제 구현은 메타데이터 기반의 크로스커팅을 적용하기로 결정했을 때 디자인을 개발하는 방법에 대한 가이드라인일 뿐이다.

이 예제는 트랜잭션 관리 프로그램이다. AspectJ를 사용하여 예제의 모든 코드를 개발한 반면 다른 AOP 시스템들의 구현은 개념적으로 동일하다. 예제의 각 단계들은 원래 디자인의 리팩토링으로 간주하라. 목표는 시스템을 서서히 디커플(decouple)하여 모듈성을 향상시키는 것이다.

Version 1: 순진한 aspect

크로스커팅 문제를 모듈화하는 내 첫 번째 시도는 pointcut 정의 뿐만 아니라 pointcut에 대한 어드바이스를 포함하고 있는 시스템 스팩의 aspect를 적용하는 것이다. 이것은 매우 간단한 스키마이고 AOP를 배울 때 처음 만나게 되는 디자인이기도 하다. 그림 1은 하나의 aspect를 적용하는 디자인의 스키마이다:

그림 1. AOP를 사용하여 트랜잭션 관리를 구현하기

Listing 1은 위 디자인을 구현한 것이다:

Listing 1: 은행 시스템을 위핸 트랜잭션 관리 aspect
public aspect BankingTxMgmt {    pointcut transactedOps()         : execution(void Customer.setAddress(..))          || execution(void Customer.addAccount(..))          || execution(void Customer.removeAccount(..))          || execution(void Account.credit(..))          || execution(void Account.debit(..));              Object around() : transactedOps() {         try {             beginTransaction();             Object result = proceed();             endTransaction();             return result;         } catch (Exception ex) {             rollbackTransaction();             return null;         }    }        ... implementation of beginTransaction() etc.}

이 스키마는 기반 시스템에 대한 지식이 별로 요구되지 않는 aspect에 잘 맞는다. 예를 들어, 풀링(pooling)을 실행하고자 한다면 풀링되고 있는 리소스의 생성과 소멸에 대한 호출을 권고하는 제너릭 aspect를 작성할 수 있다. 하지만 제너릭 방식으로는 필요한 join point를 잡을 수 없는 크로스커팅 기능의 경우 이 방식은 한계가 있다. 우선, pointcut 정의가 시스템 스팩이기 때문에 aspect는 재사용 될 수 없다. 둘째, 시스템을 변경하면 aspect도 변경해야 한다. 다시 말해서, 첫 번째 버전의 시스템은 프로그램 엘리먼트들 간 N to 1 커플링과 pointcut을 남긴다. 이것이 최상의 옵션이 아니기 때문에 다른 시도가 필요하다.

Version 2: 재사용 가능한 aspect

내 두 번째 시도는 aspect를 재사용 할 수 있는 것으로 향상시켰다. aspect의 재사용 부분을 추출하여 시스템 스팩의 방식으로 pointcut을 정의하는 하위 aspect를 추가했다. 그림 2는 기본 aspect가 추출된 후의 구조이다:

그림 2. 재사용 할 수 있는 트랜잭션 관리 aspect 추출하기

Listing 2는 재사용이 가능한 기본 aspect이다. Listing 1과 비교해 보면 두 가지 변화를 알 수 있다: aspect는 추상적인 것으로 표시되고 transactedOps() pointcut은 정의가 제거된 채로 추상적인 것으로 표시된다:

Listing 2. 재사용 가능한 트랜잭션 관리 기본 aspect
public abstract aspect TxMgmt {    public abstract pointcut transactedOps();               Object around() : transactedOps() {         try {             beginTransaction();             Object result = proceed();             commitTransaction();             return result;         } catch (Exception ex) {             rollbackTransaction();             return null;         }    }       ... implementation of beginTransaction() etc.}

다음에, 기본 aspect에 대한 하위 aspect를 작성해야 한다. 아래 하위 aspect는 트랜잭션 관리 지원을 필요로 하는 join point를 캡쳐하는 pointcut을 정의한다. Listing 3은 Listing 2의 TxMgmt aspect를 확장한 은행 스팩의 하위 aspect이다. 하위 aspect는 transactedOps() pointcut을 Listing 1에 쓰였던 것과 똑 같은 것으로 정의한다.

Listing 3. 시스템 스팩의 하위 aspect
public aspect BankingTxMgmt extends TxMgmt {    public pointcut transactedOps()         : execution(void Customer.setAddress(..))          || execution(void Customer.addAccount(..))          || execution(void Customer.removeAccount(..))          || execution(void Account.credit(..))          || execution(void Account.debit(..));}

이것은 향상되기는 했지만 이 디자인 역시 하위 aspect와 클래스들 간 N-to-1 의존형이다. 은행 시스템에 필요한 트랜잭션 요구 사항들이 변경되면 BankingTxMgmt의 pointcut 정의도 변경되어야 한다. 이상적이지 못하다.

Version 3: Participant 패턴

위에서 재사용성의 문제를 다루었지만 N-to-1 의존성은 여전히 남아있다. Participant 패턴을 적용하여 이를 의존성을 제거할 수 있다. 전체 시스템에 하나의 하위 aspect를 사용하는 대신 많은 하위 aspect를 사용하면서—하위 시스템 당 하나— 비교적 안정적인 pointcut을 작성할 수 있다. 이 상황에서 하위 시스템은 패키지, 패키지 세트, 심지어는 클래스가 될 수 있다. 그림 3은 다른 엘리먼트들 간 구조 관계이다:

그림 3. participant 디자인 패턴 적용하기

Listing 4는 임베디드 클래스를 위한 pointcut을 정의하는 participant aspect를 가진 Customer 클래스이다.

Listing 4. 임베디드 participant aspect를 가진 Customer 클래스
public class Customer {    public void setAddress(Address addr) {        ...    }    public void addAccount(Account acc) {        ...    }    public void removeAccount(Account acc) {        ...    }    ...    private static aspect TxMgmtParticipant extends TxMgmt {        public pointcut transactedOps()             : execution(void Customer.setAddress(..))              || execution(void Customer.addAccount(..))              || execution(void Customer.removeAccount(..));    }}

Customer 클래스 예제에서 하위 aspect는 인자에 대한 와일드카드를 가진 모든 메소드들을 열거한다. 실제로 pointcut 정의를 단순화 하는데 와일드카드를 사용하게 될 것이다. 예를 들어 이 클래스의 모든 퍼블릭 메소드들을 다음 정의를 사용하여 transactedOps() pointcut으로 캡쳐되도록 선언할 수 있다:

public pointcut transactedOps()     : execution(public * Customer.*(..));

Listing 5에서, 시스템의 트랜잭션 관리 기능에 참여하기 위해 Account 클래스가 어떻게 하위 aspect를 삽입하는지를 보여주고 있다.

Listing 5. 삽입된 participant aspect를 가진 Account 클래스
public class Account {    public void credit(float amount) {        ...    }    public void debit(float amount) {        ...    }    public float getBalance() {        ...    }    ...    private static aspect TxMgmtParticipant extends TxMgmt {        public pointcut transactedOps()             : execution(void Account.credit(..))              || execution(void Account.debit(..));    }}

Customer 클래스처럼, 단계를 추가하면 pointcut을 단순화 할 수 있다. 예를 들어, getBalance() 메소드를 제외한 모든 퍼블릭 메소드들이 트랜잭션 관리 시 실행되어야 한다는 것을 깨달았다면? 이러한 깨달음을 적용하여 pointcut을 정의할 수 있었다:

public pointcut transactedOps()    : execution(public void Account.*(..))     && !execution(float Account.getBalance());

클래스가 변경되면 이 클래스에서 중첩된 하위 aspect만 변경해야 한다. 큰 N 대신 시스템 커플링을 각 하위 aspect에서 캡쳐 된 더 적은 프로그램 엘리먼트의 수인 n-to-1으로 시스템 커플링을 줄였다. 더욱이 트랜잭션 관리 필요성과 관련하여 클래스가 변경되면 삽입된 participant aspect의 pointcut만 변경하여 지역성을 보존한다.

이 예제는 AOP 관련 논의에서 종종 놓치는 중요한 부분을 설명하고 있다. 전체 시스템에 대한 서명 패턴을 찾으려 한다면 불쾌한 상황 즉, 불안정하고 복잡하며 부정확한 pointcut을 만나게 된다. 이 시스템의 하위 세트를 고려할 때 그 하위 시스템과 잘 작동되는 신호 패턴을 종종 찾을 수 있다. Participant 패턴을 클래스 당 하나의 aspect와 함께 사용하는 것은, 하위 시스템으로의 논리적 구분은 잘 이루어 지겠지만, 클래스를 하위 시스템으로 간주하는 것이다.

이 솔루션은 대부분의 상황에서 적용된다. 단점은 클래스들이 기본 aspect에 대한 직접적인 의존성이 있어서 기본 aspect가 언제나 시스템에 나타나야 한다는 점이다. 이 솔루션의 또 다른 문제는, 클래스가 중첩된 하위 aspect들을 삽입하여 협업에 명확히 참여하지 않는 한, 이것의 크로스커팅 기능이 적용되지 않는 다는 것이다. 이 문제는 솔루션 보다는 크로스커팅 기능의 본질을 다루어야 하는 문제인 것이다.

Version 4: 메타데이터 기반 pointcut

각 메소드를 변경하여 주석을 갖게 하고 시스템 당 하나의 하위 aspect가 되도록 할 예정이다.(Version 2와 유사) 하지만 나의 하위 aspect는 메타데이터 기반의 pointcut을 사용하여 필요한 join point를 잡을 것이다—메소드는 내가 공급한 주석을 실행할 것이다. 하위 aspect 자체는 시스템에 걸쳐 재사용될 것이다. 그림 4는 이 버전의 스키마이다.

그림 4. 메타데이터 기반 트랜잭션 관리

메타데이터 기반의 하위 aspect를 사용할 때, 클래스의 join point가 그 특성을 변경하면 해당 join point에 대한 주석만 변경되어야 한다. Listing 6는 Version 2에서 TxMgmt aspect를 확장한 하위 aspect이고 Transactional 유형의 주석을 수행하는 모든 메소드를 잡아서 transactedOps() pointcut을 정의한다.

Listing 6. 메타데이터 기반 트랜잭션 관리 하위 aspect
public aspect MetadataDrivenTxMgmt extends TxMgmt {    public pointcut transactedOps()         : execution(@Transactional * *.*(..));}

이 클래스는 Transactional 유형의 주석을 트랜잭션 관리 시 실행되어야 하는 모든 메소드에 첨부함으로서 하위 aspect와 협업해야 한다. Listing 7은 이 Customer 클래스를 주석을 수행하는 메소드와 함께 구현한 것이다:

Listing 7. Customer 클래스와 주석
public class Customer {    @Transactional    public void setAddress(Address addr) {        ...    }    @Transactional    public void addAccount(Account acc) {        ...    }    @Transactional    public void removeAccount(Account acc) {        ...    }    ...}

Listing 8은 유사한 Account클래스의 구현이다:

Listing 8. Account 클래스와 주석
public class Account {    @Transactional    public void credit(float amount) {        ...    }    @Transactional    public void debit(float amount) {        ...    }    public float getBalance() {        ...    }    ...}

이 지점에서 메소드와 협업 aspect 간 일대일 의존성을 확립했다. 또한 aspect와 클래스 간 직접적인 의존성도 제거했다. 결과적으로 기본 aspect만 변경하고자 할 때 시스템에 변경을 하지 않고도 이를 수행할 수 있다.

기본 aspect의 사용은 선택적이다. (계층을 무너뜨릴 수 있다.) 하지만 기본 aspect를 메타데이터 기반의 하위 aspect에서 분리하는 것은 몇 가지 장점이 있다. 우선, 분리된 aspect는 주석 유형을 선택할 수 있다. 한 시스템에서 주석 유형으로 Transactional을 사용하여 join point를 잡을 수 있다. 이때 다른 시스템의 주석 유형은 Tx가 될 수 있다. 둘째, Participant 패턴과 메타데이터 기반의 방식 간 선택을 분리된 aspect로 나아간다. 셋째, 이 방식을 사용하여 @Purchase 또는 @OrderProcessing같은 비지니스 주석들에서 트랜잭션 pointcut을 분리할 수 있다. 마지막으로 메타데이터 기반의 방식과 Participant 패턴 기반의 방식을 결합할 수 있다.

주석을 통해 협업함으로서 참여에 대한 책임은 (참여하는 하위 aspect 대신) 개별 메소드로 옮겨간다. MetadataDrivenTxMgmt와 클래스들 간 의존성은 주석 유형과 관련 문법으로 제한된다.

반복보다 좋은 것은 없다. 하지만 한 가지 특별한 시나리오가 있다. 최적의 결과를 위해 한 단계 더 들어간 디자인을 리팩토링 할 수 있는 시나리오이다.

Version 5: 메타데이터 공급자로서의 Aspect

특정 상황에서, 클래스 내 대부분의 메소드들은 (Version 4의 주석 같은) 주석을 수행해야 한다. 더욱이 많은 크로스커팅 특성들은 메소드 당 한 개 이상의 주석을 필요로 한다. 이 상황은 모든 메소드에 대해 선언된 많은 주석들을 주석 지옥으로 설명되는 현상으로 몰고 간다. 주석 아수라장은 Participant 패턴과 주석자-공급자 aspect를 결합함으로서 줄일 수 있다. 이는 참여하는 join point를 표현하는 분명한 방식이 있을 때 유용한 옵션이다. 이 같은 경우, 주석자-공급자 디자인은 join point에 대해 주석을 놓치는 위험을 피한다.

그림 5. 메타데이터 공급자로서의 Aspect

주석자 aspect는 한 개 이상의 declare annotation들을 사용한다: 예를 들어, declare annotation : <Method pattern> : <Annotation definition>;. >;. 이 예제에서, 클래스에 Participant 패턴과 비슷한 협업과 하나의 주석자 aspect를 사용했다. 하지만 이렇게 하는 것이 이 디자인의 근본적인 요구사항은 아니다. 예를 들어 패키지 당 하나의 주석자 aspect를 구현할 수 있다. 핵심 개념은 필요한 join point를 캡쳐하고 그 클래스의 주석 아수라장 현상을 피하는 명확한 서명 패턴 또는 동적 콘텍스트 정보(제어-흐름 등)를 가진 알맞은 하위 시스템을 찾는 것이다. Listing 9는 주석자 aspect를 가진 Customer 클래스 이다.

Listing 9. 삽입된 주석자 aspect를 가진 Customer 클래스
public class Customer { public void setAddress(Address addr) { ... } public void addAccount(Account acc) { ... } public void removeAccount(Account acc) { ... } ... private static aspect Annotator { declare annotation: public Customer.*(..): @Transactional; } }

Listing 10의 Account 클래스도 이와 비슷하다.

Listing 10. 삽입된 주석자 aspect를 가진 Account 클래스
public class Account {    public void credit(float amount) {        ...    }    public void debit(float amount) {        ...    }    ...    private static aspect Annotator {        declare annotation: public Account.*(..): @Transactional;    }}

이제 이 구현과 Version 3에서 Participant 패턴을 사용하는 구현을 비교해보자. 이 버전은 한 가지 중대한 단점이 있다: 이것은 클래스를 특정 aspect로 묶는다. 이는 매우 적극적인 개입이다—기본 aspect는 언제나 존재해야 한다. (이는 모든 참여 aspect에게 있어 기본 aspect이기 때문이다.) 주석자 aspect 접근방식을 사용하여 참여는 공통으로 이해된 주석 유형의 레벨에서만 발생할 수 있다.

다리 역할을 하는 주석 유형들
다양한 기술들이 비지니스 목적을 위해 사용되는 주석들과 aspect 구현에 사용되는 주석들 간 다리로서 사용하고 있다. 예를 들어, @Purchase@OrderProcessing 주석을 가진 모든 메소드들이 트랜잭션 관리가 되어야 한다는 것을 알고 있다면 Listing 11 처럼 aspect를 작성할 수 있다.

Listing 11. 비지니스 주석을 크로스커팅 주석으로 변환하기
public aspect BusinessTransactionBridge {    declare annotation: @Purchase *.*(..): @Transactional;    declare annotation: @OrderProcessing  *.*(..): @Transactional;}

이 aspect는 @Transactional 주석을 @Purchase 또는 @OrderProcessing 주석을 가진 모든 메소드에 붙인다. 이 방식은 Listing 2와 Listing 6을 결합하여, 트랜잭션 관리 로직으로 메소드를 실행한다.

결론

메타데이터는 프로그램 엘리먼트에 대한 추가 정보를 표현하는 하나의 방식이다. 자바의 새로운 메타데이터 장치는 유형화된 주석을 사용하도록 한다. 메타데이터 사용법은 매우 간단하다. 어떤 것을 사용하는 지는 본인의 선택에 달려있다. Aspect 지향 프로그래밍은 메타데이터의 기본적인 소비자이다. 안정적인 서명 기반의 pointcut으로 쉽게 지정되지 않는 크로스커팅 문제에 대해 보다 단순한 pointcut을 사용하여 메타데이터로 증가된 join point 모델은 AOP를 보다 접근 가능한 것으로 만든다.

이 글에서 메타데이터 개념을 설명하고 AOP에서 프로그램 엘리먼트에 대한 메타데이터에 저장된 정보를 사용하는 방법을 설명했다. 또한 다양한 AOP 시스템에 대한 메타데이터 기반의 pointcut을 지원하는데 어떤 방식들이 개입되어 있는지 설명했다. 다섯 가지의 디자인 리팩토링을 통해 AOP 시스템에 메타데이터를 적용하는 방법 또한 제시했다.

다음 글에서는 AOP를 소비자와 공급자로서 메타데이터를 정의하고 사용하는 디자인 고려 사항들을 자세히 설명하겠다. AOP 시스템에서 메타데이터를 결합하는 것이 망각 원리에 어떤 영향을 끼치는 지와 AOP 시스템의 채택에는 어떤 영향이 있는지도 설명하겠다. 다차원 작업 공간에서 신호로서 AOP에 접근하는 고급 방식도 설명할 것이다.

참고자료

AOP@Work.
"Annotations in Tiger, Part 1: 메타데이터를 자바 코드에 추가하기"
• AOP 실행: AspectJAspectWerkzJBoss AOP
Spring AOP
proposed language modifications
"Aspect-Oriented Programming and JBoss
"Aspect-Oriented Annotations"
TestNG , "TestNG로 자바 단위 테스트를 쉽게!"
Barter
Contract4J
"Metadata for language extensions"
AspectJ in Action: Practical Aspect-Oriented Programming
Aspect-Oriented Software Development
Mastering AspectJ: Aspect-Oriented Programming in Java
Eclipse AspectJ
AspectJ Cookbook
Java technology zone
Developer Bookstore,
Java- related titles
Java technology zone tutorials page, developerWorks

제공 : DB포탈사이트 DBguide.net

출처명 : 한국IBM
Posted by tornado
|

참고할 만한 곳

DHTML 2005. 7. 13. 11:57
Posted by tornado
|

code conflicted  발생시에... 해당 줄을 클릭하면... 이쁘게 틀린부분까지 보여주고 메뉴 배치도 좋은데 말야... 한글은 왜 깨지냐고 ㅎㅎ

'이것저것 > 낙서장' 카테고리의 다른 글

포맷;;  (0) 2005.07.15
신고해부렀다~  (0) 2005.07.14
ace framework ,....  (0) 2005.07.07
9000 히트 이벤트!!!  (3) 2005.07.06
로그가 너무 많이 쌓이잖아 -.-;  (0) 2005.07.06
Posted by tornado
|
subversion을 사용하고자 한다면..
subversion을 언제인가 사용해보고 싶은 욕심이 있었는데..앞으로 공부하기에 좋은 자료가 될거 같아서 여러분과 공유하고자 퍼왔습니다.

=============================================================
Subversion  

Subversion 은 공개 버전관리 도구인 CVS 의 여러 단점들을 보완한 공개 버전관리 프로그램 입니다. 디렉토리 삭제, 텍스트/바이너리 자동인식, 속도등이 CVS 보다 뛰어납니다. 엊그제 테스트 삼아 깔아 봤는데, 간단한 설치와 뛰어난 기능. 그리고 보조도구들의 기능도 뛰어나서 만족했습니다. 

Subversion Official Site( http://subversion.tigris.org/ )
- SubVersion 공식 사이트
TortoiseSVN ( http://tortoisesvn.tigris.org/ )
- 공개 서브버전 클라이언트 인데, 정말 편리합니다. Gui 를 사용하지 않고 익스플로러 에서 ContextMenu 를 통해서 정말 쉽게 사용할수 있습니다.
KLDP > Subversion 사용 HOWTO ( http://wiki.kldp.org/wiki.php/DocbookSgml/Subversion-HOWTO/ )
- 한글로 된 튜토리얼 입니다.
김성민 님의 Wiki ( http://serious-code.net/moin.cgi/Subversion?action=highlight&value=cvs )
- SubVersion 사용에 대한 도움말과 링크들이 있습니다.


from http://www.okjsp.pe.kr/bbs?act=VIEW&bbs=TOOL&seq=51640
Posted by tornado
|

'이것저것 > 낙서장' 카테고리의 다른 글

신고해부렀다~  (0) 2005.07.14
tortoise svn 사용할때.. 이거 아쉽다.. ㅡㅡ;  (0) 2005.07.13
9000 히트 이벤트!!!  (3) 2005.07.06
로그가 너무 많이 쌓이잖아 -.-;  (0) 2005.07.06
내 캐릭터는??  (2) 2005.06.27
Posted by tornado
|
 

ASP.NET의 Visual SourceSafe 사용에 관한 모든 것

Paul Sheriff, Michael Krasowski
PDSA, Inc.

2003년 12월

요약: Microsoft Visual SourceSafe를 사용하여 ASP.NET 프로젝트를 관리하는 전체 프로세스를 안내합니다(17페이지/인쇄 페이지 기준).

적용 대상:
Microsoft ASP.NET
Microsoft Visual SourceSafe

목차

소스 코드 컨트롤을 사용해야 하는 이유
격리 모드와 비격리 모드 비교
SourceSafe 데이터베이스 설정
VSS에 ASP.NET 솔루션 추가
VSS로 파일 조작
파일 기록 추적
소프트웨어 버전에 레이블 사용
Visual Studio .NET에서 솔루션 가져오기
결론

 

일부 개발자들은 소스 코드 컨트롤을 반드시 사용해야 하지만 매우 번거로운 것으로 생각합니다. 하지만 소스 코드 컨트롤은 소프트웨어 개발 프로세스를 지원하는 안전한 업무 관례입니다. 이 문서에서는 실제로 Microsoft Visual SourceSafe를 소스 코드 컨트롤 메커니즘으로 유용하게 사용하는 단계별 방법을 보여 줍니다. 새 SourceSafe 데이터베이스를 만드는 방법, 파일을 체크 인하고 체크 아웃하는 방법, 레이블을 사용하여 릴리스를 만드는 방법을 볼 수 있습니다.

소스 코드 컨트롤을 사용해야 하는 이유

단순하게 말하자면 VSS(Visual SourceSafe) 같은 SCM(Software Configuration Management) 제품은 프로젝트를 구성하는 문서의 중앙 라이브러리(데이터베이스)입니다. Visual SourceSafe에는 프로젝트 계획, 사양 설명서, 데이터베이스 개체, 소스 코드 등의 비트 스트림과 프로젝트의 기타 모든 항목을 저장할 수 있습니다. 최상의 방법은 소스 코드뿐만 아니라 모든 프로젝트 항목을 Visual SourceSafe 데이터베이스에 포함시키는 것입니다. 그러면 액세스 및 팀 구성원 간 공유가 용이해지며, 무엇보다도 버전 제어가 용이해집니다.

여느 라이브러리에서처럼 사용할 파일을 "체크 아웃"하는 기능이 필요합니다. 사용자는 파일을 체크 아웃한 후 편집할 수 있습니다. 일반적으로 한 번에 한 명의 사용자만 파일을 체크 아웃하여 편집할 수 있습니다. 언제나 한 명의 사용자만 파일을 체크 아웃할 수 있도록 하는 것이 가장 좋습니다. 간혹, 같은 파일을 여러 사용자가 체크 아웃할 수 있도록 할 것을 권장하는 Visual SourceSafe 사용 시나리오를 소개하는 백서도 있습니다. 이러한 백서에서는 나중에 모든 변경 사항을 함께 병합할 수 있도록 할 것을 권장합니다. 그러나 VSS에 기본 제공되는 도구를 사용하면 쉽게 병합할 수 있을 것 같지만 실제로는 여러 가지 단점이 있습니다. 항목을 다시 체크 인하는 데 시간이 더 오래 걸리고, 병합 프로세스에서 충돌을 수동으로 점검해야 할 경우가 발생할 수 있으며, 데이터베이스, Microsoft Word 문서 등의 이진 항목에는 대개 사용할 수 없습니다. 또한 업데이트된 항목과 업데이트한 사람 및 시간에 대한 정확한 기록을 반영하지 못하는 경우가 있습니다.

VSS에서는 라이브러리 관리자가 액세스 제어를 정의할 수 있습니다. 사용자에게는 액세스 ID 및 암호, 그리고 액세스 권한이 주어집니다. 액세스 권한은 읽기 또는 읽기/쓰기 기능처럼 단순할 수도 있고, 기능 권한과 같이 복잡할 수도 있습니다. 예를 들어 파일을 삭제하는 기능도 하나의 기능 권한입니다.

모든 개별 파일(소스 코드, 프로젝트 계획, 요구 사항 등)에 대해 각각의 파일 주기 동안 어떠한 변화가 있었는지 파악하는 것은 매우 중요합니다. VSS는 파일을 만든 시간과 만든 사람, 해당 파일에 대한 각 수정, 해당 파일에 대한 메모 또는 주석, 그리고 해당 문서의 주기를 추적하는 데 도움이 되는 기타 정보 등 모든 작업 기록을 보관합니다.

위에서 언급한 VSS의 기능과 그 외 여러 기능을 통해 잘 관리된 구조적인 방식으로 개발, 빌드 및 유지 관리 프로세스를 효율적으로 관리할 수 있습니다. 이 외에도, VSS를 사용하여 소프트웨어 개발의 생산성을 높일 수 있는 이유에는 여러 가지가 있습니다.

격리 모드와 비격리 모드 비교

팀 환경에서 웹 응용 프로그램을 개발할 경우 두 가지 모델 중에서 하나를 선택할 수 있습니다. 첫 번째 방식인 비격리 모델에서는 모든 개발자가 중앙 서버에서 모든 파일을 만들고 수정합니다. 비격리 개발 모델에서는 중앙 공유 컴퓨터에서 하나의 Microsoft IIS(Internet Information Services) 서버를 사용해야 하며, 응용 프로그램의 모든 파일이 해당 서버의 가상 디렉터리에 상주해야 합니다. 모든 개발자가 VSS에서 파일을 체크 아웃하며, 체크 아웃된 파일은 중앙 IIS 서버의 가상 디렉터리로 이동합니다.

두 번째 웹 개발 방식인 격리 모델에서는 각 개발자가 자신의 개발 컴퓨터에서 실행 중인 IIS 안에 가상 디렉터리를 만듭니다. 격리 방식에서는 각 개발자가 중앙 VSS 데이터베이스에서 로컬 컴퓨터로 파일을 가져오거나 체크 아웃합니다. 개발자는 로컬 컴퓨터에서 모든 내용을 편집, 디버그 및 테스트하고 모든 내용이 정상적으로 작동하면 파일을 중앙 위치로 다시 체크 인할 수 있습니다. 체크 인된 파일은 다른 개발자가 가져올 수 있습니다.

두 가지 개발 유형 모두 장단점이 있습니다. 각각의 장점과 단점을 살펴보겠습니다.

비격리 개발의 장점

  • 개발자의 로컬 컴퓨터에서 IIS를 실행하고 있지 않아도 됩니다.
  • 모든 소스 코드가 서로 다른 개발자의 컴퓨터에 흩어져 있는 것이 아니라 한 위치에 모여 있습니다. 소스 코드가 저장된 컴퓨터에 문제가 발생할 경우 변경 내용을 SourceSafe에 체크 인하지 않았으면 해당 변경 내용을 잃을 수도 있습니다.

비격리 개발의 단점

  • 다른 개발자의 작업에 의도하지 않은 영향을 미치기 쉽습니다.
  • 한 개발자가 디버깅을 위해 응용 프로그램을 실행하는 동안에는 프로세스가 잠기므로 다른 개발자들이 응용 프로그램을 디버그할 수 없습니다.
  • 여러 개발자가 같은 파일을 작업하는 경우에는 마지막에 체크 인한 파일이 최종 파일이 됩니다.
  • 소스 제어 기능이 제한되어 있습니다.
  • 한 개발자가 일부 코드를 수정하여 해당 코드가 작동하지 않을 경우 다른 모든 개발자가 더 이상 프로젝트의 해당 부분을 실행할 수 없게 됩니다.

격리 개발의 장점

  • 다른 개발자를 부주의하게 방해하지 않고 응용 프로그램을 개발 및 디버그할 수 있습니다.
  • 다른 개발자에게 영향을 미치지 않고 로컬에서 변경 내용을 테스트할 수 있습니다.
  • 소스 코드 컨트롤에 대한 지원이 뛰어납니다.
  • 개발자는 네트워크에 연결하지 않아도 프로젝트를 다른 컴퓨터로 이동하거나 가지고 다니면서 사용자를 표시할 수 있습니다.

격리 개발의 단점

  • 각 개발자가 자신의 로컬 컴퓨터에 IIS를 설정해야 웹 응용 프로그램을 개발할 수 있습니다.
  • VSS 라이브러리가 백업 프로세스에 포함되는 경우 각 개발자는 파일이 백업되도록 퇴근하기 전에 모든 파일을 다시 체크 인해야 합니다.

선택할 모델

격리 개발 모델을 사용할 것을 권장합니다. 물론 이를 위해서는 각 사용자의 컴퓨터에 IIS가 있어야 하므로 일부 조직에서는 제약이 따를 수 있습니다. 하지만 격리 모델은 가장 유연한 소스 코드 컨트롤을 위한 최상의 모델입니다.

격리 개발을 위한 Visual Studio .NET 설정

격리 모델을 사용할 수 있도록 Microsoft Visual Studio .NET에서 올바른 옵션을 설정했는지 확인하십시오. Visual Studio .NET에서 도구 | 옵션 탭으로 이동하고 Microsoft FrontPage Extensions 옵션이 아닌 파일 공유를 클릭합니다. FrontPage Extensions 옵션은 모든 파일이 중앙 서버에 위치한 비격리 방식을 사용할 경우 선택하는 옵션입니다.

SourceSafe 데이터베이스 설정

지금까지는 Visual SourceSafe의 개요 및 사용 이점에 대해 알아보았습니다. 이제 Visual SourceSafe를 시작하는 방법을 살펴보겠습니다. 첫 번째 단계는 중앙 VSS 데이터베이스의 위치를 찾는 것입니다. 이 데이터베이스는 엄밀한 의미에서 데이터베이스라기 보다는 하드 드라이브의 폴더입니다. 이 폴더는 모든 개발자가 찾을 수 있는 네트워크 공유에 배치되어야 합니다. 개발자가 한 명뿐일 경우에는 개발자의 로컬 하드 드라이브에 배치할 수도 있습니다.

VSS 관리 도구를 아직 설치하지 않았으면 VSS CD에서 설치합니다. 사용자 지정 설치를 통해 이 옵션을 선택해야 합니다. CDD에서는 일반적으로 ACMBoot.exe를 실행하여 관리 도구를 설치합니다. 사용자 지정 설치 옵션에서 Administrative ProgramsCreate SourceSafe Database 옵션을 선택해야 합니다.

관리 프로그램을 설치한 후에는 시작 메뉴로 이동하여 프로그램 | Microsoft Visual SourceSafe | Visual SourceSafe 6.0 Admin을 클릭합니다. 새로 시작되는 인터페이스에서 Tools | Create Database...를 클릭합니다 . 그러면 그림 1과 같은 대화 상자가 표시됩니다. 이 새 SourceSafe 데이터베이스를 만들 위치를 "D:\MyVSSDB" 또는 \\SharedDrive\MyVSSDB와 같이 입력합니다.

그림 1. 모든 SourceSafe 파일에 사용할 공유 폴더의 위치를 지정합니다.

데이터베이스를 만들고 나면 그림 2와 같은 대화 상자가 표시됩니다. 이 대화 상자는 이 SourceSafe 데이터베이스를 만들 때 만들어지는 Admin 사용자에 관련 암호가 없다는 것을 나타내는 경고일 뿐입니다. Admin 사용자를 클릭하고 메뉴에서 Users | Change Password...를 클릭하여 Admin 사용자에 암호를 할당하십시오.

그림 2. Admin 사용자에 암호를 할당하여 관리 도구를 보안합니다.

데이터베이스를 만들고 나면 Visual SourceSafe Administrator 도구(그림 3)가 나타납니다. 이 도구에서는 한 번에 하나의 VSS 데이터베이스에만 연결할 수 있습니다. 이 데이터베이스에서 파일을 체크 아웃하고 체크 인할 수 있도록 할 모든 사용자를 이 데이터베이스 안에서 만들어야 합니다. 만드는 각 데이터베이스마다 해당 사용자를 추가해야 합니다. 이 기능은 설정된 사용자만 이 데이터베이스를 사용할 수 있도록 하므로 유용합니다. 그러나 모든 사용자에게 액세스를 허용할 VSS 데이터베이스가 여러 개 있는 경우 각 데이터베이스에서 각 사용자를 개별적으로 설정해야 합니다.

그림 3. Administrator 도구에서는 새 사용자를 만들고, 데이터베이스를 만들고, 데이터베이스를 잠그며, SourceSafe에 대한 기타 시스템 관리 기능을 수행할 수 있습니다.

이제 이 데이터베이스에 자기 자신을 새 사용자로 추가해야 합니다. SourceSafe에서 도메인 로그온 ID(도메인 이름 제외)를 사용자 이름으로 사용하고 있는지 확인하십시오. SourceSafe는 아무런 메시지를 표시하지 않고 도메인 로그온 ID를 사용하여 로그온을 시도합니다. 이 VSS 데이터베이스에 암호를 할당한 경우에는 해당 암호가 도메인 암호와 일치하는지도 확인하십시오.

이 새 데이터베이스의 위치를 기억해야 합니다. 데이터베이스에 사용자를 도메인 이름과 함께 추가한 후에는 사용자가 VSS 클라이언트 유틸리티를 처음 설정할 때 데이터베이스를 찾을 수 있도록 모든 사용자에게 데이터베이스 위치를 알려야 합니다.

VSS에 ASP.NET 솔루션 추가

새로 만든 VSS 데이터베이스에 프로젝트 및 프로젝트 항목을 추가할 수 있습니다. 두 가지 방법을 통해 이 VSS 데이터베이스를 조작할 수 있습니다. 즉, "다른 프로젝트 항목"을 데이터베이스에 추가하는 데 유용한 VSS Explorer 도구를 사용하거나 Visual Studio .NET 내에서 VSS를 사용할 수 있습니다. 사실 VSS에 새 프로젝트를 추가하는 경우에는 Visual Studio .NET을 사용하여 추가하는 것이 좋습니다. Visual Studio .NET 인터페이스를 사용하면 .SLN 파일에 몇 가지 바인딩 정보가 추가되므로 개발자가 VSS에서 솔루션을 가져올 때 VSS에 자동으로 연결될 수 있습니다.

참고 이 문서의 예제에서는 ASP.NET  사이트에서 다운로드할 수 있는 Microsoft ASP.NET Portal Starter Kit을 사용하여 파일을 체크 인하고 체크 아웃했습니다. 원하는 다른 프로젝트를 사용할 수도 있습니다.

ASP.NET Portal Starter Kit을 다운로드하여 설치했다고 가정하고 VSS에 이 솔루션을 추가하는 방법을 설명하겠습니다. Visual Studio .NET에서 솔루션을 열고 그림 4와 같이 메뉴에서 File | Source Control | Add Solution to Source Control...을 선택합니다.

그림 4. Visual Studio .NET에서 기본 제공하는 메뉴를 사용하여 솔루션을 SourceSafe에 추가합니다.

이 메뉴 항목을 선택한 후에는 그림 5와 같은 대화 상자가 표시될 것입니다. 격리 개발 모드를 사용하는 경우 이 대화 상자는 FrontPage Server Extensions 대신 일반 파일 URL을 사용하여 모든 파일을 참조한다는 의미일 뿐입니다. Don't' show this dialog box again (Always allow addition of Web projects using File Share access to source control) 확인란을 클릭하고 Continue를 클릭하십시오.

그림 5. FrontPage Server Extensions에서 파일 공유 액세스 사용으로 전환

이제 VSS 데이터베이스를 설정할 때 만든 로그온 ID와 암호(그림 6 참고)를 입력할 차례입니다. 설정한 ID(예: JohnD)와 암호를 입력합니다. 그런 다음 Browse...를 클릭하여 VSS 데이터베이스를 만든 특정 폴더를 찾습니다. 작업을 마쳤으면 OK를 클릭합니다.

그림 6. VSS 로그온

데이터베이스에서 만들 프로젝트 이름을 입력하는 대화 상자가 나타납니다. 첫 번째 대화 상자인 "Add to SourceSafe Project"(그림 7)는 솔루션 파일이 있는 Visual Studio .NET 프로젝트를 나타냅니다. 그림의 "ASP.NET Portal Starter Kit (VBVS)"와 같이 이 프로젝트의 이름을 입력합니다.

그림 7. 본인이나 다른 개발자가 나중에 쉽게 찾을 수 있도록 프로젝트에 이름을 지정합니다.

솔루션에 있는 모든 개별 Visual Studio .NET 프로젝트를 입력하는 대화 상자가 나타납니다. 그림 8과 같이 VSS는 각 Visual Studio .NET 프로젝트 이름을 "Add to SourceSafe Project" 대화 상자의 입력란에 자동으로 추가합니다. 이 경우 두 번째로 입력되는 내용은 PortalVBVS입니다. "ASP.NET Portal Starter Kit (VBVS)" 폴더를 클릭하여 이 프로젝트를 이 솔루션 아래에 배치해야 합니다.

그림 8. 각각의 새 프로젝트를 VSS에 개별적으로 추가합니다.

솔루션 파일이 프로젝트와 동일한 폴더에 있다는 경고 메시지가 표시됩니다. 의도적으로 같은 폴더에 배치한 것이므로 확인란을 클릭하여 계속 진행합니다. 그림 9와 같은 대화 상자가 나타날 수도 있고 나타나지 않을 수도 있습니다. 이 대화 상자가 나타나면 확인란을 선택하고 OK를 클릭합니다. 이 경우 다른 항목은 프로젝트 파일의 일부분이 아닌 폴더에 있기 때문에 나중에 VSS Explorer 도구를 통해 수동으로 추가해야 합니다. 폴더 안에 있지만 프로젝트 파일로 새로 지정된 문서 또는 .SQL 파일이 이러한 항목에 해당할 수도 있습니다.

그림 9. 프로젝트 파일에서 참조하지 않는 추가 파일이나 폴더가 있으면 VSS에서 이를 사용자에게 알립니다.

솔루션과 프로젝트를 SourceSafe 제어 아래에 배치하고 나면 Visual Studio .NET이 그림 10과 같이 특수 아이콘을 사용하여 파일이 잠겼는지 아니면 체크 인되었는지 표시합니다. 소스 코드 컨트롤 아래의 각 파일 옆에는 자물쇠 아이콘이 표시됩니다. 자신이 체크 아웃한 파일 옆에는 확인 표시가 나타나고, 다른 사용자가 체크 아웃한 파일에는 원형 아이콘이 나타납니다.

그림 10. Visual Studio .NET은 소스 코드 컨트롤 아래에 각 파일의 상태를 표시합니다.

VSS 데이터베이스 내의 전체 프로젝트를 보려면 운영 체제 메뉴에서 시작 | 모든 프로그램| Microsoft Visual SourceSafe| Microsoft Visual SourceSafe 6.0을 선택하십시오. 다시 로그온해야 할 수도 있습니다. 로그온 이름과 암호를 입력하십시오. VSS Explorer(그림 11 참고)를 처음 실행하는 경우 데이터베이스를 만든 폴더를 탐색하여 VSS 데이터베이스도 찾아야 합니다.

그림 11. Visual SourceSafe Explorer에서는 전체 프로젝트 및 소스 코드 컨트롤 아래에 배치된 모든 파일을 볼 수 있습니다.

VSS로 파일 조작

프로젝트 파일을 VSS 데이터베이스에 배치하고 나면 프로젝트의 모든 파일이 디스크에서 읽기 전용으로 설정됩니다. 체크 아웃되지 않은 파일로 솔루션을 실행할 수도 있습니다. 그러나 Visual Studio .NET 내에서 파일을 작업하려면 체크 아웃해야 합니다. 현재의 작업과 비교하면 한 단계가 추가된 것이지만 대신 이전 버전으로 다시 돌아갈 수 있으며 다른 개발자가 수정 중인 파일을 사용자가 동시에 수정할 수 없도록 합니다.

파일 체크 아웃

파일 작업을 위해 체크 아웃해야 할 때는 Solution Explorer 창에서 해당 파일을 마우스 오른쪽 단추로 클릭하고 상황에 맞는 메뉴에서 Check Out...을 클릭하기만 하면 됩니다. 예를 들어 Portal Starter Kit에서 Default.aspx 파일을 클릭하고 마우스 오른쪽 단추를 클릭한 다음 Check Out...을 클릭합니다. 그림 12와 같은 대화 상자가 나타납니다. Check Out 단추를 클릭하면 .ASPX 파일뿐만 아니라 .ASPX.resx 및 .ASPX.VB 파일도 체크 아웃됩니다. 이제 해당 파일을 작업할 수 있으며 다른 사용자에게 파일이 체크 아웃된 것으로 표시됩니다.

그림 12. Check Out 대화 상자에서는 프로젝트 파일을 하나 또는 여러 개 가져와서 하드 드라이브에 쓸 수 있는 상태로 설정할 수 있습니다.

파일 체크 인

체크 아웃한 파일에서 원하는 내용을 모두 수정한 후에는 SourceSafe에 다시 체크 인해야 합니다. 파일을 체크 인할 경우 두 가지 사항을 염두에 두어야 합니다. 첫째, 프로젝트의 페이지 또는 클래스에서 변경한 내용이 컴파일되는지 확인해야 합니다. 그렇지 않으면 SourceSafe 데이터베이스에서 최신 변경 사항을 가져오는 다른 개발자의 프로젝트에서 오류가 발생하는 곤란한 상황이 발생합니다. 둘째, 매일 일과가 끝나면 파일을 모두 체크 인해야 합니다. 그러면 파일이 단지 하드 드라이브에 저장되는 것이 아니라 다른 위치에 백업됩니다. 따라서 하드 드라이브에 문제가 발생할 경우에도 변경한 내용을 모두 보존할 수 있습니다. 일과 후에도 소스 코드가 아직 컴파일되지 않은 경우에는 문제가 되는 코드에 주석을 달고 체크 인하면 됩니다.

최신 버전 가져오기

팀 환경에서 작업하는 경우 프로젝트 내에서 다른 파일을 수정하는 다른 개발자도 있습니다. 특정 시점에서는 VSS 데이터베이스에 있는 모든 최신 변경 사항을 프로젝트와 동기화할 수 있습니다. 그러기 위해서는 Visual Studio .NET Solution Explorer 창에서 프로젝트를 클릭하고 마우스 오른쪽 단추를 클릭한 다음 Get Latest Version (Recursive)를 클릭합니다. 그러면 VSS 데이터베이스로 이동하여 변경된 모든 파일을 검색하고 해당 파일을 프로젝트로 가져옵니다. 이제 로컬 컴퓨터에서 프로젝트를 실행하고 나면 다른 개발자가 변경한 내용을 모두 볼 수 있습니다.

파일 기록 추적

특정 시점에서 개발 팀은 "빌드", "버전" 또는 "릴리스"를 만들 수도 있습니다. VSS는 버전 번호를 사용하여 파일 및 프로젝트에 대한 모든 변경 사항을 추적합니다. 따라서 파일 또는 프로젝트의 모든 버전을 검색할 수 있습니다. VSS는 내부 버전 번호, 날짜 및 사용자 정의 레이블의 세 가지 항목을 기준으로 이전 버전을 추적합니다. 버전을 자체적으로 지정하는 경우에는 VSS에서 할당한 내부 버전 번호가 아니라 사용자 정의 레이블을 사용합니다.

버전 번호

VSS는 체크 인된 각 파일에 대해 내부 버전 번호를 유지합니다. 파일을 체크 아웃하고 변경한 다음 VSS에 다시 체크 인할 때마다 해당 파일 버전에 대한 새 번호가 만들어집니다. VSS에서 History 대화 상자를 사용하여 파일의 전체 기록을 볼 수 있습니다. History 대화 상자는 Visual Studio .NET 또는 VSS Explorer 도구를 통해 볼 수 있습니다.

Visual Studio .NET에서 기록을 볼 파일(예: default.aspx)을 클릭한 다음 Visual Studio .NET 메뉴 시스템에서 File | Source Code Control | History를 클릭합니다. 그러면 그림 13과 같은 대화 상자가 나타납니다. default.aspx 파일을 아직 변경하지 않은 경우에는 첫 번째 버전 이외의 다른 버전이 없습니다.

VSS Explorer 도구를 사용하는 경우 Explorer에서 특정 파일을 찾아서 마우스 오른쪽 단추로 클릭한 다음 Show History... 메뉴 항목을 클릭하여 동일한 대화 상자를 표시합니다.

그림 13. VSS Explorer에 파일의 전체 기록이 표시됩니다.

참고 내부 VSS 버전 번호는 단순히 참조용이며 빌드 또는 버전 번호와 직접적인 관련이 없습니다. 빌드 또는 버전 번호에는 레이블(아래 참고)을 사용합니다.

소프트웨어 버전에 레이블 사용

SourceSafe에서 파일에 할당하는 내부 버전 번호를 사용하는 대신 소프트웨어 릴리스를 정의하는 자신만의 코드 집합용 "레이블"을 만들 수도 있습니다. 릴리스는 첫 번째 베타 버전, 제품의 첫 번째 버전, 증분 릴리스, 제품의 두 번째 또는 세 번째 릴리스일 수 있습니다.
각 파일에는 자체 내부 버전 번호가 지정되며, 파일 수정 빈도에 따라 이 번호는 전체 프로젝트에서 전혀 일치하지 않게 됩니다. 따라서 내부 버전 번호 대신 자신만의 레이블을 전체 프로젝트에 적용하여 이 레이블을 만든 특정 시점에서 체크 인된 모든 파일을 식별할 수 있습니다.

레이블(최대 31자)을 만들 때 "1.0," "2.01b," "Final Beta" 또는 "Approved for QA" 같은 텍스트를 사용할 수 있습니다. 레이블을 적용한 후에는 기록 대화 상자에서 이 레이블과 연결된 모든 파일을 검색할 수 있습니다. 개별 파일에 레이블을 할당할 수도 있지만 대개 프로젝트 수준에서 레이블을 적용합니다. 프로젝트에 설명 문자열이 있는 레이블을 할당하면 해당 프로젝트의 모든 파일과 하위 프로젝트가 그 레이블을 사용합니다.

개발 주기의 어느 시점에서나 프로젝트에 레이블을 할당할 수 있습니다. 예를 들어 제품의 각 "릴리스"마다 알파, 베타 또는 최종 생산 코드에 관계없이 해당 시점에서 모든 프로젝트 항목에 레이블을 할당할 수 있습니다. 개발을 진행하다 베타 1.0의 소스 코드가 필요할 경우 그냥 가져오면 됩니다. 원하면 원본 파일에 아무런 영향을 미치지 않고 레이블의 이름을 바꿀 수 있습니다.

레이블을 만들려면 VSS Explorer 도구에서 레이블을 할당할 Project 폴더를 클릭하십시오. 메뉴에서 File | Label...을 클릭하면 그림 14와 같은 대화 상자가 나타납니다. 설명이 포함된 레이블 이름과 이 레이블의 사용 용도를 알려 주는 주석을 입력하고 OK를 클릭하여 레이블을 이 프로젝트와 이 프로젝트 아래의 모든 파일 및 하위 폴더에 적용합니다.

그림 14. VSS Explorer 도구를 사용하여 레이블 만들기

VSS Explorer에서 프로젝트를 다시 선택하고 마우스 오른쪽 단추로 클릭한 다음 Show History... 메뉴 항목을 클릭하여 History 대화 상자를 표시하면 그림 15와 같이 레이블이 표시됩니다.

그림 15. VSS Explorer의 History 대화 상자에서 적용한 여러 가지 레이블을 볼 수 있습니다.

기존 레이블에 파일 추가

버전에 레이블을 할당했는데 나중에 레이블이 할당된 버전에 포함되었어야 할 파일을 빠뜨린 것을 발견하는 경우도 있을 수 있습니다. 파일을 레이블의 일부분으로 추가하려면 파일을 프로젝트에 추가하기만 하면 됩니다. VSS Explorer에서 해당 파일을 클릭한 다음 File | Label...을 클릭하고 프로젝트에 할당한 것과 동일한 레이블을 할당합니다. 레이블을 기준으로 파일을 가져올 경우 레이블 이름이 동일하기 때문에 이 파일도 함께 가져옵니다. 레이블 이름을 정확히 입력했는지 확인하십시오.

레이블에 할당된 모든 파일 가져오기

특정 레이블이 할당된 파일을 모두 가져오려면 해당 파일에 대해 "가져오기(get)" 작업을 수행하면 됩니다. 즉, 특정 레이블 아래의 파일을 체크 아웃할 수는 없지만 가져올 수는 있습니다. 그러기 위해서는 VSS Explorer에서 내용을 가져올 프로젝트를 마우스 오른쪽 단추로 클릭하고 Show History...를 클릭합니다. Project History Options 대화 상자(그림 16 참고)가 나타나면 Labels Only 확인란을 선택하고 OK를 클릭합니다.

그림 16. 프로젝트의 레이블 가져오기

선택한 프로젝트에 할당한 모든 레이블이 표시됩니다. 가져올 레이블을 클릭한 다음 화면(그림 15 참고) 오른쪽에서 Get을 클릭합니다. 그러면 이 레이블이 있는 모든 파일이 이 프로젝트에 할당된 작업 디렉터리로 복사됩니다. 이미 언급한 대로 레이블이 할당된 릴리스에서는 파일을 체크 아웃할 수 없습니다. 따라서 릴리스된 파일 집합은 아무도 무단으로 변경할 수 없습니다.

Visual Studio .NET에서 솔루션 가져오기

사용자가 빌드 중인 응용 프로그램에 대해 프로젝트 책임자가 초기 솔루션을 만들면 다른 개발자가 이 솔루션을 가져와서 각자의 컴퓨터에 설정할 수 있도록 해야 합니다. 이때 각 개발자가 자신의 컴퓨터에 가상 디렉터리를 다시 만들고 모든 파일을 올바른 위치로 가져왔는지 확인하게 할 필요는 없습니다. 다행히도 VSS 및 Visual Studio .NET에서는 이를 자동으로 처리합니다.

VSS와 통합된 Visual Studio .NET은 하드 드라이브에 적절한 폴더를 자동으로 만들고, 새 가상 디렉터리를 만들며, VSS에서 새 폴더로 파일을 자동 복사합니다. 항상 VSS가 아닌 Visual Studio .NET을 통해 이 프로세스를 수행해야 합니다. 그렇지 않으면 IIS를 수동으로 구성하고 VSS 데이터베이스에 대한 참조를 직접 설정해야 합니다.

다음 단계를 수행하려면 다른 컴퓨터를 사용하거나 앞에서 만든 가상 디렉터리를 지워야 합니다. Visual Studio .NET의 새 인스턴스를 엽니다. File | Source Control | Open from Source Control...을 클릭하면 그림 17과 같은 대화 상자가 나타납니다. 창에서 PortalVBVS 프로젝트를 클릭합니다. Create a new project in the Folder 입력란에 다른 폴더 이름을 입력하고 OK를 클릭합니다.

그림 17. 새 폴더로 SourceSafe 프로젝트 가져오기

드라이브에 없는 폴더를 선택하면 폴더를 만들라는 메시지가 표시됩니다. 이 예제의 경우에는 폴더가 드라이버에 없어야 정상입니다. Yes All을 클릭하여 이 프로젝트에 필요한 모든 폴더를 만듭니다.

그림 18과 같이 이 프로젝트를 배치할 가상 디렉터리를 입력하는 대화 상자가 나타납니다.

그림 18. 프로젝트에 가상 디렉터리 할당

SourceSafe 내의 프로젝트 및 솔루션 레이아웃 방법에 따라 열려는 솔루션 파일을 입력해야 할 수도 있습니다. 그럴 경우 대화 상자에서 .SLN 파일을 선택합니다. Portal 솔루션에서는 .SLN 파일이 분리된 자체 폴더 안에 있으므로 SourceSafe에서 아무런 대화 상자도 표시되지 않습니다.

다음으로는 이 가상 디렉터리를 만들 IIS의 위치를 입력하는 대화 상자가 나타납니다. 웹 서버 이름과 가상 디렉터리 이름을 입력하고 OK를 클릭합니다.

그림 19. 웹 서버에 프로젝트 할당

이제 Visual Studio .NET에서 이 프로젝트의 모든 파일을 가져오기 시작합니다. 이 문서의 예제에서는 D:\PortalVBVS를 사용했습니다. 즉, 솔루션이 이 폴더에 저장된다는 의미입니다. 이 프로젝트의 다른 모든 파일은 기본 웹 사이트가 가리키는 폴더에 배치됩니다. 일반적으로 이 폴더는 c:\inetpub\wwwroot입니다. 이로써 프로젝트가 다른 개발자의 컴퓨터에 설정되었으며 사용 준비가 끝났습니다. 사이트의 시작 페이지를 선택하고 F5를 누르기만 하면 응용 프로그램이 실행됩니다. 이제 파일을 체크 아웃하여 작업하고 다시 체크 인할 수 있습니다. 이 모든 작업이 Visual Studio .NET 내에서 가능합니다.

결론

모든 개발자는 일상적인 작업에서 Visual SourceSafe를 사용해야 하며, 모든 개발 관리자는 팀에서 Visual SourceSafe를 사용하도록 해야 합니다. 개발자가 한 명뿐일 경우에도 이 도구를 효율적으로 사용하면 소스 코드를 다른 컴퓨터에 백업하고 소스 코드의 이전 버전으로 돌아갈 수 있습니다. VSS를 만들고 사용하는 것은 간단하고 쉽습니다. 사용 방법을 조금만 배우면 됩니다. 소스 코드 컨트롤이 뛰어나면 개발 프로세스가 향상되고 소프트웨어 구성 관리의 다양한 이점을 모두 활용할 수 있습니다.

BIO

Paul D. Sheriff는 SDLC 문서 및 아키텍처 프레임워크를 비롯한 .NET 컨설팅, 제품 및 서비스를 제공하는 PDSA, Inc.의 사장입니다(http://www.pdsa.com/ 을 참고하십시오). 또한 남부 캘리포니아의 Microsoft 지역 책임자입니다. .NET 저서로는 ASP.NET Developer's Jumpstart(Addison-Wesley: 영문)와 PDSA 웹 사이트에서 구할 수 있는 여러 eBook이 있습니다. 전자 메일 주소는 PSheriff@pdsa.com입니다.

Michael Krasowski는 PDSA, Inc의 개발부 부사장입니다. 이전에는 The Boeing Company, Long Beach Division에서 선임 IT 관리자 직책을 역임했습니다. IT 분야에서 27년이 넘는 경험을 보유하고 있으며 캘리포니아 대학의 Irvine 사회 교육 과정에서 .NET에 대해 강의하고 있습니다. 전자 메일 주소는 Michaelk@pdsa.com입니다.

'.NET' 카테고리의 다른 글

[msdn 펌] .NET Enterprise Services 성능  (0) 2005.07.22
[펌] ASP.NET 가이드 5. NDoc을 통한 코드 문서화  (0) 2005.07.14
asp 트리 ...  (0) 2005.07.07
닷넷용 하이버네이트  (0) 2005.06.29
[msdn펌] ASP.NET 업로드  (0) 2005.06.27
Posted by tornado
|

asp 트리 ...

.NET 2005. 7. 7. 18:37

http://www.obout.com/t2/eMSDN_DL_deep.aspx 

 

쓸만한거 많음 ㅎㅎㅎ

 

Posted by tornado
|
[방문히트이벤트] 9000 히트를 잡아라! (이웃한정)
박종복님이 당첨되었습니다.

'이것저것 > 낙서장' 카테고리의 다른 글

tortoise svn 사용할때.. 이거 아쉽다.. ㅡㅡ;  (0) 2005.07.13
ace framework ,....  (0) 2005.07.07
로그가 너무 많이 쌓이잖아 -.-;  (0) 2005.07.06
내 캐릭터는??  (2) 2005.06.27
딱지 ㅡㅡ;  (2) 2005.06.23
Posted by tornado
|

회사 서버에.. 210.182.163.130 이랑..

일본 도메인이랑.. 매일 이렇게 침투하려고 시도한다..

A 부터 Z 까지... 다 돌려보고.. 또 돌려보고...... 계속 염병한다..

그런다구 뚫리냐~

 

일본 도메인은 다른 IP 에서 뚫린것 같고..

210.182.163 으로 들어오는 넘은.... 매일 낮에 스크립트를 돌린다. ㅡㅡ;

이렇게 쌓이는 로그가... 몇메가씩 됨..

아웃룩 열어보면 메일이 하루에 몇십통씩 쌓임 ㅡㅡ;

 

빨랑 네트워크 관리자랑 보안관리자를 어케 해야 하는데 ....

올 가을까지는 헛지랄 해야 할듯 하네;

 

 --------------------- SSHD Begin ------------------------


Failed logins from these:
   a/password from 210.182.163.130: 2 Time(s)
   aage/password from 210.182.163.130: 1 Time(s)
   aaron/password from 210.182.163.130: 1 Time(s)
   aartjan/password from 210.182.163.130: 1 Time(s)
   abacus/password from 210.182.163.130: 1 Time(s)
   abbas/password from 210.182.163.130: 1 Time(s)
   abbess/password from 210.182.163.130: 1 Time(s)
   abbot/password from 210.182.163.130: 1 Time(s)
   ablazed/password from 210.182.163.130: 1 Time(s)
   abode/password from 210.182.163.130: 1 Time(s)
   abomb/password from 210.182.163.130: 1 Time(s)
   about/password from 210.182.163.130: 1 Time(s)
   abuse/password from 210.182.163.130: 2 Time(s)
   abyss/password from 210.182.163.130: 1 Time(s)
   academician/password from 210.182.163.130: 1 Time(s)
   academy/password from 210.182.163.130: 1 Time(s)
   accent/password from 210.182.163.130: 1 Time(s)
   access/password from 210.182.163.130: 1 Time(s)
   account/password from 210.182.163.130: 2 Time(s)
   ace/password from 210.182.163.130: 1 Time(s)

'이것저것 > 낙서장' 카테고리의 다른 글

ace framework ,....  (0) 2005.07.07
9000 히트 이벤트!!!  (3) 2005.07.06
내 캐릭터는??  (2) 2005.06.27
딱지 ㅡㅡ;  (2) 2005.06.23
오늘 건강검진 했음 ㅡㅡ;  (2) 2005.06.22
Posted by tornado
|

요청 쿼리에 ?lzt=html 를 붙이니까 없어짐..

 

http://192.168.1.53:8080/lps-3.0/my-apps/hello1.lzx?lzt=html

http://192.168.1.53:8080/lps-3.0/my-apps/hello1.lzx?lzt=html-object

 

이런식으로 호출함..

 

라즐로 이용해서 포토 게시판 만들면 끝장이겠는걸~

'JAVA > JSP_Servlet' 카테고리의 다른 글

[펌] myeclipse에서 xdoclet 설명  (0) 2005.10.04
[펌] 웹개발문서모음 - iHelpers  (0) 2005.08.24
jwebunit  (0) 2005.06.03
OSCache / Quartz ... 등등 좋은것들..  (0) 2005.06.03
[펌] Opensource Web Grid  (0) 2005.05.30
Posted by tornado
|

'DHTML' 카테고리의 다른 글

[펌] SELECT 목록 그룹별로 묶어서 표시하기  (0) 2005.07.22
참고할 만한 곳  (0) 2005.07.13
브라우저별로 테스트할때...  (0) 2005.07.01
[링크] HTML 예제 죽인다...  (0) 2005.04.28
[펌] tab 만들기.. 링크..  (0) 2005.04.28
Posted by tornado
|