프리즘 4.1 도움말 번역입니다



모듈러 응용프로그램 개발



모듈러 응용프로그램은 더 큰 응용프로그램으로 통합될 수 있는 ( 모듈이라는 이름을 가진 ) 기능적 유닛들의 집합으로 구성된 응용프로그램을 말합니다. 클라이언트 모듈은 응용프로그램의 전체적인 기능들의 일부를 캡슐화함며, 일반적으로 연관된 관심사들의 집합을 표현합니다. 그것은 응용프로그램 기능과 같은 관련 컴포넌트들의 집합을 포함하는데, 이 컴포넌트 집합은 사용자 인터페이스와 비즈니스 로직, 또는 로깅이나 구사용자 인증과 같은 응용프로그램-레벨 서비스들과 같은 응용프로그램 인프라스트럭쳐의 일부를 포함합니다. 모듈들은 서로 돌립적이지만, 느슨학 결합되는 방식으로 서로 통신할 수도 있습니다. 모듈러 응용프로그램들은 응용프로그램을 개발하고 테스트하고 배포하고 확장하기 쉽게 만들어 줍니다.


예를 들어, 개인 뱅킹 응용프로그램을 고려해 보십시오. 사용자는 단일한 유저 인터페이스를 통해 계정간에 돈을 이체하거나, 세금을 내거나, 개인 정보를 갱신하는 것과 같은 다양한 기능들에 접근할 수 있습니다. 그러나 보이는 장면 뒤에는, 이러한 각 기능들이 분리된 모듈로 캡슐화되어 있습니다. 이 모듈들은 서로 통신하며, 데이터베이스 서버나 웹 서비스들과 같은 백엔드 시스템들과 통신하고 있습니다. 응용프로그램 서비스들은 서로 다른 모듈들 내에 존재하는 다양한 컴포넌트들을 통합하고, 사용자와의 통신을 제어합니다. 사용자는 단일 응용프로그램처러 보이는 통합된 뷰를 보게 됩니다.


다음 그림은 다중 모듈들을 가진 모듈러 응용프로그램의 설계를 보여 줍니다.


모듈 조합




모듈러 응용프로그램들을 빌드하는 것의 이점들



당신은 아마도 어셈블리, 인터페이스, 클래스, 좋은 개체지향 설계 원칙의 도입을 통해 잘 구조화된 응용프로그램을 이미 빌드하고 있을 것입니다. 그렇지만, 별로 신경쓰지 않고 있다면, 당신의 응용프로그램은 아마 여전히 모놀리식( 모든 기능들이 응용프로그램 내부에서 강하게 결합되는 방식으로 구현되는 것을 의미 )일 것이며, 이는 응용프로그램을 개발하고, 테스트하고, 확장하고, 유지보수하기 힘들게 만들 수 있습니다.


반면에, 모듈러 응용프로그램 접근법은 응용프로그램의 대규모 기능 영역들을 구분하는데 도움을 줄 수 있으며, 그 기능들을 독립적으로 개발하고 테스트할 수 있도록 해 줍니다. 이는 개발 및 테스팅을 쉽게 만들어 줄 뿐만 아니라, 응용프로그램을 더욱 유연하게 만들어 주며, 나중에 확장하기 쉽게 만들어 줍니다. 모듈러 접근법의 이점은 당신의 전체 응용프로그램 구조가 더욱 유연하고 유지보수 가능하도록 만들어 줄 수 있다는 것입니다. 왜냐하면 그것은 응용프로그램을 관리 가능한 조각들로 나눌 수 있게 해 주기 때문입니다. 각 조각들은 특정 기능들을 캡슐화하고, 각 조각들은 명료하지만 느슨하게 결합된 대화 채널들을 통해서 통합됩니다.


모듈러 응용프로그램 개발을 위한 프리즘의 지원


프리즘은 모듈러 응용프로그램 개발 및 실시간 모듈 관리를 위한 지원을 제공합니다. 프리즘의 모듈러 개발 기능을 사용하면 시간을 절약할 수 있습니다. 왜냐하면 당신이 자신의 모듈성 프레임워크를 구현하고 테스트할 필요가 없어지기 때문입니다. 프리즘은 다음의 모듈러 응용프로그램 개발 기능을 지원합니다:

  • 이름있는 모듈들과 그것의 위치를 등록하기 위한 모듈 카탈로그를 제공; 당신은 다음과 같은 방식으로 모듈 카탈로그를 생성할 수 있습니다:
    • 코드나 Extensible Application Markup Language( XAML )에서 모듈을 정의함으로써...
    • Windows Presentation Foundation( WPF ) 에 대해 : 디렉토리 내의 모듈들을 검색함으로써, 중앙관리되는 카탈로그 내에 명시적으로 모듈들을 정의하지 않아도, 당신의 모든 모듈들을 로드할 수 있습니다.
    • WPF 에 대해: 구성 파일에 모듈들을 정의함으로써...
  • 초기화 모드와 종속성들을 지원하기 위해서, 모듈에 대한 선언적인 메타데이터 애트리뷰트들을 제공.
  • 모듈들 사이의 느슨한 결합을 지원하기 위해서, 종속성 주입 컨테이너와의 통합을 제공.
  • 모듈 로딩을 위해서:
    • 모듈들이 올바른 순서로 한 번만 로드되고 초기화되는 것을 보장하기 위해서, 중복 검사와 사이클 검사를 포함하는 종속성 관리를 제공합니다.
    • 응용프로그램 시작 시간을 최소화하기 위해서 모듈들에 대한 온디맨드 로딩 및 백그라운드 로딩을 제공합니다; 남은 모듈들은 백그라운드로 혹은 요구되는 시점에 로드되고 초기화될 수 있습니다.

핵심 개념들


이 섹션은 프리즘의 모듈성과 관련된 핵심 개념들을 소개하는데, IModule 인터페이스, 모듈 로딩 과정, 모듈 카탈로그, 모듈간 통신, 종속성 주입 컨테이너들과 관련한 내용들을 포함합니다.

IModule : 모듈러 응용프로그램들의 빌딩 블락


모듈은 기능에 대한 논리 컬렉션이며 리소스인데, 이는 개별적으로 개발되고, 테스트되고, 배포되고, 응용프로그램에 통합될 수 있는 방식으로 패키징됩니다. 패키지는 하나 이상의 어셈블리일 수 있으며, 느슨한 컬렉션이나 XAP 파일 내에 묶여 있을 수 있습니다. 각 모듈은 그 모듈을 초기화하고 응용프로그램에 그것의 기능을 통합하는 책임이 있는 중앙 클래스를 가지게 됩니다. 그 클래스는 IModule 인터페이스를 구현합니다. IModule 인터페이스를 구현하는 클래스의 존재는 그 패키지를 모듈로서 식별하는데 충분합니다. IModule 인터페이스는 Initialize 라고 명명된 단일 메서드를 가지는데, 이 안에서 당신은 모듈을 초기화하고 응용프로그램에 모듈의 기능성을 통합하기 위해서 요구되는 로직을 구현할 수 있습니다. 모듈의 목적에 따라, 뷰를 복합 유저 인터페이스에 추가하거나, 응용프로그램에서 이용 가능한 부가적인 서비스들을 만들거나, 응용프로그램의 기능성을 확장할 수 있습니다. 다음 코드는 모듈을 위한 최소 구현을 보여 줍니다.



노트:

IModule 인터페이스에 의해 제공되는 초기화 메커니즘을 사용하는 대신에, Stock Trader RI 는 뷰, 서비스, 타입을 등록하기 위해 선언적인 애트리뷰트 기반 접근법을 사용합니다.


