ASP.NET SignalR 2.0: 자습서: SignalR 2.0과 MVC 5 시작하기

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

본문에서는 ASP.NET SignalR 2.0과 MVC 5를 이용해서 실시간 챗 응용 프로그램을 작성하는 방법을 살펴보겠습니다. 먼저, MVC 5 응용 프로그램에 SignalR을 추가한 다음, 메시지를 전송하거나 출력하기 위한 챗 뷰를 작성해볼 것입니다.

개요

본 자습서에서는 ASP.NET SignalR 2.0과 ASP.NET MVC 5를 이용해서 실시간 웹 응용 프로그램을 개발하는 방법을 소개하고자 합니다. 참고로 본문에서는 ASP.NET SignalR 2.0: 자습서: SignalR 2.0 시작하기 문서에서 살펴본 챗 응용 프로그램의 코드와 동일한 코드를 사용하지만, 대신 이번에는 해당 코드를 MVC 5 응용 프로그램에 추가해본다는 점이 다릅니다.

본문에서는 다음과 같은 SignalR 개발 작업들을 수행해볼 것입니다:

  • MVC 5 응용 프로그램에 SignalR 라이브러리를 추가합니다.
  • 콘텐트를 클라이언트에 푸시하기 위한 허브 클래스와 OWIN 시작 클래스를 생성합니다.
  • 웹 페이지에서 SignalR jQuery 라이브러리를 사용해서 메시지를 전송하거나 허브로부터 갱신된 내용들을 가져와서 출력합니다.

다음 화면 이미지는 모든 작업이 완료된 챗 응용 프로그램이 브라우저에서 실행되고 있는 모습을 보여주고 있습니다.

Chat instances

목차:

프로젝트 설정하기

전제조건:

  • Visual Studio 2013. 만약, Visual Studio 2013을 보유하고 있지 않다면, ASP.NET Downloads에서 무료 Visual Studio 2013 Express Development Tool을 다운로드 받을 수 있습니다.

