12/30/2018

블록체인 기술을 바라보는 개인적 시각

 

블록체인 기술을 한마디로 정의하기는 어렵다. 개념이 명확하게 정리되지 않은 상태이기에 기술적 정의 및 설명하는 방식도 상황에 따라 달라진다.

블록체인 기술을 이해하기 위해서는 비트코인에 대해서 알아야한다. 비트코인은 블록체인 기술을 기반으로 2009년에 배포된 암호 화폐이다. 비트코인으로 인해 그 기반 기술인 블록체인이 이목을 끌기 시작했다.

블록체인은 “블록”이라고 하는 소규모 데이터들이 P2P 방식을 기반으로 생성된 체인 형태의 연결고리 기반의 분산 데이터 저장환경에 저장되어 누구라도 임의로 수정할 수 없고 누구나 변경의 결과를 열람할 수 있는 분산 컴퓨팅 방식의 데이터 변조 방지 기술이다.

계모임을 한다고 생각해보자. 계모임의 경우에는 돈을 관리하는 계주나 계원이 잠적하면 문제가 생긴다. 종종 뉴스에서 이런 사례가 보인다. 계모임은 인간관계를 바탕으로 신뢰를 얻기 때문이다. 여기서 논제를 약간 틀어서 계모임을 하는데 각자 입금하는 금액이 상이하다고 가정해보자. 그리고 입금한 금액은 장부에 기록한다고 치자. 그런데 장부를 기록하는 과정에서나 실제 기록한 이후에 다르게 바뀔 수 가 있다. 장부 관리자가 특정 계원과 기록을 허위로 작성하거나 기록된 내용을 변조할 수 있는 가능성이 있기 때문이다.

여기에 블록체인 기술을 적용해보자.

각자의 내역을 쪽지에 적어 나머지 사람에게 전달하고 나머지 사람은 자기 기록을 포함해 각각 다른 사람의 내용을 기록한 쪽지를 갖게 된다. 이 내용을 근거로 1장의 장부를 각각 만든다. 그리고 참여하는 사람이 합계를 각각 산출한다. 이 과정에서 가장 먼저 합계를 산출한 사람이 손을 들고 사본을 만들어 나머지 사람들에게 배포한다. 사본을 전달 받은 사람들은 합계가 맞는지 일치하는지 점검하고 이상이 없다면 보관한다. 만약 내용이 틀리면 잘못되었음을 알리고 다른 누구가 정확한 자료를 만들때까지 작업을 계속한다.


위의 방식으로 처리하기 때문에 기술적 특성에서 생긴 처리 속도의 제한적 문제가 발생한다. 모든 참여자가 데이터를 기록하고 관리하는 방식의 한계이기도 하다. 이를 해결하는 방안을 “Consensus 알고리즘”이라고 한다. 속도 문제를 해결하기 위해 여러가지 다양한 Consensus 알고리즘이 나타났고., 최초의 블록체인이 추구하던 개념과는 거리가 먼 알고리즘도 생겨났다. 블록체인은 개방형과 폐쇄형으로 나뉘게 된다. 개방형은 요건을 갖추면 누구나 참여할 수 있고, 폐쇄형은 특정 조건의 참가자만 참여가 가능하다.


초반에는 블록체인이 기존 비즈니스에 혁신을 가져다 줄 것이라는 기대가 많았다. 특히 중개 거래상에서 투명성을 제공하고 거래 비용을 낮춰줄꺼라는 기대가 많았다. 하지만 현실은 녹녹치 않은 상황이다. 이미 중앙화된 시스템에서 신뢰가 확보된 분야에서는 블록체인으로 인해 투명성과 신뢰도를 제공한다고 해서 기존 대비 큰 가치를 제공하지 못한다면 굳이 도입할 이유가 없다. 이미 잘 운영되고 있는 분야에 적용하는 것은 어렵지 않을까?

오히려 블록체인 기술은 양성 시장보다는 음성 시장에 적합할 수 있다. 인류가 생긴 이래 음성적인 시장이 계속 활성화된 이유는 무엇일까? 싸게 사고, 세금을 내지 않기 위해서? 이런곳에 블록체인 기술을 응용해서 음성 시장의 입지를 줄이는건? 혹은 온라인 투표 혹은 선거에 도입하는건?

분산, 개방, 공유를 통한 투명성/신뢰성이라는 장점을 지닌 블록체인 기술을 적용할 수 있는 분야는 무엇일까? 블록체인에 대한 환상을 깨고 기존 기술로는 적합하지 않은 비즈니스 분야를 개척해야 하지 않을까?

12/25/2018

[독서] 지지 않는다는 말

 