모듈 라이프타임


프리즘에서 모듈 로딩 프로세스는 다음을 포함합니다:

  1. 모듈을 등록하고 검색하기. 특정 응용프로그램을 위해 런타임에 로드될 모듈들은 모듈 카탈로그에 정의됩니다. 이 카탈로그는 로드될 모듈에 대한 정보, 그것들의 위치, 그리고 로드될 순서에 대한 정보를 포함합니다.
  2. 모듈 로드하기. 모듈들을 포함하는 어셈블리는 메모리에 로드됩니다. 이 단계는 모듈들이 웹으로부터 다운로드되거나, 원격 위치나 로컬 디렉토리로부터 획득될 것을 요청합니다.
  3. 모듈 초기화하기. 그 다음, 모듈들이 초기화됩니다.  이는 모듈 클래스의 인스턴스를 생성하고 IModule 인터페이스를 통해 그것들의 Initialize 메서드를 호출하는 것을 의미합니다.

다음 그림은 모듈 로딩 과정을 보여줍니다.

모듈 로딩 과정





모듈 카탈로그


ModuleCatalog 는 응용프로그램에서 사용할 수 있는 모듈들에 대한 정보를 저장합니다. 이 카탈로그는 본질적으로 ModuleInfo 클래스들의 컬렉션입니다. 각 모듈은 ModuleInfo 클래스에서 기술되는데, 이는 이름, 타입, 위치, 그리고 모듈의 다른 애트리뷰트들을 기록합니다. ModuleCatalog ModuleInfo 인스턴스들로 채우기 위한 몇 가지 일반적인 접근법들이 존재합니다:

  • 코드에서 모듈들을 등록하기
  • XAML 에서 모듈들을 등록하기
  • 구성 파일에서 모듈들을 등록하기( WPF 만 )
  • 디스크의 로컬 디렉토리에서 모듈들을 검색하기( WPF 만 )


당신이 사용할 모듈 등록 및 검색 메커니즘은 응용프로그램의 요구에 달려 있습니다. 구성 파일이나 XAML 파일을 사용하는 것은 응용프로그램이 모듈에 대한 레퍼런스들을 요구하지 않도록 해 줍니다. 디렉토리를 사용하는 것은 응용프로그램이 파일에 그것들을 지정하지 않고도 모듈들을 검색할 수 있게 해 줍니다.


모듈을 로드할 시점을 제어하기


프리즘 응용프로그램들은 가능한 한 빨리 모듈들을 초기화할 수 있는데, 이는 "이용 가능할 때( when available )" 로 알려져 있습니다. 그리고 응용프로그램이 그것을 필요로 할 때 초기화할 수 있는데, 이는 "온디맨드( 요청시, on-demand )"로 알려져 있습니다. 실버라이트 응용프로그램에 대해, 모듈들은 응용프로그램과 함께 다운로드되거나, 응용프로그램 시작 후에 백그라운드로 다운로드될 수 있습니다. 모듈을 로드하기 위한 다음 가이드라인을 고려하십시오:

  • 응용프로그램을 실행하기 위해서 요구되는 모듈들은 반드시 응용프로그램과 함께 다운로드되어야만 하고, 응용프로그램이 실행될 때 초기화되어야만 합니다.
  • 응용프로그램의 일반적인 용도를 위해서 항상 사용되는 기능들을 포함하는 모듈들은 그것들이 이용 가능해질 때 백그라운드로 다운로드되거나 초기화될 수 있습니다.
  • 거의 사용되지 않는 모듈들은( 혹은 다른 모듈들을 위해서 선택적인 의존성을 가지는 지원 모듈들은 ) 백그라운드로 다운로드되고 요청시에 초기화될 수 있습니다.

응용프로그램에 모듈들을 통합하기

프리즘은 응용프로그램을 구동( bootstrap )하기 위해 다음의 클래스들을 제공합니다: UnityBootstrapper MefBootstrapper. 이 클래스들은 모듈들을 검색하거나 로드하기 위한 모듈 관리자를 생성하고 구성하는데 사용될 수 있습니다. XAML 파일이나, 구성 파일, 몇 줄의 코드에 기입된 디렉토리 위치에서 지정된 모듈들을 등록하기 위해 구성 메서드를 재정의할 수 있습니다.

모듈 Initialize 메서드를 사용해서 모듈들을 응용프로그램의 나머지 부분과 통합하십시오. 당신이 택할 수 있는 방식은 다양하며, 이는 응용프로그램 구조와 모듈의 내용에 의존하게 됩니다. 다음은 모듈을 응용프로그램ㄹ에 등록하기 위해서 수행해야 하는 공통적인 작업들입니다:
  • 모듈의 뷰를 응용프로그램의 네비게이션 구조에 추가하십시오. 이는 복합 UI 응용프로그램을 뷰 검색이나 뷰 주입을 사용해 빌드할 때 공통적인 작업입니다.
  • 응용프로그램 레벨 이벤트나 서비스를 구독( subscribe )하십시오.
  • 공유 서비스들을 응용프로그램의 종속성 주입 컨테이너에 등록하십시오.

모듈 간에 통신하기


비록 모듈들이 모듈간에 저수준 결합을 하고 있기는 하지만, 모듈간에 서로 통신하는 것은 일반적인 상황입니다. 몇 가지 느슨하게 결합된 통신 패턴이 존재하는데, 각각은 자신만의 강도를 가집니다. 일반적으로, 이 패턴들의 조합은 결과적인 솔루션을 생성하는데 사용됩니다. 다음은 이러한 패턴의 일부를 소개합니다:

  • 느슨하게 결합된 이벤트들. 모듈은 발생한 특정 이벤트를 발송할( broadcast )수 있습니다. 다른 모듈들은 그 이벤트를 구독해서, 언제 이벤트가 발생했는지를 통지받을 것입니다. 느슨하게 결합된 이벤트들은 두 모듈 사이에 통신을 설정하기 위한 가벼운 방식입니다; 그러므로, 그것들은 쉽게 구현됩니다. 그러나, 너무 이벤트에 의존하는 설계는 단일 작업을 만족시키기 위해서 서로를 열심히 조율하는 일을 필요로 하게 만듭니다. 이 경우, 공용 서비스를 고려하는 것이 더 나을 것입니다.
  • 공유 서비스. 공유 서비스는 공통 인터페이스를 통해 접근될 수 있는 클래스를 의미합니다. 일반적으로, 공유 서비스는 공유 어셈블리에서 발견되며, 인증이나 로깅, 혹은 구성과 같이 전 시스템에 걸친 서비스를 제공합니다.
  • 공유 리소스. 만약 당신이 직접적으로 다른 모듈과 서로 통신하는 모듈들을 원하고 있다면, 간접적으로 데이터베이스나 웹 서비스 집합과 같은 공유 리소스들을 통해 그것들을 통신하게 만들 수 있습니다.

의존성 주입과 모듈러 응용프로그램


