2014년 5월 30일 금요일

구글의 클라우드 컴퓨팅 아키텍처와 오픈소스 컨테이너 프로젝트 Docker

구글의 클라우드 플랫폼 담당 시니어 소프트웨어 앤지니어인 Joe Beda씨는 Containers At Scale이라는 타이틀로 구글의 스케일링 아키텍처에 대해서 설명하는 슬라이드 자료를 발표했다.


오늘은 이 자료를 통해 세계최고의 IT서비스 기업중 하나인 구글이 채택하고 있는 클라우드 아키텍처를 살펴보고자 한다.


구글의 모든 서비스들은 컨테이서안에서 실행된다. 

(Everything이 굵은 글자로 강조되고 있음을 놓치지 말자!)
  • 구글 사내의 어플리케이션을 포함한 구글의 모든 서비스들은 모두 이 컨테이너 안에서 실행되고 있다. (역자주: 현재 구글이 퍼블릭 크라우드 서비스로 제공하고 있는 App Engine또한 이 컨테이서 상에서 동작되고 있다. 자세한것은 App Engine Architecutre 문서를 살펴보자.)
  • 구글은 매주 20억개 이상의 컨테이너를 기동하고 있다. (역자주 : 세계 인구는 2013년 1월 기준으로 71억명 이다!) 


컨테이너란?

컨테이너는 프로그램이 작동하기 위한 최소한의 요소들을 묶어 패키징한 것으로 OS보다 작으면서 독립적인 배포와 실행을 가능하게 하는 일종의 가상 머신이다. 대표적인 오픈소스 컨테이너 기술인 docker가 최근 급속도로 인기를 끌고 있다. 대부분의 컨테이너 스텍은 LXC(Linux Containers)를 기초로 만들어졌으며 docker또한 LXC와 호환이 된다.

컨테이너가 동작하는 아키텍쳐 레이어

파란색 부분은 시스템 전체에서 공유되는 부분이며 노랑색 부분이 개별 컨테이너에 해당되는 부분이다.

여기서 컨테이너 아키텍처를 잘 모르시는 분들을 위해 이 추가로 설명을 해 보도록 하겠다.

가상환경에 어플리케이션을 배포하고자 할때 흔히 겪는 문제들은 다음과 같다.

  • 가상환경 서버라고는 해도 환경변수나 언어버전, 라이브러리 버전이 달라 어플리케이션이 동장을 하지 않는다
  • 개발환경에서는 잘 움직이다가도 프로덕션 환경에서 제대로 움직이지 않는다
  • 기존환경의 가동을 중단시키지 않으면서도 새로운 어플리케이션이나 기능을 추가하고자 한다


이를 해결하기 위해 등장한 것이 지금부터 소개할 차세대 가상화 오픈소스 프로젝트인  docker이다.


차세대 오픈소스 가상화 프로젝트 docker

docker는 Go언어로 작성되어 있으며 오직 리눅스 커널에만 의존 한다. 다시 말해 자바의 바이트 코드가 자바VM이 작동되는 곳 이라면 어디든지 작동 가능했던 것 처럼 docker는 리눅스 커널만 작동 가능한 환경이라면 어느곳 이든 동일한 동작을 보장한다.

이러한 컨테이너 방식의 가상화는 개발자와 운영자에게 어떠한 장점이 있을까?

개발자 입장에서 컨테이너 방식의 가상화 개발은 컨테이너 내부의 관리에만 신경을 써 주면 되고, 한번의 컴파일 만으로도 모든 환경에서동일한 동작을 보장 받게 된다. 패키지의 의존관계나 네이티브 라이브러리, 심지어 DB에 이르기 까지 말이다!
반면 DevOps엔지니어의 입장에서는 한번 설정 만으로 모든 어플리케이션의 배포를 보장 받게 되며, 여기에 운영자에게 여러모로 편리한 로그감시나 리모트억세스, 네트워크설정, 리소스 모니터링 기능이 충실히 따라온다.

docker는 가상 os환경과도 다른데, docker만의 특징을 잘 설명해주는 그림이 여기 있다.


효율성과 편의성. 두마리 토끼를 잡아라!

일반적인 가상OS환경(IaaS)에서는 호스트OS위에 게스트OS가 어플리케이션 수 만큼 올라가야 하므로 게스트OS에 소모되는 리소스 낭비가 많다는 단점을 지닌다. 이에비해 docker engine은 OS자체를 가상화 하는것이 아닌 어플리케이션 작동에 필요한 최소한의 바이너리와 라이브러리만을 가상화 함으로서 이러한 오버헤드를 줄일 수 있게된다. 간단히 말해 docker는 PaaS 클라우드를 구현하기 위한 아키텍처라고 할 수 있으며, 플렛폼 자체의 확장이나 변경이 보다 수월하다는 점에서 기존의 PaaS에서 좀 더 발전된 형태라고 할 수 있다.

docker는 장해 발생시에 그 진가를 발휘하는데, 모든 컨테이너는 고유의 ID를 지니는 동시에 업데이트시에 변경 차분을 보관하기 때문에 장해가 발생되었을 경우 롤 백이 손쉽게 가능하며, 이는 어플리케이션 뿐만이 아니라 DB에도 적용이 된다.


이번에  Joe Beda가 발표한 자료를 통해 구글은 Container Manifest라고 하는 yaml로 작성된 일종의 배포 디스크립터를 독자적으로 개발하여 이용하고 있음을 알 수 있는데, 이를 통해 컨테이너 동작에 필요한 자원 할당과 데이터 소스에 대한 공유를 수행한다. 참고로, 오리지널 사양의 docker는 리눅스의 리소스 제어툴인 cgroups를 이용하여 리소스를 제어한다.
Container Manifest의 상세에 대해서는 구글에서 제공하는 문서를 참고하길 바란다.

아마존의 EC2를 사용해 본 사람이라면 어느정도 수긍하겠지만, OS의 가상화는 관리라는 측면에서 보면 물리서버를 운영하는것과 비교해 더 낫다고 말하기 힘들다. 고작해야 하드웨어 관리에 대한 수고를 덜 수 있을 뿐이고, OS를 비롯해 환경변수나 라이브러리를 구축해야 하는 과정은 사실상 동일하다고 볼 수 있다.

또한 오버헤드의 측면에서도 512MB의 메모리를 지닌 가상머신 인스턴스가 어플리케이션에서 사용 가능한 메모리가 절반에도 미치지 못한다는 점을 감안해 본다면 docker 아키텍처의 유용함을 잘 알 수 있을것이다.

  docker아키텍처를 이용한 가상화는 어플리케이션 배포에 소요되는 노력과 오버헤드를 줄여주며, 프로덕션 환경과 개발환경의 차이를 없애주어 요휼적인 리소스 사용과 다양한 장해에 대한 대응을 가능케 해 준다.

구글이 현재 IT계에서 차지하고 있는 위치와 영향력을 감안해 볼 때에, 구글이 채택하고 있는 컨테이너 아키텍쳐는 어떠한 형태로든지 아마존이나 마이크로소프트와 같은 업체들에 영향을 끼칠것이며(이미 아마존은 대응을 시작했다. AWS Adopts Docker Containers For Elastic Beanstalk ) 조만간 클라우드 컴퓨팅의 중요한 흐름으로 우리 앞에 나타나게 될 것으로 예측해 본다.

관련링크

스케일링과 관련하여 프로덕션 환경에서의 Docker적용에 대해서 좀 더 알아보고 싶다면 다음의 링크들이 도움이 될 것이다.


최종 수정일 : 2014년 12월18일

2014년 5월 14일 수요일

TDD는 벌거벗은 임금님의 투명옷인가? (1) - TDD는 죽었다. 테스트여 영원하라!

TDD는 벌거벗은 임금님의 투명옷인가?



지난주 금요일(2014년 5월 9일) 밤 10시.
스텍오버플로StackOverflow를 비롯해 많은 IT커뮤니티를 술렁거리게한 IT업계의 드림매치가 30분간 차분히 이루어졌다.



발단은 Ruby on Rails의 개발자로 유명한 David Heinemeier Hansson(이하 DHH)가 자신의 블로그에 'TDD는 죽었다. 테스트여 영원하라!TDD is dead. Long live testing.'라는 다소 자극적인 제목으로 블로그 포스트를 올린데서 시작되었다.

