달력

42024  이전 다음

  • 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
  • 29
  • 30

[msdn 펌] AOP...

.NET 2005. 11. 29. 11:58

자바에서 쓰던거 전부 넘어오는거 아닌지 모르겠네..

스프링까지 넘어와서.. VS.NET 툴에 통합되면 무지 편리하겠는데..

 

AOP(Aspect-Oriented Programming)

 

Matthew Deiters
ThoughtWorks

2005년 9월

적용 대상:
Microsoft Visual Studio
Microsoft Visual Basic

요약: 웹 서비스 클라이언트 응용 프로그램의 동작을 동적으로 확장하는 방법을 시연하여 AOP(Aspect-Oriented Programming)에 대한 실용적인 정보를 확인합니다(11페이지/인쇄 페이지 기준).

이 기사의 코드 샘플을 다운로드하려면 여기를 클릭하십시오.

목차

소개
Aspect란?
AOP의 장단점
Trace.WriteLine을 넘어서
Mixin의 배후 구현
동작 위빙(Weaving)
정리
결론

소개

AOP(Aspect Oriented Programming)는 개발된 지 오래되었지만 최근에야 Microsoft .NET 개발 커뮤니티에서 주목을 받기 시작했습니다. 새로 채택되는 모든 기술이 그렇듯이 기술과 기술의 사용 방법에 대해서는 많은 오해가 발생하기 마련이며 AOP도 예외는 아닙니다. 이 기사와 다음 코드 샘플에서는 AOP의 실제적인 응용 방법과 AOP에서 처리할 수 있는 몇 가지 일반적인 문제를 설명하며 AOP에 대해 집중적으로 다룰 예정입니다. 또한 웹 서비스를 사용하는 응용 프로그램을 살펴보고, AOP 프레임워크를 사용하여 웹 서비스에서 반환하는 개체에 새로운 aspect를 적용함으로써 개체의 기능을 확장해 보겠습니다. 이러한 aspect는 WSDL로 생성된 개체 모델과는 별개로 이 기능만을 위한 것입니다.

Aspect란?

개체와 다른 개체 간의 관계를 떠올리면 대개 상속의 관점에서 생각하게 됩니다. 여기서는 Dog라는 추상 클래스를 예로 들어 보겠습니다. 저마다 고유한 동작을 가지는 유사한 클래스를 정의할 때는 대개 상속을 사용하여 기능을 확장하게 됩니다. 예를 들어 Poodle을 정의하는 경우 PoodleDog이므로 PoodleDog를 상속한다고 할 수 있을 것입니다. 지금까지는 괜찮지만 나중에 Obedient Dog라는 이름으로 또 다른 고유한 동작을 정의하면 어떻게 될까요? 당연히 모든 Dog가 고분고분한(obedient) 것은 아니므로 Dog 클래스에는 obedience 동작이 포함될 수 없습니다. 또한 Dog에서 상속된 Obedient Dog 클래스를 만드는 경우 Poodle은 이 계층 구조에서 어디에 위치할까요? PoodleDog입니다. 그러나 Poodle고분고분(obedient)하거나 그렇지 않을 수 있습니다. 그렇다면 PoodleDog에서 상속되는 것일까요, 아니면 Obedient Dog에서 상속되는 것일까요? obedience를 Dog 계층 구조에 부적절하게 강제로 적용하는 대신 고분고분한 모든 유형의 Dog에 적용할 aspect로 볼 수도 있습니다.

