Twitter Flock Seoul 2015 후기

어제 서울 강남구 논현동 파티오나인에서 Twitter Flock Seoul이라는 개발자 행사가 개최되었습니다. 현재는 다른 직장에 다니고 있지만 전 직원으로서 참석하지 않을 수 없는 행사였는데요. 꽤 인상깊기도 했고 부득이하게 참석하지 못하신 지인들을 위해 후기를 작성해 보았습니다.

기본적으로 이 행사는 트위터에서 발표한 Fabric이라는 개발 킷을 소개하는 자리였습니다. 단순히 전형적인 제품 홍보였다면 그다지 재미없었겠지만 그 실행 방법이 아주 훌륭해서 전혀 지루함 없이 흥미진진하게 이야기를 들을 수 있었습니다.

Fabric은 일반적인 모바일 앱을 구현하는 과정에서 겪게 되는 문제를 다음의 영역으로 나눠 솔루션을 제공하고 있습니다.

  • Stability
  • Distribution
    • Twitter Kit을 통한 앱내 Tweet 및 Timeline 내이티브 임베딩 및 Tweet 올리기
  • Monetization
    • MoPub을 통한 내이티브 광고 임베딩
  • Identity
    • Digits를 통한 전화번호/SMS 기반의 비밀번호가 필요 없는 사용자 인증
  • Mobile Analytics
    • Google Analytics와 유사한 Answers라는 모바일 앱 사용자 분석 도구

특이할만한 사실은 위 모두가 완전 무료이며 극도로 사용하기 쉽게 만들어져 있다는 것입니다. 지금까지의 웹 서비스들이 RESTful한 웹 API를 통해 자사 서비스와의 연동을 유도했다면, Fabric은 그에서 한 발 더 나아가 아예 자사 서비스와의 연동을 이미 구현한 개발 킷을 제공해 그 장벽을 한 번 더 낮추었습니다. Twitter는 더 많은 앱들이 오동작 없이 예측 가능한 방식으로 연동되니 좋고, Twitter와 연동하는 앱은 귀찮은 연동 작업이 단 몇 줄의 코드만으로 깔끔하게 끝나버리니 윈-윈이라고 할 수 있겠습니다.

게다가 Crashlytics, Digits, MoPub, Answers 같은 기능은 Twitter Timeline과 연동하지 않아도 그 자체만으로 대단히 유용하므로 앱을 이제 막 개발하려고 하는 스타트업 입장에서는 안 쓸 이유가 없겠습니다. Twitter 입장에서는 이런 개발자 대상의 서비스를 제공함으로써 앱의 종류, 지역, 기종 등의 다양한 정보를 얻어 자사의 서비스 개선이나 신규 서비스 런칭에 중요한 자료로 활용할 수 있을 것으로 보입니다.  이 부분 또한 기존의 end-user 중심의 자료 분석 기조를 넘어서는 신선한 시도라고 생각합니다.

물론 아이디어가 아무리 좋아도 실제로 개발자가 가져다 썼을 때 그 경험이 좋지 못하면 인기를 끌지 못할 텐데요. 다행이도 Fabric의 개발자 편의성은 상당해 보였습니다.

일단 앞서 말한 모듈들을 가져다 붙이는 과정이 매우 간단하고, 실제 작성해야 하는 코드의 양도 대단히 적었습니다. 예를 들어 Digits나 Twitter Timeline을 임베드하는데는 5줄 내외의 Swift 코드면 충분했습니다.  그 뿐만 아니라, 데스크탑용 Fabric 앱이 트레이에 상주하면서 각 모듈별 개발 환경 설징, API 문서 열람, code snippet의 copy & paste를 단일 창구에서 제공하기 때문에, 사용 편의성 면에서 대단한 노력을 기울였음이 느껴졌습니다. 그 외에도 API를 통해 임베드하고자 하는 모듈의 색을 바꾼다거나 하는 테마 커스터마이제이션도 가능하여 모듈이 앱 속에 잘 녹아들어가게 하는 것이 가능했습니다.

이번 행사는 Fabric이라는 모듈 자체의 유용함 외에도 몇 가지 참고할 만한 요소가 있었는데, 간단히 나열하면 다음과 같습니다.

