Software Development

Data Infrastructure @ LinkedIn

QCon London 2012에서의 Siddharth Anand의 강연입니다.

Data Infrastructure @ LinkedIn by Siddharth Anand

Siddharth Anand는 작년 7월에 열린 QCon London 2011에서 NoSQL @ Netflix라는 제목의 강연을 한 적이 있었는데, 1년 새 Netflix로부터 LinkedIn으로 옮긴 모양이군요.

강연의 제목대로 이 강연은 LinkedIn의 데이터 기술에 대해서 다루고 있습니다만, 특히 데이터베이스와 데이터의 복제 기술에 대해서 다루고 있습니다.

Read Scalability & Write Scalability

LinkedIn은 현재 Oracle을 주 데이터베이스로 사용하고 있으며, 사용자가 LinkedIn에 제공한 데이터 – 사용자의 프로필, 관계들은 모두 이 곳에 저장된다고 합니다. 이 데이터를 가공하여 생성된 2차 데이터들은 목적에 따라 여러 종류의 스토리지를 활용하고 있는 것으로 보입니다.

서비스의 규모가 커지면 물론 Oracle 성능의 Scalability가 문제가 되는데, 이를 Read Scalability와 Write Scalability의 문제로 나누어서 설명하고 있습니다.

Read Scalability는 Oracle Slaves나 Memcached, Voldemort 등의 복제나 캐시 스토리지를 활용하고 있고, Write Scalability는 Oracle이 동작하는 하드웨어를 업그레이드하거나 다른 기술 (예를 들어, Cassandra)을 사용하는 방법 밖에는 없다고 얘기합니다.

Oracle Slaves

Oracle Slaves의 경우, 문제는 결국 Master에 쓰여진 데이터와의 consistency가 문제가 되는데, LinkedIn에서는 writer에게는 그 다음에 따르는 read를 보장하고, 다른 reader들에게는 eventual consistency를 허용하고 있습니다. 이를 위해서 사용하는 메커니즘은 다음과 같습니다.

데이터 도메인별로 데이터에는 변경시점을 나타내는 timestamp를 가지고 있는데, 클라이언트로부터의 write는 항상 master에 대해 발생하며, 이 때 timestamp를 변경하면서 이 timestamp를 자신의 context에 보유하고 있습니다. 클라이언트가 read를 할 때는 먼저 slave에 대해 read 액세스를 하되, 읽어 들인 timestamp와 자신이 보유하고 있는 timestamp를 비교하여, 만약 자신이 보유하고 있는 timestamp가 더 작다면 master의 데이터를 읽습니다.

이러한 메커니즘이 Oracle에서 직접 지원되는 기능인지 inhouse에서 만든 클라이언트 라이브러리와 별도의 필드를 이용해 구성한 메커니즘인지는 정확히 모르겠습니다만, 비교적 간단한 방식으로 replication 방식의 gap 문제를 극복하고 있군요. 하지만, consistency가 항상 중요한 데이터라면 이러한 방식은 사용할 수 없기 때문에, 결국 consistency 요구사항에 대한 정확한 파악이 필요하다고 할 수 있습니다.

Voldemort

Voldemort는 Dynamo paper에 기반해 만들어진 분산 스토리지로, NoSQL이라는 키워드의 역사로 따지자면 선조격에 해당한다고 볼 수도 있겠네요. 이 글에서는 Dynamo에 관한 얘기는 생략하도록 하겠습니다. 이 후에 만들어진 Dynamo 계열의 스토리지인 Riak, Cassandra 등을 선택하지 않은 이유는 단지 Riak이나 Cassandra는 스토리지 기술을 선택할 당시 (2008년)에 존재하지 않았다고 하는군요.

다른 Dynamo 계열 스토리지에 대비해 Voldemort의 특징은 Layered Pluggable Architecture라고 하는데요. Conflict Resolution, Serialization, Repair Mechanism, Failure Detector, Routing 등의 Layer들을 필요에 따라 클라이언트 또는 서버 측으로 배치할 수 있다고 합니다. 현재 LinkedIn에서는 대부분의 기능을 클라이언트에서 수행하도록 구성 (fat client 방식)하고 있지만, 이들을 서버쪽으로 옮겨놓고자 (fat server 방식) 한다고 합니다.

Storage Engine도 필요에 따라 선택해서 사용할 수 있는데, Read-Write 저장소에는 BDB JE 스토리지 엔진을 사용하고 있고, Read-Only 저장소에는 커스터마이즈된 스토리지 엔진을 사용하는데, key는 원래의 key나 key의 MD5, value는 파일의 형태이되, 메모리 맵 인덱스 (offset의 index)를 통해서 필드를 액세스할 수 있도록 한다고 합니다.

LinkedIn에서는 Voldemort를 fault tolerant한 분산 memcached와 같이 생각한다고 합니다. Read-Only 저장소에 저장되는 데이터는 Hadoop을 통해서 생성된 데이터를 Voldemorts가 로드하는 배치를 통해 생성된다고 합니다.

DataBus: Timeline-Consistent Change Data Capture

DataBus는 LinkedIn에서 데이터를 복제하거나 2차 데이터를 생성하기 위한 주요 인프라라고 할 수 있습니다. Oracle master로의 write는 DataBus가 모두 복제하고 이를 검색 인덱스, 그래프 인덱스, replica, Standardization 서비스 등으로 보낸다고 합니다.

DataBus Architecture

DataBus는 Relay 서비스와 Bootstrap 서비스의 2가지로 이루어져 있는데, Relay는 Shard를 통해 분산되어 있고 Oracle로부터 받은 트랜잭션 – 트랜잭션을 통해 변경된 레코드 데이터 전체를 메모리 상에서 버퍼링하며, Avro로 인코딩해서 Bootstrap을 포함한  다른 스토리지로 전달하는 역할을 합니다. Bootstrap은 이러한 트랜잭션들을 저장해서 임의의 시점으로부터의 변경사항 (Consolidated Delta) 또는 특정 시점의 스냅샷 (Consistent Snapshot)을 제공할 수 있습니다. “arbitrary long lookback”이라고 부르는 기능인데요. DataBus의 Relay를 통해 트랜잭션을 수신하는 클라이언트가 재시작이나 실패 등으로 수신을 하지 못하는 상황이 벌어졌을 때, 새로운 클라이언트가 데이터를 얻어야 할 때 필요한 기능들이 아닐까 싶습니다. Bootstrap은 Log Storage와 Snapshot Storage로 구성되어 있고, Log Writer가 Log Storage에 write하고 Log Applier가 Snapshot Storage에 log를 적용하는 방식입니다.

SCN을 통해서 커밋 순서에 따른 전송 (in-commit-order delivery)을 보장한다거나 ‘arbitrary long lookback’과 같은 기능을 제공하는 것은 꽤 강력한 기능들인 것 같습니다. 반면에 Bootstrap의 데이터는 복제가 없기 때문에 데이터의 지속성 (durability)에 대해 취약한 면은 있는 것 같습니다.

Kafka: High-Volume Low-Latency Messaging System

Kafka는 기본적으로 일반적인 메시지큐라고 할 수 있는데, DataBus의 application-level 데이터 스트림, 사용자들의 행동 추적, 네트워크나 시스템의 메트릭 전송 등에 사용하고 있다고 합니다.

메시지큐의 topic (큐라고 생각하면 됩니다)은 sequential write로 쓰여지는 로그 방식의 파일이고, consumer는 이를 pulling 방식으로 가져갑니다. 그리고 topic들은 partition되어 있는데, 이들의 관리는 ZooKeeper가 담당합니다. sendfile을 이용한 zero copy와 같은 tuning들이 되어 있고, 자체적인 cache 없이 OS page cache에 의존한다고 합니다. 메시지의 전송 여부에 대한 기록은 없으며 단순히 일정 시간이 지나면 파기하는 방식이라고 합니다.

Secondary Index

NoSQL은 간단한 동작 방식 (semantic)을 통해 기존의 관계형 데이터베이스들에 비해서 가용성이나 성능을 높이는 것에 초점을 맞추고 있는데, Siddharth Anand는 secondary index를 NoSQL에 접목시키는 순간 복잡한 시스템이 되어버리고 애초의 장점을 잃는다고 얘기합니다. 따라서, DataBus와 같은 것을 이용해 비동기적으로 secondary index를 유지하는 방식을 선호한다고 얘기합니다. 클라이언트가 2군데 이상의 스토리지에 write를 하는 동기적인 방식에 대해서도 비판적으로 얘기합니다. 데이터의 불일치 문제 등에 대해서는 Netflix에서도 이를 해결하기 위한 reconcilation job이 존재했었고, 지인에게 듣기로는 Google에서도 비슷한 작업이 많이 있다고 합니다.

