전문가칼럼

DBMS, DB 구축 절차, 빅데이터 기술 칼럼, 사례연구 및 세미나 자료를 소개합니다.

Silverlight를 사용한 간단한 페이지 넘기기 구현

전문가칼럼
작성자
admin
작성일
2021-02-22 16:01
조회
2197

Silverlight를 사용한 간단한 페이지 넘기기 구현

2년 전 필자는 레드먼드에 있는 본사의 복도에서 잘 아는 동료와 마주쳤습니다. 그는 "잠깐 보여줄 게 있어"라고 말하고는 바로 노트북을 펼쳐서, 그 이후로 필자의 인생을 바꾸어버린 한 데모를 보여주었습니다. 그 데모는 SilverlightTM 페이지 넘기기 샘플의 초기 버전으로, 지금은 silverlight.net/samples/1.0/Page-Turn/default.html에서 찾아볼 수 있습니다.
필자가 놀랄 수밖에 없었던 것은 이 데모가 신기하게도 브라우저에서 실행되었다는 점입니다. 더 놀라운 것은 이 데모에는 Microsoft .NET Framework 및 Internet Explorer가 필요 없었다는 점이며, 그 당시에는 아무도 몰랐지만 나중에는 Windows 없이도 실행될 수 있게 되었습니다.
PageTurn은 상당히 중요한 Silverlight 1.0 데모입니다. 필자는 Silverlight를 처음 접하는 사용자에게 강한 인상을 주기 위해서 항상 이 데모를 사용합니다. 그러나 PageTurn 내부를 들여다보면 직접 페이지 넘기기 응용 프로그램을 작성하기란 쉬운 일이 아니라는 것을 알 수 있습니다. PageTurn은 변환, 클리핑 영역, 동적으로 생성된 XAML 개체 등을 사용하며, 이 소스 코드를 이해하기 위해서는 많은 시간과 노력 그리고 Silverlight에 대한 적지 않은 지식이 필요합니다. Silverlight의 다양한 기능을 솜씨 좋게 사용한 것임은 분명하지만 일반적인 재사용 용도로 설계되지는 않았습니다.
이러한 이유 때문에 페이지 넘기기를 사용자의 Silverlight 1.0 응용 프로그램에 간단하게 통합할 수 있는 범용 페이지 넘기기 프레임워크를 개발하게 된 것입니다. 필자의 프레임워크를 사용하면 단 몇 줄의 JavaScript 코드만으로 전체 응용 프로그램을 작성할 수 있습니다. Silverlight에 대한 최소한의 지식으로도 프레임워크를 사용하는 데는 지장이 없으며 전체 프레임워크가 약 500줄의 JavaScript 코드로 작성되어 있으므로 이를 연구하여 작동 원리를 알아내기도 어렵지 않을 것입니다. 그리고 물론 필요에 따라 수정할 수도 있습니다.

PageTurnDemo 응용 프로그램