소프트웨어 측면에서 볼 때, AOP(Aspect-Oriented Programming)를 사용하면 상속 계층 구조와 별개로 클래스나 개체의 동작을 변경하는 aspect를 적용할 수 있습니다. 그러면 이러한 aspect를 런타임이나 컴파일 시에 적용하게 됩니다. AOP는 설명하는 것보다 예제를 통해 보여 주는 편이 더 간단합니다. 시작하기 전에 반복해서 사용할 네 개의 주요 AOP 용어를 정의해야 합니다.

  • Joinpoint—식별 가능하며 제대로 정의된 코드 지점
  • Pointcut—구성 또는 코드를 사용하여 joinpoint를 지정하는 방법
  • Advice—발생해야 하는 크로스 커팅(Cross Cutting) 작업을 표현하는 방법
  • Mixin—새 동작을 적용할 클래스의 대상 인스턴스와 혼합될 클래스의 인스턴스

이들 용어에 대한 이해를 돕기 위해 joinpoint를 프로그램의 흐름에 정의된 지점으로 생각해 봅시다. 코드에서 메서드를 호출할 때 해당 호출이 발생하는 지점이 joinpoint의 좋은 예입니다. pointcut을 사용하면 프로그램 흐름을 차단할 joinpoint를 지정하거나 정의할 수 있습니다. 또한 pointcut에는 joinpoint에 도달할 경우 발생하는 advice가 들어 있습니다. 따라서 호출 중인 특정 메서드에 pointcut을 정의하는 경우, 호출이 발생하거나 joinpoint가 호출되면 AOP 프레임워크에 의해 프로그램의 흐름이 중단되고 pointcut의 advice가 실행됩니다. advice는 여러 가지일 수 있지만 호출할 또 다른 메서드로 간주하는 것이 가장 일반적입니다. 그러므로 pointcut이 있는 메서드를 호출하는 경우 실행할 advice는 호출할 또 다른 메서드가 됩니다. 이 advice 또는 호출할 메서드는 메서드가 차단된 개체에 있거나 여기서 혼합한 다른 개체에 있을 수 있습니다. mixin에 대해서는 나중에 좀 더 자세히 설명하겠습니다.

AOP의 장단점

흔히들 AOP를 차단으로 오해하지만 사실은 그렇지 않습니다. AOP는 차단 기능의 힘을 빌어 advice를 적용하거나 동작을 함께 위빙(weaving)할 뿐입니다. 현재 ContextBoundObject를 사용하여 AOP를 연상하게 하는 스타일로 차단하는 방법을 보여 주는 다양한 .NET 코드 샘플을 확인할 수 있습니다. 하지만 이 접근 방식에서는 사전 요구 사항에 따라 차단을 허용해야 하는 모든 클래스가 ContextBoundObject에서 상속되어야 하므로 ContextBoundObject는 이 작업에 적합하지 않습니다. ContextBoundObject 같은 사전 요구 사항이 있는 AOP에 대한 접근 방식은 요구 사항으로 인해 좋지 않은 영향이 발생하므로 복잡한 접근 방식으로 간주될 수 있으며 가능한 한 사용하지 않도록 합니다. 복잡한 접근 방식은 시스템에서 많은 공간을 차지하여 잠재적으로 모든 클래스에 영향을 미치므로 향후 시스템을 변경하거나 수정하는 능력을 떨어뜨릴 수 있습니다.

필자는 Encase라는 간단한 프레임워크를 만들었습니다. 여기서 "간단한"이라는 용어는 시스템 전체에 전혀 영향을 주지 않는다는 의미로 사용한 것입니다. AOP를 사용하면 한 시스템의 서로 다른 부분이 영향을 받게 되지만 간단한 프레임워크를 선택하고 뛰어난 프로그래밍 방식을 적용하면 부정적인 문제를 대부분 완화할 수 있습니다. Encase 프레임워크는 pointcut, mixin 및 aspect 위빙을 단순화하도록 설계되었습니다. 개발자는 대부분의 다른 간단한 AOP 프레임워크에 사용되는 XML 같은 구성 파일 대신 Encase가 있는 코드를 통해 aspect를 적용할 수 있습니다.