Closing

이 강연에서 가장 인상적인 것은 DataBus 였습니다.

  • 변경 사항을 실시간으로 제공하면서 변경 사항의 이력과 스냅샷을 제공하는 시스템
  • 어떤 이벤트에 대해서 수행해야할 여러가지 작업을 효과적으로 분산하는 메시지 전송 시스템

Oracle의 트랜잭션을 복제하는 것은 아주 오래전부터 캐싱을 위해서 활용하는 방법이기 때문에 새롭다고 하기는 힘들지만, 이력과 스냅샷을 제공하는 시스템으로 만든 것 하나만으로 유용성이 굉장히 높아지는 것 같습니다. 그리고, 이러한 방식 자체는 스토리지의 복제 뿐만 아니라 변화의 추적과 동시에 전체 데이터의 동기화를 필요로 하는 여러가지 장소에 활용될 수 있는 것 같습니다. 예를 들어,

  • 스마트 클라이언트의 동기화를 위한 서버 시스템: 스마트폰과 같이 로컬 스토리지를 가지고 있는 디바이스는 서버의 변경사항을 지속적으로 수신하면서도 서버의 데이터 전체를 받아야하거나 서버와의 동기화를 필요로하는 시점도 필요합니다. 이 때 서버에서는 이에 적합한 저장 방식을 보유하고 있어야 합니다.
  • 이종 스토리지 사이의 복제: Redis의 복제는 Redis의 특성상 lookback이 존재하지 않습니다. 즉, Redis slave로부터 master로의 접속이 한순간이라도 끊기면 모든 데이터를 다시 받아야 합니다. Redis-Redis 사이에서는 크게 문제가 안될지 모르지만, Redis-MySQL이나 Redis-HBase가 필요하다면 단순히 replication 프로토콜을 구현하는 것만으로는 해결되지 않습니다. 이런 경우에 유용하게 사용할 수 있습니다. MySQL을 예를 들면, 위의 Redis와 같은 문제를 해결하기 위해 binlog를 master쪽의 디스크에 저장하고 있습니다만, 당연히 master의 트랜잭션에 방해가 되거나 디스크의 용량을 크게 차지하기 때문에 이를 외부로 돌릴 수 있다면 메모리 상의 트랜잭션 로그나, 최소한의 binlog를 유지할 수 있게 되어 유용할지도 모르겠습니다.

반복되지만 스토리지 아키텍쳐의 구성에 대해서도 역시 계속 곱씹을 여지를 주는 것 같습니다.

  • 서비스에서 가장 핵심이 되는 데이터는 그 자체로는 Scalability에 한계가 있더라도 Oracle과 같은 신뢰성이 높은 스토리지를 이용한다.
  • 신뢰성이 높은 스토리지가 존재하고 이로부터의 트랜잭션을 순서대로 제공할 수 있는 기능만 있다면 비교적 단순한 구조 하에서 Eventual Consistency를 성취하는 것은 그리 어렵지 않을지도 모른다.
  • 사용자 입장에서 Loose한 Consistency를 제공하더라도 문제가 없는 데이터를 식별한다.
  • 데이터의 불일치에 대해서 수정하는 작업이 필요하다.

데이터 복제의 문제만 하더라도 일반적인 노드 사이의 복제, 클라이언트로부터의 quorum write, Proxy 등 여러가지 방법을 고민하고 있는데, 정말 쉬운 문제는 아니로군요.

한편, 강연에서 현재 LinkedIn에서 개발하고 있고 몇개월 내에 완성될 예정인 Espresso라는 key-value 스토리지에 대한 언급이 나오는데, 어떠한 목적을 가지고 만드는 것인지 궁금하네요. 어서 볼 수 있었으면 합니다.

Data Infrastructure @ LinkedIn 더 읽기"

Building Highly Available Systems in Erlang by Joe Armstrong

QCon London 2012에서의 Joe Armstrong의 강연입니다.

Building Highly Available Systems in Erlang by Joe Armstrong

Joe Armstrong은 에릭슨에서 일하던 1986년에 Erlang의 초기 버전을 개발했으며, Erlang OTP 프로젝트의 Chief Architect였습니다. Erlang은 1998년 open source로 나오기 전에는 에릭슨의 proprietary 언어로 개발 되었기 때문에 Erlang의 창시자라고 불러도 될지는 조금 애매하기는 하지만, 소위 Programming XXX라는 책 – Programming Erlang (2007)의 저자로서 그렇게 불러도 큰 문제는 없지 않을까 싶습니다. 2003년 PhD thesis로 Making reliable distributed systems in the presence of software errors이라는 논문을 내놓았는데 이 역시 Erlang에 관한 내용이고, 현재도 Erlang에 관련한 활동을 활발히 하고 있는 것 같습니다. Erlang의 역사에 대해서 좀 더 알아보기는 해야겠지만, 이런 것들만 보아도 꽤나 재미있는 이력이라고 생각합니다.

6 Rules

먼저 Redundancy, Consistent Hashing과 Chord의 Quorum System에 대해 간략하게 설명하고, Reliable Data Storage의 문제는 알고리즘 차원에서는 이미 풀렸다라고 선언합니다. 100% 납득이 가는 것은 아니지만, 그렇다고 인정하고 넘어간다면 그 다음엔 이 개념들을 어떻게 구현 – 코딩할 수 있을 것인가에 대해서, 6가지의 룰을 설명합니다. 결국 이러한 6가지 룰을 – 프레임워크나 라이브러리가 아니라 – 프로그래밍 언어 차원에서 구현한 언어가 바로 Erlang이라고 얘기하는 흐름이라서 조금 힘이 빠지는 느낌이 드는 것은 사실입니다.

1. Isolation

모든 것이 격리되어있다면, 더 많은 컴퓨터가 투입될 수록 시스템의 실패 확률은 점점 낮아질 수 있다는 얘기입니다. 이를 통해 10 nines도 실현 가능하다고 얘기합니다. Joe Armstrong은 Erlang 프로세스들이 공유하고 있는 문맥이 없다는 점으로 설명합니다. Erlang 프로세스들은 VM위에서 동작하는 가벼운 프로세스 (light-weight process)들로 일반적인 프로세스들처럼 메모리를 공유하고 있지 않습니다.

2. Concurrency

세상의 대부분의 문제들은 생각보다 병렬적(parallel)이고, 2대 이상의 컴퓨터를 제공함으로써 병행성(concurrent)을 확보할 뿐만 아니라 분산(distributed)된다고 얘기합니다. Erlang의 프로세스 얘기로 다시 돌아가면, 이론적으로 모든 Erlang 프로세스들은 병렬적으로 동작하고, 여러 core로 퍼져서 실행된다고 합니다.

3. Fault Detection

실패의 탐지를 위해서는 3대의 컴퓨터가 필요하다고 얘기합니다. 별도의 설명이 없지만 leader election의 이야기겠죠? Erlang 프로세스들은 실패를 탐지할 수 있도록 되어있고, 원격의 프로세스들을 연결해서 이들의 실패를 탐지해서 대신 문제를 해결하는 것도 가능하다고 합니다.

4. Fault Identification

실패한 원인을 아는 것도 중요하다고 얘기합니다. 이를 위해서는 4대의 컴퓨터가 필요하다고 얘기하는데 역시 consensus의 이야기일까요? 슬라이드에서는 코드를 함께 보여주지만, Erlang에서 에러를 알려줄 때, 마치 Exception 객체를 catch할 때 cause가 들어있는 것처럼 에러의 원인에 해당하는 코드도 함께 알려줍니다.

5. Live Code Upgrade

Erlang에 대해 간략한 설명을 들을 때 나름 감명깊었던 기능인데, Erlang에서는 애플리케이션이 실행되는 도중에 코드를 수정 – 업그레이드할 수 있습니다.

6. Stable Storage

Erlang에는 기본으로 제공되는 mnesia라는 storage가 있는데, 데이터를 disk와 RAM 둘다에 저장할지, RAM에 저장하되 복제할지 등등을 모두 customize할 수 있다고 합니다. 그 외에도 riak, couchdb 등의 꽤 잘 알려진 NoSQL storage들이 erlang에 기반하고 있습니다.

