카테고리

분류 전체보기 (510)
문학 (128)
찬양 콘티(Continuity) (80)
Business as heritage (6)
IT . Web (149)
Photo (127)
etc. (20)
Total348,470
Today59
Yesterday147
*20121219 국치가 회복될 사건이 올 때까지 블로그 양쪽은 조의를 표하는 검정색입니다.
Tistory 로고 이미지 티스토리 가입하기!









블로그 이미지

약 2개월 전 오픈하고 나서 현재 지속적인 안정화를 진행 중인 웹사이트가 있습니다. 사이트의 기능 중 트위터처럼 사용자끼리 팔로할 수 있는 액션이 있는데, 이 액션이 이루어질 때마다 서로에게 알림 메시지가 보내집니다.


사용자가 화면을 이동할 때 새 메시지가 있을 경우 New 아이콘을 볼 수 있게 했는데, 페이스북처럼 실시간으로 알림을 받을 수 있으면 좋겠다는 생각을 했습니다. 화면 이동이 없더라도 일정 시간마다 새 메시지를 확인할 수 있게 하는 것도 가능하지만, 우선 실시간이 아니고 소모적일 수도 있기 때문이죠.


그래서 WebSocket을 써야겠다 생각만 하고 있었는데 문득. 시그널알이 떠올랐습니다.

그럼 뭐. 일단 해 보는 거죠. 하하.


원하는 목표는 이렇습니다.

  1. 팔로follow 메서드가 실행될 때, SignalR 서버를 통해 팔로 대상 사용자가 사이트 접속 중인지 확인해서 true일 때만 SignalR 메시지를 전송한다.
  2. 팔로 대상 사용자가 사이트를 이용 중이라면, 페이지에 포함된 SignalR 자바스크립트 클라이언트를 통해 전송받은 데이터를 함수로 실행하게 되고, 그 결과 즉각 New 아이콘을 보게 된다.
  3. 함께해준 그대에게 행복을!


사전 준비


자, 먼저 GitHub 문서를 간단히 훑어보면서 셋업을 시작합니다.

https://github.com/SignalR/SignalR/wiki/QuickStart-Persistent-Connections


아, 오른손 검지만으로도 솔루션에 외부 패키지를 손쉽게 추가할 수 있는 이 좋은 시절.

<참고 URL>

오늘 중으로 짧은 시간 안에 구현할 수 있을지는 모르겠습니다.

단순히 메시지를 모든 접속자에게 Broadcast하는 게 아니라 인증 및 대상자 확인을 해야 하니까요.

그래도 왠지 될 것 같습니다. :-)



코딩 시작


일단 문서에 따라 Server Connection 클래스 작성하고, Setup Routing 진행한 다음 예제 Javascript 클라이언트를 그대로 실행해 봤습니다.

그런데 문제가, IE, FF에서는 송수신 모두 잘 동작하는데 크롬에서는 송신만 동작하고 수신이 안되네요. “원인이. 무엇일까.” (카르페이 억양)

사소한(사실 사소하지 않지만) 문제에 집착하면 일이 늦어지므로, 일단 무시합니다.


그래서 곧장 Hub 클래스에 Dictionary<string, List<string>> 타입으로 static 멤버를 만들었습니다.

그리고는 OnConnected를 거칠 때마다 if (this.Context.User.Identity.IsAuthenticated)를 체크한 다음 로그인 사용자일 때만 , 그들의 로컬 계정 아이디를 Key로 쓰고 SignalR의 this.Context.ConnectionId를 체크해서 List<string>에 추가한 다음 이 리스트를 Value로 지정해서 접속자 정보를 관리했습니다.