AOP가 널리 채택되지 않는 이유로는 복잡한 프레임워크를 꼽을 수 있겠지만, 가장 큰 원인은 현재 사용되고 있는 AOP 예제에서 찾을 수 있습니다. 이들 예제는 거의 모두가 실행 전에 메서드를 차단하고 Trace.WriteLine("Method entered.")을 실행하는 aspect를 적용하도록 구성되어 있습니다. 이러한 일반적인 인식과는 달리 AOP는 로깅, 보안, 계측 등을 제외한 문제를 해결하는 데 유용하게 사용할 수 있습니다.

Trace.WriteLine을 넘어서

AOP에 대한 보다 실제적인 접근 방식을 설명하기 위해 ContactService.Service라는 웹 서비스에서 사람 개체 컬렉션을 수신하는 응용 프로그램을 만들어 보겠습니다. 현재 .NET 개발에 웹 서비스를 사용하는 가장 일반적인 방법은 XML을 반환하는 웹 서비스를 호출하고 프레임워크에서 자동으로 이 XML을 개체로 deserialize하는 것입니다. 이러한 개체에는 데이터만 있고 동작은 들어 있지 않습니다. .NET Framework 2.0에서는 partial 키워드를 사용하고 동작을 만들어 이러한 자동 코드 생성 개체에 기능을 추가할 수 있습니다. 그러나 다양한 웹 서비스(또는 프록시) 개체에서 일부 특정 동작을 다시 사용하려고 하면 여전히 문제가 발생하게 됩니다. 앞서 언급했듯이 대부분의 경우 공유하는 공통 동작은 추상 클래스에 있고 다른 모든 클래스는 이 클래스에서 상속됩니다. 그러나 웹 서비스 개체를 사용하면 개체에서 기능을 상속할 수 없습니다. 이 문제는 AOP가 얼마나 강력한지 보여 줄 수 있는 좋은 기회로 활용할 수 있습니다.

여기서 소개하는 응용 프로그램의 용도는 연락처 정보를 표시하는 것입니다. 본래는 정보를 표시하는 것이 목적이었지만 이제는 여기에 몇 가지 동작을 추가해야 합니다. 코드 샘플을 살펴보기 위해 TheAgileDeveloper.ContactService라는 가상 디렉터리를 만들어야 합니다. 이 디렉터리는 로컬 시스템에서 TheAgileDeveloper.ContactService 프로젝트가 위치한 폴더를 가리켜야 합니다.

참고   이 프로젝트는 http://localhost/TheAgileDeveloper.ContactService를 통해 액세스할 수 있어야 합니다.

그림 1. 응용 프로그램 스크린 샷

응용 프로그램에 있는 단일 뷰는 MainForm이라는 WinForm이며, 이 뷰에는 웹 서비스에서 반환된 연락처 개체가 ListView의 왼쪽에 표시됩니다. 연락처를 선택하면 오른쪽에 있는 텍스트 상자에 성과 이름, 그리고 웹 페이지가 표시됩니다. MainForm이 로드되면 ServiceManager 클래스를 호출하여 연락처 정보를 가져옵니다. 다음 ServiceManager 클래스는 언뜻 보면 폼과 웹 서비스 사이의 또 다른 계층을 제외하고는 값을 추가하지 않는 것처럼 보입니다. 그러나 이 클래스는 코드를 복제하지 않고도 웹 서비스에 새 기능을 추가할 수 있는 하나의 공간을 제공하므로 매우 중요한 역할을 수행합니다. 또 다른 이점으로는 전체 응용 프로그램에서 웹 서비스의 자취를 추상화하여 제거한다는 점을 들 수 있습니다.

Public Class ServiceManager    Public Shared Function GetAllContacts() As ContactService.Contact()        Dim service As ContactService.Service = New ContactService.Service        Dim contacts() As ContactService.Contact = service.GetAllContacts        Return contacts    End Function    Public Shared Sub SaveContact(ByVal contact As ContactService.Contact)        Dim service As ContactService.Service = New ContactService.Service        service.SaveContact(contact)    End SubEnd Class

