Skip to content

Instantly share code, notes, and snippets.

@yebonkim
Last active November 20, 2018 02:41
Show Gist options
  • Save yebonkim/f307c11566b0998fb748682caa9bc3d5 to your computer and use it in GitHub Desktop.
Save yebonkim/f307c11566b0998fb748682caa9bc3d5 to your computer and use it in GitHub Desktop.

JavaScript 배틀그라우드로부터 살아남기

javascript_1

발표자료 링크

Vue, React, Angular 등 다양한 웹 프레임워크를 계속 접하면서 모두 JavaScript의 중요성을 느끼고 있을 것이라 생각합니다. 또 빠르게 변하는 상황 속에서 JavaScript는 어떻게 더 공부할지, 새로운 프레임워크는 언제 배워볼지 고민하는 개발자가 많다고 생각합니다. “JavaScript 배틀그라운드로부터 살아남기”에서는 이러한 고민을 하는 개발자들에게 필요한 세션이었다고 생각합니다.

이 세션은 아래와 같은 순서로 진행되었습니다.

- JavaScript의 탄생과 현재
- 파생 버전, ServerSide Framework 등 다양한 발전 버전
- Transpiling
- 우리가 가져야 할 자세

따라서 위의 내용을 순서대로 간략히 추려보았습니다.

JavaScript의 탄생과 현재

JavaScript는 1995년 12월 4일 처음 발표되었습니다. 당시에 웹을 동적으로 만들기 위해서 Java와 Java Applets 이 큰 인기였으나 비 개발자들에게 다소 어려워 더 가볍고 단순한 언어가 필요했습니다. 이 때 JavaScript의 이름은

Mocha -> LiveScript -> JavaScript

로 변경되었는데 이는 Netscape와 Sun의 협정으로 Java처럼 보여야 한다는 마케팅적 압력이 있었다고 합니다.

이후로 계속 표준화가 진행되었지만 ES4까지는 합의 도출에 실패했었습니다. ES5 버전부터는 ES표준이 잡히기 시작했으며 현재는 ES9까지 나왔습니다.

파생 버전, ServerSide Framework 등 다양한 발전 버전

그리고 JavaScript의 파생 버전으로

  - JScript
  - ActionScript

등이 있습니다.

또 아래 2가지도 JavaScript로부터 발전했습니다.

  - AJAX - 비동기식 웹 어플리케이션 개발을 위한 웹 개발 기법
  - JSON - 가벼운 Data 교환 형식

JavaScript는 NodeJS가 등장하면서 ServerSide역시 개발할 수 있는 언어가 되었습니다. 또 다양하고 많은 패키지가 개발되면서 이를 관리하기 위한 Package Manager인

  - npm
  - bower
  - yarn

등이 등장했습니다.

특히 yarn은 등장했을 당시 npm에 비해 빠른 속도로 주목받았지만 아래와 같이 npm 업데이트 이후 그 차이가 거의 없어져 가고 있다고 합니다.

javascript_2

아래와 같이 다양한 Framework들도 등장했었습니다.

1st Generation : jQuery, Prototype, MooTools
2nd Generation : AngularJS, React, Vue,js

또 다양한 브라우저가 등장하면서 버전 매칭이 중요해졌습니다.

오늘 날의 Javascript는 순수하게 그대로 쓰이기 보다 Framework와 개발도구를 통해 진행됩니다. 그리고 대다수 기능들은 npm같은 패키지 매니져를 통해 설치하고 사용할 수 있습니다.

Transpiling

JavaScript 소스를 읽어 적절한 소스로 바꿔주는 Transpiling 언어는 아래와 같은 것들이 있습니다.

- TypeScript
- CoffeScript
- elm
- Dart
- GWT

Transpiling을 통해 ES간의 버전을 호환할 수 있는 BABEL이 있습니다.

우리가 가져야 할 자세

마지막은 이렇게 많은 버전과 프레임워크들 사이에서 우리는 어떠한 자세로 JavaScript를 공부해야 하는가에 대해서 말해주셨습니다.

대체로 개발자들은 기존에 문제없이 사용하던 기술들이 있음에도 새로운 기술에 쉽게 관심을 뺏긴다는 것입니다.