다이어리 정리를 하다가 얼마전 읽은 지지 않는다는 말에 나온 글귀를 적은 페이지를 발견하고 여기에 옮겨 적는다.

  • 내 삶에서 가장 큰 영향을 끼친 건 지지 않는다는 말이 반드시 이긴다는걸 뜻하는 것만은 아니라는 깨달음이었다. 지지 않는다는 건 결승점까지 가면 내게 환호를 보낼 수많은 사람들이 있다는 걸 안다는 뜻이다. 아무도 이기지 않았건만, 나는 누구에게도 지지 않았다. 그 깨달음이 내 인생을 바꿨다.
  • 너는 네가 하고 싶은 일만하면서 살 수 있을 것 같니? 그러나 하고싶은일만 하면서 살수없다고 해서 하기 싫은 일을 반드시 하면서 살아야 한다는 의미는 아니지 않은가? 오히려 하고 싶은 일만 하면서 살수 없으니까 하기 싫은 일을 더구나 하지 말아야지
  • 후달리지 않은 것 만으로 당신은 이미 달리기의 반을 이룬 셈이다. 달리고 싶지 않을때 달리지 않고 달리고 싶을때 달릴수 있는 사람, 그가 바로 러너니까…
  • “칭커”란 친하게 지내고자 하는 사람들을 한데 모아 그들이 “이러다가 배가 터지지 않을까?” 라고 걱장할 즈음에 “이제 그럼 주문을 해볼까?” 라는 표정으로 요리와 술을 더 시킨뒤 “많이 드셨는지 모르겠다.”고 말하며 계산하는 행위를 뜻한다.
  • 내가 집으로 돌아가는 순간은 여행지가 집처럼 느껴질때…
  • 오래산 사람은 덜 산 사람처럼 호기심이 많고, 덜 산사람은 오래산 사람처럼 사려싶은 사람이 되었으면 좋겠다.
  • 근본적인 질문은 우리에게 한계가 존재할때만 가능하다.
  • 누군가와 같이 뭔가를 하는일은 정말 번거롭다. 추억을 만드는데는 최소한 두 사람이 필요하다는 것을, 혼자서 하는 일은 절대로 추억이 될 수 없다는 것을…
  • 대개 어른들이 그런건 나중에 얼마든지 할 수 있다고 말하는 일 위주로 생활하면 인생에서 후회할 일은 별로 없는 것 같다.
  • 옛날에는 지물포에서 롤페이퍼 형태로 둘둘말린 종이를 잘라서 팔았다. 그래서 “론지”라는 말이 “노루지”라는 아름다운 이름으로 불렸다.
  • 난 줄넘기를 하고 있었어… 모든게 다 괜찮았는데… 순간… 나도 모르게… 갑자기 다 부질없어 보였어
  • Winter Journey를 들으며 이제 그 길은 혼자 걸어도 괜찮은 길이라기 보다는 혼자 걸어야만 좋은 길이 된다.
  • 결승점까지 들어가면 아픔은 씻은듯이 사라졌으니까, 아이로써 출발선에서 뛰어나와 어른으로 결승점에 들어가는 법을 알게됐으니까…
  • 아픔과 고통의 경계선을 넘어서면서 어른들은 아이들과 헤어진다.

12/12/2018

GraphQL 채택 후 Netflix가 배운 것들

Netflix에서는 콘텐츠 인기도 파악과 같은 다양한 데이터 및 집계 데이터를 활용하여 관련성이 높은 광고를 제공한다. Netflix의 목표는 모든 외부 채널에 대해 광고가 사용자와 잘 어우러지게 만드는 것이다. Netflix는 보다 효율적으로 하기 위해 끊임없는 실험을 하고 있다.


Monet의 React UI는 Apache Tomcat에 의해 구동되고 REST API에 Access를 했다. 시간이 지나고 어플리케이션이 발전함에 따라서 사용 사례가 복잡해지기 시작했다. Simple page는 다양한 소스의 데이터를 가져와야 한다. 이 데이터를 클라이언트에서 효과적으로 로드하기 위해서 Backend 데이터를 비정규화 하는 노력을 시도했다. 그 이유는 모든 페이지가 모든 데이터를 필요로 하지 않기 때문에 유지하기가 어려워지기 때문이다. Network 병목 현상에 발생했다.

Backend에서 클라이언트에게 보내는 field의 수를 줄이는 방법은 모든 페이지에 대해서 endpoint를 만드는 것이었지만, 효율적이지 못했다. 대신 GraphQL을 Middleware로 선택했다. 이미 개발되어 사용중이던 Falcor도 훌륭한 솔루션이었지만 GraphQL의 Eco시스템을 이용하기 위해 Falcor가 아닌 GraphQL을 사용했다. 데이터 구조가 점차 그래프 지향적으로 변경됨에 따라 Network 병목도 해결했고, 기능을 더 빨리 추가 할 수 있게 되었다.


장점

NodeJS에서 GraphQL을 약 6개월 정도 사용하였고 개발 속도 및 페이지 로드 성능을 크게 향상시키는 것을 입증했다.

Redistributing load and payload optimization

GraphQL을 Middleware로 추가 할 때 GraphQL 서버는 Client가 직접 호출했을 때와 같이 동일한 서비스 및 REST API를 호출해야 했다. 대부분의 데이터가 동일한 DC내의 서버사이로 전달 되기에 이러한 Server to Server 호출은 대기 시간이 낮고 대역폭이 높기 때문에 브라우저에서 직접 네트워크를 호출하는 것에 비해서 약 8배의 성능이 향상되었다. GraphQL 서버에서 Client Browser의 데이터 전송 구간은 여전히 느린 속도지만, 단일 네트워크 호출로 축소시켰다. GraphQL을 사용하면 Client가 필요한 데이터만 취할 수 있기 때문에 REST API 에 비해 상당히 작은 Payload를 가져온다. Netflix의 Application에서 이전에는 10MB의 데이터를 가져온 페이지는 약 200KB를 받는다. Page load는 데이터가 제한된 모바일 네트워크에서 훨씬 빨라졌고 훨씬 적은 메모리를 사용한다.

Reusable abstractions