Messaging

발표의 중간 정도에서 Joe Armstrong은 몇가지 인용구를 보여주는데 아래와 같습니다.

the process achives fault containment by sharing no state with other processes; its only contact with other processes is via messages carries by a kernel messge system
–Jim Gray, Why do computers stop and what can be done about it?, 1985

실패를 격리하기 위해서는 프로세스 사이에 상태를 공유하지 않고, 하부의 메시지 시스템에 의해서 제공되는 메시지를 통해서만 다른 프로세스와 접촉해야한다라는 이야기네요. 1985년의 글이므로 아마 이 글이 Erlang의 설계에 커다란 영향을 미쳤을지도 모르겠습니다. Shared nothing 아키텍쳐라는 단어는 아마 다들 익숙하시리라 생각합니다. 현대의 웹 서비스 아키텍쳐에서는 이미 널리 쓰이고 있죠. 공유하는 상태를 분리하는 것은 매우 중요합니다만, 오히려 공기처럼 우리 주위에 있기 때문에 그 중요성이 간과되고 있는 것이 아닐까 생각이 들 정도입니다.

The big idea is “messaging” — that is what the kernel of Smalltalk/
Squeak is all about (and it’s something that was never quite completed
in our Xerox PARC phase)….

–Alan Kay

한편, 메시징의 가장 큰 성공은 넓은 의미에서는 클라이언트-서버 아키텍쳐에 있다고 생각하지만, 좁은 의미에서는 우리에게 익숙한 것은 아니라고 생각합니다. 비동기적인 메시징과 메시지 디스패쳐 스타일의 애플리케이션은 아직은 자주 볼 수 있는 것은 아님에도 불구하고, 커다란 규모의 시스템에서는 오래전부터 요구되어 왔던 것이고, 인터넷 서비스의 규모가 점점 커지면서 점점 자주 보게되지 않을까 싶습니다.

Fail Fast and Early

Halt on failure: in the event of an error a processor should halt instead of performing a possibly erroneous operation.

Failure status property: when a processor fails, other processors in the system must be informed. The reason for failure must be communicated.

Stable Storage Property: The storage of a processor should be partitioned into stable storage (which survives a processor crash) and volatile storage which is lost if a processor crashes.

— Schneider, ACM Computing Surveys 22(4):229-319, 1990

6 Rules에서도 어느 정도 언급이 되어있지만 기본적으로는 failure를 detection할 수 있어야 하고 failure가 발생한 프로세스는 정지시키고, 안정적인 스토리지에 저장된 상태를 이용해 다른 프로세스가 failure를 복구하는 개념입니다. 높은 수준의 가용성을 요구하는 하드웨어에서 2개의 circuit을 준비하고 언제든지 하나의 circuit에서 failure가 발견되면 다른 circuit으로 대체하는 것과 같은 이야기 같습니다. 특히, 여러 인용을 사용하여 fail-fast와 fail-early를 강조하고 있는데, 이러한 scheme에서 fault 상태의 지속을 최소화하기 위해서는 당연한 이야기 같습니다.

Closing

이 발표를 들은 것은 애초에 Erlang 자체보다는 HA 시스템을 만들기 위한 방법에 대한 Erlang의 관점을 알고 싶었던 것이고, Shared nothing + Messaging 아키텍쳐,  fail-fast, fail-early 등의 개념들의 중요성을 다시금 깨닫는 계기가 되었습니다.

Erlang을 사용해보지도 않은 상태에서 섣부른 생각일 수도 있겠지만, 이 발표를 통해 느낀 Erlang의 가장 큰 장점은 Shared nothing + Messaging 아키텍쳐의 애플리케이션을 개발할 때 필요한 거의 모든 것들을 공짜 로 또는 바로 (off-the-shelf) 제공한다는 것 같습니다. 현대의 웹 서비스들은 비교적 failure에 안전한 언어와 플랫폼 (Java), 실패를 탐지하고 복구하기 위한 메커니즘 (L4), 메시징에 기반한 프로토콜과 그 구현 (HTTP와 이를 concurrent하게 처리할 수 있는 웹 서버 구현), 안정적인 스토리지 (DB)로 만들어져 있기 때문에 역시 이 비용을 크게 느끼지 않는 것 뿐이지, 이러한 것들에 의존하지 않는 새로운 애플리케이션을 만들어야 한다면, 무시할 수 없는 비용을 치뤄야만 합니다. 예를 들어, 언제든지 segmentation fault를 맞이하더라도 이상하지 않는 C로 애플리케이션을 개발해야하고, 실패 탐지와 복구를 Linux HA를 사용하되, 애플리케이션의 요구사항에 따라 실패 탐지의 방법과 복구 방법을 개발해야하며, 메시징을 위해 RPC 프레임워크나 ESB를 개발하는거나 적절한 대안을 탐색하는 것, 새로운 애플리케이션의 특성에 적절한 분산 스토리지를 개발하거나 탐색하는 것 모두가 비용에 해당하는 것입니다. Erlang이 이에 게재되는 모든 문제를 해결하는 것이라고 생각하지는 않지만, 일부는 해결해주고 있다고 생각합니다.

한편으로는, Shared-nothing 아키텍쳐의 애플리케이션, 즉 상태를 공유하지 않아도 되는 애플리케이션은 개발하기도 쉽고, Scalability도 쉽게 보장되기 때문에, 비용은 애플리케이션 환경이나 요구사항에 따라서 다르겠지만, 상대적으로 쉬운 문제입니다. 정말 어려운 문제는 상태 즉, 안정적인 스토리지에 있습니다. 물론, 안정적인 스토리지의 구현에도 Erlang은 위에서 언급한 면에 커다란 도움을 줄 수 있다고 생각합니다만,  단지 구현상의 문제라고 보기에는 현실과 거리가 있다고 생각합니다. 안정적인 스토리지의 문제 전체 영역은 Erlang이 해결하는 영역에 비해서 훨씬 크다고 생각합니다.

Building Highly Available Systems in Erlang by Joe Armstrong 더 읽기"

Pallet – DevOps for the JVM by Antoni Batchelli

Closure/West 2012에서의 Antoni Batchelli의 강연입니다.

Pallet – DevOps for the JVM by Antoni Batchelli

제목을 보고 JVM 기반 애플리케이션들 대한 모니터링이나 관리에 대한 얘기인 줄 알았는데, JVM 기반 언어로 만든 Configuration Management Tool이네요. 한마디로 말하자면 Closure로 만든 Cloud용 Chef나 Puppet 정도 되는 것 같습니다.

설명보다는 직접 코드를 보는 편이 훨씬 와닿으리라고 생각합니다. (InfoQ 페이지에서 Slides를 받을 수 있습니다.)

 

느낀 점은 두가지 정도네요.

1. Ruby나 Closure 같은 언어들이 유행하면서 라이브러리 수준의 DSL만으로 descriptive language 처럼 쉽게 기술할 수 있게 된 것은 오래되었지만, 점점 보편화하고 있군요. 특히, 주로 행동이 아닌 상태를 기술해야하는 Configuration Management Tool에서는 이러한 방식이 더욱 이해하기 쉽고, 유용하며 따라서 모듈화에도 유리한 듯. Provisioning은 적절하게 개념을 세우고 분류를 해서 DB로 만들기만 해도 어느 정도 잘 동작하지만, 대규모 Configuration Management가 필요할 때에도 어느 정도 모듈화되고 버전 관리되는 shell scripts 이상은 직접 본 적이 없고, 그 한계도 잘 알고 있는데, 이제는 Chef나 Puppet 계열을 시도해 봐야 할지도 모르겠군요.

2. 슬라이드들을 자세히 보셨는지 모르겠지만, 만족해야하는 하드웨어 요건과 설치해야하는 소프트웨어들, 노드들의 수를 기술하면, AWS  또는 VM Infra로부터 자동으로 적절한 타입의 instance를 생성해서 요구한대로 설정해주는 시나리오입니다. cloud 환경이나 VM infra 환경 하에서는 당연하게도 이런 마법 같은 일이 가능하다는 것, 가능하다는 것은 알고 있지만, 구체적인 시나리오를 보니 느낌이 새롭네요. 전통적인 인프라 환경에서는 직접 구현하려고 해도 절대 쉽지 않은 일인데요. 저런 꿈 같은 일이 보편화 하는 날이 오게 될지 매우 기대됩니다.

