ASP.NET SignalR 2.0: 자습서: SignalR 자체-호스트(Self-Host)

등록일시: 2014-01-13 08:00,  수정일시: 2014-01-17 09:42
조회수: 7,272
이 문서는 ASP.NET SignalR 기술을 널리 알리고자 하는 개인적인 취지로 제공되는 번역문서입니다. 이 문서에 대한 모든 저작권은 마이크로소프트에 있으며 요청이 있을 경우 언제라도 게시가 중단될 수 있습니다. 번역 내용에 오역이 존재할 수 있고 주석은 번역자 개인의 의견일 뿐이며 마이크로소프트는 이에 관한 어떠한 보장도 하지 않습니다. 번역이 완료된 이후에도 대상 제품 및 기술이 개선되거나 변경됨에 따라 원문의 내용도 변경되거나 보완되었을 수 있으므로 주의하시기 바랍니다.

본문에서는 자체-호스트 방식으로 SignalR 2.0 서버를 구현하는 방법과, 자바스크립트 클라이언트를 이용해서 서버에 연결하는 방법을 살펴봅니다.

개요

대부분 SignalR 서버는 IIS에서 실행되는 ASP.NET 응용 프로그램에서 호스트 되는 경우가 많습니다. 그러나, 자체-호스트(Self-Host) 라이브러리를 사용해서 자체-호스트 할 수도 (가령, 전용 콘솔 응용 프로그램이나 Windows 서비스 등에서 호스트 할 수도) 있습니다. 이 라이브러리는, SignalR 2.0에서도 그렇듯이, OWIN(Open Web Interface for .NET)에 내장되어 있습니다. OWIN은 .NET 웹 서버와 웹 응용 프로그램 간의 추상적 개념들을 정의하고 있습니다. OWIN은 웹 응용 프로그램을 서버와 분리시켜주기 때문에, IIS 대신 여러분이 원하는 별도의 프로세스에서 웹 응용 프로그램을 자체-호스트하고자 할 때 안성맞춤입니다.

웹 응용 프로그램을 IIS에서 호스팅하지 않는 경우, 그 이유는 다음과 같습니다:

  • 기존 서버 팜에서 IIS를 지원하지 않는 등, IIS를 사용할 수 없거나 IIS가 권장되지 않는 환경인 경우
  • IIS 자체의 성능 부하까지도 피해야 할 필요가 있을 때
  • Windows 서비스나 Azure 작업자 역할, 또는 기타 프로세스에서 실행되는 기존 응용 프로그램에 SignalR 기능을 추가할 때

다만, 성능을 이유로 솔루션을 자체-호스트 방식으로 개발하고 있다면, 응용 프로그램을 IIS에 호스트한 상태에서도 테스트를 수행해서 성능 상의 이점을 직접 확인해보는 것이 좋습니다.

본 자습서는 다음과 같은 두 가지 절로 구성되어 있습니다:

서버 구현하기