개발자는 일반적으로 단일 목적으로 하는 코딩보다 재사용이 가능한 추상 방식을 사용하기를 원한다. GraphQL을 사용하면 각 데이터를 한번 정의하고 시스템의 다른 데이터와의 연관성을 정의한다.

아래의 예제를 보면, GraphQL의 Entitiy를 Catalog, 주석과 같이 한번만 정의한다. 이 정의에서 여러 페이지에 대한 View를 정할 수 있다. Client App의 한 페이지는 다른 Client Page에 광고가 속한 Catalog를 모든 댓글과 함께 보기를 원한다고 하면 동일한 그래프 모델을 사용하면 Backend 서버의 코드를 변경하지 않고도 두가지 View를 수용할 수 있게 된다.


Chaining Type Systems

GraphQL에서 Entitiy를 정의하고 나면 자동 코드 Generater 도구를 사용하여 Client 어플리케이션의 TypeScript 유형을 생성한다. 이러한 유형과 Query는 서버 Schema에 대해서도 유효성이 검사 되기에 서버에서 발생한 모든 변경 사항은 데이터를 사용하는 Client가 알게 된다. GraphQL과 함께 여러 서비스를 묶고 이러한 검사를 Build Process에 연결하면 잘못된 코드를 배포하기 전에 더 많은 문제를 파악할 수 있다.


개발 단순화

Client 어플리케이션을 만들 때 공통적으로 고려해야 하는 사항은 UI/UX 이지만, 개발자 인터페이스와 개발자 경험은 유지 관리 가능한 어플리케이션을 빌드하는 것만큼 중요하다. GraphQL을 사용하기 전에는 새로운 React 컨테이너 구성 요소를 작성하기 위해 복잡한 로직을 관리하여 필요 데이터에 대해 요청을 해야했다. 개발자는 하나의 데이터가 다른 데이터와 어떻게 관련되는지, 데이터를 Cache하는 방법, 병렬 또는 순차적으로 호출할 지 여부, Redux에서 데이터를 저장할 위치 등을 고려해야 한다. GraphQL Query Mapper를 사용하게 되면 각 React 구성 요소는 필요한 데이터를 설명하기만 하면 되고 Wrapper는 이러한 것들을 처리하게 된다.

다른 장점

몇 가지 다른 이점이 있다. 첫째 GraphQL Query의 Resolver가 실패하면 성공한 Resolver는 가능한 많은 페이지를 Rendering하기 위해 Client에 데이터를 반환하게 된다. 둘째, Backend 데이터 모델은 CRUD 인터페이스를 제공하기 때문에 매우 간단하다. 마지막으로 GraphQL Query가 테스트를 위해 stub으로 자동 변환될 수 있고 React 구성 요소와 분리되어 Resolver를 테스트 할 수 있기에 구성 요소를 테스트하는 것이 더 쉬워진다.

진화

GraphQL로 마이그레이션은 단순한 경험이었고, 네트워크 요구 사항을 정의하고 데이터를 변환하기 위해 구축한 대부분의 인프라는 코드 변경없이 React 어플리케이션에서 NodeJS 서버로 쉽게 이전 할 수 있었다. 하지만 몇가지 장애물이 존재했다.

GraphQL의 Resolver는 다른 Resolver와 관련없이 독자적으로 실행되기 때문에 동일하거나 유사한 데이터에 대해 중복적으로 네트워크 요청을 하는 것으로 나타났다. 모든 Resolver가 끝날 때 까지 네트워크 응답을 메모리에 저장하는 간단한 Caching Layer를 Wrapping하여 복제를 해결했다. Caching Layer를 사용하여 단일 서비스에 대한 여러 요청을 모든 데이터 대한 대량 요청으로 할 수 있게 되었다. Resolver는 Fetch 프로세스를 최적하는 방법에 대해 고민하지 않고도 필요한 모든 데이터를 요청 할 수 있다.


GraphQL은 다른 서비스에 대한 네트워크 호출을 자동으로 조정하여 복잡성을 숨긴다. 디버그 flag가 활성화되면 디버깅을 쉽게 하기 위해 GraphQL Response Payload에 로그가 나타난다. Netflix는 Debug Flag를 활용하여 브라우저의 네트워크 탭을 통한 자연스러운 디버깅 방법을 고안했다.

Netflix의 경우 GraphQL 사용의 초기 단계에 있지만, 현재까지 진행한 사항으로는 긍정적인 경험이었다고 한다. Netflix가 GraphQL을 사용하는 핵심 목표는 시스템이 점차 정교해짐에 따라 개발 속도를 높이는데 도움이 될 것으로 보고 있고 복잡한 데이터 구조로 어려움을 겪지 않고 Graph Data Model에 투자하여 시간이 지남에 따라 팀의 생산성이 향상되는 것이라고 한다.

지난 기간 동안, 만들어 놓은 Graph Model이 강력하기에 일부 기능을 구현하기 위해 Graph를 변경하는 일은 없었다고 했고, 확실히 더 생산적이었다고 한다. 그리고 Schema stitching과 같은 개념을 사용하여 다른 서비스와의 통합을 수월하게 하고 개발 시간을 절약되길 기대한다고 한다.

현재 진행중인 프로젝트에서도 GraphQL에 대해서 테스트중이고, Netflix와 같은 효과가 생기길 기대한다.

References: https://medium.com/netflix-techblog/our-learnings-from-adopting-graphql-f099de39ae5f