이러한 상황에서 도구들의 새로운 버전이 나왔을 때 당장 버전을 올렸다가 이슈가 생겨 다시 내리는 경우가 더러있습니다. 메이저 업데이트 후 다양한 플러그인들은 이 업데이트에 대비되어 있지 않기 때문에 문제가 더 심각해지기도 합니다. 따라서 버전업데이트는 신중히 ㅎㅎ

또 jQuery가 대세일 때가 있었는가 하면 AngularJS, React, Vue가 대세가 되었듯이 다양한 framework가 나오면서 항상 ‘저건 언제 공부하지?’라는 생각을 가지고 있었습니다. 이러한 고민에 대해

우리는 모두 다 알 수 없다는 것을 인정하고 적당한 호기심과 꾸준함을 유지하는 것이 필요하다

고 하셨습니다.

네이버에서 사용되는 여러가지 Data Platform, 그리고 MongoDB

mongodb_1

발표자료 링크

최근 NoSQL DB인 MongoDB, DynamoDB 많이 등장하면서 NoSQL에 대한 관심이 커지고 있습니다. 저 또한 네이버에서는 MongoDB를 어떻게 사용하고 있는지, NoSQL의 장단점은 무엇인지 알고 싶어 세션을 듣게 되었습니다.

해당 세션은 아래와 같은 주제로 진행되었습니다.

  - 네이버에서의 Data Platform
  - MongoDB가 네이버에서 어떤 경우 대안이 되고 있는가?
  - 네이버에서 MongoDB를 사용하면서 겪은 에피소드들
  - 개인적으로 바라보는 MongoDB의 장단점 그리고 전망(vs RDBMS)

네이버에서의 Data Platform

초창기에는 거의 모든 서비스가 Web Server와 RDBMS Server로만 이루어져 있었다고 합니다. 이 후 서비스가 점점 확장되면서 빠른 응답을 위해 Cache가 추가되었습니다. 또 대용량 데이터를 비용과 용량 측면에서 효율적으로 저장하기 위해 HBase가 추가되었습니다.

mongodb_2

따라서 위와 같은 구조로 서비스가 유지되고 있었으나 점점 MongoDB를 자체적으로 설치하여 운영하는 개발팀이 늘어났습니다.

이는 아래와 같은 문제점 때문이었습니다.

- Schema less
- Sharding 지원
- Secondary Index 지원
- Transactoin 지원
- JSON 지원
- IDC DR 지원

위의 6가지가 각각 무엇인지 살펴보았습니다.

Schema less

사전에 데이터의 구조를 미리 명시하지 않아도 되는 구조를 뜻합니다. RDBMS에서는 기본적으로 모든 데이터를 Table로 구분하여 데이터를 관리하지만 Schema Less DB는 이러한 작업이 필요하지 않습니다. 네이버의 각각 다양한 서비스에서 DB를 따로 쓴다면 비효율적이기 때문에 Schema Less를 통해 통합적으로 관리할 필요가 생겼습니다.

이 때 MongoDB는 칼럼명까지 저장하기 위해서 1 document당 46byte를 차지하기 때문에 RDBMS에 비해 read/write 비용이 증가할 수 있는 단점이 있습니다.

Sharding

서비스 규모가 커지면서 DB Scale Up의 한계가 생겼습니다. 또한 RDBMS로 Scale Out인 샤딩을 구현할 경우 확장성이 떨어지며 개발 및 관리 비용이 듭니다. 따라서 Auto Sharding이 가능한 Platform이 필요하였습니다.

여기서 샤딩이란 같은 테이블 구조의 데이터를 다수의 데이터베이스에 분산하여 저장하는 것을 뜻합니다.

Secondary Index

위에서 언급하였듯이 대용량 데이터를 처리하기 위해 HBase를 사용하고 있을 때 Secondary Index 기능이 필요했지만 HBase에서는 지원해주지 않았습니다. HBase는 File별로 물리적으로 분리되어 저장됩니다. 하지만 MongoDB는 Shard별로 데이터를 Chunk단위로 논리적으로 관리하고 Secondary Index가 가능합니다. 다만 Chunk를 나누어주거나 합칠 때 부하가 생긴다는 단점이 있습니다.

mongodb_3

Transaction

NoSQL 중에서도 Transaction을 지원하는 Platform이 필요했습니다. 여기서 Transaction이란 데이터베이스의 상태를 변화시키는 작업의 단위로 원자성, 일관성, 독립성, 지속성과 같은 속성을 지원하여 여러 작업을 한 번에 처리할 때 보다 안정적입니다.

