지난 회 차에 여러 가지 문제로 .NET 스마트클라이언트가 가진 문제점을 살펴 보았습니다. 그 중, 주된 이슈는 이미 로드된 어셈블리는 업데이트/갱신이 불가능하다는 것과, 메모리의 사용률이 지속적으로 증가한다는 문제입니다. 이러한 문제는 사내 정책적인 서버를 도입하여 해결 가능하지만, 대부분의 조직과 기업은 이러한 정책 서버를 도입하지 않는 것으로 알고 있습니다.    

이미 얘기 했다시피, 평소에도 .NET 에서 이러한 문제를 가지고 고민을 했었지만, 최근 이러한 문제가 이슈가 되었을 때 더 이상 필자 또한 방관할 수 없었습니다. 왜냐하면 "안된다!" 라는 것 자체가 .NET 의 많은 매리트를 배제한다는 의미가 될 수 있기 때문입니다. 이러한 문제로 '목숨거는' 고객이라면 차라리 '지금은 곤란하다. 조금만 기다려달라' 라는 답이 훨씬 나아 보입니다. 물론 이런 문제가 가능하다는 전제 조건으로 말입니다.

   

문제 해결 방안

일단, 몇 날 몇 일을 고민하며 생각한 끝에 아래와 같은 아키텍처링을 하게 되었습니다. 물론 최선의 방법도, 최적의 방법도 아니지만, 문제가 된다면 저에게 피드백을 주시기 바랍니다. 저 또한 짧은 지식으로 이러한 고민을 하게 되었으니 저도 많이 답답하네요^^;    

   

위의 아키텍처링은 논리적인 아키텍처입니다. 이 방법을 통해 이전 아티클을 통해 골치 아픈 .NET 어플리케이션의 메모리 릭(Memory Leak) 을 해결할 수 있을 것으로 기대합니다.

   

어플리케이션과 AppDomain 의 분리

.NET 어플리케이션은 기본적으로 하나의 프로세스(Process) 를 차지하게 됩니다. 그것이 독립 프로세스든, IEHost.DLL 또는 IEExec.EXE 든 간에 말이죠. 이 독립 프로세스는 독립적인 하나의 어셈블리에서 관장하게 됩니다. 기본적인 이 부분의 컨셉은 어플리케이션의 재시작을 방지하기 위한 방법이기도 합니다.    

기존의 어플리케이션의 프로세스와 AppDomain 을 분리함으로써 최소한으로 AppDomain 이 안전하게 언로드될 수 있는 환경을 제공하는 것입니다. 그리고 위해 AppDomain Manager 는 이것을 관장하는 최상위 Manager Layer 가 됩니다.

   

MVVM 으로 구현부와의 분리

MVVM(Model View ViewModel) 패턴의 가장 큰 특징은 View 와 ViewModel 을 분리한 것입니다. 이것을 분리함으로써 View 와 ViewModel 의 종속 관계를 완전히 해결하고, ViewModel 은 격리된 AppDomain 으로 제한함으로써 언제든지 AppDomain 이 언로드될 수 있게 합니다.    

이 부분을 구현하기 가장 이상적인 환경은 바로 WPF(Windows Presentation Foundation) 이 되겠네요.

   

Views 의 교체

MVVM 으로 구현부와의 분리를 통해 당연히 Views 는 언제든지 교체가 가능합니다. 서버/로컬에서 Views 가 교체된다면 ViewModels 을 언로드하고 새로운 Isolated AppDomain 을 생성하여 View 와 ViewModel 간에 연결하는 방법입니다.    

특히 이 통신 구간은 View 와 ViewModel 간의 Interface Contract 를 통해 크리티컬한 자원의 관리를 최소화하는 것에 있습니다. 이로써 이미 로드된 사용자 화면과 어셈블리라도 서버/로컬의 갱신이 있다면 언제든지 갈아치울 수 있는 구간입니다. 이 부분이 앞서 얘기한 .NET 스마트클라이언트의 문제를 해결할 수 있는 핵심 구간입니다.

   

업데이트 기능을 재작성

이 아키텍처링의 가장 큰 문제지만, .NET 스마트클라이언트의 NTD(No Touch Deployment) 기능을 그대로 사용할 수 없습니다. .NET 의 NTD 는 이미 실행되는 AppDomain 에 어셈블리를 로드하기 때문에 .NET 의 NTD 를 그대로 사용한다면 이 아키텍처링을 적용할 수 없습니다.

NTD 기능 뿐만 아니라, ClickOnce 의 자동 버전 감지 기능도 사용할 수 없습니다. ClickOnce 는 주기적으로 서버의 Application Manifest 를 확인하는 과정으로 새로운 버전을 감지하고 업데이트하는데, 이 기능을 그대로 사용한다면 위의 아키텍처링은 사실상 무의미하고, 결국 메모리 사용 증가는 해결할 수 없기도 합니다.

   

제한 사항

