Showing posts with label HTML5. Show all posts
Showing posts with label HTML5. Show all posts

Monday, October 3, 2016

WebSocket이란?

WebSocket이란?

WebSocket이란 Transport protocol의 일종으로 쉽게 이야기하면 웹버전의 TCP 또는 Socket (소켓)이라고 이해하시면 됩니다.  WebSocket은 서버와 클라이언트 간에 socket connection을 유지해서 언제든 양방향 통신 또는 데이터 전송이 가능하도록 하는 기술이며 2008년에 HTML5에 포함이 되어서 여러 번의 토론을 통해 프로토콜이 제정되었고 2009년 구글 크롬을 시작으로 여러 웹브라우저에서 이 기술을 적용하여서 현재 Real-time web application 구현을 위해 널리 사용되어지고 있습니다. 참고로 Real-time web application이란 서버 쪽 또는 클라이언트 쪽 데이터가 실시간으로 업데이트 되는 웹 어플리케이션을 의미합니다.

왜 사용하는가요?

WebSocket을 사용하는 이유 또는 사용시 얻을 수 있는 장점에 대해서 이해를 하려면 WebSocket 이전에 사용되었던 기술과 어떤 차별성이 있는지를  이해하는게 중요합니다. 우선 웹어플리케이션에서 기존의 서버와 클라이언트 간의 통신은 대부분 HTTP를 통해 이루어 졌으며 HTTP는 Request/Response 기반의
Stateless protocol입니다. 무슨 말이냐 하면 서버와 클라이언트 간의 Socket connection 같은 영구적인 연결이 되어 있지 않고 클라이언트 쪽에서 (예를 들어 웹브라우저 쪽에서)  필요할 때 Request를 할 때만 서버가 Response를 하는 방식으로 통신이 진행되는 프로토콜이란 뜻입니다. (짧게 이야기하면 클라이언트 쪽에서만 대화를 시작할 수 있는 한 방향 통신입니다.) 그래서 어떤 문제가 생기냐면 서버 쪽 데이터가 업데이트 되더라도  클라이언트 쪽 (예를 들어 웹페이지)에는 화면을 Refresh 하지 않는 한 바뀐 데이터가 업데이트가 되지 않는 문제가 발생합니다. 그렇지만 이런 문제는 일반적은 웹 어플리케이션에서는 기존에 있던 임시 방편인 Long polling 이라던가 Ajax를 사용해도 어느 정도 해결이 가능하지만 데이터의 빠른 업데이트가 아주 중요한 요소 중에 하나인 어플리케이션 (예를 들어 주식 관련 사이트라던가 비디오 채팅 어플리케이션)에서는 실시간 업데이트가 아주 중요하기 때문에 (그리고 기존의 Long Polling 같은 기술은 서버에 많은 부담을 주는 부작용이 있기 때문에) WebSocket이 아주 유용하고 중요한 기술로 사용되고 있습니다.
또한 WebSocket은 Stateful protocol이기 때문에 클라이언트와 한 번 연결이 되면 계속 같은 라인을 사용해서 통신을 하기 때문에 HTTP 사용 시 필요없이 발생되는 HTTP와 TCP 연결 트래픽을 피할 수 있습니다.  마지막으로 WebSocket은 HTTP와 같은 포트 (80)을 사용하기 때문에 (Secure한 채널 같은 경우에는 HTTPS와 같은 443을 이용) 기업용 어플리케이션에 적용할 때 방화벽을 재설정하지 않아도 되는 장점도 있습니다. (대부분의 기업 방화벽은 외부에서의 접속은 HTTP나 HTTPS만을 기본으로
허용하고 있으며 만약 이외의 포트를 허용해야 할 경우에는 방화벽의 설정을 수정해야 하는데 큰 회사일 수록 방화벽 설정 수정 절차가 복잡하기 때문에 HTTP와 같은 포트를 사용한다는 점이 꽤 큰 장점이 될 수도 있습니다.)

작동 원리 및 그 외의 정보

우선 서버와 클라이언트 간의 WebSocket 연결은 HTTP 프로토콜을 통해 이루어집니다. 만약 연결이 정상적으로 이루어진다면 서버와 클라이언트 간에 WebSocket 연결 (TCP/IP 기반으로 하는)이 이루어지고 일정 시간이 지나면 HTTP 연결은 자동으로 끊어집니다.
기본적으로 WebSocket API는 아주 간단한 기능들만을 제공하기 때문에 대부분의 경우 SockJS나 Socket.IO 같은 오픈 소스 라이브러리를 많이 사용하고 있으며 메세지 포멧 또한 STOMP 같은 프로토콜을 같이 이용합니다. 마지막으로 스프링 프레임워크도 WebSocket을 간단한 메세지 브로커랑 SockJS 그리고 STOMP와 같이 지원하고 있습니다.

WebSocket 사용의 어려운 점

