Silverlight2009.10.27 11:07
객체지향 언어를 사용하시는 많은 개발자분들은 좀 더 객체지향적인 코드를 원하곤 합니다. 여기서, 좀 더 객체지향적인 코드란 것은 객체지향이 추구하는 언어적인 특색을 잘 살리는 코드를 말하는 것이죠. 그래서, 많은 분들이 클래스 다운 클래스를 만드려고 하고, Design Pattern 등에 관심도 보이고 합니다. 또한, 객체의 생성과 소멸 등에 관해서도 관심을 갖게 되고요 :)

이번 포스팅에서는 Design Pattern 의 하나인 Observer Pattern과 Singleton Pattern을 포스팅 해 보려고 합니다. 그러나, 여기서 Observer Pattern과 Singleton Pattern을 사용하고 안하고의 유무에 따라서 코드가 좀 더 객체지향적이라고 할 수 있는 것은 아닙니다. 좀 더 크게 Design Pattern의 사용 유무가 객체지향적이다 아니다라고 할 순 없다는 것이죠.

또한, Design Pattern 을 접하시는 대부분의 개발자분들은, Design Pattern 에서 정의하는 Command Pattern, Factory Pattern, Observer Pattern 등의 용어만 접할 뿐, 이미 사용하고 있는 로직인 경우도 많습니다. 그래서 어떤 분들은, Design Pattern 을 로직이나 알고리즘 수준이 아닌, 개발자간의 커뮤니케이션에 필요한 용어 정도로 생각하시는 분들도 많습니다.

다만, Design Pattern 을 배움에 있어 객체 지향 언어의 특색을 전제해야 하는 것들이 있습니다. 바로 이런 특색들을 개념적으로 습득하시는 일련의 과정이 큰 도움이 될 것이라 생각합니다.

이번 포스팅에서 소개 해 드릴 Observer Pattern과 Singleton Pattern 은, Interface 나 abstract class 같은 추상 클래스에 대한 개념적 이해를 전제해야 합니다. 그럼, 간단히 Observer Pattern 을 포스팅하기 위한 목차로 시작해 보겠습니다.

1. Interface
2. Observer
3. Observer Control class
4. Singleton Pattern

Interface
우선, 기본적인 문법을 보시면
public interface IBackground
{
    void Changed(Brush _brush);
}
IBackground 라는 interface를 선언 한 뒤 IBackground 블럭 내에서 반환타입이 void 이며 파라미터로 Brush 타입의 인자를 받는다는 메소드의 형식만 선언하게 됩니다.
이 경우 IBackground 를 상속받는 class는 반드시 Changed 메소드를 구현해야 하며, 상속받은 class 는 IBackground 타입으로 형변환이 가능하고, 그 경우 Changed 메소드가 노출되게 됩니다.

사실, 위에서 말씀드린 것 이외에 interface의 다른 큰 특징은 없습니다. 말씀드린게 전부이죠.
헌데, 몇가지 매우 핵심적인 사항이 있습니다.
IBackground 라는 interface를 선언 한 뒤 IBackground 블럭 내에서 반환타입이 void 이며 파라미터로 Brush 타입의 인자를 받는다는 메소드의 형식만 선언하게 됩니다.
이 경우 IBackground 를 상속받는 class는 반드시 Changed 메소드를 구현해야 하며, 상속받은 class 는 IBackground 타입으로 형변환이 가능하고, 그 경우 Changed 메소드가 노출되게 됩니다.
바로, 다음의 3가지 사항입니다.
1. 메소드의 형식만 선언
2. 상속받은 class는 반드시 interface 에 정의 된 메소드를 구현
3. 상속받은 class는 interface 형으로 형변환이 가능

저는, Interface를 가장 쉬이 이해할 수 있는 한 마디가 바로 "표준"이라고 생각하는데요, 예를 들어 USB 포트를 들어 보면..

USB 포트는 일정한 규격, 또는 표준이라고 할 수 있습니다. 어떠한 디바이스 건 USB 포트의 형식에 맞춰 디바이스와 연결할 수 있도록 셋팅 해 둔다면, USB에 꽂는 즉시 디바이스를 인식하고 전원이 공급되게 되죠. 여기서 USB 포트는 표준을 제시하고, 디바이스 벤더는 USB 표준에 맞게 설계를 할 것이고요.

interface도 마찬가지로 "표준"이라고 생각하실 수 있습니다.
BlueUserControl class와 RedUserControl class 두 개의 UserControl 클래스가 있습니다.

<BlueUserControl.cs>
public partial class BlueUserControl : UserControl, IBackground
{
    public BlueUserControl()
    {
        InitializeComponent();
    }

    #region IOption Members 

    public void Changed(Brush _brush)
   {
        this.LayoutRoot.Background = _brush;
    } 

    #endregion
}


<RedUserControl.cs>
public partial class RedUserControl : UserControl, IBackground
{
    public RedUserControl()
    {
        InitializeComponent();
    } 

    #region IOption Members
 
    public void Changed(Brush _brush)
    {
        this.LayoutRoot.Background = _brush;
    } 