David Heinemeier Hansson. 덴마크 출신 프로그래머로 Ruby on Rails의 제작자로 알려져 있지만 르망 24에 출전하는등 프로 레이서 로서의 일면도 가지고 있다.(엄친아?) 사진의 포즈는 보통 중딩들이 새로 산 시계를 자랑하고 싶을때 하는 포즈이지만 신경쓰지 말도록 하자.
여기에 XP와 TDD의 창시자인 Kent Beck선생은 RIP TDD 라는 페이스북 포스팅을 통해 DHH의 의견에한 자신의 생각을 밝힌다.

여기에 쌈구경에 재미가 들린 Martin Fowker선생이 멍석을 깔아준다.
바로 구글 플러스를 통해 두사람의 토론을 온라인 생방송 이벤트로 만들어 버린 것이다.
Is TDD dead?

일단 내용이 만만치 않으므로 이번 포스팅은 세 단원으로 나눠서 작성할 예정이다.


  1. TDD는 죽었다. 테스트여 영원하라! - David Heinemeier Hansson의 블로그 번역
  2. TDD여 편히 잠들라 - Kent Beck의 페이스북 번역
  3. TDD는 죽었는가? - DHH, Kent Beck, Martin Fowler의 온라인 토론 이벤트 정리


아직 국내에는 이름이 생소한 DHH이지만 비교적 젊은 나이에도 불구하고 (79년생) 프레임워크에 있어서 Ruby on Rails가 지닌 지위와 영향력을 생각해 본다면 소프트웨어 업계에 있어서 결코 무시할 수 있는 인물이 아니다.

오늘은 첫번째로 DHH의 주장을 담은 블로그의 글을 번역하는것으로 TDD에 대한 논쟁을 시작해 보고자 한다.

TDD는 죽었다. 테스트여 영원하라!

원문: TDD is dead. Long live testing.

테스트 주도Test-first개발 근본주의는 금욕만을 강조한 성교육과 같이 자기혐오를 불러오는 비현실적이자 비효율적인 도덕 캠페인과 같다.

처음시작은 달랐다. 내가 처음 TDD를 접했을때, 그것은 마치 프로그래밍의 신세계가 내 눈앞에서 열리는것 같았다. 그것은 테스트가 없는 세계로부터 테스트를 당연히 여기는 세계로의 의식개혁과도 같은 것 이었다. TDD는 제대로 테스트된 코드가 주는 평온함에 눈을 뜨게 해 주었고, 코드 변경시에 안정감을 가져다 주었다.

테스트 우선 개발은 자전거의 보조바퀴와도 같은것으로, 테스트는 프로그램을 보다 싶도있게 통찰할 수 있게 해 주었으나 나는 곧 그만두었다.

시간이 흐르면서 테스트 우선이란 슬로건은 점점 더 큰고 격렬한 목소리를 내기 시작했다. 테스트우선 개발을 실행하지 않는것은 죄악시 되었고 나 자신도 그러한 근본주의 소용돌이에 휘말려 들었는데, 그것은 마치 종교적인 금욕주의 가르침을 따라가지 못하는 자신이 부끄러워지는 느낌이었다. 그리하여 나도 테스트 우선 개발을 시험해 보기로 했지만 몇주만에 결국 그만 두었다. 테스트 우선 개발이 내 설계를 망쳐놓기 시작했기 때문이다.

테스트 우선 개발은 마치 광신도의 신앙심에 대한 자부심과도 같이, 오직 교리에 적힌 한구절 한마디를 충실히 지키는 것 만이 천국에 이르는 유일한 길이고, 그대로 하지 않으면 지옥에 떨어진다고 하는 희열과 절망의 요요였다. 그리고 그것을 그만둔 나는 모두 함께 가는 버스에서 혼자만 내린 기분이었다.

아마도 처음에는 자동화된 회귀 테스트 따위는 없어도 된다라고 하는 업계의 관행을 부수기 위한 충격요법으로서 테스트 우선 개발이 필요 했을지도 모른다. 아마도 처음에는 글자 곧이곳대로 일상적으로 수행하는 프로그램 개발에 적용하는것을 의도하지는 않았을지도 모른다. 하지만 어찌되었든 시작을 한다고는 해도 금방 중단되기 일쑤였지만, 불경한자를 단죄하는 헤머와도 같이 TDD를 성실히 행하지 않는것은 프로 소프트웨어 개발자로서의 자격이 없다고 낙인 찍혀 버린다. 이것은 리트머스 테스트이다. (단순한 기준으로 흑백이 구분되어버린다는 뜻:역자주)

이제 충분하다. 그만 두겠다. 나 데이빗은 더이상 테스트 우선 개발을 하지 않는다. 나는 더이상 그것에 대해서 사과하지도 숨기지도 않겠다. 나는 TDD가 회귀 테스트에 눈 뜨게 해 준것에 감사한다. 하지만 더이상 TDD에 끼워 맞춰 프로그램을 설계하지는 않는다.

나는 여러분께 TDD적인 접근이 정말로 당신의 시스템의 완전성과 일관성에 어떠한 영향을 주고 있는가를 진지하게 다시 검토해 보기를 권한다. 만약 이것이 정말 좋은것은 아닐지도 모른다는 가능성을 심각하게 받아들이게 된다면, 당신은 메트릭스에 등장하는 붉은 알약을 먹는것이 될 수도 있다. 그리하여 직면하게된 현실 세계는 당신이 원하던 것이 아닐 수도 있다.

그럼 이제 어디를 향해야 하는 것 인가?

최초의 한걸음은 문제의 존재를 인정하는 것 이다. 여러분도 여기까지는 동의할 것으로 생각한다.  그 다음은 메소드에서 시작해 시스템 전체에 이르는 다양한 범위의 테스트에 대해 균형을 잡는것이다. 지금의 열광적인 TDD열풍은 유닛(메소드) 단위의 테스트에 초점이 맟춰져 있다. 왜냐하면 이름 그대로 유닛테스트의 범위는 유닛에 한정되어 버리기 때문이다. (원래부터 테스트 우선 개발의 근거가 이것이다.)
하지만 나는 이것이 올바르지 않다고 생각한다. 테스트 우선개발의 유닛테스트는 중간적인 오브젝트나 간접적이고 지나치게 복잡한 구조를 낳기 십상이다. 게다가 느려지는것을 피하려고 하다보니 데이터베이스나 I/O관련 테스트도 기피하게 된다. 브라우저를 이용한 시스템 전체의 테스트도 지양하게 되어 버린다. 그 결과, 진정 무서운 괴물과도 같은 프로그램 구조가 탄생하게 된다. 서비스오브젝트라던지 커맨드패턴이 형편없이 얽히고 설킨 정글과도 같은 아키텍쳐 말이다.

나는 전통적인 의미의 유닛테스트는 거의 하지 않는다. 모든 의존관계를 목(Mock)으로 하면, 수천건의 테스트가 수초만에 끝나는 유닛테스트 이지만, 레일즈Rails 어플리케이션의 테스트에 있어서 좋은 방법은 아니라는, 단지 그 이유 한가지이다. 나는 실제레코드를 직접 데이터베이스에 억세스하여 동작시키는 방식으로 테스트를 진행한다. 상위레이어에는 컨트롤러 테스트가 있지만, 나는 어느쪽인가 하면 상위레이어에 대한 시스템 테스트는 Capybara나 이와 비슷한 것을 사용하여 테스트하는 편이다.

나는 이것이 우리가 가야 할 방향이라 생각한다. 유닛테스트의 중요도를 내리고, 설계의 일부로서 테스트 우선 개발을 사용하지 않는것이다. 그리고, 보다 시간이 오래 걸리긴 하지만 시스템 테스트의 중요성을 부각시켜야 한다.(게다가, 클라우드의 등장으로 테스트조차도 클러스터링이 가능해 짐에 따라 더이상 시스템 테스트도 느리지만은 않다.)

Rails는 이러한 전환에 도움이 된다. 오늘, 우리는 풀 시스템 테스트 자동화를 장려하기 위해 아무것도 하지 않는다. 정답은 미리 준비되어있지 않다. 단지 실수를 고쳐나갈 뿐이다. 하지만, 여러분은 굳이 실수를 할 때까지 기다릴 필요가 없다. 오늘 당장 Capybara를 돌려보라. 그리고 내일이면 좋은 아이디어가 우리들 머리속에 가득할 것이다.