이 프레임워크를 소개하기 전에 이를 사용하는 응용 프로그램에 대해 살펴보겠습니다. 그림 1에서 볼 수 있듯 PageTurnDemo 응용 프로그램은, 지금은 MSDN Magazine으로 이름이 바뀐 Microsoft Systems Journal 1998년 11월호의 처음 몇 페이지를 넘겨가며 보여 줍니다. 참고로 잡지 내용을 사용하면서 저작권 문제는 어떻게 해결했을까요 사실 그 부분은 필자가 일하는 회사에서 발행한 잡지의 페이지 중에서 직접 집필한 부분을 사용했기 때문에 문제가 없었습니다. 페이지는 모두 스캔한 이미지이며, 마지막 페이지에는 이미지가 XAML(Extensible Application Markup Language) 텍스트와 겹쳐서 표시되어 있습니다. 여기에 텍스트를 포함시킨 이유는, 프레임워크에는 이미지만 페이지로 사용할 수 있는 것이 아니며, 약간의 제약은 있지만 이미지, 텍스트 블록, MediaElement 등이 포함된 임의의 XAML을 사용할 수 있다는 강점을 부각시키기 위해서입니다.
090224_wdp1.gif
그림 1 부분적으로 넘긴 페이지를 보여 주는 PageTurnDemo
소스 코드를 다운로드하고 Visual Studio 2008에서 데모를 실행할 수 있으며, wintellect.com/silverlight/pageturndemo에서 직접 데모를 볼 수도 있습니다. 잡지 표지가 표시되면(진행률 표시줄에서는 응용 프로그램에 사용된 모든 이미지를 검색하는 다운로드 과정을 보여줌) 왼쪽 마우스 단추를 사용하여 오른쪽에서 왼쪽으로 페이지를 끌어서 놓는 방법으로 이동할 수 있습니다. 오른쪽 페이지를 왼쪽으로 끌어서 놓으면 다음 페이지를 볼 수 있으며, 왼쪽 페이지를 오른쪽으로 끌어서 놓으면 반대로 이전 페이지를 볼 수 있습니다.
이 샘플 만들기는 얼마나 어려울까요 이미지를 스캔하고 잘라낸 다음 크기를 변경하고 이를 ZIP 파일로 압축하는 것 외에는 어려운 작업이 전혀 없습니다. HTML 파일, 연관된 JavaScript 파일, 그리고 XAML 파일이 세 가지 핵심 소스 코드 파일이며, 모두 이 칼럼과 함께 제공되는 다운로드 파일에 포함되어 있습니다. 이미지 다운로드를 위해 Silverlight 다운로더 개체를 사용하는 코드를 제외하면 나머지 코드는 그리 많지 않습니다. 사실 순수하게 페이지 넘기기 기능을 위한 코드는 10줄 정도입니다.

페이지 넘기기 프레임워크 사용

PageTurnDemo는 페이지 넘기기 프레임워크를 사용하기 위해 완료해야 하는 4가지 기본 단계를 보여 줍니다. 첫 번째 단계는 프레임워크 구현이 포함된 스크립트 파일인 PageTurn.js를 HTML 파일에 포함시키는 것입니다. 다음은 Default.html에서 이와 관련된 줄입니다.두 번째 단계는 프레임워크를 인스턴스화하는 것입니다. 페이지 넘기기 프레임워크는 PageTurnFramework라고 하는 JavaScript 클래스에서 캡슐화되므로 Default.html.js에 있는 다음 문이 프레임워크를 인스턴스화합니다.PageTurnFramework 생성자로 전달되는 첫 번째 매개 변수는 Silverlight 컨트롤에 대한 참조입니다. 두 번째 매개 변수는 사용자 페이지가 포함된 캔버스에 대한 참조입니다. PageTurnDemo의 XAML 문서에서 캔버스의 이름은 "PageTurnCanvas"입니다.
세 번째 단계는 페이지를 프레임워크에 등록하는 것입니다. 각 페이지는 캔버스를 통해 표시되며 PageTurnFramework는 페이지를 등록할 수 있는 addPage 메서드를 제공합니다. AddPage에는 두 개의 매개 변수가 사용됩니다.첫 번째지를 나타내는 캔버스에 대한 참조이며, 두 번째는 오른쪽 페이지를 나타내는 캔버스에 대한 참조입니다. 모든 페이지 쌍을 등록하는 데 필요한 만큼의 addPage를 호출할 수 있습니다. 그런 다음 addPage에 대한 마지막 호출이 수행되고 initializeFramework가 호출됩니다.initializeFramework 메서드는 프레임워크의 내부 상태를 초기화합니다. 특히 페이지를 잘라내고 회전하는 데 사용되는 XAML 개체 몇 개를 만들고 핵심 이벤트용 처리기를 등록합니다.
프레임워크 사용을 위한 네 번째이자 마지막 요구 사항은 올바른 정리를 수행하는 것입니다. 프로그래밍 방식으로 이벤트 처리기를 등록하는 브라우저 기반 응용 프로그램의 경우 메모리 누수를 방지하기 위해 이벤트 처리기의 등록을 취소해야 합니다. PageTurnFramework에는 addPage 및 initializeFramework에 의해 등록된 이벤트 처리기의 등록을 취소하는 dispose 메서드가 포함되어 있습니다. PageTurnDemo에서 <body> 요소의 onunload 특성은 페이지가 언로드되면 로컬 dispose 함수를 호출합니다.Default.html.js에 있는 이 로컬 dispose 함수는 프레임워크의 dispose 메서드를 호출합니다.Silverlight는 unload 이벤트를 발생시키지 않으므로 필자는 DOM 이벤트를 사용하여 dispose에 대한 호출을 트리거했습니다. 필요에 따라 window.unload 이벤트를 사용할 수도 있습니다.
PageTurnFramework 클래스는 사용자의 응용 프로그램에 페이지 넘기기 기능을 추가하기 위해 호출할 수 있는 6가지 공용 메서드를 제공합니다(그림 2 참조). PageTurnDemo는 이 중에서 addPage, initializeFramework 및 dispose의 세 가지를 사용하고 있습니다. 다른 메서드는 기능을 추가하는 데 사용할 수 있습니다. 예를 들어 Silverlight PageTurn 데모와 마찬가지로 응용 프로그램에서 페이지 미리 보기로 구성된 탐색 모음을 추가하려는 경우에는 미리 보기를 클릭할 때 PageTurnFrame work.goToPage를 호출하여 해당 페이지로 직접 이동할 수 있습니다.
Figure 2 페이지 넘기기 프레임워크 API
메서드
설명
addPage
페이지 쌍을 프레임워크에 등록합니다.
Dispose
올바른 정리를 위해 프레임워크에 보관된 리소스를 해제합니다.
getCurrentPageIndex
현재 표시되어 있는 페이지 쌍의 0부터 시작하는 색인을 반환합니다.
getPageCount
addPage로 추가한 페이지 쌍의 수를 반환합니다.
goToPage
지정된 페이지 쌍을 표시합니다.
initializeFramework
페이지 넘기기 프레임워크를 초기화합니다.