    #endregion


두 class 모두 IBackground interface 를 상속 받고, 반드시 구현해야 할 interface 내에서 정의한 메소드인 public void Changed(Brush _brush) 를 구현하고 있습니다.

MainPage의 Grid에 두 클래스를 배치 해 보도록 하죠.
<MainPage.xaml>

<UserControl x:Class="ObserverPattern.MainPage"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    xmlns:uc="clr-namespace:ObserverPattern.UserControls"

    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">

    <Grid x:Name="LayoutRoot" Background="Black">

        <Grid.ColumnDefinitions>

            <ColumnDefinition/>

            <ColumnDefinition/>

        </Grid.ColumnDefinitions>

        <uc:BlueUserControl x:Name="blueUserControl" Grid.Column="0"/>

        <uc:RedUserControl x:Name="redUserControl" Grid.Column="1"/>

        <Button x:Name="OptionChangeButton" Content="Changed" Height="30"

                HorizontalAlignment="Left"

                VerticalAlignment="Top"

                Margin="10,10,0,0"

                Click="OptionChangeButton_Click"/>

    </Grid>

</UserControl>


MainPage를 실행하면 두개의 컬럼으로 이뤄진 Grid 에 한쪽은 Blue, 한쪽은 Red로 실행 됩니다.


그럼, IBackground 를 상속받아 구현 된 두 UserCotnrol을 Changed 버튼을 클릭 했을 때, RedUserControl은 Blue로, BlueUserControl은 Red 로 바꿔 보도록 하겠습니다.
<MainPage.cs>
public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();
    } 

    IBackground option;
    public void optionChange()
    {
        SolidColorBrush brush = new SolidColorBrush(Colors.Blue);
        option = this.redUserControl;
        option.Changed(brush);
 
        brush = new SolidColorBrush(Colors.Red);
        option = this.blueUserControl;
        option.Changed(brush);
    }
 
    private void OptionChangeButton_Click(object sender, RoutedEventArgs e)
    {
        this.optionChange();
    }
}

Changed 버튼을 클릭 시, optionChanged 메소드가 실행 됩니다.
optionChanged 메소드에서는 UserControl 을 IBackground 형의 option 으로 할당한 뒤 option 객체의 Changed 메소드를 실행하게 되죠.
두 UserControl은 IBackground 형을 상속받았기 때문에 IBakground 형의 option으로 형변환이 가능하며, IBackground 에서 정의 된 메소드를 반드시 구현 했기 때문에, option 객체에 노출 된 Changed 메소드를 실행하게 됩니다.


USB 포트를 비교했었는데요, USB 포트의 표준에 맞춰 설계 된 디바이스르 USB 포트에 연결하면,
운영체제에서 디바이스를 인식하고, Driver 를 자동으로 설치하거나, Driver 를 설치하도록 지시하게 됩니다.
이와 마찬가지로, MainPage 에서 발생한 이벤트이지만, IBackground 를 상속받은 클래스의 객체에서 직접 객체 자신의 메소드를 통해 객체 자신의 속성을 변경하게 됩니다. 이는 interface 를 상속 받고, 반드시 구현 된 메소드가 존재하기 때문이죠.

아~ 여기서 제가 Observer 를 포스팅할까 했던 이유 중 하나인데요. 바로, 서로 다른 객체간의 통신(넓은 의미로 ㅎ)을 가능하게 하는 방법 중 하나가 interface의 활용이 될 수 있습니다. :)

다음에는 이런 interface의 특징을 활용한 Observer 를 만드는 방법을 포스팅 해 보겠습니다.
Posted by Min-gu, Kim
Silverlight2009.10.08 18:19
Microsoft Expression Encoder 3 에서는 SDK 가 제공 되는데요.
SDK 문서를 보시면 Get Started 에 Encoder 3 SDK 를 사용하는 방법이 자세히 설명 되 있습니다.

우선 Encoder 3 SDK 를 사용하기 위해서는 Project 에서 References 를 추가 해 주셔야 합니다.
Microsoft.Expression.Encoder
Microsoft.Expression.Encoder.Types
Microsoft.Expression.Encoder.Utilities


이렇게 네 가지 dll을 추가 하셔야 합니다.
(아, 마지막의 WindowBase 는, Encoder.Types 에서 ObservableCollection 을 사용했기 때문에 추가 해 줘야 하고요^^)

헌데, 여기서 문제점을 하나 발견 했는데요.

References 추가를 한 뒤 Get Started 에 나와 있을 법한 짧막한 코드를 실행 해 보니,
References 가 분명히 추가 되 있고, 해당 Path에는 분명히 dll 파일들이 존재 하는데도..
FileNotFoundException 이 나오더군요;;

실행 된 코드는 다음과 같습니다.

static void Main(string[] args)
{
    MediaItem mediaItem = new MediaItem(@"D:\SmoothTest\Butterfly.wmv"); 

    //create job and media item for video to encode
    Job job = new Job();
    job.MediaItems.Add(mediaItem); 

    //set output directory
    job.OutputDirectory = @"D:\SmoothTest\Encode"

    //encode
    job.Encode();
}


이대표님과 같이 열심히 뒤져 봤지만, 저와 같은 증상을 띈 분이 안 계신 것 같더라고요. Encoder 포럼에 질문도 해 보고 했지만 결국 못 찾았는데요.