이제 Reference.vb 파일의 TheAgileDeveloper.Client 프로젝트를 살펴보겠습니다. 이 프로젝트는 ContactService의 웹 참조를 가져올 때 wsdl.exe에 의해 만들어진 것입니다. 또한 이 프로젝트는 WSDL에서 다음 Contact 클래스를 자동으로 생성합니다.

'<remarks/>    <System.Xml.Serialization.XmlTypeAttribute(_  [Namespace]:=http://tempuri.org/TheAgileDeveloper.ContactService/Service1 _ )>  _    Public Class Contact                '<remarks/>        Public Id As Integer                '<remarks/>        Public FirstName As String                '<remarks/>        Public LastName As String                '<remarks/>        Public WebSite As String    End Class

위의 코드에서 현재 Contact 개체는 데이터만 처리합니다. 또한 이 코드는 wsdl.exe에 의해 자동으로 생성되며 다음에 다시 생성하면 모든 변경 내용을 잃어버리게 되므로 편집하지 않습니다. 여기서는 Save라는 메서드를 호출하여 개체를 저장하는 동작을 소개하겠습니다. 이 동작은 mixin을 사용하여 손쉽게 수행할 수 있습니다. mixin은 인터페이스 구현만 혼합할 수 있는 등의 제한 사항을 제외하면 다중 상속을 연상하게 합니다. 여기서 사용하는 Encase 프레임워크에는 개체를 가져와 래핑하는 Encaser 클래스가 들어 있습니다. 개체를 래핑하면 실제로 새 개체가 만들어지며(이 경우 새 Contact 개체) 여기에는 구성된 mixin과 pointcut이 포함됩니다.

mixin을 만들어 Contact 개체에서 Save 메서드를 호출하려면 인터페이스를 지정해야 하는데, 여기서는 이를 ISavable이라고 하겠습니다. 실제로 개체에 혼합될 것이 바로 이 ISavable 인터페이스입니다. 이 인터페이스는 ContactSave라는 또 다른 새로운 클래스에 구현해야 합니다.

Public Interface ISaveable    Sub Save()End InterfacePublic Class ContactSave    Implements ISavable    Public Contact As ContactService.Contact    Public Sub Save() Implements ISavable.Save        ServiceManager.SaveContact(Me.Contact)    End SubEnd Class

이 응용 프로그램에서 Contact 개체에 ContactSave 구현을 혼합하기에 가장 적합한 위치는 ServiceManager입니다. 이 동작을 혼합할 수는 있지만 클라이언트 코드, 즉 MainForm을 변경할 필요는 없습니다. 이는 mixin을 적용한 후에도 ContactContactSave가 통합된 새 Contact 개체가 여전히 본래의 Contact 형식을 유지하기 때문입니다. 다음은 이를 처리할 ServiceManager의 변경된 GetAllContacts 메서드입니다.

Public Shared Function GetAllContacts() As ContactService.Contact()        Dim service As ContactService.Service = New ContactService.Service        Dim contacts() As ContactService.Contact = service.GetAllContacts        '//각 contact 개체를 래핑합니다.        For i As Integer = 0 To contacts.Length-1            '//개체를 래핑하는            '//encaser의 새 인스턴스를 만듭니다.            Dim encaser As encaser = New encaser            '//ContactSave의 mixin 인스턴스를 추가합니다.            Dim saver As ContactSave = New ContactSave            encaser.AddMixin(saver)            '//Contact 및 ContactSave 구현을 사용하여            '//새 개체를 만듭니다.            Dim wrappedObject As Object = encaser.Wrap(contacts(i))            '//새로 래핑된 contact 개체를            '//이전 contact 개체에 할당합니다.            contacts(i) = DirectCast(wrappedObject, _              ContactService.Contact)             '//래핑된 개체의 형식이 여전히 동일한지 확인합니다.            '//새로 래핑된 Contact 개체를            '//혼합된 ContactSave의 대상 필드에 할당합니다.            saver.Target = contacts(i)        Next        Return contacts    End Function(참고: 프로그래머 코멘트는 샘플 프로그램 파일에는 영문으로 제공되며 기사에는 설명을 위해 번역문으로 제공됩니다.)