Pallet – DevOps for the JVM by Antoni Batchelli 더 읽기"

How To Design A Good API and Why it Matters by Joshua Bloch

2007년 1월 24일 Google TechTalks에서의 Joshua Bloch의 강연입니다.

How To Design A Good API and Why it Matters (Slides)

InfoQ에서 공개되어 있는 Javapolis에서의 2005년 강연도 있습니다만, 내용은 같아 보입니다. Slides로 충분하다고 생각하지만 OOPSLA 2006에 제출하기 위해 만든 요약도 참고하세요.

Joshua Bloch에 대해서는 Effective Java에 관한 글에서 소개한 적이 있지만, 굳이 여기서 다시 언급할 필요도 없다고 생각합니다. Java의 주요 클래스 라이브러리들의 설계를 주도하여, Java의 API 설계 품질의 기준을 한층 끌어올린 그는, API 설계에 관해 전문가라고 해도 충분하다고 생각합니다.

이 강연의 주제는 제목 그대로 좋은 API를 설계하는 방법과 그 중요성에 대한 강연이고, 제가 아는 한 API 설계에 관한 대부분의 중요한 생각들을 담고 있다고 생각합니다. 그 생각들을 전달하는 면에 있어서도 매우 훌륭한 강연이기에 만약 아직 이 강연을 보신 적이 없으신 분들은 시간을 들여 직접 보실 가치가 있으리라고 생각합니다. 이 글에서는 주로 API의 설계 과정에 대한 내용에 대해 제가 현재 시점에서 인상적인 부분들에 대한 의견을 적어봅니다.

If you program, you are an API designer

예전에는 프로그래머들을 API 설계 경험이 있는 프로그래머와 그렇지 않은 프로그래머로 분류할 수 있다고 생각했습니다. API 설계를 하기 전에는 다른 프로그래머가 어떤 도메인에 대해서 어떤 생각을 가지고 있을지, 주어진 API를 사용할 때 얼마나 실수할 수 있을지, 주어진 API가 얼마나 이해하기 쉬울지에 대해서 고민해보지 않았으니까요. 그리고, 그러한 고민들을 통해서 문제들을 해결하는 방법을 깨닫는 과정이 중요하다고 생각했습니다. API 설계를 경험하고나서 제가 느낀 것은 학부 시절에 Automata 수업을 들었을 때의 느낌이었죠.

그런데, Joshua Bloch은 모든 프로그래머는 API 디자이너라고 얘기합니다. 이 말을 듣고 다시 생각해보니, 실제로는 모든 프로그래머는 자신이 만든 코드를 사용할 모든 사용자 – 즉, 최종 사용자 (end-user)이거나 다른 프로그래머들을 고려하지 않으면 안된다는 것을 깨달았습니다. 어쩌면 그만큼 프로그래머에 대한 잣대가 올라갔다는 생각도 듭니다.

Start with Short Spec–1 Page is Ideal

API 설계의 시작 단계에서는 기민성(agility)이 완전성( completeness)보다 중요하다는 이야기입니다. API 설계의 시작 단계에서는 실제로 그 API를 들고 사용자에게 부딪혀보지 않으면 그 API가 요구사항에 적합한지 알 수 없는데, 이해하기도 힘든 복잡한 API 스펙을 가지고는 사용자들이 이해하기도 힘들고, 변경하기도 힘들다는 것입니다. 일반적인 소프트웨어 개발은 기민성을 중요시하면서도 API 설계에 있어서는 기민성과 완전성 사이에서 저울질 하기가 어려운 면이 있었는데, 한 페이지라는 기준은 매우 훌륭한 기준인 것 같습니다. 그리고, 이 한 페이지를 들고 사용자와 부딪혀보는 과정들 (이를테면, Hallway testing) 도 매우 중요하게 여겨집니다.

When in doubt leave it out

API의 어떤 요소 (메서드, 파라미터, …)가 들어가야 할지 말기 고민된다면, 빼버리라는 것입니다. 이미 다른 사람들이 사용하는 API는 없애기 힘들지만, 추가하기는 쉬운 API의 특성에 기인하는 매우 중요한 특성입니다. 요구사항을 다른 부서 등과 조율하는 과정에서 애매모호한 기능 요구사항들이 항상 나타나는데 이에 대한 명확한 결정을 내리는 것이 가장 좋긴 하겠지만, 그렇지 못하는 경우도 흔히 벌어지는 일인 것 같습니다. 이 때, API의 이러한 특성은 요구사항의 결정에서도 중요한 근거가 될 수 있지 않을까 하는 생각이 드네요.

Write to Your API Early and Often

API 설계에서 가장 흔하게 겪고, 또 가장 중요한 문제점으로 드러나는 것은, API를 이용한 구현하는 도중에 특정 기능을 충족할 수 없음을 발견하는 것일겁니다. 기민한 개발 과정으로 볼 수도 있겠지만, API 사용자 입장에서는 부족한 API 설계 상의 문제를 파악하거나 API가 동작하지 않는 문제를 발견하는 것, 그리고 변경된 API를 적용하는 과정들은 매우 힘들고 비용이 많이 들 뿐만 아니라 괴로운 과정입니다. 이러한 문제들의 대부분은 결국 API를 이용해서 구체적인 프로그램을 만들어보는 것 밖에는 방법이 없고, 기본적으로 이 역할을 API 설계자에게 있어야 합니다. TDD를 한번이라도 해보신 분들은 아시겠지만, API를 사용하는 코드를 먼저 써보는 것은 API 설계에 커다란 도움이 됩니다. 그리고 이러한 과정에서 만들어진 API 예제를 사용자에게 제공하는 것은 API를 사용하는 방법을 쉽게 익힐 수 있도록 도와줄 뿐만 아니라 API 사용자들이 잘못된 사용 방법에 빠지지 않도록 도와줍니다. Joshua는 API 설계 시의 API 예제가 API를 사용하는 모든 코드 중에 가장 중요한 코드라고 얘기합니다. 이는 절대 과장이 아니라고 생각합니다. API 예제가 제공되지 않는 API를 직접 개발하거나 사용해본 입장에서 이 부분이 뼈저리게 느껴지는군요.

Document Religiously

API라고 한다면 가장 좋은 문서화가 요구되어야 하는 것은 당연한 것 같습니다. 하지만, 문서가 없는 API를 종종 봅니다. 저도 잘못된 내용의 문서화가 된 API를 쓰거나, 모든 측면의 문서화를 하지 않은 등의 실수들이 떠오릅니다. 문서화에는 정말 ‘Religiously’라는 단어 – 우리말로 굳이 옮긴다면 ‘열광적으로’ 라고 해야할까요 – 를 써야할 정도로 개발자가 그만큼 공을 들이지 않으면 안되는 것 같습니다.

Closing

이 강연은 비록 5년 전의 내용이지만, API의 설계 과정 뿐만 아니라, 일반적인 API 설계 원리, 클래스, 메서드, 익셉션의 설계에 관한 내용들을 담고 있으므로, 현재는 물론 앞으로도 계속 곱씹을 수 있는 내용이라고 생각합니다. 다시금 말씀드리지만, 한번씩은 보시기를 권해드립니다. 가능하다면, 누군가가 자막 번역을 해준다면 좋겠다는 생각이 드는군요.

제게는 API 설계에 대해서 예전에 했던 생각들을 더올리게 되면서 현재 직면하고 있는 문제들에 대해서도 새롭게 많은 고민들을 할 수 있게 해주는 강연이었습니다. 좋은 강연에 대해서 Joshua Bloch에게 감사드립니다.

How To Design A Good API and Why it Matters by Joshua Bloch 더 읽기"

Google 20% Time

Google의 20% Time 제도는 Google의 직원이라면 누구나 업무 시간의 20%, 즉 매주 하루 정도의 시간을 자신이 원하는 일에 투입할 수 있다는 제도. 이 제도는 Gmail 과 같은 성공적인 프로젝트의 요람이 된 것으로 매우 잘 알려져 있고, Google이라는 회사에서 ‘혁신’이라는 가치를 소중하게 여긴다는 사실을 대변하고 있다.

그렇다면 어떤 소프트웨어 회사든 Google의 20% Time 제도를 도입한다면 ‘혁신’에 성공할 수 있을까? 현실을 냉철하게 바라보는 사람이라면 Google에서 조차도 20% Time 제도가 ‘혁신’에 있어서 성공적인가라는 질문에 의문을 품는 것이 당연하다고 본다.