이번 절에서는 ASP.NET MVC 5 응용 프로그램을 생성하고 SignalR 라이브러리를 추가한 다음, 챗 응용 프로그램을 구현하는 방법을 살펴보겠습니다.

  1. 먼저, Visual Studio 2013에서 대상 프레임워크를 .NET Framework 4.5로, 이름을 SignalRChat으로 지정한 C# ASP.NET 응용 프로그램을 만든 다음, 확인(OK) 버튼을 클릭합니다.

    Create web

  2. 새 ASP.NET 프로젝트(New ASP.NET Project) 대화 상자가 나타나면 MVC 템플릿을 선택하고 확인(OK) 버튼을 클릭합니다.

    Create web

  3. 그리고, 도구(Tools) | 라이브러리 패키지 관리자(Library Package Manager) | 패키지 관리자 콘솔(Package Manager Console) 메뉴를 선택해서 콘솔을 열고, 다음 명령을 실행합니다. 그러면, SignalR을 지원하기 위한 스크립트 파일들의 모음과 어셈블리 참조들이 프로젝트에 추가됩니다.

    install-Package Microsoft.AspNet.SignalR
  4. 이제 솔루션 탐색기에서 Scripts 노트를 확장해봅니다. 그러면, 프로젝트에 SignalR을 위한 스크립트 라이브러리들이 추가된 것을 확인할 수 있습니다.

    Scripts folder

  5. 이번에는 마우스 오른쪽 버튼으로 솔루션 탐색기에서 프로젝트를 클릭한 다음, 추가(Add) | 새 폴더(New Folder) 메뉴를 선택해서 Hubs라는 이름으로 새 폴더를 추가합니다.

  6. 다시 마우스 오른쪽 버튼으로 Hubs 폴더를 클릭하고, 추가(Add) | 새 항목(New Item) 메뉴를 선택해서 새 항목 추가(Add New Item) 대화 상자를 띄웁니다. 그런 다음, 설치됨(Installed) 패인에서 Visual C# | 웹(Web) | SignalR 노드를 선택하고, 중앙의 패인에서 SignalR 허브 클래스(v2)(SignalR Hub Class (v2))를 선택해서 ChatHub.cs라는 이름으로 새로운 허브를 생성합니다. 이 클래스는 모든 클라이언트들에게 메세지를 전송하기 위한 SignalR 서버 허브로 사용됩니다.

    Create new hub

  7. 방금 생성한 ChatHub 클래스의 코드를 다음과 같이 변경합니다.

    using System;
    using System.Web;
    using Microsoft.AspNet.SignalR;
    
    namespace SignalRChat
    {
        public class ChatHub : Hub
        {
            public void Send(string name, string message)
            {
                // Call the addNewMessageToPage method to update clients.
                Clients.All.addNewMessageToPage(name, message);
            }
        }
    }
  8. 이번에는 Startup.cs 파일을 엽니다 (이 파일은 이미 MVC 패키지의 일부로 추가되어 있습니다). 그리고, 파일의 내용을 다음과 같이 변경합니다. *

    using Owin;
    using Microsoft.Owin;
    
    [assembly: OwinStartup(typeof(SignalRChat.Startup))]
    namespace SignalRChat
    {
        public partial class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                // Any connection or hub wire up and configuration should go here
                app.MapSignalR();
            }
        }
    }
  9. 계속해서 Controllers/HomeController.cs 파일에 위치한 HomeController 클래스를 열고 클래스에 다음 메서드를 추가합니다. 이 메서드는 잠시 후에 작성할 Chat 뷰를 반환합니다.

    public ActionResult Chat()
    {
        return View();
    }
  10. 마우스 오른쪽 버튼으로 Views/Home 폴더를 클릭한 다음, 추가...(Add...) | 뷰(View) 메뉴를 선택합니다.

  11. 그리고, 뷰 추가(Add View) 대화 상자에서 이 새로운 뷰의 이름을 Chat으로 지정합니다.

    Add a view

  12. Chat.cshtml의 내용을 다음 코드로 변경합니다.

    중요: 패키지 관리자를 이용해서 Visual Studio 프로젝트에 SignalR과 기타 스크립트 라이브러리들을 추가할 때, 아마도 본문에서 설명하는 것보다 최신 버전의 SignalR 스크립트 파일들이 설치될 것입니다. 그러므로, 프로젝트에 실제로 추가된 스크립트 파일들의 버전과 아래 코드에 작성된 스크립트 참조의 버전이 일치하는지 확인하시기 바랍니다.

    @{
        ViewBag.Title = "Chat";
    }
    <h2>Chat</h2>
    <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>
    @section scripts {
        <!--Script references. -->
        <!--The jQuery library is required and is referenced by default in _Layout.cshtml. -->
        <!--Reference the SignalR library. -->
        <script src="~/Scripts/jquery.signalR-2.0.0.min.js"></script>
        <!--Reference the autogenerated SignalR hub script. -->
        <script src="~/signalr/hubs"></script>
        <!--SignalR script to update the chat page and send messages.-->
        <script>
            $(function () {
                // Reference the auto-generated proxy for the hub.  
                var chat = $.connection.chatHub;
                // Create a function that the hub can call back to display messages.
                chat.client.addNewMessageToPage = function (name, message) {
                    // Add the message to the page. 
                    $('#discussion').append('<li><strong>' + htmlEncode(name)
                        + '</strong>: ' + htmlEncode(message) + '</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();
                    });
                });
            });
            // This optional function html-encodes messages for display in the page.
            function htmlEncode(value) {
                var encodedValue = $('<div />').text(value).html();
                return encodedValue;
            }
        </script>
    }
  13. 프로젝트의 변경 사항들을 모두 저장합니다.

* 반드시 Startup 클래스의 선언부에 partial 한정자를 지정해야 합니다. 그렇지 않으면 빌드 오류가 발생합니다. 원문에는 이 키워드가 누락되어 있으므로 참고하시기 바랍니다.