12/10/2018

NetflixOSS Hollow

“모든 것을 효율적으로 Cache 할 수 있다면 게임 체인저가 될 수 있다.”


Netflix는 메타 데이터 Caching을 위해 Java로 작성된 범용 Cache인 Hollow를 OSS로 제공하고 있다.

일반적으로 소프트웨어 엔지니어들은 “빅데이터”라는 데이터를 보급을 요구하는 문제에 직면한다. 이런 유형의 문제는 다음과 같다.

  • 전자 상거래 사이트내 제품의 메타 데이터
  • 검색 엔진의 메타 데이터
  • 영화 및 TV 프로그램에 대한 메타 데이터

이런 문제에 직면할 때 일반적으로 아래의 두 가지 방법 중 하나를 선택한다.

  • Consumer의 원격 접근을 위해 데이터를 중앙 집중화하여 보관 (e.g. RDBMS, NoSQL, Memcached, Redis.,)
  • 데이터를 직렬화(e.g. json, xml)하고 Consumer에게 배포하여 사본을 보관

위에서 언급된 방법의 확장에는 여러 가지 문제점이 존재한다. 데이터를 중앙 집중화하면 데이터 집합이 무한히 커질 수 있지만,

  • 데이터와 상호 작용할 때 대기 시간 및 대역폭 제한이 존재
  • 원격 데이터 저장소는 데이터의 로컬 복사본만큼 신뢰할 수 있음

반면, 로컬 복사본을 전체적으로 직렬화하여 메모리에 저장하면 지연 시간이 늘어나고 주파수 Access가 훨씬 늘어날 수 있지만 이 접근법은 데이터 집합의 크기가 커짐에 따라 Scaling 문제가 존재한다.

  • 데이터 집합의 Heap 공간이 커진다
  • 데이터를 가져오려면 더 많은 비트를 다운로드 해야 한다.
  • 데이터를 업데이트하려면 상당한 CPU 리소스가 필요하거나 GC 동작에 영향을 미칠 수 있다.

엔지니어는 대부분 자주 Access하는 데이터를 로컬에 Cache하고 자주 Access하지 않는 데이터는 원격에서 가져오는 Hybrid 방식을 선택한다. 이 접근 방식에는 다음과 같은 문제가 있다.

  • 자료 구조는 상당한 Heap 공간을 소비 할 수 있다.
  • GC 행동에 부정적인 영향을 줄 수 있다.

Netflix에서는 로컬 Cache의 크기 조정은 많은 레코드의 원격 대기 시간과 더 많은 데이터를 로컬로 유지하는 Heap 요구 사항 사이의 조심스러운 조율이라는 관점으로 보고 있다.

Hollow는 Consumer에게 전체 읽기 전용 데이터를 메모리에 보관하는 기능을 제공한다. 부분 Cache에서 데이터를 업데이트하고 제거하는 결과를 회피한다.

Hollow를 사용하기전까지 Netflix는 Zeno를 사용했다. Hollow의 선구자인 Zeno는 크기가 제한되는 POJO(Plain Old Java Objects)로 데이터를 저장했다.


Hollow는 변화하는 데이터의 상태사이에 자동으로 delta를 생성한다. Consumer가 데이터 업데이트 상태를 유지하는데 필요한 노력을 최소화 시킨다. 또한 자동으로 데이터 중복을 제거하여 Consumer 데이터 셋의 Heap크기를 최소화 한다.

Hollow는 POJO 대신 데이터를 압축하고 고정 길이의 인코딩 방식으로 대체한다. 이 인코딩은 데이터 셋의 Heap 공간을 최소화하고 즉시 데이터에 Access하는데 드는 CPU 비용을 최소화하도록 설계 되었다. 인코딩 된 모든 레코드는 사용량이 많은 서버에서 GC 동작에 영향을 주지 않도록 JVM Heap에 풀링 된 메모리내의 재사용 가능한 slab에 저장된다.


Hollow는 여러 서버에 데이터를 분산하고 데이터 내구성을 위해 복제 알고리즘을 제공하지 않고 모든 Consumer가 모든 데이터를 사용할 수 있는 방법을 사용한다.

Hollow가 memcached와의 다른점은 아래와 같다.

  • Memcached의 주요 이점은 분산 Caching 시스템으로 많은 인스턴스에서 메모리를 풀링한다는 점이다. 그러나 Hollow는 분산된 Caching 시스템은 아니며, 여전히 중앙 집중화되어 있다. 데이터 관점에서는 각 시스템으로 Caching되기에 분산 시스템이라 볼 수 있다.
  • Hollow는 Netflix의 매우 높은 처리량에 대한 Cache 요구 사항을 충족 시키기 위해 제작되었다. Consumer에게 전체 데이터 셋을 복제한다는 것은 데이터를 수집하기 위해 네트워크 Hop을 만들 필요가 없으므로 데이터 셋의 어느 부분에나 Access할때 대기 시간이 거의 없음을 의미한다.
  • Hollow는 전체 데이터 집합의 폭에 Access하기 위해 CPU 비용을 줄이는데에 중점을 두고 있다. Memcached와 같이 느슨한 형식의 key/value 저장소와는 달리 구조화된 데이터 모델을 요구하면 Access 비용 문제를 한번에 해결 할 수 있다.
  • Hollow는 파일 저장소를 제공한다. S3, NFS, FTP도 가능하다. Consumer는 데이터 저장소의 전체 Snapshot을 읽고 데이터 셋을 메모리로 Boot Strap한다. 데이터 셋은 Delta 적용을 통해 메모리에 최신 상태로 유지된다. 각 Consumer의 메모리 내 사본은 일시적이다. 시스템 Restart시 BLOB 저장소에서 Snapshot을 다시 검색해야 한다.
  • Blob 파일의 형식은 간단하다. 메모리내의 Layout과 거의 동일한 구조이기에 데이터를 초기화하는 작업은 Blob to 메모리로 복사하듯이 이루어지며 신속하게 수행된다.