예를 들어, 당신은 어떤 소프트웨어 회사의 상위 관리자이고, ‘혁신’의 추진력을 높이기 위해 (그다지 현명한 이유는 아닐지라도) 유명한 Google의 20% Time의 도입을 검토하고 있다고 생각해보자.

이러한 관점에서 20% Time에 대한 Quora의 답변 내용을 간략하게 정리해본다. 여러 사람들이 기술한 사항들이기 때문에 주관적이기도 하고 시간이 흐르면서 변화한 사항들도 있을 테니, 이 글에 있는 모든 사항들이 정확하다고 보기에는 힘들다는 점을 유념해서 읽어주었으면 한다. Google의 employee가 아닌 입장에서 이 글을 쓰는 한 대체로 부정확하고 상상력에 기초한 우스운 글이 되기 쉽다는 것을 잘 알고 있지만, 동기 부여라는 주제에 관한 스스로의 고민의 과정을 정리해놓는 의미로 생각한다. 이 글에서 언급된 현실을 반영하지 않는 잘못된 사실이나 미묘한 의미가 있다면 지적해준다면 그러한 과정에 매우 도움이 될 것이다.

평가: 20% Time은 어떻게 평가되어야 하는가?

20% Time을 도입한다고 할 때, 가장 먼저 부하 직원들이 묻는 것이 바로 이 부분일 것이다. 20% Time은 강제로 사용하는 것인가? 선택적으로 사용하는 것인가? 어느 쪽이든 평가에 불이익이 있는 것이 아닌가?

In Google

20% Time을 모든 사람이 반드시 활용해야 하는 것은 아니다. 한편, 20% Time을 활용하고자 하는 사람이 20% Time을 사용하는 것을 직접적으로 가로막는 것은 없다. 하지만, 관리자나, 함께 main project의 일정을 고려해야 하는 동료들의 동의를 얻는 것이 바람직하다. 관리자의 승인 하에 20% Time을 모아서 한 주 동안 Full Time으로 일할 수도 있다.

또한 기본적으로 20% Time은 평가 (performance review)에서 제외되며, 포함된다고 하더라도 평가 (performance review)에 인지되기 힘들다. 동료 평가(peer review)에서 인지되는 것이 바람직하겠지만, 현실적으로 100%의 시간을 주요 프로젝트에 사용한 동료가 더욱 좋은 평가를 얻을 확률이 높고 승진도 빠를 수 있다. 정당한 평가를 위해서는 실제로 자신이 기여한 프로젝트의 PM에 대해 정당한 동료 평가를 요구하여야 한다.

이러한 현실적인 어려움 때문에, 대부분의 Google 직원들은 이를 활용하고 있지 않다.

Opinion

보통, 관리자의 입장에서 20% Time을 위한 리소스를 할당하는 것은 절대 쉬운 일은 아니라고 본다. 하지만, 이는 리소스에 대해 단기적인 시각에서 바라보았을 때의 결과라고 생각한다. 만약 20% Time이, 혁신을 유도하거나 생산성을 높이거나 적어도 Turn-over 비율을 감소시킴으로써, 투입한 비용 이상의 성과를 산출할 수 있다면, 처음에 이를 선택하는 것은 조금 과감할 필요가 있겠지만, 곧 익숙해진다면 별로 문제가 되지 않을 거라고 생각한다.

20% Time을 평가에 포함시킬 것인가, 포함시키지 않을 것인가는 매우 어려운 문제다. 평가에 포함시킨다면, 평가를 어떻게 할 것인가라는 문제를 차치하더라도, 평가 자체가 20% Time에 참여하는 사람들의 의도를 왜곡하여 20% Time의 본래 의미를 잃어버리기가 쉽다. 평가에 포함시키지 않는다면, Google의 사례와 같이 20% Time을 사용하기 위한 커다란 incentive가 사라지게 된다. 양쪽 모두가 각각의 문제를 지니고 있기 때문에, 결국은 제도 자체의 겉모습에 치중할 것이 아니라, 제도를 통해서 획득하려는 가치를 기준으로 판단해야 한다고 생각한다.

20% Time이 조직에 혁신을 위한 문화를 조성하고 실제로 혁신을 이끌어내기 위한 것이라면, Google과 같이 평가에 포함시키지 않는 쪽이 더 바람직해 보인다. 그 이유는 다음과 같다.

  • 모든 사람이 혁신을 위한 아이디어를 가지고 있고, 이 아이디어를 실제로 실행할 의지를 가지고 있으며, 또 그를 성공시키기 위한 역량을 가지고 있으며, 상황적인 조건이 부합하는 것은 아니다. 아마도 이는 소수에 불과할 것이다.
  • 정말로 가치 있는 일이라면 적어도 20% 정도의 보상 기회를 희생할 정도의 가치가 있어야 할지도 모른다.
  • 불확실한 미래의 보상을 기대한다고 하더라도, 현재의 확실한 희생을 수용한 사람이라면, 그만큼 보람 있고 열정적으로 일 할 것이다.

물론, 실제 실행 시에는 보다 많은 미묘한 문제들이 발생할 거라고 추측되지만, 이러한 허들을 뛰어넘을 수 있는가의 여부는 실제로 실행해보지 않고서는 미리 예측하기 힘들다.

시간: 20% Time은 너무 길거나 반대로 너무 짧은 것은 아닌가?

In Google

Google에서 실제로 하나의 서비스를 launch하기 위해서는 개발 비용을 넘어서는 커다란 오버헤드를 필요로 한다. 예를 들어, 조그마한 서비스라고 하더라도 launch를 위한 기술 및 제품 승인을 얻기 위해서는 많은 노력을 필요로 한다. 자신의 프로젝트에 참여하기 위한 사람들을 찾는 것도 매우 어려운 과정 중의 하나라고 한다. 막상 서비스를 launch하더라도 수시로 발생하는 outage나 운영 상의 변화에 대응하기 위한 유지보수에 다시 20% Time을 들여야 한다. 따라서, 제대로 뭔가를 하려면 20% Time 만으로는 부족하고 야근과 주말근무를 불사해야 한다. 의견이 엇갈리기는 하지만, 20% Time은 workholic을 위한 제도라고 얘기할 정도. 20% Time은 서비스를 launch하는 수단으로서는 그다지 좋지 않다는 의견도 존재한다.

활용: 20% Time을 어떻게 활용하는가?

In Google

다음과 같은 다양한 활용이 가능하다.

  • 기존 및 현재의 프로젝트에서 다른 사람들을 설득하지 못하지는 못했지만, 스스로는 가치가 있다고 생각하는 문제를 개선할 수 있다. 현재의 개발팀이 우선순위 때문에 관심을 기울이지 못하는 어떤 기능을 개선할 수 있다.
  • 새로운 서비스나 새로운 소프트웨어를 개발한다.
  • 이미 존재하는 전사 프로세스나 도구를 개선한다.
  • 외부의 오픈 소스 프로젝트에 기여할 수도 있고, Journal에 기고하거나, 새로운 프로그래밍 언어나 UI 디자인에 대해 공부하는 등, Job Skill을 확장하기 위한 뭐든지 할 수 있다.

가치: 20% Time이 Google에게 가져다 주는 것은 무엇인가?

이에 대해서는 일단 Dion Almaer의 글을 인용해보자.

The key was the followi
ng effect:

  • In order for 20% time to work, anyone must be able to see what is out there
  • In fact, if you want to get some people working “for free” you need to both advertise your project, and write it in such a way that it is easy to get ramped up and productive (end result: better code)

The end result is the culture HAS to be kept very open. The ability to see the projects that are worked on, check out the code, see presentations and design docs, is a key reason why Google does so well at engineering in my opinion.

난 위의 Quora의 답변 내용에서 나왔던 사실들로부터 20% Time의 효과에 대해 원래 가지고 있었던 의심을 약간은 확인했다고 생각했는데, 이 글을 읽고 내가 지인들로부터 들었던 이야기들이 떠오르면서 그러한 생각이 완전히 바뀌게 되었다.

20% Time은 어떻게 동작하는가?