이미 10여개 도시에서 비슷한 내용의 발표를 해서 그런지, 진행이나 발표 내용이 대단히 매끄러웠습니다.  특히 Fabric의 각 기능을 Cannonball이라는 데모용 앱의 개발 과정과 엮어 스토리텔링 형태로 전달하였는데, 상당히 설득력이 있었습니다. 발표가 끝난 뒤에는 바로 Fabric을 실제 사용하고 있는 BuzzFeed나 PopCap같은 유명 해외 업체와의 인터뷰 영상을 재생해 분위기를 고조시켰습니다. 또한 국내 개발자들이 적용에 회의적일 수 있다는 점을 고려했는지 ‘Between‘의 VCNC나 ‘배달의 민족‘의 우아한 형제들과 같은 업체 개발자들이 직접 단상에 올라 질의 응답을 가졌습니다. 업체들은 주로 Crashlytics를 사용하고 있었습니다만, 그 외에도 MoPub을 통해 해외 사용자들에게도 안정적인 광고 노출이 가해져 광고 매출이 10~15% 증가했다는 업체도 있었고, Digits 도입 계획을 발표한 업체도 있었습니다. 다만, Timeline 및 Tweet 임베딩은 아쉽게도 국내에서의 실 사용례가 없는 듯 했습니다.

각 모듈을 개별적으로 소개하는 세션에서는 단순히 모듈 사용법만을 다루는 기존의 홍보 발표와는 달리, 해당 모듈을 개발하게 된 구체적인 배경 및 개발 과정의 이야기를 먼저 풀어 놓는 것이 인상적이었습니다. 개발 과정의 이야기도 듣고 배울 수 있고, 결과적으로는 그런 다양한 도전을 이미 해결한 우리의 모듈을 무료로 써 달라는 홍보 그 자체에도 설득력을 부여했다는 점에서 훌륭한 발표들이었습니다.

더욱 재미있는 것은, 좋은 모듈을 무료로 공개하고 홍보하는데서 그친 것이 아니라, hatch라는 스타트업 공모전까지 열어 Fabric을 이용해 개발하는 스타트업들이 경쟁하며 홍보하고, 또 투자까지 받을 수 있는 자리를 마련했다는 점입니다. 이미 완성되어 서비스중인 앱보다는 이제 막 시작하거나 성장하기를 원하는 앱에서 Fabric을 도입하기로 마음먹는 것이 더 쉽다는 점을 고려한 좋은 결정인 듯 합니다.

그 외에도, 행사 자체뿐만 아니라 행사가 끝난 뒤의 follow-up도 마음에 들었다는 점도 언급하고 싶습니다.  행사가 끝나고 감흥이 채 가시기 전인 바로 다음 날, 참석자들에게 다시 한 번 메일로 Fabric을 권한 것은 자칫하면 잊고 지나쳐버릴 수도 있을 분들을 위한 배려이자 ‘한 번 써 보고 싶다’라는 마음을 실천으로 옮길 수 있도록 하는 자극제였습니다.  또, 행사 만족도 설문 조사 문항도 단순 텍스트가 아닌 실제 세션 진행중에 찍은 사진들로 비주얼하게 만들어져 있어서 기억을 되살리는 데 많은 도움이 되었습니다.

아시다시피 Twitter는 Google이나 Facebook과 같은 강자로부터 상당한 압박을 받고 있는데요. 이러한 상황을 타개하기 위해서 나온 것이 Fabric이 아닌가 하는 생각이 들었습니다. 선두주자들은 생각할 수 없는, 2, 3인자이기에 가능한 이런 신선한 시도는 앞으로 플랫폼 전략을 실행하고자 하는 다른 기업들에게도 훌륭한 영감을 제공했을 것으로 생각합니다.

자기 소개 쓰기

국내 오픈 소스 관련 인물들의 인터뷰를 엮은 책이 나온다고 해서 인터뷰를 받았었는데, 얼마 전 책에 들어갈 간단한 자기 소개를 부탁받았다. 내 이름이 들어간 책이라는게 생겨난다니 묘하다. 그리고 속내를 말하자면 여유로이 털 핥는 고양이마냥 아무 일 없는 듯 얌전만 떨기보다 오랫동안 남게 될 책이라는 매체에 기록되니만큼 나의 좋은 부분을 세련되게 노출하고 싶은 마음이 있다.
책의 본문이 되는 인터뷰 내용이야 기본적으로 대화에 기초하기 때문에 치밀한 자기 홍보의 여지가 딱히 없지만, 이 자기 소개는 그렇지가 않다. 예전에 별 생각 없이 써 두었던 발표자 소개를 갖고 한참을 이리 고치고 저리 고치기를 수십분, 아래와 같은 거창한 – 또는 얼굴 빨개지는 – 결과물이 나왔다.