IDC DR

서비스가 커지면서 IDC의 이중화가 필요해졌습니다. 특히 MongoDB는 IDC간의 Auto Failover가 가능하다는 장점이 있습니다.

예를 들어 천재지변이 일어났을 경우 장애가 일어난 IDC를 제외하고 정상 작동하는 IDC로 Failover하는 기능이 제공됩니다.

여기서 IDC는 Internet Data Center로 서버 컴퓨터와 네트워크 회선 등을 제공하는 시설을 뜻합니다.

네이버에서 MongoDB를 사용하면서 겪은 에피소드들

Mongos관리

제조사는 routing에 쓰이는 Mongos를 client와 같이 배포할 것을 권장하지만 그렇게 사용하고 있지 않습니다. 이는 배포 관리가 비효율적이기 때문인데 네이버에서 필요한 기능은 mongos가 아니며 dba가 엄격히 분리되어 있기 때문에 통합관리하는 것이 비효율적이기 때문입니다.

L4와 getmore 문제

네이버에서는 Sharding시에 L4를 사용할 것이 권장되었으나 getmore이슈로 제거하였습니다.

getmore 동작 중에 다른 mongos로 가면 에러가 났기 때문입니다. L4는 Round Robin 방식으로 mongos가 계속 바뀌어 L4를 제거할 수 밖에 없었다고 합니다.

mongodb_4

여기서 L4는 로드밸런싱을 할 수 있는 라우팅 기능을 포함한 스위치 장비입니다.

Mongos <-> Shard커넥션

가장 중요한 문제라고 강조를 하셨던 부분입니다. Mongos와 Shard Server 간의 커넥션 관리에 문제가 있는데 이는 요청이 많아지면 max가 unlimited이기 때문에 커넥션을 계속 맺어 부하가 엄청나다는 것이었습니다. 따라서 아래와 같은 옵션을 적용해야 한다고 합니다.

mongodb_5

Storage Engine – Eviction Problem

WiredTiger 엔진 사용시 3.2.11 또는 3.4 버전 이상을 사용하여야 Eviction Problem을 겪지 않는다고 했습니다.

만약 3.0버전을 쓰고 있으며 WiredTiger 엔진 버전 업데이트가 불가능한 경우 nmap사용을 추천했습니다.

여기서 Eviction Problem이란 Memory Buffer에서 오래된 Data가 삭제되는 문제를 뜻합니다.

Storage Engine – Checkpoint

여기서 Checkpoint는 memory buffer와 disk 사이의 데이터 불일치를 해소하기 위해서 memory에서 disk로 data를 sync하는 작업을 뜻합니다. Checkpoint 실행 시 모든 Dirty Page를 내리기 때문에 Disk IO가 많아져 성능이 하락될 수 있습니다.

mongodb_6

Background Index

RDBMS에서는 Background index 생성시 관련 테이블만 lock되지만 MongoDB에서는 db 자체가 lock되기 때문에 쿼리 지연이 생길 수 있습니다. 따라서 Background index 생성은 주로 트래픽이 낮은 새벽에 진행됩니다.

대형 컨테이너 클러스터에서의 고가용성

container_0

발표자료 링크

개인적으로 서버 아키텍쳐에 관심이 많아져 가장 재미있던 세션이었습니다.ㅎㅎ

해당 세션은 아래와 같은 내용으로 진행되었습니다.

- 대규모 컨테이너 클러스터의 Load Balancing
- Large Scale Load Balancing
- 고가용성을 위한 Consistent Hashing
- IPVS Maglev Hashing Scheduler
- 확장성 있고 신뢰할 수 있는 Load Balancer

대규모 컨테이너 클러스터의 Load Balancing

대규모 컨테이너 클러스터란 아래 그림과 같이 여러 클러스터에 수 천개 이상의 컨테이너가 운영되는 환경을 뜻합니다.

container_1

이렇게 여러 컨테이너가 있을 때 Container Load Balancing이란 Layer4 Load Balancer가 부하에 따라 적절한 컨테이너들로 연결해 주는 것을 뜻합니다. 이 때 Dynamic Load Balancer에는 연결해주는 Container의 주소를 정적으로 저장해 가지고 있는 다는 단점이 있었습니다. 이러한 상황에서 컨테이너는 자주 추가, 삭제, 재시작 되면서 아래와 같이 소속되는 Container Host가 바뀌는 경우가 빈번하였습니다. 결국 정적으로 주소를 관리할 경우 실시간으로 변하는 Container들의 상태를 반영할 수 없다는 것이었습니다.