유니티 응용프로그램 블락( Unity ) 와 관리되는 의존성 프레임워크( MEF ) 같은 컨테이너들은 쉽게 제어 역전( Inversion of Control,  IoC ) 과 의존성 주입을 사용할 수 있게 해 줍니다. 이는 느슨하게 결합하는 방식으로 컴포넌트를 조립하는데 도움을 주는 강력한 설계 패턴입니다. 제어 역전은 어떤 컴포넌트가 자신이 의존하고 있는 다른 컴포넌트에 대한 레퍼런스를 획득하기 위해, 그 레퍼런스에 대한 하드코딩을 하지 않고도, 레퍼런스를 획득할 수 있도록 해 줍니다. 결과적으로 코드 재사용성을 높이고 유연성을 증가시킬 수 있도록 합니다. 의존성 주입은 느슨하게 결합된 모듈러 응용프로그램을 빌드할 때 유용합니다. 프리즘은 응용프로그램 내에서 컴포넌트를 조립하기 위해서 사용되는 의존성 주입 컨테이너에 대한 불가지론( agnostic )으로 설계되었습니다. 컨테이너에 대한 선택은 당신에게 달려 있으며, 그것은 응용프로그램 요구사항 및 선호도에 크게 의존합니다. 그러나, 마이크로소프트가 제안하는 두 가지 주요 의존성 주입 프레임워크가 존재하기는 합니다 - Unity 와 MEF 가 바로 그것입니다.


패턴 & 경험의 유니티 응용프로그램 블락은 완전한 기능을 갖춘 의존성 주입 컨테이너를 제공합니다. 그것은 프라퍼티-기반 주입, 생성자-기반 주입, 그리고 정책( policy ) 주입을 지원합니다. 이는 당신이 컴포넌트 간에 행위와 정책을 투명하게 주입할 수 있도록 해 줍니다; 또한 의존성 주입 컨테이너에서 일반적인 다른 기능들에 대한 호스트도 지원합니다.


( 이제 닷넷 프레임워크 4 와 실버라이트 4 의 일부인 ) MEF는 의존성 주입-기반 컴포넌트 조립을 지원함으로써 확장성 있는 닷넷 응용프로그램을 빌드하기 위한 지원을 제공합니다. 그리고 모듈러 응용프로그램 개발을 지원하는 다른 기능들을 제공합니다. 이는 응용프로그램이 런타임에 컴포넌트들을 검색하고 그 컴포넌트들을 응용프로그램에 느슨하게 결합된 방식으로 통합할 수 있도록 해 줍니다. MEF 는 훌륭한 확장성 및 복합 프레임워크입니다. 이는 어셈블리, 타입 검색, 타임 종속성 결정( resolution ), 의존성 주입, 그리고 일부 좋은 어셈블리와 XAP 다운로드 기능들을 제공합니다. 프리즘은 MEF 기능의 이점을 취하기 위한 지원 외에도 다음을 지원합니다:

  • 모듈 타입과 그것의 XAP 위치를 연관시킵니다.
  • WPF 와 실버라이트 모두에 대해, XAML 과 코드 애트리뷰트를 통한 모듈 등록을 지원합니다.
  • WPF 에 대해, 구성 파일과 디렉토리 스캔을 통한 모듈 등록을 지원합니다.
  • 모듈이 로드될 때 상태 트래킹을 지원합니다.
  • MEF 가 사용될 때 모듈에 대한 선언적인 커스텀 메타데이터를 지원합니다.
유니티와 MEF 는 프리즘을 사용해 유사하게 동작합니다.

핵심 결정들


첫 번째 해야 할 결정은 어떤 모듈러 솔루션을 개발할 것인가 입니다. 이전 섹션들에서 논의된 것처럼, 모듈러 응용프로그램들을 빌드하는 것은 다양한 이점들을 가지고 있습니다만, 이러한 이점들을 취하기 위해 당신이 들여야 하는 시간과 노력의 관점에서 생각을 해 볼 필요가 있습니다. 만약 모듈러 응용프로그램을 개발하기로 했다면, 고려해야 할 점이 몇 가지 있습니다:
  • 당신이 사용할 프레임워크를 결정하십시오. 당신은 자신만의 모듈성 프레임워크를 생성할 수도 있고, 프리즘, MEF 나 다른 프레임워크를 사용할 수도 있습니다.
  • 당신의 솔루션을 조직할 방식을 결정하십시오. 어떤 어셈블리가 각 모듈의 일부가 될 것인지를 포함해, 각 모듈의 경계를 정의함으로써 모듈러 구조에 접근하십시오. 당신은 개발을 쉽게 하기 위해서 모듈성을 사용하기로 결심할 수도 있으며, 또한 그것이 플러그인을 지원하거나 확장성있는 구조를 지원하게될 때 응용프로그램이 배포되는 방식을 제어해야만 하겠다고 결심할 수도 있습니다.
  • 당신의 모듈들을 나누는 방식을 결정하십시오. 모듈들은 요구에 따라 서로 다르게 나뉠 수 있습니다. 예를 들어, 기능 영역, 프로바이더 모듈들, 개발 팀, 배포 요구사항에 의해 나뉠 수 있습니다.
  • 응용프로그램이 모든 모듈들에 대해 제공해야할 핵심 서비스들을 결정하십시오. 핵심 서비스는 에러 기록 서비스이거나 인증 서비스이거나 권한 서비스일 수 있습니다.
  • 만약 프리즘을 사용하고 있다면, 모듈을 모듈 카탈로그에 등록하기 위해서 사용할 접근법을 결정하십시오. WPF 에 대해, 당신은 코드, XAML, 구성 파일, 디스크의 로컬 디렉토리에서 검색된 모듈에서 모듈을 등록할 수 있습니다. 실버라이트에 대해, 당신은 코드나 XAML 에서 모듈들을 등록할 수 있습니다.
  • 당신의 모듈 통신 전략 및 의존성 전략을 결정하십시오. 모듈들은 서로 통신할 필요가 있을 것입니다. 그리고 당신은 모듈간의 종속성들을 다룰 필요가 있습니다.
  • 의존성 주입 컨테이너를 결정하십시오. 일반적으로, 모듈러 시스템은 의존성 주입, 제어 역전, 서비스 로케이터를 요구하며, 이것들을 통해 느슨한 결합과 모듈에 대한 동적 로딩 및 생성이 허용됩니다. 프리즘은 유니티, MEF, 혹은 다른 컨테이너를 사용하는 것을 허용하며, 유니티나 MEF 기반 응용프로그램들을 위한 라이브러리들을 제공합니다.
  • 응용프로그램 시작 시간을 최소화하십시오. 응용프로그램 시작 시간을 최소화하기 위해서, 모듈에 대한 온디맨드 로딩 및 백그라운드 다운로딩을 고려하십시오.
  • 배포 요구사항을 결정하십시오. 당신의 응용프로그램이 배포되는 방식에 대해서 생각할 필요가 있습니다. 이는 XAP 에 설정할 어셈블리의 개수에 영향을 줍니다. 또한 실버라이트에서 어셈블리 캐싱의 이점을 취하기 위해서는 프리즘 라이브러리와 같은 공유 라이브러리를 분할해야 할 것입니다.
다음 섹션에서는 이러한 결정들에 대한 세부 사항들을 제공합니다.

응용프로그램을 모듈로 분할하기

응용프로그램을 모듈화된 방식으로 개발할 때, 응용프로그램을 분리된 클라이언트 모듈로 구조화하게 되는데, 이 모듈들은 개별적으로 개발되고, 테스트되고, 배포될 수 있습니다. 각 모듈은 응용프로그램의 전체적인 기능의 일부를 캡슐화할 것입니다. 당신이 해야할 첫 번째 설계 결정은 응용프로그램의 기능을 분리된 모듈들로 분할하는 방식을 결정하는 것입니다.

모듈은 연관된 관심사들의 집합을 캡슐화해야 하며, 뚜렷한 책임을 지녀야 합니다. 모듈은 응용프로그램에 대한 수직적 슬라이스를 표현하거나 수평적 서비스 레이어를 표현할 수 있습니다. 큰 응용프로그램들은 비슷하게 두 종류의 모듈들을 모두 가지게 될 것입니다.