XAML 구조

페이지 넘기기 프레임워크가 작동하기 위해서는 XAML 문서의 구조에서 몇 가지 기본적인 요구 사항이 충족되어야 합니다. 이러한 요구 사항은 다음과 같습니다.
  1. 페이지 쌍의 각 페이지를 XAML 캔버스("페이지 캔버스")로 나타내야 합니다.
  2. 모든 페이지 캔버스의 컨테이너인 "페이지 넘기기" 캔버스가 있어야 합니다.
  3. 루트 캔버스에 너비, 높이 및 배경색(투명한 경우도 포함)을 할당해야 합니다.
세 번째 요구 사항을 충족해야 하는 이유는 초기화 시에 프레임워크가 루트 캔버스에 의해 발생하는 MouseLeave 이벤트용 처리기를 등록하기 때문입니다. 이러한 이벤트는 페이지를 부분적으로 넘긴 상태에서 커서가 Silverlight 컨트롤을 벗어난 경우에 페이지 넘기기를 완료하는 데 사용됩니다.
페이지 넘기기 프레임워크에서 페이지 넘기기를 시작할 때처럼 마우스를 캡처하는 모든 Silverlight 1.0 응용 프로그램은 루트 캔버스에서 발생하는 MouseLeave 이벤트를 처리하고 마우스가 벗어나는 가능성에 대비해야 합니다. 어떤 요소가 MouseEnter 및 MouseLeave와 같은 마우스 이벤트를 수신할 수 있으려면 Silverlight 내에서 "적중 테스트가 가능"해야 합니다. 이를 위해서는 요소(이 예에서는 캔버스)가 Null이 아닌 배경을 가진 크기가 있어야 합니다.
이러한 요구 사항을 기억하고, 그림 3을 보면 페이지 넘기기 프레임워크에서 사용되는 XAML 문서의 개략적인 구조를 볼 수 있습니다. PageTurnFramework의 클래스 생성자에 전달되는 것은 페이지 넘기기 캔버스입니다. 페이지 캔버스는 PageTurnFramework.addPage로 전달됩니다. 프레임워크에서 사용되는 마우스 이벤트가 캔버스에 포함되어 있는 XAML 콘텐츠의 내용에 관계없이 올바르게 발생할 수 있으려면 페이지 넘기기 캔버스와 페이지 캔버스에 명시적인 너비 및 높이 정보가 추가되어야 합니다. 나머지는 단순한 XAML입니다.
Figure 3 XAML 구조
페이지 넘기기 캔버스는 사용자의 XAML 문서 내에서 다른 서식 있는 콘텐츠와 함께 아무 문제없이 사용할 수 있습니다. 모든 개별 페이지는 간단한 XAML 이미지나 복잡한 XAML 렌더링으로 구성될 수 있습니다. 페이지 캔버스의 Clip 속성은 프레임워크 자체에서 사용하므로 별도로 사용하지 않는 것이 좋습니다. 그러나 페이지 캔버스 내에 하위 캔버스를 선언하고 하위 캔버스의 Clip 속성을 사용하여 클리핑 영역을 정의하는 것은 가능합니다.
첫 번째 왼쪽 페이지를 비어 있도록 하여 첫 번째 오른쪽 페이지가 아직 열지 않은 책의 표지처럼 보이도록 하려면 간단히 첫 번째 왼쪽 페이지에 불투명한 사각형을 선언하면 됩니다. 이와 마찬가지로 마지막 오른쪽 페이지에 불투명한 사각형을 사용하여 사용자가 마지막 페이지를 넘겼을 때 책을 닫은 것과 같은 효과를 만들 수 있습니다. PageTurnDemo는 이 두 가지를 모두 수행하여 잡지의 페이지를 넘기는 듯한 효과를 완성합니다.
페이지 넘기기 프레임워크에서 사용하기 위해 책이나 잡지를 스캔하다 보면 PageTurnDemo에서와 마찬가지로 페이지 안쪽 가장자리에 그림자가 생기는 경우가 있는데 이를 통해 페이지를 좀 더 현실적으로 표현할 수 있습니다. 스캔한 이미지를 사용하지 않는 경우에는 약간의 XAML로 그림자를 시뮬레이션할 수 있습니다. 필자의 무선 조종 비행기 사진을 보여 주고 있는 그림 4의 응용 프로그램(wintellect.com/silverlight/mymodels 참조)에서는 그림 5의 XAML 사각형을 사용하여 각 페이지 중앙을 세로로 나누는 그림자를 표시합니다. GradientStop 색의 Alpha 값에 의해 사각형이 왼쪽 페이지에서는 오른쪽에서 왼쪽으로, 오른쪽 페이지에서는 왼쪽에서 오른쪽으로 흐려지게 됩니다.
Figure 5 페이지 내에 그림자를 만드는 XAML
090224_wdp2.gif
그림 4 페이지 안쪽에 XAML 그림자를 사용한 페이지 넘기기 샘플
이해가 되지 않는 부분이 있으면 PageTurnDemo를 사용하여 응용 프로그램 작성을 시작해 보십시오. 간단하게 각 페이지에 대한 필자의 XAML을 여러분의 XAML로 바꾸면 됩니다. 필자의 페이지 캔버스는 너비가 400이고 높이가 544이지만 작성 시 원하는 크기를 사용할 수 있습니다.