다음 사항들은 지인들로부터 들었던 이야기들이라 더욱 부정확할 수 있겠지만, 일단 정리해보자.

  1. Google에서는 20% Time 프로젝트에 참여할 다른 엔지니어를 모집하기 위해 전사 메일을 보낼 수 있다. 그리고, 20% Time 프로젝트에 리소스를 승인 받거나 공개 서비스로 내놓기 위해 승인 받는 과정이 정의되어 있다.
    • 자신의 좋은 아이디어를 전사 메일로 보낼 수 있고, 참여를 호소할 수 있으며, 이것이 제도적으로 뒷받침되는 소프트웨어 회사는 과연 얼마나 될까?
    • 관리자들은 자신에게 이야기를 하면 되는데 이야기를 하지 않아서 그렇다고 생각할 지 모르겠지만, 공식적인 제도가 있는 것과 이야기를 하면 된다라는 것은 조직원 입장에서는 천지차이다.
  2. Google에서는 자신이 만들어 낸 코드, 문서, 발표 자료 등을 누구든지 볼 수 있다.
    • 자신의 프로젝트에 참여하고자 하는 사람 또는 관심이 가는 프로젝트를 주도하는 사람이 얼마나 뛰어난가를 확인하는 가장 정확한 방법은 그 사람이 실제로 해놓은 것을 보면 된다. 다시 말해, 엔지니어가 다른 엔지니어의 산출물에 대해 가장 잘 평가할 수 있다.
    • 대부분의 회사에서도 어떤 방식으로 산출물이 관리되고 있긴 하겠지만, 실제로 어떤 사람의 산출물을 공개적으로 접근하는 것은 매우 어렵다.그래서, 직급이라든가, 함께 일했던 시절의 주고 받은 대화나 메일, 과거 동료들의 단평 정도를 간접적으로 이용하는 것에 불과하다.
  3. Google에서는 코드 리뷰가 필수적으로 행해지고 있으며, 코드에 대한 평가를 수치화한 Readability Score라는 척도가 공개적으로 조회 가능하고, 이러한 수치가 다른 프로젝트에 대한 Commit의 허용 여부에 영향을 미친다.
    • 단순히 모든 산출물이 공개되어 있을 뿐만 아니라, 이를 정량화하고 실제로 이러한 척도가 어느 정도의 신뢰성을 가지고 동작한다는 것이 매우 놀랍다.
    • Readability Score는 평가(Performance Review)와는 무관하다.
    • Google의 코드 리뷰 제도에 관해서는 역시 Quora의 답변들을 읽어보면 참고가 될 것이다.

제도, 시스템과 문화를 통한 혁신

혁신에 관한 이야기를 꺼낸다면 아마도 대부분의 상위 관리자들은 다음과 같은 이야기를 할 것이다.

혁신에서는 시간이 있는가, 없는가가 중요한 것이 아니라, 얼마나 열정적으로 문제를 해결하려고 하는 가가 중요하다. 또한, 혁신은 아이디어가 아니라 실행이다.

나는 이런 이야기들에 거의 찬성한다. 나조차도 이런 얘기를 한 적이 분명 여러 번 있을 것이다. 조직의 구성원들의 열정은 혁신에 있어서 필수불가결한 요소이고, 시간의 부족만을 그 원인으로 진단하는 것에 대해서는 반성이 필요한 경우가 많은 것이 사실이라고 본다.

그럼에도 불구하고 혁신과 열정의 원동력이 오직 조직 구성원 내부에만 있다고 보는 관점도 온전히 옳다고만 할 수는 없다고 본다. 단지 조직원 사이에서 혁신과 열정이 저절로 꽃피어나기를 기다리는 것보다는 구성원이 혁신적인 아이디어에 대해 열정적으로 일할 수 있도록 동기를 부여하거나 지원하는, 좀 더 적극적이고 체계적인 행동이 조직에는 필요하다고 생각한다. 이 때, 적극적이고 체계적인 행동이라는 것의 의미는 관리자 개인의 능력이나 성향, 선의에 의한 동기 부여 행동과 대비되는 것을 의미한다.

제도나 시스템이 아닌 관리자 개인에 의존할 경우 다음과 같은 문제들이 존재할 수 있다.

  • 관리자 개인에 따라 개인의 능력이나 성향, 선의에 따라서 동기 부여의 수준은 극단적으로 낮을 수 있다. 이러한 경우에 대한 대책이 없거나 있더라도 제대로 동작하지 않을 가능성이 있다.
    • 일반적인 hierarchical 조직에서, 관리자 개인이 조직원의 동기 부여를 크게 해친다고 하더라도 관리자 자신은 이러한 상황을 인지하지 못하거나, 인지하더라도 변화하기가 힘들며, 조직원은 변화를 위한 적절한 권한이나 역량이 없으며, 상위 조직장은 이를 인지하지 못하는 경우가 많다.
    • 조직이 보통 요구하는 것은 조직의 단기 성과를 높일 수 있는 충분한 역량을 가진 조직장이며, 물론, 동기 부여의 능력 또한 조직이 요구하고 바람직한 능력이나, 성과와 동기 부여가 충돌할 경우, 조직은 전자를 선택하는 경향이 있는 것 같다. 팀의 morale을 와해한 조직장이 승승장구하는 (적어도 살아남는) 스토리는 이러한 이유에 기인한다고 생각한다.
  • 조직의 상황에 따라 동기 부여의 수단이 쉽게 희생될 수 있다.
    • 일반적인 상황에서 조직 및 이를 대변하는 관리자는 생산성의 저하 요소를 제거하기 위해서 동기 부여에 노력을 기울일 수 있다. 하지만, 조직원의 동기 부여와 우선순위와 R&R 같은 좀 더 전통적인 조직 가치가 충돌할 경우 후자를 우선시하는 경향이 있는 것으로 보인다. 이러한 선택은 조직의 구조나 목적 상 물론 불가피한 측면이 있는 것이 사실이다.
    • 문제는 이러한 조정이 개인에 의한 것일 경우, 극단적인 희생이 이루어질 가능성이 높다는 것이다. 예를 들어, 일반적인 상황에서 동기 부여를 위한 노력이 50%의 비중이었다면, 문제의 상황에서는 0%가 되어버릴 수 있다는 것이다.

단편적인 예를 들어, ‘내가 원하기만 한다면 내가 원하는 일을 언제든지 할 수 있어’와 ‘내가 원하더라도 조직장에게 얘기를 해야할까? 얘기를 한다면 불이익을 받지 않을까? 소속 조직을 옮겨야 할까? 소속 조직을 옮기기 위해 회사의 제도를 활용할 수 있을까? 또는 누구와 얘기해야할까? 그냥 이직을 해야할까?’는 조직원 입장에서 엄청난 차이일 수 밖에 없다.

Google의 20% Time에서 가장 중요한 측면 중 하나는 Google은 조직원의 동기 부여에 대한 강조가, 관리자 개인에만 의존하지 않고, 전사적인 제도와 이를 뒷받침하는 시스템, 그리고 문화를 통해 항상 일정 수준으로 이루어진
다는 것이다.

수평적인 평가와 비물질적인 보상을 통한 혁신의 동기 부여

평가와 보상이란 조직에 있어서 가장 중요한 요소 중의 하나이다. 평가의 본질적인 목적은 보상을 어떻게 공평하게 분배할 것이냐가 아니라, 조직원의 potential을 최대한 발휘하게 하여 조직 전체의 성과를 증가시키는 것에 있다.

하지만, 일반적으로 평가는 어려울 뿐만 아니라, 예측과 정량화의 어려움으로 인한 Software 개발의 본질 상 Software 개발 조직에서의 평가는 매우 어려운 것이 보편적으로 받아들여지고 있다.

<To Be Written>

Closing

Google이 20% Time을 통해서 단지 제도와 시스템 뿐만 아니라 혁신의 문화를 배양하는 것은 실제로 동작하는 사례로서 매우 높은 성취라고 생각한다. 하지만, 혁신을 위한 조직 문화를 만들기 위한 수단이 비단 Google의 20% Time만이 있는 것은 아닐 거라고 추측해본다. 보다 많은 조직에서 이에 대해 고민하고 또 실험하면서 그들만의 혁신 문화를 창조해나갔으면 좋겠다.

좀 더 읽어볼 글들:

Google 20% Time 더 읽기"

Jolt Awards 2011

Excellence Award는 Continuous Delivery, Productivity Award는 Seven Languages in Seven Weeks와 Mining the Social Web이 수상했다. 이들 Top 3 이외에 당장 관심이 가는 책은 Martin Fowler의 DSL 책, Scalability Rules 정도.

The Best Books