수직적 슬라이스로 조직화된 모듈을 가진 응용프로그램


수평적 레이어로 조직화된 모듈을 가진 응용프로그램


큰 응용프로그램은 수직적인 슬라이스와 수평적 레이어로 조직화된 모듈들을 가질 것입니다. 그러한 모듈들의 예는 다음을 포함합니다:

  • Stock Trader Reference Implementation( Stock Trader RI ) 의 News 모듈과 같은 특정 응용프로그램 기능을 포함하고 있는 모듈.
  • 구입, 송장, 총 계정 원장과 같은 연관된 유스케이스의 집합에 대한 특정 서브시스템이나 기능들을 포함하는 모듈.
  • 로깅, 캐싱, 권한 서비스, 웹 서비스와 같은 인프라스트럭쳐 서비스들을 포함하는 모듈.
  • 다른 내부 시스템과 더불어 Siebel CRM, SAP 와 같은 기업용 비즈니스 프로그램( line-of-business, LOB ) 시스템들을 실행하는 서비스들을 포함하는 모듈.

모듈은 다른 모듈들에 대한 최소 집합의 의존성들을 가져야 합니다. 모듈이 다른 모듈에 대한 의존성을 가지게 될 때, 그것은 콘크리트 타입 대신에 공유 라이브러리에 정의된 인터페이스를 사용하거나, EventAggregator 이벤트 타입들을 통해 다른 모듈들과 통신하기 위해서 EventAggregator 를 사용함으로써 느슨하게 결합되어야 합니다.

모듈성의 목표는 기능이나 기술이 추가되거나 삭제되더라도 응용프로그램을 유연하고, 유지보수 가능하고, 안전적인 상태로 유지하는 것이 가능한 방식으로 응용프로그램을 분할하는 것입니다. 이를 수행하기 위한 가장 최선의 방법은 모듈들이 가능한 한 독립적이고, 잘 정의된 인터페이스를 가지고, 가능한 한 고립되도록 응용프로그램을 설계하는 것입니다.

모듈들에 대한 프로젝트의 비율을 결정하기

모듈들을 생성하고 패키징하는 몇 가지 방법이 있습니다. 추천할 만하고 가장 공통적으로 사용되는 방법은 모듈당 단일 어셈블리를 생성하는 것입니다. 이는 논리 모듈들이 분리를 유지하고 적절하게 캡슐화 정도를 높이는데 도움을 줍니다. 또한 그것은 어셈블리를 모듈 경계라고 이야기하기 쉽게 만들어 줄 뿐만 아니라 모듈을 배포하는 방식에 대한 패키징을 쉽게 만들어 줍니다. 그러나, 단일 어셈블리가 다중의 모듈을 가지는 것을 막을 수는 없으며, 어떤 경우에 이는 솔루션 내의 프로젝트 개수를 최소화하기 위해서 선호되기도 합니다. 큰 응용프로그램에서, 10 개에서 50 개의 모듈들을 가지는 것은 일반적이지 않습니다. 각 모듈들을 자신의 프로젝트에 분리해 넣는 것은 솔루션에 너무 많은 복잡성을 추가하는 것이며, 비주얼 스튜디오의 성능을 저하시킬 수 있습니다. 만약 당신이 하나의 모듈당 하나의 어셈블리/비주얼 스튜디오 프로젝트로 가기로 결정했다면, 모듈이나 모듈 집합을 관리하기 위해서 자신의 솔루션에 나눠서 넣는 것도 이치에는 맞습니다.

XAP 와 모듈 팩토링

실버라이트 응용프로그램에 대해, 모듈들은 일반적으로 분리된 XAP 파일에 패키징됩니다만, 일부 경우에는 XAP 당 하나 이상의 모듈들을 가지고 있을 수 있습니다. 응용프로그램을 시작하고 새로운 기능들을 가능하게 만들기 위해서 요구되는 다운로드 요청의 횟수와 크기를 최소화하기 위해서 필요한 XAP 파일의 개수가 몇 개나 될지 고려해야 합니다. 만약 각 모듈을 자신만의 프로젝트/어셈블리로 분리하기로 했다면, 각 어셈블리를 그것들만의 XAP 에 배치할지 혹은 다중 어셈블리들을 하나의 XAP 에 포함시킬지를 결정할 필요가 있습니다.

다중 모듈들을 하나의 XAP 에 포함시킬지 그것들을 분리할지를 선택하는데 영향을 주는 요소들은 다음과 같습니다:
  • 다운로드 크기 및 공유 종속성들. 각 XAP 파일은 자신의 매니페스트 및 .zip 패키징에서 작은양의 부가적인 크기 오우버헤드를 가지게 됩니다. 또한, 모듈들 간에 공통 종속성이 존재하고 그것들이 종속적 모듈이나 캐싱된 라이브러리와 분리되어 있지 않다면, 각 XAP 는 그러한 종속적인 라이브러리들을 포함할 것이고, 이는 다운로드 크기를 심각하게 증가시킬 수도 있습니다.
  • 다중 모듈들이 응용프로그램에 의해 필요하게 될 때의 시점. 응용프로그램의 시작시에 뷰를 제출하는 것과 같이 다중 모듈들이 동시에 로드되고 사용된다면,그것들을 하나의 XAP 에 패키징하는 것이 약간 더 빠르며, 동시에 클라이언트에 대해 물리적으로 이용 가능한 상태가 되도록 보장하는데도 도움이 됩니다. 프리즘의 모듈성 기능은 종속성들을 지정하는 모듈들이 올바른 순서로 로드되는 것을 보장하며, 그래서 모듈들이 다중 XAP 들에 나뉘어 있을 때도 임포터 로드 오더가 필요하지 않도록 만들 수 있습니다. 그러나 하나가 아니라 두 개의 다운로드를 만들면 약간의 성능 오우버헤드가 존재합니다. 심지어는 전체적으로 같은 다운로드 크기를 가지고 있더라도 그렇습니다.
  • 모듈 버저닝( Versioning ). 만약 서로 다른 모듈들이 독립적인 타임라인에서 개발되고 잠재적으로 개별적으로 배포될 것이라고 하면, 당신은 그것들을 개별 XAP 들에 배치하기를 원할 것이고, 그것들은 명확하고 독립적으로 갱신되도록 하기 위해서 서로 다른 버전으로 표기될 수 있을 것입니다.

개별 XAP 파일들에서 같은 어셈블리를 중복으로 다운로드하는 것을 피하기 위한 두 가지 접근법들이 사용될 수 있습니다:

  • 공유 종속성들을 개별 인프라스트럭쳐로 분리하는 것을 고려하고, 사용되는 모듈들이 그 공유 모듈들에 대한 종속성을 가지도록 하십시오.
  • 실버라이트의 공유 라이브러리 캐싱을 사용해서 공유 타입들을 공유 라이브러리에 배치하십시오. 이는 프리즘 모듈 다운로더 대신에 실버라이트에 의해서 한 번만 다운로드되고 캐싱됩니다.


느슨한 결합을 위해 종속성 주입 사용하기


하나의 모듈은 호스트 응용프로그램이나 다른 모듈들이 제공하는 컴포넌트들과 서비스들에 의존할 것입니다. 프리즘은 모듈들 간의 종속성을 등록하는 기능을 지원하고 있어서, 그것들은 올바른 순서로 로드되고 초기화됩니다. 또한 프리즘은 모듈들이 응용프로그램에 로드될 때 초기화되도록 지원합니다. 모듈 초기화 동안에, 모듈은 그것이 요구하는 부가적인 컴포넌트들과 서비스들에 대한 참조를 획득할 수 있습니다. 그리고 다른 모듈들에서 이용 가능하게 만들기 위해서 그것이 포함하고 있는 컴포넌트들과 서비스들을 등록할 수도 있습니다.