WebSocket은 사용시 위에 서술한 것과 같은 장점들을 주지만 그에 못지 않는 비용을 지불해야 합니다. 아래는 WebSocket 사용 시 발생할 수 있는 어려운 점 또는 문제점들입니다.
1. 프로그램 구현에 보다 많은 복잡성 초래: WebSocket은 HTTP와 달리 Stateful protocol이기 때문에 서버와 클라이언트 간의 연결을 항상 유지해야 하며 만약 바정상적으로 연결이 끊어졌을 때 적절하게 대응해야 합니다. 이는 기존의 HTTP 사용 시와 비교했을 때 코딩의 복잡성을 가중시키는 요인이 될 수 있습니다.
2. 서버와 클라이언트 간의 Socket 연결을 유지한다는 것 자체가 비용이 드는 일입니다. 특히나 트래픽양이 많은 서버 같은 경우에는 CPU에 큰 부담이 될 수 있습니다.
3. 오래된 버전의 웹 브라우저에서는 지원하지 않습니다. (물론 SockJS 라이브러리 같은 경우에는 Fallback option을 제공하고 있습니다.) 참고로 인터넷 익스플로어 같은 경우에는 10 버전부터 지원합니다.
4. 이건 제 개인적인 경험인데 서버와 클라이언트 간의 연결이 끊어졌을 때 생성되는 에러 메세지가 구체적이지 않아서 (예를 들어 여러가지 다른 이유로 연결이 끊어졌는데 에러 메세지가 같은 경우) 디버깅을 하는데 어려움이 많았습니다.

아무리 좋은 기술이라 할지라도 모든 경우에 유용할 수는 없는 법이기 때문에 프로그램에 꼭 필요한 기술인지 잘 체크하고 수용 여부를 결정하는 것이 바람직합니다.

대표적인 사용예

1. 페이스북 같은 SNS 어플리케이션
2. LOL 같은 멀티플레이어 게임들
3. 구글 Doc 같이 여러 명이 동시 접속해서 수정할 수 있는 Tool
4. 클릭 동향 분석 데이터 어플 (특정 시간동안 어느 사이트에 주로 접속했는지 등의 정보를 파악하는 어플)
5. 증권 거래 정보 사이트 및 어플
6. 스포츠 업데이트 정보 사이트 및 어플
7. 화상 채팅 어플
8. 위치 기반 어플
9. 온라인 교육 사이트 및 어플

References

https://www.websocket.org/aboutwebsocket.html
http://www.javaworld.com/article/2071232/java-app-dev/9-killer-uses-for-websockets.html
https://en.wikipedia.org/wiki/WebSocket
https://samsaffron.com/archive/2015/12/29/websockets-caution-required
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API



Friday, March 27, 2015

AngularJS: $digest vs $apply vs $timeout vs $evalAsync 차이점 및 설명


 AngularJS (이하 Angular)Two-way binding이라는 편리한 기능을 제공하지만 이 기능을 사용할 때 몇 가지 어려운 점이 있습니다. 그 중에 하나가 Angular Context 외에서 들어오는 데이터를 모델에 업데이트를 할 때 (여기서 모델이란 $scope로 정의된 variable들을 이야기합니다. : $scope.data) 개발자가 인위적으로 업데이트를 해야하며 이 때 사용하는 것이 $digest, $apply, $timeout 또는 $evalAsync 입니다. 참고로 Angular Context (또는 Angular  Scope )Angular를 사용하지 않고 제작하는 모듈을 가리키며 가장 간단한 예로 서버를 들 수 있습니다. 서버에서 어떤 이벤트가 발생해서 Angular로 제작된 클라이언트 모듈 쪽으로 데이터가 들어오고 그 들어온 데이터를 UI에 반영하기 위해서 $scope.data에 업데이트를 해야 하는데 위에 언급한 함수들을 사용하지 않으면 클라이언트 모듈 쪽에는 데이터가 업데이트 되었지만 UI쪽인 HTML 쪽에는 (보통 {{data}} 형식으로 포함된) 업데이트가 되지 않아서 UI에 반영이 되지 않은채로 남아있습니다.

Two-way binding의 동작 원리
Two-way binding의 동작원리는 개발자가 $scope를 이용해서 variable을 생성하면 생성된 variable watcher가 생성되고 $apply()$digest()가 실행되었을 때 현재까지 생성된 모든 watcher들이 실행되어서 변화된 값을 업데이트합니다. 여기서 watcher란 할당된 variableold valuenew value를 비교하여 두 값이 다를 경우 old valuenew value로 업데이트해주는 모듈로 $scope.$watch 함수를 이용하여 이 작업을 합니다. UI쪽에서 발생하는 데이터값의 변화에 Two-way binding이 아무런 추가 작업 없이 정상 동작하는 이유는 AngularUI에서 발생하는 이벤트에 대해 $apply()를 자동으로 실행하기 때문입니다. 예를 들어 ng-click 같은 이벤트가 생성이 된다면 $apply()도 자동으로 실행이 됩니다.

$digest()
$digest()는 위의 동작원리에서 설명한 대로 현재까지 생성된 모든 $scope variable 들의 watcher를 실행하여 값이 변화된 variable의 값을 최신값으로 업데이트해주는 일을 합니다.
사용 예: $scope.digest();

