Silverlight의 MVVM 패턴을 소개하고 있는 YouCard Re-visited: Implementing the ViewModel pattern 라는 글을 번역한 글이다. 아직 1/3 정도라서 틈나는 대로 이어서 번역하려고 한다. 실력 부족/시간 부족으로 딱히 좋은 번역이라고 하긴 힘들겠지만.
Model-View-Control (MVC) 패턴은 더 이상 유명할 수가 없을 정도이다. ASP.NET MVC 프레임워크로 Microsoft도 이제 그 대열에 뛰어들었다. Ruby on Rails, Django (Python), Spring MVC (JAVA) 같은 다른 유명한 프레임워크들은 모두 이 유명한 패턴을 구현한 것이다. MVC 패턴은 요청-응답 기반이라는 웹의 본성에 아주 잘 들어맞는다. 요청이 들어오면, controller가 무엇을 해야하는지 결정하여, model에게 알려준다. 그리고 view 엔진에게 렌더링을 시킨다.
반면 Silverlight는 비록 Silverlight가 전통적인 웹 어플리케이션 속에서 실행되기는 하지만, 웹 어플리케이션 보다는 Windows Presentation Foundation 같은 리치 클라이언트 어플리케이션 프레임워크와 공통점이 더 많다. 그러므로 어플리케이션을 설계할 때 다르게 생각할 필요가 있다. 이 포스트에서 나는 View-Model-ViewModel (MVVM) 패턴, 혹은 마틴 파울러가 말한대로 Presentation Model에 대해서 얘기할 것이다. 예제로서 나는 내 YouCard 어플리케이션을 리팩터링하여 이 패턴을 쓰도록 만들 것이다.
Jon Gossman과 Dan Crevier는 WPF에서의 MVVM 패턴에 대해서 포스팅을 했고, 최근 Nikhil Kothari도 ViewModel Pattern in Silverlight using Behaviors라는 제목의 훌륭한 글을 썼다. 마틴 파울러(Martin Fowler)도 이 패턴에 대해서 썼지만 Presentation Model이라는 다른 이름을 사용했다. ViewModel을 Silverlight와 WPF 어플리케이션에서 사용하는 것이 꽤 재미있는 이유는, 이 패턴이 Silverlight와 WPF의 강력한 데이터 바인딩의 장점을 최대한 살려주기 때문이다. MVVM 패턴의 한 가지 중요 컨셉은 특정한 뷰 (사용자 인터페이스)에 딱 맞춘 특정 모델을 정의한다는 것이다. 그 뷰-모델은 당신의 도메인 모델을 형성하는 하나 혹은 그 이상의 필드에 기반한 IsDiscountingEnabled, PageTitle 같은 특별한 필드를 포함할 수도 있다. 당신의 IsDiscoundEnabled 필드는 할인(discount) 권한을 가진 그룹에 소속된 사용자인지 아닌지를 나타내는 것일지도 모른다. 그러나 뷰는 이런 사실을 모를 뿐더러 관심도 없다. 뷰는 뷰-모델의 IsDiscountEnabled 필드에만 신경을 쓰고, 도메인 모델과는 커플링되지 않는다. 뷰와 뷰-모델은 높은 수준으로 동기화된다. 반면, 뷰-모델과 도메인 모델 사이의 동기화는 단지 특정 포인트에서만(사용자가 Apply나 Save 버튼을 클릭했을 때 같은 경우에만) 일어날 뿐이다. 당신이 뷰와 뷰-모델 사이의 동기화를 어떻게 구현할 것인지는 당신이 사용하는 기술에 달려있다. 그러나 마틴 파울러조차도 그 작업이 데이터 바인딩을 통해서 수행되는 것을 추천했다.
아마도 Presentation Model에서 가장 귀찮은 부분은 Presentation Model과 뷰의 동기화이다. 작성하기에 단순한 코드이기는 하지만, 나는 이렇게 지루하게 반복되는 코드를 최소화하는 것이 좋다. Ideally some kind of framework could handle this, which I'm hoping will happen someday with technologies like .NET's data binding.(막 해석 : 이론적으로는 몇몇 프레임워크가 이런 일을 할 수 있지만, 내가 바라는 것은 닷넷의 데이터 바인딩과 같은 기술과 함께 나타날 것이다.) – Martin Fowler
마틴 파울러가 말하는 동기화 코드는, name 텍스트 상자의 값을 Preson 개체의 name 속성으로 옮기는 코드 같은 것이다. 모든 개발자들은 이런 코드들을 작성한 경험이 있고, 우리 모두 그것이 지겹고 반복적인 작업이라는 점에 동의할 것이라고 나는 확신한다! 고맙게도 데이터 바인딩은 .NET 1.1 과 Windows Forms 때부터 많이 개선되었고, 동기화 코드를 작성할 때 WPF와 Silverlight 데이터 바인딩을 선택하는 것은 자연스러운 일이다.
내가 예제로 사용할 어플리케이션은 내가 호주 REMIX에서 만든 YouCard 이다. REMIX에서 나는 디자이너를 위한 Silverlight 2에 대해서 이야기했다. 이야기의 초점은 어플리케이션을 빌드하고 디자인하기 위해서 Blend 2.5를 사용하는 방법에 대한 것이었다. 어플리케이션의 코어는 YouCard 사용자 컨트롤이었다. 그 컨트롤은 YouCardData 클래스에 데이터 바운딩되는 것이다. YouCardData 클래스는 Twitter와 Flickr에서 데이터를 받아오는 기능을 갖고 있고, 어플리케이션에서 모델과 뷰-모델의 역할을 한다. 이 클래스는 Tweet, Name, Bio같이 뷰에 관련된 필드를 갖고 있는데, 이 정보들은 HTTP 요청을 사용해서 Twitter로부터 얻은 Twitter-feed에서 추출한 것이다. YouCardData 클래스는 주어진 시간 간격으로 트위터와 플리커로부터 데이터를 다운로드하는 타이머를 시작시킨다. 단일 책임 원칙 같은 좋은 프로그래밍 원칙을 따르기 위해서 나는 트위터와 플리커 관련 기능을 외부 클래스로 분리시킬 것이다. 이 클래스들이 우리의 Model이 될 것이다. 이 클래스의 책임은 다운로드하고 XML을 분석해서 개체를 만드는 일이 될 것이다. YouCardData 클래스는 우리의 ViewModel이 될 것이고, 트위터와 플리커 서비스를 View의 논리에 맞게 사용하는 책임을 맞게 된다. 또한 UI에 필요한 필드들을 노출시키는 책임도 지게 된다. YouCardData 클래스는 원래 Blend 2.5가 제공하는 강력한 데이터 바인딩과 디자인 타임 지원을 강조하기 위해 설계되었기 때문에, 우리는 리팩토링을 위한 좋은 시작점을 가지고 있는 셈이다. 아래 도표의 왼쪽은 현재의 설계이고, 오른쪽은 리팩토링 후 기대하고 있는 디자인이다.
처음으로 해야 할 일은 외부 서비스를 위한 몇 가지 인터페이스를 정의하는 일이다. ITwitter나 IFlickr 인터페이스를 만드는대신, 나는 IMicroBlog와 IPhotoService 라는 좀 더 일반적인 이름을 사용하기로 했다. 이 결정은 우리가 FriendFeed, Picasa 또는 Windows Live Photo Gallery를 지원하려고 한다면 좀 더 의미있는 결정일 것이다. 나는 원래의 코드를 리팩토링하여 각각의 인터페이스를 구현하는 두 개의 구상 클래스로 만드려고한다. 하나는 진짜 온라인 서비스를 위한 것이고, 하나는 더미 데이터를 가진 목(mock) 구현이다. 앞에서 언급한대로 이 어플리케이션은 REMIX의 크리에이티브 트랙을 위한 데모로서 작성되었고, Blend에서의 멋진 디자인 타임 사용자 경험을 제공하기 위해서 작성되었기 때문에, 우리는 코드가 디자이너에 의해 사용될 때를 위해 더미 데이터를 생성할 필요가 있다. 만약 당신이 XAML이 가능하게 해주는 디자이너-개발자 업무 흐름으로부터 이익을 얻을 생각이라면, 당신의 코드가 디자인 도구에서 어떻게 동작할 지 생각해보아야 한다. 현재 구현에서 더미 데이터는 YouCardData 클래스 생성자에서 Blend에서 실행되는 것인지 아닌지 체크하는 if 문을 통해 제공된다. 만약 YouCardData 클래스가 Blend에서 실행되면 Twitter와 Flickr 서비스의 목 구현이 사용된다. 브라우저 안에서 실행되면 타이머를 시작시키고 Twitter와 Flickr에서 데이터를 받아오기 시작하는 실제 구현이 사용된다. YouCardData 클래스 생성자의 중요한 부분은 이제 이렇게 보일 것이다.
[Translation] Silverlight Model-View-ViewModel Pattern 2에서 계속.