http://drdobbs.com/joltawards/231500080

  • Domain-Specific Languages, by Martin Fowler
  • The Art of Computer Programming, Volume 4A: Combinatorial Algorithms, Part 1, by Donald E. Knuth
  • The Joy of Clojure: Thinking the Clojure Way, by Michael Fogus and Chris Houser
  • Seven Languages in Seven Weeks: A Pragmatic Guide to Learning Programming Languages, by Bruce A. Tate
  • Mining the Social Web: Analyzing Data from Facebook, Twitter, LinkedIn, and Other Social Media Sites, by Matthew A. Russell
  • Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation, by Jez Humble and David Farley

The Rest of the Best

http://drdobbs.com/joltawards/231600815

  • Arduino Cookbook
  • CLR via C#, 3rd Edition
  • Data Analysis with Open Source Tools
  • Eloquent Ruby
  • High Performance JavaScript
  • Scalability Rules: 50 Principles for Scaling Web Sites
  • The Software IP Detective’s Handbook: Measurement, Comparison, and Infringement Detection
  • The Rails 3 Way
  • The RSpec Book: Behavior Driven Development with Rspec, Cucumber, and Friends

Jolt Awards 2011 더 읽기"

NoSQL @ Netflix

http://www.infoq.com/presentations/NoSQL-Netflix

지난 7월 QCon 발표. 이 발표자는 굉장히 여러 군데서 동일한 내용으로 발표한 모양인데도 불구하고, 실은 썩 마음에 드는 발표는 아니었지만, 실제 엔지니어링 경험이 뼈저리게 느껴져서 인상 깊게 보았던 발표다.

Netflix’s Cloud Transition

2008년 말, Netflix는 하나의 데이터센터를 가지고 있었고, SPOF와 cooling, power, space, traffic capacity 문제에 봉착하고 있었다. (문맥상 그야말로 데이터센터를 ‘보유’하고 있었던 것으로 보이는데, 미국의 경우 이러한 방식이 일반적인 방식인 것인지, 그리고, SPOF가 중요한 문제가 될 만큼 데이터센터의 신뢰성이 문제가 되는 수준인지 궁금하다.) 그리고, 놀랍게도 outsourcing을 통해,  당시 IaaS 플랫폼으로서는 leader 격이었던 AWS를 통해 해결하기로 결정한다.

Netflix의 cloud migration에서 중요한 점 중 하나는 가장 중요한 사용자 개인 정보 (PII), 결제 정보 (PCI DSS)는 그들의 데이터센터에 남겨놓고, 나머지 – 비디오의 메타데이터, 리뷰, 사용자의 비디오 큐, 시청 기록, 평점, 로그 등 만을 cloud로 이동했다는 점이다.

AWS로 가면서 자연스럽게 선택하게 된 storage는 바로 Simple DB와 S3인데, Simple DB는 RDBMS의 대체, S3는 Simple DB의 item 크기 제약을 넘어서고, single key로만 액세스하는 데이터를 저장하는데 사용한다. 그러다 Simple DB의 데이터 모델 제약이라든지, Scalability concern등의 문제들을 넘어서기 위해서 Cassandra도 사용하게 되었다고 한다. 이 발표에는 등장하지 않았지만 M-R과의 조합이 필요한 곳에는 Bigtable도 사용하는 것으로 보인다.

이 발표에서는 Simple DB와 Cassandra를 간략하게 소개하고, Simple DB를 실제로 적용할 때 겪었던 문제들을 정리하고, Cassandra 에서 이러한 문제들이 많이 해결되었다고 얘기하고 있다.

Problems in transition from RDBMS to Key-Value Data Store

당연하지만, RDMS에 있을 때 편하게 썼던 기능들이 필요해지면 application layer에서 알아서 구현해야 한다.

  • partial or no sql support
    • joins이나 group by가 없기 때문에 application layer에서 구현
  • no relations between domains
    • application layer에서 구현.
  • no transaction
    • simple db에서는 conditional put/delete op이 존재하기 때문에 이를 이용해 optimistic locking
    • cassandra에서는 batch mutate op 이용
  • no schema
    • attribute 이름 등에서 misspelling이 발생할 경우 silent하게 실패.
    • 공통 data access layer에서 validation
  • no sequences
    • primary key를 위해서는 자연스럽게 발생하는 unique key나 그러한 경우가 아닐 때는 UUID 사용
    • ordering을 위해서는 distributed sequence generator (using zookeeper)나 client timestamps 사용
  • no constraints (uniqueness, foreign key, referential , integrity)
    • application layer에서 구현

Workaround Issues in SimpleDB

SimpleDB의 설계나 구현이 아직 충분히 성숙되지 않았음을 엿볼 수 있기도 하고, 어떤 측면에서는 다른 DBMS에서도 충분히 겪을 수 있는 문제이나, 충분한 사용 경험이 없기 때문에 해결에 많은 시간을 들여야 할 가능성이 높다고 생각한다. 발표를 들으면서 발표자인 Siddharth Anand가 얼마나 고생했을지 감정이입이 될 정도.

  • no backup and recovery
  • no native support for types
    • 모든 데이터는 UTF-8 character string이고 sorting은 lexicographical만 지원하기 때문에, 숫자 sorting을 하기위해서 데이터에 zero-padding을 해야 한다는 어처구니 없는 일이 발생한다.
  • null attributes are not indexed
    • null 은 indexing이 안되어있기 때문에 where clause에 is null을 쓰면 full domain scan.
      • null인지 여부를 나타내는 필드를 추가해야 하기 때문에, 결국 sparse table의 장점을 잃어버림.
    • 역시 비슷한 문제로 null일 수 있는 attribute에 대해 order by 하면 null attribute의 record는 아예 나오지 않음.
  • data set partitioning

    • domain에 10GB limit와 1B attributes limit가 존재하기 때문에 domain을 application level에서 sharding 해야 함.
    • write throughput을 늘리기 위해서는 sharding 해야 함.

  • attribute name이 case-sensitive하므로 miscased나 misspelled attribute names을 체크해야 함.
  • limit N clause가 없으면 100개의 row만 return 되므로 실수하지 않았는지 체크해야 함.
  • 하나의 statement 내에서 하나의 attribute를 업데이트하고 다른 attribute는 null out할 수 없음.

Thoughts

흔히 NoSQL로 분류되는 storage들은 RDBMS가 아니라는 것 외에는 별로 공통적이라고 할만한 것이 없다. 그래서 NoSQL이라는 말을 쓰는 것을 매우 싫어하는 편이다. 이 발표를 들으면서 이러한 생각에 좀 더 확신이 들었다고 할 수 있을 것 같다.

NoSQL이라고 하는 storage들을 실제로 자세히 들여다보면 각각마다 데이터모델, 오퍼레이션 특성, 성능 특성, 성숙도는 천차만별이다.  결국 하나의 storage를 채용하기 위해서 서로 다른 특성들을 이해하고, 유효한 방법으로 평가는 일만 하더라도 결코 쉬운 일이 아닐뿐더러, 채용하기로 결정한 storage의 데이터모델에 적합하게 데이터를 구성한다든가, 위의 사례에서 보았듯이 각 storage별 세부 특성이나 결함 등을 처리하는 일까지 더한다면 하나의 storage solution을 도입하는 일은 보통 일이 아니다. 그래서, “NoSQL이란 거 좋다면서?”라고 말을 꺼내는 사람이 있으면 “그냥 RDBMS 쓰세요”라고 얘기해주는 것이 정답이라고 본다. NoSQL이라는 bandwagon에 타려고 발걸음을 서두르기 전에, 남들이 하는 이야기들을 반복하기 전에, 왜 RDBMS를 쓰면 안되는 지부터 자신의 도메인에서 고민해보았으면 한다.

주변 사람들에게는 몇 번 얘기했었지만, 이 발표를 들으면서 한가지 매우 인상 깊었던 얘기는 consistency가 깨질 수 있는 것을 인정하고 배치의 형태로 항상 백그라운드에서 동작하고 있는 data fixer를 개발하고 있다는 내용이었다. 별 것 아니라고 생각할 수도 있지만, 이러한 패러다임은 RDBMS를 사용하던 시절에는 inconsistency를 유발하는 원인이 있다면 이를 제거해야 하는 것으로 보는 것 (아니면 아예 무시하거나)과는 완전히 다른 패러다임이다. 현재로서는 weak consistency의 NoSQL storage를 사용하면서도 아직 기존의 패러다임에 젖어 있는 것이 사실인 듯 하다. 지금은 transaction 없이 application layer에서 index를 만들고 나중에 consistency가 깨어지지 않기를 기도하겠지만, 앞으로는 application layer에서도 anomaly를 탐지하고 자연스럽게 해결할 수 있도록 해야할 뿐만 아니라, 지속적인 validation & flx 작업이 필요할 것이다. RDBMS도 경쟁하고 있는 환경에서 wea
k consistency 모델이 얼마나 유행할지는 잘 모르겠지만, weak consistency 모델의 이러한 데이터 운영 패러다임을 간략한 개념과 구현으로 정리할 수 있다면 바람직할 것 같다.