자, 우선은 심호흡을 하자. 우리가 지금 하려는 것은 신성한 암소를 도살하는 것 이다. 고통스럽고 피를 보는 과정이 수반될 것이다. TDD는 이미 성공적으로 많은 프로그래머들의 머리속에 자리잡고 있다. TDD는 그들이 하는 행위가 아닌 그들 자신이 되어버린 것 이다. 그러한 사람들을 원래대로 돌리기 위해서는 커뮤니티를 만들어 진지하게 임하지 않으면 안되고, 시간또한 오래 걸릴 것 이다.

여기서 우리가 저지를 수 있는 최악의 선택은 또다른 테스트 종교를 만드는 것이다. 이를테면 "시스템 테스트야 말로 진리이다!"와 같은 또다른 황금소의 우상을 만드는 모습이 눈앞에 선하다. 제발 그러지는 말았으면 한다.

그렇다. 나에게 있어서 테스트 주도 개발은 죽었다. 하지만 그 죽음을 축하하며 무덤앞에서 춤을 춘다던지 단점을 조롱하기 보다는, TDD가 소프트웨어 개발에 가져온 기여에 존경을 표하고자 한다. TDD는 우리들의 역사에 중요한 족적을 남겼다. 그리고 지금은 그 다음을 향해 가야할 시간이다.

테스트여 영원하라!

2014년 5월 6일 화요일

속도의 선순환 : 빠르게 진행하는것의 중요성에 대하여 by Randy Shoup

4월 30일 일본 동경에서 개최되었던 QCon Tokyo 2014에서 가장 인상깊었던 Randy Shoup씨의 기조연설 "속도의 선순환 : 빠르게 진행하는 것의 중요성에 대해서 구글과 eBay에서 배운것The Virtuous Cycle of Velocity: What I Learned About Going Fast at eBay and Google"의 내용을 요약해 소개해 보고자 한다.

연사인 Randy Shoup씨는 20년 경력의 베테랑 앤지니어로 eBay와 구글의 엔지니어링 디렉터를 거쳐 현재는 War commander로 유명한 게임회사인 KIXEYE의 CTO를 맡고있다. (개인적으로 우연의 일치인지는 모르겠으나 요즘 읽은 책이나 만났던 사람중에 엔지니어의 최종 테크트리로 게임 개발자를 택한 사람들이 많았다.)

맨 왼쪽부터 Randy Shoup(KIXEYE), Marco Cecconi(Stack Overflow), Eugene Ciurana(Yahoo,Summly), 그리고 영국인 앤지니어인 Andrew.

강연내용 요약

QCon의 강연내용을 간단히 요약해 본다.
QCon Tokyo 2014의 비디오는 아직 공개되지 않았기에 Flowcon 2013에서 동일한 타이틀로 진행한 강연영상과 QCon에서 작성한 메모를 이용해 작성하였다.

The Virtuous Cycle of Velocity: What I Learned About Going Fast at eBay and Google by Randy Shoup - Flowcon 2013

기술


A클래스 개발자를 채용하라

  • 최상위 개발자와 최하위 개발자의 생산성의 차이는 10배에 달한다.
  • 채용의 선순환과 악순환 : A클래스 개발자는  A클래스 개발자를 뽑지만 B클래스 개발자는 C클래스 개발자를 뽑는다. 왜냐하면, A 클래스 개발자는 다른 A클래스 개발자가 자신의 자리를 위협한다고 생각하지 않지만  B클래스 개발자는 다른 B나 A클래스 개발자가 자신의 자리를 빼앗을지도 모른다고 생각하기 때문이다. 그 결과 A클래스를 뽑은 개발자 그룹은 인재의 질이 시간이 지나도 떨어지지 않지만 B클래스 이하를 뽑은 개발자 그룹은 인재의 질이 갈수록 떨어지게 되어 있다. - 구글이 잘 하고 있는것.
이번 QCon내내 지겹게 들었던 말 이다. A클래스 개발자를 채용하라. 유니콘 개발자를 채용하라. 멀티 플레이어를 채용하라.


사람이 우선이다

  • 소프트웨어 기업에 있어서 사람은 가장 중요하면서 대체불가능한 자산이다.
  • 사람은 부품이 아니며 대체 불가능하다.
  • 나쁜 예 : 예전 eBay의 "Train seats" (역자 주: eBay 특유의 공수계산법. 1명의 개발자가 3주동안 진행할 수 있는 일의 양을 말한다. 전통적인 man-month와 동일한 개념으로 2014년인 현 시점에서는 더이상 사용하지 않는듯 하다.(아시는분은 댓글 요망) 자세한것은 The Journey of a Product on eBay – from Idea to Rollout을 참조)
    • man-month기반 관리는 개발자의 긍지와 주인의식을 무너트린다.
  • 사람은 자산이지 원가 절감의 대상이 아니다.
  • 개발자가 회사에게 있어서 소중한 존재라는것을 느낄 수 있도록 하라 - 구글이 잘 하고 있는것. 자신이 소중하게 다루어진다는 것을 느낄수록 더 열심히 일한다.

인재 채용의 선순환 : 인재의 질이 유지됨

인재 채용의 악순환 : 인재의 질이 꾸준히 나빠짐

서비스 개발

  • 작은팀 - 아마존의 피자 두판 팀: 팀 인원수는 피자 두판으로 끼니가 해결 될 수 있는 인원 이하로 유지하라.
  • 잘 정의된 인터페이스 - 팀은 회사의 나머지 부분들과 효율적으로 의사소통을 할 수 있도록 적절한 의사 소통 통로를 지녀야 한다.
  • 완벽하게 독립적으로 운영하라 - 팀에게 최대한의 자치권을 부여하라.
  • 자율성과 책임성 - 스스로 결정하고 스스로 책임지도록 하라. 구글은 모든 서비스에 사용할 언어와 미들웨어, 플랫폼을 아무런 제약없이 팀 내부에서 자체적으로 결정할 수 있다.대신, 그에 따른 책임도 스스로 져야만 한다.

팀 운영에 있어서 가장 중요한것은 주인의식이다. 권한과 책임 없이는 주인의식도 생기기 어려울 것이다.

품질 원칙

  • 자동화 테스트는 일의 진행을 빠르게 해 준다
    • 자동화 테스트는 안심감을 준다
    • 자동화 테스트는 과감한 리팩토링과 수정을 가능하게 함
    • 버그를 잡기 더 쉬워지고 더 빠르게 발견할 수 있음
  • 좋은건 알지요. 하지만 시간이 없다구요!
    • 당신이 틀렸다. 똑같은일을 계속해서 반복 하게 될 것을 생각하면 어느쪽이 더 시간 절약이 되는가?

기술적 채무의 악순환과 기술적 자산의 선순환

  • 자산을 저축할 것인가 채무를 늘려 나갈 것인가

기술적 자산의 선순환

기술적 채무의 악순환



품질관리의 자동화

  • 올바른 형태의 개발이 쉬워짐
  • Mocking/테스팅 프레임워크의 사용
  • 모니터링
  • 위험에 대한 경고(Canarying)


품질은 절대 타협 대상이 아니다

  • 품질(신뢰성, 스케일링)은 영순위 사항이다.
  • 구글은 잘 했으나 예전 eBay는 잘 못했음.

품질관리의 선순환 : 선순환의 시작점은 테스트이다



Randy씨는 구글에서는 약 1년2개월을, eBay에서는 6년 8개월을 일했었는데 예전 eBay의 개발 방식에 대해서는 많은 후회가 있었던듯 싶다. 반면 구글에서의 경험은 대부분 긍정적으로 평가하고 있다.


문화


책임과 주인의식

  • 개인과 팀에게 자율을 보장하라.
  • 성공의 열쇠는 책임의식.
  • 약속을 지켜라 - 무언가를 하겠다고 말했다면 반드시 실행하라.

 필자 또한 격하게 공감하는 내용이다. 주인의식이 없이는 최선을 다하기가 어렵다. 권한과  책임은 동면의 양면과 같아서 떨어트려 생각할 수 없다. 직원들을 믿는 회사로 사람들이 몰리는 이유이다.

