2. | 회사소개
파프리카. 2013년 3월 15일 시작된 반도의_흔한_웹_개발_회사입니다.
웹서비스 개발을 중심으로, 모바일, HTML5 컨텐츠 제작 등을 하고 있습니다.
SBSCNBC 인터렉티브 주식 정보 웹사이트 및 앱 개발,
LG전자 R&D 센터 차량용 반응형 하이브리드앱 개발,
LG전자 R&D 센터 프리즘 서비스 웹프론트 개발,
아동용 HTML5 인터렉티브 컨텐츠 개발,
각종 중/소규모 웹사이트 개발 등
틈새 공지
투자자 : 모집중
사장여친 : (급구)00명 상시모집중
5. | 초기 아키텍트 : SIMPLE IS THE BEST
Goal 12/31
AWS EC2
Browser
Socket.i
o
Node.js
NginX
Oracle
Socket.i
o
HTML/CSS/JS/Media
FTP
6. | 프론트 설계 : MVP 패턴
Goal 12/31
https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter
다이나믹하고 인터렉티브한 프론트를 제대로 소화하기 위해 상태관리 및 잦은 수정 등에 유리한 MVP 을 적극 활용
프론트 코딩을 보다 구조화 할 수 있다.
7. | 프론트 설계 : MVP 패턴 도입배경
Goal 12/31
기획상 모바일웹의 뷰의 레이아웃은 PC웹과 상이하다.
PC신형브라우저 VIEW 모바일웹 VIEW
공통 PRESENTER
(필요시 일부 오버라이드)
공통 MODEL
공통부 재활용
원을 그리려다..수전증
PC구형브라우저 VIEW
8. | 웹소켓
Goal 12/31
Ajax Long Polling 방식은 HTTP오버헤드에 재접속 속도도 느릴테고…
별도의 서버 설정도 필요할테고…
무엇보다,
슈퍼다이나믹인터렉티브모던웹프로젝트에
어울리지 않잖아?
그리고…
웹소켓을 어떻게든 써보고 싶은 불타오르는 욕망
10. | Node.js + Socket.io
Goal 12/31
사실 프로젝트 이전에 초간단 채팅 어플리케이션을 만들어 봤습니다.
Publish/Subscribe 패턴으로 제공되는 간결한 API에 푹 빠졌고
그 달콤함과 Node.js의 빠른 코드작성 능력에 한번 더 눈이 멀고…
(복선ㅎ)그 달콤함에 취해 앞일을 낙관하게 되는데…
11. | Redis
Goal 12/31
사이트의 제공데이터를 실시간으로 빠르게 전파하고
유저의 데이터입력이 없는 (그런데 왜 인터렉티브?)
스냅샷 형태의 데이터를 제공하는 특성
Pub/Sub Channel 제공
역시… Redis를 어떻게든 써보고 싶은 불타오르는 욕망
슈퍼다이나믹인터렉티브모던웹프로젝트에
어울리는 메모리DB
12. 프 로 토 타 이 핑 프 로 토 타 이 핑
프 로 토 타 이 핑 프 로 토 타 이 핑
프 로 토 타 이 핑 프 로 토 타 이 핑
프 로 토 타 이 핑 프 로 토 타 이 핑
프 로 토 타 이 핑 프 로 토 타 이 핑
프 로 토 타 이 핑 프 로 토 타 이 핑
프 로 토 타 이 핑 프 로 토 타 이 핑
프 로 토 타 이 핑
프 로 토 타 이 핑 프 로 토 타 이 핑
성공적?
Goal 12/31
17. Goal 12/31
HAProxy
HAProxy is free, open source software that provides a high availability load balancer
and proxy server for TCP and HTTP-based applications that spreads requests across
multiple servers.[2] It is written in C[3] and has a reputation for being fast and efficient
(in terms of processor and memory usage).[4]
HAProxy is used by a number of high-profile websites including GitHub, Bitbucket,[5]
Stack Overflow,[6] Reddit, Tumblr, Twitter[7][8] and Tuenti[9] and is used in the
OpsWorks product from Amazon Web Services.[10]
https://en.wikipedia.org/wiki/HAProxy
무슨 말인지 1도 모르겠지만... 어쨌든
| 들어는 보았나! 질풍발란서! H.A.P.R.O.X.Y
18. Goal 12/31
HAProx
y
HAProxy에서 TCP기반의 웹소켓을
StickySession 방식으로 설정하는데도 많은 삽질이 뒤따랐다.
소통원활!
사이다! x100
Browser
Socket.i
o
AWS EC2
Node.js
Socket.i
o
AWS EC2
Node.js
Socket.i
o
| 구세주 HAProxy
21. Goal 12/31
각종 커뮤니티, 구글신의 신탁을 기대해 봐도 답은 또렷하지 않고
Try catch로 도배를 해보아도 에러의 내용은 알 수 없으니
팀원들의 눈동자에는 마치 미지의 세계에서 낯선 존재를 만났을 때의 공포가…
프로세스가 죽으면 다시 살리는 각종 툴을 써봐도 이 상태로 출시할 수는 없고
오랑캐 Node.js 무용론,
Java회귀론 등
척화배척사상이 힘을 얻어 갈 무렵
| Node.js의 반란_시즌2
22. Goal 12/31
바다 밖 어딘가에는 Node기반 상용 서비스가 있다는 전설 같은 이야기를 믿고
진시황이 불노초를 찾듯, 장혁이 추노하듯 버그를 다시 찾아나서게 되는데…
오랑캐 Node.js가
비동기식 Callback 형태의 동작임을
다시금 깨닫게 된다.
| Node.js의 반란_시즌3
23. Goal 12/31
비동기메커니즘에서의 Callback이란 무엇인가!
비동기식 호출의 요체로서 호출자의 스택이 모두 끝나기전에는 호출되지 않는 특성
물론, 싱글스레드에서만.
A
B
Event Loop
수전증2
C
2) B에서 C호출
1) A에서 Try Catch
3) C에서 Exception발생
D
4) 1번의 스택이 정리되었기 때문에 C함수에서 Exception이 발생해도 잡을 수가 없다.
물론 Node.js에서는 Domain개념이 있기 때문에 방도가 전혀 없는 것은 아니다.
| Node.js와 asynchronous callback mechanism
24. Goal 12/31
로깅강화와 예외처리 디버깅 요령 체득 등…
다시 한번 상용서비스로서의 가능성을 품게 된다.
Node.js가 불안정하다는 의견이 종종 보이지만,
이후로는 단 한번도 원인없이 숨진적이 없기에 개발자의 역량문제로 잠정결론
| Node.js의 반란을 진압하고…
30. Goal 12/31
처음에는 간단한 푸시발송 서버를 구현하려고 했으나,
발송량이 상당할 것으로 예상되어 Amazon SNS를 사용하기로 협상
결론적으로는 안정적이고 빠른 발송이 보장되었으며
(또)Publish/Subscribe 모델이 지원하여 Topic기반의 관리가 가능
| 실시간 OOO 알림 : 앱 푸쉬서버 필요
34. Goal 12/31
Redis
Preflight
Upgrade
| Socket.io, Redis, Node session module만으로는 웹소켓의 세션 유지가 안된다(눈물)
Socket.io에서 Preflight(Ajax)일 때만 세션을 생성하고,
Websocket 통신시에는 세션을 만들지 않음. 위는 일반적인 Node.js의 세션공유방식(Redis를 세션스토어로..)
Browser
Socket.i
o
Node.js
Socket.io Express
Mod.
SessionStor
e
35. Goal 12/31
웹소켓상의 통신구간에서 세션을 가져올 방도를 찾을 수 없었고
시간은 흘러가는데…
그래서 어쩔 수 없이…
Socket.io에서 웹소켓 통신 중 세션 획득하신 분 연락 좀요.
피자 배달해드림.
| NPM 리파지토리를 탈탈 털어봐도…
36. Goal 12/31
…
웹소켓용 세션관리
모듈을 직접 만듦
_사족 : 세션 모듈명은 FkingSession이지만 이것은 수제임을 강조하기 위해 은유적으로 햄버거의 이름을 차용한 것
FantastickBurgerKingSession의 약자임을 밝힙니다. 이상한거 아님.
참고로 다른 업체에서 소스 인수인계해 갔는데 별말없는거 보면… 하.
| Trick or Threat
Redis
onconnection
oncookie
Browser
Socket.i
o
Node.js
Socket.io Express
수제
세션-모듈
수제 세션 생성
주기적으로
document.cookie로
정보 업데이트
40. Goal 12/31
프론트엔드 애니메이션 문제 발생 : callback, UI state
_비록 싱글스레드로 동작하나 비동기통신과 콜백이 난무하는 UI의 특성
_각 애니메이션이 끝나는 지점을 확인하여 다음 애니메이션을 진행해야 함
_(일정압박에 따른) 개발자의 모럴해저드 발생, 감으로.. 종료시간을 추측
_애니메이션의 순서가 뒤엉켜 화면낸 요소들이 곂치거나 사라지는 문제발생
_각 화면 요소 및 렌더링 엔진의 STATE점검 로직 부족
_Async라이브러리 도입
_Callback chain 전면적 리팩토링
_애니메이션 프로세스 재조정
| 모럴 헤저드
45. _웹소켓 접속과 초기 데이터의 사전 로딩의 필요상 로딩화면이 먼저 나타는 구조
_소켓서버 구조적 결함발견(불필요한 루프제거), 로딩속도 개선
_초기데이터의 양이 생각보다 큼으로 초기데이터의 분할 로딩방식으로 변경
_눈속임이지만 초기기동속도가 처음 5~6초에서 1~3초 대로 축소
| 리펙토링 : 점진적인 로딩방식
Goal 12/31
48. 재료1 : Publish/Subscribe 모델
재료2 : Node의 싱글스레드
재료3 : 고용량의 Subscribe 데이터
다수 사용자
Node.js의 채널 Subscribe 핸들러에서 서버에 접속한 모든 클라이언트에게
고용량의 데이터(2~5MB)를 순차적으로 전송하는 과정에서 이벤트 큐 마비.
싱글스레드이므로 핸들러가 종료되기 전까지 다음 이벤트가 순환되지 못한다.
Goal 12/31
| Too much love will kill you
49. 약 1시간 정도의 분석 끝에 Payload 문제임을 발견
노드 소켓서버의 복제, 초기 5개 인스턴스에서 25개 인스턴스로 확장
서버는 일시적으로 정상화됐으나…
_2vCPU EC2서버에서 다수 인스턴스를 돌리게 됨으로 생기는 비효율
_근본적인 Payload문제 미해결
_Payload가 해결되지 않으므로 many servers with low connections 아키텍트 유지
Goal 12/31
| 예측하지 못한 Payload 그리고 조치
50. Payload를 줄이기 위한 방안
데이터압축
_js 압축스크립트의 성능 문제로 클라이언트 UI freezing 우려
_클라이언트에서 web worker 도입 검토
JSON 데이터 Key 필드 축약
_개발 가독성을 위해 Key의 이름이 긴 편임, 축약시 약 20~30% 데이터 감소 가능
_그러나, 전면적 리팩토링에 대한 시간적 부담감
_데이터전송 부에서 Key필드를 별도의 메타데이터로 한벌 만들고 Value만 묶어서 보내는 방식
_역시 전면적 리팩토링 필요
데이터의 양은 둘째치더라도 소켓채널 전송시, 로그인 등의 액션에서 타임아웃 발생
어느정도의 비효율은 감수하더라도 근간 서비스가 동작하도록 리팩토링 결정
Goal 12/31
| 2박 3일간의 사투
51. 회원가입 / 로그인 / 북마크 / 프로필힛트카운트 증가 등의 로직도 WebSocket에서 동작
구조적문제점 탈피를 위한 사용자의 전송데이터 채널을 신설하기로 결정
웹소켓 채널은 오직 Server Push용으로 용도전환
Node.js에서 오라클 쿼리 작성 생산성이 열악하여 Java-Spring으로 REST API 화
Goal 12/31
| Rest Server 도입
52. Goal 12/31
| REMIND : 초기 아키텍트
AWS EC2
Browser
Socket.i
o
Node.js
NginX
Oracle
Socket.i
o
HTML/CSS/JS/Media
FTP
53. 실제로는 더 복잡함
| 최종 아키텍트
Browser
Ajax
Socket.i
o
AWS EC2
Node.js
NginX
OracleSocket.i
o
HTML/CSS/JS/Media
FTP
HAProx
y
AWS EC2
Node.js
Socket.i
o
Node.js
Rest API
Goal 12/31
54. 처음부터 알았더라면...
그렇게
2박 3일간의
전투가 끝나고...
만약, 초기 기획이 지금과 같았고 이러한 문제점을 미리 알았다면 …
1. 오라클 연동은 자바-스프링 REST (초반에 고민)
2. 최신버전 노드 사용(오라클 Module 때문에 1.11버전 사용)
3. WebSocket은 서버 Push용으로만 사용
4. 어쩌면 고전적인 Ajax Long Polling이 나았을지도
Goal 12/31
55. 종전
여러 실수가 있었으나,
어찌되었든 우리는 짧은 시간 동안 프로로서 문제해결을 했다.
하지만, 전투에서는 승리했으나 전쟁에서도 승리했다 말할 수 있을까?
상처뿐인 영광, 아니 상처뿐인 상처로 남았다.
Goal 12/31
56. 그 후, (프로젝트 종료예정일이 지난 후)
_미뤄뒀던 관리자페이지 개발
_푸쉬기능 개발
_오직 HAProxy만이 프로젝트 내내 말썽을 일으키지
않았음
끝
Goal 12/31