샘플 실행하기

  1. F5를 눌러서 프로젝트를 디버그 모드로 실행합니다.

  2. 브라우저가 실행되어 프로젝트의 기본 페이지가 나타나면 브라우저 주소 창의 기본 페이지 URL 뒤에 /home/chat을 추가합니다. 그러면, Chat 페이지가 브라우저 인스턴스에 로드되고 사용자 이름을 요구하는 프롬프트가 나타날 것입니다.

    Enter user name

  3. 사용자 이름을 입력합니다.

  4. 브라우저 주소 창의 URL을 복사한 다음, 다른 브라우저 인스턴스 두 개를 더 열어서 이 URL를 입력합니다. 그리고, 브라우저의 각 인스턴스마다 중복되지 않는 이름을 입력합니다.

  5. 각각의 브라우저 인스턴스에서 코멘트를 입력하고 Send 버튼을 클릭해봅니다. 그러면, 입력된 코멘트들이 모든 브라우저 인스턴스에 출력될 것입니다.

    노트: 이 간단한 챗 응용 프로그램은 서버 쪽에서 따로 대화 컨텍스트(Discussion Context)를 관리하지 않습니다. 허브는 새로운 코멘트를 모든 현재 사용자들에게 브로드캐스트 합니다. 챗에 참여한 사용자들은 자신이 참여한 이후에 전송된 메시지들을 보게 될 것입니다.

  6. 다음 화면 이미지는 브라우저에서 실행되는 챗 응용 프로그램을 보여주고 있습니다.

    Chat browsers

  7. 응용 프로그램이 실행되는 동안 솔루션 탐색기에서 스크립트 문서(Script Documents) 노드를 살펴보시기 바랍니다. 이 노드는 웹 브라우저로 인터넷 익스플로러를 사용하고, 디버그가 실행 중인 동안에만 볼 수 있습니다. 그러면, hubs라는 이름의 스크립트 파일을 확인할 수 있을 텐데, 이 파일은 런타임에 동적으로 생성되는 SignalR의 라이브러리입니다. 바로 이 파일이 jQuery 스크립트와 서버 측 코드 간의 커뮤니케이션을 관리해주는 허브입니다. 만약, 인터넷 익스플로러가 아닌 다른 브라우저를 사용하고 있다면, 브라우저에 직접 http://mywebsite/signalr/hubs 같이 URL을 입력해서 동적 hubs 파일에 접근할 수도 있습니다.

코드 분석

이 SignalR 챗 응용 프로그램은 두 가지 기본적인 SignalR 개발을 보여주고 있습니다. 즉, 서버 상의 핵심 조정 개체인 허브를 생성하는 방법과, 메시지를 주고 받기 위해서 SignalR jQuery 라이브러리를 사용하는 방법이 바로 그것입니다.

SignalR 허브

이 샘플 코드에서 ChatHub 클래스는 Microsoft.AspNet.SignalR.Hub 클래스를 상속 받고 있습니다. 이런 식으로 SignalR 응용 프로그램을 작성할 때, Hub 클래스를 상속 받으면 매우 유용합니다. Hub 클래스를 상속 받은 허브 클래스에 필요한 public 메서드들을 구현해 놓으면, 웹 페이지에서 jQuery 스크립트를 이용해서 이 메서드들을 호출해서 접근할 수 있습니다.

가령, 이 샘플 챗 응용 프로그램의 코드에서는 클라이언트가 ChatHub.Send 메서드를 호출해서 새로운 메시지를 전송합니다. 그러면, 허브가 Clients.All.addNewMessageToPage를 호출해서 모든 클라이언트들에게 메시지를 전송합니다.

Send 메서드는 허브의 몇 가지 개념들을 보여줍니다:

  • 허브에 public 메서드를 선언해 놓으면 클라이언트에서 이 메서드들을 호출할 수 있습니다.
  • Microsoft.AspNet.SignalR.Hub.Clients 동적 속성을 사용하면 해당 허브에 접속되어 있는 모든 클라이언트에 접근할 수 있습니다.
  • 클라이언트 측의 jQuery 함수(addNewMessageToPage 함수 같은)를 호출해서 클라이언트를 업데이트 합니다.

    public class ChatHub : Hub
    {
        public void Send(string name, string message)
        {
            // Call the addNewMessageToPage method to update clients.
            Clients.All.addNewMessageToPage(name, message);
        }
    }

SignalR과 jQuery

코드 샘플의 Chat.cshtml 뷰 파일은 SignalR jQuery 라이브러리를 사용해서 SignalR 허브와 커뮤니케이션 하는 방법을 보여줍니다. 이 코드가 수행하는 핵심 작업은 허브에 대해 자동으로 생성된 프록시를 참조하는 작업과 서버에서 클라이언트로 콘텐트를 푸시할 때 호출할 수 있는 함수를 선언하는 작업, 그리고 메시지를 허브로 전송하기 위해 연결을 시작하는 작업입니다.