협업

  • 엔지니어, 프로듀서, 운영자가 함께하는 하나의 팀
    • 함께 문제를 적극적으로 풀어나가는 게임처럼 일을 할 것인가.
    • 아니면, 보신주의(CYA:Cover your ass)를 위해 문제를 숨겨놓을 것인가.
    • 구글은 다른 지역사람들이 모여 하나의 팀을 이루는 경우도 적지 않지만 협업이 매우 잘 이루어짐.

양보다 질

  • 적은것이 더 낫다
    • 진정한 사냥꾼에게는 많은 화살이 필요 없다.
    • 한가지문제를 100%완벽하게 풀어내는것이 두 문제를 50%만 풀어내는것 보다 낫다.
    • 어정쩡한 두개의 기능을 추가하는 것 보다 훌륭한 기능 한개를 만들어내는것이 더 낫다.
  • 온전한 UX
    • 사용자 경험에 대한 모든면을 처음부터 끝까지 고려 할 수 있어야 함.
    • UX, 기능, 성능, 버그, 기타 등등.

실험정신

  • 런칭은 단지 첫 걸음에 불과하다.
    • KIXEYE의 War commander의 경우 첫달에는 주목받지 못하였다. 하지만 매달 꾸준히 개선을 거듭한 결과 6개월후 동일 카테고리에서 최고의 자리에 오름.
  • 작고 많은 실험들이 모여 큰 성공을 이루어 낸다.
    • eBay의 machine-learned 랭킹시스템 (역자주:초창기 Hadoop의 대표적인 성공사례로서 기능과 성능이라는 두마리 토끼를 잡아냄. 자세한것은 ebay tech blog를 참고)

배움의 선순환을 만들라

  • 회사는 배움의 장이 되어야 한다
  • 구글에서는 모든것에 대하여 회고를 진행한다
    • 잘 된것, 잘 못한것 모두 대상으로 진행
    • 솔직하게 진행하지 않으면 결국 형식뿐인 빈 껍데기가 되어 버린다  
  • 배우는것을 좋아하고 즐기는 사람을 채용하라

가장 공감했던 내용.
최소한 IT기업에 있어서 회사는 배움의 장이 되어야 한다.
회사는 학교가 아니다 라는 말을 하는 사람이 아직도 주변에 있는가?
아직 있다면 당당하게 말하라. 
"당신이 틀렸소."
그런데 그 사람이 사장이라면?!
진지하게 이직을 고려해 보라.

실패에 대한 관용

  • 실패를 통해 배우고 발전해 나갈 수 있어야 한다.
  • 면접때 무엇을 알고 있는가를 물어보기 보다는 무엇을 배웠는가를 물어본다.
  • 감정과 개성을 존중
  • 구글의 경우 프로젝트 사후 평가에 있어서 비난을 허용하지 않는다.

빠르고 반복적인 개발을 장려

  • 실패는 쓰러지는것을 말하는 것이 아니라, 다시 일어나기를 포기하는것이다. - 루즈벨트


Randy Shoup씨의 강연에서 가장 인상깊었던 것은 개발을 둘러싼 모든 문제들을 하나의 순환구조로 파악하고 있다는 점 이다. 시간이 흐름에 따라 좋아지는 것은 더욱더좋아지게 되고 나빠지는 것 또한 그러하다. 이러한 선순환과 악순환은 동일한 출발지점을 지니며 어떠한 선택을 하느냐에 따라 완전히 다른 방향을 향하게 된다. 악순환을 선순환으로 바꾸는 출발점은 이러한 순환구조를 이해하는데에서 출발한다.

현재 KIXEYE의 모든 게임들은 3명이 한팀을 이루어 한달을 주기로 반복형 개발을 수행하고 있으며, 소스코드의 빌드가 끝난 이후 AWS를 이용해 완전 백지상태에서 서비스 런칭까지 15분이 소요된다 한다. 아마도 DevOps를 통해 인프라 셋업의 자동화를 이루어낸 덕분이리라.

관련링크

Randy Shoup씨의 다른 강연


2014년 4월 29일 화요일

도메인 주도 설계와 애자일 개발

왜 모델링이 필요한가?

우리들이 프로그램을 제작하는 과정은 현실의 어떠한 사물이나 동작을 대상으로 하여 이를 추상적 형태로 변환시키고, 변환된 추상적 개념들을 이용하여 컴퓨터 안에서의 여러가지 형태로 실체화 시키는 일련의 과정을 거치게 된다.



프로그래밍에 있어서 어려운 점 가운데 하나는 구현하고자 하는 대상의 본질적인 원리를 정확하게 파악하기가 쉽지가 않다는 점이다. 우리가 오감을 통해 관찰 할 수 있는 범위는 구현 대상의 외형boundary에 한정되기 때문에 이러한 외형에 대한 관찰과 기존 지식을 통해 대상의 본질을 추론해 내야만 한다. 이러한 추론을 통한 추상화 작업을 프로그래밍에 있어서는 모델링이라 부르며 대상의 본질에 통찰해 내는 과정이 제한된 감각과 지식의 틀 안에서 이루어진다는 점 때문에 종종 플라톤 철학의 이데아론에 빗대어 지기도 한다.

인식과 실체의 사이에는 늘 일정한 갭이 존재하기 마련이다.
  
결국, 구현 대상에 대한 이해도를 바탕으로 본질을 정확히 파악해 내고 이를 추상화 해 내느냐가 프로그램의 완성도를 결정하게 된다고 할 수 있다.

모델링에 대해서 좀 더 알아보고 싶다면 아래의 기사를 읽어볼 것을 권한다.(영문)

모든 프로그램은 모델을 지닌다

설계문서를 일체 만들지 않는 프로그래밍이라 해도 모델링 작업은 반드시 거치게 되어 있다. 최소한 우리 머리속 에서라도 말이다. 하지만 두명 이상이 이러한 대상에 대한 인식을 공유하고자 할 때에 모델은 언어를 통해 세상에 그 모습을 드러 낼 수 밖에 없게 된다. UML과 같은 패턴언어는 경험을 패턴화 함으로서 지식 전달에 필요한 시간과 노력을 단축시키는데 사용된다.
혼자서 진행하는 프로젝트라 하더라도 모델링은 부족한 인간의 기억력을 보완해 주고 추상적 개념들을 시각화 해 나타내 줌으로서 프로그래밍에 적지않은 도움을 준다.

객체 지향 프로그래밍과 절차적 프로그래밍

객체 지향 프로그래밍Object-Oriented Programming, OOP이 무엇인지는 많은 문서들에서 설명되고 있으므로 굳이 여기서 언급하지는 않겠다. 다만 필자가 여기서 분명히 해 두고자 하는것은 OOP의 대비되는 개념으로 흔히 구조적 프로그래밍structured programming이 언급되는 경향이 있는데, 이는 잘못된 인식이라는 것 이다. 

프로그램을 객체의 조합으로 보느냐 명령어의 조합으로 보느냐에 대한 기준으로 패러다임을 나누고자 한다면 OOP의 대칭점에 있는것은 절차적 프로그래밍procedural programming이며, 프로그램의 복잡성을 관리하기 위해 계층적인 구조를 가지는 구조적 프로그래밍의 사상은 OOP에도 그대로 살아 있다고 볼 수 있을것이다.

절차적 프로그래밍은 오랜 기간동안 프로그래밍 패러다임의 주류를 이루었으며 지금까지도 처음 프로그래밍을 배울때에도 절차적인 프로그래밍을 통해서 프로그램을 구현하는 방법을 배우게 된다. 이때문에 OOP가 주류가 되었다고 하는 지금까지도 형태는 OOP의 흉내를 내고 있지만 프로그램의 실제 구조는 절차적 프로그래밍을 띄고 있는 경우가 대부분 이다.

절차적 프로그래밍은 배우기 쉽고 빠르게 작성할 수 있으며 성능에 있어서도 효율적인 경우가 많아 아래 소개할 PoEAA에서도 트랜잭션 스크립트 패턴이란 이름으로 취급하고 있다.

PoEAA의 등장과 도메인 주도 설계