NoSQL @ Netflix 더 읽기"

Development at the Speed and Scale of Google

어제 송년회가 피곤했던지 일찍 잠들었다 새벽에 깨는 바람에, QCon SF 2010에서 Google의 Engineering Manager인 Ashish Kumar가 발표한 Development at the Speed and Scale of Google이라는 Presentation을 보게 되었다.

이 발표의 내용은 Google의 Infrastructure 중 하나인 빌드 시스템에 관한 내용으로 아주 재미있는 발표는 아니었지만, 몇 가지 흥미로운 점이 있었다.

Monolithic Code Tree

Google은 어느 정도 알려진 바와 같이, 하나의 코드 저장소에 모든 코드를 관리하고 있으며, 누구든지 필요한 소스코드를 체크아웃해서 사용할 수 있다.

Reducing Checkout Costs

모든 것을 소스로부터 빌드하기 때문에, 의존성을 가진 코드들을 체크아웃하는 비용을 무시할 수가 없는데, 사실 변경하려는 코드가 아닌 코드에 대한 로컬 복사본은 필요 없으므로, FUSE 기반 파일 시스템을 이용한 전체 code tree의 읽기 전용 복사본을 이용한다고 한다.

Reducing Code Review Costs

Google의 개발 프로세스를 보면 commit 이전의 코드 리뷰가 필수적으로 들어가있는 것으로 보이며, 코드 리뷰의 비용을 줄이기 위한 시도로서, 웹 상에서 graphical diffs를 조회하고 이에 대한 comment를 남길 수 있는 code review 도구와 lint error, code coverage, code analysis, test results 등이 제공된다.

IDE 기반의 도구에 대비해, 웹 기반 도구를 사용하고 있는 것이 흥미로운 점인데, C/C++ 계열에는 적절한 IDE가 부족한 점도 있겠지만, 아무래도 웹 기반 도구는 그 기본적인 특성 덕분에 하나의 정보를 여러 사람들에게 공유하기가 매우 쉽다는 점이 커다란 장점으로 작용하는 듯 하다. 다시 말해, 웹 만큼 훌륭한 shared workspace는 흔치 않다.

Reducing Build Costs

개발 과정에서의 커다란 비용 중의 하나로 지적하고 있는 것이 바로 build를 하는 도중 기다리는 비용인데, 이를 줄이기 위해서 object 파일들의 캐슁, 빌드 결과물에 대한 lazy한 액세스, incremental link (old binary + modified object files) 등을 지원하는 분산 빌드 시스템을 채용하고 있는 것 같다.

Continuous Integration

지속적인 통합 (Continuous Integration)이 실패했을 때 발송되는 메일에는 빠르게 원인을 파악할 수 있도록, 실패한 테스트의 목록, 실패를 유발한 Difff를 포함하고 있으며, 테스트 결과, 변경사항, 빌드 결과에 해당하는 웹 도구들에 대한 직접적인 링크를 포함하고 있다.

흔히 이러한 종류의 메일 보고서의 내용은 소홀한 경우가 많은데, 문제에 대한 진단이라는 것이 최종적인 목표라는 점을 생각한다면, 이러한 메일 보고서의 내용을 잘 갈고 닦을 필요가 있다.

Infrastructure

Google의 빌드 시스템은 외부에서도 사용할 수 있는 형태로 공개되어 있지는 않지만, 원래는 존재하지 않던 도구들을 Google이 사용하고 있는 것은 아니다. 가장 중요한 것은 아무래도 모든 도구들과 시스템이 통합된 형태로, 아무런 비용을 지불하지 않아도 전사적으로 제공되며, 실제 개발 과정에서 가능한 한 보이지 않는 형태로 제공되는 것으로 보인다.

여러 가지 종류의 도구들 (예를 들어, 여러 회사의 도구)을 혼합해서 사용하는 경우, 절대로 기능적인 면은 통합된 도구에 비해서 부족하지 않겠지만, 실제로는 접근성 등에 있어서 균질적이지 않아서, 어떤 도구는 사용하지만, 어떤 도구는 상대적으로 소외되어서 결과적으로 효율 차이가 발생하는 것으로 보인다.

Measurement

빌드 시스템 자체와는 별개로 흥미로웠던 것은 빌드 시스템의 각 요소에 대한 필요성을 실제 데이터로 증명하고, 빌드나 빌드 시스템의 개선을 위해서도 측정의 중요성을 지속적으로 강조하고 있다는 점이다. 즉,  ‘Cannot improve what we don’t measure’라는 모토인데, 엔지니어로서는 더 이상 공감하기 어려운 이야기라고 생각한다. 단기간의 개선은 직관이나 추측이 잘 먹힐지는 몰라도, 장기간에 걸친 개선에 있어서 측정은 필수적이다.

현실에서는 time-to-market 요구사항이나 엔지니어 개인의 취향, 심리적 상태와 같은 요소 때문에 측정이 희생되는 모습을 자주 보게 된다. 다소 공격적으로 얘기해서, 합리적인 trade-off를 통해 희생하거나, 다른 요소에 의해 제약 받지 않은 상태임에도 불구하고, 측정을 소홀히 하는 엔지니어는 엔지니어로서의 기본적인 소양이 부족한 것이 아닌가 생각을 해본다.

Development at the Speed and Scale of Google 더 읽기"

mediocrity was a failure of will, not talent

Whatever failing prompted Cutler to mistreat people, his capacity for blocking out the ordinary distractions of life was his road to excellence. People rarely achieved greatness because they were too blinded by daily routine even to try anything extraordinary. For Cutler mediocrity was a failure of will, not talent.

커틀러가 사람들을 학대하게 만드는 것이 무엇이었든 간에, 그를 뛰어나게 만드는 것은, 바로 일상 생활에서 집중을 방해하는 것들을 차단해내는 능력이었다. 사람들이 훌륭한 무언가를 이루어내기 어려운 이유는, 반복되는 일상에 잠식되어, 더 이상 평범하지 않은 무언가를 시도하지 못하기 때문이다. 커틀러가 생각하기에, 뛰어남에 미치지 못하는 평범함이란, 그저 의지의 부족이지, 재능의 부족이 아니었다.

— quoted from Showstopper!, Pascal G. Zachary

mediocrity was a failure of will, not talent 더 읽기"

Great teams have members that defy roles

The best teams I have worked in and with are those that defy the traditional roles and responsibilities.  Putting up artificial walls between extremely closely related disciplines can only be detrimental to getting great team work.  Any given set of devs, testers and PMs working on a feature have a different set of skills and experience they bring to the team.    Putting in place a structured set of expectations denies this fact.  If the developer is more senior and experienced in an area, then  you may want them leading more of the design of the feature, not just the implementation.   Likewise if the PM is very senior and an experienced software architect, you may want them to have more of an input in the actual implementation decisions.

내가 함께 일했던 최고의 팀들은 전통적인 역할과 책임에 반하는 팀들이었다. 서로 밀접한 관련을 갖는 분야들 사이에 장벽을 세우는 것은 팀워크에 방해가 될 뿐이다. 하나의 기능을 위해 모인 개발자, 테스터, PM들로 구성된 팀은 서로 다른 기술과 경험의 집합을 보유하고 있다. 정해진 역할과 책임을 강제하는 것은 이러한 사실을 부인하는 것이다. 개발자가 해당 분야에 있어서 경험이 깊다면, 구현 뿐만 아니라 좀 더 많은 기능 설계를 이끌어가기를 바랄 것이다. 마찬가지로, PM이 매우 숙련된 소프트웨어 아키텍트라면, 실제 구현 결정에 있어서 좀 더 관여하기를 원할 것이다.

— quoted from ‘Great teams have members that defy roles‘ by Brad Adams

Great teams have members that defy roles 더 읽기"