모듈은 콘크리트 타입을 직접적으로 인스턴스화하는 대신에 외부 인터페이스의 인스턴스를 획득하기 위한 독립적인 메커니즘을 사용해야 합니다. 예를 들어, 종속성 주입 컨테이너나 팩토리 서비스를 사용할 수 있습니다. 유니티나 MEF 와 같은 종속성 주입 컨테이너들은 종속성 주입을 통해 어떤 타입이 필요로 하는 인터페이스나 타입의 인스턴스를 자동적으로 요청해 줍니다. 프리즘은 유니티와 MEF 를 통합하고 있으며, 이는 모듈들이 쉽게 종속성 주입을 사용할 수 있도록 해 줍니다.


다음 다이어그램은 컴포넌트들과 서비스들에 대한 참조를 요청하거나 등록할 필요가 있는 모듈들이 로드될 때의 일반적인 작업 과정을 보여 줍니다.


종속성 주입의 예




이 예제에서, OrdersModule 어셈블리는 OrdersRepository 클래스를 정의합니다( 이와 함께 주문 기능을 구현하는 다른 뷰들과 클래스들도 정의합니다 ). CustomersModule 어셈블리는 CustomersViewModel 클래스를 정의하는데, 이는 OrdersRepository 에 의존하며, 일반적으로 서비스에 의해 노출된 인터페이스에 의존합니다. 응용프로그램 시작과 부트스트래핑 절차는 다음과 같은 단계들을 포함합니다:

  1. 부트스트래퍼는 모듈 초기화 프로세스를 시작합니다. 그리고 나서 모듈 로더는 OrdersModule 을 로드하고 초기화합니다.
  2. OrdersModule 초기화 과정중에, 그것은 OrdersRepository 를 컨테이너에 등록합니다.
  3. 그리고 나서 모듈 로더는 CustomersModule 을 로드합니다. 모듈 로딩의 순서는 모듈 메타데이터의 종속성들에 의해 지정될 수 있습니다.
  4. CustomersModule CustomersViewModel 의 인스턴스를 컨테이너를 통해 그것을 결정( resolve )함으로써 생성합니다. 그 CustomersViewModel OrdersRepository 에 ( 일반적으로 인터페이스에 기반해 ) 종속성을 가지고 있으며, 생성자 주입이나 종속성 주입을 통해서 그것을 지정합니다. 컨테이너는 OrdersModule 에 의해 등록된 타입에 기반한 뷰 모델을 생성하는 와중에 종속성을 주입합니다. 최종 결과물은 CustomerViewModel 에서 OrderRepository 로의 인터페이스 레퍼런스이며, 두 클래스들 간에는 강한 결합이 존재하지 않습니다.
노트:
OrderRepository( IOrderRespository ) 를 노출하는 인터페이스는 분리된 "공유 서비스들" 어셈블리나 "주문 서비스들" 어셈블리에 존재할 수도 있습니다. 그 어셈블리들은 단지 서비스 인터페이스들과 그 서비스들을 노출하기 위해 요구되는 타입들 만을 포함하고 있습니다. 이러한 방식으로, CustomersModuleOrdersModule 사이에는 강한 종속성이 존재하지 않습니다.


두 모듈은 공히 묵시적인 종속성을 종속성 주입 컨테이너 상에서 가지고 있음에 주의하십시오. 이 종속성은 모듈 로더에서 모듈 생성을 하는 동안에 주입됩니다.


핵심 시나리오들



이 섹션에서는 응용프로그램에서 모듈을 사용해서 작업할 때 직면하게 될 공통적인 시나리오들에 대해 기술합니다. 이 시나리오들은 모듈 정의하기, 모듈 등록하고 검색하기, 모듈 로드하기, 모듈 초기화하기, 모듈 종속성 지정하기, 요청시 모듈 로드하기, 백그라운드로 원격 모듈 다운로드하기, 모듈이 이미 로드되었는지 확인하기 등이 포함됩니다. 코드나 XAML, 혹은 응용프로그램 구성 파일, 혹은 로컬 디렉토리 스캐닝을 통해서 모듈을 등록하고 검색할 수 있습니다.


모듈 정의하기


모듈은 개별적으로 개발되고 테스트되고 배포되고 응용프로그램에 통합될 수 있는 방식으로 패키징되는 기능 및 리소스에 대한 논리 컬렉션입니다. 각 모듈은 모듈을 초기화하고 그것의 기능을 응용프로그램에 통합하기 위한 책임이 있는 중앙 클래스를 가지고 있습니다. 이 클래스는 다음과 같이 IModule 인터페이스를 구현합니다.



Initialize 메서드를 구현하는 방법은 응용프로그램의 요구에 달려 있습니다. 모듈 클래스 타입, 초기화 모드, 그리고 모든 모듈 종속성들은 모듈 카탈로그에 정의됩니다. 카탈로그 안의 각 모듈에 대해, 모듈 로더는 모듈 클래스의 인스턴스를 생성하고, 그 다음 Initialize 메서드를 호출합니다. 모듈들은 모듈 카탈로그에서 지정된 순서로 처리됩니다. 런타임 초기화 순서는 모듈들이 다운로드되고, 이용가능해지고, 종속성들을 만족시킬 때가 언제인지에 기반합니다.


응용프로그램이 사용중인 모듈 카타로그의 타입에 기반해서, 모듈 클래스 자체의 선언적인 애트리뷰트들에 의해서 모듈 종속성들이 설정되거나, 모듈 카탈로그 파일 내부에서 모듈 종속성들이 설정될 수 있습니다. 다음 섹션들은 세부 사항들을 제공합니다.


모듈을 등록하고 검색하기


응용프로그램이 로드할 수 있는 모듈들은 모듈 카탈로그에 정의됩니다. 프리즘 모듈 로더는 모듈 카탈로그를 사용해서 응용프로그램에 로드될 수 있는 모듈이 무엇인지, 언제 그것을 로드할지, 어떤 순서로 로드할지를 결정합니다.


모듈 카탈로그는 IModuleCatalog 인터페이스를 구현하는 클래스에 의해 표현됩니다. 모듈 카탈로그 클래스는 응용프로그램 부트스트래퍼 클래스에 의해서 응용프로그램 초기화 동안에 생성됩니다. 프리즘은 모듈 카탈로그의 여러 구현을 제공하기 때문에, 여러 분은 그것을 선택할 수 있습니다. 또한 AddModule 메서드를 호출하거나 사용자 정의 행위를 가진 모듈 카탈로그를 생성하기 위해 ModuleCatalog 를 상속함으로써, 다른 데이터 소스로부터 모듈 카탈로그를 덧붙일 수 있습니다.


노트:

일반적으로, 프리즘에서의 모듈은 종속성 주입 컨테이너와 공용 서비스 로케이터를 사용해서 모듈 초기화를 위해 요구되는 타입들의 인스턴스들을 획득합니다. 유니티와 MEF 는 모두 프리즘에 의해 지원됩니다. 비록 등록, 검색, 다운로딩, 초기화의 전체 과정이 동일하지만, 그 세부사항은 유니티가 사용되느냐 아니면 MEF 가 사용되느냐에 따라서 매우 달라질 수 있습니다. 접근법들 사이의 컨테이너-지정 차이점들은 이 토픽을 통해 설명됩니다.