2002년 마틴 파울러Pattern of Enterprise Application Architecture(이하 PoEAA)를 통해 엔터프라이즈 어플리케이션에 있어서 OOP가 가져야 할 모습에 대한 재 발견을 이끌어 낸다. PoEAA는 디자인 패턴Design Pattern을 단순히 확장한 개념이라기 보다는 OOP본래의 패러다임에 충실하게 엔터프라이즈 어플리케이션의 각 요소들의 본질과 관계를 새롭게 패턴화 하여 정의하고 있는데, 이 책에서 확립된 개념들은 이후 등장하는 많은 아키텍처들에 큰 영향을 주게 된다. 

에릭 에반스는 2003년 PoEAA를 기반으로 하여 패턴간의 상호 연관성을 실제적인 예제를 곁들여 해설한 도메인 주도 설계Domain-Driven Design(이하DDD) 를 발표한다. 이 책은 출간 직후부터 열렬한 환영을 받는데, 일정수준 이상의 복잡도를 지니는 어플리케이션 개발에 있어서 복잡성을 관리 할 수 있는 실천적인 전략과 패턴들을 제공하고 있었기 때문이다. 


DDD의 네비게이션 맵
DDD에서에서 한가지 아쉬운점은, 의도적인지는 몰라도 PoEAA에서 기술한 여러 개념들에 대한 설명을 생략하고 있어 사실상 PoEAA를 먼저 읽지 않고는 제대로 이해하기가 힘들다는 점 이다. 비단 기업용 어플리케이션이 아니더라도 효율적인 소프트웨어 개발을 위해 모델링에 관심이 있는 개발자라면 이 두권의 책을 꼭 읽어둘 것을 강력히 권한다.(DDD의 경우 국내에도 이대엽씨의 훌륭한 번역으로 번역서가 출간되어 있지만 PoEAA는 절판이되어 구할수가 없다. )

DDD와 애자일 개발의 궁합

다시한번 말하지만 DDD는 지금까지 없던 새로운 개발 패러다임이 아닌 OOP 본래 모습을 되찾자는것이다. 하지만 OOP의 관점에서 객체를 모델링하는것은 말처럼 쉬운 일이 아니다. 동일한 객체라 할 지라도 시각에 따라 다양한 모습의 모델이 존재 가능하며, 복합적으로 상호작용을 하며 움직이는 객체를 설명하기 위해 다양한 모델이 동시에 존재하기도 한다.

인간의 표정에 대한  CG구현은 보이지 않는 뼈와 근육의 움직임에 대해서 모델링이 가능해진 시점에서야 자연스러움을 인정받게 되었다. 이러한 사물(객체)의 본질에 대한 고찰이야 말로 DDD를 수행해야 하는 가장 큰 이유이자 DDD의 수행이 어려운 이유이기도 하다.

DDD 수행에 있어서 애자일 개발 프로세스가 필요한 이유는 두가지이다.
첫번째는 바운더리를 통해 도메인 모델을 추론해 내는 작업을 한번에 해 내는것이 어렵기 때문으로, 모델이 올바른가를 증명하기 위해서는 이를 구현한 코드를 작동시켜보는 방법이 가장 유효한데, 동작을 통해 다시 모델을 개선시키고 구현을 통해 확인해 나가는 방법이 바로 스크럼과 같은 짧은 주기의 반복형 개발 프로세스. 즉, 애자일 프로세스이다. 반면, 한번 정해진 모델에 대해 변경이 쉽지 않은 폭포수형 개발 방식으로는 DDD를 수행하는것이 사실상 불가능하다.

Scrum으로 진행하는 DDD Flow(출전:MSDN)

도메인 정제 프로세스(출전:domainlanguage.com)




두번째는 모델링에서 구현에 이르는 일련의 작업들이 도메인 영역에 대한 이해도에 직접적으로 연관되어 이루어지므로 폭포수 개발에 따른 전통적인 역할분담(업무분석가or도메인 전문가, 설계자, 코더)으로는 엄청나게 늘어나는 커뮤니케이션 비용을 감당 할 수 없지만, 애자일 개발이라면 도메인 전문가에서 개발자에 이르는 커뮤니케이션 라인이 매우 심플하므로 이것이 DDD에 있어서 애자일 개발 프로세스가 필요한 두번째 이유이다.

위에 소개한 Model Exploration Whirlpool(모델 개발 소용돌이)은 DDD에 기반한 개발에서 많이 채택되는 프로세스인데, 눈에 보이는 부분인 시나리오에서 시작해 모델과 코드를 만들어 나가는 작업을 반복해서 수행함으로서 차츰 완성도를 높여 나가게 된다. 이러한 작업들은 기간을 나누어 구분해서 작업하는것이 아니라 동시 다발적으로 늘 이루어져야 하며 특히 시나리오와 모델의 정제작업은 사실상 분리가 불가능하므로 같은 사람이 수행 할 수 있어야 하며 DDD의 저자인 에릭 에반스는 모델 설계자가 코딩 작업에 참여하는것을 완전히 배재해서는 안된다고 말하고 있다.

2014년 4월 27일 일요일

엔터프라이즈 시스템에 있어서의 클라우드 컴퓨팅 도입


지난 20일, 삼성SDS의 과천센터에서 발생한 화재로 삼성 금융계열사의 홈페이지 접속과 온라인 결제가 중단되었었다. 비단 화재와 같은 재난 상황이 아니더라도 IT서비스를 본업으로 하지 않는 기업에서 사내 정보시스템 운영을 위해 물리적 서버를 운영하는것은 상당히 골치아픈 문제이다.

지금까지 국내의 클라우드 컴퓨팅 이용은 모바일게임, 인터넷계 기업의 웹 시스템이 주류를 이루었고, 사내 시스템의 경우엔 글로벌 비즈니스에만 주로 사용되어 왔다. 필자가 근무하는 일본 지역의 경우, 수년 전부터 불어닥친 정보 인프라의 클라우드화 열풍에 힘입어 이제는 어느 개발현장에서나 사내 정보시스템에 클라우드 컴퓨팅을 사용하는 풍경이 결코 낮설지 않다.

사내 정보시스템의 클라우드화에는 분명한 장단점이 존재한다. 이번 포스팅에서는 사내 시스템의 클라우드 마이그레이션이라는 테마로 사내 시스템의 클라우드화에 따른 장점과 과제를 정리해 보고자 한다.

사내 시스템과 클라우드 컴퓨팅

기업에서 사용되는 정보 시스템은 어느곳이나 비슷한 목표와 과제를 지닌다. 시간이 흐를수록 점차 정보시스템에의 의존도는 높아져 가고 있으며 그에따른 문제점도 빠른 속도로 표면에 등장하고 있다. 일반적으로 손꼽히는 현대 기업 IT부서의 현황과 문제점을 정리해 보자면 다음과 같다.

  • 부족한 운영 인원 : 기업의 IT부서에서 시스템의 운영은 몇명의 시스템 관리자에 의존하는 형태가 많으며, 아예 시스템 관리 자체를 아웃소싱 하는 경우도 많다. 소수의  운영 요원으로 하드웨어에서 OS, 각종 미들웨어를 포함한 수많은 시스템 관련 소프트웨어를 효율적으로 관리/운영하기는 쉽지 않은데 그나마도 여유가 생기는 시점에 운영요원들에 대한 교육이나 외부 교육 컨설팅 등을 통해 질적 수준을 향상시키기 보다는 개발업무나 엔드유저 요구 대응과 같은 다른 업무를 병행시키는 경우가 다반사이다.  
  • 적절한 스케일링 전략의 부재 : 기업활동에 따른 시스템의 규묘와 복잡성은 날로 증가하는 반면에 이에 대응하는 시스템의 스케일링은 더디게 이루어진다.
  • 서버 관리의 부담 증가 : 서버의 규모는 적게는 몇대에서 많게는 수백대에 이르는 경우도 있는데, 노후서버 교체, OS및 미들웨어의 업데이트및 모니터링과 같은 방대한 운영 업무들을 수작업에 의존하는 경우가 많다. 
  • 장애 대책 부재 : 앞서 소개한 세가지 요소들이 합체하면 "장애 대책 부재"로 변신을 하게 된다. 적은 인원으로 많은 업무를 수행하면서 주먹구구식으로 스케일링을 진행하다보니 수작업 미스에 의한 2중 3중의 재 작업이 발생하기 쉽다. 이러한 상황에서 서버의 구성을 2중화 하거나 백업시스템을 구축하는것은 아예 엄두도 못내는 경우가 태반이다. 장애 대책의 부재는 어느순간 치명적인 손해를 입히면서 그 모습을 드러내는데, 정보시스템에 점점더 많은 것을 의존하고 있는 현대기업의 특성상 그 손해가 기업의 생존을 위협하는 수준이 될 수 도 있다.