Mixin의 배후 구현

프레임워크에서 pointcut과 advice 또는 aspect를 적용하는 방법은 프레임워크별로 다르지만 적용 목적과 개념은 같습니다. 이 기사에서 Encaser가 개체를 래핑하면 실제로는 System.Reflection.Emit 네임스페이스의 클래스를 사용하여 MSIL 코드를 내보내 즉석에서 새 Contact 형식이 만들어집니다. 새 Contact 형식은 Contact 클래스에서 파생되므로 계속해서 형식을 공유하지만 새로 래핑된 개체에도 여기서 혼합한 ContactSave 개체에 대한 참조가 유지됩니다. ISavable.Save 메서드는 새 Contact 개체에 구현되므로 Save를 호출하면 실제로는 호출을 혼합된 ContactSave 개체에 위임하게 됩니다. 여기서의 이점은 새 Contact 개체를 혼합된 개체에 구현된 모든 인터페이스에 캐스팅할 수 있다는 점입니다.

그림 2. 래핑된 개체의 UML 다이어그램

.NET Framework 2.0의 부분 클래스 언어 기능을 사용하면 또 다른 partial 클래스에 Save 동작을 추가할 수 있는 것으로 생각할 수도 있습니다. 이는 가능한 일이지만 필자는 코드가 이전 버전의 .NET Framework 1.x와 호환되도록 하기 위해 이러한 방식을 피하고 있습니다. 이제 부분 언어 기능이 있으므로 이전 샘플에서도 일반적인 경우에는 mixin이 필요 없을 것입니다. 하지만 mixin은 개발자가 다른 비관련 개체의 계층 구조에 속한 개체의 다시 사용 가능한 동작을 혼합하도록 하여 partial 클래스보다 더 많은 작업을 수행할 수 있으므로 여전히 중요한 역할을 합니다. partial 키워드를 사용할 때 추가하는 코드는 클래스나 형식이 동일하며 물리적인 위치만 다릅니다. 다음에 소개할 mixin에서는 Contact 클래스에 국한되지 않고 대신 FieldUndoer라는 다시 사용 가능한 클래스인 동작을 추가하는 작업에 대해 설명하겠습니다. FieldUndoerIUndoable 인터페이스를 구현하며 수정된 개체를 원래 상태로 복원할 수 있도록 해 줍니다.

    Public Interface IUndoable        ReadOnly Property HasChanges() As Boolean        Sub Undo()        Sub AcceptChanges()    End Interface

HasChanges 속성은 변경 사항이 발생했음을 나타내며 Undo는 개체를 원래 상태로 되돌리고, AcceptChanges는 개체의 현재 변경 사항을 적용합니다. 따라서 나중에 Undo를 호출하면 마지막으로 변경 사항이 적용된 상태로 복원됩니다. 이 인터페이스가 부분 클래스에 구현된 경우 이 세 개의 메서드는 이 동작을 포함시킬 클래스마다 반복해서 복제되도록 구현되어야 합니다. 필자는 실용주의적인 성향의 프로그래머로 "한 번 코딩하여 한 번만 사용한다"는 원칙을 고수하려 노력하므로 코드를 복제하지 않을 뿐 아니라 복사하여 붙여넣는 경우도 상당히 적습니다. mixin을 사용하면 IUndoable을 구현하는 FieldUndoer 개체를 다시 사용할 수 있습니다. 필자는 이 새로운 기능을 ServiceManager에 다시 혼합하는 방법을 채택하고 있습니다. 모든 클라이언트 코드는 여전히 새로운 mixin을 인식하지 않으며 IUndoable 인터페이스를 사용해야 할 경우가 아니면 변경할 필요도 없습니다. MainFormContact 개체를 변경한 다음 undo를 클릭하여 이 동작을 테스트해 보십시오.