코드에서 모듈 등록하기


가장 기본적인 모듈 카탈로그는 ModuleCatalog 클래스에 의해 제공됩니다. 이 모듈 카탈로그를 사용해서 여러 분은 모듈 클래스 타입을 지정함으로써 모듈들을 프로그램적으로 등록할 수 있습니다. 또한 프로그램적으로 모듈 이름과 초기화 모드를 지정할 수도 있습니다. ModuleCatalog 클래스에 모듈을 직접적으로 등록하기 위해서는, AddModule 메서드를 응용프로그램의 Bootstrapper 클래스에서 호출하십시오. 그 예는 다음 코드에 나와 있습니다.



앞의 예제에서, 모듈들은 쉘에 의해 직접적으로 참조되며, 그 모듈 클래스 타입들이 정의되어, AddModule 에 대한 호출에서 사용될 수 있습니다. 이것이 예제가 모듈들을 카탈로그에 등록하기 위해 typeof( Module ) 을 사용하는 이유입니다.


노트:

만약 응용프로그램이 모듈 타입에 대한 직접 참조를 가지고 있다면, 여러 분은 위에서 보이듯이 타입에 의해 그것을 추가할 수 있습니다; 그렇지 않다면 fully qualified type name 과 어셈블리의 위치를 제공할 필요가 있습니다.


코드에서 모듈 카탈로그를 정의하는 다른 예제를 보고 싶다면, Stock Trader Reference Implementation( Stock Trader RI ) 의 StockTraderRIBootstrapper.cs 를 살펴 보십시오.


노트:

Bootstrapper 클래스는 CreateModuleCatalog 메서드를 제공해서 ModuleCatalog 의 생성을 돕도록 합니다. 기본적으로, 이 메서드는 ModuleCatalog 인스턴스를 생성합니다. 그러나 다른 유형의 모듈 카탈로그를 생성하기 위해, 상속 클래스에서 이 메서드를 재정의할 수 있습니다.


XAML 파일을 사용해서 모듈 등록하기


XAML 파일에서 모듈 카탈로그를 지정함으로써 모듈 카탈로그를 선언적으로 정의할 수 있습니다. XAML 파일은 어떤 종류의 모듈 카탈로그 클래스를 생성하고, 어떤 모듈들이 그것에 추가되어야 하는지를 지정합니다. 보통, .xaml 파일은 쉘 프로젝트의 리소스로 추가됩니다. 모듈 카탈로그는 부트스트래퍼에 의해 생성되는데, CreateFromXaml 메서드를 호출해야 합니다. 기술적인 관점에서 볼 때, 이 접근법은 코드에서 ModuleCatalog 를 정의하는 것과 매우 유사합니다. 왜냐하면 XAML 파일은 단순히 인스턴스화될 오브젝트의 계층을 정의할 뿐이기 때문입니다.


다음 코드 예제는 XAML 파일이 모듈 카탈로그를 정의하는 것을 보여 줍니다.



노트:

ModuleInfoGraoups 는 같은 .xap 파일이나 어셈블리에 존재하고, 같은 방식으로 초기화되고, 같은 그룹 내의 모듈에 대한 종속성만을 가지는 모듈들을 그룹화하는 편리한 방법을 제공합니다. 

모듈들 간의 종속성들은 같은 ModuleInfoGroup 의 모듈들 내에서 정의될 수 있습니다; 그러나, 다른 ModuleInfoGroups 내의 모듈들 사이의 종속성을 정의할 수는 없습니다.

모듈들을 모듈 그룹 내에 배치하는 것은 선택적입니다. 그룹을 위해서 설정되는 프라퍼티들은 그것이 포함하는 모든 모듈들에 적용될 것입니다. 모듈들은 그룹 내부에 존재하지 않아도 등록될 수 있다는 것도 기억하기 바랍니다.


응용프로그램의 Bootstrapper 클래스에서, XAML 파일이 ModuleCatalog 의 소스임을 지정할 필요가 있습니다. 그 예가 다음 코드에 나와 있습니다.



구성 파일을 사용해서 모듈을 등록하기


WPF 에서는, 모듈 정보를 App.config 파일에 저장하는 것이 가능합니다. 이 접근법은 이점은 이 파일이 응용프로그램으로 컴파일되지 않는다는 것입니다. 이는 응용프로그램을 재컴파일하지 않고도 런타임에 모듈을 추가하거나 삭제하는 것을 쉽게 만들어 줍니다.


다음 코드 예제는 모듈 카탈로그를 지정하는 구성 파일을 보여 줍니다. 만약 모듈이 자동으로 로드되는 것을 원한다면, startupLoaded="true" 를 설정하면 됩니다.



노트:

여러 분은 여전히 코드상에서 ConfigurationModuleCtalog 에다가 모듈들을 추가할 수 있습니다. 예를 들어, 응용프로그램이 반드시 기능하기를 바라는 모듈들이 카탈로그에 정의되도록 하기 위해서 이를 사용할 수 있습니다.


노트:

실버라이트는 구성 파일들을 사용하는 것을 지원하지 않습니다. 만약 구성파일 형식의 접근법을 원한다면, 자신만의 ModuleCatalog 를 생성해서 서버의 웹 서비스로부터 모듈 구성파일을 읽어 들이는 접근법을 추천합니다.


디렉토리에서 모듈 검색하기


WPF 에서 프리즘 DirectoryModuleCatalog 클래스는 모듈 카탈로그로 로컬 디렉토리를 지정하도록 해 줍니다. 이 모듈 카탈로그는 지정된 폴더를 스캔하고 응용프로그램을 위한 모듈을 정의하는 어셈블리들을 검색합니다. 이 접근법을 사용하려면, 모듈 이름과 그것이 가지는 모든 종속성을 지정하기 위해서 모듈 클래스에다가 선언적인 애트리뷰트를 사용할 필요가 있습니다. 다음 코드 예제는 디렉토리에서 어셈블리들을 검색해서 덧붙여진 모듈 카탈로그를 보여 줍니다.



노트:

이 기능은 실버라이트에서는 지원되지 않습니다. 왜냐하면 실버라이트 보안 모델은 어셈블리를 파일 시스템에서 로드하는 것을 허용하지 않기 때문입니다.


모듈 로드하기


ModuleCatalog 가 덧붙여지면, 모듈들이 로드되고 초기화될 준비가 된 것입니다. 모듈 로딩은 모듈 어셈블리가 디스크에서 메모리로 이동되었음을 의미합니다. 만약 어셈블리가 디스크에 존재하지 않는다면, 먼저 그걳을 획득해야만 합니다. 이것의 예는 실버라이트 .xap 파일을 사용해서 웹으로부터 어셈블리를 다운로드하는 것입니다. ModuleManager 는 로딩 및 초기화 과정을 다룰 책임이 있습니다.


모듈 초기화하기