한 가지 특징적인 것은 이대표님 PC와 제 PC가 동일한 스팩인데다, 64bit 운영체제 라는 점입니다.
그래서, 혹시나 하는 마음에 Virtual PC 를 설치하고, Windows 7 32bit OS를 설치 한 뒤에, VS2008SP1, Expression Encoder 3 를 설치 해서 다시 테스트 해 봤습니다.

그랬더니..

아주 잘 되더군요;;

결국, 잠정적 결론이긴 하지만, Microsoft Expression Encoder 3 SDK 는 64 bit 에서는 올바르게 동작하지 않는 것 같습니다.
Microsoft Expression Encoder 3 SDK 를 사용해서 개발을 하려면 32 bit 운영체제에서 해 보셔야 할 것 같네요 :)


Posted by Min-gu, Kim
Silverlight2009.10.05 15:05

Smooth Streaming 을 서비스 하기 위해서는 IIS 웹서버가 필요합니다. (IIS 버전은 7.0이상)
참고로, 필자의 Test 환경은 Windows Server 2008 R2인데요, IIS 7이상 설치가 가능한 OS면 2008 R2가 아니어도 상관 없습니다.

우선 IIS 웹서버가 구축 되 있다는 가정을 두고, 다음 순서부터 설명 드릴께요.

일단, IIS 웹서버에 IIS Media Services 를 추가적으로 설치 해 주셔야 합니다.

IIS Media Services 설치파일을 다운로드 하시려면, IIS 사이트를 방문하시면 됩니다.


사이트의 우측 상단에 보시면, 위 그림과 같은 링크가 있습니다. 여기서 서버 환경이 x86/ x64인지에 따라 다운로드 하세요.

설치파일 다운로드가 종료되면, 설치파일을 실행 합니다.

End-User License Agreement 를 체크 하신 뒤

Web Playlists, Bit Rate Throttling , Smooth Streaming 세 가지를 모두 선택 하신 후 설치 하시면 됩니다.

Default 로 모두 선택 되 있고, Session Helper 는 선택 되 있지 않은데요~ Smooth Streaming 서비스는 Session Helper 설치 유무와 상관 없이 잘 동작하기 때문에 Default 설정대로 설치하셔도 무방합니다.

이렇게 설치가 완료 되면, 서버 관리자. 혹은, IIS 웹서버 관리자를 띄워서 다음과 같이 Media Services 에 Bit Rate Throttling, Smooth Streaming 이 설치 되 있는지 확인 해 보세요.

그럼 Smooth Streaming 을 위한 준비는 모두 완료 된 것이고요.
Web Site 에서 Smooth Streaming 으로 인코딩 된 소스를 원하시는 폴더에 복사 해 두시면 됩니다.
물론, ism 파일과 ismc 파일도 모두 복사 해 두셔야겠죠 :)

서버 관리자. 혹은, IIS 웹서버 관리자를 띄워서 해당하는 사이트의 Smooth Streaming 인코딩 소스 폴더에서 Smooth Streaming Presentations 아이콘을 클릭해 보시면 Manifest 파일과 함께 Video Bit Rates , Durations 등 Smooth Streaming 인코딩 소스의 정보를 확인 하실 수도 있습니다.


이렇게 셋팅 된 Smooth Streaming 소스는 Silverlight Media Player 에서 AdaptiveStreamingSource 의 ManifestUrl 프로퍼티에 Uri 객체 형식으로 지정하게 되는데요, 이전 포스팅에서 "Smooth Streaming Url" 부분에 사이트 도메인을 포함한 ism 파일 경로와 마지막으로 "/Manifest" 를 덧하시면 됩니다. 특히, 마지막 부분의 "/Manifest" 가 없다면 Media Services 가 올바르게 설치 되 있다 하더라도 Manifest 파일을 로드 하지 못하게 되니 꼭 확인 하셔야 하겠네요 :)


this.Loaded += (s, e) =>
{
    Uri videoUri = new Uri("http://localhost:80/Smooth/winvideo-SL3Effectsa.ism/Manifest", UriKind.Absolute); 

    AdaptiveStreamingSource videoSrc = new AdaptiveStreamingSource()
    {
        MediaElement = SmoothMediaElement,
        ManifestUrl = videoUri
    }; 

    videoSrc.StartPlayback();
};


Posted by Min-gu, Kim
Silverlight2009.09.30 17:13

Silverlight 3 에서는 HD급 고화질의 영상을 끊김 없이 사용자의 환경(CPU, 로컬 네트웍 상태)에 기반하여 최적의 화질을 감상할 수 있는 Smooth Streaming 기술을 선보였습니다. 이전 버전인 Silverlight 2 에서 선보였던 Deepzoom 만큼이나 강력한 이슈가 되고 있는데요. 그래서, Smooth Streaming Media Player를 만드는 방법을 소개하도록 하겠습니다.

(Smooth Streaming 에 관해 더욱 자세히 알고 싶으시다면 Silverlight 사이트에 방문 해 보시기 바랍니다.)

우선, Smooth Streaming 을 이용한 Media Player UI를 구현하기 위해서는 Microsoft Expression Encoder 3 에 새롭게 추가 된 Media Player Templates 에서 SmoothStreaming.dll 과 PlugInMssCtrl.dll 을 추출하셔야 하는데요~

 C:\Program Files (x86)\Microsoft Expression\Encoder 3\Templates\en\