이희승은 자바 가상 머신 기반의 대표적 네트워크 어플리케이션 프레임워크인 네티 프로젝트아파치 미나 프로젝트를 창시한 소프트웨어 엔지니어입니다. 연세대학교 1학년에 재학중이던 1999년 말, (주)아레오 커뮤니케이션즈 (現 (주)스탠다드 네트웍스)에서 자바 프로그래밍 언어를 이용한 5개 이동통신사와의 단문 메시지 전송을 국내 최초로 상용화한 이래, 분산화된 대용량 단문 메시지 전송 게이트웨이, RPC 서버와 같은 고성능 네트워크 어플리케이션을 꾸준히 개발해 왔습니다. 아레오 커뮤니케이션즈, 첫눈, nhn, 레드햇을 거쳐 현재는 트위터에서 근무하며 네티 프로젝트의 성능과 편의성을 한 단계 끌어올리기 위해 팀원들과 함께 노력하고 있습니다. 일상과 업무, 가족과 나 사이에 끝없이 번뇌하며 가족의 소중함을 절감하는 자택 근무 7년차입니다.

사실 개인에 대한 소개나 칭찬이야말로 타인이 해 주어야 가치가 있는 법이지만, 그런 사치는 아마도 쉽게 허락되지 않을 것 같다. 어차피 본 웹 사이트의 자기 소개 업데이트도 오래 되었으니 한 번 쯤은 해야 할 일이었다.
한편으로는 이것 저것 남의 시선 따지다가는 평생 껍데기만 남기게 되는 것은 아닐까 걱정도 되었었다. 예전처럼 시시각각 변하는 별의 별 생각들을 날 것 채 풀어놓는 것까지는 힘들지도 모르겠다. 하지만 그 누구의 시선도 개의치 않고 내 생각의 흐름을 이 곳에 잡아두고 싶은 간절한 마음은 영원할 것 같다.

재택 근무 5년차의 고민

2007년부터 주욱 재택 근무를 해 오고 있다.

많은 재택 근무 관련 기사들이 일과 가정을 분리할 필요가 있음을 강조한다. 그러나 아이러니하게도 철저한 분리는 재택 근무가 갖는 장점을 퇴색시키면서 가족에 대한 양심의 가책까지 만들어낸다. (바로 옆 방에 있으면서 자녀와 놀아주지도 않고 가족들이 떠들거나 TV를 보게 놔둘 수도 없다! 아내가 요리하고 있으면 아이를 돌보지 않으면 아이가 심심해할 텐데..)

그렇다 보니 이도 저도 아닌 근무 환경이 쉽게 조성된다. 업무의 특성상 장시간 몰두하지 않으면 진도가 빠지지 않는다. 끊임없이 외부 자극에 노출이 되다 보니 일이 안된다. 일이 안되니 놀면서도 일 생각이 나고, 놀 때 제대로 못 노니 일하면서도 자꾸 가족이 신경쓰인다. (내 커리어는 여기서 끝장나는가?) 균형있는 분리? 그것은 철저한 분리의 다른 이름이 아닐까 싶을 정도다.

그래. 이제부터는 방문을 꼭꼭 닫아 놓고 음악을 충분히 높여 틀고 일하는거야. 가끔씩 울리는 초인종 소리에도 뛰쳐나가지 않는거야. 그리고 흐름을 탔거나 꼭 해 두고 싶은 업무가 있다면 야근을 할 수도 있겠지. 그렇게 나는 주 40시간을 꽉꽉 채울거야.

이걸 못 해내거나 해냈음에도 일이 잘 되지 않는다면 아마도 미국에 있는 사무실에 출퇴근을 하는 게 맞겠지..

How to Rip Audio CD as FLAC with Embedded Cue Sheet in Ubuntu Linux

I wrote a pretty simple shell script that rips an audio CD as a single FLAC file with embedded cuesheet for Linux. It ensures secure rip by ripping a disc three times with cdparanoia and comparing their checksums. It has been tested on Ubuntu 12.04 Precise, but it should work for any Linux system such as Fedora.

Usage

Just run the script in your shell prompt, it will retrieve the ID of the disc and generate a <DISCID>.flac

Required packages

Install the following packages first:

apt-get install cd-discid cdrdao cuetools flac cdparanoia

Install the ripper script

Put the following script into your path (e.g. /usr/local/bin). You might want to change the DEVICE variable (e.g. /dev/cdrom). If you want even more secure rip, you can set the COPIES variable to a greater value (e.g. 5).