본 자습서에서는 콘솔 응용 프로그램으로 호스트 서버를 구현해 볼 것입니다. 그러나, Windows 서비스나 Azure 작업자 역할을 비롯한 어떤 종류의 프로세스에도 서버를 호스트 할 수 있습니다.

  1. 먼저, 관리자 권한으로 Visual Studio 2013을 실행한 다음, 파일(File) 메뉴 등에서 새 프로젝트(New Project) 대화 상자를 엽니다. 그리고, 템플릿(Templates) 패인에서 Visual C# 하위의 Windows 노드를 선택하고 콘솔 응용 프로그램(Console Application) 템플릿을 선택합니다. 새 프로젝트의 이름을 "SignalRSelfHost"로 지정하고 확인(OK) 버튼을 클릭합니다.

  2. 도구(Tools), 라이브러리 패키지 관리자(Library Package Manager), 패키지 관리자 콘솔(Package Manager Console) 메뉴를 차례대로 선택해서 패키지 관리자 콘솔을 엽니다.

  3. 패키지 관리자 콘솔에서 다음 명령을 입력합니다:

    Install-Package Microsoft.AspNet.SignalR.SelfHost

    이 명령은 프로젝트에 SignalR 2.0 자체-호스트(SignalR 2.0 Self-Host) 라이브러리를 추가해줍니다.

  4. 다시, 패키지 관리자 콘솔에서 다음 명령을 입력합니다:

    Install-Package Microsoft.Owin.Cors

    이 명령은 프로젝트에 Microsoft.Owin.Cors 라이브러리를 추가해줍니다. 이 라이브러리는 SignalR을 호스트하는 응용 프로그램과 클라이언트 웹 페이지의 도메인이 서로 다른, 크로스-도메인을 지원하기 위한 용도로 사용됩니다. 본문에서 살펴볼 자체-호스트 SignalR 서버와 웹 클라이언트는 서로 다른 포트에서 호스트 될 것이므로, 이 구성 요소들 간에 통신이 가능하려면 크로스-도메인이 활성화돼야만 합니다.

  5. Program.cs의 내용을 다음 코드로 변경합니다.

    using System;
    using Microsoft.AspNet.SignalR;
    using Microsoft.Owin.Hosting;
    using Owin;
    using Microsoft.Owin.Cors;
    
    namespace SignalRSelfHost
    {
        class Program
        {
            static void Main(string[] args)
            {
                // This will *ONLY* bind to localhost, if you want to bind to all addresses
                // use http://*:8080 to bind to all addresses. 
                // See http://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx 
                // for more information.
                string url = "http://localhost:8080";
                using (WebApp.Start<Startup>(url))
                {
                    Console.WriteLine("Server running on {0}", url);
                    Console.ReadLine();
                }
            }
        }
    
        class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                app.UseCors(CorsOptions.AllowAll);
                app.MapSignalR();
            }
        }
    
        public class MyHub : Hub
        {
            public void Send(string name, string message)
            {
                Clients.All.addMessage(name, message);
            }
        }
    }

    이 코드에는 세 개의 클래스가 정의되어 있습니다:

    • Program 클래스에는 기본 실행 경로를 지정하는 Main 메서드가 구현되어 있습니다. 이 코드에서는 Startup 형식의 웹 응용 프로그램을 특정 URL(http://localhost:8080)에서 시작하고 있습니다. 만약, 종점에 보안을 적용해야 한다면 SSL을 구현할 수도 있습니다. 이에 대한 더 자세한 정보는 How to: Configure a Port with an SSL Certificate 문서를 참고하시기 바랍니다.

    • Startup 클래스에는 SignalR 서버에 대한 구성과 (이 코드에서 수행되고 있는 구성은 오직 UseCors 메서드 호출뿐입니다), 프로젝트 내의 모든 Hub 개체들에 대한 라우트를 생성해주는 MapSignalR 메서드 호출이 구현되어 있습니다.

    • MyHub 클래스는 응용 프로그램이 클라이언트에게 제공할 SignalR 허브 클래스입니다. 이 클래스에는 클라이언트가 모든 다른 클라이언트들에게 메세지를 브로드캐스트 할 때 호출하기 위한 Send라는 메서드 하나만 존재합니다.

  6. 응용 프로그램을 컴파일하고 실행합니다. 그러면, 서버가 실행되고 있는 주소가 콘솔 창에 나타날 것입니다.

  7. 만약, System.Reflection.TargetInvocationException was unhandled 예외가 발생하고 실행에 실패하면, Visual Studio를 관리자 권한으로 재시작해야 합니다.
  8. 다음 절을 진행하기 위해서 응용 프로그램을 잠시 중지합니다.

자바스크립트 클라이언트로 서버에 접근하기

이번 절에서는 ASP.NET SignalR 2.0: 자습서: SignalR 2.0 시작하기 문서에서 살펴본 것과 동일한 자바스크립트 클라이언트를 사용하게 됩니다. 다만, 딱 한 가지 사항을 변경해보게 될텐데, 바로 허브의 URL을 명시적으로 지정해볼 것입니다. 자체-호스트 응용 프로그램을 사용하는 경우, 클라이언트가 현재 연결된 URL과 (역방향 프록시나 로드 밸런서에 의해서 연결된 URL과) 서버의 URL이 반드시 동일한 주소를 가르킨다고 확신할 수는 없기 때문에, 명시적으로 URL을 지정해줄 필요가 있습니다.

  1. 다시, 솔루션 탐색기에서 마우스 오른쪽 버튼으로 솔루션을 클릭하고 추가(Add), 새 프로젝트(New Project)를 차례대로 선택합니다. 웹(Web) 노드를 선택한 다음, ASP.NET 웹 응용 프로그램(ASP.NET Web Application) 템플릿을 선택합니다. 이번에는 프로젝트 이름을 "JavascriptClient"로 지정하고 확인(OK) 버튼을 클릭합니다.

  2. 새 ASP.NET 프로젝트(New ASP.NET Project) 대화 상자가 나타나면 Empty 템플릿을 선택하고 다른 옵션들은 선택하지 않은 상태로 남겨둡니다. 확인(OK) 버튼을 클릭합니다.

  3. 패키지 관리자 콘솔에서 기본 프로젝트(Default project) 드롭-다운을 "JavascriptClient" 프로젝트로 지정하고 다음 명령을 실행합니다:

    Install-Package Microsoft.AspNet.SignalR.JS

    이 명령은 클라이언트에 필요한 SignalR과 JQuery 라이브러리들을 설치해줍니다.

  4. 마우스 오른쪽 버튼으로 JavascriptClient 프로젝트를 클릭한 다음, 추가(Add), 새 항목(New Item) 메뉴를 차례대로 선택합니다. 그리고, 웹(Web) 노드에서 HTML 페이지(HTML Page)를 선택하고 이름을 Default.html로 지정합니다.

  5. 방금 생성한 HTML 페이지의 내용을 다음 코드로 변경합니다. 이 코드의 스크립트 참조와 프로젝트의 Scripts 폴더에 추가된 실제 파일들 간의 버전이 일치하는지 반드시 확인하시기 바랍니다.

    <!DOCTYPE html>
    <html>
    <head>
        <title>SignalR Simple Chat</title>
        <style type="text/css">
            .container {
                background-color: #99CCFF;
                border: thick solid #808080;
                padding: 20px;
                margin: 20px;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <input type="text" id="message" />
            <input type="button" id="sendmessage" value="Send" />
            <input type="hidden" id="displayname" />
            <ul id="discussion"></ul>
        </div>
        <!--Script references. -->
        <!--Reference the jQuery library. -->
        <script src="Scripts/jquery-1.6.4.min.js"></script>
        <!--Reference the SignalR library. -->
        <script src="Scripts/jquery.signalR-2.0.0.min.js"></script>
        <!--Reference the autogenerated SignalR hub script. -->
        <script src="http://localhost:8080/signalr/hubs"></script>
        <!--Add script to update the page and send messages.-->
        <script type="text/javascript">
            $(function () {
                //Set the hubs URL for the connection
                $.connection.hub.url = "http://localhost:8080/signalr";
                
                // Declare a proxy to reference the hub.
                var chat = $.connection.myHub;
                
                // Create a function that the hub can call to broadcast messages.
                chat.client.addMessage = function (name, message) {
                    // Html encode display name and message.
                    var encodedName = $('<div />').text(name).html();
                    var encodedMsg = $('<div />').text(message).html();
                    // Add the message to the page.
                    $('#discussion').append('<li><strong>' + encodedName
                        + '</strong>:&nbsp;&nbsp;' + encodedMsg + '</li>');
                };
                // Get the user name and store it to prepend to messages.
                $('#displayname').val(prompt('Enter your name:', ''));
                // Set initial focus to message input box.
                $('#message').focus();
                // Start the connection.
                $.connection.hub.start().done(function () {
                    $('#sendmessage').click(function () {
                        // Call the Send method on the hub.
                        chat.server.send($('#displayname').val(), $('#message').val());
                        // Clear text box and reset focus for next comment.
                        $('#message').val('').focus();
                    });
                });
            });
        </script>
    </body>
    </html>

    바로 다음 코드가 (위의 코드에서 강조처리 된 부분) 시작하기 자습서에서 사용된 클라이언트의 코드에는 없던, 본 자습서에서 새로 추가된 새로운 부분입니다. 이 코드는 SignalR 서버에 연결하기 위한 기본 연결 URL을 명시적으로 설정하고 있습니다.

    //Set the hubs URL for the connection
    $.connection.hub.url = "http://localhost:8080/signalr";
  6. 이번에는 마우스 오른쪽 버튼으로 솔루션을 클릭하고 시작 프로젝트 설정...(Set Startup Projects...) 메뉴를 선택합니다. 여러 개의 시작 프로젝트(Multiple startup projects) 라디오 버튼을 클릭한 다음, 두 프로젝트 모두 작업(Action) 항목을 시작(Start)으로 설정합니다.

  7. 다시, "Default.html" 파일을 마우스 오른쪽 버튼으로 클릭하고 시작 페이지로 설정(Set As Start Page) 메뉴를 선택합니다.

  8. 이제 응용 프로그램을 실행하면 서버와 페이지가 동시에 실행될 것입니다. 경우에 따라 서버가 시작되기 전에 웹 페이지가 로드되면, 웹 페이지를 새로 고쳐야 할 수도 있습니다 (또는, 디버거에서 계속(Continue) 버튼을 클릭합니다).

  9. 브라우저에서 프롬프트가 나타나면 사용자 이름을 입력합니다. 그리고, 웹 페이지의 URL을 복사해서 다른 브라우저 탭이나 창에 붙여 넣고 다른 사용자 이름을 입력합니다. 그러면, 지금까지 이전 자습서에서 살펴봤던 것처럼 한 브라우저 패인에서 다른 브라우저들로 메시지가 전송되는 것을 확인할 수 있습니다.