프레임워크 내부 정보

페이지 넘기기 프레임워크는 이 기사의 다운로드에 포함되어 있는 PageTurn.js에 구현되어 있습니다. PageTurnFramework 클래스는 이 파일의 처음 몇 줄부터 시작합니다. JavaScript는 클래스를 지원하지 않지만 이 프레임워크는 ASP.NET AJAX에서 사용되는 것과 동일한 프로토타입 패턴을 사용하여 여러 Silverlight 1.0 응용 프로그램이 JavaScript로 클래스를 시뮬레이션합니다. 단지 흉내내는 것일 뿐이지만 효과는 훌륭합니다.
클래스 생성자는 내부 상태를 저장하는 데 필요한 C#의 필드에 해당하는 모든 인스턴스 변수를 정의합니다. 예를 들어 다음과 같은 문이 있다고 가정해 보겠습니다.이 문은 _control이라고 하는 "필드"를 선언하고 생성자에 전달된 Silverlight 컨트롤 참조로 이를 초기화합니다. 전체적으로 40여개의 필드가 선언되었으며 이러한 필드는 진행 중인 페이지 넘기기를 위한 백분율 완료 그림(_percent)에서 등록된 이벤트 처리기를 나타내는 토큰(dispose가 처리기 등록을 취소하는 데 사용)에 이르는 모든 것을 저장하는 데 사용됩니다. 필드는 또한 initializeFramework에서 동적으로 생성된 몇 개의 XAML 개체와 addPage에 대한 호출로 등록된 XAML 개체에 대한 참조를 저장합니다.
PageTurnFramework.prototype은 모든 PageTurnFramework 메서드를 포함합니다. 메서드는 크게 세 가지 범주로 나눌 수 있는데, 우선 addPage 및 initializeFramework와 같은 공용 메서드, 그리고 마우스 이벤트 및 프레임워크에서 내부적으로 사용하는 Storyboard.Completed 이벤트에 대해 반응하여 작동하는 이벤트 처리기, 마지막으로 프레임워크 내부에서 사용되며 외부에서는 호출되지 않는 전용 메서드가 그것입니다. 흥미로운 코드가 많이 있지만 지면이 부족하므로 PageTurn.js를 다운로드하여 확인하시기 바랍니다.
프레임 아키텍처의 한 가지 흥미로운 부분은 페이지를 넘기는 도중에 마우스 단추를 놓았을 때(또는 커서가 컨트롤을 벗어났을 때) 어떻게 페이지 넘기기를 완료하는가 하는 것입니다. 초기화 시에 프레임워크는 createFromXaml을 사용하여 타이머를 사용하는 스토리보드 개체를 만듭니다. 그런 다음 스토리보드를 페이지 넘기기 캔버스에 추가하고(클래스 생성자에 페이지 넘기기 캔버스에 대한 참조를 전달해야 하는 이유 중 하나) Storyboard.Completed 이벤트에 대한 처리기를 등록합니다.
완료되지 않은 페이지 넘기기를 완료하기 위해 프레임워크는 Storyboard.begin을 호출하여 타이머를 시작합니다. 각 타이머 틱마다 _step 필드에 저장된 단계 크기를 사용하여 페이지 넘기기를 증가시키고, 페이지 넘기기가 아직 완료되지 않은 경우에는 Storyboard.begin을 다시 호출합니다. 작동하는 예를 보려면 페이지를 절반만 넘기고 마우스 단추를 놓으면 됩니다. 마우스 단추를 놓을 때 페이지가 얼마나 넘겨졌는지에 따라 시작한 위치로 되돌리거나 완전히 넘겨지게 됩니다.
스토리보드의 XAML 정의는 initializeFramework 메서드에서 _sb라는 변수에 저장됩니다. 이 정의에 값이 GUID인 x:Name 특성이 포함된 이유를 궁금해할 수 있을 것입니다. Silverlight 1.0에서 createFromXaml로 만든 스토리보드에 이름을 지정하지 않으면 createFromXaml에서 오류가 발생합니다. 따라서 스토리보드에 이름을 지정해야 하지만 응용 프로그램에 사용된 다른 이름과 충돌하지 않도록 하기 위해 GUID를 사용하여 이름을 지정한 것입니다.
아키텍처의 다른 흥미로운 부분은 프레임워크가 마우스 이벤트를 사용하는 방법입니다. 페이지를 나타내는 캔버스의 경우 addPage는 MouseLeftButtonDown, MouseMove 및 MouseLeftButtonUp 이벤트에 대한 처리기를 등록합니다. 왼쪽 넘기기는 오른쪽 페이지가 클릭되었을 때 시작되며 왼쪽 단추를 누른 상태에서 마우스를 왼쪽으로 이동하는 동안 진행됩니다. 비슷하게 오른쪽 넘기기는 왼쪽 캔버스가 클릭되었을 때 시작되며 마우스가 오른쪽으로 이동하는 동안 진행됩니다. 이벤트 처리기에서 사용되는 핵심 메서드는 _turnTo이며, percent-complete 매개 변수로 지정된 위치로 부분적으로 넘겨진 페이지가 끝까지 넘겨지도록 합니다.
프레임워크에서 관심을 끄는 마지막 측면은 페이지 넘기기를 표현하기 위해 변환과 클리핑 영역을 사용하는 방법입니다. initializeFramework는 오른쪽 페이지 및 왼쪽 페이지를 위한 클리핑 영역으로 사용할 두 개의 PathGeometry 개체를 만듭니다. RotateTransform 및 TranslateTransform을 포함하는 TransformGroup 개체도 만듭니다.
그림 6에서는 클리핑 영역과 변환을 사용하여 부분적으로 넘긴 페이지를 표현하는 방법을 보여 줍니다. 빨간색 삼각형은 위쪽 오른쪽 페이지에 사용되는 클리핑 영역입니다. 마우스가 왼쪽으로 이동하면 클리핑 영역이 작아지며 위쪽 페이지가 보이는 부분은 점차 줄어들고 아래쪽 페이지가 보이는 부분은 늘어납니다. 파란색 삼각형은 넘기기가 진행되는 동안 표시되는 왼쪽 페이지에 사용되는 클리핑 영역을 나타내며 노란색 사각형은 잘리는 페이지 영역을 나타냅니다.
090224_wdp3.gif
그림 6 페이지 넘기기를 표현하기 위한 클리핑 영역 및 변환
페이지의 위치와 방향을 지정하기 위해 RotateTransform과 TranslateTransform이 결합되어 사용되었습니다. (물론 삼각법이 많이 사용됩니다!) 마우스가 왼쪽으로 이동하는 동안 노란색 사각형이 왼쪽으로 이동하며 위쪽 위치로 회전한다고 생각해 보십시오. 그와 함께 파란색 삼각형은 점차 커지고 빨간색은 점차 얇아지면 페이지 넘기기가 어떻게 동작하는지 이해할 수 있게 됩니다.