#!/bin/bash
# /usr/local/bin/rip-audio-cd
DEVICE="/dev/sr0"
COPIES="3"

DISCID="`cd-discid $DEVICE 2>&1 | egrep -o '^[0-9a-z]{8}'`"
if [ "$?" != "0" ]; then
  echo "Failed to retrieve disc ID."
  exit 1
fi

echo -e "33[1;32mDisc ID: $DISCID33[0;0m"
rm -f "$DISCID".*

echo -e "33[1;32mExtracting a cue sheet:33[0;0m"

cdrdao read-toc --device "$DEVICE" --datafile "$DISCID.wav" "$DISCID.toc" || exit 2
cueconvert -i toc -o cue "$DISCID.toc" | grep -vP '^ISRC "' > "$DISCID.cue" || exit 2

CHECKSUM=''
I=0
for ((I=0; I < $COPIES; I++)); do

  echo
  echo -e "33[1;32mPass $((I+1)) of $COPIES33[0;0m:"

  if [[ $I -eq 0 ]]; then
    OUT="$DISCID.wav"
  else
    OUT="$DISCID.new.wav"
  fi
  rm -f "$OUT"

  cdparanoia -zX '1-' "$OUT"
  if [ "$?" != "0" ]; then
    rm -f "$DISCID".*
    echo "Failed to rip a disc."
    exit 3
  fi

  C="`sha1sum "$OUT" | cut -f1 -d' '`"
  if [[ "x$CHECKSUM" = 'x' ]]; then
    echo "Checksum: $C"
    CHECKSUM=$C
  else
    rm -f "$OUT"
    if [[ "$CHECKSUM" != "$C" ]]; then
      echo "Mismatching checksum: $C"
      exit 4
    else
      echo "Matching checksum: $C"
    fi
  fi
done

eject "$DEVICE" &

echo
echo -en "33[1;32mCompressing...33[0;0m"
flac -f -V --replay-gain --best --cuesheet="$DISCID.cue" "$DISCID.wav"
if [ "$?" != "0" ]; then
  echo "Failed to encode the ripped tracks."
  exit 5
fi

rm -f "$DISCID.wav" "$DISCID.cue" "$DISCID.toc"

echo
echo -e "33[1;32mAll done: $DISCID.flac33[0;0m"

Fill metadata

Unfortunately, the script does not fill the metadata such as track information and cover art. I usually rip a bunch of discs first using this script and then fill their metadata in Windows. Here’s the steps I take:

  1. Load the FLAC file into foobar2000
  2. Fill the track information.
    • Select all tracks, right-click them, and choose ‘Tagging -> Get tags from freedb’.
    • If not found from freedb, you can always fill manually by choosing ‘Properties’.
  3. Update ReplayGain information.
    • Select all tracks, right-click them, and choose ‘ReplayGain -> Scan selection as a single album’.
  4. Download album arts (front cover, back cover, disc) using Album Art Downloader XUI
  5. Attach the downloaded album arts into the FLAC file using foobar2000.
    • Select all tracks, right-click then, and then choose ‘Tagging -> Attach pictures’.

How to build OpenJDK 7 on Ubuntu 11.10 and 12.04

This article will guide you to build OpenJDK in your 64-bit Ubuntu Linux (11.10 Oneiric Ocelot or 12.04 Precise Pangolin) without many trials and errors. It is based on the official OpenJDK build README, but the README file is out-of-date, and that’s why I wrote this guide.

Assumptions

  • You run 64-bit Ubuntu.
  • Your Sun/Oracle JDK 6 is installed at $HOME/.local/opt/jdk/1.6.
    • You can use your preferred installation location but you will have to adjust the scripts appear in this article.
  • You installed Apache Ant and the ant command is in your PATH variable.
  • You keep your development stuff at $HOME/Workspace.
    • This guide keeps OpenJDK source code at ~/Workspace/openjdk and HgForest at ~/Workspace/hgforest. However, you can keep them in different locations and adjust the scripts appear in this article.

Install required packages

apt-get install mercurial gawk g++ libcups2-dev libasound2-dev libfreetype6-dev libx11-dev libxt-dev libxext-dev libxrender-dev libxtst-dev libfontconfig1-dev

Install HgForest

hg clone https://bitbucket.org/pmezard/hgforest-crew/overview/ "$HOME/Workspace/hgforest"

Edit your $HOME/.hgrc to add these lines:

[extensions]
forest=~/Workspace/hgforest/forest.py

Clone the OpenJDK 7 repository