이러한 문제점을 해결하기 위한 수단으로 클라우드 마이그레이션에 대한 고려는 다음과 같은 가치를 지닌다.

  • 운영의 효율화 : 시스템 인프라를 아웃소싱함으로써 시스템 관리자는 노동 집약적 물리적 서버 관리에서 해방된다.
  • 장애 발생시의 대응과 시스템 백업 지원 : 클라우드 컴퓨팅이 지닌 큰 장점중에 한가지는 백업및 장애 대응에 있어서 높은수준의 지원을 받을 수 있게 된다는 점이다. 
  • 자유로운 스케일링 : 정보 시스템의 처리량에 대응하여 빠르게 시스템 자원을 늘리거나 줄이는것이 가능해 진다.
  • 비용 절감과 도입 용이 : 단순히 서버 하드웨어비용이나 전기세만 놓고 보자면 사내에 서버를 두고 운영하는것이 더 싸게 먹힌다고 생각할 지 모르지만, 장애대응이나 운영비용을 모두 포함시켜 생각한다면 클라우드 컴퓨팅은 비용절감에 확실히 도움이 된다. 게다가 초기 투자비용이 거의 들지 않는점도 큰 매력이다. 
  • 고수준의 보안대책 : AWS나 MS Azure와 같은 퍼블릭 클라우드 서비스들은 대부분 프라이빗 VPN을 제공하여 인터넷을 통한 외부의 공격으로 부터 보호된 네트워크를 통해 클라우드 자원에 접근할 수 있도록 하고 있다. 
  • 모니터링 툴 제공 : 일반적으로 전산실을 운영할 경우 각종 하드웨어와 소프트웨어의 상태를 모니터링 하는데 들어가는 비용이 상당하다. 대부분의 클라우드 서비스는 높은수준의 모니터링 환경을 무상으로 제공하고 있다.
  • 빅데이터 처리 : 기업에서도 점차 빅데이터 처리에 대한 수요는 커져가고 있으나 이를 처리할만한 자원이 부족하여 엄두를 내지 못하는경우가 많다. 클라우드 컴퓨팅을 이용한다면 대량의 데이터를 효율적이면서도 경제적으로 처리하는것이 가능해진다.

클라우드 컴퓨팅 도입의 과제

여러가지 장점에도 불구하고 보수적인 성향의 사내 시스템에 있어서 클라우드 컴퓨팅의 도입은 넘어야 할 산이 많다.

보안

프라이빗VPN을 사용한다고 하더라도 여전히 보안 문제는 기업이 클라우드 컴퓨팅을 도입하는데 있어서 큰 걸림돌로 작용하고 있다. 아무래도 기업활동의 핵심영역을 외부로 이동시키는 문제이다보니 경영자의 입장에선 신중에 신중을 기할 수 밖에 없는것이다.
이러한 인식의 문제는 단기간에 해결하긴 어렵지만 아마존이나 마이크로소프트와 같은 클라우드 서비스 사업자들이 적극적으로 국내에서 마케팅을 펼쳐나간다면 차츰 인식을 개선해 나갈 수 있을것으로 기대한다.

클라우드 환경에서의 보안에 대해서는 다음의 내용이 참고가 될 것이다.

전문가의 부재

사내 시스템의 클라우드 마이그레이션에서 또 한가지 큰 걸림은 기존 물리 서버에서 가상서버 시스템으로 전환하는 작업에 대한 경험을 지닌 전문가가 많이 부족하다는 점 이다. 일본에서도 이러한 전문가를 확보 할 수 있느냐 없느냐가 클라우드 컴퓨팅 도입 자체를 가능하게 하는 중요 요소로 작용한다. 하지만, 클라우드 컴퓨팅으로의 전환을 전문적으로 수행할 수 있는 경험과 실력을 지닌 엔지니어는 전체 운영 엔지니어 중에서도 극히 소수이며 여기에 DevOps적 역량을 지닌 엔지니어라고 하면 유니콘 개발자 수준의 귀중한 존재로 취급받는 실정이다.

미국내 시스템 운영 관련 직종의 급여 변동추이 (출전:indeed.com)


  

클라우드 컴퓨팅 마이그레이션을 수행하기 위한 전문가에게 요구되는 역량은 다음과 같다.
  • 기존 물리 서버 환경과 가상 컴퓨팅 환경에 대한 높은 이해도
  • 호환성과 관련된 OS및 하드웨어 구성에 대한 지식
  • 서버 구축및 설정 자동화에 대한 지식
  • 가상화 환경의 시스템 구성및 관리/모니터링 노하우
  • 성능 관련 노하우
  • 최적의 비용산출을 위한 이용 플래닝 능력

일본의 경우 아마존과 마이크로 소프트에서 무상으로 각각 자사의 클라우드 컴퓨팅에 대한 교육과 세미나를 실시하고 있으며, 특히 아마존의 경우 필요한 지식을 담은 서적을 자사의 ebook플랫폼인 Kindle을 통해 무상으로 배포하고 있다.

경영자의 인식부족

많은 장점에도 불구하고 국내에서 클라우드 컴퓨팅 도입에 있어서 무엇보다 큰 장벽은 경영자의 클라우드 컴퓨팅에 대한 인식 매우 낮다는 점 인듯 싶다.

국내 클라우드 시장 폭발적 성장, 그러나 인식의 장벽은 제자리 - 마이크로소프트

하지만 필자의 경험상 기존 전산실 관리나 인프라 아웃소싱에 비해 클라우드 켬퓨팅 사용의 장점은 비용대비 효율 면에서 매우 뚜렷하게 나타난다. 보수적이기로는 우리나라에 못지 않은 일본의 기업들도 이제는 당연하게 클라우드 컴퓨팅을 받아 들이는 모습을 볼때, 효율성을 최우선으로 하는 기업의 생리에 따라 결국 국내또한 엔터프라이즈 클라우드 컴퓨팅이 대세로 자리잡지 않을까 예측해 본다.

결론

비용대비 효용성뿐만 아니라, 보다 안정적인 기업경영을 위해서라도 사내 시스템에 클라우드 컴퓨팅을 도입하는것은 점차 필수 사항으로 자리잡아 갈 것으로 보인다.  다만 국내의 현실은 아직 클라우드 컴퓨팅에 대해 인식이 낮다는 점이 걸림돌이 되고 있다.  이러한 인식 개선을 위해서는 국내 기업에 대한 성공사례가 가장 좋은 마케팅이 될 것이다. 한국 시장 진출을 준비하는 아마존과 기존 인프라 사업자들간의 선의의 경쟁이 국내 클라우드 컴퓨팅의 보급을 촉진시키는 계기가 되길 기대해 본다.

2014년 4월 26일 토요일

자바 8 살펴보기



자바8을 배워둬야 하는 이유

지난달 18일 자바Java 8이 정식으로 발표 되었다.

자바의 버전 업은 크게 2가지로 구분하는데, 기능적인 부분의 개선이 주를 이루는 버전업을 진화계라evolution 하고 언어 자체의 형태에 변화가 오는 버전업을 혁명계revolution 라 칭한다. 자바 6,7이 전자에 속하며 자바 5와 이번에 발표된 자바 8이 후자에 속한다.

함수형 언어의 여러 개념이 도입됨으로 인해 자바 8는 자바 5보다 훨씬더 많은 변화를 자바 언어에 가져올 것으로 보이며  코드의 형태 자체가 이전의 자바와는 확연히 구별되는 모습으로 바뀔것이 확실하다.

이 말은 기존 자바 개발자들이 자바8을 제대로 사용하기 위해서는 새로운 언어 한가지를 더 배우는 정도의 학습 비용이 요구된다는 뜻으로, 2,3년후 새로운 문법에 최적화된 방식으로 자바를 배운 개발자와 기존 개발자간의 간격은 작성된 코드의 형태를 통해 뚜렷하게 드러날 것이다.

함수형 언어