container_2

게다가 Container뿐만 아니라 로드밸런서에 장애가 발생한다면 해당 로드밸런서에 연결되어있던 Container들에 대한 Connection을 모두 잃게 되는 문제도 있었습니다.

때문에 고가용성을 위해 위의 문제를 해결할 수 있는 방법이 필요했습니다.

<요약>

- Load Balancer의 Container 연결이 고정적이기 때문에 Dynamic하게 변하는 Container상황에 대응할 수 없음
- Load Balancer자체에 장애가 발생했을 시 Load Balancer에 연결된 Connection들을 모두 유실하게 됨

Large Scale Load Balancing

기존의 Layer3 Routing은 같은 비용으로 여러 경로를 연결할 수 있음에도 하나의 경로만 선택할 수 있다는 단점이 있었습니다. 위와 같은 문제점 해결을 위해 BGP(Border Gateway Protocol)과 ECMP(Equal Cost Multi Path)를 도입하였으나 또 아래와 같은 문제점이 생겼습니다. ECMP에서 경로설정이 Hashing을 통해 이루어지기 때문에 Load Balancer의 개수 N으로 나누어줄 때 Load Balancer에 장애가 발생했을 경우 Hashing시에 N-1로 나누어주게 되어 이전의 연결이 모두 바뀌게 된다는 것이었습니다. 따라서 이러한 경우 장애가 일어난 로드밸런서 뿐만 아니라 Hashing이 바뀐 로드밸런서 역시 TCP Connection이 유실되는 문제가 생겼습니다. 이러한 문제점들은 고가용성의 서비스를 구축하기 힘들기 때문에 해결이 필요했습니다.

container_4

<요약>

BGP/ECMP 사용시 로드밸런서에 장애가 일어났을 경우 Hash Disruption이 일어남

고가용성을 위한 Consistent Hashing

위의 Hashing 문제를 해결하기 위해 Consistent Hashing을 도입하였습니다. Consistent Hashing은 최대 K/n 만큼의 disruption을 보장하지만 효율적인 로드 밸런싱 방식은 아니었습니다. 각각 동일한 수의 Connection을 처리하지 않게 될 가능성이 있기 때문입니다. 여기서 K는 환경에 따라 해석이 다양하나 PPT에서는 Connection의 개수로 이해할 수 있습니다.

여기서 Consistent Hashing이란 아래와 같이 Hash 값을 Ring형으로 구성하여 각 노드는 링에서 맡은 범위를 분할하여 처리하는 방식입니다.

container_3

여기서 구글의 Maglev Load Balancer라는 Consistent Hashing을 지원하는 소프트웨어를 발견합니다. Maglev에서는 permutation과 population 방법을 통해 index table을 생성합니다.

먼저 아래와 같이 Backend 개수와 Table Size에 따라 Permutation Table을 생성합니다.

container_5

다음 Population 과정을 통해 Backend를 LookUp Table에 할당할 수 있는데 할당하는 방법은 빨간색, 초록색, 노랑색 화살표 순서대로 메모를 참조해주세요. 이 순서대로 가장 우선순위가 높은 BackEnd를 할당하며 이미 사용되어지고 있는 자리는 차순위의 BackEnd를 할당합니다.

container_6

위의 알고리즘은 아래 수도코드를 참조하면 더 이해가 쉽습니다.

container_7

해당 Maglev 자료는 이 자료 에서 볼 수 있습니다.

이를 통해 효율적인 Load Balancing을 하고 Backend가 삭제되거나 추가되는 상황에서도 K/n 만큼의 Disruption만 발생합니다.

이 Disruption은 Lookup Table크기가 커질수록 감소합니다.

IPVS Maglev Hashing Scheduler

위와 같은 알고리즘뿐만 아니라 필요한 모든 기능을 구현해야했습니다. 네이버는 이를 Linux Kernel의 Netfilter를 통해 구현하였습니다. Maglev Software에서 Consistent Hashing 알고리즘만 필요한데 다른 부가적인 기술인 Packet Forwarding이나 Packet Processing, Backend Selection도 구현해야하는 문제점이 생겨 IPVS 위에서 Consistent Hashing 알고리즘을 구현하게 되었습니다.