Public Shared Function GetAllContacts() As ContactService.Contact()        Dim service As ContactService.Service = New ContactService.Service        Dim contacts() As ContactService.Contact = service.GetAllContacts        '//각 contact 개체를 래핑합니다.        For i As Integer = 0 To contacts.Length-1            '//개체를 래핑하는            '//encaser의 새 인스턴스를 만듭니다.            Dim encaser As encaser = New encaser            '//ContactSave의 mixin 인스턴스를 추가합니다.            Dim saver As ContactSave = New ContactSave            encaser.AddMixin(saver)            '//FieldUndoer의 mixin 인스턴스를 추가합니다.            Dim undoer As FieldUndoer = New FieldUndoer            encaser.AddMixin(undoer)            '//Contact 및 ContactSave 구현을 사용하여            '//새 개체를 만듭니다.            Dim wrappedObject As Object = encaser.Wrap(contacts(i))            '//새로 래핑된 contact 개체를            '//이전 contact 개체에 할당합니다.            contacts(i) = DirectCast(wrappedObject, _              ContactService.Contact)             '//래핑된 개체의 형식이 여전히 동일한지 확인합니다.            '//새로 래핑된 Contact 개체를 대상 필드에 할당합니다.            saver.Target = contacts(i)            undoer.Target = contacts(i)        Next        Return contactsEnd Function

동작 위빙(Weaving)

mixin은 전체의 작은 부분에 지나지 않습니다. AOP가 진정한 인정을 받는 부분은 혼합된 동작이 함께 위빙될 때 나타납니다. 예를 들어 새 Contact 개체를 사용하는 경우 ISavable.Save 메서드를 호출하면 클라이언트 코드에서는 다음에 IUndoable.Undo를 호출할 때 마지막으로 저장된 변경 내용을 사용하도록 IUndoable.AcceptChanges 메서드를 호출해야 합니다. 이를 검토하여 작은 MainForm에 추가하는 것은 간단하지만 이 규칙을 단일 사용자 인터페이스보다 큰 시스템에 코딩하는 일은 상당한 노력이 요구되는 작업입니다. 이렇게 하려면 Save 메서드가 호출된 모든 항목을 찾은 다음 AcceptChanges를 추가로 호출해야 합니다. 또한 새 코드가 만들어지면 개발자는 Save를 호출할 때마다 이 기능을 잊지 않고 추가해야 합니다. 이는 곧바로 계단식 효과로 이어져 시스템을 순식간에 불안정한 상태로 만들고 추적하기 힘든 다양한 버그를 만들어 낼 수 있습니다. 하지만 AOP(Aspect-Oriented Programming)를 사용하면 이러한 메서드를 함께 위빙할 수 있습니다. 메서드를 위빙하려면 Save 메서드가 호출될 때 Contact 개체가 백그라운드에서 자동으로 AcceptChanges를 호출하도록 pointcut과 advice를 지정합니다.

응용 프로그램에 위빙을 구현하려면 ServiceManager에 코드 한 줄을 추가해야 합니다. 이 코드는 FieldUndoer mixin을 추가한 후에 추가합니다.

'//joinpoint를 저장한 다음 AcceptChanges 메서드를 실행합니다.encaser.AddPointcut("Save", "AcceptChanges") 

AddPointcut 메서드는 서로 다른 여러 개의 서명과 함께 오버로드되어 pointcut을 상당히 자유롭게 지정할 수 있도록 해 줍니다. 호출되는 AddPointcutSave 메서드에 해당하는 문자열을 joinpoint 이름으로, AcceptChanges라는 메서드를 실행할 advice로 사용합니다. 실행을 확인하려면 FieldUndoer.AcceptChanges 메서드와 ContactSave.Save 메서드에 각각 중단점을 설정합니다. MainFormSave 단추를 클릭하면 joinpoint가 차단되어 먼저 AcceptChanges 메서드인 advice를 실행하게 됩니다. advice의 실행이 완료되면 계속해서 Save 메서드를 실행합니다.