우선 자바8을 들여다 보기 전에 함수형 언어의 개념에 대해서 이해하지 않으면 안된다.
함수형 언의 개념에 대해 잠시 시간을 내어 관련 기사들을 읽어 두도록 하자.


자바8의 모든것

캘리포니아에 있는 소프트웨어 개발사인 TechEmpower에서는 자사의 블로그 에 "Everything about Java 8"란 타이틀로 자바8의 새로운 기능들을 요약해서 소개해 놓았다. 본 포스팅은 이 기사를 요약/정리한 InfoQ의 기사를 기반으로 작성되었다.

자바8의 전체 기능에 대한 상세는 Java.net가 제공하는 기능일람을 참고하기 바란다.

인터페이스의 개선

인터페이스에 static 메소드를 정의하는것이 가능해졌다. java.util.Comparator에 추가된 static naturalOrder메소드를 살펴보자.
    public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
        return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
    }
default 지시자를 이용해 기본 메소드의 정의가 가능하게되어 인터페이스를 구현하는 기존 코드의 변경없이 새 메소드의 추가가 가능해졌다. 예를 들어 java.lang.Iterable에는 forEach메소드가 default로 정의되어 있다.
    public default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
처리해야할 데이터인 Customer와 처리 내용인 action이 메소드의 인자값으로 전달 가능하게 되어 Iterable Collection에 대한 반복처리가 매우 간단히 구현 가능하게 된다.

여기서 한가지 주의해야 할 점은 예외적으로 Object클래스의 메소드에 대해서 default구현은 정의 할 수 없다는 점이다.

함수형 인터페이스

함수 인터페이스functional interface는 단 하나의 추상 메소드가 정의 가능한 인터페이스이다. 인터페이스가 함수형 인터페이스임을 나타내는 수단으로서 FunctionalInterface 어노테이션이 도입되었다. 예를 들어, java.lang.Runnable은 다음과 같은 함수 인터페이스를 지닌다.
    @FunctionalInterface
    public interface Runnable {
        public abstract void run();
    }
하지만, 어노테이션을 통해 명시적으로 지정하지 않더라도 함수 인터페이스의 정의를 만족하는 인터페이스라면 자바 컴파일러가 주석의 유무에 상관없이 함수 인터페이스로서 취급한다.

람다식

함수형 인터페이스의 중요한 특성으로 람다식lambda expression을 사용한 인스턴스 생성이 있다. 람다식에 대한 자세한 설명은 아래 기사를 참고하자.

자바에서 람다 식이 필요한 이유 – 1
자바에서 람다 식이 필요한 이유 – 2

람다식을 이용하면 동작과 데이터를 모두 동적으로 설정하는것이 가능해진다. 아래의 예제들은 모두 왼쪽이 입력값이 되고, 오른쪽이 동작에 대한 정의이다. 입력값의 데이터 타입이  유추 가능하므로 생략되고 있다는 점에 주목하자.

    (int x, int y) -> { return x + y; }
    (x, y) -> x + y
    x -> x * x
    () -> x
    x -> { System.out.println(x); }
예를들어 Runnable 함수 인터페이스를 인스턴스화 하는것은 다음과 같다.
    Runnable r = () -> { System.out.println("Running!"); }

여담으로 필자는 위의 예제를 처음 접했을때 잠시 맨붕이 왔었다.
오래전 Lisp의 벽에 부딧혀 emacs에서 손을 뗀 필자에게 모습을 바꿔 찾아온 함수형 프로그래밍은 이제 10년 넘는 세월을 투자해 간신히 얻은 자바프로그래머로서의 지위에 대해 유통기간을 부여하고 있었다.

메소드 참조

메소드 참조method reference는 이미 이름이 있는 메서드를 대상으로 한 람다식의 간략형이며, 메소드 참조를 나타내는 예약어로서 (::)를 사용한다. 메소드 참조의 예와 그에 대응하는 람다식은 다음과 같다. 오른쪽이 메소드 참조, 왼쪽이 람다식이다.
    String::valueOf     x -> String.valueOf(x)
    Object::toString    x -> x.toString()
    x::toString         () -> x.toString()
    ArrayList::new      () -> new ArrayList<>()

캡처 vs 비캡처 람다식Capturing versus non-capturing lambdas

람다식의 외부에 정의된 static이 아닌 변수나 객체에 억세스하는것을 람다가 객체를 "캡쳐"한다고 부른다. 예를 들면 다음은 람다 변수 x에 억세스하는것이다.
    int x = 5;
    return y -> x + y;
람다식으로부터 억세스 가능한것은 로컬변수와 블록구의의 파라매터중에 final이거나 사실상 final판정effectively final을 받은 것에 한정된다.

java.util.function패키지에는 많은 새로운 함수형 인터페이스가 추가되었다. 몇가지를 예로 들자면 다음과 같다.

  • Function <T, R> - T를 입력으로 R을 출력으로 반환
  • Predicate <T> - T를 입력으로 boolean을 출력으로 반환
  • Consumer <T> - T를 입력으로 아무것도 반환하지 않는다
  • Supplier <T> - 입력을 취하지 않고 T를 반환
  • BinaryOperator <T> - 2 개의 T를 입력으로 하나의 T를 출력으로 반환

java.util.stream

자바 8의 중요한 패러다임의 하나로 새로운 java.util.stream패키지는 스트림에 대한 함수형 조작을 제공한다. 좀더 알기쉽게 설명하자면 배열이나 리스트, 맵으로 대표되는 컬랙션을 스트림으로 다룰 수 있게 되었다는 것 이다. 다음은 컬랙션에 대한 스트림화의 예이다.
   Stream <T> stream = collection.stream ();
이것이 함수형 프로그래밍과 결합하면 다음과 같은 형태가 된다.
    int sumOfWeights = blocks.stream () filter (b -> b.getColor () == RED)
                                      . mapToInt (b -> b.getWeight ())
                                      . sum ();
위의 샘플코드는 stream패키지의 Javadoc에 실린 예로서, stream의 소스로서 blocks라는 Collection을 사용하고 있다. 그 스트림에 대해 filter-map-reduce를 실행하여 붉은색(RED)블록에 대한 무게(weight)의 합(sum)을 구하는 일련의 과정이 한줄의 코드에 집약되어 표현되고 있다.

제네릭 타입 인터페이스의 개선

이 개선은 자바 컴파일러가 형에대한 추론능력을 갖추는 것으로 제네릭 형식 메소드 호출시 인수에 대한 형 정의를 생략 가능하게 해 준다.
예를 들어 자바7의 코드가 다음과 같은 것 이었다면
    foo(Utility.<Type>bar());
    Utility.<Type>foo().bar();
자바8에서는 인수와 호출에 대한 추론이 자동적으로 이루어져 다음과 같이 형태가 된다.
    foo(Utility.bar());
    Utility.foo().bar();

java.time

새로운 날짜/시간 관련 API가 java.time 패키지에 추가되고 있다. 클래스는 immutable이며 스레드에 대해 안전하다. 날짜 및 시간 형식으로  Instant, LocalDate, LocalDateTime, ZonedDateTime이 추가되었으며 날짜와 시간 이외의 것으로서 Duration과 Period가 추가되었다. 새로 추가된 값 형식은 Month, DayOfWeek, Year, Month YearMonth, MonthDay, OffsetTime, OffsetDateTime등이 있다. 이런한 새로운 날짜/시간 클래스는 대부분이 JDBC에서 지원됨으로서 RDB연동의 효율적인 구현이 가능하다.

Collections API의 확장

인터페이스가 default 메소드를 가질 수 있게 됨으로써 자바8의 Collection API에는 다수의 메소드가 새롭게 추가되었다. 인터페이스는 모두 default 메소드가 구현되었으며 새로이 추가된 메소드의 일람은 다음과 같다.
  • Iterable.forEach(Consumer)
  • Iterator.forEachRemaining(Consumer)
  • Collection.removeIf(Predicate)
  • Collection.spliterator()
  • Collection.stream()
  • Collection.parallelStream()
  • List.sort(Comparator)
  • List.replaceAll(UnaryOperator)
  • Map.forEach(BiConsumer)
  • Map.replaceAll(BiFunction)
  • Map.putIfAbsent(K, V)
  • Map.remove(Object, Object)
  • Map.replace(K, V, V)
  • Map.replace(K, V)
  • Map.computeIfAbsent(K, Function)
  • Map.computeIfPresent(K, BiFunction)
  • Map.compute(K, BiFunction)
  • Map.merge(K, V, BiFunction)
  • Map.getOrDefault(Object, V)

