|
| 1 | +# 웹 패턴 |
| 2 | + |
| 3 | +## 자바스크립트 전송 |
| 4 | + |
| 5 | +### 파일 결합 |
| 6 | +브라우저의 컨텐츠 전송 |
| 7 | + |
| 8 | +#### DNS 쿼리 |
| 9 | +1. URL 입력 -> 이벤트 발생 |
| 10 | +2. 운영체제에 웹사이트 이름을 IP 주소로 알려줄 것을 요청 |
| 11 | +3. 윈도우 / 리눅스 / 맥에선 표준 C 라이브러리 함수인 `gethostbynam` 호출 |
| 12 | +4. 로컬 DNS 캐시를 확인 하여 매핑된 주소가 있는지 탐색 |
| 13 | +5. 있다면 캐시 정보를 사용하고 없다면 DNS 서버에 이를 요청 |
| 14 | +6. 일반적으로 DNS 서버는 ISP(Internet Service Provider)업체에 의해 제공 |
| 15 | +7. 해당 서버에 기록이 존재할 때 까지 DNS 서버 체인을 따라 전파 |
| 16 | +8. 루트 서버까지 도달하여 찾지 못한다면 조회는 실패 |
| 17 | + |
| 18 | +#### 연결 및 요청 |
| 19 | +1. 브라우저가 사이트 주소를 알면 연결을 만들고 컨텐츠 요청 |
| 20 | +2. 문서 혹은 문자 전송. 보안 연결일 경우 이 시점에 SSL/TLS 협상 수행 |
| 21 | +3. 서버가 HTML을 전송하고, 여기서 외부 자원을 발견하면 다시 서버와 연결하여 자원 요청 |
| 22 | + |
| 23 | +여기서 `파일 결합`의 이유가 필요해진다. 전송이 오버헤드를 줄여야 한다. |
| 24 | + |
| 25 | +네임 스페이스를 통해 결합에 문제를 피할 수 있다. |
| 26 | + |
| 27 | +다만 이때 트레이드 오프가 필요하다 |
| 28 | + |
| 29 | +- 사용자가 페이지를 돌아다닐 경우 |
| 30 | + - 파일 결합으로 캐시를 사용하여 재사용성 증대 |
| 31 | +- 사용자가 페이지 일부분만 방문할 경우 |
| 32 | + - 파일을 결합할 경우 필요없는 스크립트까지 받게 됨 |
| 33 | + |
| 34 | +> 이를 해결하기 위해 두 방법 사이의 스윗 스팟을 찾아야하는데 이를 위해 이동 통계가 필요하다. |
| 35 | +
|
| 36 | +### 축소 |
| 37 | +1. 태스크 러너/번들러 사용 |
| 38 | +2. 서버에서 컨텐츠 스트림을 압축할 때 `gzip`(무손실 압축) [관련 링크](http://www.playnexacro.com/index.html#show:article) |
| 39 | + |
| 40 | +### 콘텐츠 전송 네트워크(CDN) |
| 41 | +오직 정적 콘텐츠 제공을 목적으로 하는 호스트 분산 네트워크 |
| 42 | + |
| 43 | +## 플러그인 & 제이쿼리 & d3 |
| 44 | +[추천 도서](http://www.yes24.com/24/goods/11371306) |
| 45 | + |
| 46 | +## 멀티 스레드 |
| 47 | +UI 환경에서 싱글 스레드는 흔히 사용된다. 레이스 컨디션을 피하기도 좋다. |
| 48 | + |
| 49 | +하지만 웹 앱의 규모가 커지면서 복잡도는 증가했고 이에때라 복잡한 연산을 백그라운드에서 |
| 50 | + |
| 51 | +실행해야할 필요성이 높아졌다. 이에 대응한 것이 `Web Workers` 출현이다. |
| 52 | + |
| 53 | +모던 브라우져에서 사용 가능하며 메시지를 통해 메인 스레드와 통신한다. |
| 54 | + |
| 55 | +```js |
| 56 | +// 워커 파일 내부(worker.js) |
| 57 | +self.addEventListener('message', e => { |
| 58 | + var data = e.data; |
| 59 | + // startCalcualtion 메시지를 받으면 |
| 60 | + if (data.cmd === 'startCalculation') { |
| 61 | + self.postMessage({event: 'caculationStarted'}); |
| 62 | + // fib의 새로운 인스턴스를 시작 |
| 63 | + var result = fib(data.parameters.nummber); |
| 64 | + self.postMessage({ |
| 65 | + event: 'calculationComplete', |
| 66 | + result: result |
| 67 | + }); |
| 68 | + } |
| 69 | +}, false); |
| 70 | + |
| 71 | +// 메인 스레드 |
| 72 | +// 외부 파일에서 웹워커를 로드하고 |
| 73 | +worker = new Worker('worker.js'); |
| 74 | +// 리스너를 추가한다. |
| 75 | +worker.addEventListener('message', message => { |
| 76 | + logEvent(message.data.event); |
| 77 | + if (message.data.event === 'calculationComplete') { |
| 78 | + writeResult(message.data.result); |
| 79 | + } |
| 80 | + if (message.data.event === 'calculationStarted') { |
| 81 | + document.getElementById('result').innerHTML = 'working'; |
| 82 | + } |
| 83 | +}); |
| 84 | + |
| 85 | +// 계산을 위한 명령 |
| 86 | +worker.postMessage({ |
| 87 | + cmd: 'startCaculation', |
| 88 | + parameters: {number: 40} |
| 89 | +}); |
| 90 | +``` |
| 91 | +백그라운드 실행 동안 메인 스레드는 다른 작업을 할 수 있고, |
| 92 | + |
| 93 | +웹 워커로 부터 메시지가 수신되면 기존 이벤트 루프로 처리한다. |
| 94 | + |
| 95 | +Node.js에서 자식 프로세스를 포크 하는 형식으로 비슷한 인터페이스를 제공한다. |
| 96 | + |
| 97 | +하지만 프로세스를 포크하는 만큼 비용이 많이 든다. |
| 98 | + |
| 99 | +## 서킷 브레이커 패턴 |
| 100 | + |
| 101 | +대형 시스템은 많은 중복으로 이루어져 있다. 이러한 중복은 컴포넌트의 실패 시 |
| 102 | + |
| 103 | +백업을 제공하는 수단이 될 수 있다. |
| 104 | + |
| 105 | +> 앱이 외부 데이터 소스에 5초마다 쿼리를 보낸다고 가정하자. |
| 106 | +
|
| 107 | +이러한 폴링이 실패하면, 대부분 실패를 무시하고 계속 폴링한다. |
| 108 | + |
| 109 | +일부의 경우 실패시 즉시 재요청을 하기도 하는데, 이는 바쁜 스케쥴링에서 |
| 110 | + |
| 111 | +문제가 될 수 있다. |
| 112 | + |
| 113 | +서버측에서는 수많은 클라이언트에게 5초마다 응답해야 한다. |
| 114 | + |
| 115 | +서킷 브레이커 패턴은 실패가 일정 횟수에 도달하면 통신 시도를 차단 한다. |
| 116 | + |
| 117 | +물론 어느 시점에서는 서킷 브레이커를 리셋하여 서비스가 복구되도록 해야한다. |
| 118 | + |
| 119 | +## 백 오프 |
| 120 | + |
| 121 | +서킷 브레이커의 변형으로 통신을 차단하는 대신 요청에 딜레이를 준다. |
| 122 | + |
| 123 | +폴링 간격이 5초 였다면, 고장 검출 시 간격을 10초로 변경한다. |
| 124 | + |
| 125 | +이 과정을 반복하여 간격을 늘리고, 다시 정상 작동 한다면 다시 간격을 줄여간다. |
| 126 | + |
| 127 | +## 성능 저하 애플리케이션 동작 |
| 128 | + |
| 129 | +실시간 주식 시세를 서비스하는 경우 |
| 130 | + |
| 131 | +시스템에 문제가 생기면, 비실시간으로 서비스를 제공할 수 있다. |
| 132 | + |
| 133 | +모던 브라우저가 제공하는 저장 공간을 사용하는 것이다. |
| 134 | + |
| 135 | +앱이 서버로 데이터를 전송할 때도 유용하다. |
| 136 | + |
| 137 | +데이터 업데이트를 로컬에 저장하고 서비스가 가능해질 때 한꺼번에 보낼 수도 있다. |
| 138 | + |
| 139 | +(사용자가 페이지를 떠나면 백그라운드 작업은 종료된다.) |
| 140 | + |
| 141 | +> 이런 방식을 사용할 경우 사용자에게 데이터가 최신이 아님을 경고해 줘야 한다. |
| 142 | +
|
| 143 | +## 프로미스 |
| 144 | + |
| 145 | +냉무 |
0 commit comments