모듈이 로드된 후에는, 그것들이 초기화됩니다. 이는 모듈 클래스의 인스턴스가 생성되고 그것의 Initialize 메서드가 호출되는 것을 의미합니다. 초기화는 응용프로그램에 모듈을 통합하는 장소입니다. 모듈 초기화를 위해 다음과 같은 가능성들을 고려하십시오:

  • 모듈의 뷰를 응용프로그램에 등록하십시오. 만약 모듈이 뷰 검색이나 뷰 주입을 사용해 유저 인터페이스( UI ) 조립하는 것이라면, 모듈은 그것의 뷰나 뷰 모델을 적절한 영역( region ) 이름과 연관시킬 필요가 있습니다. 이는 뷰가 메뉴에서 동적으로 나타날 수 있도록 해 주거나, 응용프로그램의 다른 비주얼 영역에서 나타날 수 있도록 해 줍니다.
  • 응용프로그램 레벨 이벤트나 서비스를 구독하십시오. 보통, 응용프로그램은 여러분의 모듈이 관심을 가지게 되는 응용프로그램-지정 서비스나 이벤트를 노출합니다. 모듈의 기능들을 그러한 응용프로그램-레벨 이벤트와 서비스에 추가하기 위해서는 Initialize 메서드를 사용하십시오. 예를 들어, 응용프로그램은 아마도 그것이 종료될 때나 여러분의 모듈이 그 이벤트에 반응하기를 원할 때 이벤트를 발생시킬 것입니다. 또한 여러분의 모듈은 응용프로그램 레벨 서비스에 어떤 데이터를 제공해야만 할 가능성도 있습니다. 예를 들어, 만약 MenuService( 이것은 메뉴 아이템을 추가하거나 삭제할 책임이 있습니다 )를 생성했을 때, 모듈의 Initialize 메서드가 여러분이 올바른 메뉴 아이템을 추가할 위치입니다.

노트:

모듈 인스턴스 라이프타임은 기본적으로 매우 짧습니다. 로딩 과정 동안 Initialize 메서드를 호출한 후에, 모듈 인스턴스에 대한 참조가 해제됩니다. 만약 모듈 인스턴스에 대한 강한 참조 체인을 구성하지 않는다면, 그것은 가비지 수집될 것입니다.

이 동작은 여러분이 모듈에 대한 약한 참조를 유지하는 이벤트를 구독하고 있을 때 디버깅을 어렵게 만듭니다. 왜냐하면 여러분의 모듈은 가비지 수집기가 실행될 때 이미 "사라지기" 때문입니다.

  • 종속성 주입 컨테이너에 타입들을 등록하십시오. 만약 유니티나 MEF 와 같은 종속성 주입 패턴을 사용하고 있다면, 모듈은 아마도 응용프로그램이나  사용할 다른 모듈들을 위한 타입들을 등록할 것입니다. 또한 그것은 컨테이너에 그것이 필요로 하는 타입의 인스턴스를 결정해 줄 것을 요구할 것입니다.

모듈 종속성들을 지정하기


모듈들은 다른 모듈들에 의존합니다. 만약 모듈 A 가 모듈 B 에 의존한다면, 모듈 B 는 반드시 모듈 A 전에 초기화되어야 합니다. ModuleManager 는 이러한 종속성들에 대한 트랙을 유지하며, 모듈을 적절히 초기화합니다. 여러분이 모듈 카탈로그를 정의했던 방식에 의존해, 모듈 종속성을 코드, 구성 파일, XAML 에서 정의할 수 있습니다.


코드에서 종속성들을 지정하기


코드에서 모듈을 등록하거나 디렉토리에 의해 모듈들을 검색하는 WPF 응용프로그램을 위해, 프리즘은 모듈을 생성할 때 사용하기 위한 선언적 애트리뷰트들을 제공합니다. 그 예가 아래에 나와 있습니다.



XAML 에서 종속성들을 지정하기


다음 XAML 은 모듈 F 가 모듈 E 에 의존하는 것을 보여 줍니다.



구성파일에서 종속성들을 지정하기


다음 App.config 파일 예제는 모듈 D 가 모듈 B 에 의존함을 보여 줍니다.



온디맨드로( 요청시에 ) 모듈을 로드하기


모듈을 온디맨드로 로드하려면, 모듈이 InitializeMode OnDemand 로 설정한 상태로 모듈 카탈로그에 로드되어야 합니다. 그렇게 하고 나서, 모듈이 로드될 것을 요청하는 응용프로그램 코드를 작성할 필요가 있습니다.


코드에서 온디맨드 로딩을 지정하기


모듈은 애트리뷰트를 사용해서 온디맨드로 지정되는데, 아래 코드 예제를 보십시오.



XAML 에서 온디맨드 로딩 지정하기


XAML 에서 모듈 카탈로그를 정의할 때, InitializationMode.OnDemand 를 지정할 수 있습니다. 아래 코드 예제를 보십시오.



구성파일에서 온디맨드 로딩 지정하기


App.config 파일에서 모듈 카탈로그를 정의할 때 InitializationMode.OnDemand 를 지정할 수 있습니다. 아래 코드 예제를 보십시오.



모듈의 온디맨드 로딩 요청하기


모듈이 온디맨드로 지정되면, 응용프로그램은 모듈이 로드될 것을 요청할 수 있습니다. 로딩을 초기화하기 원하는 코드는 부트스트래퍼에 의해 컨테이너에 등록된 IModuleManager 서비스에 대한 참조를 획득할 필요가 있습니다.



백그라운드로 원격 모듈들을 다운로드하기


응용프로그래 시작 후나 사용자가 모듈을 필요로 할 때 백그라운드로 모듈들을 다운로드하는 것은 응용프로그램 시작 시간을 개선해 줍니다.


원격 다운로드를 위해 모듈을 준비하기


실버라이트 응용프로그램에서, 모듈들은 .xap 파일들에 패키징됩니다. 응용프로그램으로부터 분리된 모듈을 다운로드하기 위해서는 개별적인 .xap 파일을 생성하십시오. 여러분은 다중 모듈들을 하나의 .xap 파일에 배치해서 다운로드 요청의 개수를 최적화하거나, 각 .xap 파일의 다운로드 사이즈를 최적화할 수 있습니다.


노트:

각 .xap 파일들에 대해, 새로운 실버라이트 응용프로그램 프로젝트를 생성할 필요가 있습니다. 비주얼 스튜디오 2008 과 2010 에서는, 하나의 응용프로그램 프로젝트만 .xap 파일을 만들 수 있습니다. 이런 프로젝트들 내에서 App.xaml 이나 MainPage.xaml 파일들을 만들 필요는 없을 것입니다.


다운로드 과정을 트래킹하기


ModuleManager 클래스는 응용프로그램을 위해서 모듈에 대한 다운로드 과정을 추적하기 위한 이벤트를 제공합니다. 이는 다운로드된 바이트 대 전체 받은 바이트를 제공하며, 다운로드 과정의 퍼센트도 제공합니다. 이를 사용해서 비주얼 프로그레스 인디케이터를 출력해 사용자에게 다운로드되는 과정을 보여 줄 수 있습니다.




모듈이 다 로드되었는지를 확인하기


ModuleManager 서비스는 응용프로그램을 위해서 모듈이 로드되거나 로드에 실패했을 때를 추적하기 위한 이벤트를 제공합니다. IModuleManager 인터페이스의 종속성 주입을 통해서 이 서비스에 대한 참조를 획득할 수 있습니다.




응용프로그램과 모듈의 느슨한 결합을 유지하기 위해서, 응용프로그램은 이 이벤트를 모듈을 응용프로그램에 통합하기 위한 목적으로 사용하는 것을 피해야만 합니다. 그 대신에, 모듈의 Initialize 메서드가 응용프로그램과의 통합을 다뤄야 합니다.


LoadModuleCompletedEventArgs IsErrorHandled 프라퍼티를 포함합니다. 만약 모듈을 로드하는데 실패했는데, 응용프로그램이 ModuleManager 가 에러를 로깅하거나 예외를 던지지 않기를 원한다면, 이 프라퍼티를 true 로 설정할 수 있습니다.


노트:

모듈이 로드되고 초기화된 후에, 그 모듈 어셈블리는 언로드될 수 없습니다. 모듈 인스턴스 참조는 프리즘 라이브러리에 의해 유지되지 않을 것입니다. 그래서 모듈 클래스 인스턴스는 초기화가 완료되면 가비지 수집될 것입니다.