Concurrency API의 확장

Concurrency API의 기능이 추가되었다. 몇가지를 소개해 보자면, ForkJoinPool.commonPool()은 모든 병렬 스트림 작업을 처리하는 구조이다. ForkJoinTak는 명시적으로 특정 풀을 가지지 않고, 일반적인 풀을 사용하게 되었다. 말도 많고 탈도 많았던 ConcurrentHashMap은 완전히 재 작성되었다. 또한 새로운 Locking처리의 구현으로서 추가된 StampedLock은 ReentrantReadWriteLock의 대안으로 사용할 수 있다.
 Future인터페이스의 구현인 CompletableFuture에서는 비동기 작업의 실행과 체이닝을 위한 방법이 제공된다.

IO/NIO API의 확장

IO/NIO에 메소드가 추가되어 파일이나 입력 스트림에서 java.util.stream.Stream을 직접 생성할 수 있게 되었다.
  • BufferedReader.lines ()
  • Files.list (Path)
  • Files.walk (Path, int FileVisitOption ...)
  • Files.walk (Path, FileVisitOption ...)
  • Files.find (Path, int BiPredicate, FileVisitOption ...)
  • Files.lines (Path, Charset)
  • DirectoryStream.stream ()
새로운 클래스의 UncheckedIOException은 RuntimeException을 확장한 IOException이다.
클로징 가능한 CloseableStream이 추가된것 또한 눈여겨 볼만 하다.

리플렉션과 어노테이션의 변경

어노테이션이 더 많은곳에서 사용될 수 있게 되었다. 예를들면, List<@Nullable String>과 같이 제네릭 형식 매게변수에 작성할 수도 있다. 따라서 정적 분석 도구에서 감지 가능한 오류의 범위가 확대되어 Java의 built-in type 시스템 또한 강화되고 정교해졌다.

Nashorn JavaScript엔진

Nashorn은 새로 JDK에 통합된 경량 고성능 JavaScript구현 엔진이다. Rhino의 후속이며, 성능과 메모리 관리가 개선되었다. javax.script API를 지원하고 있지만, DOM/CSS와 브라우저 플러그인API는 포함되어 있지 않다.

java.lang, java.util, 그리고 그 밖의것들

지금까지 언급한 것들 이외의 패키지에도 많은 추가 기능들이 있다. 몇가지 주목할만한 것들을 들어보자면, ThreadLocal.withInital(Supplier)는 보다 컴팩트한 thread 로컬 변수의 정의를 허용한다. 오랜 숙원이었던 StringJoiner과 String.join(...)가 자바8에서 구현되었다. Comparator는 체인 또는 필드기반의 비교를 가능하게 하는 새로운 방식을 제안하고 있다. String 풀의 기본값이 25~50K까지 확장되었다.

그분이 오신다. 긴장하라

눈치 빠른 독자들은 중간쯤에서 눈치를 채셨겠지만 자바8에서 추가된 중요 패러다임들은 대부분 멀티코어 프로세서상에서의 병렬처리 구현과 관련이 있다.

사실 자바 8의 모습에 대해서는 2011년 하반기에 어느 정도 윤곽이 확정되었으며 2013년5월8일 기능 사양이 동결되고 이후 모습을 드러낸 OpenJDK 8을 통해 많은 사람들이 준비해 오고 있었다. 기업용 어플리케이션의 경우 안정성을 중시하는 특성상 JavaEE8이 발표된 이후로도 얼마간 시간이 더 흘러야 주류로 정착될 것으로 보이긴 하지만 함수형 프로그래밍functional programming개념은 병렬처리 아키텍처나 코드 작성상의 간결함에 대한 매리트가 분명한 만큼 오픈소스 프로젝트를 중심으로 발빠르게 확산이 이루어지고 있으며, 자바4에서 5로 넘어가는 기간보다는 빠르게 확산될 것으로 보인다. 

이미 Tomcat과 Jetty는 자바 8을 지원하고 있으며 Spring및 Play와 같은 프레임워크도 자바8 정식 발표와 거의 동시에 자바8용 업데이트를 발표하고 있는 실정이다.

기존의 자바 개발자들은 긴장해야 한다. 멀티코어 개발에 대한 열망이 그 어느때보다 높은 현 시점에서 자바8이 가져올 변화는 예상보다 빠르고 치명적인 모습으로 우리앞에 나타날지도 모른다.



2014년 4월 15일 화요일

글로벌 고수들의 노하우 대 공개 - 2013 QCon 뉴욕 강연내용 모음 (Scaling)


QCon은 InfoQ에서 주최하는 개발자 컨퍼런스로 런던, 뉴욕, 샌프란시스코, 토쿄, 베이징,샹하이,리오 데 자네이로, 그리고 상파울로에서 2007년부터 해마다 개최되고 있다.

각 도시에서 개최하는 QCon이지만 뉴욕과 런던, 샌프란시스코가 규모가 가장 크다. 유료 행사인 만큼 참가비로는 뉴욕의 경우 400달러, 동경은 만엔정도의 거금이 들지만 페이스북, 링크드인과 같은 성공한 업계 최고의 서비스들의 살아있는 노하우를 전수 받을 수 있는 기회인 만큼 매회 초 만원인 인기 행사이다.
 국내에도 블로그 등을 통해 후기를 찾아 볼 수 있는걸 보면 한국서 찾아가는 사람도 있을 정도로 아름아름 입소문이 나 있는듯 하다.

하지만 외국에서 하는 유료 행사라고 낙심할 필요는 없다.
모든 컨퍼런스 내용은 동영상과 동영상연동 슬라이드, 그리고 PDF로 제공되고 있으며 InfoQ에 가입만 하면 무료다.(페이스북과 트위터, 링크드인의 계정을 이용한 인증도 가능하다.)

작년인 2013년 뉴욕에서 있었던 강연내용들을 몇개 소개해 본다.

전체 강연의 내용은 아래 링크를 통해 관람 가능하다.
QCon New York 2013 Videos and Slides

기조연설: 봉건적 보안 세계에서 살아남기 
Bruce Schneier는 보안전문가로 12권의 책을 집필했다. 컴퓨팅 환경이 클라우드, SaaS화 되어감에 따라 각각의 서비스 프로바이더의 보안정책에 종속되어 버리는 현실을 봉건적 보안 세계라 표현하고 여기서 어떻게 효율적으로 보안을 구성할 수 있는지에 대해 이야기 한다.

기조연설 : 기술혁신이 뉴욕타임즈를 살릴 수 있는가?
무려 뉴욕타임즈의 CIO인 Marc Frons와 CTO인 Rajiv Pant가 연사로 나섰다. 뉴욕타임즈의 디지털 구독 정책에 대해 설명한다. Rajiv Pant는 NodeJs, Scala, cloud, 그리고 big data를 활용해 지속적 배포Continuous Delivery를 실현하는 노하우를 공유한다.

LinkedIn에게서 배우는 구축과 스케일링
LinkedIn의 수석 앤지니어인 Jay Kreps는 LinkedIn의 데이터 인프라스트럭처와 관련 영역의 기술리딩을 담당하고 있다. 그는 LinkedIn 아키텍처의 발전과정을 통해 단일 어플리케이션과 단일 데이터베이스를 분산 서비스와 분산 데이터스토어로 스케일링 하는 것에 대해 강의한다.

Facebook Messages : HBase상에서의 백업및 복제시스템
페이스북의 HBase기술팀 스토리지 엔지니어인 Nicolas Spiegelberg는 매달 500테라바이트의 새로운 데이터가 발생하는 페이스북 매시징을 HBase상에서 구현하고 스케일링해 나갔던 분투기를 소개한다.

트위터 분해하기 - Service-Oriented Architecture를 둘러싼 모험
Jeremy Cloud는 고도의 동시성Concurrency 에대한 접근방법과 코드의 복잡성을 관리하는데 사용되는 몇가지 함수형 디자인패턴을 소개하는 것으로 트위터에서의 SOA에 대해 설명한다.