이 간단한 예제에서는 전체 응용 프로그램에 걸쳐 새 동작을 추가하는 매우 강력한 기능을 보여 주고 있습니다. AOP는 단순히 기능을 효과적으로 추가하는 방법이 아니라 든든한 조력자의 역할을 담당합니다. AOP는 코드를 다시 사용하고 시스템 관리 용이성을 향상시키는 등의 다양한 이점을 통해 새로운 요구 사항에 발맞추어 손쉽게 발전시켜 나갈 수 있도록 해줍니다. 그러나 이와 동시에 AOP를 잘못 사용하면 시스템 유지 관리에 매우 심각한 영향을 미칠 수 있으므로 AOP의 사용 시기와 방법을 적절히 알아 두는 것이 중요합니다.

정리

AOP는 아직 대규모 또는 중요한 프로덕션 시스템에 사용할 만큼 발전하지는 못했지만 언어에 대한 지원이 늘어나면 보다 널리 채택될 것으로 예상됩니다. 또한 AOP를 활용하는 소프트웨어 팩토리 같은 새로운 소프트웨어 개발 패러다임은 이러한 지원을 촉진하는 사례로 볼 수 있습니다. 현재 .NET 영역에는 다양한 AOP 프레임워크가 있으며 이들은 각각 고유한 접근 방식과 장단점을 보유하고 있습니다.

  • Encase (영문)—이 코드 샘플에 포함된 Encase 프레임워크는 AOP를 신속하게 실행하여 AOP의 기반이 되는 개념을 이해하는 수단으로 사용하기 위한 것입니다. Encase는 런타임에 개체에 개별적으로 추가할 수 있는 aspect를 적용합니다.
  • Aspect# (영문)—aspect를 선언 및 구성하는 언어를 기본적으로 제공하는 CLI를 위한 AOP 지원 호환 프레임워크입니다.
  • RAIL (영문)—RAIL 프레임워크는 가상 시스템에서 클래스를 JIT 컴파일 중일 때 aspect를 적용합니다.
  • Spring.NET (영문)—현재 널리 사용되는 Java Spring 프레임워크의 .NET 버전으로 향후 릴리스에 AOP와 함께 구현될 예정입니다.
  • Eos (영문)—C#을 위한 aspect 지향 확장입니다.

결론

이 기사의 목적은 기존의 로깅 또는 보안 예제에 비해 새롭고 보다 실제적인 AOP 적용 방식을 보여 주는 데 있습니다. AOP를 올바르게 사용하면 많은 이점이 있을 뿐 아니라 기존 프로그래밍 옵션으로는 불가능한 결과를 손쉽게 얻을 수 있습니다. 아울러 AOP의 적용 시기와 방법에 대한 결정을 내릴 때는 가능한 한 인터넷에 나와 있는 다양한 리소스를 검색하여 도움을 얻도록 합니다.

 


저자 소개

Matthew Deiters는 소프트웨어 개발에 깊은 관심을 갖고 있으며 ThoughtWorks에서 컨설턴트로 활동하고 있습니다. 또한 .NET Framework를 사용한 금융 및 보험 업계의 다양한 엔터프라이즈 시스템 개발 업무에 참여했습니다. 그는 XP 프로그래밍과 TTD 방법론을 높이 평가하며 인간이 겪는 문제의 대부분은 디자인 패턴이나 뛰어난 단위 테스트를 통해 해결할 수 있다고 생각하고 있습니다. Matthew의 개인 웹 페이지는 http://www.theagiledeveloper.com/ (영문)입니다.

Posted by tornado
|