Web Programming/ASP .Net Core 3

SignalR

안녕하세요 씨앤텍 시스템즈 최홍준 연구원입니다.

이번 포스트는 SignalR 입니다.

SignalR은 웹 개발 진행 시 실시간 처리가 필요할 경우 사용하는 라이브러리 입니다.

SignalR을 내용을 알기 전 선행 지식이 필요합니다.


1. TCP/IP Socket

2. WebSocekt


TCP/IP, WebSocket에 관련하여 간단하게 정리 후
SignalR에 대해 소개하겠습니다.


[ Socket ]

Socket이란 네트워크상에서 동작하는 프로그램 간 통신의 종착점(EndPoint)입니다.

프로그램이 네트워크에서 데이터를 통신할 수 있도록 연결해주는 연결부라고 할 수 있습니다.

EndPoint : IP Address + Port 번호의 조합을 뜻함, 최종 목적지는 사용자의 디바이스 혹은 Server

[ TCP/IP Socket ]

TCP/IP Socket은 인터넷 프로토콜인 IP, 전송 프로토콜인 TCP로 구성되어 있습니다.

TCP는 IP 위에서 동작하는 프로토콜로, 데이터 전달을 보증하고 보낸 순서대로 받습니다.

TCP/IP는 표준 프로토콜로, 인터넷에서 데이터를 주고 받는데 필요한 일련의 프로토콜 모음

가장 대표적인 HTTP, FTP, SMTP 등등 TCP 기반으로 한 많은 Application 프로토콜들이 IP 위에서 동작하기 때문에

TCP/IP로 부릅니다.

그림1. TCP/IP Layer

이러한 통신규약을 이용하여 프로그램이 네트워크 간 데이터 주고 받을 때 사용할 경우 TCP/IP Socket을 이용합니다.

여기서 서로 Connection, Close 할 경우 규칙에 따라 통신을 하게 되는데

Connection할 경우 3-way-handshake, Close할 경우 4-way-handshake 입니다.

 

3-way-handshake는 다음 사진과 같이 동작하게 됩니다.

그림2. 3-way-handshake


[STEP 1]

클라이언트는 서버에 접속을 요청하는 SYN 패킷을 요청,

이때 클라이언트는 SYN 패킷을 보내고, SYN/ACK 응답을 기다리는 SYN_SENT 상태

서버는 Wait For Client 상태입니다.

 

[STEP 2]

서버는 SYN 요청을 받고 A클라이언트에게 요청을 수락한다는 ACK, SYN flag가 설정된 패킷을 발송

클라이언트가 다시 ACK 패킷으로 응답하기를 기다림

이때 서버는 SYN_RECEIVED 상태입니다.

 

[STEP 3]

클라이언트는 서버에게 ACK를 보내고 이후로부터 연결이 이루어지고

서버와 연결되어 데이터 전송이 시작됩니다.

이때의 서버 상태는 ESTABLISHED 입니다.


 

4-way-handshake는 다음 사진과 같이 동작하게 됩니다.

 

그림3. 4-way-handshake


[STEP 1]

클라이언트는 서버에게 연결을 종료하겠다는 FIN 패킷을 전송

 

[STEP 2]

서버는 일단 확인 메시지를 보내고 자신의 통신이 끝날 때까지 기다리는 상태로 변환

이때의 Server 상태가 TIME_WAIT 입니다.

 

[STEP 3]

서버는 연결이 종료되었다고 클라이언트에게 FIN 패킷을 전송

 

[STEP 4]

클라이언트는 확인했다는 ACK 패킷을 전송


TIME_WAIT : Client는 Server로부터 FIN 수신 하더라도 일정 시간 동안 세션을 남겨놓고
잉여 패킷을 기다리는
과정

[ WebSocket Socket ]

WebSocket은 하나의 TCP 접속에 전이중 통신 채널을 제공하는 컴퓨터 통신 프로토콜입니다.

HTTP Polling과 같은 반이중 방식에 비해 더 낮은 부하를 사용하여 웹 브라우저와 웹 서버 간의 통신을 가능하며
서버와의 실시간 데이터 전송을 쉽게 할 수 있습니다.

Polling : 하나의 장치(또는 프로그램)가 충돌 회피 또는 동기화 처리 등을 목적으로 다른 장치(또는 프로그램)의 상태를 주기적으로 검사하여 일정한 조건을 만족할 때 송수신 등의 자료처리를 하는 방식

그림4. WebSocket 통신 프로세스

WebSocket 통신 시 Client가 Server에게 연경 요청에는 Connection:Upgrade / Upgrade:Websocket

헤더를 통해 웹소켓 요청임을 표시합니다.

해당 요청이 끝나면 Server 쪽에서 응답 상태 코드인 101을 전달받게 됩니다.

HTTP 101 : 101코드는 Switching Protocols로 Server가 Client가 요청한 것에 따라 서버 프로토콜을
바꾼다는 것을 알려주는 응답 코드

이 과정이 끝난 후 Client는 Server와 통신하고 데이터를 주고받을 수 있습니다.


[ SignalR ]

ASP .NET Core SignalR은 응용 프로그램에 실시간 웹 기능 추가를 간소화 하는 오픈소스 라이브러리입니다.