그외 Hollow에 대한 궁금증을 아래에 정리했다.

CAP 이론에 담긴 우려 사항을 해결 할 수 있는지? 간헐적인 네트워크 연결 문제가 발생했을때 오래된 데이터로 작업이 가능한지?

  • Consumer는 각각 메모리에 데이터 셋의 전체 복사본을 가지고 있기 때문에 가용성은 타의 추정을 불허한다.
  • 일관성에 대해서는 변화하는 데이터 셋에 대한 Timeline을 개별 데이터 상태로 분해해야 하며, 각 상태는 특정 시점의 데이터에 대한 완벽한 Snapshot을 의미한다.

Hollow는 주로 작은 메타 데이터에서만 활용되는 것인가? Local 서버의 메모리 리소스가 고갈 된 경우는 어떻게 되는가?

  • Hollow는 주로 중소 규모의 데이터 세트를 대상으로 한다. Hollow는 Tera Byte, Peta Byte가 아닌 Mega byte, Giga byte에 대한 경험을 제공한다. 일반적으로 JSON형태의 문서 저장소보다 Hollow의 인코딩을 활용하여 저장할 경우 사용하는 용량이 훨씬 작다. 그래서 Tera Byte이상의 데이터 셋을 중형 데이터 셋으로 전환 하는 것을 고려할 수 있다.
  • 데이터 모델링이 중요하다. 데이터가 구조화 되는 방식은 Holloww가 데이터 집합을 중복 제거 할 수 있는지, 압축률이 어떤지에 따라 영향을 미친다. 일반 압축 알고리즘은 허프만 트리를 사용하여 데이터의 패턴을 찾는 반면 Hollow는 데이터 모델의 코드 구조를 사용하여 패턴을 지정한다.

POJO에서 멀어지는 전략은 어떤 효과가 있는가?

  • Hollow의 경우 중복 제거, 인코딩, 패킹 및 Java 객체의 Overhead 제거와 같은 다양한 방식으로 압축을 수행한다. 중복 제거의 방법과 범위는 주로 Zeno에서 가져왔지만, POJO에서 벗어나지 않으면 인코딩, 패킹 및 Object Overhead 제거가 불가능했다.
  • Hollow는 데이터 셋의 데이터에 Access할때 CPU 영향을 최소화하고 해당 데이터를 저장하는데 필요한 Heap 공간을 최소화해야 했다.

비 Java 어플리케이션이 Hollow를 활용할 수 있는가?

  • 비디오 메타 데이터용 시스템은 JVM 기반 언어를 사용하여 제작되었기에 Java용 Hollow를 구축했다. 비 JVM 기반 언어는 현재 Hollow를 활용할 수 없다.

참고: https://github.com/Netflix/hollow

12/09/2018

스마트 시대에 헌책방이 공존할 수 있는 이유

 


종종 헌책방에서 책을 사기도 한다. 우연히 들려 마음에 드는 책을 사는 경우가 보통이었고, 그렇게 내손에 잡힌 책에서 타인의 흔적을 발견하는 것이 헌책을 사는 것에 대한 매력이었다. 헌책방은 추억을 사고파는 곳이다.

헌책방에서 주로 사는 책은 유행(세월)을 타지 않는 책이다. 가치가 있는 책은 오래되고 낡아도 관계가 없다. 좋은 책인지 아닐지는 감으로 알 수 있다.

그렇게 구매한 책은 다 읽고나서도 내곁을 떠나지 않는 것이 대부분이다. 반면 자기 계발서 같은 책은 내손을 쉽게 떠났다.

요즘은 예스24, 알라딘 처럼 큰기업이 중고 서점을 오픈하고 운영중이다. 그리고 멀지 않은 거리에 대형 서점이나 도서관이 즐비하다.

하지만 이런 곳에서 쉽게 찾을 수 없는 책들이 있다. 결국 이 경우에는 마지막으로 헌책방에 갈 수 밖에 없다. 쉽게 구할 수 없는 책들이 모이는 곳이 헌책방이니까…

12/06/2018

PaaS vs. CaaS

 

PaaS

PaaS가 나오기 전에 개발팀은 개발한 어플리케이션에 대해서 인프라를 구축하고 유지해야 했다. PaaS는 어플리케이션이 실행되는 플랫폼을 제공하기에 개발자에게는 전례없는 민첩성을 제공했다.

PaaS는 생산성을 향상 시켰지만, 개발자의 선택을 제한 시켰다. 그러나 이런 제약에도 불구하고 인프라를 구축하고 유지해야 했던 기존 단점을 상쇄시키기에 충분 했기에 오랜 기간동안 많은 기업에서 선호했었다.

강점

  • 개발자에게 작업에 대한 오버 헤드가 발생하지 않음, 개발자는 코드만 집중할 수 있고 어플리케이션은 자동으로 배포됨
  • 12 factor 어플리케이션에 적합