$apply()
간단하게 설명하면 $apply() $rootScope.$digest()랑 같습니다. 하는 일은 $digest()와 같지만 다른 점은 커버하는 scope가 다르다는 점입니다. 다시 말해서 $digest()는 해당 scopevariable의 값들만 업데이트하지만 $apply()는 무조건 rootScoperootScope 밑에 있는 모든 child scope들의 variable들 값을 모두 업데이트하기 때문에 자주 사용하면 제품 전체의 성능/효율성을 저하 시킬 수 있습니다. 기본적으로 Angular$apply()의 사용을 추천하고 있지만 제 개인적인 의견으로는 만약 어떤 scopevariable이 업데이트 되어야 하는지 안다면 $digest()의 사용을 추천합니다.
사용 예: $scope.$apply(); 또는 $scope.$apply(function() { ….. } );

$timeout()
$timeout()은 일반적인 자바스크립의 APIsetTimeout()Angular 버전으로 $timeout()함수 안에서 바뀐 variable 값을 업데이트하기 위해 $apply()를 기본적으로 포함하고 있습니다. $timeout()은 보통 setTimeout()과 마찬가지로 얼마동안의 Delay 이후에 해당 코드를 실행하기 위해 사용되어지고 있는데 이 용도 이외에 ‘$digest already in progress’ 에러 발생에 대한 임시 해결책으로도 사용되어지고 있습니다. (DirectiveController 안에서 여러 번의 $apply()를 포함한 개발을 해본 개발자라면 최소한 한 번 이상은 저 에러 메세지를 본 경험이 있을겁니다.) ‘$digest already in progress’에러의 발생원인은 Angular는 기본적으로 한 번에 두 개의 $digest() 동시 실행을 금지하고 있어서 이미 $digest()가 실행 중일 때 또 다른 $digest()가 실행이 된다면 이 에러 메세지가 출력되고 나중에 실행된 $digest()는 실행이 되지 않습니다. 그럼 어떻게 $timeout()의 사용이 이 문제의 해결책이 될 수 있는건가요? 그 이유는 $timeout()$apply() 실행 타이밍 때문인데 $timeout()은 이미 기존에 실행되고 있는 $digest()가 있다면 그 실행이 끝날 때까지 기다렸다가 $timeout() 내부에 포함된 $scope.$apply()을 실행하는 특징이 있고 이 때문에 위의 에러에 대한 임시 해결책으로 사용되어 지고 있습니다.
사용 예: $timeout(function() {…….}, 0);

$evalAsync()
$evalAsync()‘$digest already in progress’에러에 대한 Angular팀의 근본적인 해결책으로 이해하시면 편합니다. (위에도 언급했듯이 $timeout()의 기본용도는 이 문제의 해결이 아닌 얼마간의 Delay이후에 실행이기 때문에 근본적인 해결책이 될 수는 없습니다. 또한 약간의 화면 깜빡이는 문제를 발생시킬 수도 있습니다.) $evalAsync()도 기본적으로 $apply() 함수를 포함하고 있으며 현재 진행중인 $digest()가 있을 경우에 이 $digest()의 실행이 끝나기 전에 $evalAsync()에 포함된 variable의 바뀐 데이터도 같이 업데이트할 수 있는 기능을 제공합니다. $evalAsync()AngularJS 1.2 버전부터 제공되어지고 있습니다.
사용 예: $scope.$evalAsync(function() {…….});

추가사항:
AngularJS 1.3 버전부터 $applyAsync() 함수가 추가 되었다고 합니다.  기본적인 기능은 $evalAsync()와 비슷하지만 효율성 면에서 아주 미세한 차이가 있다고 하는 것 같은데 필자는 사용 경험이 없어서 자세한 사항은 잘 모르겠습니다.

References

Tuesday, July 15, 2014

FOUC란?

FOUC는 Flash of Unstyled Content의 약자로 웹브라우저가 웹 페이지를 로딩할 때 일시적으로 외부의 CSS stylesheet이 적용되지 않는 컨텐트를 로딩하여 화면에 출력하는 현상을 의마하는 말입니다.

원인: 이 현상은 브라우저마다 틀리지만 보통 아주 짧게 진행되며 이 현상이 생기는 이유는 웹브라우저가 컨텐트를 로딩할 때 한 번에 모든 컨텐트와 관련 화일을 로딩하여 출력하는 것이 아니라 우선 순위의 컨텐트를 먼저 로딩하기 때문에 (그리고 로딩이 다 끝나기 전에 화면에 출력이 되기 때문에) 발생합니다.

해결방법: HTML 파일의 Body tag에 'unresolved'라는 pseudo class를 포함하면 이런 현상이 생기는 것을 방지할 수 있습니다.
<body unresolved>

Sources:
http://en.wikipedia.org/wiki/Flash_of_unstyled_content
http://www.polymer-project.org/docs/polymer/styling.html#fouc-prevention
http://ko.wikipedia.org/wiki/FOUC