결론

이 칼럼을 마감하기 직전에 PageTurnFramework API에 추가하면 유용할 것 같은 몇 가지 아이디어가 떠올랐습니다. 예를 들어 페이지 넘기기가 완료될 때마다 프레임워크가 이벤트를 발생시킨다면 페이지의 다른 내용을 업데이트하는 처리기를 작성할 수 있을 것입니다. 또한 넘기는 페이지와 함께 표시되는 그림자의 너비라든지 완료되지 않은 넘기기에 애니메이션 효과를 주는 데 사용되는 단계 크기와 같은 핵심 페이지 넘기기 매개 변수를 제어할 수 있도록 속성을 공개하면 유용할 것입니다.
자체 프로젝트에서 자유롭게 이 프레임워크를 사용하고 수정하십시오. 의견이 있으면 알려 주시고 기능 집합과 API에 대한 유용한 추가 기능이 생각나면 그 역시 알려 주십시오. 보내 주신 의견은 잘 정리했다가 버전 1.0보다 훨씬 나은 페이지 넘기기 프레임워크 버전 2.0을 만드는 데 활용하겠습니다.
Jeff에게 질문이나 의견이 있으면 다음 전자 메일 주소로 보내시기 바랍니다:wicked@microsoft.com.

필자소개

Jeff Prosise는 MSDN Magazine 편집자이며 Programming Microsoft .NET 을 비롯한 여러 권의 책을 집필했습니다. 또한 .NET Framework로 특화된 소프트웨어 컨설팅 및 교육 업체인 Wintellect( www.wintellect.com )의 공동 설립자이기도 합니다. 이 칼럼에 대해 의견이 있거나 문의 사항이 있으면 wicked@microsoft.com 으로 전자 메일을 보내시면 됩니다.