단점

  • 기본적으로 Stateless 어플리케이션만 지원
  • 벤더를 기준으로 Resource가 제한 될 수 있음
  • 사용 편의성이 유연성을 희생 시킴
  • 많은 PaaS 제공 업체가 Enterprise에서 진전을 이루지 못한 이유는 제공하는 모델이 제한적이기 때문, 수 Peta byte의 데이터를 가진 수잭 개의 어플리케이션을 관리하는 조직의 경우 동그란 구멍에 정사각형 구멍을 맞추기 위해 비즈니스를 크게 변경하지 않고 모든 것을 관리할 수 있는 팀을 만드는 것이 효율적

CaaS

Container의 출현으로 PaaS를 무용지물로 탈바꿈 시켰다. Container를 사용하면 개발자가 어플리케이션 구성 요소를 쉽게 설명하고 Container 이미지를 작성할 수 있다. 이런 방식으로 구축 된 Container 이미지는 Middleware 또는 가상화 계층없이 모든 시스템에서 원할하게 실행되는데 필요한 모든 기능을 갖추고 있다. 따라서 일반적인 가상화 시스템보다는 효율적이다.

Container와 같은 기술을 사용하면 어플리케이션이 플랫폼에 독립적으로 된다.

강점

  • 복잡한 엔터프라이즈 배포
  • Stateful and Stateless 어플리케이션 모두 이용 가능
  • Orchestration 지원
  • Container를 사용하여 Public Cloud로 Lift & Shift
  • VM 관리 대비 Container는 수백개가 존재해도 관리 할 운영체제는 단 하나

단점

  • 개발자가 어플리케이션을 배포하기 위한 작업을 숙지해야 함 (PaaS와 비교하여 자동화된 DevOps 지원이 부족)

PaaS의 미래

Container는 PaaS를 만들게 된 문제에 대해서 새로운 해결책을 만들었다. Container는 개발자가 PaaS를 사용하여 수행했던 많은 협약에서 자유롭게 해줄 것을 약속한다. 예를 들어서 Container 관리툴을 사용하여 어플리케이션을 배포할때 원하는 언어로 코드를 작성하고 원하는 구성 요소를 사용할 수 있지만, PaaS는 일반적으로 몇 가지 언어와 구성 요소로 제한한다.

Container도 PaaS와 마찬가지로 운영 관점에서 관리가 필요하다. Container 관리 소프트웨어는 Container Deploy, Monitoring 및 관리를 위한 서비스를 제공함으로써 고정적 제약없이 PaaS가 할 수 있는 모든것을 할 수 있다.

현재 PaaS를 사용하고 있는 일부 회사에서는 PaaS를 유지할 수 도 있다. 그러나 Container는 어플리케이션을 간단하고 다양한 프로세스로 제공하기에 많은 회사들이 Container로 전향을 한다.

Why Kubernetes?

Kubernetes는 AWS, Azure, GCP 또는 Private에서의 실행 여부에 관계없이 어디서나 실행할 수 있고, 동일하게 작동한다.

Kubernetes는 PaaS가 아니며 PaaS를 구축하기 위한 기반이고, 커뮤니티에 의해 Kubernetes를 둘러싼 도구 및 애드온이 많이 생기고 있다.

모듈성을 통한 관리 향상

Container를 사용하면 어플리케이션을 명확하게 분리하여 더 작게 분해 할 수 있다. 개별 Container 이미지에 제공되는 추상화 계층을 통해서 분산 어플리케이션을 구축할 수 있다. 이런 모듈식 접근 방식은 의존성을 격리하고 작은 구성 요소를 잘 조율하게 광범위하게 사용할 수 있다.

그러나 이런 부분은 Container 만으로 달성 할 수 없다. 통합하고 조율하는 시스템이 필요하고 Kubernetes는 단일 어플리케이션으로 제어 되는 Container Collection in Pods를 사용하여 지원한다. Container는 파일 시스템, Kernel name space 및 IP주소와 같은 자원을 공유함으로써 너무 많은 기능을 하나의 Container 이미지로 만드는 유혹을 제거한다.

배포 및 업데이트

Kubernetes 배포 컨트롤러는 여러가지 복잡한 관리 작업을 단순화 한다.

  • Scalability: Pod를 수평 확장 방식으로 배포 할 수 있고, 언제든지 확장/축소가 가능하다.
  • Visibility: Status Query기능을 사용하여 프로세스 및 실패한 배포를 식별한다.
  • Time savings: 언제든지 배포를 중지하고 다시 시작할 수 있다.
  • Version control: 최신 버전의 어플리케이션 이미지를 사용하여 배포 된 Pod를 업데이트하고 현재 버전이 안정적이지 않을 경우 이전 배포로 Rollback할 수 있다.

References:

  • https://dzone.com/articles/paas-or-container-services-which-one-is-right-for

12/04/2018

AWS Outposts

AWS는 지난 수년간 Amazon VPC(Virtual Private Computing), AWS Direct Connect와 Amazon Storage Gateway와 같은 서비스를 제공하여 AWS와 함께 사내 구축형 데이터 센터를 손쉽게 실행할 수 있도록 지원해왔다. 2017년에는 VMware와 공동 작업을 통해 AWS에 VMware Cloud를 도입하여 VMware 가상화 기업의 대다수가 AWS에 쉽게 인프라를 관리 할 수 있도록 VMware 도구도 지원하고 있다.