하지만 필자가 제안한 .NET 스마트클라이언트의 문제를 해결하기 위한 방법은 제한적인 방법으로 수행이 가능합니다. 물론 모든 경우라도 제안이 가능한 방법이라면 좋겠지만, .NET 의 기본 아키텍처가 해결하지 못한 이상, 필자 또한 제한적인 방법으로 .NET 스마트클라이언트의 문제점을 해결할 수 있습니다.

그 제한적인 방법의 한계는 아래와 같습니다.

  • 개발 표준을 완벽하게 MVVM 기반으로 개발되어야 한다.
  • MVVM 패턴으로 완벽하게 분리가 되어야 한다.
    • WPF 를 사용할 경우 MVVM 패턴으로만 작성되어야 한다.
    • 윈도우 폼(Windows Forms) 또는 ActiveX 컨트롤 일 경우, MVVM 로 작성할 수 없다.
    • 이 경우, View와 ViewModels 를 분리하도록 별도 프레임워크 개발이 필요하다.
  • Marshaling 을 통한 통신
    • Marshaling 은 AppDomain 간의 원격 통신을 해야 한다.
    • 원격 통신으로 인한 성능 저하
  • WPF 개발
    • Binding Expression 을 확장한 Binding Marshaling Expression(단지, 예임) 으로 바인딩을 해야 한다.
    • 원격 바인딩으로 성능 저하 예상

   

결론

필자는 .NET 어플리케이션이 업데이트될 경우 왜 반드시 최적의 방법이 어플리케이션 쉘을 재시작하느냐에 시작한 고민으로부터 시작됩니다. .NET 아키텍처를 이해못하는 것은 아니지만, 고객은 언제나 더 향상된 방법을 제안합니다. 그리고 필자는 그런 고민을 극복하고자 제안한 방법입니다.

물론 위의 아키텍처링을 효율적인 면과 성능적인 면을 더 자세히 테스트해 보아야 하겠지만, 분명한 것은 끊임없이 고객의 요청은 진화하지 퇴화하지는 않을 거라고 생각합니다.

예전에 필자는 위와 같은 문제를 문의할 때, ".NET 에서는 안된다" 라고 답했습니다. 맞아요. 안됩니다. 하지만 문득, '안되면 되게 해야지!' 라는 생각이 들더군요. 짧은 소견이지만 잘못된 부분이 있으면 언제든지 피드백 주시기 바랍니다.

Posted by 땡초 POWERUMC

댓글을 달아 주세요

  1. 남정현 2010.07.20 14:12 Address Modify/Delete Reply

    좋은 글 잘 읽었습니다. 늘 그렇지만 "안되는 것을 가능하게 만드는 것"은 쉽지만, 그것을 다른 사람들에게 전달하고 공유하도록 만드는 것 (문서를 쓰는것부터 설명에 이르기까지)이 사실은 훨씬 더 어려운 작업이지 않나 생각하게 되네요. :-)

    • 땡초 POWERUMC 2010.07.20 23:26 신고 Address Modify/Delete

      오늘 뵙게 되어 너무 반가웠습니다.
      저는 사실 항상 정현님을 모티브로 본받으려고 노력하고 있답니다.^^
      언제나 겸손하시고 솔선수범해 주시는 모습..
      제 곁에 있어 주실꺼죠? ^^

    • 남정현 2010.07.28 23:53 Address Modify/Delete

      오우.. 댓글을 늦게 봤네요. =_=

      저야 말로 여러모로 앞으로 엄준일 MVP님께 많은것을 배워야 할것 같아요. 언젠가 인사드렸었지만 그래도 다시한번 잘 부탁드립니다. ㅎㅎ

  2. lancers 2010.07.21 09:07 Address Modify/Delete Reply

    어차피 별도 AppDomain을 사용하는 방법이 유일한 해결책인데,
    이 아키텍처의 착상은 나쁘지 않으나 실제로 진행하다 보면 많은 문제에 부딪칠 거야.
    지금 상황에선 예상하지 못한 문제들을 많이 겪게 될 거고..

    이론 상으로 볼 때는 이런 방향으로 가는 게 맞는데,
    실질적으로 사용자가 원하는 건 굳이 이런 방식이 아니어도 된다는 것도 알게 될 거고..

    회사 내부에서 이미 진행하고 있는 내용의 결론이 조만간 나올 듯..

    • 땡초 POWERUMC 2010.07.22 04:52 신고 Address Modify/Delete

      저도 그 많은 문제가 제가 생각하는 이상으로 많을 것 같아요.
      말씀하신 ShadowCopy 가 좀 더 현실적으로 가까운 것 같습니다.^^
      말씀해주신 힌트가 큰 도움이 되었습니다.
      ---------- Updated ----------
      다만, AppDomain 의 ShadowCopy 는 AppDomain 당 1회성이 아닐까요?
      테스트 해 보지는 않았지만, 논리적으로 본다면 AppDomain 당 ShadowCopy 폴더를 둔다는 것은 1회에 한한 제한적인 방법인 것 같습니다.
      ------------------------------

      DX 의 멋진 솔루션이 기대됩니다용^^