hg fclone http://hg.openjdk.java.net/jdk7u/jdk7u "$HOME/Workspace/openjdk"

Apply some patches

If you need to apply some patches, do it now, and then continue to build.

Build the OpenJDK 7

cd "$HOME/Workspace/openjdk"
unset JAVA_HOME
export LANG=C
export ALT_BOOTDIR="$HOME/.local/opt/jdk/1.6"
export ALLOW_DOWNLOADS=true
export EXTRA_LIBS=/usr/lib/x86_64-linux-gnu/libasound.so
source jdk/make/jdk_generic_profile.sh
make sanity && make && echo 'Images at: build/linux-amd64/j2sdk-image'

I usually write a build script that automatically sets the environment variables and calls make.

Once the build process is successful, you will find your OpenJDK image at build/linux-amd64/j2sdk-image.

용기를 낼 시간

과거는 흥미롭다.

돌이킬 수 없기에 받아들인 채 나아가야 한다. 하지만 그대로 묻어두기에는 너무나 아쉽다.

먼지를 털어내려 하면 그것은 두려움이 대상이 되기도 한다. 미숙했던 자신과 마주하게 되니까.

흡사 하이젠버그의 상자와도 같다는 생각이 든다. 돌아보는 것만으로도 스스로의 변화를 느낀다.

현재나 미래뿐만 아니라 과거마저도, 시간은 언제나 내게 용기를 요구한다.

그 날을 향해

피곤하지만 잠은 잘 오지 않는다.

샌프란시스코에서도 체하지 않았는데 오히려 편안한 집에서 갑자기 긴장을 하니 쉽게 체해버렸다. 아마도 나의 위장은 아직도 시차 적응중인 듯 하다.

만약 그 때 십이지장이 천공되지 않고 궤양이 잘 나아 수술을 받지 않았다면 지금의 나는 어떤 모습일까.

필요없는 상상이다. 받아들이고 극복하는 쪽이 좋다.

이제는 갑자기 어지럽거나 두근거려도 쉽게 당황하지 않는다. 약물도 거의 쓰지 않는다.

그것으로 충분하지는 않다. 위장이 더 튼튼하기를 바란다.

아마도 이런 걱정 언제 했냐는 듯 살아가는 바로 그 날만큼 멋진 날도 없겠지?

Self-estimation

큰 두려움을 느낀다. 고비를 넘을 때마다 몰려왔던 긴장이 풀리고 피곤이 쏟아진다. 한편으로는 얼마나 멀리 갈 수 있는지 끝장을 보고 싶다. 나의 정신과 육체는 그 모든 것을 견뎌낼까, 아니면 어느 순간 무너져내릴까.

두려움을 넘어서

열렬히 원하지는 않았지만 선택한 길이 있다. 안정적이기에 남들이 내가 되돌아가기를 바랐던 그 곳으로 나는 돌아갔고, 그다지 마음에 딱 들지는 않았지만 중요한 역할을 맡았음에 스스로를 위안했다. 변화에 대한 두려움도 있었기에 그것은 좋은 선택처럼 보였다.

아마도 내가 잠시 미쳤었나 보다!

이젠 됐다. 내 멋대로 하겠다. 그 누가 나에게 뭐라 해도 나는 내 멋대로 해야 겠다.

How to Start Pidgin Minimized (or always start Pidgin with its buddy list invisible)

Pidgin does not have an option that allows a user decide whether the Pidgin buddy list window starts minimized or not. It just remembers the state of the window when it quits, and restores the last window state.

The last window status is stored in $HOME/.purple/prefs.xml:

...
<pref name='pidgin'>
  ...
  <pref name='blist'>
  ...
    <pref name='list_visible' type='bool' value='0'/> <!-- 0: invisible, 1: visible -->
    <pref name='list_maximized' type='bool' value='0'/> <!-- 0: normal, 1: maximized -->
  ,,,
  </pref>
</pref>
...

When the list_visible property is set to 0, you will see Pidgin minimizes its buddy list window into the system tray (or the notification area). How can we make sure it’s always set to 0 when Pidgin updates it when it exits? Let’s write a shell script:

#!/bin/bash
perl -pi -e "s/pref name='(list_visible|list_maximized)' type='bool' value='[1-9]'/pref name='$1' type='bool' value='0'/gi" ~/.purple/prefs.xml
/usr/bin/pidgin &

The first perl command searches the list_visible and list_maximized properties and replaces their values with 0 before Pidgin starts. Problem solved!

Not that I like this workaround. I still just can’t believe there is no option about this.