이런 지원에도 불구하고 고객들은 일부분은 사내 데이터센터에 머물기를 희망하고 있었다. 그리고 AWS는 현재 많은 회사들이 여전히 사내에 머물고 싶어한다는 점을 인정했다.

AWS Outposts는 AWS Computing 기반의 Rack에 Amazon EC2(Amazon Elastic Compute Cloud), Amazon EBS(Amazon Elastic Block Store)와 같은 서비스를 실행 할 수 있도록 제공함으로써 이러한 문제를 해결한다. Amazon Outposts는 두가지 Option을 제공한다.

  • VMware Control Plane과 API를 사용하여 인프라를 구성하고자 하는 고객은 AWS Outposts에서 VMware Cloud를 로컬로 실행 할 수 있다. AWS Outposts의 VMware Cloud Option은 On-Premise에서 실행되고 AWS의 VMware Cloud와 동일한 console에서 서비스를 관리할 수 있다.
  • AWS Cloud에 익숙한 고객은 On-Premise에서 AWS Outpost의 AWS Option을 사용할 수 있다. 즉, On-Premise와 Cloud에서 같은 방식으로 관리할 수 있게 된다.

두 경우 모두 AWS는 고객에게 Rack을 제공하고, 고객이 원하는 경우 설치하고, Rack의 유지 보수 및 교체를 모두 처리하게 된다. AWS Outposts는 고객의 Amazon VPC의 연장이며 고객은 AWS Outposts에서 AWS 또는 기타 AWS 서비스의 나머지 어플리케이션과도 원할하게 연결할 수 있게 된다.

AWS의 경우 고객이 AWS가 사용하고 있는 것과 동일한 하드웨어, 동일한 인터페이스, 동일한 API를 사용하여 On-Premise AWS 환경에서 AWS또는 VMware Cloud로 확장하길 원한다고 언급했고, 최신 AWS 기능을 즉시 사용할 수 있어야 하며 하드웨어나 소프트웨어를 고려하고 싶지 않다고 했다. 그래서 AWS는 Hybrid mode에서 실행될 때 고객이 실제로 원했던 것을 재해석하기 위해 AWS Outposts를 개발했다고 말했다.

Google 그리고 Amazon도 On-Premise 시장에 진출을 시작했다. 이미 시장 저변에 깔려있는 VMware라는 우군과 함께…

이 상황에서 국내 Cloud 사업자들은 어떤 전략을 펼칠 것인지 궁금하다. 가장 무서운 점은 익숙함이라는 무기이다. AWS Cloud를 사용했던 익숙함을 경험한 고객의 선택은 무엇일까?

12/01/2018

우버의 요금 정책

Uber는 스마트폰 기반 차량공유 플랫폼 서비스를 제공하고 있고 전통적인 택시 시장을 위협하고 있다. 특히 우버는 기존 운송 업체에서 사용하지 않는 Surge Pricing이라는 탄력 요금 전략을 사용하고 있다. 택시의 고질적인 문제점은 송년회 및 회식이 많은 연말이나 특별한 날 소비자의 수요가 많을 때에 택시를 잡기 어렵다는 것이다. 우버는 많은 사람들이 택시를 이용하는 시간대에 가격을 인상하는 정책을 도입했다. 이 전략은 차량 드라이버들에게 단기적인 인센티브 제공 효과가 있기에 많은 사람들이 택시 서비스를 이용하는 시간에 짧게 돈을 벌고 싶어하는 드라이버들을 유도할 수 있다고 봤고 수요가 몰리는 시간에도 많은 운송 서비스를 제공할 수 있다고 생각했다. 하지만 2011년 뉴욕의 새해 맞이 전날 밤 우버가 소비자에게 청구한 요금은 평상시의 8배에 달했고, 우버에 대해 소비자들이 불만을 쏟아내기 시작했다. 이런 비난에도 불구하고 우버는 이런 요금 정책을 포기하지 않고 있다. 경제학자들은 우버의 요금 정책에 동의한다. 수요와 공급이 달라질 때 가격 차별을 통해 균형을 찾으면 소비자들도 효용을 본다. 라는 것이다.

정말 Surge Pricing이 전략이 플랫폼과 소비자에게 도움이 될까? 라는 의문이 생겼다.

아래의 그래프는 드라이버가 반응하는데까지 걸리는 시간이 가격 변화와 어떤 연관이 있는지를 보여 준다.


아래의 그래프는 U st.나 K st.에서 Surge 가격이 더 높을 경우 Navy Yard의 소비자가 픽업을 위해 더 많이 기다려야 한다는 것을 나타낸다. 즉, 가격이 어느 한 지역에서 더 높을 경우 인접한 지역의 드라이버 공급을 감소 시킨다는 것이다.


수요를 맞추기 위한 Surge Pricing 정책이 인접 지역의 드라이브를 감소 시키는 결과가 나타난다. 수요가 몰리는 지역에서의 가격 인상은 드라이버가 다른 지역으로 이동한다는 것을 나타내고 다른 지역은 오히려 공급이 없는 상태가 된다. 결국 공급이 없는 지역 또한 드라이버를 구하기 위해 Surge 가격이 반영되어야 한다는 의미다. 이것이 소비자에게 도움이 되는 것일까? Surge Pricing이 적용되는 지역의 소비자와 드라이버만 이득을 볼 것이다. 소비자는 돈을 더 많이 지불해야겠지만, 돈과 시간의 가치의 중요도는 소비자의 판단이기에…