위 경로를 찾아가 보시면 다음과 같이 기본적으로 제공 되는 Templates 가 있습니다.


아무 Template 나 들어가 보시면

SmoothStreaming.xap 파일이 있는 것을 확인 하실 수가 있는데요, SmoothStreaming.xap 파일을 zip로 변경 하신 뒤 압축을 해제하시면, PlugInMssCtrl.dll 과 SmoothStreaming.dll 을 추출 하실 수 있습니다.

귀찮으신 분들을 위해서 다운로드 할 수 있도록 링크해 둘께요 :)

Smooth Streaming Media Player UI 를 구성하기 위해 솔루션을 만드신 후, References 에 PlugInMssCtrl.dll 과 SmoothStreaming.dll 을 추가합니다.

PlugInMssCtrl.dll 에는
Microsoft.Expression.Encoder.PlugInMssCtrl 네임스페이스 안에,
IPlugInMssCore, IPlugInMssOfflineSupport, IPlugInMssStatisiticsGraph 세가지의 인터페이스가 있습니다.
인터페이스 내 정의 된 프로퍼티나 메소드를 보면, StartPlayback, StopPlayback, GetBitratesInKbps, ParseManifest 등 이름만 봐도 무슨 역할을 하게 될 프로퍼티인지 가늠할 수 있는 것들이 많이 있네요 :)
바로 이 인터페이스들은 SmoothStreaming.dll 에서 사용 됐는데요.
SmoothStreaming.dll 에는

ExpressionMediaPlayer
Microsoft.Expression.Encoder.AdaptiveStreaming
Microsoft.Expression.Encoder.AdaptiveStreaming.Utilities
MS.Internal.Expression.Encoder.AdaptiveStreaming.Advertising
MS.Internal.Expression.Encoder.AdaptiveStreaming.Heuristic
MS.Internal.Expression.Encoder.AdaptiveStreaming.Logging
MS.Internal.Expression.Encoder.AdaptiveStreaming.Manifest
MS.Internal.Expression.Encoder.AdaptiveStreaming.Network
MS.Internal.Expression.Encoder.AdaptiveStreaming.Parsing
MS.Internal.Expression.Encoder.AdaptiveStreaming.Url
MS.Internal.Expression.Encoder.AdaptiveStreaming.Utilities
가 있습니다. (헉헉..)
그 중, Microsoft.Expression.Encoder.AdaptiveStreaming 네임스페이스 안에 Smooth Streaming Media Player UI를 구성할 수 있는 AdaptiveStreamingSource 클래스가 있습니다.
위에서 설명 드렸던 Microsoft.Expression.Encoder.PlugInMssCtrl 네임스페이스의
IPlugInMssCore, IPlugInMssOfflineSupport, IPlugInMssStatisiticsGraph 세가지의 인터페이스를 바로 AdaptiveStreamingSource 클래스가 상속을 받아 구현 되 있죠~ :)

아쉽게도, MSDN이나 구글링.. 등등 아무리 찾아봐도 이 AdaptiveStreamingSource 의 라이브러리 문서는 없는 것 같습니다. ^^
고로, 직접 사용 해 보시면서 느끼실 수 밖에 없을 것 같아요~

그럼, 직접 사용 해 보실 수 있도록.. 간단하게 Smooth Streaming Media Player 의 Source 를 연결하고, Play 하는 코드를 적어볼께요.

우선 XAML 에서 Media Player 가 될 엘리먼트는, 이전과 같이 MediaElement 입니다.
그리고, AdaptiveStreamingSource 클래스를 생성하여, MediaElement와 ManifestUrl (Smooth Streaming 으로 인코딩 된 결과물의 위치)을 설정하신 뒤, StartPlayback 메소드를 통하여 미디어를 재생 하실 수 있습니다.

this
.Loaded += (s, e) =>
{
    Uri videoUri = new Uri("Smooth Streaming Url", UriKind.Absolute);

    AdaptiveStreamingSource videoSrc = new AdaptiveStreamingSource()
    {
        MediaElement = SmoothMediaElement,
        ManifestUrl = videoUri
    };

    videoSrc.StartPlayback();
};


또한, AdaptiveStreamingSource를 보시면, Bit rate 의 변화를 나타내는 엘리먼트를 프로퍼티로 갖고 있는데요.
StatisticsGraph 프로퍼티 입니다. 이 프로퍼티의 타입은 UIElement 이기 때문에 원하시는 Layout Panel에 Add 하시면 사용자의 환경 변화에 따라 달라지는 Bit rate 그래프를 보실 수 있습니다.

또한, 이 Bit rate 를 실무에 적용하시게 된다면.. Poor 한 디자인 덕분에 새로 만들어야 할 사항이 오는데요.
그런 경우, AdaptiveStreamingSource의 PlayBitrateChange 등의 이벤트나 GetBitratesInKbps 등의 메소드를 적절하게 이용하셔야 할 듯 합니다.

저도 기회가 되면, AdaptiveStreamingSource 의 모든 맴버를 분석해서 다시 포스팅 하도록 할께요 :)
우선, 다음 번에는 Smooth Streaming 인코딩 방법과 IIS7에서의 Smooth Streaming 셋팅을 포스팅 하도록 하겠습니다.
Posted by Min-gu, Kim
기타2009.09.29 11:36

안녕하세요. 오늘은, Silverlight 기술 포스팅이 아닙니다.
얼마전 성황리에 마친 REMIX09에 제가 스피커로 참여했었는데요, 뒤 늦은 후기를 남기려고 해요.

이번 REMIX09 에는, MS의 키노트. 그리고, 잠시 휴식시간을 가진 뒤 Silverlight3, Expression, Web Platform 세 가지 트랙으로 나뉘어 진했됐습니다. 그 중, Silverlight3 에서 두 번째 세션을 제가 진행하게 됐습니다.


또한, 저희 Silverlight Korea 커뮤니티에서도, 부스 운영을 했는데요.
인디님과 승미님께서는 Silverlight Korea 티셔츠를 배포하기 위해 열심히 포장하고 계시네요. 간단한 Silverlight 퀴즈도 만드는 등 모두 열심히셨네요. 

저희 Silverlight Korea 스티커 인데요.. 아침부터 패러다임님께서 혼자 가위질 해 주셨어요. +_+
모두들 이른 시각(10시)부터 나오셔서 부스운영에 힘써 주셨습니다.

모두들 열심히 부스운영에 필요한 준비를 하고 계시는데.. 저는 가운데서 이렇게 세션 진행을 위한 발표자료 점검을 하고 있었습니다. ^^;;

점점 시간이 다가오고.. 스피커들도 준비를 시작하는데요. 우선, 장비 리허설부터 진행 했습니다.
MS의 박중석 대리님께서 저와 길버트님의 장비 리허설에 각별히 신경을 써주셨어요 :)
이번에 알았는데, 제 노트북의 그래픽카드가 1280x768을 지원하지 않더라고요. 그래서, 어쩔 수 없이 발표자료는 16:9 사이즈 기본 템플릿에서 4:3으로 바꿨고요.(양쪽 사이드가 잘린다고 해서..) 데모는 약간 떨림이 있더라도 강행할 수 밖에 없었습니다.

저는 이번 REMIX 행사 처럼 큰 규모의 행사에서 스피커로 진행하는 게 처음이었는데요, 그래서 인지 너무나도 떨렸답니다. 덕분에, 제 세션에 주어진 50분이란 시간 중에 초반 10~15분 정도는 "시...실버라.아..이...트으..." 거진 이 정도 수준으로 발표를 진행했었죠;; 아직도 생각하면 민망합니다. ㅠ.ㅠ 그래도, 제가 만든 데모를 시연할 차례가 오니, 조금씩 안정이 되더군요 :) 개발자는 개발자 인가 봅니다. 생각해보니, 제 코드를 본 뒤 안심(?)이 됐던 듯 하네요..ㅎ

아 참.! 다들 아시겠지만.. 이번 REMIX09행사에서는 Live Smooth Streaming 으로 Silverlight 3 트랙을 생중계 했었는데요. 휴즈플로우에서 UI를 구성해 주셨다고 하네요. 지금도 REMIX09 홈페이지를 가보시면 Silverlight 3 트랙 영상을 감상하실 수가 있습니다. 아직 못 보신 분들은 한 번 찾아가셔서 감상해 보세요.

http://www.visitmix.co.kr/live

REMIX 같은 큰 행사에서 스피커로 참여하게 되 너무나 감격스러운 하루였지만, 역시나 아쉬움이 남네요.
하지만, 다음 번 세미나엔 더욱 자신감을 갖게 되는 계기가 된 것 같습니다. ^^
Silverlight Korea 커뮤니티 부스도 순조롭게 잘 운영되고, 행사가 끝난 뒤 운영진분들과 함께 모임을 가졌는데요.
모두들 기분 좋게 마무리 하시는 것 같아서 정말 좋았습니다. 저 또한, 아쉬움을 뒤로 하고 즐거운 마음으로 다시 정진하도록 하겠습니다. 화이팅 :)

'기타' 카테고리의 다른 글

블로그 스킨 제작 중!  (0) 2012.08.03
QR Code 만들어 봤어요!  (0) 2010.08.27
블로그 개편 했습니다.  (0) 2010.07.30
REMIX09 스피커로 참여하다.  (2) 2009.09.29
2009 Elite Model Look Korea  (0) 2009.08.21
Posted by Min-gu, Kim
Silverlight2009.09.03 12:11

이번 포스팅은 Out-of-Broswer 를 Debugging 하는 간단한 Tip입니다. :D

Out of Browser 를 염두하고 개발을 하시다 보면, 디버깅이 안 되서 답답한 경우가 있을 것입니다.
저 또한, Out of Browser 를 테스트 하면서 디버깅이 안 되, 추측만 했었는데요.

자세히 찾아보니, OOB 도 디버깅 할 수 있는 방법이 있네요.

우선, 프로젝트 속성에서 Debug 탭을 선택 하신 후, Start Action에서 Installed out-of-browser application 을 선택 합니다.



그 다음, 실버라이트 프로젝트를 우 클릭 하신 뒤, Set as StartUp Project를 선택 하여 스타트 프로젝트로 설정하면 됩니다.


이렇게 설정하셨다면, Out-of-Browser 를 Debugging 하실 수 있습니다. :)

Posted by Min-gu, Kim
기타2009.08.21 14:50

 안녕하세요. 이번 포스팅에서는 (주)더블가이에서 실버라이트로 만든 2009 엘리트 모델 룩 코리아 온라인 인기 투표 페이지 사례를 소개 하고자 합니다.

화면 구성
 우선, 첫 메인화면을 접속 하시면, 현재 남자 모델, 여자 모델 각각의 랭킹 정보를 읽어옵니다.



 랭킹 정보를 읽고 난 뒤에 메인 화면에 들어갑니다. 남, 여 각각 순위가 가장 높은 순서대로 좌측의 Profile Thumbnail 부분과 중앙하단에 각각의 모델들이 정렬 됩니다.


 모델들의 Thumbnail 을 클릭하셔서 원하시는 남, 여 모델 각각의 자세한 프로필을 보실 수 있습니다. (Age, Height, Weight, Bust, Waist, Hip)

 Thumbnail 만 보고 투표를 하실 순 없겠죠^^? 좀 더 각각의 모델들을 면밀히 살펴 볼 수 있도록 하기 위해서, 남, 여 모델 각각의 화보집을 구경하실 수 있도록 구성 했어요. View Contents 버튼을 클릭하시면 되는데요~ 옆에 VOTE! 버튼은 진짜 투표를 하게 되는 것이고요~ Contents 를 보신 뒤 가장 맘에 드는 모델을 투표하시면 되겠죠 :)

컨텐츠 감상
 View Contents 버튼을 클릭하시면, Profile 우측에 Corverflow 로 표현 된 각 모델 개개인의 화보집을 감상 하실 수 있습니다.

 Silder 를 움직이면서, 혹은 << , >> 버튼으로 하나씩 감상 하실 수 있습니다. 물론 컨텐츠를 직접 마우스로 선택 하시면서 감상 하실 수도 있습니다.

 아.. 그리고 Zoom 버튼이나 현재 Coverflow 상에서 가운데 선택 된 컨텐츠를 클릭하시면, 확대 된 Deepzoom 영역이 새 창으로 뜨는데요, 줌인, 줌아웃은 3 단계로, MouseWheel과 Slider 를 움직이면서 감상 하실 수 있습니다.

<1단계> - 이미지의 세로 사이즈가 딥줌 영역의 세로 사이즈와 같기 때문에 Slider 를 통해서 좌우로 컨텐츠를 감상합니다.


<2단계> - 마우스로 클릭한 부분을 1단계 보다 좀 더 확대 하여 감상 하실 수 있습니다. 2단계 부터는 이미지의 세로 사이즈가 딥줌 영역의 세로 사이즈보다 적어지기 때문에 MouseWheel을 통하여 상하로, Slider를 사용하여 좌우로 컨텐츠를 감상합니다.


<3단계> - 마우스로 클릭한 부분을 2단계 보다 좀 더 확대 하여 감상 하실 수 있습니다.  마우스를 클릭하시면 다시 1단계로 돌아가게 됩니다.



투표하기
 투표하는 방법은 VOTE! 버튼을 클릭하시면 됩니다. VOTE! 버튼을 클릭하면, 투표가 됐다는 것을 사용자가 알 수 있게 해야 하는데요. 엘리트 모델 룩 대회에서 우승자는 파리 본사에서 개최하는 글로벌 대회에 참가하게 되기 때문에, 그 컨셉으로, VOTE! 버튼 클릭 시, Seoul 에서 해당 모델에게 투표 페이지가 날라가고 투표페이지가 해달 모델에게 도착하면 게이지(능력 증가?ㅎ)가 올라갑니다. 또, 동시에 비행기가 Seoul에서 Paris로 날아가게 되죠. 투표를 받았으니, 글로벌 대회 참가 확률이 높아진다? 이런 컨셉입니다.



 메인 화면에서 MEN, WOMEN 탭을 선택하여 남,여 모델 페이지를 이동하는데요, WOMEN을 선택하셔서 여자 모델들도 감상 해 보세요 :)



모델 투표하러 가기Click

'기타' 카테고리의 다른 글

블로그 스킨 제작 중!  (0) 2012.08.03
QR Code 만들어 봤어요!  (0) 2010.08.27
블로그 개편 했습니다.  (0) 2010.07.30
REMIX09 스피커로 참여하다.  (2) 2009.09.29
2009 Elite Model Look Korea  (0) 2009.08.21
Posted by Min-gu, Kim
Silverlight2009.08.19 18:49
Lambda Expressions in Silverlight #1 포스팅과 이어지는 내용입니다.

 구체적인 예를 한 가지 들어보자면, Image Control을 배치 한 뒤 ImageOpened 되면 Image Control을 MouseLeftButtonUp 했을 때, 마우스의 포인트를 ListBox에 추가하는 기능을 구현한다고 가정 해 보겠습니다.
 위와 같이 구현하기 위해서는 이미지가 반드시 Opened 되야 만 MouseLeftButtonUp 이 발생하여야 하도록 하기 때문에 ImageOpened 이벤트 구현부에서 MouseLeftButtonUp 이벤트를 구현 한다면, 무리 없이 모든 기능을 구현할 수 있습니다.
int count = 1;
this.LogoImage.ImageOpened += (s, e) =>
{
    this.MousePositionListBox.Items.Clear();
    this.LogoImage.MouseLeftButtonUp += (obj, args) =>
    {
        this.MousePositionListBox.Items.Add(String.Format("{0} , Point : {1}",
            (count++).ToString(), args.GetPosition(this.LogoImage)));
    };
};

 아무 문제 없이 쉽게 구현 한 것 같지만, 여기에는 한 가지 중요한 문제가 존재합니다. 바로 Image Control의 Source가 변경 되는 경우, ImageOpened 가 또 일어나게 된다는 점이죠. 그렇게 되면, MouseLeftButtonUp 이벤트는 Image Control 의 Source가 변경 될 때마다 이벤트 구현부분인 람다식의 구현부가 계속 추가 되겠죠. 그럼 MousePositionListBox에는 Image Control이 변경 된 만큼 뜨게 됩니다. 

 이런 경우를 막기 위해서, 보통 람다식을 떼고 아래와 같이 코드를 입력하여 방지 할 수 있는데요,
Int32 count = 1; 

public MainPage()
{
    InitializeComponent();
 
    bool firstImageOpened = true;
    this.LogoImage.ImageOpened += (s, e) =>
    {
        this.MousePositionListBox.Items.Clear();
        this.count = 1;

        if (firstImageOpened)
        {
            this.LogoImage.MouseLeftButtonUp += new MouseButtonEventHandler(LogoImage_MouseLeftButtonUp);
            firstImageOpened = false;
        }
        else
        {
            this.LogoImage.MouseLeftButtonUp -= new MouseButtonEventHandler(LogoImage_MouseLeftButtonUp);
            this.LogoImage.MouseLeftButtonUp += new MouseButtonEventHandler(LogoImage_MouseLeftButtonUp);
        }
    };

void LogoImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    this.MousePositionListBox.Items.Add(String.Format("{0} , Point : {1}",        (count++).ToString(), e.GetPosition(this.LogoImage)));
}


 우선 count 변수를 맴버 변수로 바꿔야 했고, ImageOpened 가 처음 일어나는 것인지 여부를 체크하여 동일한 이벤트 구현부를 추가 또는 삭제 하는 작업을 추가했습니다. 이렇게 되면, Image Control의 Source가 변경 되어 ImageOpened 될 때 MouseLeftButtonUp에 등록되는 함수는 단 하나만 되게 됩니다.

 미리 예상을 하고 람다식을 사용하지 않았다면 상관이 없지만, 이미 사용한 뒤에 나중에 이런 문제를 발견한다면 (그나마 발견하면 다행이겠죠) 앞서 설명을 드렸던 Variable Lifting이 쓰인 경우 람다식을 떼어 내기가 여간 쉬운 것이 아닙니다. 람다식 블럭 내에서 사용 된 모든 변수를 맴버로 떼어내던가 하는 귀찮고, 정교한 작업을 해야 하기 때문이죠.

 그러나, 이런 점을 Variable Lifting을 그대로 이용하여 적용할 수 있는 방법이 있습니다. 람다식의 다른 표현을 사용하는 것이죠 :)
bool firstImageOpened = true;
MouseButtonEventHandler mouseHandler = null;
this.LogoImage.ImageOpened += (s, e) =>
{
    this.MousePositionListBox.Items.Clear();
    int count = 1;
 
    if (firstImageOpened)
    {
        mouseHandler = delegate(object sender, MouseButtonEventArgs args)
        {
            this.MousePositionListBox.Items.Add(String.Format("{0} , Point : {1}",
                (count++).ToString(), args.GetPosition(this.LogoImage)));
        };
        this.LogoImage.MouseLeftButtonUp += mouseHandler;
        firstImageOpened = false;
    }
    else
    {
        this.LogoImage.MouseLeftButtonUp -= mouseHandler;
        this.LogoImage.MouseLeftButtonUp += mouseHandler; 
    }
};
Posted by Min-gu, Kim
Silverlight2009.08.19 17:23
 안녕하세요. 오늘은 포스팅 할 주제는 C# 3.0의 언어적 특성인 부분이라서 Silverlight 뿐만 아니라, WPF든, WinForm이건 상관 없이 유용한 팁이 될 것 같습니다.

Variable Lifting
 제가 생각하는 람다식의 가장 큰 이점 중 하나는 바로, Variable Lifting 입니다.
 Variable Lifting 이란, 다음 코드와 같이 전역 변수가 아닌 블럭 내 지역 변수 임에도 람다식의 블럭에서도 사용이 가능한 것을 말합니다. 
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    int index = 0;

    this.TestButton.Click += (s, args) =>
    {
        index++;
        MessageBox.Show(index.ToString());
    };
}

 위 코드에서 int형 변수인 index는 MainPage_Loaded 함수의 블럭에 존재하는 지역 변수이지만, TestButton.Click 이벤트를 등록하는 람다식의 블럭에서도 사용이 가능합니다.

 어떻게 보면 그냥 당연하게 보일 수도 있는데요. 그럼 람다식이 아닌 형태로 코드를 타이핑 했다면 어떨까요?