그런데 역시, 생각이 짧았습니다. 싱글톤으로 만들 생각을 못해서, 디버깅을 시도하면 모든 커넥션들이 한 번 열릴 때마다 허브 클래스를 하나씩 만들고 자기들끼리 자기 커넥션 아이디만 딕셔너리에 추가하는 것입니다. 덕분에 외부 cs 파일에 있는 메서드들도 허브 클래스를 만들어서 메서드를 실행해 봤자 그 안에 누적된 접속자 정보가 없으므로 할 수 있는 게 없죠. 접속자 수만큼 Client 정보가 따로따로 분산되니까요.



결국은 문서에서 “How to call client methods and manage groups from outside the Hub class” 소제목을 찾아 참고한 다음 싱글톤을 만들었습니다. 이제는 모든 커넥션이 하나의 클래스에 클라이언트 정보를 저장하고, 로컬 계정과 연계된 커넥션 아이디 딕셔너리도 한 곳에 누적되죠. 그레이트!


세상에. 외부 cs 파일에서 메서드를 호출해도 싱글톤을 통하므로 유효한 메시지를 브로드캐스팅할 수 있을 뿐 아니라 딕셔너리를 활용해서 특정 사용자에게만 보낼 수도 있었습니다.


예시)

    public class SocketHubSingleton     {         private readonly static Lazy<SocketHubSingleton> _instance = new Lazy<SocketHubSingleton>(() => new SocketHubSingleton(GlobalHost.ConnectionManager.GetHubContext<SocketHub>().Clients));         private readonly ConcurrentDictionary<stringList<string>> _userConnections = new ConcurrentDictionary<stringList<string>>();         private SocketHubSingleton(IHubConnectionContext clients)         {             Clients = clients;         }         public static SocketHubSingleton Instance         {             get             {                 return _instance.Value;             }         }         private IHubConnectionContext Clients         {             get;             set;         }

        ...

    }

하지만. 하지만… 로컬에서는 잘 동작하는데 웹에 배포하면 아래와 같은 커넥션 이슈가 있네요.

[16:10:42.334] ws://weblab.tistory.com/signalr/connect?transport=webSockets&connectionToken=xKonPN3hnX5jvccwPBKr0IXXrb3LneWPDBApkiQyQHyCRQYr4-urkB-fhJCIiog6YIOeoqzupsquLLd_4Net32p9-aC7mbfG6RYxg9UmN5JhoEONFquwW-437obkDaZWSzBBxi3NqZM5S6oKxBFi6A2&connectionData=%5B%7B%22name%22%3A%22sockethub%22%7D%5D&tid=3 서버와 연결할 수 없습니다. @ http://weblab.tistory.com/Scripts/jquery.signalR-1.1.3.js:1089


역시 배포. 배포… 역시 피들러가 있어야!

<현재 응용 프로그램 구성에서 WebSocket은 지원되지 않습니다. 이를 사용하려면 Web.config에 다음 구성 스위치를 설정하십시오.>


애고. 마지막 미션까지 해결했습니다.

<system.web> 아래에 <httpRuntime targetFramework="4.5" /> 엘리먼트를 추가해 주면 해결되는군요. :)



감상


이렇게 소켓을 활용한 실시간 푸시를 구현하는데 걸린 시간이 불과 몇 시간이 안되다니 놀랍네요.

10시 정도에 출근해서 점심도 챙겨먹고, 낮잠도 자고, 구구콘도 먹었는데 말이죠! (한두 가지 다른 업무도 도와주고요.)


예전에는 이런 식으로 동작해야 한다는 그림은 있었어도 이걸 저 혼자 만들기 겁나서 손댈 수 없었는데, SignalR 덕분에 정말 편리하게 구현할 수 있었습니다.

GitHub documentation에서 필요한 부분 찾아 읽고, stackoverflow 조금 보고 샘플 코드 작성한 다음 실제 운영 코드에 접목하기까지 4시간 안쪽으로 소요된 것 같습니다.

웹사이트에 채팅, 메시징을 통합시키시려는 분들께 정말 유용하겠네요!



저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by One of Remnants

댓글을 달아 주세요

달력

« » 2017.08
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    

최근에 받은 트랙백

글 보관함

티스토리 툴바