결국, 플랫폼은 공급자(드라이버), 소비자(승객)를 플랫폼 사업자(우버)가 연결해줌으로써 상호 작용이 되어야 한다. Surge Pricing 정책은 고정 가격보다는 상호간에 이득이 되는 것은 분명하다. 수요가 몰리때에 가격이 오를 수 있지만, 수요가 몰리지 않는 시간대에서는 저렴한 가격으로 이용할 수 있기 때문이다.

플랫폼이 성공적으로 성장하기 위해서는 공급자와 소비자 양측에 끊임없이 높은 가치를 제공해줘야 한다. 그래야 사람들이 지속적으로 모이기 때문이다.

참조: https://www.washingtonpost.com/news/wonk/wp/2015/04/17/how-uber-surge-pricing-really-works/?noredirect=on&utm_term=.c2ad3fc1e4a1

11/28/2018

Istio & Envoy에서 OpenTracing 사용 하기

Sidecar Proxy는 코드 삽입없이 모니터링 데이터를 얻는 매우 간단한 방법을 제공한다. Tracing은 대규모 분산 시스템에서 가장 어려운 부분이기 때문에 Sidecar Pattern은 큰 이점으로 작용한다.

Sidecar Proxy에서 Tracing을 하기 위해서는 Inbound에서 Outbound 요청으로 일부 Header를 전달해야 한다. Application단에서는 매우 간단하지만 전달받은 Header를 넘기는 로직을 처리하면 불편 할 수 있다. 비즈니스 레이어에서 Header를 전달하는 것을 조정한다고 상상해보면 Sidecar Pattern을 사용하는 이점이 없을 수 도 있다.

Tracing은 Envoy만 사용

Header 전달이 기존 Application 코드에서는 아래처럼 작성된다.

@RestController
public class HelloController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/hello")
public String hello() {
return "Hello from Spring Boot!";
}
@RequestMapping("/chaining")
public String chaining(@RequestHeader HttpHeaders headers) {
HttpHeaders tracingHeaders = new HttpHeaders();
extractHeader(headers, tracingHeaders, "x-request-id");
extractHeader(headers, tracingHeaders, "x-b3-traceid");
extractHeader(headers, tracingHeaders, "x-b3-spanid");
extractHeader(headers, tracingHeaders, "x-b3-parentspanid");
extractHeader(headers, tracingHeaders, "x-b3-sampled");
extractHeader(headers, tracingHeaders, "x-b3-flags");
extractHeader(headers, tracingHeaders, "x-ot-span-context");
ResponseEntity<String> response = restTemplate
.exchange("http://spring-boot:8080/hello", HttpMethod.GET, new HttpEntity<>(tracingHeaders), String.class);
return "Chaining + " + response.getBody();
}
private static void extractHeader(HttpHeaders headers, HttpHeaders extracted, String key) {
List<String> vals = headers.get(key);
if (vals != null && !vals.isEmpty()) {
extracted.put(key, Arrays.asList(vals.get(0)));
}
}
}

위의 코드상에서는 특별한 것은 없다. 하지만 코드상에 header 정보를 set하기에 변경이 생기면 리팩토링이 필요할 수 도 있다. 그리고 코드에 header 정보를 set하기에 잊어버릴 가능성도 존재한다.

Envoy and OpenTracing

OpenTracing의 일부 기능을 어플리케이션에 추가 한다. Spring Boot는 classpath에 jar를 추가하는 것만으로도 구현이 가능하다. Auto Configuration은 개발자가 개입하지 않아도 필요한 Tracing Code를 어플리케이션에 추가합니다.

OpenTracing은 Vendor 중립적이기에 Tracing 구현을 제공해야 한다. 이 경우 일반적으로 jaeger-java-client를 사용하게 된다. 끝으로 Tracing Bean을 Instance화하고 구성해야 한다. Envoy는 기본적으로 Jaeger에서 활성화되지 않고 명시적으로 등록되어야 한다.

@Bean
public io.opentracing.Tracer jaegerTracer() {
Builder builder = new Builder("spring-boot",
new RemoteReporter(new HttpSender("http://jaeger-collector.istio-system:14268/api/traces"), 10,
65000, new Metrics(new StatsFactoryImpl(new NullStatsReporter()))),
new ConstSampler(true))
.registerInjector(Builtin.HTTP_HEADERS, new B3TextMapCodec())
.registerExtractor(Builtin.HTTP_HEADERS, new B3TextMapCodec());
return builder.build();
}

Istio, Jaeger 및 어플리케이션을 kubernetes에 배포한다. 배포가 완료되면 /chaining endpoint에 요청을 할 수 있다.


Proxy 범위에 적용되는 Timeout 규칙은 두 가지이다.

첫번째는 Proxy Client의 지속 기간이 원래 지속 기간보다 항상 짧아야 한다.

두번째는 첫번째와 반대이며 Proxy Server 기간이 항상 길어야 한다.


span과 관련된 로그 내에서 어떤 컨트롤러 메소드가 호출되었는지 확인할 수 있다.

Envoy만 Tracing하면 설치가 매우 간단해진다. OpenTracing을 사용하면 이 작업을 자동으로 할 수 있으며 모니터링되는 프로세스에 대한 가시성을 높일 수 있다.