여러 Scheduling 알고리즘을 모듈별로 제공하고 있기 때문에 스케쥴러 변경이 용이합니다. 따라서 네이버는 여기에 Maglev 모듈을 추가하였습니다.

마지막으로 IPVS kernel 파라미터로

- sloppy_tcp : ipvs가 sync아닌 tcp 메시지는 모두 버리기 때문에 이 파라미터를 통해 모두 포워딩받을 수 있음
- conn_reuse_mode : 로드 밸런싱 퍼포먼스를 올려줌

가 있고 사용을 권장하였습니다.

네이버 검색과 개인화

personalize_0

발표자료 링크

해당 세션은 아래와 같은 순서로 진행되었습니다.

- 검색의 목표
- 개인화가 필요한 경우
- 개인 검색의도 파악
- 개인화 검색 확장

검색의 목표

이전까지 검색은 ‘최대 다수의 최대 만족’을 이루기 위해 최대한 많은 사람을 만족 시킬 수 있는 동일한 검색 결과를 제공하였습니다. 최대한 다양한 의도를 만족시키기 위해 아래 그림에서처럼 자동차 외관을 보여주기 위해 3D로 차를 회전시키는 기능등 다양한 기능을 개발하였습니다.

personalize_1

개인화가 필요한 이유

점점 유저의 검색 의도가 다양해지고 있기 때문입니다. 아래와 같이 ‘펜타곤’ 이라는 단어에 대해 검색할 때 아이돌 펜타곤과 미국의 펜타곤 중 어느 것을 의도하였는지 알기 쉽지 않습니다. 따라서 최대 다수의 최대 만족보다 개인의 최대 만족이 중요해진 것입니다. 이와 같은 관점에서도 똑같은 질의어에 대해서 똑같은 내용을 보여준다고 하더라도 어떤 레이아웃에 어떤 정보를 보여주는 것이 중요해졌습니다. 예를 들어 이미지를 검색하고자 하는 목적이었다면 이미지를 띄어주고 실시간 Talk을 보기위한 목적이었다면 TALK을 띄워줄 것입니다.

personalize_2

이와 같은 개인화 검색은 네이버 사용자 중 1%만이 경험하고 있습니다.

이를 위해 여러 Click Entropy, User Entropy, Potential curve for personalization 등 다양한 연구가 진행되었으나 모두 예측 결과가 80%를 넘지 못했습니다. 따라서 개인화가 필요한 부분을 정의하기 위해 아래와 같이 3-Level Query Ambiguity 가 있습니다.

personalize_3

개인의 검색 의도

남은 문제는 사용자의 검색 의도를 파악하여 적용하는 일입니다. 이를 해결하기 위해 아래와 같이 사람의 기억은 장기 기억, 단기 기억으로 나뉜다는 점에 착안하여 모델을 정의하였습니다. 즉 3-Level Query Ambiguity는 언제 개인화 해줄것인가에 대한 것이며 Humm은 누구에게 정보를 줄 것인가에 관련되어있습니다.

personalize_4

personalize_5

여기서 각 메모리의 의미는 아래와 같습니다.

- Immediate 메모리 - 객관적, 단발적 검색, 실시간 검색 순위에 영향받음 
– Working memory – 사용자의 검색 세션안에서 의미있게 연속되는 검색들 
- Long term memory - 며칠동안 working memory의 검색 내용이 유지될 때 

Working Memory는 사용자의 검색 세션이 길게 유지되지 않아 데이터가 충분히 모이지 못해 아직 개발중입니다.

개인화 검색 확장

확장 방안에는 아래와 같이 2가지가 있습니다.

-User Group으로의 확장 : 그 사람에게 디오에 대한 데이터가 없어도 남의 데이터로 이용가능한 방법을 말합니다. 따라서 Long Term Memory를 결합하여 구현합니다.

-Query Group으로의 확장 : 예를 들어 ‘지민’이라는 쿼리가 들어왔을 때 평소에는 방탄소년단의 ‘지민’의 결과를 보여줄 수 있지만 Long Term Memory에 ‘설현’이 있다면 AOA의 ‘지민’을 보여줄 수 있습니다.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment