Adobe Animation Edge CC


참조 URL
  1. http://html.adobe.com/edge/animate/
  2. http://helpx.adobe.com/creative-cloud/learn/start/animate.html



 Adobe에서 HTML5에서 애니메이션을 쉽게 만들 수 있는 툴을 제공하고 있다. 플래시나 Silverlight 같은 타임라인으로 애니메이션을 만들도록 하고 있다.




[동영상1] Adobe Edge로 애니메니션 만드는 예제














[Exchange] Exchange의 EWS에서 일정관련 연계 작업시 GlobalObjectId를 이용해 일정 찾기


일정을 사용자가 작성하면 ItemId와 GlobalObjectId가 생성이 된다. 

ItemId는 Exchange에서 Item을 인식하는 Unique 값으로 유일한 값을 나타낸다. 그리고 다른 사용자와의 일정에서 공통적인 값을 GlobalObjectId를 사용하여 같은 일정인지를 알아 낼 수 있다.


사용자A가 일정을 만들 때 사용자B를 참조인으로 입력 후 생성하면


사용자A : ItemId : aa1, GlobalObjectId : abcdef

사용자B : ItemId : bb1, GlobalObjectId : abcdef


와 같이 생성이 되게 된다.



그러면 타 시스템에서 EWS를 사용하여 정보를 알아 내기 위해서 아래와 같은 코드로 GlobalObjectId를 가져올 수 있다.


Appointment exItem = null;
 
// GlobalObjectId
ExtendedPropertyDefinition globalObjectId = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Meeting0x03MapiPropertyType.Binary);
 
//하나의 객체에 대해서만 바인딩
exItem = Item.Bind(service.Servicenotification.ItemIdnew PropertySet(
            ItemSchema.Id,
            ItemSchema.Subject,
            AppointmentSchema.ICalUid,
            globalObjectId)) as Appointment;

[코드1] GlobalObjectId의 값을 가져오는 코드


위 코드에서 ExtendedPropertyDefinition으로 확장 프로퍼티를 사용해서 가져와야 하며 선언 시 '0x03'을 입력하고 Binary를 선택해야 한다. 이제 넘겨진 값을 '코드2'에서와 같이 스트링으로 변환해서 사용 할 수 있다.


Convert.ToBase64String((byte[])exItem.ExtendedProperties[0].Value);

[코드2] Binary 형식을 스트링으로 변환하는 코드



이와 같은 코드로 다른 시스템과 연계하여 여러사람에 관계된 같은 일정을 찾아서 변경 해 줄 수 있을 것이다. 그렇지만 예외 케이스가 있다. 반복 일정에서 특정 항목만 편집하여 참조인을 추가 하는 케이스에서는 GlobalObjectId가 변경이 일어 나게 된다. 아래 글에서 설명이 나와 있다.



Using GlobalObjectId poses a problem however…If you were to create a recurring appointment and invite one attendee for only one instance of that recurring appointment that attendee ends up with only the one exception instance of the parent recurring appointment in their calendar.  This is called an “orphaned” appointment.  This type of appointment’s GlobalObjectId has additional information in it related to the exception date (for more information look at PidLidGlobalObjectId in MS-OXOCAL).  The bottom line here is that this orphaned instance in this one attendee’s calendar will have a GlobalObjectId, and therefore UID, which doesn’t match the related appointments in the other attendee’s and organizer’s calendar.  Henning’s code won’t work in this specific scenario…


참조 URL : http://blogs.msdn.com/b/mstehle/archive/2009/09/02/ews-uid-not-always-the-same-for-orphaned-instances-of-the-same-meeting.aspx


 


그래서 위의 문제점과 관련하여 CleanGlobalObjectId 라는 것이 존재하고 이는 위의 같은 CASE일때도 Id가 달라 지지 않는 프로퍼티를 사용해야 할 것이다.


The format of this property is the same as that of LID_GLOBAL_OBJID (PidLidGlobalObjectId). The value of this property must be equal to the value of LID_GLOBAL_OBJID, except the YH, YL, M, and D fields must be zero. All objects that refer to an Instance of a recurring series (including an orphan instance), as well as the recurring series itself, will have the same value for this property.


참고 URL : http://msdn.microsoft.com/en-us/library/cc839502.aspx



그래서 결론 적으로 아래 코드처럼 ClearnGlobalObjectId를 사용해서 값을 가져와서 연계 하면 변하지 않는 값으로 외부 시스템과 연동할 수 있을 것이다.


// GlobalObjectId
// ExtendedPropertyDefinition globalObjectId = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Meeting, 0x03, MapiPropertyType.Binary);
 
// LID_GLOBAL_OBJID 
ExtendedPropertyDefinition globalObjectId = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Meeting0x23MapiPropertyType.Binary);

[코드3] ClearnGlobalObjectId로 변경한 코드








Visual Studio 2013 Preview


참조 URL
  1. http://www.microsoft.com/visualstudio/eng/2013-downloads
  2. http://channel9.msdn.com/Shows/Visual-Studio-Toolbox/Visual-Studio-2013-Preview
  3. http://channel9.msdn.com/Events/Build/2013/3-339
  4. http://channel9.msdn.com/Events/Build/2013/3-503
  5. http://channel9.msdn.com/Events/Build/2013/2-546
  6. http://channel9.msdn.com/Shows/Visual-Studio-Toolbox/Asynchronous-Debugging-in-Visual-Studio-2013
  7. http://channel9.msdn.com/Shows/Web+Camps+TV/New-Features-in-Visual-Studio-2013-for-Web-Developers



 마이크로소프트에서 Visual Studio 2013에 대해서 프리뷰판이 올라왔다. 2012에 툴에 대해서도 아직 제대로 모르는데 2013이 벌써 나오려고 하고 있으니 툴만 익히는데 버거운거 같다. ㅠㅠ;;


 필요하신분은 링크에서 다운 받아 프리뷰해보시면 될거 같습니다. 저도 조만간 집에 컴터가 세팅이 되면 설치를 해보려고 하네요.



Download

Install and try Visual Studio today and seize the future of development.











Real time Apps #4 - SSE ( Serve Sent Events )


참조 URL
  1. http://en.wikipedia.org/wiki/Server-sent_events - 위키피디아
  2. http://www.w3schools.com/html/html5_serversentevents.asp
  3. https://today.java.net/article/2010/03/31/html5-server-push-technologies-part-1#sse
  4. http://www.w3.org/TR/2012/WD-eventsource-20120426/
  5. http://techbrij.com/real-time-chart-html5-push-sse-asp-net-web-api
  6. http://m.mkexdev.net/71

  

목차
  1. Polling - 있어?
    [ASP.NET MVC] - Real time Apps - Polling
  2. LongPolling - 있으면 보내줘!
    [ASP.NET MVC] - Real time Apps - LongPolling
  3. SSE ( Server Send Events ) - 있으면 보내줘 기다릴께~ 
    [ASP.NET MVC] - Real time Apps - SSE ( Serve Sent Events )
  4. WebSocket - 어! 왔네~
    [ASP.NET MVC] - Real time Apps - WebSocket
  5. SignalR - over WebSocket ( MS Platform )
    [ASP.NET MVC] - Real time Apps - SignalR over WebSocket


 이 포스트에 있는 내용이 언제나 확실한 정답은 아닙니다. 진실이라고 생각해 왔던 전제가 시간의 지남에 따라 들어나지 않았던 다른 이면 때문에 좋은 방향으로 이끌어 낼 수 있는 역할로 변환 되는게 역사적으로도 많은 증명 있었습니다. 그렇지만 저는 현재 상황에서 최선의 답을 찾고자 노력하였으며 이 글을 읽는 다른 분들에게 다음 길을 갈 수 있도록 도와주는 디딤돌이 되고자 노력하고자 포스팅을 통해 공유하고자 하는 것입니다. 그리고 프로그래머라는 타이틀을 달고 살아야 한다면 "왜"라는 의문을 항상 가지고 다니면서 자신의 위치에 안주하지 않고 항상 노력하는 모습으로 살아 가고자 합니다. 언제든 지적이나 오류가 있으면 피드백 부탁 드리겠습니다.

ing™       


 이번에는 SSE(Server Sent Events)에 대해서 알아 보자. SSE는 HTML5의 스펙으로서 단방향 푸시를 구현하기 위해 제안된 표준 기술이다. 앞의 Polling, LongPolling은 묵시적인 표준과 같은 기법의 범주에 속한다 할 수 있겠다. 그렇지만 SSE가 완전한 푸시를 구현한 스펙은 아니다.  소켓 통신과 같이 서버에서 클라이언트로 임의의 시간에 데이터를 보내주는 사항은 아니며 이전 기술과 같은 폴링 기법과 같은 유사한 방법으로 커넥션을 유지해 구현되고 있다. '그림6'로 전체 동작 방식을 이해해 보자.


[그림 6] SSE 동작 방식


1. 브라우저의 javascript에서 EventSource('url') 객체를 이용하여 웹서버와 통신 세션을 맺는다.

2. 서버에서 이벤트가 발생하면 개발자가 정의한(여기서는 Message로 하겠다) 해당 정보를 브라우저에 보내주고 커넥션은 유지한다.

3. 서버에서 이벤트가 두번째로 발생이 되면 유지되고 있는 커넥션을 통해 Message를 보내준다.

4. 연결 종료시 까지 3단계를 수행 한다.

5. 만약 중간에 어떤한 이유로 종료가 되었다면 EventSource 객체는 다시 통신 세션을 맺는다.


 SSE는 지금까지 살펴본 유사 Polling 기법과는 다르게 서버와의 커넥션을 유지하여 서버에서 발생한 이벤트 정보를 브라우저에 보내주는 방식이다. 추가 이벤트 정보를 받을 때마다 유지된 커넥션을 통하므로 재 연결시 필요한 부가 정보(사용자 정보, 쿠키, 헤더,...) 없이 데이터를 받을 수 있게 된다.


<!-- Polling 하여 받은 데이터를 반영할 수 있는 DOM --> <ol id="messages"></ol> @section scripts{     <script type="text/javascript">         $(function () {             if (typeof (EventSource) !== "undefined") {                 // 이벤트 소스를 선언한다. EventSource('/ControllerName/GetMesages');                 var eventSrc = new EventSource("@Url.Action("GetMessages")");                 // 이벤트 소스 객체에서 데이터를 받는 이벤트 처리 핸들러 선언                 eventSrc.addEventListener("open", function (evt) {                     $("<li>").text('Opened!').appendTo("#messages");                 });                 // 이벤트 소스 객체에서 데이터를 받는 이벤트 처리 핸들러 선언                 eventSrc.addEventListener("message", function (evt) {                     $("<li>").text(evt.data).appendTo("#messages");                 });                 // 이벤트 소스 객체에서 에러 이벤트 처리 핸들러 선언                 eventSrc.addEventListener("error", function (evt) {                     console.log(evt);                 });             }             else {                 alert('EventSource 객체를 지웒하지 않는 브라우저 입니다.');             }         });     </script> }

[코드5] SSE - Browser의 HTML과 Javascript


 위 코드는 페이지가 로딩이 되면 EventSource 객체를 통해 웹 서버에 커넥션을 맺는다. 그리고 EventSource에서 제공하는 이벤트에 대해서 open, message, error에 대해 처리할 수 있는 핸들러를 각각 선언하여 연결한다. open 이벤트는 #messages 테그에 'Opened!'를 표시하도록 하고 message 이벤트는 서버에서 보내준 데이터 값을 표시하고, error 이벤트는 console에 표시하도록 하였다. 이제 아래 코드를 통해 서버쪽의 코드를 알아 보자.


/// <summary> /// 초기화시 중복 초기화가 되지 않도록 잠금 역할하는 객체 /// </summary> private static object _blockCollectionLock = new object(); /// <summary> /// 메세지 컨테이너 역할 /// </summary> private static BlockingCollection<string> _data = null; /// <summary> /// 생성자 /// </summary> public EventSource2Controller() { InitSSE(); } // // GET: /EventSource2/ public ActionResult Index() {     return View(); } /// <summary> /// 중간 정산 - 중간에 채워진 버퍼의 내용을 보낸다. /// </summary> public ActionResult GetMessages() { // EventSource로 통신할 때는 ContentType을 'text/event-stream'으로 해야 한다.     Response.ContentType = "text/event-stream";     Response.Expires = -1;     var message = string.Empty;     while (true)     {         Thread.Sleep(1000); if (_data.TryTake(out message, TimeSpan.FromMilliseconds(1000)))         {             // 종료하지 않고 일부 데이터만 웹 브라우저에 보냄             if (Response.IsClientConnected)             {                Response.Write("data: " + message + "\n\n");                 Response.Flush();             }         }         else         {

// 서버에 데이터가 없으면 종료하고 커넥션을 닫는다.             Response.Write("data: 종료\n\n");             Response.Flush();             Response.End();             break;         }    }

    return Content("""text/event-stream"); } /// <summary> /// 초기화 함수 /// </summary> [NonAction] // 웹에서 직접 호출해도 동작하지 않도록 해주는 Attribute protected void InitSSE() {     _data = new BlockingCollection<string>();     _data.Add("started");     for (int i = 0i < 10i++)     {         _data.Add("item" + i.ToString());     }     _data.Add("ended"); }

[코드6] SSE - Server side 코드



 '코드6'의 Server-side 코드는 이전 Polling 기법과는 다르게 다소 복잡하게 수행이 된다. 생성자에서 초기화 함수인 InitSSE()를 호출하여 초기화를 진행하고 Browser에서 EventSource를 통해 요청한 GetMessage()는 내부적으로 루프를 돌면서 수행하며 계산된 결과를 브라우저에 'Response.Write()'를 통해서 브라우저에 보내주고 있다. 이때 커넥션을 종료하지 않고 그대로 유지하며 지속적으로 클라이언트인 브라우저에 보내준다. 실제적인 비지니스 개발에서는 이 부분에서 DB를 폴링하여 적절한 값의 변화를 브라우저에 보내줘 클라이언트에서는 실시간으로 정보가 변경되는 것 같이 보여주도록 할 수 있다는 것이다. 이전 Polling과는 다른점은 EventSource를 통해 한번만 연결된 상태에서 보다 적은 통신 용량으로 같은 효과를 낼 수 있다는 것이다. 아래 '그림7'로 결과 화면을 확인해 보자.



[그림7] SSE - 결과 화면



소스 코드 자체에 주석과 직관적인 코딩으로 충분히 파악이 가능할 것으로 예상하므로 별도의 설명을 생략하도록 하겠습니다. 포스트의 내용이 장황한 설명 보다는 주석과 소스코드 자체 만으로도 이해할 수 있도록 하기 위해 노력하였습니다. 실 개발에서도 적용할 수 있도록 간단하면서도 현실적인 예제 프로그램을 통해 각 소스를 만들고 이해 시키고자 하였으며 실무에 필요한 개발요구 사항들을 해결 하는데 도움이 되고자 노력하였습니다. 그리고 소스와 같이 있는 주석을 이용해 nDoc이나 별도의 자동 Document 제작 유틸로 API 문서를 만드는 데에도 도움이 되었으면 한다. 
※ DOC에 대한 프로그램 정보 Util link

ing™       



Real time Apps #3 - LongPolling


참조 URL
  1. http://techoctave.com/c7/posts/60-simple-long-polling-example-with-javascript-and-jquery
  2. http://tkjeon.tistory.com/entry/Jquery-Jquery-폴링Polling-기법
  3. http://msdn.microsoft.com/ko-kr/library/dd449174.aspx - TaskCompletionSource<TResult>


목차
  1. Polling - 있어?
    [ASP.NET MVC] - Real time Apps - Polling
  2. LongPolling - 있으면 보내줘!
    [ASP.NET MVC] - Real time Apps - LongPolling
  3. SSE ( Server Send Events ) - 있으면 보내줘 기다릴께~ 
    [ASP.NET MVC] - Real time Apps - SSE ( Serve Sent Events )
  4. WebSocket - 어! 왔네~
    [ASP.NET MVC] - Real time Apps - WebSocket
  5. SignalR - over WebSocket ( MS Platform )
    [ASP.NET MVC] - Real time Apps - SignalR over WebSocket


 이 포스트에 있는 내용이 언제나 확실한 정답은 아닙니다. 진실이라고 생각해 왔던 전제가 시간의 지남에 따라 들어나지 않았던 다른 이면 때문에 좋은 방향으로 이끌어 낼 수 있는 역할로 변환 되는게 역사적으로도 많은 증명 있었습니다. 그렇지만 저는 현재 상황에서 최선의 답을 찾고자 노력하였으며 이 글을 읽는 다른 분들에게 다음 길을 갈 수 있도록 도와주는 디딤돌이 되고자 노력하고자 포스팅을 통해 공유하고자 하는 것입니다. 그리고 프로그래머라는 타이틀을 달고 살아야 한다면 "왜"라는 의문을 항상 가지고 다니면서 자신의 위치에 안주하지 않고 항상 노력하는 모습으로 살아 가고자 합니다. 언제든 지적이나 오류가 있으면 피드백 부탁 드리겠습니다.

ing™       


 이번에는 LongPolling에 대해서 알아 보자. 좀전에 Polling에 대해서 알게 되었다면 별로 어렵지 않게 이해를 할 수 있을 것으로 예상한다. 그냥 Polling은 주기적으로 서버에 요청하는 방식이지만 LongPolling 방식은 한번 요청하고 서버에 데이터가 있을때만 반환받는 방식이다. 아래 '그림3'으로 보면 좀더 쉽게 이해할 수 있을 것이다.


[그림3] LongPolling 방식


 1. Request1로 서버에 요청하고 서버에서 Event( or Data )가 발생되면 해당 형식( 여기서는 Message라고 정의 )을 브라우저에 보내주고 브라우저 커넥션은 끊어진다.

 2. 받은 데이터를 처리하고 곧바로 서버에 Request2를 요청하고 데이터가 발생할 때까지 대기한다.

 3. 1단계를 다시 시작한다. 


 이와 같은 단계로 LongPolling 방식이 구동이 된다. Polling와 LongPolling 방식은 전체적으로 비슷한 방식을 개발할 수 있으나 다른점은 'LongPolling'이라는 이름처럼 길게 대기하여 서버에 응답요청을 한다는데 있다. 길게 기다리다가 "있으면 보내줘!"와 같은 컨셉이다. 이제 실제 코드로 알아가 보자.


<!-- Polling 하여 받은 데이터를 반영할 수 있는 DOM -->
<ol id="messages"></ol>
 
@using (Ajax.BeginForm("PostMessage"new AjaxOptions())) { 
    <p>
        Say : @Html.TextBox("messageText")
        <input type="submit" /> 
    </p>
}

<!-- 위 코드는 아래의 HTML Tag로 변환된다. <form action="/LongPolling/PostMessage" data-ajax="true" id="form0" method="post">    <p>         Say : <input id="messageText" name="messageText" type="text" value="" />         <input type="submit" />      </p> </form> -->

@section scripts{ <script type="text/javascript">     $(function () {         // Begin the LongPolling loop         getNextMessage();         // Form의 Submit 이벤트  통제         $("form").submit(function () {             var form = $(this);

            // messageText의 Html tag에 입력된 값을 가져온다.              var txtMessageText = $(form.find('#messageText'));

            // Ajax로 서버에 입력한 값을 넘겨준다.             $.post('@Url.Action("PostMessage")', { 'messageText': txtMessageText.val() }, function () {                 txtMessageText.val('');                 txtMessageText.focus();             });                              // HTML의 Submit가 일어나지 않도록 한다.             return false;         });     });     // 서버에 메시지가 있는지 문의 요청     function getNextMessage() {         $.post("@Url.Action("GetNextMessage")", function (message) {             $("<li>").text(message).appendTo("#messages");             // 응답받은 즉시 다시 요청             getNextMessage();         });     } </script> }

[코드3] LongPolling - Browser의 javascript 코드


 위 코드에서는 '그림3'과 같이 사용자의 입력을 받는 부분이 있다.


[그림4] LongPolling 테스트 대기 화면


 위 '코드3'의 전체적인 흐름을 파악해 보자

- HTML이 완성되면 getNextMessage()를 호출하여 서버에 요청을 한다.

- Html의 form에서 submit 버튼을 눌렀을 때 페이지 이동이 일어나지 않도록 처리한다.

- getNextMessage() 함수는 서버에 GetNextMessage()를 호출하고 반환 받을 때까지 대기한다.

- 사용자에게 데이터 입력을 받고 제출 버튼을 누르면 ajax의 Post 방식으로 PostMessage 함수를 호출하여 넘겨준다.


  이제 서버측 '코드4'에 대해서 알아 보자


/// <summary>
/// 요청이 오면 임의의 시간 대기 후 응답
/// </summary>
/// <returns></returns>
public async Task<string> GetNextMessage()
{
    return await _nextMessage.Task;
}
 
/// <summary>
/// Lock object
/// </summary>
static object _nextMessageLock = new object();

/// <summary>
/// for LongPolling object
/// </summary>
static TaskCompletionSource<string> _nextMessage = new TaskCompletionSource<string>();
 
public void PostMessage(string messageText)
{
    lock (_nextMessageLock)
    {
        // Concurrent 해결 하기 위해 임시 변수에 옮긴다.
        var oldNextMessage = _nextMessage;
        _nextMessage = new TaskCompletionSource<string>();
        oldNextMessage.SetResult(messageText);
    }
}

[코드4] LongPolling - Server side 코드


 1. GetNextMessage 함수가 호출이 되면 return await _nextMessage.Task 구문에서 리턴값이 있을 때까지 비 동기로 대기 한다.

 2. PostMessage 함수가 호출 될 때 위에서 대기하고 있던 객체인 _nextMessage 객체에 SetResult(msg)에 값을 넘겨주면 1에서 대기하던 객체는 해당 값을 반환하도록 해주며 다시 대기하도록 한다. 이때 Lock를 통해 쓰레드 안정성을 확보하도록 하였다.

 3. TaskCompletionSource<string> 객체는 입력값이 string이고 출력 값이 string인 객체로 선언되었으며 비 동기로 동작할 수 있도록 .Net Framework 4에서 부터 제공하는 클래스다.

 4. public async Task<string> GetMessage()는 비 동기로 수행된다고 알려주는 C# 5.0 예약어다. 이 함수 안에는 반드시 await 예약어를 사용하여 비 동기로 사용하는 구문이 있어야 한다. - 이 부분은 node.js의 특징인 비 동기 방식을 .Net에서 지원하는 것이라 이해해도 되겠다.


 이제 LongPolling에 대해 전체적인 흐름을 이해했으리라 생각이 든다. 지금까지 살펴보았다면 꼭 실습으로 한 번씩 테스트를 해 보기를 바라며 정 여건이 되지 않는다면 마지막 편에 제공되는 전체 소스파일을 다운바다 실행해 보기 바란다.


 마지막으로 결과 화면으로 확인해 보자 아래 '그림5'를 통해 확인 할 수 있다.




[그림5] LongPolling 결과 화면


위 화면에서 제출을 누르면 “5.Step #5" 밑에 "6. Step #6"이 추가 됨을 확인 할 수 있을 것이다.


소스 코드 자체에 주석과 직관적인 코딩으로 충분히 파악이 가능할 것으로 예상하므로 별도의 설명을 생략하도록 하겠습니다. 포스트의 내용이 장황한 설명 보다는 주석과 소스코드 자체 만으로도 이해할 수 있도록 하기 위해 노력하였습니다. 실 개발에서도 적용할 수 있도록 간단하면서도 현실적인 예제 프로그램을 통해 각 소스를 만들고 이해 시키고자 하였으며 실무에 필요한 개발요구 사항들을 해결 하는데 도움이 되고자 노력하였습니다. 그리고 소스와 같이 있는 주석을 이용해 nDoc이나 별도의 자동 Document 제작 유틸로 API 문서를 만드는 데에도 도움이 되었으면 한다. 
※ DOC에 대한 프로그램 정보 Util link

ing™       




빈꿈 EMPTYDREAM - 웹툰으로 알리는 IT


참조 URL
  1. http://emptydream.tistory.com/






[그림1] 웹툰으로 IT를 알리는 만화 화면










Real time Apps #2 - Polling


참조 URL
  1. http://reallifejs.com/brainchunks/repeated-events-timeout-or-interval/ - setTimeout vs setInterval
  2. http://en.wikipedia.org/wiki/Comet_(programming) - COMET programming
  3. http://blog.falafel.com/blogs/basem-emara/2012/06/06/polling-ajax-requests-in-javascript

  

목차
  1. Polling - 있어?
    [ASP.NET MVC] - Real time Apps - Polling
  2. LongPolling - 있으면 보내줘!
    [ASP.NET MVC] - Real time Apps - LongPolling
  3. SSE ( Server Send Events ) - 있으면 보내줘 기다릴께~ 
    [ASP.NET MVC] - Real time Apps - SSE ( Serve Sent Events )
  4. WebSocket - 어! 왔네~
    [ASP.NET MVC] - Real time Apps - WebSocket
  5. SignalR - over WebSocket ( MS Platform )
    [ASP.NET MVC] - Real time Apps - SignalR over WebSocket


 이 포스트에 있는 내용이 언제나 확실한 정답은 아닙니다. 진실이라고 생각해 왔던 전제가 시간의 지남에 따라 들어나지 않았던 다른 이면 때문에 좋은 방향으로 이끌어 낼 수 있는 역할로 변환 되는게 역사적으로도 많은 증명 있었습니다. 그렇지만 저는 현재 상황에서 최선의 답을 찾고자 노력하였으며 이 글을 읽는 다른 분들에게 다음 길을 갈 수 있도록 도와주는 디딤돌이 되고자 노력하고자 포스팅을 통해 공유하고자 하는 것입니다. 그리고 프로그래머라는 타이틀을 달고 살아야 한다면 "왜"라는 의문을 항상 가지고 다니면서 자신의 위치에 안주하지 않고 항상 노력하는 모습으로 살아 가고자 합니다. 언제든 지적이나 오류가 있으면 피드백 부탁 드리겠습니다.

ing™       


 Polling에 대해서 알아보기 전에 우선은 Ajax와 인터랙티브 웹 페이지에 대해 간략히 알아 보자. Ajax 통신은 브라우저에서 제공해주는 특별한 객체를 통해(IE - new ActiveXObject("Microsoft.XMLHTTP"), Other - new XMLHttpRequest()) 사용자의 행위에 따라 페이지의 새로 고침 없이 Background에서 서버에서 원하는 데이터를 가져와  페이지의 일부분만을 수정할 수 있는 메커니즘을 말한다. 이런 개발 방식으로 개발된 웹 페이지를 접한 사용자들은 기존의 페이지에서는 느낄 수 없었던 사용자 경험을 얻을 수 있었다.  이 후 수많은 사이트에서 이 개발 방식으로 웹 페이지를 제공하게 되었다. 이런 개발 방식이 조금 더 응용되어 Polling 기법으로 사용자의 행위 없이도 서버에서 변경된 정보를 실시간 - 사용자의 입장에서는 실시간이나 개발자 입장에서는 실시간 지향적 이라 하겠다 - 적으로 업데이트를 할 수 있게 되었다. 간단하게 예를 들면 브라우저에서 서버에게 주기적으로 "데이터가 있어?"라고 물어 보고 서버에서 데이터의 여부에 따라 다르게 대답 하는 것이라 하겠다. 브라우저에서는 받은 데이터로 웹 페이지의 일부분만을 업데이트하여 사용자에게 보여주므로 빠른 응답을 사용자에게 경험하게 할 수 있다. 대표적인 애플리케이션은 웹 채팅이다. 상대방에서 보낸 메시지 여부를 주기적인 Polling으로 알아내어 사용자에게 보여주는 것이다.


Polling의 사전적인 의미를 알아보자. N사이트의 국어사전의 뜻을 보면 다음 표와 같이 풀이하고 있다.


<컴퓨터> 컴퓨터 또는 단말 제어 장치 따위에서 여러 개의 단말 장치에 대하여 순차적으로 송신 요구의 유무를 문의하고요구가 있을 경우에는  단말 장치에 송신을 시작하도록 지령하며없을 에는 다음 단말 장치에 대하여 문의하는 전송 제어 방식. 

[표3] 폴링에 대한 국어사전 풀이


 이 뜻풀이처럼 데이터가 필요한 곳에서 제공자에게 송신을 요구하는 패턴을 Polling 방식이라고 할 수 있겠다. 즉 원하는 곳에서 당겨가는 방식이다. 그렇다면 웹 페이지와 서버 간에는 어떻게 Poll이 이루어지고 있는지를 아래 '그림1'을 통해서 전체적인 흐름을 알아 가 보자.

[그림1] Polling 방식


 웹 페이지에서 Polling을 구현하는 방식은 setTimeout() 함수를 이용해 주기적인 시간 간격으로 서버에 요청하여 원하는 정보를 얻어오도록 하고 있다. 

  1. '그림1'에서와 같이 첫번째 요청처럼 브라우저에서 Ajax로 'Request1'을 요청하면 서버에서는 유효한 데이터가 있는지 조회하고 없으면 개발자가 정의한 형식(여기서는 Empty라고 정의)으로 리턴받고 브라우저 커넥션은 끊어진다.

  2. setTimeOut()함수로 'Request2'요청이 발생할 당시 서버에서 이벤트가 발생하여 유효한 데이타가 있으면 Empty와 대신 개발자가 정의한 형식(여기서는 Message라고 정의)으로 리턴받고 브라우저 커넥션은 끊어진다.

  3. 1단계를 다시 시작하여 서버에서 반영된 유효한 값을 브라우저에 업데이트 한다.

 위와 같은 방식으로 서버의 변경된 데이터를 브라우저에 지속적으로 반영하여 실시간 반응을 지향하는 웹 페이지를 만들었다. 


 이제 예제를 통해서 실제적인 코드로 살펴 볼 것이다. ( 실행해 볼 수 있는 소스코드를 마지막 포스트에서 첨부할 것 이니 다운받아 확인할 수 있습니다. ) 

<!-- Polling 하여 받은 데이터를 반영할 수 있는 DOM -->
<ol id="messages"></ol>

@section scripts{ <script type="text/javascript">     $(function () {         // Begin the Polling loop         getNextMessage();     });     function getNextMessage() {         // Http post method request

//@Url.Action("GetNextMessage") -> /현재 페이지/GetNextMessage로 치환된다         $.post("@Url.Action("GetNextMessage")", function (message) {             $("<li>").text(message).appendTo("#messages");         });         // Http get method request         //$.get("@Url.Action("GetNextMessage")", function (message) {         //    $("<li>").text(message).appendTo("#messagees");         //});         setTimeout(getNextMessage, 1000);     } </script> }

[코드1] Polling - Browser의 HTML과 javascript 코드

( ASP.NET MVC4의 Razor 문법으로 작성된 코드다. )


 위 코드는 페이지가 로딩이 되면 getNextMessage() 함수를 호출하여 서버에 데이터를 요청하고 <ol> 노드에 <li> 노드를 추가하는 코드다. ( 서버 요청을 HttpPost 또는 HttpGet으로 할 수 있다 ) 그리고 setTimeout를 통해 1초후에 다시 getNextMessage()를 호출하도록 되어 있다. 별도의 문제나 행위가 발생하지 않는 한 무한 호출이 되는 단순한 구조로 구성 되어 있다. 이제 아래 코드를 통해 서버쪽의 코드를 알아 보자.

 

/// <summary>
/// 요청이 오면 즉시 응답
/// </summary>
/// <returns></returns>
public string GetNextMessage()
{
    int waitingCount = 0;
    var now = DateTime.Now;
    return "Response at " + now.ToString() + "." + now.Millisecond + " 서버 대기 시간 : " + waitingCount + "ms";
}

[코드2] Polling - Server side 코드

( 서버 사이트 코드는 ASP.NET MVC4 기반에서 작성이 되었다. )


 위 코드는 따로 설명을 할 필요도 없을 정도로 간단하여 짧게 설명을 하도록 하겠다. GetNextMessage()함수는 호출이 되면 현재 시간을 알아내 string으로 반환하도록 되었다. 이제 위 결과 화면을 아래 그림을 통해 확인해 보자.


[그림2] Realtime Apps - Polling 실행 결과 화면

( 위 화면은 Visual studio에서 ASP.NET MVC4 템플릿에서 기본 제공되었다.)



  '그림2'의 결과 화면을 보면 1초마다 호출된 결과를 화면에 뿌려주는 것을 확인할 수 있다. 이제 코드와 결과 화면까지 확인을 하였다. 이제 Polling이 어떤 방식으로 구성되고 개발되는지 대략적으로 알 수 있을 것이라고 기대한다. 위 예제는 MS 진영에서 개발 및 테스트를 할 수 있지만 Java나 PHP, 기타 Ruby와 같은 곳에서도 비슷한 방식으로 구현이 될 것이므로 이해 하는 데에 크게 무리가 없을 것이라 생각한다.


Tip!

 Request가 지속적으로 일어 날 때마다 서버에서는 유효한 사용자의 요청인지를 알아내기 위해 내부적으로 HTTP Handshanking이 지속적으로 일어나기 때문에 오버헤드가 발생한다. 그래서 예측할 수 없는 웹 서비스를 제공하는 서버에서는 성능에 대한 고려를 충분히 해야 한다.


소스 코드 자체에 주석과 직관적인 코딩으로 충분히 파악이 가능할 것으로 예상하므로 별도의 설명을 생략하도록 하겠습니다. 포스트의 내용이 장황한 설명 보다는 주석과 소스코드 자체 만으로도 이해할 수 있도록 하기 위해 노력하였습니다. 실 개발에서도 적용할 수 있도록 간단하면서도 현실적인 예제 프로그램을 통해 각 소스를 만들고 이해 시키고자 하였으며 실무에 필요한 개발요구 사항들을 해결 하는데 도움이 되고자 노력하였습니다. 그리고 소스와 같이 있는 주석을 이용해 nDoc이나 별도의 자동 Document 제작 유틸로 API 문서를 만드는 데에도 도움이 되었으면 한다. 
※ DOC에 대한 프로그램 정보 Util link

ing™       



Real time Apps #1
Polling, LongPolling, Server Sent Events, Websocket, SignalR


참조 URL
  1. http://en.wikipedia.org/wiki/Comet_(programming) - 위키피디아

 실시간 인터랙티브 웹 페이지(또는 앱, 이하 웹 페이지로 통일)에 대해서 익히 들어 봤을 것이다. 사용자의 행동(클릭, 스크롤,...)으로 웹 브라우저에서 서버의 변경된 데이터를 사용자에게 보여 줄 수 있는 웹 페이지 말이다. 사용자의 발전되는 경험으로 인해 오래전부터 인터랙티브형 웹 페이지에 대해 요구되고 있었으며, Ajax 방법론이 대두 되면서 사용자가 만족할 만한 인터랙티브 웹 페이지를 만들 수 있었다. 그렇지만 앞으로의 개발 방향이 기존의 레거시 시스템을 웹을 지원하는 방향으로 흘러가고 있으며 Active-X, Flash, Silverlight를 제외 하고 표준 HTML 과 CSS, Javascript 만으로 C/S 프로그램이 하던 일을 대체해야 한다는 시대적 흐름이 형성 되었다. 그리고 시대적으로 새로운 디바이스(이기종 스마트폰, 이기종 타블렛, Other...)가 출시되었으며 새로운 규격의 브라우저에서도 호환되게 개발해야 한다. 개발자는 이러한 여러 가지 제약 사항을 이겨내고 만족 스러운 인터랙티브형 웹페이지를 구현하기란 쉽지 않다. 

 그렇지만 개발자들은 고객의 요구 사항을 최대한 만족 시키기 위해 부단히 노력하여 여러 가지 시도로 인터랙티브형 웹 페이지가 되도록 노력하였다. 그래서 Polling, LongPolling등과 같은 방법으로 인터랙티브형 웹 페이지가 되도록 개발하게 되었다. 하지만 처음 설계될 당시의 HTTP 프로토콜과 HTML의 한계성을 가지고 있기 때문에 개발자는 뒤에서 컨트롤하고 사용자에게는 감추는 역할을 더 많이 신경 쓰게 된 것이다. 세계의 여러 개발자들이 이런 문제점을 개선하고자 HTML5와 ECMAScript 6(ECMAScript는 표준화된 스크립트 프로그래밍 언어를 말한다. - 위키피디아 click) 표준이 정립이 되고 있으며 Windows, Linux 같은 또 다른 하나의 개발 플랫폼으로 HTML이 진화를 하고 있다.


 HTML5에 대해서 좀더 이야기를 하고 싶으나 주제에 벗어나므로 간단히 정리하고자 한다. HTML5를 짧게 수식 같이 정리하면 아래 '표1'과 같을 것이다.


HTML5 = Javascript + CSS + Templates 

[표1] HTML5 정의 표

 (이것은 개인적인 정의일 뿐 W3C 공식적인 정리는 아님을 알려 드린다.)


 Javascript와 CSS에 대해서는 대부분 알 고 있을 것이라 생각하고 Template에 대해서만 더 설명을 더 하겠다.


 Javascript 

 사용자의 행위에 대해서 처리

 CSS 

 HTML의 레이아웃 및 디자인

 Template

 HTML Tag의 유동적인 데이터를 템플릿 엔진을 통해 DOM(Document  Object Model) 관리가 되도록 한다. Template engine은 JsRender(구 jquery-template), HandleBars와 같이 여러 라이브러리를 통해 얻을 수 있으며 HTML의 대부분 작업을 담당한다.


 간단하게나마 HTML5에 대해서 마무리를 하고 이제 본론으로 돌아와 인터랙티브 웹 페이지를 가능 토록하는 방법 중에 서버와의 통신으로 데이터를 가져오는 기법이란 주제로 좁혀 다루고자 한다. 아래 목차대로 하나씩 짚어 나가면서 진행해 보도록 하겠다.


목차
  1. Polling - 있어? : [ASP.NET MVC] - Real time Apps - Polling
  2. LongPolling - 있으면 보내줘! : [ASP.NET MVC] - Real time Apps - LongPolling
  3. SSE ( Server Sent Events ) - 있으면 보내줘 기다릴게~ [ASP.NET MVC] - Real time Apps - SSE ( Serve Sent Events )
  4. WebSocket - 어! 왔네~ : [ASP.NET MVC] - Real time Apps - WebSocket
  5. SignalR - over WebSocket ( MS Platform ) : [ASP.NET MVC] - Real time Apps - SignalR over WebSocket



 본격적으로 살펴보기에 앞서서 아래 '표1'과 같이 데이터 통신에 관한 기술 정리를 간단하게나마 해 보았으니 참조만 하자.


기술 규격

기술 명칭

COMET

 Polling

 LongPolling

 Hidden iframe

 XMLHttpRequest

 XMLHttpRequest long polling

 Script tag long polling

HTML 5

 SSE(Server Sent Events - Streamming) - Not Socket

 WebSocket - HTML5

 SignalR - hybrid

 Socket.IO - hybrid

※ hybrid : 하위 브라우저 호환을 지원하는 기능으로 WebSocket를 지원하지 않는 브라우저에서는 다른 하위 통신 방식으로 데이터 요청을 지원해준다.

[표2] 통신 방식


'Music' 카테고리의 다른 글

Sara Bareilles - Brave  (0) 2014.02.06
10월의 어느 멋진 날에  (0) 2013.08.17
잊혀진 계절  (0) 2013.08.16
Joe Hisaishi in Budokan - Studio Ghibli 25 Years Concert  (0) 2013.08.14
18- (5) Porco Rosso - Joe Hisaishi (Music Box Collection)  (0) 2013.08.14






'Music' 카테고리의 다른 글

Sara Bareilles - Brave  (0) 2014.02.06
아름다운 사람 - 서유석  (0) 2013.08.17
잊혀진 계절  (0) 2013.08.16
Joe Hisaishi in Budokan - Studio Ghibli 25 Years Concert  (0) 2013.08.14
18- (5) Porco Rosso - Joe Hisaishi (Music Box Collection)  (0) 2013.08.14

+ Recent posts