Int32 index = 0;

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    this.TestButton.Click += new RoutedEventHandler(TestButton_Click);
}

void TestButton_Click(object sender, RoutedEventArgs e)
{
    this.index++;
    MessageBox.Show(this.index.ToString());
}


 보시는 바와 같이, index 변수를 전역으로 올려서 써야만 TestButton_Click 이벤트를 구현하는 부분에서 사용할 수 있습니다.

 이렇게 좋은 Variable Lifting 를 활용하다 보면, 람다식을 너무 많이 쓰게 됩니다. (특히, 이벤트의 구현 같은 부분에서 말이죠) 그러나, 너무 과하게 사용하다 보면 아니, "적재적소에 사용하지 않고 남발하게 되면" 뜻하지 않게 이벤트가 엉켜 있거나 등록이 중복 되어 구현부가 수 번 실행 되는 등의 문제가 발생하게 됩니다.

 위와 같은 문제가 일어나는 구체적인 예제는, #2에서 다시 포스팅 하겠습니다. (바로~)
Posted by Min-gu, Kim
Silverlight2009.07.28 11:39

 안녕하세요.

 지난 10일 Silverlight 3 RTW (정식버전)이 런칭 되면서, Deepzoom Composer 도 함께 새 버전이 나왔는데요. 새로운 Deepzoom Composer 를 열심히 분석 해 본 결과, 놀라운 기능(Sildershow, Navigation, Hyperlink)이 추가 된 것 처럼 보이지만, 실상 Export 해 보면 지난 버전과 크게 차이나는 게 없고, scene.xml 이란 파일이 생성되는데 도통 어떻게 써먹는 것인지도 모르겠더라고요. 그래서 미 완성된 버전이라 생각하고 차후 버전을 기다려 왔습니다.
 헌데, 지난 22일 차후 버전이 드디어 나왔더군요!! +_+

New Deepzoom 다운로드

 우선, 놀랍고 쉽게 구현 할 수 있는 Sildershow, Menu, Hyperlink 세 가지 기능에 관해 설명 드리겠습니다.
 

 새 버전의 Deepzoom Composer에서 Compose 메뉴를 가보시면, Laysers 좌측에 새로 생긴 Slidershow, Menu, Internal Links, External Links 메뉴가 생겼습니다. 각각은 Slidershow, Menu, Hyperlink 를 디자인 할 수 있도록 지원합니다. :D

Slidershow

 Slidershow 의 경우에는,
Layers 에서 Image를 선택해서 Slidershow에 Drag and Drop으로 추가를 하시는데요, 이 때 순서를 정하시는 대로 Slidershow 를 실행하게 됩니다.

 물론, Slidershow 내에서 추가 된 Image의 순서를 마찬가지로 Drag and Drop으로 변경 하실 수 있습니다.

 나중에 Export 하게 되면, Slidershow가 기능이 추가 됩니다. +_+




















Menu

 Menu 도 Slidershow와 마찬가지로 Layers 에서 메뉴가 될.. (정확히는 메뉴를 Click시 보여지게 될 Image) Image를 Drag and Drop으로 추가 하실 수 있습니다.























 또,  Menu 를 디자인 하기 위해 상단에 7가지 기능을 제공 하는 버튼이 있습니다.
 마우스 우클릭을 통해서, 메뉴 이름을 수정할 수도 있습니다.

 저는 이 기능들을 이용해서 메뉴를 이렇게 수정하였습니다.

Hyperlink
Internal Links
Internal Links 는 MultiScaleImage 내에서 SubImage를 선택했을 경우, 다른 SubImage로 이동할 수 있도록 하는 기능을 디자인 할 수 있게 합니다.

 Layers 에서 Internal link 될 이미지를 선택 하신 후, Drag and Drop을 통해 Internal links 에 추가 하시면, Direct Link 팝업 창이 뜨는데요, 여기서 Link 될 이미지를 선택하시면 됩니다.

Internal link를 디자인 하게 되면, 좌측의 이미지처럼, Hyperlink 이미지와 Hyperlink 이미지를 선택 시, Link 될 이미지가 보이게 됩니다.

우클릭을 통해서 Link를 수정하시거나 삭제하실 수 있습니다.












External Links

External Links 는 MultiScaleImage 내에서 SubImage를 선택했을 경우, 새 브라우저를 띄워 지정된 URL로 이동하거나 하는 기능을 디자인 할 수 있게 합니다.

 Layers 에서 External link 될 이미지를 선택 하신 후, Drag and Drop을 통해 External links 에 추가 하시면, External Links Management 팝업 창이 뜨는데요, 여기서 Name, URL, Description을 입력하시면 됩니다.
Name : External link 명
URL : External link 될 사이트 URL
Description : 입력 시 External Image에서 Tooltip 표시

모든 디자인이 완료 되셨다면, Export 하셔서 결과물을 확인 하실 수 있습니다.
 Export 에서도 몇가지 추가 된 사항이 있는데요, Templates 를 보시면, Deep Zoom Navigation (Default) 가 있습니다. 이것을 선택 하신 후, 하단에 추가된 Preview 버튼을 클릭 하시면 바로 결과물을 확인 하실 수도 있습니다 :D

샘플
Posted by Min-gu, Kim

티스토리 툴바