실시간 웹 기능을 사용 하면 서버측 코드에서 클라이언트에 콘텐츠를 즉시 푸시 할 수 있습니다.

 

SignalR 사용하기 적합한 콘텐츠들은 다음과 같습니다.


1. 게임, 소셜 네트워크, 투표, 경매, 지도 및 GPS 앱

2. 대시보드 및 모니터링 앱

3. 공동 작업 앱


Microsoft에서 명시한 SignalR의 기능은 다음과 같습니다.


1. 연결 관리를 자동으로 처리

2. 모든 연결 된 클라이언트에 동시에 메시지 전송 ( Ex. 대화방 )

3. 특정 클라이언트나 클라이언트 그룹으로 메시지를 전송

4. 늘어난 트래픽을 처리 하도록 크기를 조정


그림5. SignalR Transport Method

SignalR 사용시 서버와 클라이언트의 성능에 따른 범위 안에서 가장 최선의 전송방식을 자동으로 선택합니다.

 

그림6. SignalR 통신 방법

Server에선 Hub, Client에선 Hub Proxy로 연결되어 서로 통신하게 됩니다.

 

Server의 Hub의 역활은 서버코드에서 클라이언트에 의해 호출 되는 메서드나

연결 된 클라이언트의 메서드를 호출 하는 메서들 정의하는 역할입니다.

 

간단한 Chatting 페이지를 구현하면서 SignalR에 대해서 더 자세히 설명 드리겠습니다.

 


[ Chatting App ]

SignalR을 이용한 가장 기본적인 예제인 Chatting을 구현하겠습니다.

해당 내용은 Microsoft 공식 홈페이지에 있는 내용을 기반으로 작성했습니다.

 

[STEP 1] 새 프로젝트 만들기

그림 7. Visual Studio 2019 새프로젝트 만들기 - 1
그림 8. Visual Studio 2019 새프로젝트 만들기 - 2
그림 9. Visual Studio 2019 새프로젝트 만들기 - 3
그림10. Visual Studio 2019 새프로젝트 만들기 - 4
그림11. Visual Studio 2019 새프로젝트 만들기 - 5

[STEP 2] SignalR 패키지 추가

그림12. SignalR 패키지 추가 - 1
그림13. SignalR 패키지 추가 - 2
그림14. SignalR 패키지 추가 - 3

[STEP 3] Startup.cs SignalR 설정

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            services.AddSignalR(); // 이부분 추가
        }

[STEP 4] Startup.cs endpoint SignalR 경로 설정

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
                endpoints.MapHub<ChattingHub>("/hubs");
            });

[STEP 5] SignalR Hub 구성

그림15. SignalR Hub 구성 - 1

 

그림16. SignalR Hub 구성 - 2
그림17. SignalR Hub 구성 - 3
그림18. SignalR Hub 구성 - 4

using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Chatting.Hubs
{
    public class ChattingHub : Hub
    {
    }
}

[STEP 6] SignalR startup.cs signalR Map 경로 설정

그림19. SignalR startup.cs Hub 구성 - 1

[STEP 7] Hub Method 설정

        [HubMethodName("Send")]
        public async Task SendMessage(string id, string message)
        {
            await Clients.All.SendAsync("Received", id, message);
        }

[STEP 8] Client SignalR 설정

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center" style="margin-top: 10px;margin-left: 30px;">
    ID : <input type="text" id="id" />
</div>
<div class="text-center" style="margin-top: 10px;margin-left: 13px;">
    내용 : <input type="text" id="message" />
</div>
<div class="text-center" style="margin-top: 10px;margin-left: 13px;">
    <button id="submit">전송</button>
</div>
<div class="row">
    <div class="col-12">
        <hr />
    </div>
</div>
<div class="row">
    <div class="col-6">
        <ul id="messagesList"></ul>
    </div>
</div>

<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/microsoft/signalr/dist/browser/signalr.js"></script>

<script type="text/javascript">
    $(function () {
        var connection = new signalR.HubConnectionBuilder().withUrl("/hubs").build(); // SignalR 허브에 연결

	    // Server Method 호출
        connection.start().then(function () {
            $("#submit").click(function () {
                connection.invoke("Send", $("#id").val(), $("#message").val());
            });
        });
        
        // Server단에서 Client Method 호출
        connection.on("Received", function (user, message) {
            var msg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
            var encodedMsg = user + " : " + msg;
            var li = document.createElement("li");
            li.textContent = encodedMsg;
            document.getElementById("messagesList").appendChild(li);
        });
    });
</script>

[STEP 9] 실행 후 테스트

그림20. SignalR Test


이번 포스트는 MS에서 개발한 SignalR에 대해서 설명드렸습니다.

더 자세한 내용이 궁금하시다면

https://docs.microsoft.com/ko-kr/aspnet/core/signalr/introduction?view=aspnetcore-5.0

 

ASP.NET Core SignalR 소개

ASP.NET Core SignalR 라이브러리가 앱에 실시간 기능 추가를 간소화 하는 방법을 알아봅니다.

docs.microsoft.com

MS 공식 홈페이지를 참조하시면 감사드리겠습니다.

감사합니다.

728x90