MEF 에서 모듈들


이 섹션은 당신이 종속성 주입 컨테이너로서 MEF 를 선택했을 때의 차이점에만 집중합니다.


노트:

MEF 를 사용할 때, MefModuleManager MefBootstrapper 에 의해 사용됩니다. 이는 ModuleMnager 를 확장하고, IPartImportsSatisfiedNotification 인터페이스를 구현하여, MEF 에 의해 새로운 타입들이 임포트될 때 ModuleCatalog 가 갱신되도록 보장합니다.


MEF 를 사용하여 코드에서 모듈들을 등록하기


MEF 를 사용할 때, 여러분은 MEF 가 자동으로 타입들을 검색하도록 만들기 위해서 모듈 클래스에 ModuleExport 애트리뷰트를 적용할 수 있습니다. 다음은 그 예제입니다.



여러분은 AssemblyCatalog 클래스를 사용해서 모듈들을 검색하고 로드하도록 할 수도 있습니다. 이 클래스는 어셈블리 내에서 익스포드되는 모든 모듈 클래스들을 검색하기 위해서 사용될 수 있습니다. 그리고 AggregateCatalog 클래스는 하나의 논리 카탈로그에 다중 카탈로그들이 결합될 수 있도록 해 줍니다. 기본적으로, 프리즘 MefBootstrapper 클래스는 AggregateCatalog 인스턴스를 생성합니다. 그러면 여러분은 ConfigureAggregateCatalog 메서드를 재정의해서 어셈블리들을 등록할 수 있습니다. 그 예가 아래에 나와 있습니다.



프리즘 MefModuleManager 구현은 MEF AggregateCatalog 와 프리즘 ModuleCatalog 가 동기화되도록 유지합니다. 결국, ModuleCatalog AggregateCatalog 를 통해 추가된 모듈들을 프리즘이 검색할 수 있도록 해 줍니다.


노트:

MEF 는 Lazy<T> 를 확장해서 사용하는데, 익스포트되거나 임포트된 타입들의 초기화를 Value 프라퍼티가 사용되기 전까지 지연시키기 위해서입니다.


MEF 를 사용하여 디렉토리 내의 모듈들을 검색하기


MEF 는 모듈들을 포함하고 있는 어셈블리들( 그리고 다른 MEF 익스포트 타입들 )을 위해 디렉토리를 검색하는 데 사용되는 DirectoryCatalog 를 제공합니다. 이 경우, 여러분은 ConfigureAggregateCatalog 메서드를 재정의햇, 디렉토리를 등록하게 됩니다. 이 접근법은 WPF 에서만 이용 가능합니다.


이 접근법을 사용하기 위해서는, 먼저 ModuleExport 애트리뷰트를 사용해 모듈에 모듈 이름들과 종속성들을 적용할 필요가 있습니다. 아래 코드에 그 예가 나와 있습니다. 이는 MEF 가 모듈들을 임포트할 수 있도록 해 주고, 프리즘이 ModuleCatalog 를 갱신할 수 있도록 해 줍니다.



MEF 를 사용해 코드에서 종속성들을 지정하기


MEF 를 사용하는 WPF 응용프로그램에 대해, ModuleExport 애트리뷰트를 아래와 같이 사용하십시오.



MEF 는 런타임에 모듈들을 검색하도록 해 주기 때문에, 모듈들 간의 새로운 종속성도 런타임에 검색될 수 있습니다. ModuleCatalog 를 MEF 와 함께 사용할 수 있기는 하지만, ModuleCatalog 는 XAML 이나 구성 파일로부터 그것이 로드될 때 ( 모듈이 로드되기 전에 ) 종속성 체인에 대한 유효성 검사를 수행한다는 것을 기억하는 것이 중요합니다. 만약 ModuleCatalog 에 모듈이 열거되어 있고 MEF 를 사용하여 로드된다면, ModuleCatalog 종속성들이 사용될 것이며, DependsOnModuleNames 애트리뷰트가 무시될 것입니다. 개별 XAP 파일에 모듈들을 가지고 있는 실버라이트 응용프로그램에서는 ModuleCatalog 와 함께 MEF 를 사용하는 것이 가장 일반적입니다.


MEF 를 사용해 온디맨드 로딩을 지정하기


MEF 를 사용하고 모듈들과 모듈 종속성들을 지정하기 위해서 ModuleExport 애트리뷰트를 사용하고 있다면, 온디맨드로 로드되어야 하는 모듈을 지정하기 위해서 InitializationMode 프라퍼티를 사용할 수 있습니다. 다음 예제를 보십시오.



MEF 를 사용해 원격 다운로드를 위한 모듈을 준비하기


내부적으로 MEF 를 사용하는 프리즘 응용프로그램은 MEF 의 DeploymentCatalog 클래스를 사용하여 .xap 파일들을 다운로드하고 그 .xap 파일들 내의 어셈블리들과 타입들을 검색합니다. MefXapModuleTypeLoader AggregateCatalog 에 각 DeploymentCatalog 를 추가합니다.


두 가지 다른 .xap 파일들이 추가되고 같은 공유 어셈블리들을 포함한다면, 같은 타입들이 다시 임포트됩니다. 이는 타입이 싱글톤으로 지정되었는데 모듈들 간에 공유되는 어셈블리에 존재할 때 recomposition 에러를 발생시킬 수 있습니다. Microsoft.Practices.Prism.MefExtensions.dll 은 그런 어셈블리의 예입니다.


중복 임포트를 막기 위해서는, 각 모듈 프로젝트의 참조를 열고, 그러한 공유 DLL 들에 대해 'Copy Local'=false 로 설정하십시오. 이는 모듈의 .xap 파일에 그 어셈블리가 패키징되는 것을 막으며, 다시 임포트되는 것을 막습니다. 또한 각 .xap 파일의 전체적인 크기도 줄여 줍니다. 이를 위해서, 모듈 .xap 파일이 다운로드되기 전에, 응용프로그램이 공유 어셈블리를 참조하거나 응용프로그램이 공유 어셈블리를 포함하는 .xap 파일을 다운로드하는 것을 보장할 필요가 있습니다.


더 많은 정보들



어셈블리 캐싱에 대한 더 많은 정보를 원한다면, MSDN 의 "방법: 어셈블리 캐싱 사용하기" 를 참조하심시오: http://msdn.microsoft.com/en-us/library/dd833069(VS.95).aspx


프리즘의 모듈성에 대한 더 많은 정보를 원한다면, Modularity with MEF for WPF QuickStart 나 Modularity with Unity for WPF QuickStart 를 참조하십시오. QuickStart 에 대한 더 많은 정보를 원한다면, 도움말의 Modularity QuickStarts for WPF 를 참조하십시오.


프리즘 라이브러리에서 확장될 수 있는 모듈성 기능들에 대한 더 많은 정보를 원한다면, 도움말에서 "Extending Prism" 의 "Modules" 를 참조하십시오.


'Programming > Prism4.1' 카테고리의 다른 글

진보된 MVVM 시나리오들  (0) 2014.09.20
MVVM 패턴 구현하기  (0) 2014.09.16
컴포넌트 간의 종속성 관리하기  (0) 2014.09.10
프리즘 응용프로그램 초기화하기  (0) 2014.08.24
왜 프리즘을 사용하는가?  (0) 2014.08.19
소개  (0) 2014.08.18
프리즘 4.1 설치  (0) 2014.08.14

+ Recent posts