다음은 허브 프록시에 대한 참조를 선언하는 코드입니다.

var chat = $.connection.chatHub; 

노트: 자바스크립트로 서버의 클래스와 그 메서드를 참조할 때는 카멜 표기법을 사용합니다. 즉, 자바스크립트에서는 chatHub를 참조하고 있지만, 이 코드가 실제로 참조하는 C# 클래스는 ChatHub입니다. 만약, jQuery에서도 ChatHub 클래스를 C#처럼 파스칼 표기법으로 참조하고 싶다면 ChatHub.cs 클래스 파일을 수정해야 합니다. 먼저, Microsoft.AspNet.SignalR.Hubs 네임스페이스를 참조하는 using 문을 추가해야 합니다. 그런 다음, [HubName("ChatHub")] 같은 형식으로 ChatHub 클래스에 HubName 어트리뷰트를 추가해줍니다. 마지막으로 ChatHub 클래스에 대한 jQuery 참조를 수정하면 됩니다.

그리고, 다음 코드는 스크립트에서 콜백 함수를 생성하는 방법을 보여주고 있습니다. 서버 상의 허브 클래스는 이 함수를 호출해서 각각의 클라이언트에 갱신된 콘텐트를 푸시할 수 있습니다. 참고로, 이 코드에서 콘텐트를 출력하기 전에 호출되는 htmlEncode 함수는, 필수적인 코드는 아니지만 메세지를 대상으로 HTML 인코드를 수행해서 스크립트 인젝션을 방지하는 간단한 요령을 보여줍니다.

chat.client.addNewMessageToPage = function (name, message) {
    // Add the message to the page. 
    $('#discussion').append('<li><strong>' + htmlEncode(name)
        + '</strong>: ' + htmlEncode(message) + '</li>');
};

다음 코드는 허브 연결을 여는 방법을 보여줍니다. 이 코드는 먼저 연결을 시작한 다음, 이를 HTML 페이지의 Send 버튼의 click 이벤트를 처리하는 함수에 전달합니다.

노트: 이런 방법을 사용하면, 이벤트 처리기가 동작하기 전에 항상 연결이 먼저 이루어져 있는 것을 보장할 수 있습니다.

$.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();
    });
});

이후 과정 안내

본문에서는 실시간 웹 응용 프로그램을 구축하기 위한 SignalR 프레임워크에 대해서 살펴봤습니다. ASP.NET 응용 프로그램에 SignalR을 추가하는 방법과 허브 클래스를 추가하는 방법, 그리고 허브를 이용해서 메시지를 전송하고 수신하는 방법 등 몇 가지 SignalR 개발 작업들을 살펴봤습니다.

본 자습서의 예제 응용 프로그램이나 다른 SignalR 응용 프로그램들을 호스팅 공급자에 배포해서 인터넷 상에서 사용할 수도 있습니다. 마이크로소프트는 최대 10개까지 웹 사이트를 무료로 호스팅 할 수 있는 Windows Azure trial account를 제공해주고 있습니다. 예제 SignalR 응용 프로그램을 배포하는 과정은 Publish the SignalR Getting Started Sample as a Windows Azure Web Site 포스트를 참고하시기 바랍니다. 그리고, Visual Studio 웹 프로젝트를 Windows Azure 웹 사이트에 배포하는 방법에 대한 더 자세한 정보는 Deploying an ASP.NET Application to a Windows Azure Web Site를 참고하시기 바랍니다.

노트: 현재 Windows Azure 웹 사이트에서는 WebSocket 전송방식이 지원되지 않습니다. WebSocket 전송방식을 사용할 수 없는 경우, SignalR은 ASP.NET SignalR 2.0: SignalR 소개 문서의 전송방식들(Transports)과 그 대안(Fallbacks) 절에서 설명한 것처럼 사용 가능한 다른 전송방식들을 사용하게 됩니다. *

더 고급의 SignalR 개발 개념들을 살펴보고 싶다면, SignalR 소스 코드와 리소스들이 제공되는 다음 사이트들을 방문해보시기 바랍니다:

* 이제 Windows Azure 웹 사이트에서도 .NET 프레임워크 버전이 4.5로 설정되어 있고, 사이트 구성 페이지의 웹 소켓 항목이 활성화되어 있으면 WebSocket을 사용할 수 있습니다