Upgrade to Pro — share decks privately, control downloads, hide ads and more …

H1 개발자 컨퍼런스

Avatar for riix riix
February 12, 2013

H1 개발자 컨퍼런스

테스트용 업로드입니다.

Avatar for riix

riix

February 12, 2013
Tweet

Other Decks in Technology

Transcript

  1. 이 책은 KTH의 지적 재산이므로 어떠한 경우에도 KTH의 공식적인 허가

    없이 이 책의 일부 또는 전체를 복제, 전송, 배포하거나 변경하여 사용할 수 없습니다. 이 책은 정보 제공의 목적으로만 제공됩니다.
  2. 가 두 번째 준비한 ‘H3’ 개발자 컨퍼런스에 참석해 주신 여러

    분을 환영합니다. 작년 2011년 H3가 끝나고 많은 분들이 SNS와 블로그, 신문 등을 통 해서 많은 호평을 해주셨습니다. H3가 추구하는 지식공유와 토론이라는 지향 점에 많은 분들이 공감 해 주신 것이라 생각합니다. 작년 H3에서는 스마트 모 바일을 향한 KTH의 개발 방향에 대해 처음으로 소개했다면, 올해 H3에서는 조금 더 다양한 분야의 주제를 가지고 이번 개발자 컨퍼런스를 준비하였습니 다. IT업계에서, 기술변화의 속도를 따라가는 것은 개인이 혼자 하기에는 벅찬 일입니다. 2011년도에만 해도 작은 주제로 여겨지던 DevOps, 빅데이터 등 의 주제가 이제는 메인스트림의 반열에 다가섰습니다. 클라우드 관련 기술들은 작년에도 이미 많은 분들이 논의하던 주제였지만 이제는 성숙기에 들어섰다고 할 수 있습니다. 이러한 기술 동향에 발맞추어 새로운 주제들에 대해서 KTH가 먼저 시도해 본 결과물들을 공유할 수 있는 자리를 H3에서 마련하였습니다. 올해 모바일 분야에서 커다란 추세 중에 하나는 클라우드를 기반으로 한 모바일 백엔드를 제공하는 BaaSBackend as a Service의 등장 입니다. 이에 KTH 는 모바일 개발자들이 서버없이 고도화된 앱을 쉽게 구현할 수 있도록 하는 “baas.io” 서비스를 이번 H3를 통해 공개합니다. 새로운 기술이 발전 해 나아 가면서 관련된 기술과 서비스를 통해 점점 더 성숙하게 되듯이, baas.io는 모 바일 서비스 시장이 더욱 발전하는데 기여하는 또 하나의 전환점이 되고자 합니 다. 그리고, 작년에는 부족했던 모바일 서비스 사용자 분석이나 위치기반/빅 데이터 분석에 관한 세션이 강화되었고 아직까지는 한국에서는 생소한 단어인 클라우드 서비스 자동화를 위한 DevOps에 관련 주제가 추가되었습니다. 2012년 올해는 본격적으로 클라우드와 모바일이라는 키워드가 무르익 은 한 해였습니다. 이제 이 키워드는 매일매일 우리가 사용하는 제품과 서비스 들에 녹아 들어 있습니다. 앞으로도 H3가 시작한 공유와 상생이라는 목적을 가 지고 좋은 컨퍼런스를 통하여 KTH가 더욱 커뮤니티에 기여할 수 있도록 하겠 습니다. 고맙습니다. 인 사 말 KTH 대표 서 정 수
  3. 01 들어가며 : H3 컨퍼런스 소개 02 H3 컨퍼런스 세션

    내용 앱스프레소Lab 장동수 [email protected] DEVOPS팀 김동수 [email protected] 봄날은 간다 앱 중심으로 생각하기 : DEVOPS와 자동화 014 쪽 036 쪽 DEVOPS팀 김성식 [email protected] JUST DO IT, Chef! 062 쪽 목 차
  4. 기술전략팀 강소리 [email protected] 내 컴에선 잘 되던데 ?! VAGRANT로 서버와

    동일한 개발환경 꾸미기 078 쪽 BaaS기술팀 진성주 [email protected] 오픈소스로 개발 실력 쌓기 102 쪽 분산기술Lab 김신영 [email protected] VISUALIZATION을 중심으로 살펴본 SNS와 E-COMMERCE 121 쪽 BaaS기술팀 김양원 [email protected] 우리가 모르는 NODE.JS로 할수 있는 몇 가지 142 쪽 기술전략팀 박민우 [email protected] OAUTH2, OPEN API 인증을 위한 만능 도구상자 164 쪽 목 차
  5. 프로젝트지원팀 남종인 [email protected] 스마트 모바일 시장에서의 품질관리 방안 202 쪽

    고객가치혁신팀 유용선 [email protected] 스타트업 개발사의 생존필수 아이템, baas.io 모바일 고객센터 234 쪽 FI팀 지훈 [email protected] 모두의 도구로 프로토타이핑을 시작하라! 252 쪽 앱스프레소Lab 이상찬 [email protected] BRIDGE OVER TROUBLED WATER 272 쪽 CVI팀 김일화 [email protected] 기획/디자인/개발자 모두 알아야하는 대박앱의 비밀 178 쪽 목 차
  6. 앱스프레소Lab 박종순 [email protected] 푸딩얼굴인식을 통해 살펴 본 하이브리드 앱 제작

    노하우 284 쪽 PMC팀 김상범 [email protected] 꽃보다 SCALA 305 쪽 데이터지능팀 원종석 [email protected] 오픈 소스로 구현하는 REAL-TIME CEP 347 쪽 데이터지능팀 김남미 [email protected] 로그 속에 있는 사용자 발자국 들여다 보기 BY DAISY 367 쪽 목 차
  7. 03 KTH 개발자 블로그 베스트 396 쪽 AMAZON RDS에 서비스

    런칭 이후, 빛과 그림자 성동찬 412 쪽 오픈 소스의 또 다른 진영, MYSQL 쌍둥이 형제 MARIA DB 성동찬 424 쪽 하이브리드 앱의 스크롤 성능 개선하기 김남훈 433 쪽 ANDROID에서 SQLITE를 이용한 반경 내의 위치기반 정보 QUERY 홍성훈 440 쪽 메모리 기반 RDBMS, MEMSQL을 알아봅시다. 성동찬 목 차
  8. 450 쪽 연령 낮을수록 ‘스크린샷’, 높을수록 ‘앱설명’ 보고 앱 선택

    이경은 459 쪽 앱 설치 시 사용자들의 리뷰 영향력 높아져 김일화 471 쪽 앱스토어! BLUE OCEAN인가? BLOOD OCEAN인가? 김일화 481 쪽 위대한 PRODUCT LEADER 되기 하용호 04 KTH 소개 490 쪽 KTH 소개 목 차
  9. 11 들어가며 개발자 컨퍼런스는 스마트 모바일의 선두주자 kth의 직원들이 외부

    개발자 들을 대상으로 기술을 공유하는 지식공유 컨퍼런스입니다. 올해로 2회째 행 사를 진행하고 있습니다. kth는 N-Screen, 클라우드 환경에 맞는 다양한 콘텐츠와 서비스를 제공 하여 모바일 라이프의 고객 가치를 실현하고자 노력하고 있습니다. 모바일 서비스를 개발한 경험과 노하우, 축적된 기술을 개방하고 공유하여 더 나은 모바일 생태계를 꾸려가고자 합니다. 기술을 중시하는 회사로 거듭나기 위해 kth는 내•외부적으로 계속 다각 도로 노력하고 있으며, 2011년 5월에 오픈한 kth 개발자 블로그(http:// dev.kthcorp.com)를 시작으로 외부 개발자들에게 내부의 기술과 노하우 들을 국내 개발자 커뮤니티에 공유하고, 국내 개발자들이 모두 다같이 힘을 합쳐 발전하는 IT 환경을 만들고자 노력하고 있습니다. 이제 매년 H3 개발자 컨퍼런스를 통해 외부 개발자분들과 좀 더 가깝게 다 가가고, 이를 통해 같이 발전했으면 합니다. 들어가며 : H3 컨퍼런스 소개 http://h3.kthcorp.com
  10. 01 _ 봄날은 간다 – 장동수 02 _ 앱 중심으로

    생각하기 : DEVOPS – 김동수 03 _ JUST DO IT, CHEF – 김성식 04 _ 내 컴에선 잘 되던데 ? VAGRANT로 서버와 동일한 개발환경 꾸미기 – 강소리 05 _ 오픈소스로 개발 실력 쌓기 – 진성주 06 _ VISUALIZATION을 중심으로 살펴본 SNS 와 E-COMMERCE – 김신영 07 _ 우리가 모르는 NODE.JS로 할 수 있는 몇 가지 – 김양원 08 _ OAUTH2 – OPEN API 인증을 위한 만능 도구상자 – 박민우 09 _ 대박앱의 비밀 – 김일화 10 _ 스마트 모바일 시장에서의 품질관리 방안 – 남종인 11 _ 스타트업 개발사의 생존필수 아이템, BAAS 모바일 고객센터 – 유용선 12 _ 모두의 도구로 프로토타이핑을 시작하라 – 지훈 13 _ BRIDGE OVER TROUBLED WATER – 이상찬 14 _ 푸딩얼굴인식을 통해 살펴 본 하이브리드 앱 제작 노하우 – 박종순 15 _ 꽃보다 SCALA – 김상범 16 _ 오픈 소스로 구현하는 REAL-TIME CEP – 원종석 17 _ 로그 속에 있는 사용자 발자국 들여다 보기 BY DAISY - 김남미 컨퍼런스 세션 내용
  11. 14 H3 개발자 컨퍼런스 2012 The Past, Present & Future

    of Web Application Framework 들어가는 글 영화 속에서, 헤어지자는 은수에게 상우가 묻는다. “어떻게... 사랑이 변하니?” 영원할 것 같은 스프링의 아성에 균열의 조짐이 보인다. 수많은 웹프레임웍들이 스프 링의 아성에 도전하고, 틈을 비집고 들어가면서 그 틈은 점점 커진다. 스프링의 창시 자 로드 존슨(Rod Johnson)이 스칼라를 배우고 있다는 트윗 하나가 일파만파 논란이 되는 상황 만으로도 균열은 존재를 확인할 수 있다. 생각해보면, 스프링도 스트러츠의 아성을 허물고 지금의 자리를 차지했으니, 다른 무언가가 스프링을 밀어내고 그 자리 를 차지한다고 해도 전혀 이상한 일이 아니다. 그런데, 왜 우리는 스프링이 영원할 것 처럼 매달리는 것일까? 불과 몇 년 전 스트러츠에 매달렸던 것처럼... 봄날은 간다 앱스프레소Lab 장동수 [email protected]
  12. 15 봄날은 간다 이 글에서는 웹 애플리케이션 프레임웍(Web Application Framework;

    WAC; 이하 웹프레임웍)의 등장 배경과 지금의 상황을 되짚어 보고, 웹프레임웍의 지존 - 스프링 을 위협하는 후보들을 살펴 보려고 한다. 짧은 한 편의 글로 최신 웹프레임웍을 모두 소개할 순 없겠지만, “이런 것도 있구나, 이런 식으로 접근할 수도 있구나, 이건 좀 더 살펴봐야겠다” 정도의 생각할 꺼리를 제공한다면 이 글은 제 역할을 다 한 것이다. 사실, 스프링은 웹에만 국한된 프레임웍이 아니다. 웹과 무관한 스프링도 현존하는 가 장 성공적인 범용 IoC(Inversion-of-Control; 제어의 역전) 프레임웍이지만, 우리나 라에서는 웹과 무관한 스프링을 볼 기회가 없다. 오히려 웹과 무관한 상황에서도 스프 링을 쓰기 위해 톰캣을 띄우는 웃지 못할 상황을 종종 본다. 이 글에서 언급하는 스프 링은, 범용 IoC 프레임웍 스프링이 아닌, 웹프레임웍 스프링이라는 점을 미리 밝혀둔 다. 덧붙여 이 글이 필자의 짧은 지식과 개인적인 경험에 근거하다 보니, 자바를 중심 으로 전개됨을 미리 밝혀둔다. 웹프레임웍의 과거 보기 좋은 떡이 먹기도 좋다, 웹의 등장 초창기의 웹은 단순한 호스트/터미널 환경이었다. 웹브라우저가 사용자의 입력(URL) 을 받아서 웹서버로 요청을 보내고, 웹서버는 요청받은 HTML 문서를 응답으로 보내 고, 웹브라우저는 서버가 보낸 응답에 포함된 문서의 내용을 사용자에게 보여주는 것 이 전부였다. 기술적인 관점에서 웹서버는 가장 단순한 형태의 소켓 응용프로그램이 었고, HTML은 ANSI 코드를 사람이 쉽게 입력할 수 있는 태그로 바꾸어 놓은 “짝퉁” SGML에 불과했지만, 사용자의 관점에서 웹브라우저는 기존의 VT 터미널과 완전히 다른 물건이었다. 전혀 기술적이지 않는 차이가, 인터넷의 보급 초기 “웹”이 수많은 경 쟁 기술들을 물리치고 “대세”로 자리 잡는 과정에서 지렛대 역할을 한 것이다. 멀어지는 시맨틱의 꿈, 동적 웹 페이지와 CGI 인터넷과 웹의 보급이 늘어나면서 점점 다양해지는 사용자의 요구를 충족하기 위 해서 “동적인 웹 페이지”가 필요했고, 이를 위해서 만들어진 규격이 CGI(Common Gateway Interface)다. CGI를 단어 그대로 해석하면 웹서버를 일종의 (데이터베이스 를 포함한 백엔드에 대한) 공통 게이트웨이로 보고, 웹서버와 응용프로그램 간의 인터 페이스(구체적으로는 환경 변수 이름)를 규정한 것이다. 다르게 표현하면, “웹서버가
  13. 16 H3 개발자 컨퍼런스 2012 웹브라우져와 주고 받을 내용을 응용프로그램에게

    위임하는 방법”이다. RFC822(메 일)와 RFC959(FTP) 대충 합쳐놓은 허술한 HTTP와, 그 허술함 덕분에 등장할 수 있 었던 더 허술한 CGI가, 이후의 웹 중심의 컴퓨팅 시대를 여는 기폭제 역할을 했다. 아 이러니하게도 이때부터 웹은 창시자 팀 버너스 리(Tim Burners-Lee) 일당이 꿈꾸던 웹과 멀어지기 시작했다. 그림 1. CGI 봉이 김선달, WAS의 등장 “위임”이라는 무책임한(?) 아키텍쳐 덕분에 수많은 가능성이 열려 있었고, 그 중의 하 나가 위임할 때마다 매번 다른 응용프로그램을 실행하는 대신, 미리 떠 있는 하나의 응용프로그램 - “웹 애플리케이션 서버”(Web Application Server; WAS)에게 모두 위임하는 방식이었다. 중간에 끼어있는 하나의 응용프로그램, 즉 WAS의 존재에서 “황금”의 냄새를 맡 은 수많은 개발사들이 시장에 뛰어들었다. 네스케이프의 Enterprise Server에 포함 된 NSAPI와 Livewire, 마이크로소프트의 IIS에 포함된 ISAPI와 ASP, ColdFusion, PHP, NetDynamics 등, 무수히 많은 제품들이 OO 서버 페이지, OO 프레임웍 같 은 거창한 이름을 달고 나왔다. 당시로써는 신생 마이너 프로그래밍 언어에 불과했던 자바도 Java Web Server에 포함된 Servlet과 JSP로 재빠르게 이 시장에 뛰어들었 다. 아이러니하게도 Java Web Server의 형편없는 완성도는 Tomcat, Resin, JRun, WebLogic Application Server 등의 제품들이 나올 수 있는 배경이 되었고, 이렇게 확 대된 기반은 자바가 프로그래밍 언어를 넘어 주류 플랫폼으로 자리 잡는 데 결정적인 역할을 했다.
  14. 17 봄날은 간다 이렇게 장황하게 지나간 이야기를 하는 이유는, 무슨

    무슨 서버페이지라고 해봐야 결 국은 HTTP와 CGI의 범주에서 벗어날 수 없다는 점을 강조하기 위해서다. 웹 개발로 계속 먹고살 계획이라면 한번 쯤은 HTTP와 CGI 스펙을 읽어보길 권한다. 최신 스펙 은 양도 많고 어렵지만, 초기 스펙은 양도 적고 쉽다. HTTP와 CGI를 이해하면 웹 개 발에서 마주치는 수많은 제약의 원인을 더 빨리 알 수 있고, 더 좋은 해결책을 더 쉽게 찾을 수 있을 것이다. 수동적 프로그래밍의 시대, 프레임웍의 재발견 태생적으로 중간에 끼어있는 존재인 WAS는 (웹서버가 파일 경로를 보고 CGI 응용프 로그램을 실행하듯) 누군지 알 수 없는 써드파티 개발사가 작성한 도메인 로직을 통 제된 환경에서 실행할 수 있어야 했다. 다음의 서블릿 예제 코드를 보면 init, service, destroy 세 개의 메소드가 보이는데, 문서에 따르면 각각의 메소드는 이러 저러한 상 황에서 “호출된다”. 서블릿 코드 import java.io.IOException; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletLifeCycleExample extends HttpServlet { private int count; @Override public void init(ServletConfig config) throws ServletException { super.init(config); getServletContext().log("init() called"); count=0; } @Override protected void service(HttpServletRequest request, HttpServletResponse re- sponse) throws ServletException, IOException { getServletContext().log("service() called"); count++;
  15. 18 H3 개발자 컨퍼런스 2012 response.getWriter().write("Incrementing the count: Count =

    "+count); } @Override public void destroy() { getServletContext().log("destroy() called"); } } 내가 작성한 코드가 라이브러리 코드를 호출하는 것이 아니라, WAS(CGI의 일종인 응 용프로그램)의 코드가 내가 작성한 코드를 호출한다. 이와 같은 주객이 전도된 흐름을 멋진 말로 제어의 역전(Inversion of Control; IoC)이라고 하고, 다름 아닌 프레임웍의 시발점이다. 프레임웍이 등장하면서부터 (나와 독자를 포함한) 써드파티 개발자가 알 아야 하는 것은 프레임웍이 내가 작성한 코드를 호출하는 시점과 호출된 시점의 문맥 (Context)뿐이다. 개별 개발자의 코드가 프로그램 전체의 흐름을 주도하는 것이 아니라, 플랫폼 제공자 가 결정한 흐름에 개별 개발자가 작성한 코드가 부품처럼 동작하는 “수동적 프로그래 밍” 시대가 다시 돌아왔다. 그 플랫폼은 과거의 그것보다 훨씬 더 거대하고 복잡하고, 개별 개발자가 작성한 코드의 영역은 더 작아졌지만, 더 많은 일을 할 수 있다. 그것이 프레임웍의 힘이다. 살짝 옆 길로 빠져서, 필자가 프레임웍이라는 아키텍처를 처음 본 것은 비아르네 스트 라스트럽(Bjarne Strousrup)의 The C++ Programming Language 2판 부록이었는 데, 비슷한 시기 윈도의 이벤트 드리븐 프로그래밍(Event Driven Programming)을 익 히면서 프레임웍의 개념을 몸소 체득할 수 있었다. 그러나 학교에서 main()으로 시작 하는 리포트용 애플리케이션만 개발하다가 웹 개발자 커리어를 시작했다면 이벤트라 는 단어가 쉽게 와닿지 않을 것이다. 웹브라우저가 대신 이벤트를 처리해서 웹서버 에 “요청”을 보내기 때문에 웹 서버 개발자가 이벤트다운 이벤트를 접할 기회는 거의 없다. 그런 이유로, 이제 막 개발을 시작한 웹 개발자들에게 안드로이드나 iOS의 GUI 프로그래밍을 해보길 강력히 권한다. 앱을 만들어서 대박 날 정도까지 깊이 있게 공 부하지 않더라도, 이벤트 드리븐 프로그래밍을 경험해보는 것만으로, 레벨 업(!)을 보 장한다.
  16. 19 봄날은 간다 웹프레임웍의 현재 생산성 향상의 유혹, MVC의 재발견

    “웹 2.0”이라는 유행어(buzzword)로 요약되는 웹의 황금광 시대는 웹 개발의 모든 면 에서 엄청난 변화를 가져왔다. CGI와 그 연장선에 있는 ISAPI, NSAPI, Servlet 등의 초기 웹프레임웍은 폭발적으로 증가하는 요구를 감당하기에 역부족이었고, 이 틈새시 장에 생산성 증대를 슬로건으로 내건 통합(integrated) 웹프레임웍들이 비집고 들어 왔다. 기존의 CGI 기반 웹프레임웍은 웹 기술에 대해서만 관여할 뿐이지만, 통합 웹 프레임웍들은 웹 뿐 아니라 데이터베이스 접근, 세션 관리, 입출력 값 검증, 템플릿, 보안 등의 범용 프레임웍의 기능을 포괄하기 시작했다. 지금도 명맥을 유지하고 있는 아파치의 터빈(Turbine)을 필두로 스트러츠(Struts), ASP.NET, WebWork, Zope, JSF(Java Server Faces) 등의 프레임웍이 봇물처럼 쏟아져 나왔다. MVC(Model-View-Controller)는 이 무렵에 등장한 거의 모든 프레임웍들이 제각기 자신들만의 특징이라고 주장했던 아키텍처였다. 생산성 향상을 위해서는 분업을 해야 만 했고, 이를 위해서 계층 간 의존성을 줄여야 했다. MVC의 V-C를 분리해준다는 템 플릿 엔진(Template Engine)과 M-C를 분리해준다는 DAO(Data Access Object) 와 ORM(Object-Relation Mapper)은 지금도 인기를 누리고 있다. 그림 2. Model-View-Controller
  17. 20 H3 개발자 컨퍼런스 2012 바다 건너에서는 스트러츠의 인기가 시들해질

    무렵, 국내에는 스트러츠에 기반을 둔 “한국형” 웹프레임웍들이 등장했지만, (훗날 모델1라고 명명된) JSP, ASP, PHP 날 코딩으로 월화수목금금금을 실천하던 이 땅의 웹 개발자에겐 그마저도 시련의 시기 였다. 적과의 동침, 자바스크립트의 재발견 서버 사이드가 변화를 거듭하는 동안, Internet Explorer 6와 Active-X의 벽에 막혀 제자리걸음을 하고 있던 클라이언트 사이드도, AJAX를 기점으로 급변하기 시작했다. 아이러니하게도(이 글을 쓰다 보니 아이러니가 참 많기도 하다), 마이크로소프트가 익스체인지 서버(Exchange Server)의 웹 클라이언트인 아웃룩 웹액세스(Outlook WebAccess)를 만들기 위해 Internet Explorer에 추가한 비표준 기능에 불과했던 XMLHttpRequest가, AJAX(Asynchronous Javascript and XML)의 핵심 요소로 웹 2.0 시대의 도화선 역할을 했다. 지금은 존재감도 희미한 Prototype.js를 시작으로, 지금은 De-facto로 자리잡은 jQuery도 이 시기에 등장했지만, 웹브라우져의 반응성을 높이고, 시각적인 효과를 가 미하는 등의 보조적인 역할에 머물렀다. 웹 UI 툴킷의 원조 격인 Dojo, YUI 등도 이때 등장했지만, 당시 웹브라우저의 성능으로는 “가까이하기엔 너무 무거운 UI”로 외면받 았다. Easy Come Easy Go, 루비 온 레일즈 2006년, 그야말로 혜성처럼 등장한 루비 온 레일즈(Ruby-on-Rails; 이하 레일즈)는 5분 만에 블로그를 만드는 동영상과 Convention-over-Configuration(CoC; 설정보 다 관례 우선)이라는 감언이설(?)로 센세이션을 일으켰다. 그리고 그뿐이었다. 5분 만 에 만든 블로그를 서비스로 할 수 있는 수준으로 만드는 데 몇 달이 걸렸고(개발은 코 딩만으로 끝나는 것이 아님을 새삼 깨닫게 해주었다), 그걸 유지 보수할 수 있는 사람 은 사막의 바늘만큼 구하기 어려웠다. 결국, 힘들게 만든 서비스를 “관리 가능한” 자바 와 스프링으로 다시 작성하는 데 반년의 시간을 들여야 했다. 그러나 레일즈가 초기 학습 비용 감소를 위해 채택한 CoC와 스캐폴딩(scaffold), REST 기반의 라우팅(route) 등은 Grails, CakePHP, Django, Play 등 이후의 웹프레 임웍에 지대한 영향을 끼쳤다.
  18. 21 봄날은 간다 그림 3. 레일즈가 생성한 기본 웹 애플리케이션

    따뜻한 봄날, 스트러츠에서 스프링으로 이 땅의 개발자들이 스트러츠에 매달려, 스트러츠 개발자들마저 등을 돌린 스트러츠2 라는 구세주를 기다리는 사이, 바다 건너에서는 IoC(Inversion of Control; 제어의 역 전), DI(Dependency Injection; 의존성 주입), SoC(Separation of Concern; 관심사 의 분리) 논쟁으로 뜨거웠다. 논쟁의 불씨를 당긴 스티브 맥코넬(Stephen McConnel) 의 Avalon 프로젝트가 버전 다운 릴리즈를 포함한 4개의 포크(fork)로 공중분해 되고, 어부지리로 승리를 얻은 것이 로드 존슨의 스프링이었다. 스프링은 범용 IoC 컨테이 너에서 출발해서 비교적 늦게 웹프레임웍 시장에 뛰어들었지만, IoC의 장점을 활용한 무한한 융통성을 무기로, DAO와 ORM을 통한 데이터베이스 접근, 트랜잭션, 세션관 리, 템플릿 엔진, 보안 등 웹 개발자의 모든 고민을 일거에 해결해주며 “대세”로 자리 잡았다. 한 참 뒤에 스프링에 기반을 둔 “한국형” 웹프레임웍이 나왔지만, (훗날 모델2 라고 명명된) 스트러츠의 ActionMapping과 ActionForm에 겨우 익숙해진 이 땅의 개 발자들에겐 봄날은 아득하게만 느껴졌다.
  19. 22 H3 개발자 컨퍼런스 2012 그림 4. 스프링의 모듈 구성

    거꾸로 매달아도 국방부 시계는 돌아간다고 했던가? IoC를 몰라도 월급날은 어김없 이 다가온다. 시련의 시기가 끝나고, 지난 몇 년 동안 이 땅의 개발자들은 따뜻한 봄 날을 만끽하고 있다. 웹 개발은 스프링이었고, 스프링은 웹 개발이었다. 스프링의 applicationContext.xml가 없으면 트랜잭션도 처리할 수 없고, Velocity 템플릿은 JSP보다 더 복잡한 매크로가 가득했지만, 아무도 스프링 없는 세상을 걱정하지 않 았다. 그러는 동안에도, 바다 건너에서는 Ruby-on-Rails, Django, Tapestry, CakePHP 등 새로운 웹프레임웍들이 쉴 새 없이 쏟아져 나오고 있었다. 사실, 레일즈는 스프링 2.0과 거의 비슷한 시기에 만들어졌지만, 국내에서는 스프링이 스트러츠의 벽에 막혀 고전하는 동안에 먼저 소개되었다. 그리고 먼저 사라졌다. 영화 속에서, 사랑에 빠진 은수와 상우를 앞에 두고 노부부가 노래한다. “서산에 지는 해는 지고 싶어 지나, 나를 버리고 가시는 님은 가고 싶어 가나...” 웹프레임웍의 미래 소셜, 모바일 그리고 클라우드 최근 몇 년 동안 IT 분야의 화두를 꼽으라면 단연 “소셜(social)”과 “모바일(mobile)” 이다. 트위터와 페이스북으로 시작된 소셜과 아이폰에서 시작된 모바일이 상승효과 를 일으키면서 개발자에게 다시 시련의 겨울이 찾아왔다. 앱 만들어서 대박 났다는 아
  20. 23 봄날은 간다 무개의 소식에 혹해서, 이름도 낯선 Objective-C 책도

    한 권 보고, 학교 리포트 이후 로는 구경도 못해 본 Swing/AWT 비스름한 안드로이드 GUI 책도 한 권 봤는데, 아 무개는 어디서 뭘 하고 있는지 모르겠고, 애플 개발자 등록비 $99만 날렸다. 하이브 리드(hybrid)가 대세라길래 거들떠봤더니 결론은 자바스크립트를 잘해야 한단다. 개 발자가 꺼리는 노가다 중에서도 최고로 꼽던 자바스크립트가 대세라니, 다시 공부해 야 하나? 아파치 앞에 놓고, 톰캣 클러스터에 mod_jk로 연결하고, 스프링에 iBatis 통 해서 MySQL 클러스터에 접근하는 것밖에 안 배웠는데, 빅데이터, 클라우드, 비동기, NoSQL... 그야말로 OTL이다. 웹프레임웍 얘기하다 말고 뜬금없이 소셜, 모바일, 클라우드? 최근 웹프레임웍의 변 화는 소셜과 모바일이 가져온 축복이자 재앙인 “빅데이터”와, 해결사로 등장한 “클라 우드”와 밀접한 관련이 있다. 흔한 예로, 10,000명의 팔로어를 가진 트위터 사용자가 내 트윗을 리트윗하는 시나리 오를 생각해보자. 10,000명의 팔로어들의 타임라인에 내 트윗이 보여야 한다. 기존의 RDB스러운 사고방식으로 보면 내가 쓴 트윗과 리트윗한 사용자와 그 트윗을 보게 될 팔로어 간에 10,000개의 새로운 관계가 만들어진다. 이런 상황이 1분에 1번씩 있다 면 하루에 864,000,000(=10000*60*60*24)의 행이 추가되는 것이다. 이 숫자는 몇 번의 리트윗을 거치면서 기하급수로 증가한다. 그러다가 90만 명의 팔로어를 가진 금 강경(!?)이 리트윗이라도 하면? 어떻게 해야 할까? 소셜과 모바일이 결합해서 만들어 내는 빅데이터가 누군가에겐 축복이겠지만, 개발자들에겐 재앙이다. 다른 예로, 3억 명의 사용자를 가진 페이스북이 보낸 “당신의 친구 아무개님이 당신도 알 것 같은 아무개님과 친구가 되었어요. 혹시 이 사람 알지 않아요?”라는 신기한 메 일을 본 기획자는 기쁨에 가득 찬 목소리로 개발자인 당신에게 쿨하게 한마디, “우리 도 이렇게 해주세요!” 어떻게 해야 할까? 누군가에겐 인센티브 올라가는 소리겠지만, 개발자들에겐 졸업하고 처음 들어보는 “아카데믹”한 소리다. 하루에 10억 개의 행이 추가되는 RDB는 어떻게 구성해야 할까? 익숙한 방식대로 슬 레이브(slave)를 늘려보지만, 복제(replacation)를 하는 사이에 10,000개의 행이 추 가되고, 다시 복제가 시작된다. 요즘은 클라우드가 만능이라던데, 클라우드가 출동하 면 어떨까? 트랙과 섹터 사이를 오가는 디스크 헤드의 물리적인 움직임까지 최적화했 다는 멋지지만 비싼 RDBMS가 가상화된 디스크 환경에서 어떻게 동작할지 상상해 보 자. 상상이 잘 안 된다면 SSD에 디스크 조각모음을 돌리면서 곰곰히 생각해보자, 내가 지금 무슨 짓을 하고 있는지를... 이런 얘기를 듣는 사람들의 반응은 거의 한결같다.
  21. 24 H3 개발자 컨퍼런스 2012 “우리 서비스는 그렇게 대단한 서비스가

    아니에요. 제온 8코어에 16G씩 꽂아서 MySQL 1+3 클러 스터로 묶으면 충분해요~ 아~ 디스크요? 그건 16테라짜리 SAN 붙였죠.” 그런데 그것보다 더 큰 작업을 Cassandra, MongoDB 등이 1T짜리 시게이트 하드 디 스크를 몇 개 꽂은 PC 몇 대로 해치우면서 사람들의 관심을 끌기 시작했다. “도대체 NoSQL이 뭐야?” 하루에 10억 페이지뷰를 처리하는 톰캣은 어떻게 구성해야 할까? 익숙한 방식대로 CPU와 메모리를 업그레이드하고 쓰레드 풀을 늘려보지만, 어느 순간 CPU는 놀고 있 고, 자바의 힙은 놀고 있는 쓰레드로 가득 차 있을 뿐, 응답이 없다. 요즘은 클라우드 가 만능이라던데, 클라우드가 출동하면 어떨까? 이름도 멋지고 가격도 저렴한(시간당 $2) 아마존 EC2 쿼드러플 엑스트라 라지 인스턴스에 올려보지만, 올라가는 건 청구서 금액뿐이다. 이런 얘기를 듣는 사람들의 반응은 거의 한결같다. “우리 서비스는 그렇게 대단한 서비스가 아니에요. 제온 8코어에 16G씩 꽂아서 앞에 아파치 2대 뒤에 톰캣 2대만 묶으면 충분한걸요~ 아~ 프레임웍이요? 물론 스프링에 iBatis죠. 스트러츠가 편한데 갑 이 스프링으로 하래요.” 그런데 그것보다 더 대단한 작업을 NginX, Node.js 등이 “코어 2 듀오” PC 1대로 해 치우면서 사람들의 관심을 끌기 시작했다. “도대체 비동기가 뭐야?” 15년의 세월을 담으려는 욕심에 잡설이 많이 길어졌다. 이제부터 본론! Simply the Best, 비동기의 재발견 집적도, 발열, 간섭 등의 물리적인 한계 탓에 개별 CPU 코어의 성능이 정체된 상 황에서 멀티 코어를 최대한 활용할 수 있는 기술들이 주목받고 있다. “비동기 (asynchronous)”는 그중에서도 가장 뜨거운 감자다. 구글 크롬의 V8 자바스크립트 엔진을 재활용한 서버사이드 자바스크립트로 출발한 Node.js는, 서버사이드를 주름 잡던 멀티쓰레드 기반의 프레임웍들이 모바일과 소셜 의 빅뱅이 만들어낸 엄청난 트래픽을 감당하지 못해 버벅거리는 상황을, 콜럼부스의
  22. 25 봄날은 간다 달걀처럼 단순무식하게(!) 해결하면서, 개발자들도 예상치 못한 성공을

    거두고 있다. 그 콜럼부스의 달걀은 “어차피 멀티쓰레드로 감당하지 못할 거라면, 한 번에 하나씩, 기다려야 하는 놈은 뒤로 보내 버리고, 빨리빨리 처리하자”는 것인데, 멋진 말로 “비동 기(asynchronous)”, “이벤트 큐(event queue)”, “넌블러킹(non-blocking) I/O”라고 한다. 은행에서는 대기표 받고 기다리다가 상담원과 마주 않는 순간부터 그 상담원은 다른 고객을 받지 않고 내 업무가 끝날 때까지 내 일만 처리한다. 고객 개개인의 업무는 확 실하게 처리되지만, 상담원의 수가 충분하지 않으면 소파에 앉아있는 고객들, 기다리 다 지쳐 돌아가는 고객들이 늘어날 수밖에 없다. 이것이 동기(synchronous) 방식이다 (그림 4). 그림 5. 멀티쓰레드 서버 아키텍쳐 별다방에서는 단일한 창구에서 주문만 하고 뒤로 빠진다. 뒤에서 기다리는 동안 점원 은 다른 주문을 받고, 커피도 내리다가 내 커피가 준비되면 나를 부른다(callback). 이 과정에서 점원이 커피를 엎지르면 매장 전체의 업무가 중단되고, 고객 모두가 기다려 야 한다. 큰 많은 매장에서는 커피만 내리는 점원(worker)을 따로 두기도 한지만, 주 문을 받고 커피를 내 주는 창구는 하나뿐이다. 이것이 비동기 방식이다(그림 5).
  23. 26 H3 개발자 컨퍼런스 2012 그림 6. Node.js의 이벤트 큐

    기반 비동기 서버 아키텍쳐 이벤트 큐 방식의 비동기 아키텍처는 앞에 있는 작업이 하나라도 시간을 끌면 뒤에서 기다리고 있는 다른 작업들은 무한정 기다릴 수밖에 없다는 치명적인 결함을 내재하 고 있다. 이 작업들 반대쪽 끝에는 웹브라우저(혹은 스마트폰 앱)를 쳐다보고 있는 인 내심이 부족한 사용자가 있다는 사실을 떠올려 보면... 태생이 20세기 개발자인 필자에게는 1990년대 초반을 뜨겁게 달궜던 선점형 (preemptive) vs 비선점형(non-preemptive; cooperative) 멀티 태스킹 논쟁의 데자 뷰다. 예나 지금이나 해결책은 개발자들이 코딩할 때 긴 작업을 여러 개의 비동기 작 업으로 잘 쪼개서 작성하는 것 뿐인데, 이 과정이 그리 녹록지 않다. 99%의 비선점 코 드가 1%의 선점 코드에 발목이 잡혔던 20세기 개발자들의 전철을, 21세기 개발자들 은 되풀이하지 않기를 바랄 뿐이다. Keep it simple, Stupid! 경량 웹프레임웍의 재발견 CGI에서 OO서버 페이지를 거쳐 스프링에 이르기까지 끊임없이 기능을 추가하면서 몸집을 부풀려온 주류 웹프레임웍들에 대한 반작용으로 Sinatra(루비)와 Flask(파이 썬), Express(Node.js), Spray(스칼라) 등의 경량(lightweight) 웹프레임웍도 다시 주 목받고 있다. 경량 웹프레임웍은 데이터베이스 접근 지원이나 템플릿 엔진 등의 기능 을 과감히 제거하고, 수신한 요청을 라우팅하고, 결과를 응답에 실어 보내는 웹 애플 리케이션 본연의 과정에 충실하다.
  24. 27 봄날은 간다 Sinatra 프레임웍으로 작성한 Hello, World $ gem

    install sinatra $ cat > hello.rb require 'sinatra' get '/hello/:name' do |name| 'Hello, #{name}' end $ ruby -rubygems hello.rb Flask 프레임웍으로 Hello World 만들고 실행하기 $ pip install Flask $ cat > hello.py from flask import Flask app = Flask(__name__) @app.route("/hello/<name>", methods=["GET"]) def hello(name): return "Hello, %s" % name if __name__ == "__main__": app.run() $ python hello.py Express 프레임웍으로 Hello World 만들고 실행하기 $ npm intall express $ cat > hello.js var express = require('express'), app = express(); app.get('/hello/:name', function (req, res) { res.send('Hello, ' + req.param('name')); }); app.listen(3000); $ node hello
  25. 28 H3 개발자 컨퍼런스 2012 Spray 프레임웍으로 Hello World 만들고

    실행하기 $ git clone git://github.com/spray/spray-template.git . $ cat > src/main/scala/hello.scala import cc.spray._ trait HelloService extends Directives { val helloService = { path("hello" / PathElement) { name => get { completeWith { "hello, " + name } } } } } $ sbt run 비교를 위해서 스프링이나 레일즈로 만든 Hello World의 소스를 여기에 다 나열하는 짓(?)은 하지 않겠다. 이 정도의 예제라면 뭐로 만들어도 큰 차이는 없겠지만, 웹 프로 그래밍에 대한 기본 지식(HTTP와 CGI)만 있다면 프로그래밍 언어 자체에 대한 지식 이 없어도 어느 정도 코드의 의도를 파악할 수 있을 정도로 직관적이다. HTML5와 웹앱, 그리고 프론트엔드 웹프레임웍 경량 웹프레임웍이 다시 주목받는 또 다른 이유는 HTML5와 웹앱의 확산이다. 구글 크롬의 등장으로 촉발된 웹브라우저의 버전업 경쟁 덕분에 웹브라우저의 성능이 비약 적으로 향상됐고, 웹브라우저의 역할이 확대되면서 서버가 해야 할 일이 상대적으로 줄어들었다. 쉬운 예로, 서버에서 모델 데이터와 뷰 템플릿 결합하여(render) 완성된 HTML을 보 내는 대신, 서버는 모델 데이터만 보내고 웹브라우저에서 자바스크립트로 (로컬에 캐 시된) 뷰 템플릿과 결합하는 단일 페이지 인터페이스(Single Page Interface; SPI)이 확대되면서 Velocity 같은 서버 사이드 템플릿 엔진이 불필요해졌다. 웹 애플리케이션 개발에서 “노가다”로 분류됐던 웹 퍼블리셔(또는 웹 코더)들도 더 복잡하고 더 많은 자바스크립트 코드를 작성하게 되면서 “프론트엔드(frontend) 개 발자”로 재조명받고 있다. 이와 함께 JavaScript MVC, SproutCore, Backbone.js, Knockout.js, Sencha Touch(ExtJS) 등의 수많은 프론트엔드 웹프레임웍이 등장했다.
  26. 29 봄날은 간다 대부분의 프론트엔드 웹프레임웍은 URL 해시(#) 기반의 라우팅,

    템플릿 엔진, 자바스 크립트 객체 기반의 모델 등의 기능을 제공하며, UI 툴킷, 서버와의 양방향 RPC, 웹스 토리지나 HTTP를 통한 모델 퍼시스턴스(persistence) 계층 등을 함께 제공하는 프레 임웍도 많다. Backbone.js의 MVC <script type="text/template" id="item-template"> <div class="view"> <input class="toggle" type="checkbox" <%= done ? 'checked="checked"' : '' %> /> <label><%- title %></label> <a class="destroy"></a> </div> <input class="edit" type="text" value="<%= title %>" /> </script> <script type="text/javascript"> var Todo = Backbone.Model.extend({ defaults: function() { return { title: "empty todo...", order: Todos.nextOrder(), done: false }; }, initialize: function() { if (!this.get("title")) { this.set({"title": this.defaults().title}); } }, ... }); var TodoView = Backbone.View.extend({ template: _.template($('#item-template').html()), initialize: function() { this.model.on('change', this.render, this); this.model.on('destroy', this.remove, this); }, render: function() { this.$el.html(this.template(this.model.toJSON())); this.$el.toggleClass('done', this.model.get('done')); return this; }, ...
  27. 30 H3 개발자 컨퍼런스 2012 }); </script> Knockout.js의 MVVM <select

    data-bind="options: tickets, optionsCaption: 'Choose...', optionsText: 'name', value: chosenTicket"></select> <button data-bind="enable: chosenTicket, click: resetTicket">Clear</button> <p data-bind="with: chosenTicket"> You have chosen <b data-bind="text: name"></b> ($<span data-bind="text: price"></span>) </p> <script type="text/javascript"> function TicketsViewModel() { this.tickets = [ { name: "Economy", price: 199.95 }, { name: "Business", price: 449.22 }, { name: "First Class", price: 1199.99 } ]; this.chosenTicket = ko.observable(); this.resetTicket = function() { this.chosenTicket(null) } } ko.applyBindings(new TicketsViewModel(), document.getElementById("liveExam- ple")); </script> Sencha Touch의 MVC Ext.define('User', { extend: ‘Ext.data.Model’, fields: [ {name: ‘name’, type: ‘string’}, {name: ‘age’, type: ‘int’}, {name: ‘pic’, type: ‘string’} ] }); var myStore = Ext.create(‘Ext.data.Store’, { model: ‘User’, proxy: { type: ‘ajax’, url : ‘/users.json’,
  28. 31 봄날은 간다 reader: { type: ‘json’, root: ‘users’ }

    }, autoLoad: true }); Ext.create(‘Ext.DataView’, { fullscreen: true, store: myStore, itemTpl: ‘<img src=”{pic}” /><h2>{name}</h2><p>{age} years old</ p>’ }); 자바스크립트에 익숙하지 않은 독자들에겐 다소 생소해 보이겠지만, 본질은 기 존 서버 사이드 웹프레임웍과 크게 다르지 않다. 가장 큰 차이점은 퍼시스턴스 (persistence) 계층인데, (혼자 놀기 애플리케이션이 아니라면) 결국은 서버에 데이터 를 저장해야 하는데, 현재로썬 정형화된 방법이 없고, 프레임웍에 따라 다양하다. 두 마리 토끼를 한 번에, Play! 프레임웍 플레이(Play!)는 그루비(Groovy) 템플릿 엔진, 하이버네이트(Hibernate) ORM 등을 채택한 자바 개발자를 위한 레일즈 “류”의 웹프레임웍으로 시작했지만, 2.0부터는 자 바와 스칼라를 병행 채택하고, 실용적인 레일즈 ”류” 웹프레임웍과 고전적인 스프링 ” 류” 웹프레임웍의 장점을 모두 취하려는 야심 찬 웹프레임웍이다. 레일즈(루비)나 장고(파이썬)같은 좋은 웹프레임웍이 프로그래밍 언어의 보급과 성능 이라는 벽을 넘지 못한 전례를 거울삼아, 플레이는 어디에서나, 누구나 관리 가능한 (?) 자바와, 호기심 많은 개발자를 위한 스칼라를 함께 지원하여 두 마리 토끼를 한 번 에 잡으려 하지만, 프레임웍 자체가 스칼라로 작성되었고, 사용하는 도구들도 대부분 스칼라 기반이라, 현실적으로 플레이로 진지한 웹 애플리케이션을 개발하려면 스칼라 에 대한 이해는 불가피하다.
  29. 32 H3 개발자 컨퍼런스 2012 그림 7. 플레이가 생성한 기본

    웹 애플리케이션 자바로 작성한 플레이 컨트롤러 package controllers; import play.*; import play.mvc.*; import views.html.*; public class Application extends Controller { public static Result index() { return ok(index.render("Hello, World!")); } } 스칼라로 작성된 플레이 컨트롤러 package controllers import play.api._ import play.api.mvc._ object Application extends Controller {
  30. 33 봄날은 간다 def index = Action { Ok(views.html.index("Hello, World!"))

    } } 스칼라 DSL 기반의 플레이 뷰 템플릿 @(tasks: List[Task], taskForm: Form[String]) @import helper._ @main("Todo list") { <h1>@tasks.size task(s)</h1> <ul> @tasks.map { task => <li> @task.label @form(routes.Application.deleteTask(task.id)) { <input type="submit" value="Delete"> } </li> } </ul> <h2>Add a new task</h2> @form(routes.Application.newTask) { @inputText(taskForm("label")) <input type="submit" value="Create"> } } 플레이는 자바 개발자를 위해 Ebean ORM, 스칼라 개발자를 위해 Anorm을 기본 데이터 접근 계층으로 제공하지만, JPA, ScalaQuery 등을 다른 자바나 스칼라 라 이브러리도 쓸 수 있다. 그 외에도 Evolution을 통한 데이터베이스 스키마 버전 관 리, Comet과 WebSocket 지원, 내장된 Netty 웹서버를 통한 편리한 개발과 디버깅, WAR 파일 내보내기, 이클립스, IntelliJ, 넷빈즈 등의 통합 개발 환경 지원 등 최신 웹 프레임웍에 걸맞은 다양하고, 강력한 기능을 자랑한다. 플레이의 가장 큰 장점은 프레임웍 자체가 비동기 처리를 전제로 설계되어 있고, 내장 된 Netty 웹서버, AKKA 프레임웍 연동 등을 통해 효율적인 비동기 처리가 가능하다 는 점인데, 이 장점들은 대부분 스칼라에서 기인한 것이라, 보는 관점에 따라 오히려 약점이 되기도 한다.
  31. 34 H3 개발자 컨퍼런스 2012 AKKA를 활용한 비동기 처리 def

    index = Action { Async { Akka.future { longComputation() }.map { result => Ok("Got " + result) } } } 스칼라가 배우기 쉬운 언어도 아니고, 스칼라에 익숙한 개발자를 찾기도 어렵다. 그러 나 함수형 언어, 명령형 언어, 객체지향 언어의 학문적 특징과 실용성을 함께 갖춘 흔 치 않은 언어라는 점에서, 시간을 들여서라도 배울 만한 가치가 있다는 점은 내가(?!) 보증한다. 특히 루비에 익숙한 개발자라면 절반은 먹고 들어가는 이 기회를 놓치지 않 기를... 나가는 글 가벼운 마음으로 “세상에는 스프링만 있는 것도 아니고, 스프링도 영원하지 않다”를 모티브로 삼아 시작한 글이, 시작할 때의 마음과는 달리 “웹프레임웍의 과거와 현재를 통해 미래를 준비하자!”라는 거창한 주제를 가진 IT 무협소설(?)이 되어 버렸다. 필자 도 지금은 비록 회사의 젊은 동료로부터 20세기 개발자라는 핀잔 아닌 핀잔을 듣는 신 세지만, 조만간 세기를 넘나드는 개발자라고 되받아칠 순간을 고대하며 Express 프레 임웍(Node.js)과 Spray 프레임웍(스칼라)를 열심히 익히고 있다. 필자의 짧은 지식과 일천한 경험으로 쓴 글이라 왜곡된 부분도 많지만, 21세기 웹 개발자들이 밥줄의 미래 를 한 번쯤 고민해 보는 계기가 되었으면 하는 바람이다. 영화가 끝날 무렵, 은수와 헤어지고 괴로워 하는 상우에게 할머니가 한마디 툭 던 진다. “버스와 여자는... 떠나면 잡는 게 아니란다.”
  32. 35 봄날은 간다 참고자료 HTTP, W3C http://www.w3.org/Protocols/HTTP/AsImplemented.html HTTP, 위키피디아 http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol

    CGI,위키피디아 http://en.wikipedia.org/wiki/Common_Gateway_Interface 자바 서블릿, 위키피디아 http://en.wikipedia.org/wiki/Java_Servlet 소프트웨어 프레임웍, 위키피디아 http://en.wikipedia.org/wiki/Software_framework  프레임웍 vs 라이브러리, 스택오버플로 http://stackoverflow.com/questions/148747/ what-is-the-difference-between-a-framework-and-a-library  제어의 역전(IoC; Inversion of Control), 마틴파울러 http://martinfowler.com/bliki/ InversionOfControl.html  웹 애플리케이션 프레임웍, 위키피디아 http://en.wikipedia.org/wiki/Web_application_ framework  웹 애플리케이션 프레임웍 비교표, 위키피디아 http://en.wikipedia.org/wiki/Comparison_ of_web_application_frameworks  자바스크립트 MVC 프레임웍 비교 http://codebrief.com/2012/01/the-top-10- javascript-mvc-frameworks-reviewed/ Spring 프레임웍 홈페이지 http://www.springsource.org Play 프레임웍 홈페이지 http://www.playframework.org Spray 프레임웍 홈페이지 http://spray.cc Flask 프레임웍 홈페이지 http://flask.pocoo.org Sinatra 프레임웍 홈페이지 http://www.sinatrarb.com Express 프레임웍 홈페이지 http://expressjs.com Prototype js 홈페이지 http://prototypejs.org jQuery 홈페이지 http://jquery.com Dojo Toolkit 홈페이지 http://dojotoolkit.org Knockout 프레임웍 홈페이지 http://knockoutjs.com Backbone 프레임웍 홈페이지 http://backbonejs.org Sencha Touch 홈페이지 http://www.sencha.com
  33. 36 H3 개발자 컨퍼런스 2012 클라우드가 나오기 이전에는 서비스를 개발하기에

    앞서 시스템 아키텍처를 잡을 때 최우선 순위에 있던 것이 하드웨어였습니다. 개발팀과 운영팀은 요구하는 스펙에 따 른 하드웨어의 크기, 그 크기에 따른 전력량, 설치 장소에 대한 고민, 네트웍은 어떻게 연결해야 하며, 데이터를 저장할 스토리지는 SAN/NAS/로컬 등 고민한 끝에 결정을 하고, 그 환경에 맞게 개발을 들어가게 됩니다. 사용 중 증설이 필요할 경우, 시스템을 추가 구매해야 하고 또 네트웍 작업을 해야하며, 스토리지와 연결해야 합니다. 앱(APP) 중심으로 생각하기 DevOps와 자동화 DEVOPS팀 김동수 [email protected]
  34. 37 앱(APP) 중심으로 생각하기 DevOps와 자동화 서버 중심 설계 출처:

    http://news.cnet.com/8301-19413_3-10470260-240.html 하지만, Amazon Cloud Service를 시작으로 클라우드 컴퓨팅이 활성화되고 퍼블릭 클라우드와 프라이빗 클라우드가 활성화 되면서, 새로운 서비스를 시작하거나, 기존 서비스의 시스템을 증설할 때 하드웨어에 대한 고민에 할애하는 노력은 아주 조금만 해도 됩니다. 시스템 성능이 떨어지면 웹콘솔에서 버튼 클릭만으로 관리가 되고, 증설 또한 부하에 따라 자동으로 되므로, 서비스를 하기 위한 앱(APP) 중심으로 생각할 수 있게 되었습니다. 앱 중심 설계 출처: http://news.cnet.com/8301-19413_3-10470260-240.html
  35. 38 H3 개발자 컨퍼런스 2012 이렇게 클라우드의 도움으로 앱 중심으로

    생각할 수 있게 되면서 개발과 운영에 있어 중간적인 입장에서 역할을 수행하는 방법론인 DevOps에 대한 언급이 많이 되고 있습 니다. 여기서는 DevOps에 대한 이야기와 KTH에서 DevOps를 어떠한 계획으로 수용 하여 진행하고 있는지 이야기를 하고자 합니다. DevOps에 대해서 이야기 하기에 앞서, DevOps를 소개하는 자료에서 자주 등장하는 3개의 서비스를 간단히 살펴 보겠습니다. Netflix는 미국에서 BlockBuster라는 거대한 오프라인 영화 렌탈 체인을 함몰시킨 VOD 회사로 이 많은 트래픽을 감당하기 위해 AWS에 10,000개 이상의 인스턴스를 10명의 DevOps 팀으로 운영하고 개발을 지원하고 있습니다. Flickr는 2004년 2월부터 서비스 하고 있는 사진 중심의 SNS 서비스로, 초당 40,000 장의 사진이 업로드 되고 있습니다. 거의 모든 것을 자동화하고, 개발과 운영 각각의 문화를 바꾸고, 서로 협력하여, 서로 협력하여 하루에도 10번씩 새로운 코드를 배포할 수 있도록 하였습니다.
  36. 39 앱(APP) 중심으로 생각하기 DevOps와 자동화 fotopedia는 2006년 파리에서 설립된

    20여명의 직원으로 구성된 기업으로, 인간 중 심의 사진이라는 모토로 Flickr와 Wikipedia를 섞어 놓은 서비스를 제공하고 있습니 다. 일일 1억 5000만의 페이지뷰를 생성하는 사이트입니다. AWS 클라우드에 시스템 을 구축하여 1개의 MySQL DB와 4개의 MongoDB Cluster로 운영되고 있으며, 매일 평균 3개정도의 hot-patch를 배포하고 있습니다. 이들 서비스를 제공함에 있어 공통적으로 개발과 운영에 적용한 방법론이 DevOps입 니다. 위의 세 서비스 이외에도 DevOps 방법론을 적용하고 서비스 하는 곳은 점점 더 많아지는 추세입니다. 그럼 DevOps에 대해서 좀 더 자세히 이야기 해 보겠습니다. DevOps는 무엇인가? IT에 몸을 담고 있는 분이라면 “DevOps”라는 단어만 보더라도 무엇이 합쳐져서 만들 어진 용어인지 쉽게 짐작할 수 있을 것입니다. 짐작되는 대로 Development (개발)와 Operations (운영)의 두 단어가 합쳐진 합성어입니다. 영문 Wikipedia에서는 DevOps를 다음과 같이 정의하고 있습니다.
  37. 40 H3 개발자 컨퍼런스 2012 DevOps라는 합성어는 소프트웨어 개발자들과 IT

    종사자들 사이의 의사소통, 협업, 융 합을 강조한 소프트웨어 개발 방법론이며, 소프트웨어 개발과 IT 운영간의 상호 의존관 계에 대한 산물이다. DevOps는 조직에서 소프트웨어 상품과 서비스를 신속히 생산하는 것에 도움이 되는 것을 목적으로 한다. DevOps(a portmanteau of development and operations) is a software development method that stresses communication, collaboration and integration between software developers and information technology(IT) professionals. DevOps is a response to the interdependence of software development and IT operations. It aims to help an organization rapidly produce software products and services. http://en.wikipedia.org/wiki/Devops 즉, 소프트웨어를 만들어 내는 개발자, 잘 동작하도록 운영하는 운영자, 그리고 그 소 프트웨어의 품질을 관리하는 품질관리 조직이, 소프트웨어를 개발, 빌드, 테스트, 배 포, 운영에 이르는 사이클을 신속하게 진행할 수 있도록, 업무 프로세스를 정의하고, 각 조직간의 역할을 조율하고, 그 프로세스들을 자동화하여 효율적으로 운영되도록 하는 역할과 방법론을 DevOps라고 할 수 있습니다. devopsdays 2009, from http://devopsdays.org/ DevOps 용어는 2009년 벨기에에서 시작되어, 인도, 미국, 브라질, 오스트리아, 독 일, 스웨덴 등지에서 개최되고 있는 “Devops Days” 행사로부터 보급되기 시작했습 니다.
  38. 41 앱(APP) 중심으로 생각하기 DevOps와 자동화 devopsdays 2012 사이트 이

    행사는 2009년 이후 해마다 세계 여러 나라에서 개최되고 있으며, 2012년에는 일본의 도쿄, 호주의 시드니, 미국의 마운틴뷰, 인도, 이탈리아에서 개최됩니다. 6월 28~29일 마운틴뷰에서 DevOps Days Mountain View 2012 행사가 열리고, 저희 DevOps 팀에서도 참석하여 많은 경험을 얻고 왔습니다. 참관기 링크 • http://dev.kthcorp.com/2012/07/02/devopsdays-mountain-view-2012-report-1-by- kth • http://dev.kthcorp.com/2012/07/03/devopsdays-mountain-view-2012-report-2-by- kth
  39. 42 H3 개발자 컨퍼런스 2012 잦은 배포의 효과 DevOps를 이야기

    하면서, 애자일 방법론이 빠질 수는 없습니다. 그 이유는 다음의 그림에서 애자일과 워터 폴 방식에서의 위험도의 변화차이로 설명 할 수 있습니다. 잦은 릴리스로 인한 위험의 하향 균등화, from http://en.wikipedia.org/wiki/DevOps#Devops_Days 애자일 방법론을 적용하면 작게 그리고 잦은 릴리즈를 하게 되어, 변경되는 범위가 작 아지므로, 릴리즈에 따른 위험도가 낮게 균등해 집니다. 반면에, 전통적인 워터 폴 방 법론을 적용하는 SI 프로젝트와 같은 경우 긴 텀을 두고 한번에 여러 기능을 개발하고 배포하므로 그 추가되는 기능만큼 위험도가 커지게 됩니다. 이렇게 잦은 주기로 반복적으로 배포를 매끄럽게 수행하기 위해서는 만족되어야 하는 것이 있습니다. 첫째, 잦은 개발 및 배포와 그에 따른 버그 픽스를 할 수 있고, 공유할 수 있는 소스코드 버전 관리 시스템이 있어야 합니다. 이것이 없다면, 동시에 여러 버 전을 운영하는 환경에서는 잦은 개발 및 배포를 할 수 없게 됩니다. 둘째, 빌드, 테스 트, 배포 단계를 가능한 한 자동화 해야 합니다. 빌드, 테스트, 배포 단계를 수작업으 로 하게 된다면, 실수가 있을 수 있고, 각 단계마다 많은 시간이 반복 소요되어 효율이 낮아지므로, 자동화를 통해 효율성을 확보해야 합니다. 그리고, 셋째 서비스를 개발하 는 개발 조직과 운영해 가는 운영조직간의 매끄러운 협업이 필요합니다.
  40. 43 앱(APP) 중심으로 생각하기 DevOps와 자동화 개발과 운영 조직 <Wall

    of Confusion, from http://dev2ops.org/blog/2010/2/22/what-is-devops.html> 잦은, 반복적인 배포를 하기 위해서는 개발과 운영의 협업이 매우 중요합니다. 개발자는 새로운 기술을 소프트웨어에 적용해서 개발하고, 실험하고, 배포하길 원합 니다. 반면, 운영자는 잘해야 본전이므로, 서비스는 절대 멈추어서는 안되기 때문에 서비스의 안정성에 우선하여 보수적인 입장에서 접근하게 되는 서로간의 장벽이 존재 합니다. 물론, 각자의 역할을 충실히 임하고 있으니, 어느 누가 잘못된 것은 아닙니다. 규모가 아주 큰 금융이나 통신 SI 프로젝트 인 경우 배포해야 할 시스템도 많고, 개발 할 요구사항 목록도 적게는 수백에서 수천 라인을 넘어가는 프로젝트에서는 개발자와 운영자는 각자의 명확한 역할 분담과 함께 책임이 주어져야 합니다. 그러나, 잦은 배 포를 하는 인터넷 서비스와 모바일 서비스를 하는 조직에서도 한정된 리소스 내에서 위와 같이 각자의 역할을 분담해서 개발자는 개발만, QA 조직에서는 테스트만, 운영 조직에서는 운영에만 한정되도록 역할을 분담하여 서비스를 운영한다면, 조직간의 시 너지를 얻을 수 없고 자원 낭비와 품질에 문제를 가져올 수 밖에 없습니다. 운영자는 서비스하는 어플리케이션에 대한 아키텍처와 데이터저장소, 프레임웍, 프로 세스에 대한 이해를 가져야 하고, 개발자 또한 어플리케이션이 돌아가고 있는 서버와 클라우드 환경에 대해서 이해를 하고 있어야 합니다. 그럼, 이 글의 처음에 소개된 3개의 인터넷 서비스 중 Flicker에서는 어떻게 두 조직을 융합하고 있는지 예를 들어 보도록 하겠습니다.
  41. 44 H3 개발자 컨퍼런스 2012 운영자 처럼 생각하는 개발자, 개발자

    처럼 생각하는 운영자 개발자와 운영자는 서로 존중하며, 신뢰해야 합니다. 다른 사람들의 전문성과 의견, 책임을 인정해야 합니다. 운영자는 새로운 기능에 있어서, 개발자를 믿어줘야 하고, 개발자는 운영자가 제안하 는 인프라의 변화를 믿어줘야 합니다. 서로 숨기지 말고 투명해야 합니다. 개발자는 자신의 코드가 어떠한 영향을 주는지 알려야 하고, 운영자는 개발자에게 시 스템에 들어갈 방법을 제공해야 합니다. 장애닷! 아악!! fixed time 놀라기, 묵비권, 잘못 찾기 비난하기, 내 살길 찾기 낑낑 숨기, 자아보호 문제 파악하기 장 애 수 정 복 구 손가락질 프로세스 그리고, 서로에게 손가락질을 금지해야 합니다. 서로를 비난하고, 시작부터 손가락질 하기 시작하면 다음의 “손가락질 프로세스”와 같이 숨기기에 급급하여 가장 먼저 해야 할 문제 파악이 뒤쳐지게 됩니다. 장애닷! 아악!! time 문제 파악하기 죄책감 느끼기 새 삶 살아가기 장 애 수 정 복 구 fixed 생산적인 프로세스
  42. 45 앱(APP) 중심으로 생각하기 DevOps와 자동화 반면 다음의 “생산적인 프로세스”에서는

    가장 먼저 문제부터 파악하고, 신속히 장애를 수습하여 정상적인 서비스와 정상적인 삶으로 복귀할 수 있습니다. 개발, 품질관리, 운영의 교집합 <개발, 품질관리, 운영의 교집합, from http://en.wikipedia.org/wiki/DevOps#Devops_Days> DevOps는 신뢰성, 보안성 그리고 개발과 배포 사이클을 더 빠르게 개선하기 위해 배 포, 테스트, 세부기능 개발, 릴리즈 관리를 목표로 합니다. 이러한 면에서 개발, 품질관리, 운영의 교집합이 되는 부분에 위치한다고 볼 수 있습 니다. 실무에 적용하기 – KTH에서의 사례 저희 KTH에서 DevOps팀을 만들게 된 동기는 스마트 모바일로 회사의 나아갈 방향 을 정한 후 아임인, 푸딩카메라, 푸딩얼굴인식, 114 전국전화, 아임리얼맛집에 이은 푸딩.투 등에 이르기까지 많은 종류의 모바일 서비스를 내 놓다 보니, 어쩔 수 없이 버 그픽스와 이벤트, 메이저 업데이트 등으로 인하여 개발하면서 서비스에 배포해야 하 는 상황에 직면하면서 부터입니다. 앞에서 언급한 “잦은 배포”를 잘 하기 위해서 뒷받 침 되어야 할 것이 있는데, 자동화가 최 우선이라 할 수 있습니다. 서비스의 배포를 자 주 하기 위해서는 개발자와 운영자의 수작업만으로는 해결할 수 없습니다. 물론 매번 한번에 몇시간~몇일 이상 몇십~몇백대의 서버에 배포하고, 테스트 하는 반복작업을 담당 개발자가 답답해 하지 않는다면 그렇게 할 수도 있지만, 실수도 있을 수 있으며, 작업자 마다 순서와 품질이 다를 수 있습니다. 몇시간이나 걸리는 작업을 자동화 해서 짧게, 버튼 클릭만으로 할 수 있다면 그 줄인 시간을 좀 더 생산적으로 활용할 수 있
  43. 46 H3 개발자 컨퍼런스 2012 고, 개발자는 운영에 투입되는 시간을

    창조적인 개발에 더 많이 투자할 수 있게 되는 것입니다. 자동화 이전 자동화 이후 이슈 관리 메일, 메신저, 전화 Jira 티켓으로 통합 소스 + 이슈 관리 별도 관리 Jira 티켓으로 통합 소스 빌드 로컬빌드 시스템 빌드 테스트 케이스 별 직접 테스트 빌드 후 자동 테스트 서버 배포 파일 복사, 직접 재 기동 시스템 배포, 자동 재 기동 앱 배포 파일 복사 빌드 후 자동 배포 빌드 후 모니터링 직접 모니터링 배포 후 자동 모니터링 서버 설정 정해진 룰에 의해 직접 설치 및 설정 자동 설치, 설정 VM 인스턴스 생성 콘솔에서 직접 생성 설정 툴에서 자동 생성 서비스에서의 자동화 전 후 위 자동화를 하기 위해 DevOps 팀에서는 다음의 로드맵으로 진행하고 있습니다. DevOps 로드맵 그럼 KTH는 어떠한 로드맵을 가지고 DevOps를 적용하고 있는지 보도록 하겠습니다. 마일스톤 사용 소프트웨어 1. 이슈 통합 JIRA 2. 계정 통합 Active Directory 3. 소스활용 효율성 확보 GitLabHQ, Gitblit, GitHub 4. 빌드통합 및 사내배포 자동화 Jenkins, 자체 개발
  44. 47 마일스톤 사용 소프트웨어 5. 테스트 자동화 Junit, SoapUI 등

    6. 시스템 설정 자동화 Chef, 자체 개발 7. 모니터링 자동화 자체 개발 8. 배포 자동화 자체 개발 마일스톤 별 사용 소프트웨어 위 마일스톤 중 1.이슈 통합, 2.계정 통합, 3.소스 활용 효율성 확보, 4.빌드 통합 및 자동화에 대해서 기술하도록 하겠습니다. 이슈 통합 하기 서비스를 기획하고 서비스에 대한 아이디어를 두루 수집하여 개발사항을 정리, 그에 따른 설계와 시나리오 작성, 개발 및 빌드, 테스트, 배포, 패치, 새로운 버전 개발의 사 이클을 효과적으로 순환하기 위해서는 모든 단계에서 발생하는 이슈와, 그 이슈에 해 당되는 개발사항, 빌드, 배포, 모니터링 등 모든 활동이 추적이 가능 해야 하며, 한곳 으로 레포트가 통합되어야 합니다. 마침 KTH는 프로젝트지원 팀에서 이미 많은 개발 소프트웨어들이 지원하는 JIRA 시스템을 훌륭하게 도입하고 사용법을 전파하여 구성 원들이 JIRA 사용에 익숙해져 가고 있어, JIRA를 중심으로 이슈를 관리하기로 하고, 다음과 같은 밑그림으로 진행하고 있습니다. 이슈 추적 싸이클의 밑그림
  45. 48 H3 개발자 컨퍼런스 2012 이슈 추적 싸이클의 각 단계는

    다음과 같습니다. ➊ 요구사항, 아이디어, 버그, 개선사항 등을 JIRA에 티켓으로 등록합니다. ➋ 개발 PM은 해당 티켓을 검토하고, 수용여부를 판단 한 뒤 개발자를 할당합니다. ➌ 개발자는 작업할 티켓을 오픈하고 ➍  코드를 수정, 커밋, push 합니다. 이때, 커밋 메시지에는 티켓번호를 입력하여 추적할 수 있도 록 합니다. 이 단계를 거치면, 코드 변경내역이 해당 티켓의 활동내역에 푸시 되며, 관련자에 게 메일로 알려줍니다. ➎  코드가 변경이 되면, Jenkins 빌드 시스템이 빌드 후 Unit/기능 테스트 수행, 코드 분석을 수행 합니다. ➏  위 결과를 JIRA 티켓의 comment를 등록합니다. 이 역시, 즉시 이메일로 관련자에게 알려줍니 다. ➐  배포 시스템에서는 서비스 서버에 새로운 릴리즈를 배포하고, 대상 시스템을 테스트 합니다. ➑ 새로운 릴리즈를 배포, 테스트 한 결과를 해당 티켓의 comment로 등록합니다. ➒ 최초 티켓을 발행한 오너는 처리 상태를 확인하고, ➓ 처리 상태에 따라 티켓을 종료하거나, 재 오픈하여 한 싸이클이 종료됩니다.
  46. 49 앱(APP) 중심으로 생각하기 DevOps와 자동화 JIRA 티켓으로 통합된 소스코드

    체인지셋, 빌드결과 계정 통합하기 예전에는 개발실 내에 개발과 관련한 시스템을 많이 보유하고 있고, 각 시스템들은 다 음과 같이 각기 관리되고 있습니다. 각 시스템 별로 별도 관리되는 계정 이렇게 되면 개발자가 입사하거나 퇴사하게 되면, 일일이 추가/삭제를 해야 하므로 누 락되는 경우도 있고, 이 관리를 위해 소중한 시간을 허비하게 되고, 개발자도 사람인 지라 패스워드를 잃어먹고 리셋 해야 하는 불편함이 있습니다. Active Directory 계정 연동
  47. 50 H3 개발자 컨퍼런스 2012 이를 개선하기 위해 회사의 Directory

    서비스인 Active Directory 서버와 LDAP 프로 토콜로 연동하여, 별도의 계정을 따로 생성/추가 하지 않고, 간단한 권한만 부여하면 되므로 개발자도 기다리는 시간이 없이 회사의 모든 개발 리소스에 접근할 수 있게 되 었습니다. 물론 관리를 해야 하는 DevOps 팀에서도 계정에 대해서는 관리대상에서 제외할 수 있게 되었습니다. GitHub은 앱스프레소와 같은 오픈 소스 프로젝트를 위한 저장소로, 외부의 git 호스팅 서비스이므로 LDAP 연동이 되지 않아 이메일로 부득이하게 별도 관리함. 기본 저장 소는 내부의 git을 사용함. 소스 활용 효율성 확보 (SCM, Source Code Management) 기존에는 파란 서비스 소스를 포함하여 회사의 기본 소스코드 관리 시스템으로 SVN 을 사용하고 있었습니다. 기본적인 팀 코딩을 위한 용도로는 SVN 만으로도 충분하지 만, 이미 개발된 좋은 소스코드를 같이 나누고 개선해 나가고, 이미 개발된 모듈들을 검색해서 재활용하기에는 부족함이 있어 새로운 코드 관리 시스템이 필요했습니다. Subversion (http + svn) Git (gitlab, gitblit) 홈페이지 http://subversion.apache.org/ http://git-scm.com/ 버전 1.7.6 (2012-08-15) 1.7.12 (2012-08-20) 관리 형태 집중 관리 SVN Server에 집중 분산관리 n개의 로컬, n 리모트 서버 커밋 조건 Online Offline 키워드 Revision control Hash, Distributed, Stash, branch 명령어 비교 svn checkout svn add svn commit svn status git clone git add git commit, git push git stash git stage git checkout Since 2000, Clooabnet, Inc. 2005, Linus Torvalds 등 SVN과 Git 비교
  48. 51 앱(APP) 중심으로 생각하기 DevOps와 자동화 Subversion (http + svn)

    Git (gitlab, gitblit) 인증된 유저에게 default read 권한 부여 X O 웹에서 코드 확인 △ (텍스트) O (코드 하이라이트) 웹에서 히스토리 확인 X O (diff 도 지원) 웹에서 소스 검색 X O (소스, 커밋, 브랜치, 작성자 등) Jenkins 연동 O O Jira 이슈와 연동 O (Fisheye 연동) O (DVCS Connector, Fisheye 연동) 저장소 권한 자율성 확보 SVN 관리 팀에 집중 프로젝트 오너에 이양 웹 Admin 지원 X O 필요한 기능 지원 여부 사내에 많은 프로젝트들이 있고, Facebook, twitter, KPNS 등 많은 서비스들과 연동 하는 모듈들이 있어, 그것들을 쉽게 찾아 재 사용할 수 있으며, 서버에 터미널로 직접 접속하지 않고, 웹에서 쉽게 관리할 수 있는 솔루션이 필요했습니다. 오픈 소스에서 가장 많이 사용하고 수많은 기업 사용자를 확보한 GitHub 이 있습니 다. 아름다운 web ui로 아주 좋은 솔루션이긴 하지만 사내 Directory 시스템과 연동 이 되지 않아 다른 솔루션을 찾게 되었습니다. default로 모든 프로젝트에 read 권한 을 줄 수 있는 기능은 없지만, 그것은 개발하기로 하고, GitHub 유사한 기능을 제공하 면서 Directory 시스템과 연동이 되는 Gitlab를 도입하였습니다. Gitlab 이 좋은 툴이 긴 하지만 도입 시 고민을 할 수 밖에 없었던 이유인 “인증된 유저는 모든 소스에 쉽게 접근할 수 있어야 한다. 즉, 구성원 모두에게 default read 권한이 부여되어야 한다”는 조건을 만족하기 위해 도입 직후 해당 기능 개발을 진행했습니다. gitlab을 직접 수정 할 수도 있지만, 버전업이 잦은 gitlab의 특성상 버전업 때마다 수정된 버전을 머지해 야 하는 반복되는 수작업이 발생하기 때문에 배치 프로세스를 만들기로 하였습니다. 다행스럽게도 https://gist.github.com/1722391에 이러한 기능을 하는 shell 이 있 었지만, 우리것과 버전이 맞지 않아 gitlab 2.5버전 이상 지원, database에서 프로젝 트 리스트를 조회하여 프로젝트 리스트를 정확히 설정하는 것으로 다시 개발하게 되 었습니다. 사용 초기엔 10분 주기로 하였다가, 프로젝트와 유저가 늘어날수록 소요되 는 시간도 증가하여 100 이상의 유저와 프로젝트를 사용 중인 현재 2시간 주기로 수 행하고 있습니다. 이 배치프로세스의 소스는 https://gist.github.com/2786818에 공개되어 있습니다.
  49. 52 H3 개발자 컨퍼런스 2012 add_users_to_projects.sh #!/bin/sh ############################### ## baseurl=YOUR_GITLAB_URL

    logdir=YOUR_LOG_DIRECTORY basedir=YOUR_BASE_DIRECTORY usermail=YOUR_ADMIN_MAIL userpass=YOUR_ADMIN_PASSWORD project_access=20 #00=deined 10=read 20=report 30=admin ## SIMPLE LOGGER ## $logdir default => /var/log ## logfile path & name : $logdir/2012-XX-XX.log ## log type : [16:00:36]loggingtest function logger(){ user=`whoami` filename=`date +%Y-%m-%d` filename=$filename.log if [ ! $logdir ]; then logdir=/var/log fi if [ ! -d $logdir ]; then mkdir -p $logdir && chown -R $user $logdir fi if [ "$1" ]; then now=`date +%T` echo [$now]$1 >> $logdir/$filename fi } ## Is there excuted process? if [ -e $basedir/cookies.txt ] then logger "There is running script : add_users_to_projects" exit fi start=`date +%s` logger "=====================================================================" logger "adding user process start" #get login page's authtoken authtoken=`curl -s -c $basedir/cookies.txt $baseurl/users/sign_in | grep -Po '(?<=<meta content=")([^"]+)(?=" name="csrf-token" />)'` logger "Login page's auth token & cookies acquired : $authtoken"
  50. 53 앱(APP) 중심으로 생각하기 DevOps와 자동화 # login authtoken=${authtoken//+/%2b} #when

    csrf token includes '+' character, authenti- cation is failed, it must be URI encoded curl -s -b $basedir/cookies.txt -c $basedir/cookies.txt -d "utf8=%E2%9C%93&au- thenticity_token=$authtoken&user[email]=$usermail&user[password]=$userpass&com- mit=Sign+in" $baseurl/users/sign_in logger "Login completed " #get projects list projectslist=`mysql -ugitlab -pYOUR_GITLAB_DB_ACCOUNT -h YOUR_DB_HOST < $basedir/select_projects.sql` projectscount=`echo "$projectslist" | wc -l` let "projectscount-=1" #remove column name logger "Gitlab project count : $projectscount" #adding users loop for project in $projectslist do if [ "$project" != "name" ]; #database column name pass then logger "Project name : $project" # get admin project pages and store it to project_page.html curl -i -s -b $basedir/cookies.txt $baseurl/admin/projects/$project > $basedir/project_page.html # parse user_ids userIdsStr=`grep -Po '(<select id="user_ids")([^\}]+)(<select)' $basedir/ project_page.html | grep -Po '(?<=option value=")\d+(?=">)'|tr '\n' ','|sed 's/,/\&user_ids\[\]=/g'` userIdsLog=`grep -Po '(<select id="user_ids")([^\}]+)(<select)' $basedir/ project_page.html | grep -Po '(?<=option value=")\d+(?=">)'|tr '\n' ','` if [ ${#userIdsLog} = 0 ]; then logger "Added user Ids : no new users" else postdata="utf8=%E2%9C%93&_method=put&authenticity_token=$authtoken&user_ ids[]=$userIdsStr&project_access=$project_access&commit=Add" echo curl -s -b $basedir/cookies.txt -d $postdata $baseurl/admin/proj- ects/$project/team_update logger "Added user Ids : $userIdsLog" fi fi done end=`date +%s` let "end-=$start" logger "elapsed time : $end"
  51. 54 H3 개발자 컨퍼런스 2012 logger "batch ended" rm -f

    $basedir/cookies.txt $basedir/project_page.html # remove temp files exit select_projects.sql use gitlab; select path from projects; gitlab은 50인 이하의 개발자 있는 규모의 회사나 개발 그룹에는 큰 불편함이 없지만, 그 이상의 규모에서는 ssh key를 입력할 때, 약 15초 후 다음의 붉은색 오류 화면을 자주 보게 됩니다. Gitlab SSH Key 입력 화면 Gitlab SSH Key 입력 시 오류
  52. 55 앱(APP) 중심으로 생각하기 DevOps와 자동화 이러한 현상은 키관련 작업시

    gitlab 이 직접 하는 것이 아니라 gitolite에 키 입력을 요 구하는데, gitolite는 유저가 권한을 보유하고 있는 모든 프로젝트에 대해서 일일이 키 를 입력하는 작업이 수행되므로, 프로젝트가 100개 있다고 하면, gitolite-admin.git 을 clone 한 후, conf/gitolite.conf 파일을 100번 open-write-close 하는 작업을 반 복하고, 입력작업이 끝난 후 gitolite-admin.git에 다시 push 하는데, 이 작업을 기다 리는 시간이 오래 걸려 성공하거나, 오류가 발생하게 됩니다. SSH Key 입력 시 gitlab에서 gitolite-admin clone -> push 하는 로그 remote: Counting objects: 41512, done. remote: Compressing objects: 100% (21036/21036), done. remote: Total 41512 (delta 10758), reused 40170 (delta 10407) Receiving objects: 100% (41512/41512), 3.86 MiB | 7.55 MiB/s, done. Resolving deltas: 100% (10758/10758), done. Counting objects: 10, done. Delta compression using up to 4 threads. Compressing objects: 100% (5/5), done. Writing objects: 100% (6/6), 1.14 KiB, done. Total 6 (delta 2), reused 0 (delta 0) remote: creating git_ssh_test... remote: Initialized empty Git repository in /data2/git/repositories/git_ssh_ test.git/ remote: remote: ***** WARNING ***** remote: You have 37 pubkeys that do not appear to be used in the config remote: remote: ***** WARNING ***** remote: You have 12 users WITHOUT pubkeys...! To git@localhost:gitolite-admin 1695517..55ea212 master -> master SSH Key를 입력한 후 위와 같은 오류가 발생했을 때, git clone/push 등 git client로 하는 작업은 문제없이 할 수 있는 경우가 대부분이지만, Gitlab의 웹UI에서는 키 리스 트가 나오지 않아, 키가 관리되지 않아 향후 접근 제어에 큰 구멍이 발생할 수 있습니 다. 웹 UI에서 리스트가 나오게 하고 관리가 되도록 하기 위해서는 database에 직접 key의 정보를 입력해 주어야 합니다. users 테이블에서 유저의 ID 확인 >select id, email from users where email like 'imdevops%';
  53. 56 H3 개발자 컨퍼런스 2012 +----+-----------------------+ | id | email

    | +----+-----------------------+ | 39 | [email protected] | +----+-----------------------+ keys 테이블에 키 입력하기 insert into `keys` ( user_id, created_at, updated_at, `key`, title, identifier ) values ( 39, now(), now(), 'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAnFEdCaK6J2GRSorBiWpaNevVK/9F1IsGRC/yDEr- rdMqGzrQoOnEd6OKiwdx70I/fepc0LxRGqbkfyEup1wkL1iazJnxFrMDJJdmbDItjqVrHkXc1qKgSQ- DYfwJ/YDQrLuE3++6TnqcLrX9toj/KdFQ2B2S33pra5ppFj4BKrSYvh2e6XRTAtxxutsLgcmryILm- od4vH3GP9vU5zBKfgj+r22SsiANMqtPAxLlllUPsFbHCKYPbBgEwkAK0vFSktwFdXFMLNPIKU2qINV/ YZQ6lBCIS0Jzl+VvChoiiGknv4NAISoDCIg+uaxhk7YjLM0mHdFp8v9BFHUFNa4SwI8IQ== user2@ i-5453-33039-VM', '[email protected]', 'imdevops_kthcorp_com_1344499222.pub' ); 이와 같이 git 사용의 필수적인 인증 요소인 SSH Key 관련 잦은 오류와, 소스 검색이 되지 않는다는 결정적인 이유로 다른 솔루션들을 찾고 있던 중, 때마침 1.0.0 정식버 전에서 LDAP 연동을 지원하기 시작한 Gitblit을 발견하여 도입하였습니다. 다행히도 동일한 git 저장소 디렉토리를 지정하고 사용하여도 문제가 발생하지 않아, Gitlab에서 Gitblit으로 마이그레이션 시 별도의 추가 작업이 필요 없습니다. Gitlab Gitblit 홈페이지 http://gitlabhq.com/ http://gitblit.com/ 버전 2.8 (2012-08-25) 1.1.0 (2012-08-25) Git 프로토콜 SSH, SmartHTTP (LDAP 연동시 오류 발생) SmartHTTP(s)
  54. 57 앱(APP) 중심으로 생각하기 DevOps와 자동화 Gitlab Gitblit Git 인증

    RSA key HTTP Basic Authentication 개발언어 Ruby(1.9.2 이상) on Rails Java 1.6 이상 미들웨어 Git core, Gitolite JGit 데이터베이스 mysql, sqlite 중 선택 (유저, 권한, 키, 리파지토리 정보 등) 파일 사용 리파지토리 설정 Database에 저장 git 디렉토리의 config 파일 확장 백 업 X O (federation) 소스 단위 검색 X (프로젝트명, 프로젝트 설명) O (소스, 커밋, 브랜치, 작성자 등) 프로젝트 그룹 X O 팀 X O 인증된 유저에게 default read 권한 부여 X O 한글화 X O UI의 편의성 O (github clone) △ Gitlab과 Gitblit 비교 Gitlab 메인 화면
  55. 58 H3 개발자 컨퍼런스 2012 Gitblit 메인 화면 Gitblit :

    *.java 파일에서 ds5apn 검색어 검색한 결과 화면
  56. 59 앱(APP) 중심으로 생각하기 DevOps와 자동화 빌드 통합 및 사내

    배포 자동화 사내에는 Android, iOS와 같은 모바일 플랫폼, Java, C, PHP, Ruby, Python과 같은 서버 플랫폼으로 개발이 진행되고 있습니다. 프로젝트 당 개발자도 적게는 1명, 많게 는 10명까지 협업이 이루어지고, 소스는 한 곳으로 통합되어 집니다. 소스가 한곳에 있으니 통합해서 빌드 할 수 있는 환경이 준비되었습니다. 위와 같은 개발 언어를 지 원하고, 많은 플러그인들을 지원하는 Jenkins를 선택하여 CentOS 서버에 구축하고, 프로젝트들을 빌드하도록 하였습니다. 하지만, iOS 용 프로젝트는 Linux에서 빌드를 할 수 없기에 Mac server를 node로 링크하여 iOS와 Android 프로젝트를 빌드합니다. 빌드와 사내 배포 흐름 Jenkins는 빌드 후 shell 실행을 통하여 여러 추가 동작을 수행할 수 있습니다. 다음 Job 설명의 일부분은 gitblit을 KTH 내부 목적에 맞도록 커스트마이징 한 소스를 다음 의 단계로 타깃시스템에 배포하는 것을 보여줍니다. 빌드 후 타켓 시스템이 배포하는 단계
  57. 60 H3 개발자 컨퍼런스 2012 빌드 후 배포하는 Job의 스크립트

    부분 서버 뿐만 아니라 모바일 앱도 내부 기획자/개발자/QC 담당자들이 다운받아 테스트 하기 위해서는 내부의 앱 배포시스템이 있어야 합니다. 매번 따로 빌드하고 필요한 사 람에게 메일로 전달할 수 없기 때문에 모바일 플랫폼 전용의 배포 시스템이 필요합니 다. 이미, iOS와 Android 팀에서는 각자의 배포 시스템을 개발하여 사용하고 있었으 나, 빌드를 통합하면서 사내 앱 배포시스템도 통합하여 활용하고 있습니다. 사내 앱 배포시스템의 일부분
  58. 61 앱(APP) 중심으로 생각하기 DevOps와 자동화 그리고. 테스트도 자동화해야 하며,

    스테이지 서버까지 테스트에서 이상이 없었다면 실 서비 스 서버에 배포 할 수 있는 시스템이 있어야 하고, 배포 시스템과 연동되는 모니터링 시스템이 있어, 신 버전이 배포된 시스템만 테스트하여 정상유무를 판단할 수 있어야 합니다. 물론 배포 결과와 모니터링 결과는 JIRA의 이슈티켓에 레포팅해야 합니다. 그 리고, 새로운 서비스가 있어 시스템에 서버 스택별 소프트웨어를 설치해야 하거나, 증 설이 필요하여 기존과 동일한 환경으로 설정해야 할 경우 수작업으로 하지 않도록 자 동화 해야 합니다. 여기에 기술하지 않은 5.테스트자동화, 7.모니터링 자동화, 8.배포 자동화 단계는 완전한 Continuous Delivery를 구현하기 위해 한창 개발 진행 중입니 다. 그리고, 6. 시스템 설정 자동화는 이 책의 “Just Do IT, Chef 언제까지 손으로 일 일이 할텐가?”에서 자세히 다루고 있습니다. 마무리 하며 DevOps는 툴이 아니라 사업적인 목표를 개발과 운영 조직이 서로 협업하여 같은 목 표로 나아갈 수 있도록 하는 문화이고 일하는 방식입니다. DevOps를 실행하는데 도 움을 줄 수 있는 수많은 소프트웨어를 도입하더라도 구성원들이 새로운 방식에 적응 하지 않고 거부할 수도 있습니다. 조급하게 생각하지 말고 꾸준히 조금씩 변화를 주 어야 합니다. 첫술에 배 부를 수 없습니다. 하지만 시작이 반이니 처음의 추진 의지를 잃지 않고 계속해서 나아간다면 개발자가 일하기 좋은 환경을 만들 수 있음을 확신합 니다.
  59. 62 H3 개발자 컨퍼런스 2012 Chef를 이용하면 Infrastructure AS Code가

    가능하게 됩니다. Infrastructure가 더 이 상 서비스에게 있어서 어떤 컨트롤 불가능한 변수로써 취급되는 것이 아니라, Code로 눈에 보이고 코딩할 수 있는 것으로 바라보게 되는 것입니다. Class를 사용할 수 있는 형태로 실제 구현되는 것을 인스턴스화라고 부릅니다. 자 Chef을 이용해서 Infra를 코 딩하고 인스턴스화 해보시지 않으시겠습니까? Chef는 2009년 1월에 Opscode가 오픈 소스로 내놓은 3살짜리 Systems Integration Framework입니다. 한마디로 서버 설정 자동화 툴입니다. DevOps한다면 반드시 한 번은 들어봤을 만큼 유명한 툴입니다. DevOpsDays MountainView 2012에서 Chef 를 개발하고 있는 회사인 Opscode의 담당자가 1분간 홍보할 시간이 주어지자 말했 습니다. “ Never Heard of Chef? Why are you even here? We are The Chef!! ” Just Do IT, Chef! DEVOPS팀 김성식 [email protected]
  60. 63 Just Do IT, Chef! 실은 Puppet이라는 Chef보다 4년이나 앞서

    등장한 설정 자동화 툴이 있었습니다. Chef 제작자 본인인 Adam Jacob도 Puppet의 Serious User였습니다. Puppet을 사 용하면서 불편했던 점들을 보완하기 위해 시작한 Project가 바로 Chef였습니다. 오픈 소스의 파워는 바로 그 커뮤니티에 달려 있다고 할 수 있는데, 현재 Chef의 커뮤니티 는 급속도로 성장하고 있습니다. 현재 약 580여개의 opscode공식 cookbook이 등록 되어 있고, 1180여명의 멤버가 활동 중입니다. 특히 Github Repository는 puppet을 앞서 있습니다. 2012년 8월 30일 현재 Github.com Repository Puppet : 3266 repositories Chef : 5995 repositories Chef와 Puppet은 모두 Ruby로 작성되었습니다. Chef는 Cookbook, Puppet은 Module이라는 DSL(Domain Server Language)를 작성하여 서버를 어떻게 설정할 지 정의하게 됩니다. Chef는 DSL로 Cookbook이라는 개념을 사용하고 있습니다. Cookbook은 기본적으로 Ruby파일이기 때문에 Ruby문법을 바로 사용할 수 있습니 다. loop문을 사용하고 싶다면, Ruby loop문을 쓰면 loop문이 실행됩니다. 그러나 puppet은 puppet만의 DSL문법이 존재하기 때문에 puppet만의 loop문을 작성해야 합니다. 실제로 두 시스템의 장단점을 따지려면 세션 하나를 다 하고도 모자를 수 있 습니다. 일단 이번 세션에서는 더 깊게 들어가는 것은 미뤄두도록 하겠습니다. Chef가 이렇게 큰 힘을 얻고 있는 것은 바로 AWS를 선두로 한 Cloud라는 새로운 Infrastructure의 등장이 그 배경을 드리우고 있습니다. Chef와 Cloud의 만남은 굉장 히 매력적인 조합입니다. Auto Scaling: AWS를 비롯한 대부분의 퍼블릭 클라우드 벤더들이 지원하지만, 단순히 기존 EC2의 스냅샷을 인 스턴스화 해주는 수준입니다. 좀 더 섬세한 컨트롤이 필요한 당신에게 필요한 건, Chef의 Smart한 AutoScaling. Automation: 웹서버 500대의 Tomcat를 재 시작 하려고 합니다. 일일이 들어가서 재시작 시키시겠습니까? DevOpsDays에서 들은 이야기가 또 떠오르네요. “ If you wanna do same thing again and again and again, then.. It’s your life. ”
  61. 64 H3 개발자 컨퍼런스 2012 현재 KTH에서는 uCloud환경에서 Chef를 본격적으로

    테스트 중이며, Chef의 client 측 웹UI를 개발 중입니다. 9월중으로 웹에서 버튼 클릭 한번으로 cloud에서 VM를 생 성하고 원하는 서비스를 설치한 후 개발자에게 넘겨주는 일련의 과정을 논스톱으로 자동화 해주는 시스템을 베타로 선보일 예정입니다. 이 과정을 테스트한 동영상을 확 인해보세요. [http://j.mp/UCloudChef ] Chef로 할 수 있는 일 Provisioning 간단히 설명하면 서버를 만들어 낼 수 있습니다. 이것은 VM환경이기 때문에 가능한 것인데요, 우선 기본적으로 libvirt와 hypervisor(XEN, KVM, VMware)의 API를 직접 호출해서 VM을 생성해 낼 수 있습니다. cloud환경이라면 cloud의 API를 호출하여 원 하는 인스턴스를 생성하는 것입니다. uCloud의 경우는 ClousStack을 모체로 하고 있 어, ucloud에 맞도록 수정한 CloudStack의 플러그인을 Chef에 추가해 줌으로써 간 단하게 Provisioning이 가능했습니다. Configuration Management Chef는 서버에 Application들을 설치해주고 필요한 설정들을 해줄 수 있습니다. 앞에 서도 언급했듯이, Chef는 Cookbook이라는 Ruby DSL 파일을 작성하면서 서버 설
  62. 65 Just Do IT, Chef! 정을 정의하게됩니다. (실제로 recipe는 정의들의

    나열처럼 보입니다.) Cookbook은 recipe와 다른 컴포넌트로 구성되는데, Chef의 사용자라고 하면 이 recipe를 작성하 는데 대부분의 시간을 보내게 됩니다. 그러나 Ruby를 잘 모른다고 하더라도 크게 문 제되지 않습니다. 왜냐면 Ruby문법을 이용해서 DSL 파일을 작성하는 것이지, Ruby 프로그래밍을 하는 것이 아니기 때문입니다. Systems Integration 이 기능은 Puppet이 가지지 못한 기능 중에 하나이며, Automated Infrastructure 완 성의 마지막 한걸음이라고 볼 수 있습니다. Chef는 설정 로직과 설정 데이터를 분리하 여 관리할 수 있습니다. 설정 데이터란 서버를 설정할 때 동적으로 변경되는 데이터들 을 의미하는데 예를 들어 Provisioning을 통해서 uCloud에서 서버를 하나 받습니다. 이때 해당 서버의 Private IP가 할당되는데 이를 Chef의 DataBag이라는 기능을 이용 하여 저장해 놓습니다. 이렇게 새로 생성된 서버에 MySQL Master를 설치하고, 필요 한 데이터들을 덤프해 넣습니다. 그 다음 서버를 한대 더 받아서 MySQL Slave를 설 치합니다. 이때 미리 DataBag에 저장해놓은 Master의 IP로 설정 파일에 써넣어주고 리플리케이션을 구성해주면 바로 DataBase 인프라가 완성되는 것입니다. DataBag 은 내부적으로 CouchDB라는 NoSQL DB로 구현되어 있으며 강력한 검색 쿼리를 지 원하기 때문에 손쉽게 데이터를 검색해서 사용할 수 있습니다. 이런 작업들을 Recipe 에 정의 해두는 것만으로 자동화된 인프라가 완성되는 것입니다.
  63. 66 H3 개발자 컨퍼런스 2012 요약하면, Cloud에서 서버를 할당 받고,

    원하는 Application을 설치하고 이 서버들을 서로 연결해주는 것입니다. Chef의 좌우명 Thick Client, Thin Server Chef는 일단 Server – Client Architecture를 가지고 있습니다. 그러나 대부분의 작업은 최대 한 Client측에서 하도록 되어있고, 서버의 기능 은 최소한으로 줄였습니다. 서버는 단순히 설정 데이터들을 저장, 검색해주고, 타깃 노들에 다 운로드 해줄 파일들을 보관해줍니다. 간단히 말 해서 저장소로 격하시켰습니다. 이런 방식으로 중앙 집중식이 아니라 여기저기 분산 시킬 수 있게 되는 것입니다. Order Matters 너무나 당연한 이야기이지만 서버를 설정할 때, 순서가 중요합니다. Chef는 이 순서에 별 신경 을 쓰지 않아도 되도록 해줍니다. 기본적으로 Chef가 서버를 설정한다 함은, 타깃 Node에 Recipe들의 리스트를 실행 시키는 것을 의미합 니다. 이때 Recipe들의 리스트를 Run List라고 부릅니다. 그런데 Recipe는 다른 Recipe에 의 존성이 있을 가질 수 있습니다. 이런 경우, Chef는 알아서 의존되고 있는 Recipe들을 불려 들여와 Run List 앞쪽에 놓아 줍니다. 그리고 같은 Recipe가 중복되어 Run List 에 들어가게 되면 상대적으로 뒤쪽에 있는 Recipe는 실행되지 않습니다. 결국 우리는 좀 더 간단하게 생각하면 됩니다. “내 Ruby On Rails 어플리케이션을 스타트 시키기 전에 Nginx가 먼저 설치되어야 해.” 이런 식의 걱정만 하면 되는 것입니다.
  64. 67 Just Do IT, Chef! Reasonability Chef는 사용자가 자신의 인프라를

    서로 어떻게 연결해야 하는지 가장 잘 안다고 생각 합니다. 따라서 Chef가 자동으로 해주는 부분을 최소로 줄여 놓았습니다. 만약 자동으 로 되더라도 언제나 변경할 수 있게 되어 있습니다. 이 특징은 Chef를 배우기 좀 더 어 렵게 만드는 부분일 수 있겠습니다만, (좀 알아서 해주면 안되나?이런 생각이 들 때가 있습니다.) 이 특징을 보장하기 위해 Chef는 DSL로 ruby를 선택한 것입니다. 사용자 에게 자유도를 제공하기 위해서입니다. 이 특징이 다시 Puppet과 구별되는 것입니다. “ Puppet is a kind of Application easy to use. And Chef is a Library ” Chef가 이런 원칙을 고수하는 이유는 TMTOWTDI1이기 때문이랍니다. Chef Architecture 1 TMTOWTDI : There's more than one way to do it
  65. 68 H3 개발자 컨퍼런스 2012 여기서 말씀드릴 것은 위와 같은

    Chef를 구축할 때, 위 그림과 같은 Architecture를 가지지 않을 수도 있다는 사실입니다. 위 구조는 Chef Solo를 이용해서 더 간단한 Architecture를 구성할 수도 있지만, 그림의 구조가 가장 일반적인 형태입니다. Chef Server Chef Server는 기본적으로 Configuration Information을 저장하고 조회해주는 역할이 그 주요 기능입니다. REST API를 통해서 WorkStation이나 Node와 통신할 수 있고, WebUI를 제공해서 Web에서 바로 Configuration 정보를 조회 수정 삭제가 가능합니다. Simple Diagram For Chef Server
  66. 69 Just Do IT, Chef! Chef Client Chef Client는 약간의

    혼동을 주는 감이 있는 용어입니 다. 왜냐면 좌우명에서 잠깐 언급했듯이 Chef에서 하는 일의 거의 대부분이 Server가 아니라 Client에서 수행하 기 때문입니다. Chef Client가 Node에서 실행되면 Chef Client는 Chef Server에서 자신의 RunList와 Attribute, RunList를 실행시키는 방법이 구체적으로 적혀 있는 Cookbook의 Recipe들을 다 받아와서 실행 시킵니다. Chef Client는 일회성이 아니 라 데몬으로 일정한 주기와 랜덤 유격을 줘서 주기적으로 Chef Server에 접속해서 자 신의 RunList와 Attribute를 읽어와 변경 사항이 있을 때 반영하게 됩니다. Node Node는 간단히 Chef Client가 운영되고 있는 호스트 를 의미합니다. Chef는 Node를 추상화 시켜서 인식하 게 됩니다. 다시 말해서Attribute라고 하는 설정 값들과 RunList라고 하는 실행 목록을 구성된 객체(객체지향 언 어에서 말하는 그 객체)로 인식하는 것입니다. 객체는 멤 버변수와 메소드들을 가질 수 있습니다. Node도 그렇습 니다. Attribute라는 설정 값들을 담고 있는 멤버변수와 RunList, Recipe, Role등을 담고 있는 객체입니다. WorkStation WorkStation은 근본적으로 Node입니다. 그러나 단순한 Node는 아니고 특별한 능력 을 가지고 있습니다. 바로 칼을 쓸 줄 아는 녀석이라는 것입니다. Chef Server와 통신 할 수 있도록 설정된 Knife를 가지고 있어서 이를 통해서 Server API를 호출하여 로컬 에 repository에 있는 Cookbook과 같은 Configuration Information을 서버에 업로드 할 수 있습니다. 결국 Chef를 사용한다는 것은 이 WorkStation에서 작업하는 것을 의 미합니다.
  67. 70 H3 개발자 컨퍼런스 2012 Chef WorkFlow Run List RunList는

    Node의 todo리스트입니다. 가장 간단한 용례 는 Recipe들을 순서대로 RunList에 넣어서 만드는 방식 입니다. Chef의 좌우명에서도 언급했듯이 순서가 중요합 니다. 당연히 ruby를 설치하지 않고, ROR어플리케이션을 시작 시킬 수는 없을 겁니다. 그렇다면 이렇게 어떤 어플리 케이션을 설치하려고 할 때 의존성이 있는 다른 팩키지를 설치하는 Recipe들을 일일이 다 RunList에 등록 시켜줘야 할까요? 아닙니다! Nginx Cookbook의 Metadata에는 Nginx 설치에 필요한, 6개의 다른 cookbook들이 적혀 있습니다. Nginx recipe만 Run List에 등록해도 Nginx Cookbook의 Metadata에 의 존성 정보를 읽어와 7개의 Recipe들이 들어있는 RunList로 확장 시켜줍니다.
  68. 71 Just Do IT, Chef! Role Role은 특정 기능을 하는

    “역할”이라는 개념으로 묶어서 관리할 수 있는 기능입니다. 우리가 APM웹서버를 구축 한다고 가정할 때, 우선 기본적으로Apache를 설치한 다 음 PHP를 설치하고 MySQL Client를 설치해야 합니다. 이런 일련의 프로세스를 APM웹서버라는 Role로 정의 하여 관리하는 것입니다. 이렇게 APM웹서버가 한대 필 요하다면 타깃 Node에 APM웹서버라는 Role할당하는 방식으로 간단하게 웹서버 설 정을 끝낼 수 있습니다. Role은 RunList와 Attribute으로 구성되어 있습니다. 하나의 Node에는 여러 개의 Role을 설정할 수도 있습니다. Knife Knife는 Chef의 CLI(Command Line Interface)입니 다. 요리사가 요리하는데 사용하는 도구는 당연히 칼이 겠죠. Knife를 사용하기 위해서는 Chef Client가 설치되 어 있는 node중에 admin권한을 설정하면 됩니다. bash command line에서 각종 명령어를 입력해서 cookbook작성을 제외한 거의 모든 동작
  69. 72 H3 개발자 컨퍼런스 2012 을 실행 할 수 있습니다.

    게다가 명령어도 굉장히 직관적입니다. Knife의 더 강력한 기 능은 Ruby로 작성된 Plugin들입니다. gem으로 제공되는 Plugin을 그냥 설치하면 다 른 설정 없이 바로 사용할 수 있습니다. Attribute Attribute은 Node Data들 로 IP, 호스트명, 커널모 듈, 설치되어 있는 Java, PHP, Ruby, Python등의 버전 정보와 같은 데이터를 의미합니다. 특히 로그 디 렉토리나, Tomcat의 힙사 이즈등 보통 서버를 설정 할 때 정하는 설정들 Chef 를 이용하여 동적으로 변경할 수 있습니다. Chef Client가 최초 실행되면 이런 서버 의 정보들을 읽어 들여 Chef Server에 저장하게 됩니다. 그리고 몇몇 변경할 수 없는 Attribute(Automatic attributes- ex:Hardware specs)을 제외하고 실시간으로 변경 할 수 있습니다. Attribute을 이해하는 데에는 Type과 Precedence라는 개념이 필수 적입니다. Attribute은 크게 세가지 Type이 있습니다. Default, Normal, Overrides(, Automatic)입니다. 그리고 이 세가지 타입은 서로 우선순위를 가지고 있습니다. Overrides는 Normal과 Default을 덮어 씌울 수 있고, Normal은 Default를 덮어 씌울 수 있습니다. 네번째 Type으로 Automatic이 있지만 이 값들은 사용자가 수정할 수 없 는 Attributes입니다. 일반적으로 Hardware관련 정보입니다. 이 값들은 사용자가 지 정해도 Chef Client가 실행되면 Ohai2가 시스템 정보를 다시 읽어와 덮어씌워 버립 니다. 2  Ohai : Opscode에서 개발한 gem으로 시스템의 정보를 읽어들이는 기능을 해줍니다. 주로 Chef Server에게 Node 정보를 제공하는데 사용됩니다.
  70. 73 Just Do IT, Chef! Attribute의 Type은 선언되는 위치와 명시적으로

    Type을 정할 수도 있습니다. 그 러나 명시적으로 타입을 정하는 방식보다는 선언되는 위치로 Precedence를 관 리하는 것이 더 바람직합니다. 우선 Cookbook에서 Default Attribute을 지정하 고, Role에서 필요하다면 Default Attribute을 다시 설정합니다. 이때 Role의 Attri- bute이 Cookbook의 Attribute을 덮어 씌우게 됩니다. 그 이유는 Role이 Attribute “Specific”하기 때문입니다. 그리고 특정 Node에 더 Specific한 Attribute값이 있 다면 Node의 Normal Attribute으로 다시 덮어 씌어가는 방식으로 설정하면 됩니다. Chef의 Cookbook이란? Cookbook이라는 개념만 확실히 잡아도 Chef의 반은 이해 했다고 볼 수 있습니다. 그래서 좀 더 자세히 설명 드리도록 하겠습니다. Cookbook은 Recipe, Resource
  71. 74 H3 개발자 컨퍼런스 2012 Definition, Attribute, Template, Metadata등의 모음집입니다.

    일반적으로 하나의 패 키지나 서비스를 설정하도록 구성합니다. 예를 들어 MySQL Cookbook은 server와 client를 모두 포함하고, 이를 설정하기 위한 Attribute파일로 구성되어 있습니다. Recipe 기본적으로 Resource에 대한 정보들이 나열되어 있는 파일입니다. 그렇지만 그렇게 단순 하지만은 않습니다. Recipe에는 Ruby코드를 그대로 작성하여 chef가 실행 시키도록 할 수도 있습니다. 여기서 chef가 어떻게 동 작하는지 이해해 둘 필요가 있습니다. Chef는 Recipe 를 두 단계에 거쳐서 실행 시킵니다. 첫 번째 단계는 컴 파일단계로 일단 Recipe파일 전체를 읽어 들여와 이를 검사하고 Resource들의 리스 트를 작성하게 됩니다. 또 Rresource들이 필요로 하는 Provider들이 제대로 준비되어 있는지 확인하는 과정을 포함하고 있습니다. 두 번째 단계에서는 실제로 이 리스트를 참조해 실행 시키게 됩니다. 주의해야 할 점은 여기에 작성 해 놓은 Ruby코드는 실행 단계가 아니라 컴파일 단계에서 실행된다는 사실입니다. 만약에 실행단계에서 Ruby 코드를 실행 시키고 싶다면 Ruby_block이라는 Resource를 이용해 실행을 두 번째 단계로 지연 시킬 수 있습니다 Metadata Metadata는 말 그대로 정보를 설명하는 정보입니다. Chef에서 말하는 Metadata란 Cookbook의 의존성을 선언하는 기능을 주로 수행합니다.(정말 객체 지향 프 로그래밍 같습니다. – Infrastructure As Code) 예를 들면 Tomcat을 서비스에 올리려면 Java가 필요하므 로 Tomcat Cookbook은 Java Cookbook의 의존성 을 갖습니다. 이런 의존성에 관한 정보를 적어 놓는 곳이 바로 Metadata입니다. 의존 성을 적어두는 것이 Metadata의 표면적인 기능이지만 이 역할만 하는 것은 아닙니다. Metadata에는 작성자, 라이센스, Cookbook의 정보, 지원하는 플랫폼들의 정보를 다 른 사용자에게 전달하는데도 이용됩니다. 새로 작성한 쿡북이 있다면 멋있게 자신의 이름과 이메일을 넣어놓고 Github에 올려보세요!
  72. 75 Just Do IT, Chef! Resource Resource는 주로 cross-platform 추상화를

    도와주게 됩니다. Recipe을 설명할 때 말씀 드렸듯이 Recipe에 는 Resource 정의들의 나열처럼 보입니다. Ubunto 계 열의 OS를 사용 중이라면 package를 설치할 때 apt를 주로 사용할 테고, red hat계열이라면 yum을 사용할 것 입니다. 이런 구체적인 방법을 추상화 시켜서 install이라 는 Action으로 뭉뚱그려서 표현합니다. 실제로 platform 에 따른 차이점은 Chef가 알아서 해주게 됩니다. 멋지 죠? 솔직히 말씀 드리면 Provider라는 녀석들의 도움 덕분입니다.실제 작업하실 때는 웬만한 Action은 특별한 생각 없이 Chef 라이브러리의 Provider에게 떠넘기면 알아서 잘 처리됩니다. Action Action은 Resource를 가지고 할 수 있는 행동들을 의미 합니다. Package를 “install”한다던가, 최신 버전으로 “update”한다던가, “remove”한다던가 하는 행동들을 수 행시키는 것입니다. Recipe에서 Resource를 정의할 때 “action:install” 이렇게 적어주면 바로 인스톨이 됩니다. 이때 apt를 사용할지 yum을 사용할 지는 걱정할 필요가 없고, Provider가 알아서 해주므로 따로 신경 쓰지 않아도 됩니다. Provider Action에서 설명 드린바 대로 platform에 상관없이 Action을 통해서 조작 할 수 있는 이유는 Provider덕분 입니다. install이라는 action요청이 오면 Cookbook의 Provider에서 해당 install Action이 정의되어 있는지 확 인합니다. 정의 되어 있지 않다면 Chef library에 미리 정의 되어 있는 Provider가 호출됩니다. provider에는 platform에 따라서 어떻게 행동해야할지 정의 되어 있는 것입니다.
  73. 76 H3 개발자 컨퍼런스 2012 마치며... 서버에 세월이 쌓이는 것을

    느껴 보신적이 있으십니까? 처음 입사하여 5~6년 서비스 를 하고 있는 서버에 처음 접속했을때 그 서버에 차곡차곡 쌓여있는 선배들의 발자취 를 느꼈습니다. 그래서 제가 개발용으로 사용할 서버를 새로 설정하고 기존 소스를 옮 겨와 실행 시켰을 때, 좌절하곤 했습니다. 쌓여 있는 세월이, 발자취가 없기 때문에 소 스는 작동하는 것을 거부합니다. 4년이상 “짬”이 꽉 찬 서버들는 아무도 감히 건드릴 수 없는 말년 고참처럼 변화를 거부하고 있었습니다. 팩키지들의 버전업은 상상(예상) 할 수도 없는 대참사를 초래할 수 있으므로 할 수 없는 일 이었습니다. 서버 셋팅은 시 간을 잡아먹는 하마 같은 작업이고, 기존 서버와 완벽히 똑같은 설정을 한다는 건 불 가능한 일이라고 인정하고 시작하고 있습니다. “거의 똑같다”에 만족하고 지냈습니다. 정말 이대로 괜찮을까요? 우리에게는 Cloud가 있습니다. 예전처럼 현실적으로 불가 능한 트래픽 예측을(서비스가 얼마나 큰 성공을 할 지, 대실패를 낳을지 예상 가능하 십니까?) 억지로 하고 몇 대의 서버를 운용할 지 결정 필요가 없습니다. 트래픽의 변 화에 따라서 운용할 서버의 대수를 유동적으로 변경하면 됩니다. 인스턴스를 추가하 고 Chef로 설정하고 바로 서비스에 투입하세요. 현재 운용되고 있는 서버의 설정이 어 떻게 되어 있는지 짐작하지 말고, Chef Server에서 서버의 설정이 어떻게 되어있는지 조회해보세요. 스테이징 서버에서 되던 소스가 실서버에서 안됩니까? Chef가 완벽히 똑같게 스테이징과 실서버를 설정했기 때문에 설정이 서로 다른 건 아닐까 짐작하실 필요가 없습니다. 그렇게 설정을 걱정할 시간에 다른 원인이 있는지 고민하세요
  74. 77 Just Do IT, Chef! 참고자료 http://wiki.opscode.com – opscode wiki

    http://community.opscode.com/cookbooks - Opscode Community Puppet vs Chef http://devopsanywhere.blogspot.kr/2011/10/puppet-vs-chef-fight.html http://devopsanywhere.blogspot.kr/2011/10/stupid-simple-chef-tutorial-for- dirty.html https://github.com/search?q=cookbook&type=Repositories&language=Ruby https://github.com/search?langOverride=Puppet&q=Puppet&repo=&start_ value=1&type=Repositories Images http://www.boannews.com/media/view.asp?idx=8732&page=13&kind=1&search =title&find=%B9%E8%B1%BA%B5%E6%B1%E2%C0%DA http://blog.daum.net/_blog/hdn/ArticleContentsView.do?blogid=0IgKe&articleno =3057584&looping=0&longOpen= http://www.zerodigm.org/cultbrain/60 http://www.freepatentsonline.com/D517542.html
  75. 78 H3 개발자 컨퍼런스 2012 내 컴에선 잘 되던데?! 어랏,

    실서버에서 문제가 생겼다는데 분명 내 로컬에서는 잘 되기만 합니다. 동일한 소스를 빌드해서 배포했으니 내 로컬이나 실서버나 다를리가 없는데 도대체 왜 그럴 까 분석을 하다보면 대부분 환경 설정에서의 차이가 원인입니다. 개발자로 하여금 자기만의 작업환경에서 자유롭게 개발하게 하고, 실서버로의 배포가 동일한 결과를 준다는 것을 보장하기 위해 로컬, 테스트, 스테이지, 실서버 환경을 일 치시키는 것은 매우 중요합니다. 하지만 여러 프로젝트를 진행하며 개발 환경을 빠르고 일관되게 설정한다는 것은 쉽 지 않은 일입니다. 프로젝트마다 사용하고 있는 소프트웨어의 종류와 버전, 설정에 이 르기까지 달라질 수 있는 항목들은 너무나 많습니다. 사실 내가 사용하고 있는 OS와 실서버의 OS부터 다릅니다. 진행 중인 프로젝트의 개발환경을 실서버와 꼭 맞게 구성 해서 휘파람나는 개발을 진행하다가도, 어느 날 갑자기 옛날 옛적에 운영하던 프로젝 내 컴에선 잘 되던데?! Vagrant로 서버와 동일한 개발 환경 꾸미기 기술전략팀 강소리 [email protected]
  76. 79 Vagrant로 서버와 동일한 개발 환경 꾸미기 트에 대한 버그

    수정 요청이 오기라도 하면 현재 하고 있는 환경은 고이 놔두고 그 먼 옛날의 환경을 다시 구성해야 하는 일이 생깁니다. 게다가 업무는 혼자 하기보다는 함께 하는 경우가 더 많습니다. 개발 환경에 대한 공 유가 필요합니다. 하지만 문서로 공유된 다운로드 링크들을 찾아서 설치하고 설정하 는 시간은 꽤 소요될 뿐 더러, 이 때문에 프로젝트 개발에 바로 착수하기 어렵습니다. 또한 패치를 적용하라는 메일을 놓치는 동료도 있을 것이고, 각자가 다른 프로젝트에 속해 있기도 하며, 설정이 미묘하게 다를지도 모르는 일입니다. Git으로 버전 컨트롤을 위해 브랜치를 자유자재로 오가면서 개발하듯이 개발환경도 유연하게 바꾸면서 개발하면 좋겠습니다. 해결책은 가상머신 해결책은 사실 간단하게도 가상화입니다. 내가 사용하고 있는 메인 OS가 여러 프로젝 트로 인한 의존성이나 패키지와의 충돌 문제로 어지럽혀지는 것을 피하기 위해 개발 과 테스트를 VM(가상머신)에서 하는 것입니다. 가상화의 특징은 독립적이고 반복적인 작업환경을 만드는 데 사용이 가능하다는 점입니다. 무엇보다 로컬에서 쓸 수 있어 개 발자들은 원하는 플랫폼을 구성해서 자유롭게 개발을 할 수 있습니다. 또한 적은 비용 으로 분산 시스템과 같은 복잡한 시스템을 모형화하여 테스트가 가능합니다. 대표적 으로 VMWare, KVM, Parallels, LXC, VirtualBox 같은 소프트웨어들이 있습니다. 하지만 VM을 개발환경으로 활용하는 것도 그리 간편하지만은 않습니다. 설치된 여러 VM들을 또한 관리해야 하는 것이 요구되기 때문입니다. 실제 개발 환경으로 사용하 기에 손에 익지도 않고, 매 프로젝트마다의 VM을 일일이 설정을 하는 것도 시간이 걸 리고 번거로운 일입니다. “개발과 실서버의 일치를 위한 로컬 VM을 손쉽게 빌드하자.” 이것이 바로 앞으로 설명하게 될 Vagrant가 나오게 된 배경입니다. Vagrant를 소개합니다.
  77. 80 H3 개발자 컨퍼런스 2012 Vagrant 소개 Vagrant는 VM을 쉽게

    관리해주는 오픈소스 툴입니다. Vagrant는 미리 설정된, 다양 한 VM 템플릿 중 하나를 기반으로 하여 VM 인스턴스를 자동으로 설치할 수 있게 합 니다. https://github.com/mitchellh/vagrant Mitchell Hashimoto와 John Bender가 시작한 Vagrant는 2010년 3월 7일에 0.1.0 첫 릴리즈를 하고, 정확히 2년 후에 1.0 버전을 릴리즈하였습니다. Ruby로 개발되었 으며, 이미 많은 개발자들이 기여하고 있습니다. Vagrant는 Mac OS X 10.5+, Windows 7, Debian, Ubuntu, Redhat, CentOS, Fedora, Arch, and Gentoo를 지원합니다. 이미 Mozilla, LivingSocial, EventBrite, Yammer, Disqus 및 그 외에도 많은 곳에서 사용되고 있습니다. Vagrant는 VM을 동적으로 빌드하기 위해 VM 소프트웨어에 의존합니다. 현재 릴리즈 된 버전 1.0.5 기준으로는, VM의 Provider로서 오라클의 VirtualBox만을 사용합니다.
  78. 81 Vagrant로 서버와 동일한 개발 환경 꾸미기 Vagrant 시작하기 그럼

    어떻게 생긴 것인지 Vagrant를 실제로 사용해보도록 하겠습니다. 먼저 Vagrant 를 사용하기 위한 툴을 설치하고 다음으로는 간단한 명령으로 Vagrant로 VM을 생성 하고, 실행해 보겠습니다. 1. VirtualBox 설치 Vagrant는 오라클의 VirtualBox 상에서 동작하므로 먼저 VirtualBox를 설치해야 합니 다. VirtualBox는 Windows, Mac OS X, Linux, 그리고 Solaris 에서 실행됩니다. https://www.virtualbox.org/wiki/Downloads 2. Vagrant 설치 각 OS에 맞게 패키징된 Vagrant를 다운로드 받아 설치합니다. http://downloads.vagrantup.com/ 지원되는 플랫폼이 아니라면 다음처럼 gem으로 인스톨할 수도 있지만 패키지 방식을 추천합니다. $ gem install vagrant
  79. 82 H3 개발자 컨퍼런스 2012 Vagrant 설치가 완료되면 터미널을 띄워

    vagrant 커맨드 라인을 확인할 수 있습 니다. 이후 커맨드라인은 OSX에서 실행한 결과입니다만, Windows에서도 거의 동일합니다. $ vagrant Usage: vagrant [-v] [-h] command [<args>] -v, --version Print the version and exit. -h, --help Print this help. Available subcommands: box destroy gem halt init package provision reload resume ssh ssh-config status suspend up For help on any individual command run `vagrant COMMAND -h` 3. Vagrant 프로젝트 셋업 Vagrant 설치를 완료했으므로 첫 프로젝트를 만들어 VM을 생성해봅니다. 먼저 Vagrant에서 VM을 만들기 위해 사용하는 이미지를 먼저 다운로드 받습니다. Vagrant에서는 이것을 “box”라고 부릅니다. 여기서는 lucid32라는 이름을 사용해서 32bit의 우분투 Lucid Lynx를 다운로드 받아 보겠습니다. $ vagrant box add lucid32 http://files.vagrantup.com/lucid32.box Vagrant 프로젝트로 사용할 디렉토리를 생성하고 이동합니다. $ mkdir project $ cd project
  80. 83 Vagrant로 서버와 동일한 개발 환경 꾸미기 위에서 다운로드 받은

    lucid32로 이름 지은 box를 사용하여 VM을 생성하겠다는 명령 을 내립니다. $ vagrant init lucid32 A `Vagrantfile` has been placed in this directory. You are now ready to `vagrant up` your first virtual environment! Please read the comments in the Vagrantfile as well as documentation on `vagrantup.com` for more information on using Vagrant. $ ls/dir 명령을 내리면 Vagrantfile이 생긴 것을 볼 수 있습니다. Vagrantfile은 Vagrant 프로젝트 당 생기는 Config 파일입니다. 마지막으로 한 명령만 내리면 VM이 생성되고 실행됩니다. $ vagrant up [default] Importing base box 'lucid32'... [default] Matching MAC address for NAT networking... [default] Clearing any previously set forwarded ports... [default] Forwarding ports... [default] -- 22 => 2222 (adapter 1) [default] Creating shared folders metadata... [default] Clearing any previously set network interfaces... [default] Booting VM... [default] Waiting for VM to boot. This can take a few minutes. [default] VM booted and ready for use! [default] Mounting shared folders... [default] -- v-root: /vagrant $ 이것으로 간단하게 VM을 생성하는 작업이 모두 끝났습니다. VM을 생성하고 실행하 는데 사용한 명령은 vagrant box add / vagrant init / vagrant up 이 전부입니다. 4. VM 사용 정말 개발 환경으로 사용할 수 있는 VM의 생성이 완료된 것인지 확인해봅니다. SSH 로 접속합니다. $ vagrant ssh Linux lucid32 2.6.32-38-generic #83-Ubuntu SMP Wed Jan 4 11:13:04 UTC 2012 i686 GNU/Linux Ubuntu 10.04.4 LTS Welcome to Ubuntu!
  81. 84 H3 개발자 컨퍼런스 2012 * Documentation: https://help.ubuntu.com/ New release

    'precise' available. Run 'do-release-upgrade' to upgrade to it. Welcome to your Vagrant-built virtual machine. Last login: Fri Sep 14 07:26:29 2012 from 10.0.2.2 vagrant@lucid32:~$ 이 명령은 ssh vagrant@localhost –p 2222와 동일합니다. (비밀번호는 vagrant 입니다.) 윈도우의 명령프롬프트에서는 vagrant ssh 명령이 동작하지 않지만, 대신 PuTTY와 같은 윈도우용 SSH Client를 사용하면 됩니다. 그러면 로컬 VM에 우분투가 설치된 것을 확인할 수 있습니다. 만일 프로젝트가 실행 되는 실서버가 우분투이고, 내가 사용하고 있는 컴퓨터는 맥 또는 윈도우라 해도, 똑 같은 실서버 OS를 내 로컬에서 가질 수 있다는 것입니다. 하지만 위에서 생성한 project는 사실 단지 우분투 VM을 vagrant를 통해 생성한 것 에 불과합니다. 필요한 WAS나 DB 서버를 설치하기 위해서는, 만든 우분투 VM에 vagrant ssh로 접속해서 설정하면 되지만, 우리가 원하는 것은 그 설정을 모두와 일치 시키는 것입니다. 내 개발환경을 좀 더 손쉽게 구성하고 이것을 다른 사람들에게 공유 하기 위해서는 Vagrant 명령어와 Vagrantfile을 다루면 됩니다. 어떻게 동작하는 거지? Vagrant 컨셉 Command Line Interface 앞에서 vagrant box add/vagrant init/vagrant up/vagrant ssh로 이어지는 명령으 로 VM을 생성, 실행하고 사용하는 것을 확인했듯이 Vagrant는 vagrant command의 subcommand로 컨트롤됩니다. git 명령과 같은 형태입니다.
  82. 85 Vagrant로 서버와 동일한 개발 환경 꾸미기 사용할 수 있는

    모든 명령을 보기 위해서는 단지 vagrant를 입력하면 됩니다. 각각의 subcommand에 대해서는 vagrant COMMAND –h를 치면 사용법을 볼 수 있습 니다. $ vagrant -h Usage: vagrant [-v] [-h] command [<args>] -v, --version Print the version and exit. -h, --help Print this help. Available subcommands: box destroy gem halt init package provision reload resume ssh ssh-config status suspend up For help on any individual command run `vagrant COMMAND -h` Vagrantfile 또 하나의 Vagrant 동작을 설명하는 것은 Vagrantfile입니다. Vagrantfile이 생성된 디 렉토리를 Vagrant 프로젝트라고 부르며 Vagrantfile은 Vagrant 프로젝트 하나당 하나 씩, 루트에 생성됩니다. Vagrant와 Vagrant가 생성하는 VM을 어떻게 사용할 것인지 이 파일을 통해 모두 설정할 수 있습니다. vagrant init 명령어로 초기 Vagrantfile이 생성됩니다. Vagrantfile은 대부분의 일반적 인 설정 옵션들로 긴 주석으로 설명하고 있습니다. 열어보면 다음과 같습니다. # -*- mode: ruby -*- # vi: set ft=ruby :
  83. 86 H3 개발자 컨퍼런스 2012 Vagrant::Config.run do |config| # All

    Vagrant configuration is done here. The most common configuration # options are documented and commented below. For a complete reference, # please see the online documentation at vagrantup.com. # Every Vagrant virtual environment requires a box to build off of. config.vm.box = "lucid32" # The url from where the 'config.vm.box' box will be fetched if it # doesn't already exist on the user's system. # config.vm.box_url = "http://domain.com/path/to/above.box" # Boot with a GUI so you can see the screen. (Default is headless) # config.vm.boot_mode = :gui # Assign this VM to a host-only network IP, allowing you to access it # via the IP. Host-only networks can talk to the host machine as well as # any other machines on the same network, but cannot be accessed (through this … Ruby 언어로 되어 있는 것을 볼 수 있습니다. 하지만 단순히 변수할당 방식으로 되어 있기 때문에 Vagrantfile 설정 값들만 알면 ruby에 대한 지식이 없어도 쉽게 설정할 수 있습니다. Base Box 가장 먼저 했던 것이vagrant box add입니다. Vagrant는 VM을 생성할 때 아무 것도 없는 것에서 생성하는 것이 아니라, 기본적으로 root파일 시스템이나 RAM, disk 사이즈 같은 설정을 가진 기본 이미지를 불러와 빌드 하여 VM을 생성하게 됩니다. 그것을 base box 라고 부릅니다. 이것은 Vagrant 사용 자들이 메모리 용량, 하드디스크 용량, 네트워크 컨트롤러 등과 같은 지루한 세부사 항들을 설정하는 데 시간을 보낼 필요가 없도록 굉장히 단순하게 만듭니다. Usage: vagrant box add <name> <url> vagrant box add 명령은 지정한 경로로부터 base box를 다운로드 받아 원하는 이 름으로 로컬에 저장합니다. Vagrant는 로컬 파일시스템 그리고 HTTP URL으로부터 두 방식으로 box를 추가할 수 있도록 합니다. box 이름은 단지 Vagrantfile이 들어간 Vagrant 프로젝트가 어떤 box를 기본 이미지로 사용할 것인지에 지정하는 것이므로 원하는 것 아무거나 지을 수 있습니다. 다운로드 받은 box는 ~/.vagrant.d/boxes (
  84. 87 Vagrant로 서버와 동일한 개발 환경 꾸미기 윈도우는 %HOMEPATH%\.vagrant.d\boxes )에

    저장됩니다. 한번 설치된 box는 동시에 여러 vagrant 프로젝트에서 사용될 수 있고, 서로 영향을 주지 않습니다. Usage: vagrant init [box-name] [box-url] 그 후에 vagrant init에 box 이름을 주어 Vagrantfile을 생성하거나, 그냥 vagrant init 을 한 후, Vagrantfile을 열어 box 이름을 적어줌으로써 다운로드 한 base box를 템 플릿으로 사용할 수 있습니다. 프로젝트 초기화의 첫 단계는 항상 Vagrantfile 안의 box를 정하는 것입니다. 공식 box들과 3rd Party box들은 여기서 다운로드 받을 수 있습니다. • 공식: http://files.vagrantup.com/NAME.box (lucid32, lucid64, precise32, precise64) • 3rd Party box 모음 사이트: http://vagrantbox.es vagrant box의 서브 커맨드인 add명령으로 box를 추가한 것처럼 box의 목록을 보거 나 삭제하는 기능도 서브 커맨드로 가능합니다. Usage: vagrant box <command> [<args>] Available subcommands: add list remove repackage For help on any individual command run `vagrant box COMMAND -h`
  85. 88 H3 개발자 컨퍼런스 2012 VM 라이프사이클 vagrant up 명령으로

    VirtualBox에 VM을 생성하고 인스턴스를 시작하였듯이 단순 한 명령어로 VM을 관리할 수 있습니다. vagrant suspend를 하고vagrant resume할 수 있습니다. 또는 머신을 power off 시키는vagrant halt도 할 수 있습니다. 그런 후의 vagrant up은 머신을 다시 생성하는 대신 리부트 합니다. Vagrantfile의 설정을 바꾸 고나면 vagrant reload 명령을 이용해서 import 단계를 생략하며 VM이 재시작할 수 있습니다. 또 vagrant destroy로 VM을 완전히 삭제할 수 있습니다. VM 이미지와 그 안에 포 함된 파일들을 모두 삭제합니다. VM이 삭제되고 나서 다시 vagrant up을 하면 Vagrantfile에 설정된 것을 기반해서 새로운 머신이 생성됩니다. Vagrant는 단지 기본 이미지를 베이스로 VM을 생성하는 일만 하는 것이 아닙니다. Vagrant로 생성한 VM에 개발환경을 어떻게 구성할 수 있는지 좀 더 알아보겠습니다. Vagrant로 개발환경 구성하기 아주 간단한 프로젝트를 예로 들겠습니다. https://github.com/SpringSource/spring-mvc-showcase 라는 프로젝트를 개발 하고 있습니다. 실서버는 우분투이고, 소스는 /service에 위치합니다. OpenJDK 6을 사용하고, maven2를 이용한 mvn tomcat:run 명령으로 빌드하여 8080 포트로 실제 서비스를 운영하고 있습니다.
  86. 89 Vagrant로 서버와 동일한 개발 환경 꾸미기 나는 이제 막

    이 프로젝트에 팀원으로 포함되었고, 소스를 다운 받아서 내 로컬에서 내가 좋아하는 에디터로 개발을 하고 싶습니다. 수정한 소스를 실제로 띄워 테스트해 야 하는데, 실서버와 다르게 내 로컬은 우분투가 아닌데다가, maven을 설치하고 싶지 않고, 8080포트는 이미 사용하고 있습니다. Vagrant 프로젝트로 사용할 디렉토리를 생성하고 개발 프로젝트를 받습니다. $ mkdir vagrant-showcase $ cd vagrant-showcase $ git clone https://github.com/SpringSource/spring-mvc-showcase 이미 위에서 우분투를 설치했으므로 vagrant box list 명령으로 해당 box가 있는지 확 인해봅니다. $ vagrant box list lucid32 이것으로 Vagrant 프로젝트를 초기화하고, VM을 생성하고 실행해봅니다. $ vagrant init lucid32 $ vagrant up 여기까지는 위에서 했던 것과 동일한 단계입니다. 그 다음은 어떻게 해야 할까요? 내가 수정한 소스를 VM에서 maven으로 빌드하고 실 행하고 싶은데 어떻게 할 수 있을까요? Vagrantfile을 열고 다음과 같이 수정합니다. # -*- mode: ruby -*- # vi: set ft=ruby : Vagrant::Config.run do |config| # Every Vagrant virtual environment requires a box to build off of. config.vm.box = "lucid32" # The url from where the 'config.vm.box' box will be fetched if it # doesn't already exist on the user's system. config.vm.box_url = "http://files.vagrantup.com/lucid32.box" # Forward a port from the guest to the host, which allows for outside # computers to access the VM, whereas host only networking does not. config.vm.forward_port 8080, 8088 # Share an additional folder to the guest VM. The first argument is # an identifier, the second is the path on the guest to mount the # folder, and the third is the path on the host to the actual folder. config.vm.share_folder "v-showcase", "/service", "spring-mvc-showcase" # Update Server
  87. 90 H3 개발자 컨퍼런스 2012 config.vm.provision :shell do |shell| shell.inline

    = "apt-get update --fix-missing" end end VM에 대한 설정을 변경하였으니 재실행합니다. vagrant reload SSH Vagrant 시작하기에서 확인했듯이 Vagrant는 SSH 접근을 제공합니다. VM에 로그 인하게 하고, VM에 설치된 OS에서 명령어들을 입력할 수 있습니다. 접속하여 서버를 업데이트하고, jdk와 maven2도 설치해봅시다. $ vagrant ssh vagrant@lucid32:~$ sudo apt-get install openjdk-6-jdk vagrant@lucid32:~$ sudo apt-get install maven2 File Sync Vagrant의 장점 중 하나는 VM과 통신할 수 있는 몇 가지 채널을 설정한다는 것입니 다. 그 중 한 예가 위처럼 SSH 접근을 제공하는 것이고, 또 다른 것으로는VirtualBox 의 공유폴더 기능이 있습니다. 처음에 vagrant ssh로 접속을 해서 ls /vagrant 명령을 입력한다면 Vagrantfile을 볼 수 있습니다. 디폴트로 호스트의 Vagrant 프로젝트를 VM 내의 /vagrant로 마운트하 기 때문입니다. 디폴트 값 만이 아니라, 공유폴더를 직접 설정해서 호스트와 VM 간에 파일을 쉽게 교환할 수 있습니다. 이것을 이용해서 아까 git clone하였던 프로젝트를 VM 내의 / service 폴더에 마운트한 것입니다. ls /service를 하면 동일한 소스들이 들어와 있는 것을 볼 수 있습니다. $ vagrant ssh vagrant@lucid32:~$ ls /service 이것은 수정한 Vagrantfile의 일부입니다: config.vm.share_folder "v-showcase", "/service", "spring-mvc-showcase"
  88. 91 Vagrant로 서버와 동일한 개발 환경 꾸미기 마지막 인자 값이

    호스트의 실제 폴더를 의미하는데 Vagrantfile이 들어있는 Vagrant 프로젝트부터 상대경로로 입력하면 됩니다. 참고로 Virtualbox의 공유폴더의 성능이 파일이 증가되면 떨어진다는 이슈가 있습니 다. 이럴 경우엔 Vagrant는 NFS 설정도 가능합니다. 단지 공유폴더 옵션에 nfs 기능 만 true로 설정하면 됩니다. config.vm.share_folder("v-root", "/vagrant", ".", :nfs => true) Port Forwarding 이제 maven으로 톰캣을 실행합니다. maven repostiory로부터 디펜던시 라이브러리 를 모두 다운받고난 후 톰캣을 8080포트로 실행합니다. vagrant@lucid32:~$ mvn tomcat:run VM에서의 서버 실행이 완료되었습니다. 그럼 http://localhost:8080/spring-mvc-showcase로 확인을 해야 하는데, 내 로 컬 브라우저가 아닌, ssh로 로그인한 VM 내에서 curl이나 wget 커맨드로만 확인이 가능합니다. 이것은 내가 원한 것이 아닙니다. VM 내에 웹서버를 돌린다면 호스트에서는 어떻게 접속해야할까요? Vagrant는 Vagrantfile 내에 포트 포워딩을 설정할 수 있도록 합니다. 호스트의 포트 를 통해 게스트인 VM의 포트를 노출시킵니다. 예를 들어, 웹 서버를 테스트한다면, 80 포트를 호스트 시스템에 포워드할 수 있습니다. 호스트의 포트를 통해 VM의 포트 를 노출시킵니다. config.vm.forward_port 8080, 8088 이렇게 해서, 내가 사용하던 호스트의 브라우저를 이용해서 방금 띄운 웹 애플리케이 션 확인이 가능합니다. http://localhost:8088/spring-mvc-showcase SSH도 사실은 2222을 기본으로 포트포워딩이 되도록 Vagrant에 디폴트로 설정되어 있습니다. 다른 VM을 띄우면, 2222는 이미 사용되고 있으므로 자동으로 다른 포트를 할당합니다.
  89. 92 H3 개발자 컨퍼런스 2012 Provisioning config.vm.provision :shell do |shell|

    shell.inline = "apt-get update --fix-missing" 마지막으로 Vagrantfile에 수정했던 부분은 provision이라는 옵션입니다. provision 기 능은 Vagrant가 box자체에 모든 것을 하지 않도록 합니다. provision에 대해서는 뒤 에서 조금 더 설명하겠지만, provision의 몇 가지 옵션 중, 이것은 가장 기본적인 shell 프로비저너입니다. shell 프로비저너는 VM의 root 유저로서 shell을 실행시키게 합니 다. 이것은 VM에 로그인해서 shell 상에 apt-get update 명령을 내린 것과 동일한 일을 합니다. VM의 시스템을 항상 최신 것으로 유지하도록 Vagrantfile을 설정한 것입 니다. Vagrant로 개발환경 공유하기 Package - Box 만들기 (예를 든 상황에서의) 실서버와 동일한 환경을 로컬에서 빌드하는 것을 성공하였습니 다. 이제 이것을 혼자만 갖는 것이 아니라, 다른 사람들도 내 환경과 동일한 환경을 가 지도록 해야 합니다. Vagrant의 장점은 이러한 VM들을 쉽게 공유할 수 있다는 것입니다. VM에 접속하여 Java와 maven 설치 했던 것을 반복하지 않아도 된다는 것입니다. vagrant package 명령을 통해 VM을 패키지할 수 있습니다. Vagrant box 안에서 개발 환경을 패키지 할 수 있고 다른 사람에게 배포할 수 있는 방법입니다. $ vagrant package –-output vagrant-showcase-lucid32.box –-vagrantfile Vagrantfile
  90. 93 Vagrant로 서버와 동일한 개발 환경 꾸미기 명령이 실행되면 output

    옵션의 인자로 넘긴 이름으로 파일이 생깁니다. 그리고 이 파 일을 받아 새로운 Vagrant 프로젝트를 구성합니다. 이 경우, 새 프로젝트도 spring- mvc-showcase를 포함하고 있어야 합니다. $ vagrant box add vagrant-showcase-lucid32 [SharedLoc]/vagrant-showcase-lucid32. box $ mkdir vagrant-showcase-test $ cd vagrant-showcase-test $ vagrant init vagrant-showcase-lucid32 $ vagraut up VM에 들어가 java 버전과 maven을 확인하면 개발 환경이 패키지 된 것을 확인할 수 있을 것입니다. 물론, maven 명령으로 톰캣을 실행시키면 위에서 설정했던 대로 8080포트에서 동일한 결과를 얻을 수 있습니다. 새로 만든 vagrant-showcase-test에서는 Vagrantfile에 포트 포워딩 설정을 안했는 데 가능한 이유는, 이것은 포트 포워딩이 설정을 한 Vagrantfile을 box에 포함시켰기 때문입니다. Vagrantfile 로드 순서 Vagrant가 어떻게 Vagrantfile을 로드하는지 이해하는 것은 중요한 개념입니다. 사실, Vagrant가 로드할 Vagrantfile들은 여럿 있습니다. 나중에 로드된 Vagrantfile이 앞의 것을 override 합니다. 로드되는 Vagrantfile과 로드되는 순서는 다음과 같습니다: 1.  gem 디렉토리의 Vagrantfile이 로드됩니다. 이것은 모든 디폴트들을 포함하고 수정되지 않습니다. 2.  box가 지정이 되었다면 box 디렉토리의 Vagrantfile이 로드됩니다. 만약 패키징할 때 --vagrantfile 옵션을 사 용했다면, 이것은 그 box 안에 패키지된 Vagrantfile입니다. 3.  home 디렉토리(디폴트 ~/.vagrant.d/)의 Vagrantfil가 있다면 그것이 로드됩니다. 이 Vagrantfile에 사용자에게 특화될 수 있는 몇 가지 디폴트값을 설정할 수 있습니다. 4. 프로젝트 디렉토리의, 사용자가 수정할 수 있는 Vagrantfile이 로드됩니다. Vagrant 프로젝트 구성 위의 예에서는 만든 box를 공유하고 Vagrantfile을 직접 생성하도록 하였습니다. 하지 만 기본 box는 http로 다운받을 수 있는 파일 서버 어딘가에 두고, Vagrantfile만 공유 해서 개발환경을 구성하는 것이 일반적입니다.
  91. 94 H3 개발자 컨퍼런스 2012 다시 말하자면, Vagrantfile이 개발 프로젝트

    내에 포함되어 버전 컨트롤 되고, 단지 vagrant up만 하면 로컬에서 개발이 되도록 구성되는 것입니다. 예로 github.com에 공유되는 facebook에서 만든 tornado 프로젝트를 보면 Vagrantfile을 프로젝트 내에 포함시킨 것을 알 수 있습니다. https://github.com/facebook/tornado Vagrantfile의 여러 설정들 Vagrant는 이 외에도 여러 값들을 다양하게 설정할 수 있는 옵션을 제공합니다. • config.vm.auto_port_range • config.vm.base_mac • config.vm.boot_mode • config.vm.box • config.vm.box_url • config.vm.customize • config.vm.define • config.vm.forward_port • config.vm.guest • config.vm.host_name • config.vm.network • config.vm.provision • config.vm.share_folder • config.nfs.map_uid • config.nfs.map_gid • config.package.name • config.ssh.username • config.ssh.host • config.ssh.port • config.ssh.guest_port • config.ssh.max_tries • config.ssh.timeout • config.ssh.private_key_path • config.ssh.forward_agent • config.ssh.forward_x11 • config.ssh.shell • config.vagrant.dotfile_name • config.vagrant.host
  92. 95 Vagrant로 서버와 동일한 개발 환경 꾸미기 vagrantup.com의 Document에서 각

    옵션이 지원하는 기능을 확인할 수 있습니 다. 여기서는 이 중 몇 가지만 더 설명하고 마칩니다. Multi-VM 실서버 환경에서는 웹 서버 하나만 달랑 띄우는 경우는 드뭅니다. SOA나 분산 시스템 으로 작업환경을 구성하게 됩니다. 이것에 대응하여 Vagrant는 하나의 Vagrantfile로 여러 VM 설정을 할 수 있도록 합니다. Vagrant::Config.run do |config| config.vm.define :web do |web_config| web_config.vm.box = "web" web_config.vm.forward_port 80, 8080 end config.vm.define :db do |db_config| db_config.vm.box = "db" db_config.vm.forward_port 3306, 3306 end end config.vm.define을 사용하여 얼마든지 Multi-VM을 생성할 수 있습니다. 위에 예를 든 web_config 또는 db_confg 변수는 Vagrantfile의 일반적인 config와 완전히 똑같 습니다. 이것은 VM이 설정가능한 값들에 대해서 그들만의 커스텀 설정을 갖도록 합 니다. Multi-VM의 라이프 사이클은 어떻게 될까요? 싱글 VM 환경에서는 vagrant up 명령 이 VM을 시작합니다. Multi-VM 환경에서는 vagrant up 명령이 모든 VM을 시작합 니다. 만일 vagrant up web 과 같이 명령에 이름이 명시되면, 그것은 명시된 VM만을 시작할 것입니다. 이 패턴은 vagrant ssh 처럼 특정 VM이 지정되어야 하는 경우를 제 외한 다른 명령에도 마찬가지로 적용됩니다. $ vagrant up web $ vagrant ssh web 싱글 VM 라이프 사이클 up / status/ reload / suspend / halt /destroy 멀티 VM 라이프 사이클 up <target> / status <target> / reload <target> / suspend <target> / halt <target>
  93. 96 H3 개발자 컨퍼런스 2012 Host-only Networking multiple VM들이 수행되면,

    다음 단계는 VM 간의 통신을 지원하는 것입니다. 말하자 면, 웹 서버는 데이타베이스 서버와 통신할 수 있습니다. Vagrant::Config.run do |config| config.vm.define :web do |web_config| # ... web_config.vm.network :hostonly, "10.11.12.13" end config.vm.define :db do |db_config| # ... db_config.vm.network :hostonly, "10.11.12.14" end end 위의 것은 static IP를 두 web, db VM에 할당합니다. 이 static IP는 그리고나서 서로 다른 VM과 직접적으로 통신하는데 사용될 수 있습니다. 프로비저닝 vagrant package를 이용하여 java와 maven이 설치된 box 이미지를 공유할 수 있었 습니다. 그런데 java 버전을 업데이트해야 한다면 어떻게 해야할까요? 이것은 box 이 미지를 다시 빌드해서 관리해야 하는 또 다른 유지 비용을 발생시킵니다. 사실 매우 간단한 예였지만, 실제로는 여러 소프트웨어와 설정들이 존재하게 되고, 수정이 생길 때마다 매번 box를 패키지하는 것은 또 하나의 일이 됩니다.
  94. 97 Vagrant로 서버와 동일한 개발 환경 꾸미기 이에 대한 해결책으로

    Vagrant는 서버에 대한 프로비저닝을 지원합니다. base box를 매우 기본적인 기능으로만 사용하게 하고, 어떤 소프트웨어와 어떤 Configuration이 서버에 만들어야 하는지는 따로 추가하도록 하는 것입니다. Vagrant에서 기본적으로 사용할 수 있는 프로비저너들은 다음과 같습니다: • Chef Solo • Chef Server • Puppet Standalone • Puppet Server • Shell 프로비저닝은 vagrant up 그리고 vagrant reload가 호출될 때 자동으로 실행됩니다. 그러나 두 방법은 프로비저닝 외에도 더 많은 것을 수행하기 때문에, Vagrant는 이미 돌고 있는 VM에서 프로비전만 수행할 수 있도록하는 vagrant provision 커맨드도 따 로 제공합니다. 이 중 Chef-Solo 프로비저닝 설정만 살펴봅니다. Chef–Solo Provisioning Chef는 프로그램이 가능한 “cookbooks”를 통해 자동화할 수 있는, 오픈소스의 시스 템 통합 프레임워크입니다. Chef Server가 있다면 좋겠지만, 없어도 cookbook으로 VM을 프로비저닝하도록 Chef Solo 프로비저닝을 지원합니다. 이 글에서서는 Chef에 대한 설명은 생략합니다. 2-2 와 2-3의 DevOps 와 Chef 글 을 참고하시기 바랍니다. Vagrant로 Chef-Solo 프로비저닝을 위한 설정값이 어떤 것 들이 있는지만 잠깐 살펴보고, 예제를 실행해보겠습니다. 먼저 Vagrant는 어디에 cookbook들이 위치해 있는지 알아야 합니다. Vagrant프로젝 트로부터 상대경로로 입력할 수 있습니다. Vagrant::Config.run do |config| config.vm.provision :chef_solo do |chef| # This path will be expanded relative to the project directory chef.cookbooks_path = "cookbooks" end end
  95. 98 H3 개발자 컨퍼런스 2012 기본적으로, cookbooks 디렉토리는 이미 다양한

    cookbook 의 모든 폴더들을 포함 하고 있을 것입니다. 이를테면 cookbooks 디렉토리는 다음과 비슷한 구조를 가질 것 입니다: . └── cookbooks ├── apache2 ├── apt └── php 또한 Vagrantfile을 이용해서 run list를 지정할 수 있고, JSON으로 애트리뷰트 값도 설정할 수 있습니다. roles와 data_bags 도 지원합니다. Vagrant::Config.run do |config| config.vm.provision :chef_solo do |chef| chef.roles_path = "roles" chef.add_role("web") chef.add_recipe("mysql") chef.json = { :mysql_password => "foo" } end end 또는, 미리 설정된 cookbook이 있다면, 로컬에 cookbook 디렉토리를 유지하는 것 이 아니라, 다운로드해서 프로비저닝 하는 것도 가능합니다. Vagrant::Config.run do |config| config.vm.provision :chef_solo do |chef| chef.recipe_url = "http://files.mycompany.com/cookbooks.tar.gz" end end 간단한 예로 다음 프로젝트를 받아 Vagrant 실행을 해봅니다. $ git clone git://github.com/curioe/vagrant_sample.git $ cd vagrant_sample $ vagrant up $ open localhost:8080 그러면 git clone한 프로젝트에 포함된 index.php가 실행되는 것을 볼 수 있습니다.
  96. 99 Vagrant로 서버와 동일한 개발 환경 꾸미기 Vagrantfile을 열어보면 box는

    그저 기본 우분투입니다. apache나 php가 설치된 이 미지가 아닙니다. 그런데도 php 실행이 되는 것은 chef-solo로 apache2에 php5 모 듈을 설치하도록 프로비저닝 설정을 했기 때문입니다. 소프트웨어 설치에 대한 변경 등에 대해 box 이미지를 수정하지 않고도, VM 밖에서 Vagrantfile이나 cookbook recipe 수정으로 개발 환경 변경이 가능한 것입니다. # -*- mode: ruby -*- # vi: set ft=ruby : Vagrant::Config.run do |config| # All Vagrant configuration is done here. The most common configuration # options are documented and commented below. For a complete reference, # please see the online documentation at vagrantup.com. # Every Vagrant virtual environment requires a box to build off of. config.vm.box = "lucid32" # The url from where the 'config.vm.box' box will be fetched if it # doesn't already exist on the user's system. config.vm.box_url = "http://files.vagrantup.com/lucid32.box" # Forward a port from the guest to the host, which allows for outside # computers to access the VM, whereas host only networking does not. config.vm.forward_port 80, 8080 # Enable provisioning with chef solo, specifying a cookbooks path, roles # path, and data_bags path (all relative to this Vagrantfile), and adding # some recipes and/or roles. config.vm.provision :chef_solo do |chef| chef.cookbooks_path = "cookbooks" chef.add_recipe "php_sample" end end 정리 여기서는 Vagrant의 소개와 간략한 사용법까지만 보았습니다. 실제로 서버 환경은 위 에서 예를 든 것보다 훨씬 더 복잡합니다. 그래서 각 환경에 따라 Vagrantfile 또는 프 로비저닝이 복잡해질 수 있습니다. 실서버의 OS와 버전도 매우 다양해서 그에 맞는 box 이미지도 각각 필요한데 나중에는 나에게 맞는 base box도 만들어야 합니다.
  97. 100 H3 개발자 컨퍼런스 2012 하지만 모든 개발자들이 다 구성해야

    하는 것이 아니라, 한명만 설정해서 나누기만 하 면 나머지는 단지 vagrant up 명령만으로 개발 환경이 실서버와 동일하게 구성될 수 있음을 확인하였습니다. 이것은 개발 환경 차이에서 오는 오류를 줄이고, 개발에만 집 중할 수 있어 생산성을 높여줍니다. Vagrant는 MIT 라이선스를 사용하는 오픈소스로 꾸준히 발전하고 있으며, 현재는 VirtualBox에만 의존하지만 추후 다른 Hypervisor 지원도 계획되고 있습니다. 이미 해 외에서는 활발한 포럼 활동과 Contributor들의 플러그인 개발 등이 이루어지고 있고, github에 올라온 프로젝트들에도 Vagrantfile들이 포함되어 있는 것을 볼 수 있습니다. “vagrant up”이 간단한 명령만으로 개발 생산성을 높이는데 도움이 되길 바라며 글을 마칩니다.
  98. 101 Vagrant로 서버와 동일한 개발 환경 꾸미기 참고 - Vagrant

    http://vagrantup.com/ - Vagrant 설명 http://net.tutsplus.com/tutorials/php/vagrant- what-why-and-how/ https://speakerdeck.com/u/mitchellh/p/develop-and-test-configuration- management-scripts-with-vagrant http://nefariousdesigns.co.uk/vagrant-virtualised-dev-environments.html - Vagrant 구글 그룹스 https://groups.google.com/forum/?fromgroups=#!forum/ vagrant-up - Mitchell Hashimoto 트위터 @mitchellh 이미지 출처 http://www.scalarium.com/features/automation/ http://www.tipsnext.com/computer/share-files-between-two-computers-in- windows/ http://www.telefibre.com.au/networkcabling
  99. 102 H3 개발자 컨퍼런스 2012 왜 개발자가 되고 싶으세요? 출근

    시간의 압박이 없는 아침, 휴일과 평일을 구분하지 않는 삶. 따스한 햇살을 받으 며 느지막이 일어나 브런치를 먹고 가까운 도서관에 들러 책을 빌리고 조용한 커피숍 에서 여유롭게 이야기를 나눌 수 있는 삶. 이런 여유롭고 따스한 삶을 누구나 꿈꿉니 다. 그래서 좋은 대학, 좋은 직장에 목을 매는 것이죠. 필자는 운 좋게도 모바일회사에서 병역특례로 근무했습니다. 내겐 회사가 놀이터였고 마냥 배우는 게 좋아 주말에도 일하며 시간을 보냈습니다. 그러다 소집 해제되어 삶에 서 회사가 차지 하던 자리가 비게 되니 아무것도 할 수 없게 되었습니다. 스스로가 한 심해 냉장고에서 맥주를 꺼내 벌컥벌컥 마셨습니다. 그러다 책장 한편을 바라보았는 데 예전에 사놓고 보지 않은 ‘보물지도’라는 책을 발견했습니다. 그만둔 회사의 동료와 이 책을 보고 목표를 함께 만들어보자고 했던 것이 생각났습니다. 동료에게 들어 책의 내용을 대충은 알고 있었지만 읽은 것이 아니라 무슨 내용인지 궁금해지기도 했고 내 고민에 대한 답을 줄 수 있을지 않을까 싶어 책장을 넘기기 시작했습니다. 책에서는 목표를 근처에 두고 지속적으로 상기 시키면 목표를 이룰 수 있다고 했습니다. 그럼 지금까지의 무료한 일상에서 과연 내 목표는 무엇일까? 오픈소스로 개발 실력 쌓기 BaaS기술팀 진성주 [email protected]
  100. 103 오픈소스로 개발 실력 쌓기 ‘2010, 2011, 2012년의 목표는 무엇인가?’

    ‘내 꿈은 무엇인가?’ ‘아니, 내가 되고픈 게 무엇일까?’ ‘난 개발자가 되고 싶은 건가?’ 회사를 다니면서 번아웃(Burn Out)되버려 좀 쉬며 재충전하려는 생각에 시작한 백 수 생활이 인생을 어떻게 살아야 하는지, 내가 왜 개발자가 되고 싶은지에 대해 본 격적으로 물음을 던지는 계기가 되었습니다. 이런 질문들은 마음속에서 연거푸 계 속되며 나를 고민하게 했죠. 언제부터 내가 개발자를 꿈꾸기 시작한 것일까. 개 발자의 현실을 알면서도 여전히 개발자의 꿈을 꾸는 이유가 정말 궁금했습니다. 검사, 판사, 의사, 한의사 등 소위 잘나가는 직업을 택하지 않고 왜 개발자를 택했냐고 물으면 우스갯소리로 “수능 점수가 안되잖아요”라고 말할 수밖에 없는 한국에서 개발 자를 꿈꾸기 시작한 이유가 무엇일까요? “왜 내가 이 길을 택했을까?” 기억을 거슬러 올라가보면 한번쯤은 내가 이 길을 가겠다고 마음먹은 사건이 있지 않 을까요. 며칠 전 모임에서 만난 사람들과 술을 마시며 했던 얘기가 떠올랐습니다. 그 들은 기다렸다는 듯 각자의 사연을 이야기했습니다. “게임을 좋아해서 멋진 게임을 만들고 싶었어.” “컴퓨터 하는 것이 좋았어. 컴퓨터 더 공부하고 싶더라.” “컴퓨터를 마음껏 업그레이드해도 엄마가 혼내지 않으실 것 같았거든.” 내 마음도 이와 같지 않았을까. 내 어린 시절을 떠올려봤습니다. 내가 컴퓨터를 처음 접했던 적이 언제일까? 요즘 아이들은 태어날 때부터 아이패드를 보고 자란다지만 지 방 소도시에서 자란 나는 컴퓨터라는 단어조차 몰랐습니다. 어느 날 아버지께서 멋 진 책상보를 깔며 하얀 기기를 올려두었는데 그것이 내 생의 첫 컴퓨터인 한국통신 01410 단말기였습니다. 하지만 어린 아이들이 그렇듯 재미있는 게임이 없어서 금방 흥미를 잃고 말았죠. 그러던 어느 날 친구가 컴퓨터 있다고 자랑하며 자신의 집에 초 대했습니다. 아무 생각 없이 찾아간 친구 집에 놓인 하얀색 컴퓨터에서 동작하는 ‘고 인돌’ 게임을 보며 오랫동안 부러워했고 결국 부모님께 컴퓨터를 사달라고 졸라댔습니 다. 그 결과, 당시 엄청나게 고가였던 컴퓨터를 구입하게 되었습니다. 고가의 컴퓨터 를 구입하고도 내겐 그저 게임을 하기 위한 도구였습니다. 보통 그렇듯 비싼 게임기였 던 것이죠.
  101. 104 H3 개발자 컨퍼런스 2012 몇 년 뒤, 스타크래프트와 리니지의

    폭발적인 성장과 함께 PC방이 동네에 여기저기 생겨나기 시작했고 곧 학생들의 놀이터가 되었습니다. 집에서 컴퓨터를 하면 부모님 의 잔소리를 들을 테니 학교만 마치면 정해진 일과인양 곧장 PC방으로 향했습니다. 당시 게임의 묘미는 친구들과 함께하는 온라인 게임이나 채팅이었습니다. PC방의 요 금을 지불하다보니 용돈이 금방 바닥나버린 친구들은 잔머리를 굴리기 시작했습니다. 컴퓨터학원에서 강좌를 들으면 토요일이나 수업시간 전에 자유롭게 컴퓨터를 할 수 있 다는 것을 안 것이죠. 곧 무리들 사이에서 컴퓨터학원을 다니는 게 유행이 되었습니다. 누구나 그렇듯 제 자식이 남에게 지는 것을 싫어하셨던 부모님은 컴퓨터와 영어 를 배우라 시며 컴퓨터학원에 다니라고 말씀하셨습니다. 친구들과 삼삼오오 모여 자격증 수업을 듣고 온라인게임과 전혀 모르는 타지의 사람들과 만날 수 있는 인 터넷 채팅을 하며 시간을 보냈습니다. 사실 제게 컴퓨터는 게임기이거나 타지 사 람들과 얘기할 수 있는 기계 혹은 장난감 정도였는데 가끔 보게 되는 멋지게 꾸며 진 웹사이트들을 보며 나도 이런 사이트를 가지고 싶다는 생각을 하게 되었습니다. 그게 시작이었던 것 같네요. 당시 인기를 누리던 가수 브리트니 스피어 스의 팬 페이지를 만들게 되었습니다. 홈페이지를 만들며 느꼈던 성취 감과 재미는 밤새 게임하며 느꼈던 것보다 더 짜릿했습니다. 당연히 부 모님은 홈페이지를 밤새 만들고 등교하는 저를 좋아하지 않으셨죠. 어 찌되었든 그때는 “그저 좋았다”라는 말이 가장 어울리는 것 같았습니다. 이 글을 쓰는 지금도 질문에 대한 명확한 대답을 얻지 못했습니다. 지금도 “그냥 좋아 서”라는 말이 가장 적당한 것 같기도 합니다. 계속 고민하며 살다보면 알 수 있지 않을 까요? 스스로에게, 또한 이 길을 선택한 사람들에게 질문 하고 싶습니다. 왜 개발자가 되고 싶으세요? 개발자가 되기 위한 과정 왜 개발자가 되고 싶은 이유를 찾았든 찾지 못하였든 간에 현재 우리는 개발자입니다. 생각해보면 개발자가 되기 위한 과정이 있을 것입니다. 한국에서 개발자가 되기 위한 과정을 모두 알지 못하지만 가장 보편적인 과정은 크게 3가지 정도 될 것 같습니다. • 대학교육 • 학원교육 • 독학
  102. 105 오픈소스로 개발 실력 쌓기 대학 교육 학년 학기 과목명

    학기 과목명 1 1 공학설계입문 2 고급C프로그래밍및설계 2 1 컴퓨터공학기초설계및실험 고급프로그래밍실습 회로이론 디지털논리회로1 고급프로그래밍설계 2 컴퓨터공학기초설계및실험2 데이터구조실습 어셈블리프로그램설계및실습 디지털논리회로2 전자회로 데이터구조설계 3 1 컴퓨터구조실험 시스템프로그래밍실습 컴퓨터구조 시스템프로그래밍 신호및시스템 컴퓨터네트워크 2 운영체제 실습 운영체제 마이크로프로세서 임베디드시스템H/W설계및실험 컴퓨터네트워크실험 데이터통신설계 디지털신호처리 통신시스템설계 4 1 디지털신호처리응용실험 임베디드소프트웨어실습 시스템반도체설계 임베디드시스템S/W설계 컴파일러 무선이동네트워크 영상처리시스템설계 음성신호처리설계 2 캡스톤설계 멀티미디어응용설계 데이터베이스및응용 컴퓨터공학특론 표 1 대학 커리큘럼 보통 공대(전자공학/컴퓨터공학) 계열에서 개발자가 배출된다고 생각하여 모 대학교 의 공학대학 일반적인 커리큘럼을 옮겨 보았습니다. 일반적으로 대학의 커리큘럼은 “엔지니어”를 길러내기보다 컴퓨터 과학을 공부하고 "컴퓨터 과학자"를 양성하는데 목 적이 있습니다.3 따라서, 커리큘럼 구성은 컴퓨터의 원리에 대한 탐구가 주를 이루고 있습니다. 한국에 서는 대학이 많이 있고 목적에 따라서는 산업계와 연계하여 소프트웨어 개발자를 육 성하고자 특수한 커리큘럼이 구성이 되기도 합니다. 대학을 다니면서 공학을 배우고 취업을 준비하고 사회에 진출합니다. 학원 교육 보통 IMF 이후 실업자 구제 중심에 IT가 있었고 실업자 숫자를 줄이기에 관심이 있었 3  스티브 맥코넬의 저서 'Professional 소프트웨어 개발'을 살펴보면 과학자는 무엇이 진실인지, 만들어 놓은 가설을 어떻게 테스트할 수 있는 지, 또 어떻게 하면 지식을 더 확장할 수 있는지 배운다. 엔지니어는 무엇이 진실인지, 어떤 것이 쓸모가 있는지, 받아들인 지식을 사용하여 실무 상의 문제를 어떻게 해결하는지에 대해 배운다. - http://goo.gl/oq5jv
  103. 106 H3 개발자 컨퍼런스 2012 던 시절부터 많은 IT 인력

    양성을 위한 학원들이 생기기 시작했습니다. 목적상 산업계 의 요구사항을 잘 반영하여 “엔지니어”를 양성하기 위해서 운영이 됩니다. 커리큘럼은 프로그래밍 언어부터 신기술 적용까지 있으며 수료 이후에 중소기업과 연계를 통해서 사회에 진출하기도 합니다. 순번 과정명 1 C Programming I 2 C++ Programming I 3 Windows Programming 4 Java Web Programming I 5 Java Web Programming II 6 Objective C 7 HybridWeb For Android 표 2 학원 커리큘럼 독학 보기 힘들지만 개발이 정말 좋아서 다른 직업을 가지고 있다가 개발자로 전직한 경우 입니다. 대표적으로 안철수 서울대학교 융합과학기술대학원장 같은 사람이 있을 수 있습니다. • 대학교육 • 학원교육 • 독학 3가지 과정 이외에도 다른 방법이 있을 수 있습니다. 어찌되었든 이러한 교육과정을 거치고 나면 과연 개발자로써 ‘짜잔’ 하고 완성이 되는 것일까요? 위에서 정리한 많 은 커리큘럼을 배우고 나면 자신감 있게 개발자라고 말할 수 있는 것일까요? 대학, 학 원, ㅇㅇㅇ 출신을 떠나서 컴퓨터의 원리와 프로그래밍 기술을 습득하고 나서 개발자 가 됩니다. 그리고 우리는 좋은 개발자가 어떤 개발자인지, 좋은 개발자가 되기 위해 서 어떠한 교육을 받아야 하는지 어떻게 해야 되는지 방법을 알지 못합니다. 그래서인 지 학생들이나 업계에 막 들어온 사람들에게 다음과 같은 안타까운 질문들을 듣게 됩 니다. • ‘HTML5’가 뜬다던데 좋아요?! • ‘빅데이터’가 뜬다던데 좋아요?! • ‘모바일’이 뜬다던데 좋아요?!
  104. 107 오픈소스로 개발 실력 쌓기 사실, 우리도 알지 못할 수도

    있습니다. 그래서인지 한국에서는 “대기업”에 가야 한다 고 “영어” 공부나 잘하라고 후배에게 청춘들에게 말하고 있는지도 모르겠습니다. 좋은 개발자 개발자가 되기 위한 교육의 시간들을 거치고 개발자가 됩니다. 그리고 과연 좋은 개발 자란 어떤 것일까라는 질문들을 하게 됩니다. 개인마다 좋은 개발자의 정의가 다르지 만 좋은 개발자가 누구인지 궁금합니다. Google, Facebook 등 세계적으로 이름난 회 사에 다니는 개발자일까요? 아님 세계적인 테크 기업의 CTO 일까요? 우리가 생각하 는 좋은 개발자가 누구 일까요? 근데, 좋은 개발자가 누구인지 묻기 전에 질문하고 싶습니다. 개발자로 살아가면서 이 분야의 사람들을 얼마나 알고 있나요? ‘이름난 개발자, 당신에게 영향을 준 대가 개발 자가 누구인가요?’ 하면 멈칫하지 않으신가요? 좋은 개발자의 정의가 다르고 정답이야 없겠지만 제가 생각하는 좋은 개발자는 다음 과 같은 일들을 실천하는 사람이라고 생각합니다. • 원하는 것을 개발할 수 있다 • 컴퓨터로 일하는 것이 아니라 컴퓨터에게 일을 시키는 사람 • 좋은 정보(최신, 고전)를 계속 습득 • 정보를 공유 개발자는 자신 혹은 타인의 요구사항을 바탕으로 기술적으로 해석하고 구현하는 사람 이며 시간과 노력을 적절히 투자하여 원하는 목표를 이루는 사람이라고 생각합니다. 요구사항을 모두 이해 했음에도 기술적인 방법을 몰라 구현하지 못하는 것은 좋은 개 발자라고 생각되어지지 않네요. 따라서, 충분히 기술적인 검토를 할 수 있고 실제로 개발 할 수 있는 사람이라고 생각됩니다. 요즘은 컴퓨터로 일하는 것은 당연한 것이 되었습니다. 좋은 개발자는 프로그램 코드 만 작성할 수 있는 사람을 일컫지는 않을 것입니다. 주변에 있는 관리자, 기획자, 디자 이너 모두 컴퓨터로 일을 하고 있습니다. 다른 직능과 다르게 개발자는 개발자는 자신 을 위한 도구를 만들 수 있는 재미난 직업입니다. 기획자, 디자이너는 그들의 도구를 구입하여 사용하지만 개발자는 직접 만들 수 있습니다. 컴퓨터로 일을 하는 사람이 아 니라 컴퓨터에게 일을 시키는 사람이 되어야 합니다. 반복적인 작업은 자신의 일을 줄 여줄 수 있도록 자동화하고 더 창의적인 생각에 집중하는 것이 좋은 개발자라고 생각 됩니다.
  105. 108 H3 개발자 컨퍼런스 2012 또한, 좋은 개발자는 다양한 매체를

    통해서 좋은 정보를 계속 습득 해야 하고 목적에 맞게 잘 사용해야 합니다. 그리고 자신의 경험과 지식을 정리하고 다른 사람들과 공유 하는 것이 진짜 내 지식이 되는 것이라고 생각합니다. 저 또한 좋은 개발자가 되기 위해서 노력하는 중입니다. 정답은 없습니다만 좋은 개 발자는 어떤 모습일까요? 각자 생각하고 하나씩 실천하면 길이 더 명확히 보이지 않 을까요? 참좋은 정보를 접하는 다양한 매체 IT 블로거(구글리더) : 몇 년간 모아둔 RSS 모음집 http://blog.softwaregeeks.org/open-rss RSS 리더인 구글리더로 짬이 나는 대로 개발 정보를 봅니다. 국내에서 양질의 컨텐츠를 올리는 블로그를 많이 구독해 두었습니다. 하루에 평균 100여개의 좋은 정보들이 올라 옵니다. 그림 1 RSS 구독기 구글리더 Daum DNA : http://dna.daum.net/lens/ Daum 에서 운영중이며 IT 유명 사이트를 모아둔 메타 사이트입니다. 특히, 실시간 인기 글을 제공하여 트랜드를 잘 알 수 있습니다. OPML 형식으로도 제공하고 있으니 구글리 더와도 통합이 가능합니다.
  106. 109 오픈소스로 개발 실력 쌓기 그림 2 Daum Lens Hacker

    News : http://news.ycombinator.com 스타트업 투자사인 Y Combinator 가 IT 뉴스를 볼 수 있도록 모아둔 사이트입니다. 세계 에서 가장 빠른 소식이 전달되는 곳입니다. 그림 3 Hacker News
  107. 110 H3 개발자 컨퍼런스 2012 오픈소스 프로젝트를 분석한다는 것 좋은

    개발자가 되기 위해서는 원하는 것을 개발할 수 있어야 한다고 했습니다. 원하는 것을 개발하기 위해서는 그만큼의 개발실력이 좋아야겠죠. 그럼 개발 실력을 쌓기 위 해서는 어떻게 해야 할까요? 시인이 되고 싶은 사람은 옛사람의 시를 보면서 공부합니다. 화가가 되고 싶은 사람은 대가의 작품을 보면서 공부합니다. 가수오디션에 지원하는 가수 지망생조차 다른 옛 선배의 노래를 듣고 부르며 성장을 하려고 합니다. 근데, 개발자는 왜 컴퓨터 원리만 공부하고 선배들의 멋진 소프트웨어에 대해서 공부를 하지 않을까요?! 잘 만들어진 오 픈소스를 분석하며 개발자로써 한 단계 성장할 수 있는 방법과 제 경험담을 풀어 놓으 려고 합니다. 저는 대한민국에서 일반적인 교육과정을 거쳤습니다. 초등학교 - 중학교 - 고등학교 - 대학교 – 병역특례 - 직장 - 직장의 일반적인 경험들이죠. 다만, 남들보다 중학교 때부터 연예인의 팬페이지를 만들면서 공개된 HTML 마크업을 보고 공부했으며 디자 인에 관심이 있어서 대학교 생활을 하면서는 공개 CMS 툴로 홈페이지 구축 아르바이 트를 한 정도입니다. 즉, 기술적으로 엄청나게 뛰어나지도 뒤쳐지지도 않는 상태였습 니다. 사회에 나와 회사 생활을 하며 이런저런 프로젝트를 진행하면서 이렇게 업무들이 흘 러가고 이렇게 코드를 짜야 하구나라고 느끼고 있을 무렵 가까운 곳에서 큰 충격을 받 았습니다. 주로 많이 사용하는 언어인 Java 소스가 JDK(Java Development Kit)을 설치할 때에 같이 설치되어 있고 압축파일로 잠자고 있다는 사실 이였습니다. 아시는 분들은 어이없어할 내용이지만 당시 견습생인 저에게는 굉장히 큰 충격 이였습니다. 당시 개발 실력을 쌓으려면 어떻게 해야 하는지 방법을 모르는 상태여서 더욱 그렇게 느껴졌는지도 모르겠네요. •http://www.theserverside.com •http://www.infoq.com •http://www.readwriteweb.com •http://radar.oreilly.com •http://www.javacodegeeks.com
  108. 111 오픈소스로 개발 실력 쌓기 그 사실을 알고부터 JDK의 소스들을

    들여보기 시작했습니다. 무심코 쓰는 String. class 안의 메소드부터 확장되는 패키지까지 하나하나씩 들여보게 되었습니다. 대중 없지만 하루에 수개(2개~10개)를 정해놓고 코드를 읽었습니다. 언어관점에서 특정 키워드 하나로 달라지는 내용부터 성능을 위해서 처리하는 코드까지… 길을 한참 헤 메고 있는데 마치 길 안내판을 발견한 느낌이였죠. 그때 이후부터 타인의 잘된 코드의 모습을 보며 마치 화가가 명작을 바탕으로 수 많은 습작들을 하듯 코드 작성을 그렇게 연습했던 것 같습니다. 그리고 나서는 몇 년이 지 난 지금 수십개가 넘는 오픈소스 코드를 읽었으며 회사 업무 외에 기술적으로 보는 눈 이 넓어졌다고 느껴졌습니다. 그림 4 오픈소스를 분석과 개발실력 향상 잘 된 오픈소스를 분석한다는 것은 내가 가고자 하는 길을 먼저 걸었던 그들의 발자취 를 따라가는 것이며 그들의 경험을 배우는 것입니다. 컴퓨터 동작의 원리, 기본기 중요합니다. 또한, 중요한 것이 선배의 경험과 시행착오 들을 배워야 더 좋은 개발자가 되지 않을까요? 그럼, 지금부터 관심이 있는 분야에 오 픈소스를 찾고 선정하는 것부터 어떻게 분석하면 조금 쉽게 분석할 수 있을지 알아보 도록 하겠습니다. 오픈소스 프로젝트 찾고 선정 사람마다 관심있는 분야가 다르기 때문에 특정 오픈소스를 소개한다기보다는 어떤식 으로 관심있는 오픈소스 프로젝트를 찾는지를 알아보겠습니다.
  109. 112 H3 개발자 컨퍼런스 2012 검색엔진 – 구글, 야후, 빙

    유명한 검색엔진에서 키워드로 검색 했을 시 상위에 프로젝트를 찾는 방법 오픈소스 커뮤니티에서 프로젝트 찾기 오픈소스 프로젝트 커뮤니티, 호스팅 서비스에서 찾는 법 순번 사이트명 주소 1 The Apache Software Foundation(ASF) http://apache.org 2 JBoss http://www.jboss.org/ 3 GitHub https://github.com 4 BitBucket https://bitbucket.org 5 Google Code http://code.google.com/hosting 6 PyPi http://pypi.python.org/pypi 7 CodeProject http://www.codeproject.com 8 sourceforge http://sourceforge.net 프로젝트 선정하기 관심 있는 프로젝트를 찾았으면 과연 이 프로젝트가 유명한 프로젝트인지 코드를 봐 도 될 만큼 성장을 한 프로젝트인지를 알아보아야 합니다. 크게 4가지 항목으로 검토 를 합니다. • 검색엔진 검색결과 개수 • 프로젝트 비교 - 구글 트랜드 • stackoverflow(http://stackoverflow.com)에서 언급된 횟수 • 프로젝트 WIKI, 소스코드 주석의 질 검색엔진 검색결과 개수 보통 검색엔진에서는 검색어를 입력하고 검색 시 하단에 검색결과의 개수를 알려줍니 다. 검색 개수가 많으면 그 만큼 세계에서도 많이 사용하고 있다는 증거이며 적용과 분석 시에 참고할 문서도 많다는 것을 의미 합니다. 그림 5 구글에서 zookeeper 프로젝트로 검색했을 때 검색결과 개수
  110. 113 오픈소스로 개발 실력 쌓기 프로젝트 비교 - 구글 트랜드

    구글 트랜드(http://www.google.com/trends/)를 활용하면4 특정 검색어가 지역, 도시, 언어에 따라 어떻게 달라지는지를 파악할 수 있습니다. 해당 사이트에서 오픈 소스 프로젝트 명을 입력해서 추이가 어떻게 바뀌는지 알아 볼 수 있습니다. 프로젝트 빌드에 사용되는 Ant와 Maven 프로젝트를 비교하려면 “ant, maven”으로 검색어를 설정하면 됩니다5. 그림 6 Ant, Maven 프로젝트 비교 stackoverflow(http://stackoverflow.com)에서 언급된 횟수 “조엘 온 소프트웨어”6의 저자 Joel Spolsky와 Jeff Atwood7가 2008년 공동으로 창업하여 만든 사이트이며 개발관련 질문 답변 게시판입니다. 전 세계 개발자들이 질 문을 올리고 답변을 다는 곳 이여서 이 사이트에서 언급된 개수가 많으면 그 만큼 많 은 개발자들이 사용하고 있다고 판단해도 될 것입니다. 4 구글 트랜드 사용법 http://googlekoreablog.blogspot.kr/2008/06/blog-post_27.html 5 “ant, maven “ 검색 시 구글 트랜드 주소 http://www.google.com/trends/?q=ant,+maven 6 조엘 온 소프트웨어 - http://goo.gl/8C1uz 7 http://en.wikipedia.org/wiki/Jeff_Atwood
  111. 114 H3 개발자 컨퍼런스 2012 그림 7 stackoverflow에서 maven으로 검색

    하였을 때 검색 결과 개수 프로젝트 WIKI, 소스코드 주석의 질 오픈소스 프로젝트도 사용자(일반인, 개발자 등)가 많이 사용하길 바라기 때문에 그들 을 위해서 문서를 만들고 공개합니다. 전체적인 아키텍쳐 문서나 소프트웨어의 문서 가 존재하지 않는다면 아직은 인큐베이팅 프로젝트일 가능성이 높습니다. 오픈소스 프로젝트를 분석하며 학습하고 개발실력을 향상시키기 위해서 프로젝트를 선정하는 것이기 때문에 문서의 품질이나 소스코드의 주석의 품질이 좋지 않은 프로젝트 보다 는 조금 더 성숙된 프로젝트를 선정하는 편이 좋을 것입니다. 그림 8 검색엔진 라이브러리인 Apache Lucene의 배포 사이트에서 파일 포맷 문서
  112. 115 오픈소스로 개발 실력 쌓기 오픈소스 프로젝트 분석하기 오픈소스 프로젝트를

    찾고, 선정하였다면 이제부터는 오픈소스 프로젝트를 분석할 단 계입니다. 분석을 하기 위해서 접근을 할 때에는 2가지 접근법이 있습니다 • 오픈소스 프로젝트 사용자 • 오픈소스 프로젝트 개발자 먼저, 오픈소스 프로젝트 사용자로써 실제로 어떻게 동작하는지 어느 정도 사용해보 는 것이 좋습니다. 배포 사이트에서 문서로 제공되는 경우도 있지만 프로젝트의 테스 트 프로젝트를 통해서 사용법을 알려주는 경우도 있으므로 잘 살펴보아야 합니다. 오 픈소스 사용자로써 충분히 숙지가 되었다고 생각된다면 전체적인 아키텍쳐를 파악해 보아야 합니다. 프로젝트 구성 프로젝트 구성이라는 것은 다수의 사람들이 협의를 통해서(혹은 프로젝트 리더가) 각 컴포넌트 혹은 담당역할마다 의견을 나누어 구성해 놓은 것입니다. 따라서, 전체적인 프로젝트가 어떠한 방향으로 가고 있고 핵심 모듈이 무엇인지 파악하기 위해서는 프 로젝트 구성을 살펴보아야 합니다. 그림 9 usergrid-stack 프로젝트 구성
  113. 116 H3 개발자 컨퍼런스 2012 Visualization 도구로 아키텍쳐 파악 작은

    오픈소스 프로젝트를 분석할 때는 소스를 모두 읽어도 크게 문제가 없지만 어느 정도 규모가 있는 프로젝트를 분석 할 때면 각 클래스 혹은 각 모듈별 역할이 한눈에 들어오지 않습니다. 이 때 사용하는 것이 Visualization 도구입니다. 각 클래스 소스 혹 은 바이너리를 통해서 분석하기 쉽게 의존관계, 각 모듈 별 참조 개수를 도식화 하여 보여줍니다. 제가 사용하는 도구는 크게 2가지입니다. • Enterprise Architect - http://www.sparxsystems.com.au/ • Stan4J - http://stan4j.com/ 각 도구를 사용하면 다음과 같은 전체적인 구조를 파악하기에 쉽게 됩니다. 그림 10 Stan4J를 사용하여 usergrid-core 프로젝트를 분석한 화면 각 도구의 자세한 사용법은 각 사이트에서 친절히 나와있으나, 실제로 리버스 엔지니 어링을 통해서 분석하는 예제는 제 블로그에 동영상으로 촬영된 화면들이 있으니 참 고하시길 바랍니다. ( http://blog.softwaregeeks.org/archives/487 ) API명을 살펴봄 동서양을 넘어 프로그램 코드를 작성할 때 해당 클래스명, 메소드명, 변수명은 해당 역할을 정의하고 있다는 것은 모두 같습니다. 다양한 API들이 조합되어 프로그램 혹 은 라이브러리가 완성되니 API 명이 의미하는 역할을 이해하려고 노력해야 합니다.
  114. 117 오픈소스로 개발 실력 쌓기 왜 이런 변수명과 왜 이런

    클래스 구조를 가지게 되었는지 고민해야 학습으로써 의미 가 있습니다. 그림 11 검색엔진 라이브러리인 Apache Lucene의 API 문서 동작되는 코드(테스트 코드)를 기준으로 진행 코드가 공개되어 있고 다양한 사람들의 참여를 이끌어 내기 위한 오픈소스 프로젝트 는 완벽한 테스트코드는 아니더라도 실제로 배포하고 유지보수 할 수 있을 만큼 테스 트코드를 작성합니다. 따라서, 해당 클래스 혹은 메소드의 사용법과 의도를 알기 위해 서는 동작되는 코드(테스트 코드)를 보는 만큼 좋은 것이 없습니다. 테스트코드를 하 나씩 실행하면서 파악을 합시다. 다음 코드는 자바 비동기 네트워크 프레임워크인 netty(http://netty.io)의 테스트 코 드입니다. 앞서 API 문서를 읽음으로써 구조와 역할을 이해했다면 테스트 코드로 실 제로 어떻게 동작시키는지 결과는 어떤지 알 수 있습니다. @Test public void testFixedLengthEcho() throws Throwable { ServerBootstrap sb = new ServerBootstrap(newServerSocketChannelFactory(executor)); ClientBootstrap cb = new ClientBootstrap(newClientSocketChannelFactory(executor)); EchoHandler sh = new EchoHandler(); EchoHandler ch = new EchoHandler();
  115. 118 H3 개발자 컨퍼런스 2012 sb.getPipeline().addLast("decoder", new FixedLengthFrameDecoder(1024)); sb.getPipeline().addAfter("decoder", "handler",

    sh); cb.getPipeline().addLast("decoder", new FixedLengthFrameDecoder(1024)); cb.getPipeline().addAfter("decoder", "handler", ch); Channel sc = sb.bind(new InetSocketAddress(0)); int port = ((InetSocketAddress) sc.getLocalAddress()).getPort(); ChannelFuture ccf = cb.connect(new InetSocketAddress(TestUtil.getLocalHost(), port)); assertTrue(ccf.awaitUninterruptibly().isSuccess()); } 좋은 도구 - 통합개발도구(IDE)로 소스 읽기 메모장으로 소스코드를 보는 것보다 좋은 도구를 활용하여 소스코드를 읽게 되면 훨 씬 파악하는 데 시간이 줄어듭니다. 메모장으로 소스를 읽게 되면 한 클래스, 메소드 에 연관된 파일들을 다시 열어서 봐야 하는데 IDE를 활용하면 자동으로 해당 소스를 추적할 수 있기 때문이죠. 좋은 도구들이 많습니다. 도구를 활용해야 합니다. 예를 들어, A는 안드로이드 개발자입니다. 고맙게도 안드로이드는 오픈소스입니다. 안드로이드 앱 개발을 잘하려고 공개된 안드로이드 플랫폼 내부 구조를 분석하고 싶 습니다. API 문서도 보았고 실제 테스트 케이스를 보았습니다. 그리고 소스코드를 하 나씩 읽고 있습니다. 핵심인 안드로이드 화면 구성을 위해서 필요한 플랫폼의 동작방 식과 실제 구현은 어떻게 되어있는지 알고 싶습니다. 이러한 상황일 때 A라는 개발자는 코드를 분석하기 위해서 Z 파일을 열고 읽다가 Z와 연관 있는 Y라는 클래스를 발견합니다. 여러 개의 윈도우 창을 뒤적이며 고분분투하 며 분석 합니다. 이러한 장면을 상상만해도 비효율 적일 것이라는 것은 바로 알 수 있 습니다. 이 때 도구를 잘 활용하면 A라는 개발자는 안드로이드 플랫폼 소스를 직접 짠 코드인양 IDE 상에서 코드를 볼 수 있습니다. 안드로이드 플랫폼을 예로 들었지만 오픈 소스를 분석할 때 각 언어와 환경에 맞는 통합 개발환경을 잘 써야 코드를 분석하는 데에 집중할 수 있다는 것을 얘기하고 싶 습니다.
  116. 119 오픈소스로 개발 실력 쌓기 그림 12 이클립스에서 안드로이드 소스코드

    통합하기 글로 표현하기에는 어려운 면이 있어서 이해가 잘 되지 않으시는 분들을 위해서 Java 대표적인IDE인 이클립스(eclipse)에서 안드로이드 플랫폼 소스를 함께 볼 수 있도록 설정하는 장면을 동영상( http://goo.gl/MC5jc )으로 만들어 올려두었습니다. 영상을 보시면 쉽게 이해될 수 있을 것입니다. 정리 관심 있는 오픈소스를 선정하고 해당 프로젝트를 어떻게 분석 해야 할지를 알아보았 습니다. 가장 중요한 오픈소스를 분석할 때 가장 마음 가짐을 말해보고자 합니다. 먼저, 쫄지(?) 말자는 것입니다. 가끔 주위 후배들에게 오픈소스를 분석하여 실력을 키워보라고 권하여 그 친구들이 실천하다 보면 프로젝트나 커미터들을 너무 우상화하 여 자신의 실력을 키우기보다 마음 속 장벽을 먼저 치는 경우를 봤습니다. 외국에서 만든 소프트웨어는 모두 다 멋질 것이다라는 환상들이 있는 것 같습니다. 소스를 읽다 보면 사람마다 다 다르다는 것을 느낄 수 있습니다. 그야 말로 케.바.케(CaseByCase )죠. “프로젝트 멤버는 코드를 잘짜니까, 영어를 잘하니까…” 자신의 벽을 만드는 자세는 지양해야 합니다. 잘 만들어진 소프트웨어를 배워 내 실력을 쌓겠다는 것이 중요합니 다. 그리고 어차피 컴퓨터에서 동작하는 코드 덩어리입니다. 어차피 바이너리(0,1)가 되어서 컴퓨터에서 처리되니 너무 겁먹지 말았으면 합니다.
  117. 120 H3 개발자 컨퍼런스 2012 분석 시에 동일한 목적으로 내가

    해당 프로젝트를 진행한다면 어떻게 개발 할지를 고 민하는 것입니다. 비슷한 고민으로 현재 만들고 있는(만들 것인) 프로젝트에서 해당 아키텍쳐 혹은 디자인을 어떻게 활용할지를 고민해야 합니다. 마지막으로 작지만 유사한 무엇인가를 직접 짜보지 않으면 머리 속에서 금새 지워지 게 되더군요. 프로젝트를 어느 정도 분석하였다고 판단한다면 클론 프로젝트를 진행 하거나 해당 프로젝트에서 부족한 부분들을 보충할 수 있는 프로그램을 직접 짜봐야 합니다. “백문이 불여일타”라고 하는 이유들이 다 있는 것 같습니다. 왜 개발자가 되고 싶은지, 좋은 개발자가 무엇인지, 좋은 개발자가 되기 위해서 무엇 을 해야 하는지 생각 할 시간이 우리에게 필요합니다. 제가 생각했던 좋은 개발자의 필수 조건인 개발실력을 키우기 위해서 행했던 제 자그마한 경험들을 정리해보았습 니다. 사실, 회사에서 업무를 하기에도 업무에 필요한 기술을 익히기도 바쁜 것이 현실입니 다. 월화수목금금금의 현실에서 자기계발을 하기 위해서 무엇인가 한다는 것은 큰 도 전입니다. 이러한 현실에서 한숨만 쉰다면 달라지는 것이 없을 것입니다. 먼저 걸었던 그들의 발자취를 따라가 내가 하는 시행착오를 조금이라도 줄이는 것이 내 삶을 더 행 복하게 하는 것이 아닐까 생각해 봅니다. 즐거운 개발을 하며 미소 지을 수 있는 삶을 꿈꿉니다. 모두 멋진 개발자가 되기를 기 원합니다.
  118. 121 Visualization을 중심으로 살펴본 SNS와 e-Commerce SNS 데이터 ‘인간은 사회적

    동물이다’라는 구절을 알고 계실 것입니다. 한국에서 중학교를 나온 우 리 모두, 도덕 시간에 한 문제를 더 풀기 위하여 외운 구절 중 한 구절이니까요. 사회 적 동물이라는 말은 많은 뜻을 함축합니다. 사회라는 단어에서 다수의 인간의 교류를 전제하고요, 또한 사회 밖에서는 인간일 수 없다는 의미를 전제합니다. ‘인간을 인간이 게 만드는 사회라는 것은 무엇인가.’라는 테마는 사회학에서 너무 오래 고민한 테마이 기도 합니다. 이를 위하여 보다 단순한 동물 사회, 곤충 사회를 관찰하고 실험을 하곤 합니다. 가능 하다면, 인간사회를 관찰하고 데이터를 수집하여 가설 검정을 하기도 합니다. 이런 데 이터를 분석하는 방식 중 하나가 소위 소셜 네트워크(social network)입니다. 사실상 소셜 네트워크는 최근 생긴 개념이 아니라 꽤나 오래된 개념입니다. 단지 관련 연구자 가 아닌 일반인들에게 잘 알려지지는 않은 개념 이었던 거죠. Visualization을 중심으로 살펴본 SNS와 e-Commerce 분산기술Lab 김신영 [email protected]
  119. 122 H3 개발자 컨퍼런스 2012 이 개념이 연구자가 아닌 일반인의

    일상에 침투하게 된 계기가 싸이월드(cyworld), 페 이스북(facebook), 트위터(twitter), 포스퀘어(foursquare), 아임인(i'm in) 등의 인터 넷 기반 소셜 네트워크 서비스(Social Network Service SNS )의 유행입니다. 드디어 일반인들의 눈에, 우리가 이루고 있는 네트워크의 실체가, 인터넷의 힘을 빌어, 지 인들과 즐길 수 있고 공유할 수 있는 형태로 나타난 것이죠. 사실상 소셜 네트워크 분석의 분야에 실험데이터가 아닌 실제 인간 사회를 다룬 데이터가 생긴 계기이기 도 합니다. 데이터 특성 SNS 데이터 특성을 살펴보자면, 통계학계에서 말하는 소위 Highly Correlated Data 입니다. 굳이 한글로 쓰자면 데이터 간에 상관관계가 매우 높다고 말할 수 있습니다. ‘상관관계가 높다’고 쓰면 뭔가 ‘친구끼리 정말 친밀한 관계’를 연상하시는 분들이 많습 니다만, Correlate라는 개념은 수학적이며 동시에 기하학적인 개념입니다. ‘친구끼리 정말 친밀한 관계’와 아주 관련 없지는 않습니다. 실제로 ‘친구끼리 정말 친밀한 관계’ 에서 생긴 데이터는 굉장히 Highly Correlate 하거든요. 그렇다면, SNS에서는 왜 데이터 간에 상관관계가 매우 높을까요. KTH에서 서비스하 고 있는 지역기반 SNS서비스인 아임인의 제 데이터를 한번 보여드리겠습니다. 제 1년 전 일상생활입니다. 일단 일어나서 버스 타고 번화가에 가서 아침 먹고 쇼핑합 니다. 이 그림을 데이터로 나열하면 다음 표처럼 되겠죠.
  120. 123 Visualization을 중심으로 살펴본 SNS와 e-Commerce 여기서 우리가 추가로 얻을

    수 있는 feature가 두 개 생깁니다. 여기까지 보셨다면, 데이터 분석에 익숙하신 분들은 이미 감 잡으셨을 것입니다. 아 임인의 데이터는 필연적으로 시공간 이동 시퀀스 데이터 (Spatio-Temporal moving sequence data)가 될 수 밖에 없습니다. 시퀀스 데이터의 가장 대표적인 예는 DNA 데이터입니다. 여러 가지 유전자가 서로 긴 밀한 유기체로 연결되어 돌아가는 구조를 데이터로 풀면 시퀀스 데이터가 됩니다. 데 이터 간에 매우 긴밀하게 Correlate 되어 있죠. 유전자마냥 서로 긴밀하게 연결되어 있는 데이터들이 시간과 공간적인 이동 패턴을 가지면 시공간 이동 시퀀스 데이터라 고 부르고요, 시간적인 패턴을 가지면 시간 시퀀스 데이터가 되는 것입니다. 주가, 곡 물 생산량 이런 시계열(time series)데이터들도 시퀀스 데이터라고 부를 수 있습니다. 보시다시피 제가 아임인에서 구성한 데이터는 시간적으로, 그리고 공간적으로 매우 긴밀하게 연결되어 있으며, 시공간적 제약에서 벗어날 수 없습니다. 따라서 시공간 이 동 시퀀스 데이터라고 이야기 할 수 있는 것입니다. 여기서 '지역기반 SNS가 아닌 다 른 SNS 예를 들면 twitter 같은 서비스 데이터는 다르지 않은가?'라는 질문이 나올 수 있습니다. 제가 드릴 대답은 '대부분의 SNS 데이터는 시간 시퀀스 데이터(Temporal sequence data; Time series)라는 카테고리에서 도망갈 수 없습니다.'입니다. 아임 인처럼 공간까지 영향을 미치지 않더라도요, 시간에 긴밀히 영향을 미칩니다. 예를 들
  121. 124 H3 개발자 컨퍼런스 2012 면, 한국 기준으로 '나 점심먹지롱!'이라는

    글귀(트윗)을 트위터에 남길 때, 점심 시간 에 남기겠죠. 새벽 3시에 남기진 않을 것입니다. 하다못해, 같은 사람에게서 '나 과식 했어!'라는 트윗이 올라오고, 그 후 30분 후에 '나 체했어. OTL'이라는 트윗이 올라왔 을 때 두 개의 트윗이 Uncorrelated라고 가정하는 것은 꽤나 무리일 것입니다. SNS 데이터는 시퀀스 데이터입니다. 데이터는 시간 혹은 공간, 이벤트, 정치 등 여러 이름 의 축으로 서로 매우 긴밀한 상관관계를 구성합니다. 그래서 데이터를 분석함에 있어 서 대단히 복잡하고 그에 따른 많은 문제가 생깁니다. 분석의 문제점 우선 학부 때 배우는 통계학 입문 혹은 통계학 시간에 배운 대부분의 데이 터 분석 방법이 통하지 않습니다. 심지어 평균도 구하기 힘듭니다. Identically Independent(Correlated와 완전 반대 되는 개념)한 데이터를 가정한 대부분의 평균 을 구하는 공식이 이런 데이터에선 잘 통하지 않습니다. 수식을 쓸 수 없다는 이야기 는 아닙니다. 구하고 난 결과의 질이 떨어진다는 의미입니다. 데이터가 biased(편향) 되어 있기 때문에 어떤 의미에선 틀린 평균이 나온다고 말 할 수도 있습니다. 평균을 왜 구하나요? 대부분 해당 데이터를 대표하는 값을 구해서 그 데이터가 반영하 는 정보, 또는 특징을 추출하기 위하여 구할 것입니다. 예를 들면 '유저들의 시간 당 평 균 서비스 이용량'은 원래 굉장히 중요한 정보입니다. 서비스 운영에 아주 큰 영향을 끼치는 정보입니다. 그렇다면, 먼저 일반적인 평균 구하는 방법 (초등학교 때 반 평균 중간고사 점수 구할 때 썼던 그 방법)을 이용하여 아임인의 '시간 당 평균 서비스 이용 량'을 구해 보겠습니다. 위의 표에서 칸의 색이 하얗게 될 수록 평균값이 크다는 의미입니다. 이대로 보면, ‘점 심시간과 수, 목, 금의 퇴근 시간대에 아임인 사용자들이 몰린다’라는 굉장히 단순하고 도 상식에 어긋나지 않은 정보를 알 수 있습니다. 어쩌면 평균 잘 냈다는 소리를 들을 지도 모릅니다. 과연 우리가 데이터에서 평균을 통하여 뽑을 수 있는 정보가 겨우 이 정도 일까요? 원래 평균은 대단한 겁니다. 해당 데이터에서 가장 나올 확률이 높은 값
  122. 125 Visualization을 중심으로 살펴본 SNS와 e-Commerce 이니까요. 실제로 평균값은 가장

    많은 정보를 함축해야 합니다. 이것을 알기 위해서 시퀀스 데이터 분석 기법을 가미해서 최대한 Correlation을 상쇄하여 데이터를 전처리 한 후 일종의 가중 평균을 구해보겠습니다. 다시 구한 평균에는 위치 정보가 가미되었습니다. 다시 구한 평균은 단순히 개수만 많 다고 평균이 높아지지 않습니다. 강남 맛 집, 지하철 역, 관광지 등 소위 여러 사람이 발자국을 찍는 명소에서 발자국을 찍어야 그 평균이 높아집니다. 즉, 빈도정보에 밀도 정보를 더한 결과입니다. 다시 구한 평균에 의하면, 아임인 사용자들은 출근시간에 지 하철, 버스정류장 등 중요한 장소에서 많이 찍습니다. 특히 월요일은 좀 일찍 일어나 서 출근을 하네요. 보이진 않지만, 새벽 5시 수치가 일주일 중 가장 낮습니다. 일단 퇴 근하면 딱히 어딘가에 모여서 열심히 찍지는 않습니다. 빈도에 비하여 한참 숫자가 낮 은 것은 여기저기(각자 집)에 퍼져 들어가서 찍기 때문입니다. 그러다가 금요일 친구 들과 모여서 비싼 음식을 먹는 퇴근시간을 보면 다시 수치가 커집니다. 특히 목, 금, 토요일 자정(0시)를 보면 한잔 하고 있는 것을 알 수 있습니다. 토요일은 술자리가 새 벽 1에서 2시까지 이어지는 것 같습니다. 제일 재미난 사실은 월요일은 새벽 5시부터 발자국을 찍어요. 따라서 일요일 저녁에는 평균보다 일찍 잠자리로 들어갑니다. 또한 자정 무렵까지 찍은 토요일 다음날인 일요일에는 늦잠을 자네요. SNS 데이터의 또 다른 형태 지금까지는 일반적으로 상상할 수 있는 형태의 데이터를 잠깐 들여다 보았습니다. 지 금부터는 조금 다른 형태로 SNS 데이터를 구성해 보겠습니다. 시나리오 1. 옛날 옛적 호랑이 담배 피던 시절 신대방동에 철수(1), 영희(2), 민지(3), 지수(4)가 살았습니다. 철수는 모든 동네 아이들과 친구입니다. 영희는 철수, 민지와 친구이고요. 민지는 철수, 영희, 지수와 친구입니다. 이 시나리오를 그림으로 나타내 고, network theory에서 쓰는 데이터 형태인 adjacency matrix(connectivity matrix; similarity matrix)로 구성하면 데이터는 다음과 같습니다.
  123. 126 H3 개발자 컨퍼런스 2012 위 데이터를 Visualization 하면 결과는

    다음과 같습니다. 위 그림은 신대방동의 인간관계의 데이터와 시각화 결과를 나타냅니다. 대부분의 SNS에서 유저들은 포스퀘어에서는 friends, follows, dones, comments, 트위터에 서는 follow, retweet, reply, 아임인에서는 친구, 발자국, 댓글의 형태로 서로 관계를 맺고 있습니다. 저렇게 단순하고, 인위적인 결과보다는 포스퀘어(foursquare)가 뉴욕 (New York)에서 이루어지는 SNS 데이터 그림을 살펴볼까요. 2011년 포스퀘어 연구실(foursquare lab)에서 발표한 ‘Machine Learning with Large Networks of People and Place’의 내용의 일부입니다. 포스퀘어 연구실에서는 네트 워크 형태는 위 그림과 같고, 데이터 matrix를 구성한 후 collaborative filtering이라 는 추천 알고리즘을 적용했다고 합니다. 그렇다면 포스퀘어에서 쓴 collaborative filtering은 무엇일까요? 머리 아픈 알고리즘 이야기는 빼겠습니다. 간단히 이야기 하자면 위 그림의 가운데서 보이는 형태의 데이 터를 구성하여 알고리즘에 적용하면 사람들에게 추천을 해줍니다. 비슷한 사람들끼 리 묶어서 데이터를 기반으로 추천하는 것이 기본이고요, 포스퀘어의 경우 장소 추천 에 collaborative filtering 알고리즘을 썼다고 하는군요. Collaborative filtering은 요
  124. 127 Visualization을 중심으로 살펴본 SNS와 e-Commerce 새 아마존(Amazon), 넷플릭스(Netflix) 등

    대규모 인터넷 쇼핑몰을 통해 유명해진 추 천 알고리즘 이기도 합니다. 즉 SNS업계와 e-Commerce업계 모두 추천 알고리즘 은 collaborative filtering을 도입하였다는 이야기입니다. 여기서 한가지 질문이 생 길 수 있습니다. SNS와 e-Commerce 업계는 왜 모두 이 알고리즘을 쓰고 있을까 요? collaborative filtering이 만능 추천 알고리즘이기 때문은 아니지만 SNS데이터와 e-Commerce데이터가 본질적으로 매우 비슷하기 때문입니다. 잠깐 살펴보는 e-Commerce 데이터 e-Commerce 데이터란 무엇일까요. 어렵게 생각하실 것 없습니다. 그냥 여러분이 인터넷으로 주문하는 물건들의 데이터입니다. 로그인, 아이템 찍어보기, 장바구니 담 았다 비웠다... 이런 모든 행위의 데이터를 말합니다. 시나리오를 하나 더 써보겠습 니다. 시나리오 2. 어느 쇼핑몰에 상품 1, 2, 3, 4가 있었습니다. 1을 사는 사람들 중 20명 정도가 2를 같이 샀고요, 35명이 3을, 50명이 4를 샀습니다. 2를 산 사람 중 20명이 1을, 40명이 3을 샀고요, 3을 사는 사람들 중 35명이 1을, 40명이 2를, 25명이 4를 샀습니다. 어디서 많이 본 시나리오지요. 우리가 이미 본 그림과 네트워크 그림은 완전히 같습 니다. 다른 것은 데이터 뿐입니다. 사실상 데이터도 다르지 않습니다. 위에서 살펴본 신대방동의 데이터는 좋아한다(1), 안 좋아한다(0)의 소위 이진처리를 한 데이터 이 지만, 이걸 '누가 누구와 얼마만큼 대화했는가'라고 처리하면 데이터도 같을 것입니
  125. 128 H3 개발자 컨퍼런스 2012 다. 보시다시피 SNS데이터와 e-Commerce 데이터는

    어떤 의미에서 매우 비슷합 니다. 데이터가 SNS 데이터이건, e-Commerce 데이터이건 위에서 보인 matrix는 similarity matrix, connectivity matrix 등 여러 이름을 가지고 있습니다. 어떤 이름이 든 기본 아이디어는 같습니다. '관계' 혹은 '서로 얼마나 비슷한가'를 표현한 matrix입 니다. 쇼핑몰의 상품은 소비자를 매개로 서로 관계를 맺고 서로 비슷한 사람을 찾아낼 수 있고요, SNS 유저는 neighbor, reply, retweet 등 여러 SNS의 기능을 통하여 관 계를 맺고 서로 비슷한 사람을 찾을 수 있습니다. 여기서 조금 현실적인 문제로 들어가 봅시다. 쇼핑몰에 아이템은, 특히 이런 데이터 분석을 하겠다고 할 정도의 규모라면 적어도 몇 백 만개의 아이템을 거래할 것입니다. 일반적으로 10개의 아이템을 거래하는 쇼핑몰에서 데이터 분석을 하겠다고 하진 않습 니다. 몇 백 만개의 아이템으로 저런 데이터 matrix를 구성하면 (백만 * 백만 * n) 단 위가 됩니다. 포스퀘어의 경우 15,000,000 명의 유저를 보유하고 있습니다. 고로 구 성된 matrix의 크기는 (15,000,000 * 15,000,000) 이 됩니다. 통계학을 전공한 제가 분산기술랩에 있는 이유입니다! 포스퀘어의 예에서도 확인 할 수 있듯, 이런 데이터들 은 map reduce 등의 분산기술을 이용하지 않고서는 도저히 불가능 합니다. 여기서 잠시 요약 하겠습니다. SNS 데이터는 시간, 공간 축을 매개로 매우 correlate 되어 있습니다. 평균내기도 까다롭습니다. e-Commerce 데이터도 SNS와 비슷한 수 준으로 매우 correlate 되어 있습니다. 그리고 이 두 데이터는 분산기술을 쓰지 않고서 는 다루기도 힘듭니다. 하지만 지금은 데이터 추천 알고리즘이나 분산 기술에 대한 이 야기 대신 Visualization에 대해 이야기를 하려고 합니다.
  126. 129 Visualization을 중심으로 살펴본 SNS와 e-Commerce 어떤 목적으로 저 데이터를

    분석하는가. 사람들이 원하는 insight는 무엇인가? 잠시 우리가 어떤 목적으로 저런 힘든 데이터를 분석하는지 생각해 봅시다. 인간의 행 태, 그리고 관계, 그리고 영향력은 사회학의 오래된 떡밥이자 수많은 사람들이 궁금 해 하는 '어떤 것'입니다. 굳이 사회학까지 가지 않더라도 조금 더 실생활에 가까운 예 를 들어보겠습니다. 퇴근길 치킨을 사 들고 가는 회사원에게 맥주를 할인된 가격에 내 미는 거죠. 런던 올림픽은 한국시간 밤 12시에 합니다. 야식 장사들이 미친 듯이 아파 트 입구에 야식 전단지를 붙여야 하는 시점이 온 것입니다. 열대야가 왔습니다. 이불 장사들은 솜이불 걷어 치우고 냉매를 꽉꽉 채운 이불을 내미는 거죠. 위에서 든 조악 한 예들의 공통점은 하나입니다. 세상 인간의 행태의 어떤 면들은 확률로 규칙을 만들 수 있습니다. 물론 모든 확률적 규칙이 그렇듯 이 규칙에는 예외가 존재합니다. 예외 때문에 이러한 규칙에 불신을 느끼실 수도 있습니다. 하지만 이러한 규칙들을 아는 것 은 여러 면에서 많은 힘을 아는 사람에게 부여해 줄 것입니다. 최소한 내가 이불장사 를 하는데 한여름에 땀 흘리는 사람들에게 오리털 이불을 권하지는 않겠죠. 몇 년 전 만 해도 인간의 행태, 관계, 영향력을 실시간으로 이렇게까지 직접적으로 볼 수 있는 데이터는 존재하지 않았습니다. 그러나, 지금 현재 우리 눈 앞에는 행태, 관계, 영향력 을 한방에 분석할 수 있는 데이터가 생겼습니다. 바로 e-Commerce 데이터와 SNS 데이터입니다. 근데 문제는 제가 계속 강조하는 저 correlation입니다. 위에도 잠깐 언급했든 correlation은 굉장히 수학적이고, 기하학적인 개념입니다. 두 데이터 vector가 직각이면 uncorrelate 되 있는 거고요, 직각이 아니면 correlate 되어 있는 겁니다. 시각적으로 표현하면 위의 그림인 것입니다. correlate 된 데이터를 최대 한 uncorrelate 하게 데이터를 transform 하여 분석하지 않으면, 그 결과가 틀어집니
  127. 130 H3 개발자 컨퍼런스 2012 다. 괜히 SNS, e-Commerce 데이터

    가지고 낸 통계 결과 치고 의미 있는 결과가 드 문 게 아닙니다. 이런 환경에서 데이터의 correlation은 관리자의 의도에 의하여 만들 어질 수도 있고, 우연히 발생할 수도 있습니다. 좋은 데이터는 인간을 훌륭하게 분석 할 수 있는 도구가 될 수 있습니다. 그러나 나쁜 데이터에서 훌륭한 분석 결과가 나오 긴 매우 힘듭니다. 그리고 SNS, e-Commerce 데이터의 correlation은 매우 지독합 니다. 평균도 그냥 내기 힘듭니다. 불행히도 저 그림처럼 데이터 vector가 두 개일리도 없습니다. 15,000,000 명도 넘는 사람들이 구성한 데이터가 구성하는 데이터 vector 가 숫자가 작고 서로 적당히 상쇄되게 잘 얽혀있으리라는 추측은 너무 낙관적입니다. 그렇다고 그냥 correlation이 없다고 가정하고 분석하기엔 너무 얽혀있습니다. 심지어 normal분포도 아닙니다. 그래서 visualization 인 것입니다. visualization된 결과를 보고 최대한 correlate 된 것 을 uncorrelate 되게 데이터를 보정하는 거죠. 일단 visualization이 되면 correlation 보정 말고도 여러 막대한 이점이 있거든요. 그 중 하나가 설명하기 편하다는 것입 니다. 단적으로 말해서, 여러분께서 프레젠테이션을 해야 할 순간이 왔다고 상상해 보세요. collaborative filtering의 근간을 이룰 왼쪽의 similarity matrix를 들고 발표하고 싶은 가요? 아니면 오른쪽의 visualization 결과를 들고 발표하고 싶은가요? 어느 쪽이 설 명하기가 편할까요? 단순히 설명 만이 아닙니다. 일단 visualization이 되고 나면 네트 워크 군집(clustering), 퍼짐(infusion) 등을 graph theory를 이용하여 관계 structure 자체를 분석할 수 있습니다. 대부분의 네트워크 분석 기법들이 저 visualization된 structure를 기반데이터로 분석하는 하는 graph theory를 사용하기 때문입니다.
  128. 131 Visualization을 중심으로 살펴본 SNS와 e-Commerce 그래서 visualization은 해야겠는데, 문제가

    있습니다. 그림 그리는 방식의 문제가 아닙니다. 이미 python에는 NetworkX라는 이름의 훌륭 한 library가 있습니다. 심지어 결과물이 아름답기까지 합니다. 다음 그림을 보세요. 다 음 그림은 NetworkX의 결과물입니다. 근데 이 NetworkX는 가장 중요한 문제를 해결해주지 않습니다. 바로 triangle inequality 문제입니다. triangle inequality 잠시 중등 수학으로 돌아갑시다. 삼각형의 성립 조건은 다음과 같습니다. ‘제일 긴 변의 길이가 나머지 두 변의 길이의 합보다 짧다.’ 위의 시나리오들의 수치는 이 삼각형 성립 조건을 벗어나지 않게 인위적으로 구성한 수치입니다. 다시 보는 시나리오 2. 어느 쇼핑몰에 상품 1, 2, 3, 4가 있었습니다. 1를 사는 사람 들 중 20명 정도가 2를 같이 사고, 35명이 3를, 50명이 4를 샀습니다. 2를 산 사람 중 20명이 1을, 40명이 3을 사고, 3를 사는 사람들 중 35명이 1을, 40명이 2을, 25명이 4를 샀습니다.
  129. 132 상품들은 삼각형의 꼭지점이고, 그 사이에 거리는 구입한 사람의 인원수입니다.

    보시 다시피 데이터가 삼각형 성립조건에 어긋나지 않는다면 Visualization 자체는 그렇게 어렵지 않습니다. 저렇게 작은 데이터의 경우는 그냥 손으로 그려도 되고요, 좀 복잡 해져도 distance만 있을 경우 역으로 좌표를 연산하는 수많은 알고리즘들이 증명되고 쓰이고 있거든요. 근데 과연 SNS 및 e-Commerce 데이터들이 저 삼각형 성립조건 에 맞을까요? 시나리오 3: 트위터를 예로 들어보겠습니다. 제 친구 A와 B는 트위터를 통하여 늘상 수다를 떱니다. 둘이 같이 트위터를 시작하여 지금까지 서로 수다(mention)를 100번 정도 서로 주고받았다고 가정해 봅시다. 그리고 이 둘이 저에게 트위터를 같이할 것을 요구합니다. 그래서 제가 트위터를 시작했고요, A랑 수다 1번 떨어보고, B랑 수다 1 번을 떨어본 다음에 걍 트위터를 접었습니다. 당연히 트위터 데이터 분석가는 제가 트위터를 접었는지 아니면 뜨문뜨문 하는 사람 인지 어떤지 모릅니다. 어느 날 이 분석가가 트위터 데이터를 Visualization 하려고 보 니 triangle inequality 문제가 눈앞에 발생했습니다. 저와 A와 B는 Visualization 상 에서 삼각형의 관계를 맺고 있어야 합니다. 하지만 변AB는 길이가 100 이고 나머 지 두 변은 1이군요. 아주 지독하게 삼각형 성립 조건에 맞지 않습니다. 이걸 어떻 게 해결해야 할까요? 실제 저희 회사 아임인 데이터의 경우 전체 데이터의 56%정도 가 이 triangle inequality 문제를 가지고 있었습니다. 저는 처음엔 inequality 현상이 나는 삼각형의 제일 짧은 변을 다 삭제하는 방식을 도입해 보았습니다만, 너무 많은 information loss가 일어나서 아무 쓸모도 없는 결과가 나오더군요. 다음 그림은 어찌어찌 하여 inequality 문제를 해결하고 난 첫 결과입니다. 하지만 아 직 온전한 결과라고 볼 수 없습니다. 컨퍼런스 세션 내용
  130. 133 Visualization을 중심으로 살펴본 SNS와 e-Commerce input is wrong 위

    그림은 아임인 이용자들의 데이터를 이용한 결과입니다. 좀더 구체적으로 말 하자면 강원도에 있는 모 술집을 찾은 사람들이 이룬 network를 분석하기 위하여 visualization 한 결과입니다. 이 술집을 선정한 이유 1은 다음의 그림으로 설명하겠습 니다. 위 사진은 아임인 상에서 해당 술집에 ‘혼자 술을 마신다’고 올린 어느 유저에게 달린 댓글입니다. 같이 술 먹어 주겠다, 와라, 간다, 안간다, 여러 명의 대화가 계속 이어집 니다. 다음 사진은 선정이유입니다.
  131. 134 H3 개발자 컨퍼런스 2012 위 사진은 또 다른 유저가

    안주와 사람 손을 찍고, 그 사진과 같이 올린 댓글입니다. 서로가 서로를 다 알아 맞추더군요. 이 장소의 발도장을 읽어보면 네트워크의 끈끈함 이 꽤나 농도가 짙습니다. 술집에 자리 없으니 다른 술집 가라는 일상적인(?) 조언부 터, 낚시해서 회 떠놨으니 와서 같이 먹자는 자체 이벤트 성 발자국, 같이 낚시 가자고 조르는 발자국, 이 술집에 새 안주를 먹어봤는데 맛있으니 먹어보라는 추천 발자국까 지, 꽤나 친밀한 네트워크를 이루고 있습니다. 그런데 이런 끈끈한 네트워크의 그림이 왜 저 위의 그림처럼 이상 했을까요. 구성원 에 대한 고민 없이 그냥 마구 데이터를 생성했기 때문입니다. 실제로 서로 대화한 관 계, 그냥 이웃 맺은 관계 할 것 없이 다 긁어오고, 이웃의 이웃도 긁어오고 그 이웃의 이웃도 또 긁어오고 하다 보니 저런 네트워크가 형성되더군요. 구성원이 무엇인지, 어 떤 구성원을 어떻게 네트워크에 편입 해야 하는지에 대한 고민, 즉 input data에 대한 고민 없이 구성했기 때문입니다. 좀더 깐깐하게 다시 구성원을 구성하여 그린 결과, 저 데이터 속을 갈라볼 수 있었습니다.
  132. 135 Visualization을 중심으로 살펴본 SNS와 e-Commerce 보시다시피 외부 네트워크와 내부

    네트워크가 거의 분리되어 있었습니다. 위 데이터 를 들여다본 결과 외부네트워크는 강원도에 우연히 놀러 갔다가 서울로 상경한 어느 분 덕분에 구성된 네트워크였고요, 내부 네트워크가 제가 원했던 강원도의 모 술집 network 였습니다. 데이터에 노이즈 (강원도에 우연히 놀러 갔던 어느 분)가 발생했던 거죠. 해당 노이즈를 제거한 결과는 다음과 같습니다. 위 그림은 아직 많이 부족하지만, 그래도 해당 술집 네트워크의 발생과 발전과정을 어 느 정도 볼 수 있습니다. 마지막 그림은 주변 노이즈를 사진상에서 제거하고 중앙부분 만 확대한 결과입니다. 보시다시피 내부 네트워크 구조가 뭐가 뭔지 보이지 않습니다. 노이즈 제거를 일정 수준까지 해줬는데도 불구하고 실제 네트워크가 어떻게 형성되어 있는지 보이지 않으며 유용한 정보 또한 알아낼 수 없습니다. 뭐가 문제 일까요? node size and edge size 문제에 관한 이야기에 앞서 그림에 관한 설명을 좀더 자세히 해보겠습니다. 각 node(원)은 유저입니다. 지금 현재 위의 술집 네트워크는 329명의 유저들로 이루어 진 네트워크입니다. node의 반지름은 유저가 이웃을 추가하면 추가할수록 커집니다.
  133. 136 H3 개발자 컨퍼런스 2012 그리고 유저들간의 거리(edge)는 서로 많은

    대화를 할수록 가까워 집니다. 일단 유저 가 해당 술집에 방문을 하면 색이 주홍 색으로 변합니다. 아직 술집에 가지 않은 유저 는 회색입니다. 원의 반지름과 유저간의 거리는 사실 상대적인 개념입니다. 예를 들어 저 군집 안에서 커플 A가 한달 동안 200개의 로그를 남기며 대화를 했습니 다. 같은 기간 동안 다른 커플 B는 300개의 로그를 남기며 대화를 했습니다. 두 커플 의 거리는 얼마나 차이가 나야 할까요? 가령 커플 A의 거리를 2cm로 표현하고 B의 거리를 3cm로 디테일 하게 표현했다고 했을 때 거대한 329명의 군집 안에서 1cm의 차이는 얼마나 전체 구조에 영향을 미칠까요. 그러한 고민 없이 그저 visualization에 집착한 결과인 것입니다. 위 그림의 문제는 이것 만이 아닙니다. your relationship has expired 또 다른 예를 들어보겠습니다. 커플 A는 아임인 상에서 열렬한 연애를 하다가, 약 3개 월전에 깨졌습니다. 그래서 둘 중 한 명은 아임인을 더 이상 하지 않습니다. 커플 B는 요새 연애를 열렬히 시작하였습니다. 과연 데이터를 어떻게 처리해줘야 이 깨진 커플 의 링크, 특히 아임인 접은 사람의 영향력을 네트워크에서 최소화하고 커플 B의 영향 력을 최대화할까요. time series 데이터에서 데이터 유효성을 전혀 생각하지 않았을 때 위 그림 같은 결과가 나오는 것입니다. 그렇다면 모든 것을 고려했을 때는 어떤 결 과가 나올까요? 다음과 같은 결과가 나옵니다.
  134. 137 Visualization을 중심으로 살펴본 SNS와 e-Commerce 왼쪽 그림은 node와 edge

    길이에 대한 충분한 실험 끝에 나온 결과, 오른쪽 그림은 expired 된 relationship까지 고려한 결과입니다. 강원도 모 술집의 네트워크 형성과 발전 과정을 요약하자면 다음 그림과 같습니다. 초록색은 아직 술집에 안간 사람들입니다. 일단 술집에 가면, 색이 빨간색으로 바뀝 니다. 보라색 원은 2012년 6월 기준으로 이 술집에 제일 많이 간 사람입니다. 아임인 에서는 어떤 장소에 제일 많이 간 사람에게 ‘마스터’ 호칭을 줍니다. 즉 저 보라색 원은 2012년 6월 기준으로 마스터가 된 유저입니다. 네트워크 초반에는 그렇지 않지만 중 반 이후부터 마스터를 중심으로 술집에 간 사람들(빨강)과 안간 사람(초록)들의 군집 이 뚜렷하게 나뉩니다. 특히 4번째 그림에서는 친한 사람들과 친하지 않은 사람들의 차이가 매우 뚜렷합니다. 관계의 밀도가 높아 선들이 서로 겹쳐 흡사 노란색 점으로 보일 정도입니다. 마지막 그림은 워낙 서로를 연결한 관계(노란선)의 농도가 짙고 복 잡도가 높아 군집 현상이 잘 안보일 수 도 있습니다. 그래서 마지막 그림은 편의상 관 계(노란선)을 삭제하고 그렸습니다. 마스터를 기준으로 왼쪽 하단에 빨간원(술집에서 서로 친한 사람)들이 친하게 모여있고요 오른쪽 상단은 초록원 (술집에 안간 사람)들 이 조금 밀려나간 형태로 모여서 조금 약한 밀도로 서로 관계를 맺고 있습니다.
  135. 138 H3 개발자 컨퍼런스 2012 위 그림은 거의 실시간으로 찍은

    네트워크 변천 과정입니다. 굉장히 역동적으로 사람 들이 이 술집에 방문하며 서로 대화를 나누고, 관계 맺고 있음을 볼 수 있습니다. 두 번째 케이스입니다. 이번에는 광주에 있는 모 케이크 집입니다.
  136. 139 Visualization을 중심으로 살펴본 SNS와 e-Commerce 보시다시피 주로 가게 주인이

    발자국을 남기고 있고요. 다음 사진을 보면 가게 홍보를 위하여 활동하고 있습니다. 보시다시피 실망했다는 발도장에 리플도 남기며, 새 제품 홍보도 합니다. 이 케이크 집의 네트워크 형성과 발전 과정을 요약하자면 다음 그림과 같습니다.
  137. 140 H3 개발자 컨퍼런스 2012 여전히 초록색 원은 아직 케이크

    집에 안간 사람들이고요, 빨간색이 케이크 집에 방문 한 사람, 보라색은 케이크 집의 아임인 마스터입니다. 이번 경우 마스터가 케이크 집 주인입니다. 발달과정에서 군집이 나뉘거나, 누군가에게 노란선이 모이거나, 하지 않 습니다. 네트워크 그림의 특성상 친한 사람들이 생기면, 방사형으로 원을 연상하는 동 그란 군집이 생깁니다. 술집의 경우 네트워크 전체 변천사를 그린 7장의 그림 중 4번 째 그림에서 그 현상이 가장 뚜렷하게 나타납니다. 하지만, 케이크 집의 경우 특정한 패턴 없이 처음부터 끝까지 그냥 사람들의 관계가 무질서하게 얽혀있습니다. 술집과 케이크 집을 비교해 봅시다. 일단 둘 다 수도권이 아니라는 점에서 같습니다. 다른 점은 술집 네트워크는 누가 만들려고 의도해서 생긴 네트워크가 아니라 자생적 으로 생긴 네트워크이고, 케이크 집 네트워크는 주인의 의도로 생긴 인위적 네트워크 라는 점입니다. 그래서 네트워크의 structure 자체가 완전히 틀려집니다. 술집의 경우 술집 마스터는 2개의 그룹과 친합니다. 첫 번째 그룹은 술집에 몰려다니 면서 같이 노는 그룹(다음 그림에서 위쪽 빨간 점이 많은 그룹)이고요, 두 번째 그룹은 술집에 방문하지는 않으나 어떻게든 관계를 맺고 있는 사람들(아래쪽 초록색 그룹), 이렇게 두 그룹입니다. 실제로 마스터는 두 그룹간에 가교 역할을 하고 있습니다. 케 이크 집의 경우, 마스터가 중앙에서 조금 잘 안 보이는데요, 이것은 마스터가 사실상 이 그룹에서 거의 모든 사람들하고 이야기를 조금씩 조금씩 다 해보았기 때문입니다.
  138. 141 Visualization을 중심으로 살펴본 SNS와 e-Commerce 그리고 어떤 이유에서든 케이크

    집에 간 사람들을 main으로 구성한 사람들은 특별히 친밀한 군집현상이 보이지 않고 있습니다. 관계가 복잡해 보이는 것은 실제로 무질서 하게 섞여있고, 술집의 약 2배 정도의 사람들의 활동으로 형성한 네트워크 이기 때문 입니다. (술집: 329명, 케이크 집: 618명) 사실상 데이터의 수는 패턴의 유무를 결정 해주지 않는 다는 사실을 여기서 알 수 있습니다. 일단 결론 지금까지 여러분은, SNS데이터를 중심으로 왜 visualization을 해야 하는지, visualization 과정에서 어떤 문제가 있는지, 하고 난 결과는 어떠한지를 가볍게 살펴 보았습니다. 다음 이야기는 여기서 얻을 수 있는 분석(중요한 유저 추출이라던가, 가 능성 있는 타깃 고객이라던가) 내용이 되어야 할 것 인데요, 그건 H3 발표 때 하도록 하겠습니다. 감사합니다.
  139. 142 H3 개발자 컨퍼런스 2012 시놉시스 그 어떤 언어보다 자유롭고

    인간적인 언어, 자바스크립트! 자바스크립트는 최근까지도 대화형 웹 서비스에서 폼유효성 체크와 다이나믹한 유저 인터페이스를 다루는 목적으로 가장 많이 사용되고 있습니다. 그런데 웹 표준의 진화로 크로스 플랫폼의 한계를 넘어섰고 노드로 인해 서버와 클라 이언트에서 동일 언어로 프로그래밍을 할 수 있는 아이소모픽(isomorphic) 프로그래 밍을 패러다임을 만들고 있으며 더 나아가 소프트웨어와 하드웨어의 벽도 허물고 있 습니다. 이 글에서는 서버측으로 넘어온 자바스크립트로 인해 미래의 웹이 과연 우리에게 어 떤 재미난 가능성을 보여줄 수 있는가를 “우리가 모르는 노드로 할 수 있는 몇 가지”라 는 제목으로 이야기를 해볼까 합니다. 우리가 모르는 Node.js로 할 수 있는 몇 가지 BaaS기술팀 김양원 [email protected]
  140. 143 우리가 모르는 Node.js로 할 수 있는 몇 가지 첫째

    흔히 시스템 프로그래밍은 대부분 서버측 프로그래밍 언어들의 영역이였지만 서 버측으로 확장한 자바스크립트는 특정 수준의 시스템 프로그래밍도 가능하게 해주었 습니다. 쉘 스크립팅으로 간단한 HTTP 서버인 로컬리(locally) 개발 경험과 방법을 소 개합니다. 둘째 자바스크립트로만 구현된 새로운 개념의 블로깅 엔진인 하루프레스 (haroopress)를 소개합니다. 하루프레스는 정적 페이지 기반의 블로깅 엔진으로 웹 서버, 데이터베이스 관리 시스템이 없이 블로깅이 가능합니다. 뿐만 아니라 하루프레스는 HTML5를 만나 사용자가 작성한 마크다운 문서를 다양 한 형태로 출력해줍니다. 이 챕터에서는 이런 하루프레스의 개발 경험과 특징 그리고 HTML5의 또 다른 가능성을 경험할 수 있습니다. 그리고 마지막으로 ‘설마 노드로 이런일도 가능해?’라고 할 정도로 흥미로울 만한 아 두이노를 만난 노드와 이런일도를 통한 가전 제품 전원 컨트롤 방법에 대해서 알아봅 니다. 자바스크립트로 간단한 시스템 프로그래밍 여기서는 직접 구현한 로컬 웹 서버(정확히 말하면 HTTP 서버)인 로컬리(locally)에 대 한 개발 경험에 대해 소개를 합니다. 로컬리는 본격적으로 노드를 기반으로 프로그래 밍을 한 시작점에서의 최초 오픈소스 프로젝트입니다. 먼저 로컬리를 만들게 된 계기는 굉장히 단순했습니다. 지난 H3 웹 사이트 구측 프로 젝트를 시작하면서 제가 맡은 롤은 UI 개발이였는데 간단한 마크업과 자바스크립트 동작을 확인하기 위해서는 웹 서버가 필요 했습니다. 하지만 H3 웹 사이트 구축이 다소 촉박했기 때문에 그런 귀찮은 구축 작업의 여유가 주어지질 않았습니다. 그러던 와중에 직장 동료분께서 Python 스크립트 한줄을 던져 주었습니다. //파이선 SimpleHTTPServer 모듈을 이용해 8080 포트로 HTTP 서버를 구동 $ python -m SimpleHTTPServer -p 8080 한 줄을 입력하고 나니 현재 위치한 디렉토리를 기준으로 웹 서버가 구동되었습니다. 프론트 앤드 개발 시 웹 서버 환경에서 확인해야 할 기능이라면 굉장히 유용한 팁입 니다.
  141. 144 H3 개발자 컨퍼런스 2012 그렇게 H3 사이트 구축은 별탈

    없이 완료되었고 Python 명령보다 좀더 간단한 방법 이 없을까 홀로 고민하게 되었습니다. 그렇게 문득 떠오른 노드 공식 사이트의 HTTP 서버 코드가 떠올랐습니다. var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); }).listen(1337, '127.0.0.1'); console.log('Server running at http://127.0.0.1:1337/'); 만약 이 코드가 실행 형태로 언제 어디서든지 실행할 수 있다면 비록 Python의 간단 한 코드 한줄이 있지만 더 간단하게 만들 수 있겠구나. 그리고 자바스크립트로도 쉽게 만들 수 있겠구나라는 생각으로 코딩을 시작했습니다. 그런데 저는 쉘 기반으로 프로그래밍한 경험과 웹 서버를 구현한 경험이 없어서 다음 세가지 기술적인 문제에 봉착했습니다. • 자바스크립트가 노드 기반으로 쉘 스크립트로 동작하는 방법 • 노드에서 제공하는 HTTP 모듈의 API로는 저레벨 HTTP 구현 원리에 대해 이해가 필요 •  노드 애플리케이션을 실행할 때 node locally.js라고 하는 것보다 locally 처럼 독립 실행형태로 하는 방법 쉘 스크립트 선언부 한번쯤 윈도우에서 perl 스크립트를 열어본 경험이 있다면 상단에 #! 해쉬뱅으로 시작 하는 주석을 본적이 있을 것입니다. 그리고 이미 수 많은 노드 모듈 중에는 npm과 같이 CLI(Command-Line Interface) 방식의 실행형 모듈들이 많이 있습니다. 그런 모듈들의 코드를 분석해 보니 가장 상단 에 다음과 #!/usr/bin/env node 같이 모두 선언되어 있었습니다. example.js #!/usr/bin/env node var foo = 'hello '; console.log(foo + process.argv[2]); 실행 $ ./example.js world hello world <-- 출력
  142. 145 우리가 모르는 Node.js로 할 수 있는 몇 가지 보통

    Unix Shell Script를 만들 때 파일 첫줄에 #!/bin/sh과 같이 작성하는데 이것을 shebang 이라고 합니다. 이것은 스크립트 파일이 실행될 수 있도록 권한을 주고 해당 스크립트를 실행시켰을 때 코드가 수행될 인터프리터를 지정하는 것입니다. shebang : http://en.wikipedia.org/wiki/Shebang_(Unix) 이렇게 자바스크립트 코드도 shebang에 노드를 지정해주면 쉘에서 실행 할 수 있었 습니다. 그런데 위의 절차로 진행하면 example.js는 권한이 없기 때문에 실행되지 않 습니다. 그래서 example.js에 실행 권한을 부여해야 합니다. Linux/Unix라면 chmod +x example.js로 하면됩니다. 윈도우라면 해당 파일의 등록정보에서 보안 탭에서 실 행 권한을 부여할 수 있습니다. 다음은 웹 페이지 서빙에 대한 이슈입니다. 이 문제는 노드의 HTTP 모듈은 Apache 나 Nginx와 같이 웹 애플리케이션 서버의 역할이 아닌 HTTP 프로토콜만을 구현한 구 현체이기 때문에 요청 MIME 타입에 대한 모든 처리를 해주어야 합니다. 확장 모듈로 편안하게 웹(HTTP) 서버 구축 좀더 쉽게 설명해보면 우리가 브라우저를 통해 요청하는 URL은 HTML 만 요청하고 그 안에 포함된 이미지, 스타일시트, 자바스크립트와 같은 리소스들은 브라우저가 웹 페이지를 렌더링하기 위해 다시 서버로 요청을 하게 됩니다. 만약 index.html에 이미 지, 스타일, 자바스크립트가 각 1개씩 있다고 가정하면 브라우저는 각기 다른 3개의 요청을 추가적으로 하게 됩니다. 즉 서버에서는 MIME 이 text/html 인 index.html 외에 text/css, image/*, text/ javascript 요청에 대한 응답을 추가적으로 해주어야 합니다. 물론 Apache나 Nginx와 같은 웹 서버는 알아서 처리하기 때문에 고민하지 않아도 되지만 노드의 경우에는 고 도화된 웹 애플리케이션 서버가 아니기 때문에 이런 부분은 직접 코드로 구현을 해야 합니다. 이렇듯 웹 서버가 HTTP 프로토콜을 어떻게 처리하는 지에 대한 깊은 이해도가 없다 면 노드를 이용해 간단한 웹 서버를 만드는 것도 쉽지 않습니다. 물론 로컬리에서 이 런것들을 모두 구현 했다면 아마 이 챕터 대부분은 웹 서버와 HTTP 프로토콜에 대한 이야기로 도배가 되었을 것입니다. 그래서 이 문제를 좀더 간단하게 해결하기 위해 Sencha Lab에서 만든 유명한
  143. 146 H3 개발자 컨퍼런스 2012 connect라는 HTTP 확장 모듈을 사용하였습니다.

    이 모듈은 쿠키, 세션, 캐시등을 편 리하게 제어할 수 있는 미들웨어를 함께 제공하여 가벼운 웹 애플리케이션 서버로 사 용하기에 굉장히 적당합니다. 복잡할 것만 같았던 웹 서버의 역할도 connect 모듈을 활용해 다음과 같이 간단하게 해결하게 되었습니다. var connect = require('connect'); var app = connect( connect.static(_static), connect.bodyParser() ); app.listen(program.port); • 레퍼런스 문서 : http://www.senchalabs.org/connect/ • 소스 : https://github.com/senchalabs/connect 이렇게 노드 환경에서 간단한 로컬 웹 서버를 생각보다 간단하게 구현하였습니다. 그 리고 이렇게 목적에 따라 활용할 수 있는 확장 모듈이 무수히 많다는 것은 노드의 장 점중에 한 가지입니다. 단독 실행형 애플리케이션 다음은 작성한 쉘 자바스크립트가 단독으로 실행될 수 있도록 약간의 설정을 하는 것 입니다. 자바스크립트 파일은 실행 파일 포맷이 아니기 때문에 일반적으로는 실행할 수 없습니다. Linux/Unix에서 심볼릭 링크를 잡는 방법 drwxr-xr-x 4 kimyangwon staff 136B 3 24 11:37 . drwxr-xr-x 13 kimyangwon staff 442B 8 25 23:50 .. -rw-r--r-- 1 kimyangwon staff 423B 2 11 2012 locally $ chmod +x locally -rwxr-xr-x 1 kimyangwon staff 423B 2 11 2012 locally $ ln -s ./locally /usr/local/bin/locally 윈도우에서는 해당 파일의 등록정보에서 실행 권한을 설정하고 시스템 환경에 설정된 Path의 위치에 넣어주면 언제 어디서든지 실행할 수 있게 됩니다.
  144. 147 우리가 모르는 Node.js로 할 수 있는 몇 가지 물론

    NPM을 이용하면 리눅스, 윈도우 할 것 없이 복잡한 과정을 알아서 처리해줍 니다. 로컬리 간단한 사용법 현재 내가 작업하려는 디렉토리의 위치가 /path/to/work라면 다음과 같은 명령어로 현재 디렉토리를 기준으로 웹 서버를 띄울 수 있습니다. 설치 $ npm install locally -g (설치 로그는 생략) $ locally --version 0.1.3 실행 $ pwd <-- 현재 디렉토리 표시하는 명령 /path/to/work <-- c:\path\to\work (윈도우인 경우) $ locally document root : /path/to/work/./ debug mode : false Serving started at http://localhost:8080 이렇게 만들어진 로컬리는 현재 npm 모듈로 등록되어 있고 몇몇 프론트엔드 개발자 분들이 편리하게 사용하고 있습니다. Baas.io 사이트 프론트 엔드 개발에도 편리한 역 할을 해 주었습니다. 요약 노드를 이용한 간단한 로컬 웹 서버를 구현하고 이를 독립 실행형 애플리케이션으로 만들어 유틸리티 처럼 사용할 수 있는 쉘 스크립트의 구현 방법에 대해서 알아 보았습 니다. • 프로젝트 사이트 : http://rhiokim.github.com/locally/ • 노드 모듈 : https://npmjs.org/package/locally
  145. 148 H3 개발자 컨퍼런스 2012 간단한 마크업, 스타일, 자바스크립트, Ajax

    처리 등의 확인 작업이 필요하다면 현재 작업하고 있는 디렉토리에서 locally라는 명령어를 실행해보세요. 복잡한 서버 환경 구축이 필요 없이 손쉽게 웹 서버를 띄워 작업 내용을 확인할 수 있 습니다. 자바스크립트로만 만들어진 새로운 블로그 엔진 시작 하루프레스 프로젝트의 시작은 여러가지 이유에서 시작되었지만 그 이유중에 하나를 소개하자면 옥토 프레스 때문입니다. 옥토프레스는 Ruby를 기반으로 작성된 정적 페이지 기반의 블로깅 엔진입니다. 하 지만 저는 루비에 대한 경험이 전혀 없었고 내 스타 일대로 옥토프레스 테마를 커스터마이징하려고 하니 루비를 학습해야 했습니다. 물론 루비를 학습해야 할 이유와 명분이 충분했다면 루비를 학습해서 커스터마이징 했겠지만 노드로 해보고 싶었습니다. 그래서 노드로 개발해 보기 위해 올해 2월 말부터 아이디어를 구상하기 시작했고 3월 1일부터 개발을 시작해 약 4개월간 진행하여 v0.8.x 버젼까지 구현되었습니다. 그리고 지난 9월까지 지인들과 같이 CBT(Closed beta test)를 진행했고 9월에 정식 릴리즈를 하였습니다.
  146. 149 우리가 모르는 Node.js로 할 수 있는 몇 가지 하루프레스란?

    하루프레스는 하루라는 순 우리말과 ‘발행하다’라는 뜻을 가진 프레스라는 단어의 조 합으로 하루에 이야기를 작성하여 발행하는 매우 간단한 블로그 엔진이라는 의미에서 하루프레스라고 이름을 지었습니다. 그리고 기술적으로는 웹 서버와 데이터베이스가 필요 없는 정적 페이지 기반의 블로 깅 엔진입니다. 정적 페이지 기반 블로그란 PHP로 만들어진 워드 프레스와 같이 서버 측에서 프로그램이 동작하는 것이 아닌 블로그를 구성하는 모든 페이지를 HTML로 생 성하는 프로그램을 말합니다. 하루프레스는 블로그를 위한 모든 콘텐츠를 정적 페이지(HTML)로 생성합니다. 그리 고 이렇게 생성된 페이지들을 인터넷이 되지 않는 컴퓨터에서 볼 수도 있고 Github의 정적 페이지 서비스를 이용해 퍼블리싱도 할 수 있습니다.
  147. 150 H3 개발자 컨퍼런스 2012 그리고 HTML5, CSS3을 이용한 테마와

    플러그인도 존재하여 다양한 편리한 기능을 부가적으로 제공합니다. 그리고 마지막으로 하루프레스의 가장 중요한 목표는 블로그가 필요한 사람들보다 글 을 쓰는데 불필요한 서버 구성, 데이터 베이스 설치 등을 잊고 글 쓰는 곳에만 몰입할 수 있도록 하는데에 있습니다. 마지막으로 하루프레스가 갖은 중요한 목표와 지향점은 글을 쓰고자 하는 사람에게 글을 쓰는데 집중할 수 있게 하는 것입니다. 더불어 그렇게 작성한 글이 기존의 블로 그 서비스들의 경험을 그대로 유지하고 HTML5와 CSS3를 통해 표현층이 자유로운 컨텐츠 관리 도구가 되는 것입니다. 장점 먼저 하루프레스의 가장 큰 특징은 개발자를 위한 블로그 엔진이라는 것입니다. 물론 이것은 현재까지의 개발과정에서 특징이고 점점 더 사용층을 확대해 갈 수 있는 기능 들을 추가 할 계획입니다. 몇 가지 장점을 살펴보면 다음과 같습니다. • 웹 서버와 데이터베이스 관리 시스템이 필요 없음. • 5분이면 설치 끝. • 다양한 플러그인 지원. • 반응형 디자인(Responsive Design)을 지원하는 테마. • Dropbox, Github와 연동되어 Cloud CMS의 역할도 가능. • 도메인 연동도 간단. • 팀블로깅도 간단. 단점 개발자를 위한 블로그 엔진이다 보니 몇 가지 익숙해야 할 서비스와 도구들이 있습 니다. • Github.com 서비스를 즐겨 사용해야 한다. • 마크다운 포맷을 즐겨 사용해야 한다. • 아주 간단한 수준으로 콘솔을 다룰 줄 알아야 한다.
  148. 151 우리가 모르는 Node.js로 할 수 있는 몇 가지 구현

    스택 하루프레스는 모두 자바스크립트로 개발되어졌고 15여개의 NPM 모듈들로 구성되었 습니다. 그리고 문서 포맷도 마크다운과 JSON을 활용하였습니다. 뿐만아니라 클라이언트 부분도 요즘 이슈가 되고 있는 트위터 부트스트랩을 기반으로 하고 있으며 하루프레스를 구성하기 위한 모든 플러그인도 자바스크립트로 이루어져 있습니다. 좀더 자세한 정보는 다음의 목록을 확인하세요. 컨텐츠 스펙 •Markdown: http://daringfireball.net/projects/markdown/ •JSON: http://json.org/ 하루프레스 초기화 및 빌드 •express.js: http://expressjs.com/ •locally: https://github.com/rhiokim/locally 하루프레스 코어 엔진 •colors: http://search.npmjs.org/#/colors •ejs: http://search.npmjs.org/#/ejs •findit: http://search.npmjs.org/#/findit •mkdirp: http://search.npmjs.org/#/mkdirp •moment: http://search.npmjs.org/#/moment •robotskirt: http://search.npmjs.org/#/robotskirt •rss: http://github.com/dylang/node-rss •step: http://search.npmjs.org/#/step •string: http://stringjs.com/ •stringex: http://search.npmjs.org/#/stringex •watch: https://github.com/mikeal/watch •yaml: http://search.npmjs.org/#/yaml 자바스크립트 라이브러리 •jQuery: http://jquery.com
  149. 152 H3 개발자 컨퍼런스 2012 •jQuery-jsonp Plugin: https://github.com/jaubourg/jquery-jsonp •jQuery-simpleWeather Plugin:

    http://monkeecreate.github.com/jquery.simpleWeather/ •Mustache.js: http://mustache.github.com/ •require.js: http://requirejs.org/ •Bootstrap.js: http://twitter.github.com/bootstrap/javascript.html •Google Code Prettify: http://code.google.com/p/google-code-prettify/ 프리젠테이션 라이브러리 •shower: https://github.com/pepelsbey/shower 마크업과 스타일시트 •트위터 부트스트랩: http://twitter.github.com/bootstrap •Font Awesome: http://fortawesome.github.com/Font-Awesome/ 동작 방식 동작 방식은 의외로 간단합니다. 마크다운 포맷으로 작성하면 하루프레스 엔진은 이 문서를 이미 설정된 템플릿과 플러그인과 함께 각각 문서의 설정에 맞춰 블로그, 페이 지, 슬라이드 형태의 정적 블로그로 출력 해줍니다.
  150. 153 우리가 모르는 Node.js로 할 수 있는 몇 가지 이렇게

    출력된 정적 페이지는 하루프레스에 의해서 Github에 지정된 위치로 업로드 (Push) 되며 Github를 통해 웹 서버가 필요 없이 블로그가 동작합니다. 하루프레스를 사용 중인 사이트 하루프레스를 사용중인 몇 곳의 사이트를 소개합니다. •FRENDS : http://frends.kr •하루프레스 공식 사이트 : http://haroopress.com •노드 해커 그룹 : http://nodejs.kr •Insanehong’s Incorrect Note : http://insanehong.kr/ Markdown과 HTML5 마크다운은 • 작성하기 매우 간단하고 • 가독성이 뛰어나며 • 일반 텍스트여서 특수한 에디터가 필요 없으며 • HTML 형태 뿐만아니라 다양한 포맷(PDF, ePub, mobi 등)으로 출력이 쉽다. 마크다운 : http://daringfireball.net/projects/markdown/syntax HTML5와 CSS3는 1. 시멘틱 문서 구조 2. 표현층에 대한 자유도 3. 문서의 스크린과 플랫폼 자유도
  151. 154 H3 개발자 컨퍼런스 2012 Markdown과 HTML은 문서를 위한 포맷이지만

    형태는 굉장히 다릅니다. 특히 마크 다운은 사람이 읽기 쉬운 형태의 구조적 문서이고 HTML는 브라우저가 읽기 쉽고 표 현하기 쉬운 형태의 구조적 문서입니다. 마크다운은 사람에 의해서 최소한의 표현법을 이용해 구조적으로 마킹을 한 문서이고 이를 브라우저가 인식할 수 있는 시멘틱 문서 구조로 변환을 하게 됩니다. 이렇게 변 환된 웹 문서는 CSS3로 표현층을 완전히 새롭게 정의하게 됩니다. 하루프레스는 바로 Markdown 문서를 HTML5 포맷으로 변환하면서 블로그 형태로 표현한 것입니다. 하루프레스에는 이런 마크다운과 HTML5, CSS3의 특징을 이용해 만든 또 다른 유 용한 기능이 있는데 그건 바로 웹 프리젠테이션 기능입니다. 웹 프리젠테이션도 마크 다운 형식으로 작성하기만 하면 HTML5와 CSS3의 표현층을 프리젠테이션 웹 애플 리케이션에 전달하면 다음의 그림과 같이 언제 어디서든지 프리젠테이션이 가능한 웹 프리젠테이션으로 출력해줍니다. 하루프레스를 이용해 웹 프리젠테이션을 만드는 방법은 별도로 존재하지 않습니다. 마크다운을 작성하면 그 자체가 블로그가 되기도 하고 웹 프리젠테이션이 되기도 합니다. 하지만 표현층의 정의가 다르기 때문에 내용을 다음과 같이 작성하는게 좋 습니다.
  152. 155 우리가 모르는 Node.js로 할 수 있는 몇 가지 sample.markdown

    ## 슬라이드 제목 * 리스트 항목 * 리스트 항목 ![커버이미지](./@img/cover.jpg) ===== ## 두번째 슬라이드 제목 내용영역 ===== 위의 sample.markdown 처럼 작성하면 하루프레스는 이를 특정 HTML 구조로 변환 해서 이를 CSS3와 JavaScript를 통해 웹 프리젠테이션 형태로 표현해 줍니다. 요약 구현 스택, 동작원리 그리고 HTML5와 Markdown 등 하루프레스 전반에 걸친 다양 한 소개를 하였습니다. 노드에 관심이 많은 독자라면 구현에 필요한 실무 기술에 대해 궁금하겠지만 구현 스택에서도 소개했듯이 실제 구현 코드보다 유용한 모듈을 대부분 사용하는 것도 굉장히 중요합니다. 실제로 하루프레스 코어 엔진을 위한 코드는 900 라인도 되지 않습니다. • 소스 : https://github.com/rhiokim/haroopress • 공식사이트 : http://haroopress.com 이렇듯 노드도 수 많은 모듈을 어떻게 활용하느냐는 굉장히 중요하다고 할 수 있습 니다. 두번째 이야기는 자바스크립트를 이용해 백/앤드 프론트 엔드 구분 없이 유용한 도구 와 블로그 엔진과 같은 프로덕트를 만들 수 있다는 것을 알아 보았습니다.
  153. 156 H3 개발자 컨퍼런스 2012 자바스크립트가 로봇제어까지 마지막으로 아두이노와 자바스크립트에

    관해 이야기를 할까 합니다. 과거 브라우저에 서만 동작하던 인터프리팅 언어가 과연 하드웨어를 제어할 수 있을까? 노드를 만난건 2010년 5월, 아두이노를 알게 된건 2010년 10월이였습니다. 그때 당시 Flash로 아두이노와 연계해 RC카를 동작시키는 모습을 보고 영감을 얻었 고 노드가 있다면 노드로도 구현 가능하겠다는 생각이 들어 간단한 LED 전원 제어 구 현에 들어갔고 그때 당시 노드를 통해 아두이노를 제어하기 위한 레퍼런스가 그다지 많지 않았어서 힘들게 2달여 만에 완성하였습니다. 새로운 영역에 가능성을 맛보고 나니 막혀있던 수로에 물길이 열리듯이 프론트 엔드 와 하드웨어의 연결이라는 새로운 영역에 눈을 뜨게 되었고 바로 오늘까지 자바스크 립트를 이용해 새로운 영역에 계속 시도하게 되었습니다. 여기서는 노드를 이용한 220v 가전 기기 전원제어에 대한 전체적인 구현과정에 대해 설명합니다.
  154. 157 우리가 모르는 Node.js로 할 수 있는 몇 가지 준비물

    가장 중요한 준비물은 당연 아두이노입니다. 아두이노는 오픈 소스를 기반으로 한 피 지컬 컴퓨팅 플랫폼으로, AVR을 기반으로 한 보드와 소프트웨어 개발을 위한 통합 환 경을 제공합니다. 아두이노는 많은 스위치나 센서로부터 값들을 받아들여, LED나 모터와 같은 것을 통 제함으로써 환경과 상호작용이 가능한 로봇을 만들어 낼 수 있습니다. 아두이노 공식 사이트 : http://arduino.cc 출력 최대 전압이 5v인 아두이노로 220v의 가전기기를 제어하기 위해서는 그 중간 역 할을 할 무접점릴레이가 필요합니다.
  155. 158 H3 개발자 컨퍼런스 2012 반도체 릴레이 (solid state relay,

    SSR)는 전기기계 릴레이와 다르게 움직이는 부품을 포함하지 않는 전자 스위치입니다. 무접점 릴레이라고도 합니다. 반도체 릴레이의 종 류는 빛에 반응하는 반도체 릴레이, 전압에 반응하는 반도체 릴레이와 두가지 모두 반 응하는 반도체 릴레이가 있습니다. 빛에 반응하는 반도체 릴레이는 부하에서 광학적 으로 분리된 상태이며 낮은 전압 신호로 제어합니다. via wikipedia 무접점릴레이 그외에 콘센트와 플러그 그리고 약 3~5m 전기선이 필요합니다. 설치 제일 먼저 아두이노에 스케치(아두이노 프로그래밍)를 위해서는 아두이노 IDE를 먼저 설치해야 합니다. 아두이노 IDE : http://arduino.cc/en/Main/Software 또한 노드 최신 버젼을 설치합니다. 노드 : http://nodejs.org 노드를 이용해 아두이노를 제어하기 위해서는 최신 버젼의 노드와 duino라는 모듈이 필요합니다. 물론 아두이노를 제어하기 위한 노드 모듈은 dunio 이외에도 몇 가지 더 있습니다. duino : https://github.com/ecto/duino
  156. 159 duino는 기본적인 아두이노의 digitalWrite, digitalRead, analogWrite, analogRead 를 구현해

    놓아서 복잡하게 구현하지 않고도 손쉽게 아두이노와 통신할 수 있습니다. 노드와 duino 모듈까지 설치가 완료되었다면 아두이노를 컴퓨터에 연결하고 duino 모 듈에 포함된 src/du.ino 소스를 아두이노 IDE에서 열어 아두이노에 업로드합니다. 회로 설계 준비물이 완료되었다면 다음과 같이 무접점릴레이를 전선으로 연결을 해야 합니다. (220v 전압을 다뤄야 하기 때문에 접지와 연결에 유의해야 합니다.) 다음으로는 아두이노에 연결한 모습입니다. 아두이노와 무접점릴레이 연결 시 Gnd, 13Pin을 잘 확인하고 접지해야 합니다. 접지 위치가 잘못되면 동작을 하지 않습니다. 접지 정상 확인은 13 핀에 전류가 흐르면 무접점 릴레이 램프에 불이 켜지는 것으로 확인할 수 있습니다.
  157. 160 H3 개발자 컨퍼런스 2012 다음은 실제로 완성된 모습입니다. 이렇게

    연결된 아두이노는 노드를 통해 간단한 프로그래밍으로 컨트롤 할 수 있게 됩 니다. 아두이노 스케치 #include <Servo.h> bool debug = false; int index = 0; char messageBuffer[12]; char cmd[3]; char pin[3]; char val[4]; char aux[4]; Servo servo;
  158. 161 우리가 모르는 Node.js로 할 수 있는 몇 가지 void

    setup() { Serial.begin(115200); } void loop() { while(Serial.available() > 0) { char x = Serial.read(); if (x == '!') index = 0; // start else if (x == '.') process(); // end else messageBuffer[index++] = x; } } <생략> 소스참고 : https://github.com/ecto/duino/blob/master/src/du.ino 소스는 다음의 이미지에 표시한 업로드 버튼을 누르면 아두이노로 업로드됩니다.
  159. 162 H3 개발자 컨퍼런스 2012 노드 코드 다음 코드는 duino

    모듈의 API 문서에 제공되는 기본적인 코드입니다. app.js //duino 모듈 로드 //아두이노 보드 객체 var arduino = require('duino'), board = new arduino.Board(); //Led 객체는 아두이노의 디지털 0번 부터 13번 핀까지를 제어할 수 있도록 해줍니다. //board 객체에는 위에서 생성한 보드 객체를 할당해주고 //pin에는 0부터 13번 핀중에 하나를 지정합니다. var led = new arduino.Led({ board: board, pin: 13 }); led.blink(); //13핀에 1초 간격으로 전류를 on/off 실행 $ node app.js 좀더 자세한 API는 프로젝트 페이지에서 확인할 수 있습니다. 요약 세번째 이야기는 노드를 이용해 하드웨어를 컨트롤 하고 이를 이용해 간단한 가전 제 품 전원 컨트롤 시스템을 구현해 보았습니다. 이 이야기는 꼭 자바스크립트와 노드로 인해서 가능한 것만은 아닙니다. 굳이 자바스 크립트가 아니더라도 전기 제품 전원 제어는 가능합니다. 하지만 웹으로 끌어 내기 위 해서는 자바스크립트 만큼 쉽지는 않습니다. 그리고 여기에서 주목해야 할 부분은 하드웨어 컨트롤부터 웹 인터페이스 구현까지 하나의 언어로도 충분히 가능하다는 것이 큰 장점이라고 할 수 있습니다.
  160. 163 우리가 모르는 Node.js로 할 수 있는 몇 가지 전체요약

    노드로 할 수 있는 세가지라는 주제로 작은 실험 몇 가지 해보면서 우리의 생각은 웹 이라는 환경과 웹 기술을 서버와 클라이언트라는 관계에만 묶어서 자유로운 생각을 못하고 있다는 느낌을 받았습니다. 뿐만 아니라 주변 개발자들과 노드에 대한 이야기를 나누다 보면 늘 ‘이벤트 루프고 싱 글 쓰레드며 그렇기 때문에 성능이 이렇고 스케일 업이 좋고, 디버깅이 불편하고 웹 서버로서의 성능 우위를 따지고 노드와 비슷한 Vert.x가 JVM 기반으로 나왔는데 성능 이 더 좋다더라’라는 식의 대화가 이어집니다. 세가지 이야기 모두 대부분 웹 기술을 다루지만 서버와 클라이언트라는 환경에 종속 되지 않다는 것을 특징적으로 표현하고 있습니다. 즉 웹 기술은 꼭 서버가 존재해야 하고 클라이언트가 존재해야 만 하는 것이 아닌 기술 산업 전반에 걸쳐 활용될 수 있 는 기술이라는 것입니다. 자바스크립트라는 언어는 여전히 고도화된 언어들에 비해 가볍게 여겨지고 있다는 것 도 발전 과도기에 있는 어쩔 수 없는 현실인 것 같습니다. 몇 가지 경험 사례를 통해 자바스크립트와 노드의 비젼에 대해서 작게나마 공유되었으면 하는 바램으로 글을 마 칩니다.
  161. 164 H3 개발자 컨퍼런스 2012 시작하며 모바일의 시대, 플랫폼의 시대가

    도래하면서 IT기업에게 open API는 가장 중요한 자 산으로 자리잡았다. 어떤 형식으로 API를구성하고 어떤 포맷으로 데이터를 주고받을 것인가에 대한 싸움도 치열했는데, SOAP & XML 과 REST & JSON이 경합을 벌인 끝에 REST & JSON의 승리로 끝났다. 이제 새로 생기는 모든 웹 서비스, 모바일 서 비스들은 REST & JSON 기반으로 API를 제공하고 있으며 인증 방식으로는 OAuth 2.0을 택하고 있다. 얼마 전 OAuth 의 메인 에디터인 Eran Hammer 가 자신의 블로그에 자신이 OAuth 2.0 editor를 그만둘 것이며 OAuth 2.0 스펙에서 자신의 이름을 지워 달라는 글을 올렸다. OAuth는 SNS와 모바일 세상에서 가장 중요한 인증 방법으로 자리잡았고 OAuth 2.0은 아직 최종 스펙이 나오지는 않았지만 Facebook, Google 등에서 이미 널리 사용되고 있는 스펙이기에 이 소식은 많은 사람들의 관심을 받았다. 이 글에서는 OAuth에 대한 간단한 소개와 함께 OAuth 2.0에 대한 이야기를 해보려고 한다. OAuth2 Open API 인증을 위한 만능 도구상자 기술전략팀 박민우 [email protected]
  162. 165 OAuth2 Open API 인증을 위한 만능 도구상자 OAuth 1.0a

    – API 인증을 위한 만능 칼 OAuth를 만들고 활성화 시키는데 기여한 가장 유명한 회 사는 트위터다. 트위터를 비롯한 웹 개발자들이 API의 인 증(authentication; 이 사용자가 누구인가)과 권한 부여 (authorization; 로그인 한 사용자가 무엇을 할 수 있는 가?)를 동시에 제공하는 인증 프로토콜을 찾다가, 결국 적 당한 것이 없다고 결론 내리고 새로 만든 것이 OAuth 1.0 이다. OAuth 1.0은 2007년 10월에 확정되었으나 나중에 세션 고정 공격(session fixation attack) 보안 결함이 발견되어 2009년 6월에 이 문제가 개선된 OAuth 1.0a 가 발표되었다. OAuth 1.0은 보안 결함이 있는 버전이기 때문에 더 이상 사용해서는 안되는 버전이다. OAuth 1.0a는 2010년 4월에 “The OAuth 1.0 Protocol”이라는 이 름으로 RFC5849 문서 번호를 부여 받으며 IETF 표준이 되었다. RFC 표준이름에는 1.0뒤에 “a”가 붙지 않지만 많은 사람들이 아직도 OAuth 1.0a라고 부른다. 이 글에서 도 명확하게 하기 위해 OAuth 1.0a라고 표현하기로 한다. 이 글의 주요 내용은 OAuth 2.0이긴 하지만, 1.0a에 대해서도 간단히 알고 넘어가려 고 한다. OAuth 1.0a의 장점 OAuth 1.0a가 기존의 다른 인증과 구분되는 특징은 크게 두 가지이다. 첫째, API를 인증함에 있어 써드파티 어플리케이션에게 사용자의 비밀번호를 노출하지 않고 인증 할 수 있다는 점. 둘째, 인증(authentication)과 API권한 부여(authorization )를 동시 에 할 수 있다는 점이다. OAuth 1.0이 만들어지는 시점에는 써드파티에게 비밀번호를 노출하지 않고 인증하는 방법으로서 이미 Open ID가 있었다. 하지만 Open ID는 API 의 권한 부여기능을 가지고 있지 않았고 인증 방법도 OAuth와는 방향이 많이 달랐다. OAuth 1.0a 동작방식 OAuth 1.0a 가 작동하기 위해서는 기본적으로 유저(user), 컨슈머(consumer), 서 비스 프로바이더(service provider)가 있어야 한다. OAuth 1.0a 인증을 3-legged OAuth 라고 부르기도 하는데 OAuth는 둘이서 하는 것이 아니라 셋이서 하는 것이라
  163. 166 H3 개발자 컨퍼런스 2012 는 말이다. 간단하게는 각각 유저는

    트위터 사용자, 컨슈머는 트위터 단말 어플리케이 션, 서비스 프로바이더는 트위터 API 서비스 라고 생각하면 쉽다. OAuth 1.0a 트라이앵글 새로운 트위터 어플리케이션을 앱스토어에서 다운 받았지만, 아직은 어플리케이션을 신뢰할 수 없는 상황이라고 하자. 사용자는 이 어플리케이션에 아이디와 비밀번호를 저장하면 이 어플리케이션이 또 다른 어떤 짓(몰래 아이디/비밀번호를 수집하는 등)을 할 지 모르기 때문에, 어플리케이션에 비밀번호를 저장하고 싶지 않다. OAuth 1.0은 이 경우 트위터 단말 어플리케이션 (consumer)에게 인증토큰(access token)만을 전 달하고 단말 어플리케이션이 인증토큰으로 트위터 API(service provider)를 사용할 수 있도록 해준다. OAuth 1.0a 인증 프로세스
  164. 167 OAuth2 Open API 인증을 위한 만능 도구상자 이 과정에서

    사용자가 서비스 프로바이더의 API를 사용하겠다고 로그인 할 때, 컨슈 머는 서비스 프로바이더의 로그인 화면으로 사용자를 리다이렉트 하게 된다. 이 서비 스 프로바이더의 화면은 다음과 같은 정보를 제공한다. 사용자가 이 화면에서 로그인을 완료하면 다시 컨슈머로 리다이렉트 되고 동시에 컨 슈머는 인증토큰을 사용할 수 있게 된다. 이 인증 토큰은 컨슈머가 사용자의 아이디/ 패스워드 없이 허가 받은 API에 접근할 수 있게 해준다. 사용자는 컨슈머에 저장되어 있는 인증 토큰이 유출 되더라도 서비스 프로바이더의 관리자 화면에서 언제나 그 인 증토큰의 권한을 취소(revoke)할 수 있다.
  165. 168 H3 개발자 컨퍼런스 2012 OAuth 1.0a의 인증 과정에서 request

    token 등 추가적인 개념에 대해서는 이 글에서 는 자세히 설명하지 않는다. OAuth 1.0a인증 과정에 대한 자세한 설명은 관련 자료가 많이 있으니 참고하길 바란다. 인증토큰 OAuth 1.0a 인증이 완료가 되면 컨슈머 (예를 들면 트위터 모바일 어플리케이션) 은 사용자의 아이디/패스워드를 직접 저장하게 되는 것이 아니라, 인증토큰(access token)을 받게 된다. 이 인증 토큰은 OAuth 2.0에서도 같은 개념으로 사용된다. 인증 토큰은 커베로스(Kerberos)의 티켓 개념과 비슷하다라고 할 수 있는데, 다음과 같은 특징을 가진다. 1. 컨슈머가 아이디/패스워드를 가지지 않고 API를 사용할 수 있음 2. 필요한 API에만 제한적으로 접근할 수 있도록 권한 제어 가능 3. 사용자가 서비스 프로바이더의 관리 페이지에서 권한 취소 가능 4. 패스워드 변경 시에도 인증 토큰은 계속 유효함. 자, 그러면 사용자의 스마트폰에 트위터를 인증해 놓은 상태에서, 스마트폰을 분실했 을 때, 핸드폰을 습득한 사람이 내 트위터에 접근하지 못하게 하기 위해서 어떻게 해 야 할까? 트위터 사이트에서 비밀번호를 바꿔도 트위터 어플리케이션은 계속 사용할 수 있다. 핸드폰을 분실 했다면, 다음과 같이 트위터 관리 페이지에서 어플리케이션 인증을 취소(revoke)하면 된다. 또한, 같은 원리로 트위터 비밀번호를 바꾸어도 내가 트위터 인증을 해놓은 수많은 어플리케이션들과 트위터 내보내기 설정해 놓은 서비스 들에서 다시 인증할 필요 없 이 그대로 사용할 수 있다. OAuth 2.0 – API 인증을 위한 만능 도구상자 OAuth 2.0은 OAuth 1.0a와 호환되지 않으며 사용 되는 용어부터 시작해서 많은 것들이 다르다. OAuth 1.0a가 만들어지고 어느 정도 지난 후에 IETF 표준이 된 반면에 OAuth 2.0은 거의 초기부터 IETF 표준 프 로세스 안에서 만들어지고 있다. OAuth 2.0의 첫 번
  166. 169 OAuth2 Open API 인증을 위한 만능 도구상자 째 draft가

    등록된 것은 2010년 4월 이었고, OAuth 1.0a에서 불편하다고 느꼈던 모 바일에서의 사용성 문제나 signature 생성과 같은 개발이 복잡하고 CPU를 많이 소 비하는 기능의 단순화, 기능과 규모의 확장성 등을 지원하기 위해 만들어 졌다. 그러 기 위해 표준이 매우 커지고 복잡해 졌는데, 이것은 OAuth 1.0a 표준의 정식 명칭이 “OAuth 1.0 프로토콜(The OAuth 1.0 Protocol)“ 인데 반해 OAuth 2.0의 정식 명칙 이 “OAuth 인증 프레임웍(The OAuth 2.0 Authorization Framework)” 인 것을 봐도 알 수 있다. 또한 OAuth 1.0은 하나의 RFC문서로 되어있지만, OAuth 2.0은 여러 개 의 표준으로 작업이 이루어지고 있으며 그 표준들은 http://tools.ietf.org/wg/oauth/ 에서 확인 할 수 있다. OAuth 1.0a가 인증을 위한 만능 칼이라면, OAuth 2.0은 인증 을 위한 도구상자라고 할 수 있다. 다만 그 안에는 몇몇 위험한 도구들이 섞여있으니 검증된 도구만을 사용해야 하는데 그 안에 무엇이 있는지 알아보자. OAuth 2.0이 1.0a에서 개선된 부분을 정리해보자 • 간단해 졌다. OAuth 1.0a에서는 https 가 필수가 아니었기 때문에 API를 호출할 때 signature를 생성해서 호출해야 했다. 때 문에 OAuth 1.0a API를 테스트 하려면 curl등을 사용하기 힘들고 별도의 API 콘솔등을 사용해서 테스트 해야 했다. OAuth 2.0의 Bearer 토큰 인증 방식을 쓰면 더 이상 signature 가 필요 없기 때문에 API를 테스트하거나 예제를 만들 때 간단하게 curl 등 직관적인 방법을 사용해서 문서화하고 개발할 수 있게 되었다. • 더 많은 인증 방법을 지원 OAuth 1.0a는 한가지 인증 방식을 제공한다. HMAC을 이용한 암호화 인증 방식이다. 하지만 OAuth 2.0은 시 나리오별로 여러가지 인증 방식을 제공하기 때문에 웹브라우저, 모바일 등의 다양한 시나리오에 대응할 수 있게 해준다. • 대형 서비스로의 확장성 지원 커다란 서비스를 만들기 위해서는 인증 서버를 분리할 수 있어야 하고 또한 인증 서버를 다중화 할 수 있어야 한 다. OAuth 2.0에서는 실제 API 서비스를 하는 서버와 인증 역할을 하는 authorization server의 역할을 명확히 구분함으로서 인증서버의 분리와 다중화 등에 대한 고려가 되어있다. 또한 OAuth 1.0a에서는 사용자(user), 써드파티 어플리케이션(consumer), API 서버 (service provider)로 불리우던 것이 OAuth 2.0에서는 용어도 바뀌었다. • Resource Owner : 사용자 • Resource Server : API 서버 • Authorization Server : 인증서버 (API 서버와 같을 수도 있음) • Client : 써드파티 어플리케이션
  167. 170 H3 개발자 컨퍼런스 2012 OAuth 2.0 spec 구성 위

    홈페이지에서도 볼 수 있지만, 현재 OAuth는 oauth-v2와 oauth-v2-bearer 라 는 2개의 표준이 가장 핵심적인 부분이며 현재 RFC에 등록되기 위한 과정을 밟고 있 는 중이다. 대부분 “OAuth 2.0 지원”이라고 하는 서비스들은 이 2가지 spec을 지원 한 다는 것을 의미한다. 이 외에도 SAML, JSON 웹 토큰, MAC 토큰 등의 방식이 있 지만 아직 활발히 수정 중 이기 때문에 실제 서비스에서 사용되고 있지는 않다. OAuth 2.0의 버전들 API 서비스를 일찍 시작한 회사들은 기존의 OAuth 1.0a를 계속 유지하는 경우도 많 이 있다. 1.0a와 2.0을 사용하는 유명한 서비스들은 다음과 같다. OAuth 2.0의 최종 버전이 나오는데 오래 걸리고 있기 때문에 Facebook, Google 등 은 OAuth 2.0 spec의 draft 버전이 올라가면서 그 개선사항들을 구현해 오고있다. 현 재 최신 draft는 31버전인데 주요 서비스들이 구현하고 있는 버전들은 다음과 같다. 서비스 draft 출처 Google 22 https://developers.google.com/accounts/docs/OAuth2 Facebook 12 http://developers.facebook.com/docs/authentication/ SalesForce 10 http://wiki.developerforce.com/page/Digging_Deeper_into_OAuth_2.0_ on_Force.com
  168. 171 OAuth2 Open API 인증을 위한 만능 도구상자 위 버전들은

    서비스가 제공하는 OAuth 인증 페이지에서 수집한 것들이다. 보통 OAuth 2.0 spec의 draft 10 ~ 22 정도를 많이 구현하였는데 중요한 변경사항은 다 음과 같은 것이 있다. • HTTP 헤더 앞 부분에 bearer 토큰을 보내기 전에 “OAuth” 에서 “Bearer”로 수정 • “oauth_token” 이름이 “access_token”으로 변경 위 변경사항 때문에 아직까지는 두 가지를 모두 받아들이는 서비스들이 많다. RFC로 확정이 되면 더 이상은 변경이 불가능 하기 때문에 최종 안으로 정리가 될 것이다. 다양한 인증 방식 (Grant types) 앞에서 OAuth 1.0a가 동작하기 위해서는 사용자, 컨슈머, 서비스 프로바이더가 필요 하고 3-legged OAuth 라고 불리우기도 한다고 하였지만, OAuth 2.0은 2-legged 모델 등 다양한 인증 방식을 지원한다. 3-legged 모델의 장점은 최종 사용자 뿐 아니 라 개발자가 누구인지도 인증하기 때문에 어떤 어플리케이션이 API를 사용하는지 통 계/과금을 위한 필수적인 정보를 얻을 수 있다는 점이다. user-agent 나 referer 같 이 변경될 수 있는 값이 아닌 인증을 통해 확실하게 구분할 수 있기 때문에 개발자 가 API를 비정상적으로 호출하고 있다거나 할 때 개발자와 직접 연락하는 등의 조치 를 취할 수도 있다. 그럼에도 불구하고 리다이렉트와 같은 OAuth에서 필요로하는 동 작이 불가능한 시나리오, 둘이서만 인증하는 시나리오 등을 지원하기 위해 OAuth 2.0은 2-legged 모델도 지원하나, 그래도 OAuth 2.0에서 가장 기본이 되는 것은 3-legged 모델이다. Client는 기본적으로 Confidential Client와 Public Client로 나뉜다. •  Confidential 클라이언트는 웹 서버가 API를 호출하는 경우 등과 같이 client 증명서(client_secret)를 안전하게 보관할 수 있는 Client를 의미한다. •  Public Client는 브라우저기반 어플리케이션이나 모바일 어플리케이션 같이 client 증명서를 안전하게 보관할 수 없는 Client를 의미하는데 이런 경우 redirect_uri를 통해서 client를 인증한다. OAuth 2.0이 지원하는 인증방식은 client 종류와 시나리오에 따라 다음의 4가지가 있 다. 하지만 실제로 Authorization Code Grant와 Implicit Grant를 제외하고는 일반적 인 3-legged OAuth 가 아니기 때문에 open API에서는 많이 사용되지 않는다.
  169. 172 H3 개발자 컨퍼런스 2012 1. Authorization Code Grant 웹

    서버에서 API를 호출하는 등의 시나리오에서 Confidential Client가 사용하는 방식이다. 서버사이드 코드가 필 요한 인증 방식이며 인증 과정에서 client_secret이 필요하다. 로그인시에 페이지 URL에 response_type=code 라고 넘긴다. 2. Implicit Grant token과 scope에 대한 스펙 등은 다르지만 OAuth 1.0a과 가장 비슷한 인증방식이다. Public Client인 브라우저 기반 의 어플리케이션(Javascript application)이나 모바일 어플리케이션에서 이 방식을 사용하면 된다. Client 증명 서를 사용할 필요가 없으며 실제로 OAuth 2.0에서 가장 많이 사용되는 방식이다. 로그인시에 페이지 URL에 response_type=token이라고 넘긴다. 3. Password Credentials Grant 이 방식은 2-legged 방식의 인증이다. Client에 아이디/패스워드를 저장해 놓고 아이디/패스워드 로 직접 access token을 받아오는 방식이다. Client를 믿을 수 없을 때에는 사용하기에 위험하기 때 문에 API 서비스의 공식 어플리케이션이나 믿을 수 있는 Client에 한해서만 사용하는 것을 추천한다. 로그인시에 API에 POST로 grant_type=password 라고 넘긴다. 4. Client Credentials Grant 어플리케이션 이 Confidential Client일 때 id와 secret을 가지고 인증하는 방식이다. 로그인시에 API에 POST 로 grant_type=client_credentials 라고 넘긴다. 5. Extension OAuth 2.0은 추가적인 인증방식을 적용할 수 있는 길을 열어놓았다. 이런 과도한 확장성을 메인 에디터인 Eran Hammer는 매우 싫어했다고 한다. Password Credentials Grant와 Client Credentials Grant는 기본적으로 우리가 생각 하는 OAuth 의 프로세스를 따르지 않기 때문에 반드시 인증된 client에만 사용되어야 하며 가능하면 사용하지 않는 것이 좋다. 다양한 토큰 지원(Access token) OAuth 2.0은 기본적으로 Bearer 토큰, 즉 암호화하지 않은 그냥 토큰을 주고받는 것 으로 인증을 한다. 기본적으로 HTTPS를 사용하기 때문에 토큰을 안전하게 주고받는 것은 HTTPS의 암호화에 의존한다. 또한 복잡한 signature 등을 생성할 필요가 없기 때문에 curl이 API를 호출할 때 간단하게 Header에 다음과 같이 한 줄을 같이 보내므 로서 API를 테스트해 볼 수 있다. Authorization: Bearer <Bearer token>
  170. 173 OAuth2 Open API 인증을 위한 만능 도구상자 또한 OAuth

    2.0은 MAC 토큰과 SAML 형식의 토큰을 지원할 수 있지만 현재 MAC 토큰 스펙은 업데이트 되지 않아 기한 만료된 상태이고 SAML 토큰 형식도 아직은 활 발하게 수정중이기 때문에 사용할 수 없는 상태이다. 정리하자면, OAuth 2.0은 다양 한 토큰 타입을 지원한지만 실질적으로는 Bearer 토큰 타입만 지원한다. Refresh token 시간이 많이 주어지면 access token은 결국은 읽을 수 있는 확률이 높아진다. 그래 서 OAuth 2.0에서는 refresh token이라는 개념을 도입했다. 즉, 인증 토큰(access token)의 만료기간을 가능한 짧게 하고 만료가 되면 refresh token으로 access token 을 새로 갱신하는 방법이다. 이 방법은 개발자들 사이에서는 논란이 있는데, 토큰의 상태를 관리해야 해서 개발이 복잡해 질 뿐만 아니라 토큰이 만료되면 다시 로그인 하 도록 하는 것이 보안 면에서도 안전하다는 의견이 있기 때문이다. API 권한 제어 (scope) 클라이언트가 같은 access token을 오래 사용하면 결국은 해킹에 노출될 위험이 높 아진다. scope의 이름이 스펙에 정의되어있지는 않으며 여러 개의 권한을 요청할 때 에는 콤마등을 사용해서 로그인 시에 scope를 넘겨주게 된다. http://example.com/oauth?....&scope=read_article,update_profile OAuth 2.0은 위험한가? Eran Hammer가 OAuth 2.0가 형편없다고하며 자신의 블로그에서 제시한 이유는 OAuth 2.0이 너무 복잡하고 안전하지 않다는 점이다. 그는 자신의 블로그에 이렇게 된 이유를 설명하고 있다. OAuth 2.0 스펙에 참가한 사람들은 주로 웹 커뮤니티 멤버 들과 대형 기업멤버들로 되어있었다. 웹 관련 멤버들은 OAuth 1.0a와 비슷하되 단점 을 개선한 버전을 만들기를 원하는데 반해, 기업 쪽 사람들은 OAuth 2.0을 자신의 솔 루션을 위한 인증 framework으로 사용할 수 있도록 유도하며 OAuth 2.0을 너무 복잡 하게 만들었고 또 거의 무한한 확장성을 가질 수 있게 하면서 거의 모든 것에 ‘OAuth
  171. 174 H3 개발자 컨퍼런스 2012 2.0 호환’ 딱지를 붙일 수

    있게 되었다는 것이다. 그는 OAuth 2.0이 더 간결하고 제한 된 스펙이 되기를 원했다. 실제 블로그에서는 “OAuth 1.5 정도의 내용을 가진 새로운 OAuth 2.1이 10page 정도의 짧은 문서로 새로 나왔으면 좋겠다” 라고 했다. 그가 블로그 글에서 지적한 OAuth 2.0의 문제점은 어떤 것들 일까? •  OAuth 1.0a에서는 token 과 함께 token 비밀번호를 같이 받는데 2.0에서는 이 토큰 비밀번호가 없어져서 실제 로 클라이언트를 구분하기가 힘들어 졌다. •  OAuth 1.0a의 signature 기능을 없애서 SSL 기능에 의존함으로서 더 위험해졌다. 또한 이렇게 된 것은 기업 솔 루션에 적용 되기위한 것이었다. •  OAuth 2.0에서 토큰 유효기간을 설정 할 수 있고 또 만료가 되면 갱신 되어야 한다. 이 변화는 OAuth 1.0 개발 자들이 토큰 상태까지 관리해야 한다는 점에서 매우 커다란 변화이다. 이 기능은 자체적으로 인코딩 되어서 저장 되는 토큰을 위한 것인데 이런 토큰은 권한을 취소(revoke) 하는데에 문제가 있기 때문에 또 다시 유효기간을 짧 게 가져가게 된다. • 권한 부여 방식 OAuth 2.0에서는 너무 많은 방식을 지원 하고있다. 이는 여러 보안상의 문제점의 가능성을 의미한다. 또한 OAuth 2.0을 IETF에서 시작한 것을 후회하는 말도 하면서, 그렇다고 딱히 다른 대안이 있는 것도 아니라는 의견도 밝힌다. 현재 워킹 그룹이 합의를 하지 못하고 있 는 사항들에 리스트도 적었는데, 그만큼 OAuth 2.0스펙이 너무 포괄적이며 스펙은 더 많은 제한을 가지고 있고 많은 것이 결정되어있어야 한다는 이야기라고 그는 계속 주장 한다 위 글에 대한 반박 글은 참 많지만 그 중에 유명한 것은 아래 2개이다. • In Defense of OAuth 2.0 http://blog.programmableweb.com/2012/08/30/in-defense-of-oauth-2-0/ • The OAuth 2 Sky is NOT Falling http://www.thread-safe.com/2012/07/the-oauth-2-sky-is-not-falling.html 위 글에서는 OAuth 2.0의 장점들과 실질적으로는 OAuth 2.0 워킹 그룹이 잘 해나가 고 있다는 내용의 글들이다. Eran Hammer는자기 자신의 첫 번째 글이 커다란 반향을 일으키자, 내용을 어느 정도 개선한 두번째 글을 쓰기도 했다. 이 글에서 몇몇 OAuth 2.0을 잘 받아들인 단체들을 언급하면서, Facebook이나 Google은 OAuth 2.0이 직 접 내렸어야 하지만 내리지 못한 결정들을 직접 내리고 OAuth 2.0을 성공적으로 구 현했다고 이야기 하고있다. 하지만 그는 자신의 신념에는 변화가 없다는 뜻을 다시 한
  172. 175 OAuth2 Open API 인증을 위한 만능 도구상자 번 비추었다.

    즉 OAuth 2.0이 명확하게 정의하지 않을 부분을 잘 구현한다면 OAuth 2.0은 꽤 쓸만한 표준이나, Eran Hammer는 현재의 OAuth 2.0은 너무 많은 부분들 을 허용하고 있고 복잡하기 때문에 안전하지 않다고 주장한 것이다. 정리하자면, 가장 많이 사용되는 Grant type인 Authorization Code 방식이나 Implicit 방식을 사용하고 access token으로서는 Bearer 토큰을 사용하며 HTTPS를 통해 서 서비스하고 널리 사용되는 라이브러리들을 사용해서 구현한다면 OAuth 2.0은 안전하다고 할 수 있다. 다만 아직 표준 진행중인 토큰 방식을 사용하거나 자신만의 Extension을 정의해서 사용하는 경우도 OAuth 2.0이라고 부를 수는 있지만 아직은 안전하지 않다고 할 수 있다. OAuth 2.0에 대한 예상질문 이상 OAuth 2.0에 대해서 알아보았다. 마지막으로 간단한 몇 가지 사항을 짚어보자 1. SSL을 사용하지 않는 bearer 토큰은 안전하지 않나? 안전하지 않다. MAC token을 사용할 수 있지만 OAuth 2.0에서는 실질적으로 관리되고 있지 않은 스펙이다. OAuth 2.0을 이용한 API 호출에는 반드시 HTTPS를 사용해야 한다. 2. API를 서비스하는데 HTTPS를 쓸 수 없는 상황이다. 어떻게 해야 하는가? 그런 경우라면 현 시점에서는 OAuth 1.0a를 사용하는 것이 최선이다. 아직 OAuth 2.0 스펙은 자체 암호화를 지 원하지 않는다. 3. OAuth 2.0의 대안이 있는가? 의미있는 대안은 현재 없다. Facebook, Google 등이 모두 API 인증방식으로OAuth 2.0을 채택했기 때문에 대 세는 이미 OAuth 2.0이다. 4. API 사용자를 생성하는 좋은 방법은? 이 이슈는 API의 고전적인 이슈 중 하나이다. API인증을 하기위한 사용자를 생성하는 API는 어떻게 인증해야 하 는가에 대한 이야기 이다. API를 사용해서 사용자를 생성한다면, CAPCHA 등의 방법을 사용할 수 없기 때문이 다. 보통 다양한 조건체크, email 확인 등의 방법을 사용하기도 하지만, 가능하면 사용자 추가는 그냥 웹 브라우저 상에서 직접 하도록 하는 것이 정답이다.
  173. 176 H3 개발자 컨퍼런스 2012 마무리 하며 암호 기술과 함께

    인터넷상에서 인증 관련 기술들은 매우 빠르게 발전하고 있다. 최근 에는 SHA-3 해쉬 알고리즘이 기나긴 선정과정을 걸쳐 최종 선정되는 커다란 뉴스가 있었고API인증에 있어서도 OAuth 2.0 뿐만 아니라 openid 진영의OpenID Connect 도 활발히 활동하고 있다. 많은 우여곡절 속에서 OAuth 2.0 spec은 최종안을 위해서 달려가고 있는데 예상보다 많은 시간이 걸리고 있고 또 잡음이 있다는 것은 그만큼 많 은 사람들과 기업들에게 OAuth 2.0가 중요하고 많은 기대를 하고 있다는 것을 말해 준다. OAuth 2.0의 기본 스펙은 안전하다. 다만 스펙에 참여하고 있는 일부 기업들의 욕 심으로 생긴 일부 추가적인 기능들과 방향성에 논란이 있는 상황이다. 이슈가 되는 Refresh 토큰이나 추가기능을 제공하는 extension, 그리고 아직 RFC 단계에 있지 않 은 스펙 들 때문에 OAuth 2.0전체가 안전하지 않다고 할 수는 없다. HTTP 1.1스펙 의 PATCH 나 HEAD 메소드는 거의 사용되지 않지만 그렇다고 HTTP 1.1 의 GET/ POST 메소드 까지 버릴 수는 없지 않을까? AES나 SHA-3 등과 같은 암호화 알고리즘이 NIST같은 미국 정부기관의 주도로 정 해지는 것과 달리 OAuth는 IETF의 열린 프로세스에 따라서 스펙이 결정되고 메일링 리스트를 통해서 주로 토론이 이루어진다. 이 글을 쓰면서 인터넷 실명제 위헌 판결에 따라서 개인 인증에 대한 중요성이 부각되고 있는 우리나라에서 인터넷에서의 주민번 호 대체품으로서 한국 정부가 OAuth 프로바이더를 만드는 것은 어떨까 하는 상상도 해보았다. 더 많은 사람들이 OAuth 2.0등의 열린 인증방법에 관심을 가지고 더 많은 자료들이 API를 통해 공개되고, 또 안전하게 접근할 수 있는 날이 오기를 기대해 본다.
  174. 177 OAuth2 Open API 인증을 위한 만능 도구상자 참고자료 OAuth

    2 - OAuth 2 공식 홈페이지 http://oauth.net/2/ IETF OAuth 2 spec http://tools.ietf.org/html/draft-ietf-oauth-v2 위 링크로 가면 가장 최신의 draft로 연결됨 OAuth 2.0 and the Road to Hell (2012.7.26) http://hueniverse.com/2012/07/oauth-2-0-and-the-road-to-hell/ 모든 사건의 시작이된 OAuth 2.0 editor Eran Hammer의 폭탄선언 On Leaving OAuth (2012.7.30) http://hueniverse.com/2012/07/on-leaving-oauth/ 윗 글의 후속 글 In Defense of OAuth 2.0 http://blog.programmableweb.com/2012/08/30/in-defense-of-oauth-2-0/ The OAuth 2 Sky is NOT Falling http://www.thread-safe.com/2012/07/the-oauth-2-sky-is-not-falling.html An Introduction to OAuth 2 http://www.slideshare.net/aaronpk/an-introduction-to-oauth-2 OSCON 2012 발표자료 OAuth 2 Simplified http://aaronparecki.com/2012/211/article/1/oauth2-simplified IETF OAuth Word Group 메일링 리스트 https://www.ietf.org/mailman/listinfo/oauth
  175. 178 H3 개발자 컨퍼런스 2012 이번 섹션은 “대박 어플의 비밀”입니다.

    다음 내용은 2009년 11월 아이폰 국내 출시 시점부터 지금까지 “모바일 서비스의 성공”이라는 궁극적인 목표를 가지고 진행되어 온 다양한 관찰조사, 설문조사, 실험조사에 대한 결과와 그 결과를 통해 알게 된 노하 우로 작성 되었습니다. “대박 어플”의 정의가 무엇인지? 서비스마다 사람마다 다르겠지만, 다음 내용은 “대박 어플”의 원초적인 지표인 “대량의 어플 설치(다운로드)”로 정의 하였습니다. 기획/디자인/개발자 모두 알아야 하는 대박앱의 비밀 CVI팀 김일화 [email protected]
  176. 179 기획/디자인/개발자 모두 알아야 하는 대박앱의 비밀 대량의 어플을 이용자

    들에게 설치 시키기 위해서는 어떻게 해야 할까?에 대한 비밀은 우연히 주변 지인들이 앱스토어/플레이마켓를 이용하면서 공통 된 이용행태가 발견되 면서부터 시작되었고, 이 후 스마트폰 이용자를 대상으로 그 공통점을 검증하는 단계 에서 구체화 되었습니다. 이 과정을 반복 진행하면서 대박어플의 비밀을 알아내는 “방 법론”이 완성되었고, 그 방법론은 다음과 같습니다. “대박어플 비밀”을 알아내는 방법론 • 이용자가 어플을 설치할 때 어떤 이동 경로와 행동 패턴을 보이는지? 파악! • 이용자의 이동 경로 및 행동 패턴 중에서 우리가 컨트롤 할 수 있는 부분이 있는지 파악! • 우리가 컨트롤 했을 때 이용자의 행동 변화가 예상되는 부분이 있는지 파악! • 파악된 부분에서 고객이 어플을 설치 하게끔 유도하고 피드백을 통해 개선을 반복! 즉, 대박 어플의 비밀은 한마디로 이용자의 길목을 지키는 방법으로 우리는 이 방법론 을 “골목대장 방법론” 이라 부릅니다. “골목대장 방법론”의 핵심은 서비스 이용자를 세 밀하게 관찰하는 것이고, 만약 “골목대장 방법론”을 충분히 이해 했다면 대박 어플 뿐 아니라, ‘대박 치킨집’, ‘대박 순대집’, ‘대박 김밥집’, ‘대박 떡볶이집’에도 충분히 적용 가능한 방법론입니다. 아이폰 어플은 ”인기25”, 안드로이드 어플은 “인기무료애플리케이션” 메뉴 상위에 랭크 되어야 함 그렇다면 이용자들이 어플 설치 시 어떤 공통 된 행동패턴과 동선이 있는지 파악하기 위해 애플 앱스토어/플레이마켓을 이용하는 5,983명을 대상으로 다음과 같은 질문을 해 보았습니다. “[질문]어플 설치를 위해 가장 많이 방문하는 메뉴는 어디인가요?” 그 결과 다음 그림[1~2]에서와 같이 어플 설치를 위해 가장 많이 찾는 메뉴가 아이폰 인 경우 “인기25”이고 플레이마켓인 경우는 “인기무료어플리케이션”이라고 답했고, 이 조사는 2012년 분기별로 2차례 진행 했었는데 그 결과가 크게 다르지 않았습니다.
  177. 180 H3 개발자 컨퍼런스 2012 [그림1] 아이튠스 앱스토어에서 어플설치시 가장

    많이 찾는 메뉴는 “인기25” [그림2] 안드로이드 마켓에서 가장 많이 찾는 메뉴는 “인기 무료 어플리케이션” 즉, 어플 설치를 위한 앱스토어 이용자의 길목은 “인기25”, 플레이마켓 이용자의 길목 은 “인기무료애플리케이션”이라는 것을 확인 하였습니다. 따라서, 우리는 최선을 다해 “인기25”, ”인기무료애플리케이션” 메뉴에 랭크 되어야 합니다. 그러나 매일 매일 쏟 아지는 신규 어플과 이미 엄청난 사랑을 받고 있는 메이저 어플들이 상위에 포진되어 있으므로, 상위순위가 되고 싶다고 해서 쉽게 될 수 있는 상황은 절대 아닙니다. 그런 데 다행히도 출시되는 모든 어플에게 공평하게 제공되는 순위상승의 기회가 딱! 한번 있는데, 그 시점이 언제인지 알아 보겠습니다.
  178. 181 기획/디자인/개발자 모두 알아야 하는 대박앱의 비밀 순위상승의 기회는 출시

    당일이며 출시 전 마케팅이 준비되어 있지 않다면 어플 등록을 연기하라 앱스토어와 플레이마켓에서 출시되는 모든 어플에게 공평하게 주어지는 순위상승의 기회가 언제인지? 알아보기 위해, 2012년 상반기 앱스토어에서 1위한 어플을 대상으 로 최초 순위진입 후 +50일 동안 순위변화 추이를 알아 보았습니다. [그림3] 1위 어플은 대부분 첫 1~3일안에 1위에 도달한다. 그 결과 [그림3]의 A박스에서 보는 것과 같이 1위를 하는 어플들은 대부분 랭킹진입 직후 최소 1~3일안에 대부분 1위에 도달했다는 것을 알 수 있고, 출시와 동시에 이렇 게 상위권에 랭크 된 이유는 드라마틱한 마케팅의 효과가 아니라, 이미 앱스토어에서 제공하는 “신규어플” 소개 란에 노출되었기 때문이고, 이는 플레이마켓도 동일한 패턴 을 가진다는 것을 알 수 있었습니다. 즉, 신규 어플 소개 공간은 출시되는 모든 어플에게 공평하게 부여되는 홍보의 공간이 며, 무료로 제공되는 절호의 순위 상승기회이므로 절대 놓쳐선 안 됩니다. 이 시점에 만약 나의 어플이 너무나도 뛰어나서 스스로의 힘으로 1위를 하면 가장 좋겠지만, 그 렇지 않다면 출시 초기인 바로 이 시점에 마케팅을 통해 나의 어플의 순위 상승에 힘 을 보태줘야 합니다. 만약 출시 전에 힘을 보태 줄 마케팅이 준비되어 있지 않다면, 몇 개월 동안 준비한 어플을 출시 후 몇 일 만에 사장될 가능성이 아주 높습니다. 따라서, 마케팅이 준비되어 있지 않다면 차리리 어플 등록을 연기하는 것이 더욱 바람직하다 는 것을 꼭 기억하셔야 합니다.
  179. 182 H3 개발자 컨퍼런스 2012 어플의 수명은 출시 후 +30일이며,

    상위순위 유지를 통해 선 순환구조를 만들어야 한다. 어플 출시 직후도 중요하지만 어플 출시 후 초기 운영도 상당히 중요합니다. 그 이유 는 [그림3]에서 보듯이 잘 나간다는 1위 어플들만 모아 놓은 순위변화 그래프임에도 불구하고 한 번 순위가 떨어진 후 다시 상위(상위의 기준은 앱스토어 첫 화면에 보이 는 25위를 기준으로 함)순위로 재 진입하는 경우가 “D”어플과 같이 극소수 밖에 없기 때문입니다. 또한, [그림3]의 “C”시점에서 보듯이 잘 나가는 1위 어플들도 출시 후 +30일을 기점 으로 거의 대부분의 어플들이 순위가 떨어졌거나 하락 추세임을 확인할 수 있는데, 유 선 웹 서비스와 달리 어플의 라이프사이클이 짧다는 것을 단적으로 보여주는 그래프 입니다 혹시, 어플 오픈을 위해 몇 일간 밤을 샜기 때문에 오픈과 동시에 샴페인을 터트리고, 한 일주일 정도 쉰 다음, 그 다음 일주일에 마케팅/프로모션 계획을 세우고, 그 다음 일주일에 이벤트 페이지 디자인/개발을 하고, 그 다음 주에 이벤트 페이지를 오픈 할 예정이다.라고 계획하고 있다면 지금까지 몇 개월 동안 고생해서 만든 그 어플은 이미 수명을 다 한 후이며, 이용자의 기억 속에서 사라진 다음일 수 있습니다. 따라서 어플 제작 프로젝트를 진행하고 있다면 그 프로젝트의 종료 시점이 어플의 앱스토어/플레 이마켓에 노출되는 시점이 아니라, 최소한 어플 출시 후 +30일까지라는 것을 명심해 야 합니다. [그림3]에서 “B”의 화살표를 보면 1~25위보다 26~50위까지의 화살표 기울기가 급 하게 꺾이고, 26~50위보다 51~75위까지 화살표의 기울기가 급하게 꺾인 것을 확인 할 수 있는데, 상위순위에 랭크 되어 있는 어플보다 하위순위에 랭크되어 있는 어플의 순위 하락속도가 급하다는 것을 확인할 수 있습니다. 즉 순위가 떨어지면 떨어질수록 가속도가 붙는다는 의미입니다. 여기에서 초기에 나의 어플이 상위에 노출되어야 하는 이유가 있는데, 어플이 상위 순 위에 랭크 될 수록, 이용자에게 어플이 더 많이 노출되고, 어플이 더 많이 노출되면, 더 많은 설치가 일어나고, 더 많은 설치가 일어나면 다시 상위 순위에 랭크 되는 선 순 환 구조가 완성되기 때문에 상위 유지가 중요합니다. 상위 순위에서 1등을 계속하면 좋겠지만 그렇지 못하다면 도대체 몇 위까지가 순위 방어에 의미가 있는지? 알아 보겠 습니다.
  180. 183 기획/디자인/개발자 모두 알아야 하는 대박앱의 비밀 필사적인 어플 순위

    관리는 25위까지이며 실패할 경우 75위까지 최선을 다해야 한다 [그림3] “E”박스에서 어플의 순위하락 패턴을 보면 75위가 넘어가면 100위든, 125위 든, 150위든…거의 동일한 기울기로 순위가 떨어진다는 것을 확인할 수 있는데, 그 기 울기가 의미하는 바는 이용자가 앱스토어에서 어플을 설치할 때 다음페이지 즉, More 를 3번만 Tab을 한다는 것을 의미 합니다. 그 이유는 앱스토어에서는 어플이 한 페이지에 25개가 노출되고, 75위를 보려면 More를 3번 눌러야 하기 때문입니다. 따라서 76위부터 나타나는 동일 기울기의 순위 하락곡선은 더 이상 이용자들이 More를 눌러 보지 않아 생기는 현상으로 볼 수 있습 니다. 따라서, 우리는 첫 페이지인 25위 랭킹 방어선이 무너졌을 경우 최소 3페이지 (75위)내에 어플을 유지시켜야 이용자의 최소한의 동선 안에 함께 있는 수 있습니다. 단, 위와 같은 25위와 75위의 의미는 현재 iOS5에서 유 의미 하지만, 현재 개발자버 전으로 배포된 iOS6에서는 More를 Tab하지 않아도 다음 순위를 볼 수 있는 Swipe UI방식을 채택하고 있어, iOS6과 플레이마켓에서는 25위, 75위가 가지는 의미는 조 금 퇴색될 수 있으나, 다음 페이지를 보기 위해 이용자가 Tab을 하던? Swipe을 하던? 중요한 것은 순위가 하위로 갈수록 떨어지는 데 가속도가 붙는다는 것이므로, 이용자 의 다운로드 동선 내에 있기 위해서 노력해야 한다는 점은 변하지 않습니다. 다운로드에 가장 중요한 요소는 스크린샷과 리뷰 지금까지 이용자들이 가장 많이 방문하는 메뉴의 길목과, 순위의 길목에 대해 알아 보 았습니다. 이제는 이용자가 앱스토어/플레이마켓를 Tab한 이후부터 어플 설치 바로 직전까지의 동선에 대한 관찰 조사결과를 설명 드리겠습니다. 조사의 목적은 어플 설치를 위해 이용자들이 어떤 행동을 하는지 파악하고, 그 행동 패턴 중에 우리가 컨트롤 할 수 있는 길목이 없는지? 확인하기 위해서입니다. [그림4]는 아이폰을 사용하는 남/여를 대상으로 다음과 같은 미션을 제시하고 관찰조 사를 진행해본 이미지입니다. 이용자에게는 [미션]”앱스토어에서 본인이 원하는 어플 을 다운로드 해 보세요”라는 미션이 주어졌고, 관찰조사 영상은 [그림4]에 있는 QR 또 는 URL을 통해 확인하실 수 있습니다.
  181. 184 H3 개발자 컨퍼런스 2012 남자 아이폰 이용자 여성 아이폰

    이용자 http://bit.ly/PfJogq http://bit.ly/NJux21 [그림4] 남녀 아이폰 이용자의 앱스토어 이용행태 관찰조사 위 관찰조사를 [그림5]와 같이 이용자가 시선이 머문 시간(“=초)으로 기재해 보았는 데, 그 결과 실험자가 어플을 설치하기 위해 가장 오랫동안 시선이 머문 순서대로 나 열하면 “⑥스크린샷(8초)”, “③랭킹리스트(6초)”이고, “⑧리뷰(6초)”로 나타났다. “③랭킹리스트(6초)”는 한 개의 어플을 보는데 사용한 시간이 아니라 여러 개의 어플 을 스캔 하는데 사용한 시간이기 때문에 실제 어플 설치에 가장 많은 시간을 할애한 요소는 “⑥스크린샷(8초)”과 “⑧리뷰(6초)”라고 볼 수 있다. 따라서, 이번 이용자의 어플 설치패턴에서는 “스크린샷”과 “리뷰”가 우리가 지켜야 하는 길목임을 확인 할 수 있다. [그림5] 남녀 아이폰 이용자의 앱스토어 이용행태별 시간추적
  182. 185 기획/디자인/개발자 모두 알아야 하는 대박앱의 비밀 모든 유료어플은 어플

    내 구매방식으로 개발되어야 한다. [그림5]의 결과를 기반으로 좀 더 자세한 검증을 위해 [그림6~7]과 같이 실제 총 5,983명(아이폰 4,088명+ 안드로이드폰2,027명)을 대상으로 “어플 설치 시 가장 중 요하다고 생각하는 3가지를 선택해 주세요?”라고 설문조사를 진행한 결과 앱스토어, 플레이마켓 모두 1위가 “유/무료”이고, 2위가 “리뷰”로 관찰조사와 유사한 결과가 나 왔습니다. [그림6~7]설문조사 결과에서 보듯이 어플 설치에 가장 많이 영향을 미치는 요소가 역 시 돈과 관련된 “유/무료”로 나타났는데, 만약 현재 유료 어플을 기획 또는 운영하고 계시다면 비록 메모리릭의 압박과 개발의 복잡함이 있다 할 지라도 어플은 무료로 출 시하고, 앱스토어는 In-app-Purchases, 플레이마켓은 In-app Products방식을 통 해 유료화를 고민해야 이용자에게 선택 받을 기회가 높아집니다. [그림6] 앱스토어 어플설치 시 영향을 미치는 요인 3가지
  183. 186 H3 개발자 컨퍼런스 2012 [그림7] 플레이마켓에서 어플설치 시 영향을

    미치는 요인 3가지 나의 서비스에서 가장 행복한 시점에 이용자에게 리뷰를 요청해라 [그림6~7]에서 어플 다운로드에 영향을 미치는 두 번째 요인은 “리뷰”인데 리뷰의 길 목을 지키기위해 흔히 생각하는 첫 번째 방법은 지인을 동원하여 긍정적인 리뷰와 별 5개를 강요하는 것이고, 두 번째 방법은 리뷰를 달면 선물을 주는 이벤트를 진행하는 것입니다. 그런데 이 모든 활동들은 아주 단기적이고 비용이 많이 발생하는 방법이라 는 것을 한번이라도 진행 해 보신 분들은 모두 체감 하였을 것입니다. 따라서, 리뷰의 길목에서 장기적이고 긍정적인 리뷰를 획득하기 위해서는 긍정적인 리뷰를 달 수 밖에 없는 상황을 [그림8~9]와 같이 이용자에게 만들어야 합니다.
  184. 187 기획/디자인/개발자 모두 알아야 하는 대박앱의 비밀 [그림8] 푸딩얼굴인식 리뷰요청

    PUSH [그림9] Boom! 어플 리뷰요청 PUSH 그런데 이렇게 리뷰를 요청할 때 주의해야 할 점이 있는데 그것이 바로 리뷰를 요청하 는 타이밍입니다. 초급 기획자인 경우는 어플 설치와 동시에 리뷰를 요청하는 경우가 있고, 중급 기획자인 경우는 방문 횟수를 카운팅하여 X번째 방문자에게 리뷰를 요청 하는 경우가 있는 데, 이 모든 경우는 우리가 컨트롤 할 수 있는 범위 밖에 있어 부정 적인 리뷰가 등록 될 가능성이 있습니다. 그 이유는 어플 최초 실행 시 이용자가 처한 환경은 대부분 서비스를 어떻게 이용해 야 하는지? 학습을 해야하는 스트레스 상황에 놓이게 됩니다. 그 상태에서 리뷰를 요 청할 경우에는 학습에 대한 스트레스로 인해 부정적인 리뷰가 등록될 수 있기 때문입 니다. 또한 횟수를 통한 리뷰를 요청하는 방식은 이용자가 어떤 상황에 있는지? 전혀 예측이 되지 않는단점이 있습니다. 경우의 수는 아주 적겠지만 리뷰를 요청할 시점이 어플이 튕긴 직 후 일 수도 있고, 어플에서 작업했던 모든 내용이 모두 날아간 다음 실행일 수 도 있기 때문입니다. 최대한 좋은 리뷰가 필요한 우리로써는 예측할 수 없는 이용자의 상황에서 굳이 리뷰를 요청할 필요가 없습니다. 따라서 가장 좋은 리뷰요청 타이밍은 이용자가 내 어플을 이용하면서 가장 행복한 시 점이라고 예측이 가능한 시점에 리뷰를 요청해야 합니다. 예를 들어 게임 어플인 경우
  185. 188 H3 개발자 컨퍼런스 2012 Stage Clear/Level Up 또는 끝판

    대장을 넘긴 시점이고, 사진SNS인 경우는 내가 등 록한 사진이 친구들에게 ”좋아요”를 10개째 받은 시점이며, 카메라 어플인 경우는 유 료 카메라 필터를 무료로 제공한 직 후 리뷰를 요청 하는 것이 좋은 리뷰를 유지할 수 있는 비법이 되는 것입니다. 젊은 연령층은 스크린샷/미리보기를 보고 어플을 설치한다. [그림6~7]에서 어플 설치 시 영향을 미치는 요소 중 유/무료, 리뷰, 랭킹 다음으로 중 요한 항목이 앱스토어는 스크린샷, 플레이마켓은 미리보기로 확인 되는데, 이 항목에 대해서는 연령별로 확인해 보았습니다. [그림10~11]을 보면 앱스토어, 플레이마켓 모두 연령이 젊을수록 스크린샷 또는 미리보기를 보고 어플을 설치하는 경우가 많았 고, 연령이 높을수록 앱설명이 어플 설치에 큰 영향을 미치는 것으로 나타났습니다. 따라서, 만약 내가 만든 어플의 타깃 연령이 10~20대라면 몇 장 들어가지 않은 스크 린샷/미리보기에 심혈을 기울려 자신의 어플에서 가장 재미있는 시점의 스크린샷/미 리보기로 꾸며야 합니다. 만약 이렇게 중요한 스크린샷/미리보기에 의미 없는 어플 로 딩 이미지가 들어가 있다면 지금 당장 교체해야 합니다. [그림10] 앱스토어 어플 설치 시 영향요인 연령대별 분류
  186. 189 기획/디자인/개발자 모두 알아야 하는 대박앱의 비밀 [그림11] 플레이마켓 어플

    설치 시 영향요인 연령대별 분류 실제 “푸딩카메라”와 “푸딩얼굴인식”이 매년 애플에서 발표하는 올해의 어플상에 뽑혔 었는데, 그 이미지를 [그림12]와 같이 이용하여 스크릿샷에 “◀◀Rewind” 삽입한 후 다운로드 추이를 확인한 결과 해당일에 다른 프로모션/마케팅이 없었음에도 불구하고 다운로드 수가 소폭 상승했음을 볼 수 있어 효과를 확인하였습니다. 단, 주의할 점은 어플과 전혀 상관없는 마케팅 이미지를 등록할 경우에는 앱스토어에서 Reject 사유가 될 수 있으므로 수위 조절을 잘 해야 합니다. [그림12] 푸딩카메라, 푸딩얼굴인식 스크린샷 변경 후 다운로드 추이변화
  187. 190 H3 개발자 컨퍼런스 2012 어플 이름은 “이용자의 언어”로 만들어라

    [그림13]은 아이폰을 이용하는 미국인을 대상으로 어플 설치 시 자주 찾는 메뉴 (Which menu do you usually choose when you install applications through the App Store?)에 대한 설문 결과입니다. 이 결과를 한국 이용자 패턴과 겹쳐서 표시 해 보았는데, 어플 설치 시 미국이용자는 한국이용자와 달리 Search와 Categories를 더 많이 이용하는 것으로 나타났습니다. 현재 제작 또는 운영하고 있는 어플의 타깃이 글로벌 이용자라면 나의 어플이 어떻게 하면 검색에 많이 걸릴 수 있게 할까?라는 고민이 필요한 대목입니다. 만약 한국 이용 자보다 앱스토어를 더 오랫동안 경험한 미국 이용자의 이용패턴이 한국이용자의 선행 지표라고 가정한다면, 향 후 한국 이용자도 어플을 직접 찾아볼 수 있는 “검색” 메뉴를 더 많이 이용할 것으로 예상해 볼 수 있으므로 검색의 중요성이 증가할 수 있습니다. [그림13] 앱스토어 어플 설치 시 가장 많이 찾는 메뉴에 대한 한국/미국 이용자 비교 이렇게 검색이 중요한 상황으로 전개되고 있는 시점에서 검색의 길목을 다른 길목보 다 더 잘 지켜야 하는데, 혹시 나만 이해할 수 있고, 나에게만 의미 있는 어플명을 만 든다면 그 어플은 이미 대박 어플에서 한 발 물러날 수 밖에 없을 것입니다. 다시 말하자면 미국 홈페이지가 구글에 검색되지 않으면 그 홈페이지는 세상에 존재 하지 않는 것이고, 국내 홈페이지가 네이버에 검색되지 않으면 그 홈페이지는 국내에 존재하지 않는 것과 마찬가지로 어플이 앱스토어/플레이마켓에서 검색되지 않으면 그 어플은 세상에 존재하지 않는 것과 같기 때문입니다.
  188. 191 기획/디자인/개발자 모두 알아야 하는 대박앱의 비밀 따라서, 나만의 언어로

    나만이 알 수 있는 의미심장한 어플 이름을 만드는 것보다 내 어플을 필요로 하는 이용자들이 내 어플을 찾기 위해 어떤 검색어를 입력할 것인지? 고민하고 이용자들이 평소 쉽게 사용하는 언어로 어플명을 만든 후 앱스토어/플레이 마켓에서의 검색결과에 내 어플이 검색될 수 있게 만들어야 합니다. 이 과정에서 비로 소 내 어플이 세상에 존재하게 되는 것입니다. 그렇다면 앱스토어/플레이마켓에서 다른 어플 보다 내 어플이 잘 검색 되게 하는 방법 이 모엇일까? 라는 문제를 가지고 앱스토어와 플레이마켓에서 여러 가지 실험을 진행 해 보았는데 앱스토어에서 특이사항이 발견 되었습니다. 앱스토어 SEO를 위해 Metadata>Keyword와 IAP(In-App-Purchases)을 이용하라 보통 PC WEB인 경우 검색이 잘 되게 하기 위해 SEO(Search Engine Optimizer)를 진 행하는데 있어 Metadata 관리가 기본인데, 앱스토어도 마찬가지로 [그림14]와 같이 어플 등록 시 Metadata 작성하는 란이 있습니다. 따라서, 해당 Metadata > Keywords 란에 이용자가 입력할 만한 이용자의 언어로 키워드를 등록해야 하는데 안타깝게도 Metadata 글자수가 100bytes로 제한되어 많은 키워드를 입력할 수 없습니다. [그림14] 앱스토어 등록 폼 따라서 SEO를 위해 추가 키워드를 등록하는 다른 방법을 찾는 중에 [그림15~17]과 같이 KTH에서 출시한 “Playy TV”라는 어플을 통해 “플레이”, “범죄의 재구성”, “의뢰 인”과 같이 Metadata>Keyword에 등록되어 있지 않은 키워드를 입력해도 검색결과 에 “Playy TV”가 노출됨을 확인 하였습니다.
  189. 192 H3 개발자 컨퍼런스 2012 [그림15] 앱스토어 검색테스트1 [그림16] 앱스토어

    검색테스트2 [그림17] 앱스토어 검색테스트3 그 이유를 확인해 보니 [그림18~19]에서 보는 것과 같이 “인기App 내 구입” 리스 트에 해당 키워드가 등록되어 있기 때문이라는 것을 확인 하였습니다. 따라서, 만약 Metadata에 다 입력하지 못한 키워드가 있다면 IAP(In-App-Purchases) 즉, “인기 App 내 구입” 방식을 통해 검색의 노출빈도를 높일 수 있다라는 것을 확신 할 수 있었 습니다. [그림18] 앱스토어 내 Playy TV 상세페이지 [그림19] Playy TV 인기 App 내 구입 리스트 만약 나의 어플은 무료 어플이라 IAP를 만들 수 없다고 생각하는 분이 계시다면 다음 에 나오는 무료 어플의 IAP 예시가 조금의 도움이 되었으면 합니다. 다음의 예시는 IAP를 이용한 SEO 아이디어입니다.
  190. 193 기획/디자인/개발자 모두 알아야 하는 대박앱의 비밀 예시) “푸딩카메라”는 세상이

    모두 다 아는 무료 카메라 어플입니다. “푸딩카메라”에서 만약 IAP를 만든 다면 어떤 아이템들을 만들 수 있을지 작성해 보았습니다. “푸딩카메라” IAP를 이용한 SEO 예시 ➊ 야경 잘 찍는 노하우 $0.00 ➋ 자동차 불 빛 찍는 노하우 $0.00 ➌ 실내에서 인물사진 잘 찍는 방법 $0.00 ➍ 웨딩사진 잘 하는 방법 $0.00 ➎ 우리 아기 웃는 100일 사진 찍는 방법 $0.00 ➏ 해운대 바닷가 파도 촬영 방법 $0.00 ➐ 이력서 사진 잘 나오게 하는 노하우 $0.00 ➑ 뒷 배경 날리는 방법 $0.00 ➒ 아웃 포커스 하는 방법 $0.00 위와 같은 방법을 실제 앱스토어에서 사용하기 위해서는 IAP의 아이템 길이를 너무 길게 하지 말고, 아이템 내에 키워드를 많이 포함한다면 더욱 효과적인 SEO가 가능할 것으로 보입니다. 단, 모든 ITEM이 $0.00일 경우 앱스토어에서는 Reject 가능성이 있 으므로 여기 또한 수위 조절은 필요 합니다. 어플 이름은 숫자가 앞에 나오도록 만들어라!! 시간이 갈수록 새로운 어플들은 끊임없이 출시될 것이고, 더 많은 어플들이 내 폰에 설치될 것입니다. 이 경우 “내가 설치한 어플을 내 폰에서 찾지 못하는 경우가 빈번히 발생할 것이고, 내가 원하는 어플을 내 폰에서 찾기 위해 폰 내 검색의 활용빈도가 높 아 질 것이다.”라는 가설을 세우고, 폰 내에서 다른 어플 보다 내 어플이 상위에 노출 되게 하는 방법이 없을까?에 대한 실험을 진행해 보았습니다. 가설검증을 위해 먼저 안드로이드 폰 내 검색기능을 이용해 본 결과 안드로이드OS에 서는 연락처, 어플이름, 인터넷 검색결과 등을 모두 초성검색을 우선으로 보여주고 있 어, 임의의 키워드를 입력했을 경우 어떻게 하면 상위에 노출되는지에 대한 실험의 의 미가 없어 안드로이드폰은 해당 실험에서 제외하였습니다. 그러나 아이폰에서는 조금 다른 결과가 나타났는데, [그림20] ①은 실제 아이폰 내 검색에서 “맛집”을 검색한 결 과 화면인데 “30년맛집” 선두로 ~ “트래블로맛집”까지 노출되고 있습니다.
  191. 194 H3 개발자 컨퍼런스 2012 [그림20] 아이폰 내 검색 결과

    상위 노출을 위한 테스트 단계 이번 실험방법은 내가 만들고 있는 어플이 맛집 어플이라고 가정하고, 내가 만든 맛집 어플과 경쟁 어플이 한대의 아이폰 내에 동시에 존재할 때, 아이폰 검색 창에 “맛집”이 라는 키워드를 입력 할 경우, 경쟁 어플보다 상위에 노출 될 수 있는 이름이 무엇인지? 확인하는 방식으로 진행하였습니다. 실험의 목표는 [그림20] ①에서 보듯이 내가 만든 맛집어플 이름이 아이폰 내에서 “맛집”이라는 이용자의 언어로 검색했을 때 “30년 맛 집”보다 상위에 노출되는 것이었습니다. 실험 순서는 [그림20]의 ②사파리를 실행한 후 ③임의의 홈페이지에 접속한 후 ④내보 내기 아이콘을 선택하고 ⑤홈 화면에 추가 버튼을 클릭한 후 ⑥실험에 필요한 임의의 맛집 어플 이름을 ⑦”고객참여맛집”, “100만개맛집”, “IMIN맛집”으로 입력한 후 폰 내 바탕화면에 바로가기 아이콘을 만든 후 다시 아이폰 내 검색 창에서 ⑧”맛집”을 검 색해 결과를 확인해 보았습니다.
  192. 195 기획/디자인/개발자 모두 알아야 하는 대박앱의 비밀 ⑧검색결과를 자세히 보면

    아이폰 내 검색정렬 우선순위를 알 수 있는데, 1순위가 숫 자(1~9)순이고, 2순위는 영문(A~Z)이며, 3순위는 국문(ㄱ~ㅎ)순임을 알 수 있었습 니다. ⑧번과 같은 결과가 나오는 이유를 검색정렬 우선순위로 해석해 보면 “30년맛집”의 “3”보다 “100만개맛집”의 “1”이 우선 하기 있기 때문에 상위에 노출되었고, TV맛집의 “T”보다 “IMIN맛집”의 “I”가 우선하기 때문에 “IMIN맛집”이 상위에 노출되었으며, “근 처맛집”의 “그”보다 고객 참여맛집의 “고”가 우선하기 때문에 상위에 노출된 것이었습 니다. 즉, 앱스토어에서도 검색이 잘 되는 어플을 만들어야 하겠지만, 한 발 더 나간다면 아 이폰 내에서도 설치된 어플의 높은 실행횟수를 유도하기 위해 아이폰 내 검색 우선순 위를 이해하고 어플 이름을 만드는 것도 고려해 볼 필요가 있습니다. 투입인력과 개발기간의 최소화, 출시 후 +30일 이내 본전을 찾아야 한다 만약 대박 어플의 정의가 돈을 많이 버는 것이라고 한다면, 어플을 제작하기 전에 가 장 중요하게 해야 할 일이 있습니다. 그것은 투자 대비 수익률을 분석하는 것인데 만 약 계산을 통해 투자보다 수익이 적다는 결론에 도달하면 차라리 어플을 안 만드는 것 이 대박 어플의 비밀일 수 있기 때문입니다. 만약 예를 들어 기획/디자인/개발이 모두 가능한 인디 개발자인 경우라면 인건비를 많 은 부분 줄일 수 있지만 회사에서 어플을 제작한 후수익을 창출해야 하는 상황이라면 어플 제작이 과연 이익인지? 손해인지? 꼭! ROI(Return On Investment)분석을 통해 신중하게 어플 시장에 진입해야 합니다. 그 이유는 아직까지 어플이나 모바일 서비스가 “모바일 광고” 또는 “컨텐츠 판매” 이외 에 특별한 BM(Business Model)이 없기 때문이기도 하고, 소위 벤처 붐이라고 말하는 2000년 즈음에는 회원가입 자체가 실제 엔젤 투자금을 유치할 때 주요 지표로 사용한 경우도 있었지만, 벤처거품을 겪은 현재의 IT 현실에서는 회원수가 아무리 많아도, 명 확한 BM이 없을 경우에는 회원 수 자체는 그냥 인프라 비용의 증가 그 이상 그 이하 도 아니기 때문이다. 그럼 어플 제작을 위한 투자금과 수익금에 대한 계산을 해 보겠습니다. 투자 대비 수 익율 계산방법은 아주 다양한 방법이 존재 하지만, 그 중 인건비를 중심으로 계산해
  193. 196 H3 개발자 컨퍼런스 2012 보겠습니다. 수익률 계산을 위해 전제

    조건은 우리가 어플을 만드는 데 있어 어플 런 칭과 동시에 매출을 올릴 수 있는 게임 어플을 만든다고 가정하고, 게임 중에서도 타 게임장르에 비해 오랫동안 플레이 하는 게임장르인 SNG를 개발한다고 가정 하였습 니다.[그림22참조] 개발 수준은 타 서비스에 비해 난이도가 높은 SNG라는 점을 감안해서 기획/디자인/ 개발을 각 2명씩 중급기술자로 배치하였고, 개발기간은 사내에서 출시한 SNG 어플개 발 시 대략의 개발 기간을 근거로 6개월로 잡았고 중급기술자월급여의 근거는 2011 년 소프트웨어 노임단가를 기준으로 산정 하였습니다. 그 결과 SNG 게임을 하나 개 발하는데 인프라 비용을 제외한 인건비만 계산했을 경우 [그림21]에서와 같이 2억2천 이 넘는 투자비용이 발생합니다. [그림21] SNG 게임 어플 개발 비용계산 (주의, 게임에 따라 인력/기간은 변동 될 수 있음) [그림22] 가장 오랫동안 플레이 하는 게임장르 조사결과
  194. 197 기획/디자인/개발자 모두 알아야 하는 대박앱의 비밀 여기에서 서비스를 약

    2년간 운영한다고 가정하면 [그림23]과 같이 유지보수 비용 이 발생하게 되는데 이때 총 투자비가 개발비+운영비입니다. 따라서, 총 투자 비 용을 계산해 보면 [개발비+(1개월유지비x24개월) ] = [225,658,440원+(18,804,870원x24개월) ] = 676,975,320원 이 됩니다. [그림23] SNG 게임 1개월 유지비용 만약 2년(24개월) 안에 총 투자 비용의 본전을 찾겠다는 목표를 세웠다면, 총 투자비 676,975,320원을 24개월로 나누면 한 달에 28,207,305원씩 벌어야 하며 이렇게 개 발한 게임이 1설치당 $0.99(\1,136)로 팔린다면 한 달에 24,830건 설치되어야 하 고, 하루(÷30)로 계산하면 24개월 동안 매일 838건이 유료설치가 발생해야 한다는 결론이 나옵니다. 하루에 838건 유료설치 된다는 것이 어느 정도 힘든지? 감을 잡기 위해 자사 어플 중 2012년 6월에 출시한 C어플이 KR앱스토어에서 3위까지 올랐는데 그 시점에 하루 설 치 수를 확인해 보니 약 300건 정도가 됩니다. 같은 시기에 출시되는 경쟁 어플이 누구냐?에 따라 순위와 설치 수는 변동될 수 있지 만 단순히 산술 계산만으로도 하루 유료 설치가 838건이 되려면 최소한 KR앱스토어 1~3위 안에 들어야 함은 물론이고, 그 순위를 24개월 동안 유지 해야만 본전이 가능 하다고 할 수 있습니다. 위 내용들이 비관적으로 들릴 수 있으나, 여기서 핵심은 만약 “내가 앱스토어에서 어 플을 팔아 돈을 벌 것이다.”라는 생각을 가지고 있다면 과거 2년 전과 같이 어플을 만 들기만 하면 팔리는 시기를 생각하면 절대 안 되고, 품질을 최우선으로 하면서 개발기
  195. 198 H3 개발자 컨퍼런스 2012 간과 인력 등의 투입비용을 최소화할

    수 있는 방법을 고민하고, [그림3]에서 보았듯이 기본적인 어플의 라이프사이클인 출시 후 약 +30일 이내임을 감안하여, 30일 이전에 최대한 많은 수익을 낼 수 있게 모든 준비가 완벽해야 한다는 내용을 말씀 드리기 위 해서입니다. KR앱스토어 1분만에 1위하는 방법 어플을 개발하는 사람이라면 누구나 한번쯤은 순위가 어떻게 정해질까?라는 의문을 가져 본 적이 있을 것입니다. 이 의문을 해결하기 위해 몇 가지 엉뚱한 실험을 진행 했었는데, 그 중 앱스토어 순위변화 주기에 대한 실험 결과에 대해 설명 드리고자 합 니다. 실험방법은 애플에서 제공하는 앱스토어 순위 RSS 웹 페이지를 10초 단위로 우리가 원하는 폼으로 Crawling Parsing 한 후 DB로 저장해 보았습니다. 그 후 [그림24] 그래프를 통해 순위변화를 확인해 보니 ③④에서 보듯이 임의의 어플 이 여섯줄 만에 순위가 바뀌는 패턴을 확인 할 수 있었고, 그 시간 간격을 ⑤⑥에서 확 인해 보니 애플 앱스토어에서는 순위 변화가 1분임을 확인할 수 있었습니다. [그림24] 10초 단위 앱스토어 순위 크롤링 데이터
  196. 199 기획/디자인/개발자 모두 알아야 하는 대박앱의 비밀 랭킹 알고리즘이 단순히

    신규어플 설치만으로 산정되진 않겠지만, 랭킹에 반영되는 많은 요소 중 신규 어플 설치의 가중치가 가장 높다고 가정하고, [그림25]에서 보듯이 2012년 2월에 출시한 자사 어플인 “푸딩.투”가 1위 했을 때 하루 약 6만 건이 설치가 되었다는 근거로, 1분에 몇 건이 설치되면 KR앱스토어에서 1등을 할 수 있을까?를 산술적으로 계산해 보니 [60,000건÷24시간÷60분=42건/1분) 즉, 1분 내에 42건의 어플이 설치되면 1위를 할 수 있다는 계산 결과가 나왔습니다. [그림25] 2012년 2월 푸딩.투 1위 당시 다운로드 건수 표 이용자들이 많이 몰리는 시간과 그렇지 않은 시간대에 따라 1위를 하기 위해 1분당 설 치 건수가 달라질 수 있겠지만, 1분내 42건의 설치만으로 만약 높은 순위에 랭크 된다 면 정말로 매력적인 방법이 아닐 수 없습니다. 그러나, 이 방법은 아직 가설단계이며, 1분이라는 시간이 순위 변화의 시간 일수도 있지만, 서버의 Load Balancing의 시간 일 수도 있으므로 지속적인 검증 중에 있으므로 지속적인 실험을 통해 공유하도록 하 겠습니다. 글을 마치면서 대박 어플이 되기 위한 수 많은 요건 중 몇 가지 방법에 대해 요약해 보았습니다. 내용 작성 중 이해를 돕기 위해 단정적인 어투를 사용한 점에 대해서는 너그러운 양해 부탁 드립니다.^^ 또한, 위 내용의 조사 및 실험환경은 iTunes 10.6.3, iOS 5.1.1, Android 2.3.3입니 다. 따라서, 책 출판 시점에 만약 버전 업으로 인해 일부 내용이 달라 질 수 있음을 말 씀 드립니다. 글 도입부에 말씀 드린 이용자의 중요성과 “골목대장 방법론”에 대한 의미를 이해해 주신다면 아무리 험한 환경변화가 올 지라도 대박 어플의 비밀은 이미 여러분께서 알 고 계시리라 생각됩니다.
  197. 200 H3 개발자 컨퍼런스 2012 마지막으로 제 글로 인해 어플(서비스)를

    바라볼 때 이용자를 위한 것이 무엇인지? 다 시 한번 고민하는 계기가 마련되었으면 좋겠다는 작은 바람을 가져 봅니다. 긴 글 읽어 주셔서 대단히 감사의 말씀 드립니다. 대박어플의 비밀 01. 아이폰 어플은 ”인기25”, 안드로이드 어플은 “인기무료애플리케이션” 메뉴에 랭크 되어야 함 02. 순위상승의 기회는 출시 당일이며 출시 전 마케팅이 준비되어 있지 않다면 어플 등록을 연기 03. 어플의 수명은 출시 후 +30일이며, 상위순위 유지를 통해 선 순환구조 구축 04. 필사적인 25위까지 순위를 관리해야 하며 실패할 경우 75위까지 최선을 다해야 함 05. 어플 설치시 가장 중요한 요소는 스크린샷과 리뷰 06. 모든 유료어플은 어플 내 구매방식으로 개발 07. 나의 서비스에서 가장 행복한 시점에 이용자에게 리뷰를 요청 08. 젊은 연령층 일수록 스크린샷/미리보기를 보고 어플을 설치 09. 어플 이름은 “이용자의 언어”로 작명 10. 앱스토어 SEO를 위해 Metadata>Keyword와 IAP(In-App-Purchases)을 이용 11. 어플 이름은 숫자로 만들면 효과적 12. 어플에서 돈을 벌려면 개발기간의 최소화, 출시 후 +30일 이내 본전을 찾아야 함
  198. 201 기획/디자인/개발자 모두 알아야 하는 대박앱의 비밀 참고자료 [kth 모바일

    리포트]앱스토어! Blue Ocean인가? Blood Ocean인가? http://bit.ly/OaFeFF [모바일 리포트]앱 설치 시 사용자들의 리뷰 영향력 높아져 http://bit.ly/NtQj9i [kth 모바일 리포트] 연령 낮을수록 ‘스크린샷’, 높을수록 ‘앱설명’ 보고 앱 선택 http://bit.ly/QGTD1M
  199. 202 H3 개발자 컨퍼런스 2012 들어가기에 앞서 1980년대 초, 국내

    전자 제품 시장의 1위는 금성(현 LG)전자였다. “순간의 선택이 10 년을 좌우한다”라는 광고 카피에서처럼, 한번 들여놓은 가전 제품은 10년 정도의 라 이프사이클을 가지던 시점이었고, 대우 전자에서 “탱크”라는 이미지를 광고했을 만큼 “품질”이 중요한 상품 가치 중 하나였다. 그러던 전자 제품시장이 1990년에 대에 들어 오면서 서비스를 강조한 삼성전자로 주도권이 넘어가게 되는데, 이는 “전자제품의 짧 아진 라이프사이클”과 “삼성의 서비스 중심” 전략이 잘 맞아 떨어진 결과라고 할 수 있 다. (당시 삼성은 품질에서 LG에 미치지 못했지만, AS가 어려웠던 타사 제품에 비해, 문제가 생긴 제품을 새 제품으로 교환해 주는 등, AS에 있어서 파격적이었던 것으로 기억한다.) 이는 결국 시장의 흐름에 따라, 대상 제품에 따라 요구되는 품질의 수준이 다르다는 것을 의미한다. 단순히 “양보할 수 없는 가치” 가 아니라 고객이 무엇을 요구하는지, 시장이 어떻게 변화하고 있는지에 따라 접근 전략도 달라져야 한다는 의미이다. 20년이 지난 지금, 우리가 개발하고 서비스 하고자 하는 스마트 모바일 시장은 어떻게 변화하고 있을까? 그리고 그 변화가 요구하는 것은 무엇이며, 우리는 그 요구에 어떤 품질 전략을 가지고 접근 해야 할까? 같이 고민해 보고자 한다. 스마트 모바일 시장에서의 품질관리 방안 프로젝트지원팀 남종인 [email protected] 프로젝트지원팀 한동준 [email protected]
  200. 203 스마트 모바일 시장에서의 품질관리 방안 경쟁이 치열한 스마트 모바일

    시장 쏟아지는 앱 요즘 App Store나 마켓에는 누구나 앱을 등록 할 수 있어, 개발지식만 있다면 혼자서 도 앱을 개발하여 시장에 내 놓을 수 있다. 이렇다 보니 혼자서 혹은 작은 조직을 만들 어 앱을 생산하는 경우를 많이 볼 수 있다. 한국콘텐츠진응원(KOCCA)에서 2011년 12월에 발간한 조사자료에 따르면 조사대상 모바일 앱을 제작하는 업체의 설립 비중 이 2009년 이후 크게 늘어 났으며, 조사대상 업체의 72% 이하가 24명 이하의 소규모 업체로 나타났다. [기간별 설립 사업자 수의 평균] [사업자의 전체 근무 인원 규모 및 누적분포]
  201. 204 H3 개발자 컨퍼런스 2012 이렇듯 모바일 앱 시장의 진입장벽이

    낮다 보니, 수 많은 앱이 쏟아지고 있다. iOS의 경우 월 평균 약 25,700개, 하루 평균 865개의 앱이 App Store에서 등록되고 있다. 이런 수 많은 앱 들 가운데, 과연 얼마나 성공할 수 있을까? 월 앱 게임 변동 누계 Jan-12 454,622 88,827 +23,085 543,449 Feb-12 474,258 92,276 +27,359 566,534 Mar-12 497,535 96,358 +27,942 593,893 Apr-12 521,341 100,494 +29,310 621,835 May-12 546,441 104,704 +23,982 651,145 Jun-12 566,882 108,245 +22,523 675,127 Jul-12 585,933 111,717 - 697,650 [2012년 1월 ~ 8월까지 애플 App Store에 등록된 앱 수 8] 사실 이렇게 생산되는 앱들 중 상당수는, 사용자에게 미처 소개되지도 못한 채 사라 진다. App Store의 경우 추천 메뉴, 유료/무료 Top 25 메뉴를 제공하는데, 대부분의 사용자가 이를 통해 앱을 선택하고 설치한다. 다음 표를 보면, iOS 스토어 중 가장 많 은 컨텐츠를 초기화면에 노출하고 있는 아이튠즈 스토어 조차 전체 108개의 앱이 공 개 되는데 그친다. 동일 컨텐츠가 iPhone이나 iPad에서 제공되는 App Store에서 더 적게 표시하고 있다는 점을 감안하면, 초기에 노출되는 앱은 총 합인 108개 보다 적은 수가 노출 된다고 볼 수 있다. 여기에 순위를 제외하고 일반 분류 항목이 매일 바뀐다 고 가정하더라도 (실제로는 매일 바뀌지 않음) 1/10 정도만 노출 되는 것이다. 성공을 위한 첫 단계 조차도 얼마나 어려운지를 보여준다. 항목 노출 개수 일반분류 최신 및 추천 목록 32 What’s Hot 32 테마별 앱소개 (홀인원, 마법) 24 순위분류 유료 Apps Top 10 10 (전체 보기 200) 무료 Apps Top 10 10 (전체 보기 200) [iTunes App store 초기 페이지 앱 노출 개수] 8 출처: http://148apps.biz/
  202. 205 스마트 모바일 시장에서의 품질관리 방안 그렇다면, 노출되어 순위에 올라간

    앱들의 상황은 어떨까? Bloter.net9에 소개된 KTH 개발자 블로그의 글을 살펴보면 여기서도 결코 만만한 상황은 아니다. 내용을 요 약 해 보면, 다음과 같다. ‘11년 ~ ‘12년 사이 국내 App Store 무료 300위 내에 한 번이라도 든 적이 있는 앱들을 대상으로 순위 변화에 대 해 관찰한 결과, ▪ 스토어 순위(300위, 25위) 내 진입 앱 수 증가 (11년 상반기 2097  12년 상반기 2,842)  순위 권 내 유지 일 수 감소 (11년 상반기 8.2일  12년 상반기 6.4일) ▪ 스토어 300위 內 1위 앱 비중은 2~ 3% (11년 상반기 3.1%, 12년 상반기 2.0%) 위 내용을 살펴보면, 동일 기간 중 특정 순위 내 진입 앱이 증가했다는 것은 결국 순위 권 안에 머무는 시간이 감소했다는 것이다. 이는 결국 순위 경쟁이 더욱 치열해 지고 있다는 것을 의미한다. 또한, 300위 내에 들었던 앱 중에서도 1위를 차지하는 앱 비중 이 2% 정도라는 것은 스마트폰 앱 시장의 경쟁이 얼마나 치열한 지를 단적으로 보여 준다. Lite한 사용 패턴 이렇게 수 많은 앱이 시장에 나타나고 경쟁함에 따라, 사용자들이 앱을 대하는 태도도 과거 PC 환경과는 많이 달라졌다. 반드시 어떠한 목적을 가지고 앱을 찾아보거나 다 운로드 하기보다는 심심할 때 App Store나 마켓을 들어가 새로운 앱, 인기 있는 앱을 살펴보고 마음에 들면 일단 다운로드 하여 사용해 보는 경우가 많다. 앱을 보고 다운 로드까지 이어지는데 신중한 결정이 필요 없어 진 것이다. 무료 앱이 넘쳐나고, 유료 라고 하더라도 커피 한 잔 값이다. 올 4월 insidemobileapps10에 기제된 2011년 말 시장 별 무료, 유료 앱 비중을 표시 한 자료에 따르면 약 53%가 무료(부분 유료 포함)앱 이었다. 금년 하이서울뉴스11에 기고된 글에서도 역시 무료 앱의 비율은 70%에 달한다고 밝히고 있다. 9 http://www.bloter.net/archives/123470 10  http://www.insidemobileapps.com/2012/04/19/the-windows-phone-marketplace-and-the-amazon-appstore- are-the-fastest-growing-app-stores/ 11  http://inews.seoul.go.kr/hsn/program/article/articleDetail.jsp?boardID=179296&category1=NC9&category2=NC9_2
  203. 206 H3 개발자 컨퍼런스 2012 즉 수치를 떠나서 무료 앱의

    비중이 유료 앱에 비해 매우 높다는 것은 확실해 보인다. 무료 앱이 많다는 것은, 사용자가 특정 어플리케이션을 설치/삭제하는 데에 부담을 없 애 준다. 사용해 보다가 안 쓰게 되면 삭제하면 되고, 필요하면 설치하면 되는 것이다. 적어도 무료 앱에 있어서, 사용자의 패턴은 변하고 있다. 앱을 소유하는 개념이 아닌, App Store에서 대여하는 개념으로 변하고 있는 것이다. 이러한 사용자 패턴은 국내에서 조사된 통계에서도 드러난다. 한국인터넷진흥원 (KISA)에서 제작한 “11년 하반기 스마트폰 이용실태 조사자료”에 따르면, 무료 앱 다 운로드 수가 유료 앱 다운로드 수에 비해 압도적으로 높은 수치를 보였다. 특히 모바 일 앱 이용자의 16.3%가 하루에 1회 이상 앱 다운로드, 주 평균 6.0개의 앱을 다운로 드 하는 것으로 조사되었다. [모바일앱 다운로드 빈도(%)] [주평균 다운로드 모바일앱 개수(개)]
  204. 207 스마트 모바일 시장에서의 품질관리 방안 [유/무료 모바일앱 다운로드 현황(복수응답,

    %)] [월평균 유료 모바일앱 구입 비용(%)] 무한정 설치할 수 없는 단말 환경임을 가정하면, 이 설치 수치는 앱의 삭제 수치로도 판단 할 수 있다. 사용자는 일상적으로 새로운 앱을 검색하고 설치한다. 아니다 싶은 앱은 바로 삭제된다. 흥미가 있었던 앱도, 흥미를 잃으면 삭제된다. 앱을 개발하고 서 비스하는 주체로서 정말 어려운 시장이 된 것이다. 새로운 앱, 빠른 개선이 필요한 모바일 생태계 일단 사용자의 마음에 들어 바로 삭제되지 않고 꾸준히 사용되는 앱이 되려면, 지속적 으로 사용자의 관심을 받고자 하는 노력이 필요하다. 그렇지 않으면 유사한 경쟁 앱 에 자리를 내 놓아야 할 수 있다. 실제로 우리회사의 사례를 보면 업데이트 시점에 다 운로드 수의 증가 및 앱의 사용량이 증가하여 사용자의 관심을 받는 것으로 나타났고, 업데이트가 없었던 시기에는 다운로드 수 및 앱의 사용량이 감소하여 점점 사용자에 게 잊혀지는 것을 알 수 있었다. 결국 사용자의 단말에 오랫동안 삭제되지 않고 꾸준히 사용되는 앱이 되려면, 삭제되 기 전에(짧은 시간) 사용자의 관심 안에 들어야 하고, 꾸준한 업데이트가 필요하다. 우 리회사의 경우에는 보통 2 ~ 4주 주기로 지속적으로 업데이트를 진행하고 있다. 신규 앱의 경우에도 마찬가지이다. 6개월 이상 걸리는 대규모 프로젝트 보다는 중소규 모 프로젝트가 대부분이다. 다음 표를 보면 66% 이상이 3개월 이내 개발기간을 가지 는 것을 볼 수 있다. 상황이 이렇다 보니 앱 시장에는 점점 더 많은 앱이 나타났다 사 라지고, 순위권 안에 머무는 기간도 점점 짧아져 오랜 기간 인기를 얻기란 쉽지 않다.
  205. 208 H3 개발자 컨퍼런스 2012 [스마트콘텐츠의 적용 플랫폼별 개발 소요기간]

    지금까지의 내용을 종합하면 다음과 같이 정리할 수 있다. 스마트 모바일 앱 시장에서 사용자는 다른 시장보다 더 흥미롭고 새로운 것에 민감하 다. 새로운 것을 찾고, 흥미를 잃은 것은 지우면서 앱을 지속적으로 소비한다. 시장은 하루에도 800개 이상의 앱이 출시되며, 사용자의 소비 욕구를 만족시키고 있다. 그럼 에도 불구하고 실제로 사용자에게 소비되는 앱은 극 소수에 불과하다. 모든 것을 집어 삼키는 블랙홀 같은 시장이다. 이 시장에서 살아남기 위해서는 사용자 로부터 요구된, 그리고 요구될 가치를 빠르고 반복적으로 제공해야 한다. 그렇다면 품 질 활동도 명확해 진다. “과연 우리가 개발한 가치가 바르게 동작하는가?“와 “가치를 빠르고 반복적으로 전달할 수 있는가?” 이다. • 고객이 요구하는 가치에 대한 품질 활동 집중 • 빠른 반복 출시에 대응할 수 있는 프로세스 앱이 사용자에게 전달되지 못하고, 소비되지 못한다면 아무리 잘 테스트 되었다고 해 도 무의미한 활동이 된다. 물론 출시를 위해 품질을 소홀히 해도 된다는 의미는 아니 다. 하지만, 치열한 시장과 빨라진 개발 주기에 대응하기 위해서 품질 활동은 관리와 통제가 아니라 참여와 협조 활동으로 변화해야 한다. 또한 늘어난 출시 횟수에 대응하 기 위해서 “완벽”과 “효율”의 적절한 타협점을 찾아야 한다.
  206. 209 스마트 모바일 시장에서의 품질관리 방안 고객이 요구하는 가치에 대한

    품질 집중 앱에서 고객이 요구하는 가치는 무엇일까? 사용자가 앱을 선택했을 때 기대하는 무언 가 이다. 사용자는 블로그나 신문기사를 통해 보고 설치하거나, App Store에서 서핑 하다가 호기심 설치하거나, 혹은 친구의 권유 등의 이유로 설치할 것이다. 어떤 방식 을 통해 설치를 하든, 사용자가 앱을 선택하는 시점에는 앱이 어떤 기능을 가지고 어 떤 동작을 했으면 좋겠다는 기대를 가진다. 그리고 설치된 앱이 그 기대를 만족시키는 지에 따라 앱의 운명이 결정된다. 사용자의 기대는 우선 “기능”과 “디자인”에 집중된다. 기대했던 기능이 깔끔한 UI로 표 현 되었다면 사용자는 만족할 것이다. 품질은 여기서부터이다. 기대했던 기능과 디자 인이 사용자의 품질 기대 수준 이상인가?가 앱 시장에서 품질의 핵심이다. 사실 사용자가 무엇을 기대하는가?에 대한 고민은 기획자의 몫이고, 선택도 기획자의 결정에 따른다. 품질쪽에서 의견을 줄 수는 있지만 최종 결정은 기획에서 이루어 진 다. 그렇다면 품질관점에서는 기획자가 결정한 핵심 기능을 고객이 요구하는 가치라 고 봐야 할 것이다. 핵심기능 검증방안 검증을 위해 앱의 기능을 구분하는 방법은 여러 가지가 있다. 어디에 결함이 많이 발 생할까?라는 기준에 따라 복잡도로 구분할 수 있고, 결함 발생 시 사업적 손해는 얼마 나 될까?의 관점에서는 비즈니스적 리스크(개인정보, 결제 등)으로 구분해 볼 수 도 있 다. 다양한 관점에서 기능을 구분하고 테스트 하는 것은 중요하다. 스마트 모바일 시 장에서는 이들 구분 말고도, 한 가지 구분이 더 중요해 진다. 바로 지금까지 설명했던, 핵심기능인가? 비 핵심기능인가?의 관점이다. 이런 관점에서 기능은 크게 다음과 같 이 구분될 수 있다. • 핵심 기능: 크게 앱의 사용목적과 직결되는, 그리고 타 앱에 비해 강조/차별화되는 기능 • 보조 기능: 핵심기능에 가치를 추가하거나, 원활한 사용을 지원하는 기능 • 일반 기능: 기본적으로 앱의 조작을 위해 필요한 기능 및 소개, 설명, 도움말과 같은 기능 서비스를 하고 있다면, 혹은 앱을 다운로드 받아 보았다면, 스토어 다운로드 화면에 사용자들의 평가 글 들을 본 적이 있을 것이다. 일부 결함에 대한 불만이 올라오기도 하는데, 어떤 결함들이었는가? 잘 생각해 보면, 핵심기능의 사용을 방해 하는 결함들
  207. 210 H3 개발자 컨퍼런스 2012 이라는 것을 알 수 있다.

    알다시피 무결함 제품은 없다. 제한된 시간과 인력을 어디에 더 투자해야 하고, 어디의 결함을 줄여야 할 지 명확해 진다. 그렇다면, 이런 중요한 기능에 대한 테스트는 어떻게 진행해야 할까? 바로 테스트케이스의 활용이다. 일반적으로 사용자의 다양한 조작이 이루어지는 SW의 경우 테스트케이스를 활용하 기 보다는 테스터의 경험에 의존하는 경우가 많다. 사용자의 다양한 조작을 예측하여 테스트케이스로 문서화 한다는 것은 불가능 하기 때문이다. 설사 가능하다고 해도 테 스트케이스를 작성하는 노력, 그리고 유지보수 하는 노력에 비해 효과가 미미하기 때 문에, 테스트케이스 활용은 줄고 있다. 그러나 여기에도 문제가 있다. 바로 사람의 기억력, 꼼꼼함에 한계가 있기 때문이다. 정해진 케이스에 따라 수행하는 테스트의 경우, 최소한 작성된 케이스에 대한 동작은 보장한다. 그러나 사람이 테스트하는 경우, 누락되는 항목이 생길 수 밖에 없고, 그날 의 컨디션에 따라서도 발견되는 결함 양이나 수준에 차이가 난다. 이를 보완하기 위 해 기능의 기본적인 동작을 정의한 테스트 케이스 수행과, 테스터의 조작에 의한 테스 트를 병행하기도 한다. 하지만 이 경우에도, 테스트케이스와 테스터의 조작 사이에 빈 곳이 생기게 되고, 발견해야 할 결함을 발견하지 못하는 상황이 발생하게 된다. 그렇다면 테스트케이스를 어떻게 활용해야 할까? 바로 핵심기능에 포커스 된 테스트 케이스 작성 및 활용이다. 앞서 핵심기능이 앱의 성공에 가장 중요한 요소로 정의하 고, 이에 대한 품질을 강화해야 한다는 설명을 했다. 당연하지만 그렇지 못했던 핵심 기능의 품질, 테스트케이스로 끌어 올릴 수 있다. 먼저 핵심기능에 대해 테스트케이스 활용이 가능한 이유를 살펴보자 • 핵심기능은 변경이 작다.  일반적으로 핵심기능은 버전이 올라가면서 수정이 발생해도 변경 범위가 크지 않다. 따라서 테스트케이스의 유지 보수 노력이 감소한다. • 제한적이다.  모든 기능에 대해 다양한 케이스를 기술하고, 테스트하는 것은 비효율 적이다. 더구나 콤팩트한 업무 진행을 요하 는 앱 시장 환경과는 맞지 않는다. 하지만 핵심기능으로 기능 범위를 제한한다면, 테스트 케이스의 숫자는 확 줄어 든다. 이 두 가지는 자칫 비효율적 일 수 있는 테스트케이스의 활용을 가능하게 해준다. 그 렇다면, 테스트케이스를 만들어 실행했을 때에 어떤 효과가 있을까?
  208. 211 스마트 모바일 시장에서의 품질관리 방안 • 꼼꼼한 체크가 가능하다.

     테스트케이스는 일종의 체크리스트이다. 핵심기능에 있어서 확인해야 할 항목을 빠짐없이 체크할 수 있게 해 준다. • 일정 수준 이상의 테스트를 가능하게 한다. 작성된 케이스를 통해 수행되므로, 테스터의 역량과 무관하게 일정 수준 이상의 품질을 확보 할 수 있다. • 경험치가 누적된다.  테스트케이스는 우리가 생각할 수 있는 케이스들을 기록해 놓은 것이다. 외부에서 발견된 결함의 발생원인을 파악 하여 케이스에 추가함으로써, 높은 수준의 테스트를 진행할 수 있게 해 준다. • 자동화 가능성이 높아진다.  앞서서도 이야기되었지만 핵심기능이 변경되는 경우는 드물다. 만일 테스트케이스를 많이 변경해야 할 정도로 변 경된다면, 단순 마이너 업데이트나 패치가 아닌 버전 첫째 자리 수준의 변경일 것이다. 짧은 주기로 반복해서 출시 해야 하는 상황에서, 매번 동일한 확인 활동이 필요하다는 것은 자동화 도입 가능성을 높여 준다. 물론 변경되지 않는다고 해서 자동화가 가능한 것은 아니지만, 자동화 가능성이 높아지고 자동화 됐을 때 효율을 보장한다. • 일정 수준의 정량화가 가능하다.  탐색적테스트나 경험기반테스트의 경우 테스터의 전략적 접근에 따라 범위나 수준이 달라지기 때문에, 100%라는 수치를 만들기는 매우 어렵다. 이에 반해 테스트케이스를 통한 수행방법은 100%가 정해져 있다. 가령 100개의 테스트케이스가 있다고 한다면, 100개중 얼마나 수행했는지(수행율), 결함은 몇 개인지.(결함율), 등의 수치를 개별 혹은 각 버전 별로 비교해 볼 수 있다. 물론 케이스가 많을수록, 커버리지가 높을수록 뽑을 수 있는 데이터는 많아 진다. 그렇다면, 핵심기능에 대한 테스트케이스는 어떻게 작성해야 할까? 사실 테스트 설계 기법은 상당히 많다. 기법이 많은 이유는 테스트란 활동이 다양한 시각에서 다양한 방식으로 접근하는 것을 요구하기 때문이기도 하지만, 한편으로는 테스트 해야 할 SW의 특성이 다양하기 때문이기도 하다. 따라서 기법을 적용하기 위해서는, 핵심기능이 어떤 형태의 결함발생 위험에 처해 있 는지를 확인해 보아야 한다. 이는 기존에 발견된 결함을 분석하는 것이 좋다. 기존에 발견되었으니, 당연히 수정되었을 것이고 이제 문제가 없을 것이라는 추측은 위험하 다. 결함은 기능의 특성에 따라 특정 패턴의 조작, 특정 상황에 집중되는 경우가 많고 사람은 같은 실수를 반복하기 마련이다.(개발자는 당연히 사람이다.) 사실 지나치게 다양한 조작, 패턴에서 발생한다면 테스트케이스의 효율이 떨어질 수도 있다. 또한 사용자의 앱 사용 패턴을 유추해 보는 것도 좋은 방법이다. 여기서 주의할 점은, 어떤 기능항목을 추출하는 것이 아니라, 조작 패턴을 추출해야 한다는 것이다. 핵심기 능이라고 정의된 항목들은 기본적으로 모두 케이스에 포함되어야 한다. 사용자의 패
  209. 212 H3 개발자 컨퍼런스 2012 턴을 유추하는 목적은 기능범위를 정하기

    위해서가 아니라, 핵심기능을 어떤 형태로 테스트 할 것인가를 정하기 위함임을 기억해야 한다. 본격적으로 테스트케이스를 작성하려고 보면, 다시 부딪치는 어려움이 있다. 과연 기 능 단위로 케이스를 기술해야 하나, 화면 단위로 케이스를 기술해야 하나 이다. 일반 적인 앱 테스트케이스의 경우 테스트케이스를 작성하는 사람이나, 테스트하는 사람이 빠뜨리지 않고 테스트 하기 위해 화면 단위로 케이스를 작성하는 경우가 많다. 하지만 핵심 기능에 있어서는 “케이스는 기능위주로 설계하고, 확인은 화면위주”로 기술하는 형태의 케이스가 적합하다. 하나의 기능이 동작해야 하는 케이스 별로 데이터와 화면 을 동시에 볼 수 있게 작성하는 것이다. 핵심기능 품질의 위험요소들 앞서 핵심기능에 대해 테스트케이스 작성의 필요성과, 효과, 그리고 기술방법에 대해 살펴보았다. 이번에는 단말환경에서 핵심기능의 품질에 위험을 미치는 요소를 살펴보 고, 실제로 테스트케이스를 어떻게 작성하는지 간단히 살펴보자 불안정한 네트워크 2G에서 3G, 4G, 그리고 WIFI 등 모바일 환경에 데이터를 공급하기 위한 기술은 점점 확대, 발전하고 있다. 많이 개선되었지만, 스마트폰 사용자의 폭주로 체감할 수 있는 데이터 품질은 미미하다. 사실 전국, 전 세계 구석구석에 촘촘하게 통신망이 구축되어 있고, 망 전환에 따른 Delay가 존재하지 않는 이상, 유선 환경과 같은 네트워크 환경 기대는 접어야 할 지 모른다. 따라서 앱이 전혀 네트워크를 사용하지 않고, 무관하다 면 신경 쓸 필요가 없으나 핵심기능과 관련하여 네트워크에 영향을 받는 다면, 이 부 분에 대한 검증이 필요하다. 네트워크의 영향을 받는 다는 것은 일반적으로 서버와 통신을 한다는 의미이다. 클라 이언트를 통해 사용자의 요청을 받은 이벤트를 서버를 통해 처리하고, 다시 클라이언 트로 결과를 반환하는 동작을 수행한다. 이러한 수행은 시간의 흐름에 따라 이루어지 는데, 결함은 네트워크의 문제로 인해 서버와 클라이언트 간 정보가 어긋나면서 발생 한다. 따라서 테스트케이스를 작성할 때에는 플로우 차트를 그려서 케이스를 정의하는 것이 도움이 된다.
  210. 213 스마트 모바일 시장에서의 품질관리 방안 네트워크 관련 테스트케이스 작성

    ➊ 시간의 흐름에 따른 서버, 클라이언트 기능 동작 플로우를 그린다. ➋ 사용자의 이벤트 케이스를 정의한다. ➌  케이스 별로 클라이언트의 설정(코드 상 변수)의 어떻게 바꾸어 져야 하는지 기록한다. 서버에 요청 시점에 전 클 라이언트가 정상적으로 설정된 상태를 기록하는 것이다. ➍  클라이언트의 요청에 따라 서버 내부에서 처리되어야 할 동작과 상태를 기록한다. 역시 클라이언트의 응답 시점에 설정되어야 할 상태도 기록한다. ➎ 클라이언트에서 서버의 응답을 받았을 때의 설정과 화면에 표시 해야 할 정보를 기록한다. ➏ Workflow가 완성되면, 표시된 통신 단계별로 불안정한 상황을 가정한다. 사용자의 이벤트 별로, 서버와 클라이언트간 통신하는 단계에서 통신에 문제가 있는 상황을 가정하여 작성하면 된다. 문제가 있는 상황은 다음과 같이 세가지 상태로 구분 할 수 있다. Case A) 클라이언트에서 요청 할 수 없는 상태 Case B) 클라이언트에서 요청은 이루어 졌으나 서버에 전달되지 않은 상태 Case C) 서버에 전달 되어 처리되었으나, 클라이언트에 전달하지 못한 상태 먼저 Case A의 경우, 앱이 “지속적으로 네트워크 요청을 하는지” 아니면 “실패 처리 를 하는지” 케이스에 추가해야 한다. 드물 지만, 실패 처리를 하지 않을 경우, 지속적 인 요청을 시도하게 되며, 자칫 발열과 배터리 방전을 야기하는 경우가 있기 때문에 확인이 필요하다. Case B와 C의 경우에는 클라이언트 설정과, 서버 설정에 대해 비정상 시, 각 단의 처 리를 확인하는 케이스를 추가해야 한다. 종종 비정상적인 경우에 대해 처리되지 않았 을 경우, 전혀 알 수 없는 결함을 유발 시키기도 한다. 일반적으로 네트워크로 인한 결함은 사용자에게 빠른 응답을 제공하기 위해, 서버와 비동기적 방식으로 처리함으로 인해 발생하는 경우가 많다. 이렇게 개발 된 경우, 특 히 위와 같이 Workflow로 도식화 하여 각 케이스를 추출하는 방법은 매우 도움이 된다.
  211. 214 H3 개발자 컨퍼런스 2012 메모리 HW기술의 발달 및 단말제조사의

    경험 축적으로 메모리로 인한 문제는 감소하는 추 세이다. 물론 Android의 경우 단말 환경이 방대하여, 단일 앱 구동 메모리가 지나치게 낮게 설정되어 있는 경우도 있지만, 시장 상 점유율은 점점 미미해 지고 있다.12 그럼 에도 메모리가 이슈가 되는 것은, 앱이 무거워 지고 있다는 점과, 멀티태스킹을 자유 롭게 지원한다는 점 때문일 것이다. 사실 메모리와 관련해서는 사실 케이스를 정의하기 어렵다. 왜냐하면 앱이 설치되 어 있는 환경이나, 백그라운드에서 실행되고 있는 앱 무게 및 개수, 그리고 무엇보 다도 조작 패턴에 따라 메모리 사용량이 달라지므로, 정형화된 케이스를 정의하기 어렵다. 또한 테스트를 한다고 해도 개발자의 도움 없이 진행하는 것은 별 의미가 없을 수 있다. 따라서 원칙적으로는 메모리관련 문제를 최종 테스트 단계에서 잡고자 하는 것 보다. 개발 단계에서 설계할 때 고려하고, 개발하면서 튜닝하는 활동이 중요하다. 물론 정적 분석도구를 사용하는 것도 좋다. 다만 메모리로 인한 위험이 예측되었을 경우, 테스트케이스 작성 및 수행해야 한다면, 다음과 같이 간단히 진행 할 수도 있다. 먼저 실시간 메모리를 측정 코드를 삽입한다. 그리고 주요 조작을 통해 메모리를 많이 잡아 먹는 기능과 이벤트를 파악한다. (ex: 지도의 이동 확대축소 등의 조작, 이미지 데이터 캐싱 화면에서의 로딩 요청 등) 그리고 각 기능상 흐름도를 그린다. (흐름도는 각 기능간 이어서 사용함으로 인해 발생할 수 있는 문제의 조합을 가시화 시켜 준다.) 흐름도 상 연관된 기능에 대한 시나리오 및 이벤트를 기록하여 테스트 케이스를 만 든다. 기능 A  기능 C  기능 D  기능 F 기능 A  기능 B  기능 D  기능 F … 기능 A : OO 버튼 10회 이상 클릭, 기능 B : 20회 이상 이동 시도 … 12  사실 메모리는 특정 하나의 앱 만에 문제라기 보다, 단말 자체에 얼마나 허용되도록 설정했는가의 문제이기 때문에, 이러한 단말의 사장 추세는 빠른 편이다.
  212. 215 스마트 모바일 시장에서의 품질관리 방안 만일 조합이 많다면, 테스트케이스

    설계 기법 중 페어와이즈나 OA 등의 기법을 통해, 케이스를 줄이는 것도 좋으며, 케이스의 플로우가 복잡할 경우, 문제를 발견하고 점진 적으로 범위를 줄이는 방식으로 확인하는 것도 효율적이다. 앞서서도 언급했듯이 메모리와 관련한 테스트는 정형화 시키기 쉽지 않다. 다만 테스 트를 통해 메모리 초과 여부, 초과시 정상 동작 여부, 그리고 기능 동작 후 메모리가 바르게 해제되는가?를 확인해야 한다는 목적에 맞게 구성하면 된다. 기타 확인 요소들 백그라운드 상태 및 종료 후 실행 시 동작 확인 최근 앱들은 기본적으로 백그라운드 상태에서 실행되었을 때 기존 상태를 유지하도록 설정되며, 경우에 따라 종료 후 실행 시에도 일부 정보는 저장되어 있다가 복구되어 표시하기도 한다. 당연히 되겠지라고 간과 할 수 있지만, 의외로 많은 결함들이 발생 하는 경우이기도 하다. 일부 타 기능과 조합될 수 있는데, 데이터 통신 중 혹은 저장 중, 상태 변경에 대한 케 이스나, 가로모드에서 백그라운드로 이동 후, 세로모드에서 실행한다거나 하는 식으 로 테스트 될 수 있다. 일부 기능과의 충돌 여부 확인 단말기 SW는 크게 제조사에서 단말 자체의 기능을 위해 삽입된 SW와 앱과 같이 사 용자의 선택에 따라 설치된 SW로 구분할 수 있다. 일반적으로 전자의 경우 단말기 내 에서 최 상위 레벨의 우선순위를 가지게 되는데, 사용자가 설치한 대부분의 앱은 이 우선순위 하위에 속한다. 이는 우리의 앱이 실행 중인 상태에서, 상위레벨 SW가 아무 때나 침범할 수 있으며, 경우에 따라 리소스를 빼앗아 갈 수도 있다는 의미이기도 하다. 물론 1차적으로는 단 말의 이러한 기능을 보장해야 하는 것이 필요하며, 다음으로는 우리의 앱이 단말 기능 동작 후 잘 유지되는 지를, 마지막으로 설정 기능으로 적용되어 앱이 동작해야 하는 경우 기능 동작을 보장해야 한다. 일부 문제가 있었던 기능을 보면 다음과 같다. • 음성인식, 녹음 등의 음성 관련: 알림 • 실시간 화면표시, 캡쳐, 촬영 등의 화면 처리 및 저장 등의 프로세싱 관련: 통화 • 검색, 아이디입력 등의 입력 관련: 텍스트 자동 완성
  213. 216 H3 개발자 컨퍼런스 2012 빠른 반복적 출시에 대응할 수

    있는 프로세스 앞선 통계에서 보면, 앱 개발주기는 평균 2~3개월, 대부분 6개월 이내였으며, 프로 젝트를 진행하는 사업체 인력 규모도 24명 이하(72%)로 나타났다. 이는 기존 PC기반 어플리케이션 개발에 비해 주기가 빨라 졌고, 투입되는 인력도 소규모로 진행되고 있 음을 의미한다. 개발 주기가 빨라 졌음에도 적은 수의 개발 인력이라는 의미는 두 개 중 한 가지 의미로 볼 수 있는데, 개발자 들의 역량이 더 뛰어나다거나, 그렇지 않다 면, 개발 규모가 축소되었다는 의미이다. 생각해 보면 비교적 신흥 시장, 앱 개발자의 증가로 미루어 인력의 기술적 향상보다는 개발 규모가 작아 졌다는 쪽에 무게를 둘 수 있을 것이다. 정리하면, “작은 개발규모로 빠르게 개발주기를 가져가고 있다. “로 볼 수 있는데, 이 는 기존 SW 개발 방식과는 다른 형태이며, 그 만큼 고객의 피드백 반영이 중요한 성 공 요소로 부각되었음을 추측할 수 있다. 즉 “기획자가 예측하는 시장”에서 “사용자가 요구하는 시장”으로 변화했으며, 이에 대한 대응을 위해서 개발 주기도 짧게 변화되었 을 것이다. 아임IN, 푸딩 등의 스마트모바일 서비스를 출시하는 KTH에서는 어떠한 변화가 있었 을까? Open & share 그리고 JIRA, Confluence 3전 들여왔던 JIRA와 Confluence. 사실 작년까지만 해도 일부 부서를 제외하고 제 대로 사용하는 부서는 거의 없었다. 여러 가지 문제가 있었던 것도 사실이지만, 그 보 다는 “왜 이 툴을 써야 하는지?” 체감하지 못했던 점이 컸다. 당연히 무관심했었고, 그 러다 보니 사용하는데 무엇인 문제인지도 구체적으로 드러나지 않았다. 그랬던 것이 올해 Open & Share라는 슬로건을 통해 사람들의 업무 패턴이 바뀌게 되며(물론 툴에 일부 맞춘 부분도 있지만) 활성화 된다.
  214. 217 스마트 모바일 시장에서의 품질관리 방안 [JIRA 사용 추이] JIRA

    사용 추이: 2011년을 보면 Defect 관리를 주 목적으로 사용되었음을 알 수 있다. 이에 비해 12년의 경우 전 체적으로 사용 규모가 늘어난 것을 볼 수 있으며, Defect 관리뿐 아니라 Task에 대한 관리도 많이 증가했음을 알 수 있다. Confluence의 경우 GA 통계가 적용되어 있으나 11년 비교 데이터가 없어 보여 주지 못함을 양해 바랍니다. JIRA의 경우에는 Defect 관리라는 기본적인 목적이 있었기 때문에, 활성화에 대해서 최소한의 성공(?)은 보장되는 상황이었다. 그러나 Confluence의 경우, 기존 유의미 하게 관리되는 데이터가 거의 없었던 것이 사실이며, 무엇보다도 Confluence 자체의 Text Editor의 제약 및 문제13들에 의해 과연 얼마나 사용할 수 있을까 우려했던 것 도 사실이다. 하지만 이러한 우려는, 업무 방식이 바뀌며 자연스럽게 해소되었다. 오 히려 더 다양한 시도들이 이루어 지며, Confluence 사용 동력을 만들기도 했다. Confluence 활성화는 Open & Share에 대한 공감에서부터 시작되었다. 공감으로부 터 시도가 이루어 졌고 시도는 회의하고, 토의하는 과정의 업무부터 확정된 내용의 공 유까지 각 업무로 구체화 되었다. 더불어 경영진 역시 Confluence를 통한 업무에 적 극 참여하고, 잘 쓰여 진 글에 대해 적극 격려하면서 사용은 더욱 활성화 되었다. 올 초 활성화를 시도한 지 얼마 되지 않아 사용자들은 Confluence내 “정보의 생산자”에 서, “정보의 소비자”도 가능해 지면서 툴의 긍정적인 선 순환 구조를 만들게 되었다. 13 Confluence의 Wiki 기반의 툴로서 Wiki 기반의 문법을 통한 Editor과 자체 Text Editor를 제공하고 있었다. Wiki Editor의 경우 Text 를 제외하고 모두 wiki 문법을 통해 적용됨으로 인해 초기 사용자들은 문법을 익혀야 했으며, 자체 Eidtor는 매우 불안정 하고, 디테일한 편집 이 불가능하여, 역시 사용이 쉽지 않았다. Confluence가 4.0에 들어서면서 기존 Wiki 기반 문법 사용이 제한되고 자체 Text Editor가 강화 하여 사용자의 접근이 쉬워지긴 했으나, 여전히 결함이나 제약들은 존재했고, 지금도 만족스러운 수준은 아니다.
  215. 218 H3 개발자 컨퍼런스 2012 Confluence를 통한 업무 시도 •

    Confluence를 통한 Storyboard 공유, 그리고 커뮤니케이션  기존 PPT로 되어 있던 제품 기획서를 Confluence 각 페이지에 화면 단위로 구성하였다. 어찌 보면 이중 작업이 었을 수도 있었으나, 크롬 브라우저에서 실행된 Confluence에서 PPT 내용의 Copy & paste를 지원 14하며 가능해 졌다. 각 페이지 단위로 세분화 된 화면들은 토의가 어디에 집중되어야 할지를 명확히 했으며, 더불어 댓글로 주고받은 의견들에 대한 확인을 통해, 사람들이 무엇을 고민하고 어떻게 결정했는지 알 수 있게 되었다. • 일정 현황 관리, Release 공유  각 프로젝트의 구체적인 일정은 Confluence를 통해 관리된다. 서버, 클라이언트 등 해야 할 업무와 완료된 업무 들이 JIRA의 링크나 혹은 CI서버의 제품과 함께 표시되고, 변경은 최대한 빨리 반영된다. 프로젝트의 정보를 일일 이 담당자나 PM에게 물어 볼 필요가 적어 졌으며, 운영 중인 프로젝트의 경우, History 파악이 원활해 졌다. • 요청 게시판 및 현황 공유  Confluence의 장점 중 하나는 JIRA 정보활용이 가능하다는 점이다. JIRA에 정보가 있다면, Confluence를 통 해 보여 줄 수 있다. 이러한 점을 이용하여, KTH에서는 요청 게시판을 만들고, 요청/처리된 현황을 공유하고 있다. 개략적인 구성은 다음과 같다. - Confluence: 요청 및 현황 게시판 (요청 버튼을 두어 JIRA 이슈생성으로 바로 접근 가능, 통계는 JIRA Filter를 통해 JIRA Garget 및 JIRA Issues Macro 활용) - JIRA: 등록 및 현황 처리, 필터 생성 즉 JIRA에 등록된 항목들은 데이터가 되며, Confluence는 대 고객 창구 형태로 이해할 수 있을 것이다. 업무 방식의 변화 앞서서도 언급했지만, 이러한 JIRA, Confluence의 활성화는 업무방식의 변경과 함께 이루어졌다. 구체적인 프로세스 문서와 각 담당자간 역할을 정의하는 프로세스를 만 들고 접근하는 대신, Open & Share와 함께, 기본적인 원칙 몇 가지만을 정의하고 진 행했다. • Iteration을 짧게 계획하자(2주) • 모두 함께 협의하고, 모두 함께 정하자 • 프로토타입을 만들고, 만들어 진 프로토타입을 통해 이야기하자 • Iteration 회고 회의를 통해 우리의 일하는 방식을 점검하자 • JIRA와 Confluence를 활용하여 공유하자 14  크롬 브라우저를 통해 실행된 Confluence에서는 PPT에서 오브젝트를 드래그하여 복사한 후 붙여넣기 하는 것이 지원된다. 물론 이 경우 이미지화 되어 Confluence에 저장함으로 인해 검색 시 검색이 이루어 지지 않는다는 문제가 있지만, Storyboard를 Confluence로 옮 기는 시간을 획기적으로 줄여주었다.
  216. 219 스마트 모바일 시장에서의 품질관리 방안 기존 진행 방식에서 이러한

    변화의 시도 어떤 효과가 있었을까? 먼저 일하는 문화와 관련하여 긍정적인 변화가 있었다. [긍정적 요소] • 프로젝트의 충성도, 조직력 향상  시스템을 통한 정보 공유와 더불어, 프로젝트 진행 중 이슈에 대해 협의하는 활동이 강화되면서, 프로젝트 의사결 정에 참여하는 참여자도 늘어났다. 기존, 개발은 개발관점, 디자인은 디자인 관점에서만 의견을 제시하는 소극적 인 참여자였다면, 이제는 모두가 고객이 되어 바라보고, 같이 만들어나가는 적극적인 구성원으로 변화했다. 당연 히 프로젝트에 대한 충성도는 물론, 이슈에 대응하는 조직력도 향상되었다. • 프로토타입의 활용, 토론 문화 확산  우리가 결정한 내용이 반영된 프로토타입은 우리가 생각했던 것이 가능한지, 무엇을 놓쳤는지 알 수 있게 해 주었 다. 또한 프로토타입을 통해 분야별로 서로 다른 용어로 이야기함으로 인해 발생했던 커뮤니케이션 노력을 줄임으 로써, 보다 활발한 토론 문화가 가능해 졌다. • 인정 그리고 개선 노력  Iteration이 끝나고 진행된 “회고 회의”는 우리가 무엇을 잘했고, 무엇을 잘못하고 있는지 구체적으로 알 수 있게 해 주었다. 각 Iteration에서 발견된 이러한 잘/잘못은 다음 Iteration을 진행하기 위해 우리가 해결해야 할 과제였 고, 그 과제에 대한 성공과 실패의 반복과 기록은 프로젝트의 성공 여부를 떠나 회사의 자산이 되었다. 이렇게 긍정적인 부분도 있었던 반면, 기존 방식과 차이, Agile 경험 부족 등의 이유로 인해 많은 시행착오와 숙제를 남겼다. 사실 프로젝트 진행에 있어서 이러한 시행착오 는 프로젝트 자체에 있어서 일정 지연의 원인이 되기도 하였다. • [계획] Milestone이 되어버린 Iteration  Iteration은 Agile에서 가장 기본적인 개념이고 이를 모르는 사람은 드물지만, 막상 처음 실무에 적용하기란 쉽지 않았다. 처음 Iteration을 적용한 프로젝트에서 Iteration 계획은 폭포수 모델 내의 마일스톤 개념과 별반 다르지 않았다. 기획하고, 개발하고, 검증하는 흐름을 2~4주 간격으로 나누었을 뿐, 산출물이나 활동 계획은 기존과 동일 했다. 결국 수 차례 계획을 수정하면서 진행되었지만, 검증 가능한 산출물은 출시에 임박해서 나왔고, 테스트에 많 은 인력을 투입해야 했다. • [변경통제] 피드백이란 꽃의 가시  프로젝트의 정의를 보면, ‘유한한 기간’이라는 조건이 있다. 즉 일정은 프로젝트의 성립 요소이자 중요한 성 공 기준 중 하나이다. 그런데 업무 방식을 바꾸면서 중요한 가치 하나가 포함되었다. 바로 피드백이다. 프로젝트가 진행 되는 동안 수많은 회의가 있었다. 많은 인원이 다양한 의견을 제시하고, 합의를 통해 결과가 개발 에 반영되었다. 분명 좋은 변화였다. 하지만 의외(?)의 이슈가 발생했다. 시간이 지난 상태에서 이미 확정된 주요 기능에 대해 더 좋은 기능이 제안되었을 때, 반영 여부에 대한 이슈들이었다. 사실 더 좋았으므로, 일정에 대한 부 담이 있었지만 “더 개발되기 전에 발견되었다”는 위안 하에 다양한 고민 없이 변경을 수용하게 되었다. 그라나 결 과적으로 변경은 일정 지연과, 부가 기능의 스펙아웃이라는 부작용을 낳게 되었고, 앱은 시스템적으로나, 기능적 으로 2% 부족한 형태로 출시되었다.
  217. 220 H3 개발자 컨퍼런스 2012 • [개발] 기획을 위한 프로토타입

     Iteration 회의를 통해 살펴보면, 잘 되었고, 만족스러웠다고 이야기 한 부분은 프로토타입이다. 그 만큼 커뮤니케 이션에 도움이 되었고, 피드백 역시 구체적으로 나올 수 있었다.  초기 프로토타입은 기술 적용 시 사용자가 느끼게 될 효과, 성능 테스트를 위한 목적으로 진행되었다. 실제 적용해 봄으로써, 기획자의 생각과 실제 모습이 얼마나 차이가 있는지 눈으로 볼 수 있게 해준 도구였다. 이러한 시도는 UX/UI 설계 시에도 이루어 졌다. 이렇게 디자인해 보고, 저렇게 디자인 해보고 하며 바른 방향으로 맞추어 나갔 다. 그런데 문제는 이러한 시도가, 개발이 이루어져야 할 시점까지도 진행된 것이 문제였다. 이 기간 동안 개발자 는 실질적인 개발 보다는 프로토타입을 기획자의 의도대로 개발하는 것에 포커싱 되었었다. 이로 인해 서버 역시 그 기간 동안은 별다른 작업을 할 수 없었고, 변경이 없으리라 예상하고 개발했던 부분 조차도, 프로토타입의 변경 으로 인해 버려져야 했다. • 문서 vs 커뮤니케이션  Agile 하게 하는데, 과연 어느 정도의 문서가 필요할까? 프로젝트의 규모나 프로젝트 참여자의 물리적 공간, 커뮤 니케이션 활동성 등 여러 가지 측면에 따라 차이가 있을 수 있다. 사실 짧은 기간 동안, 모여서 커뮤니케이션 하고, 집중해서 기획/개발/디자인/검증 한다면, 문서의 상당수는 작성하지 않아도 될 수 있다. 그러나 현실적으로 물리 적 공간에 모여 빠뜨리지 않고, 이상적으로 커뮤니케이션 하는 것은 매우 어려운 일이다. 따라서 최소한의 문서가 필요하다는 점은 누구나 인정 한다. 그러나 어디까지 문서화 하고, 어디까지 커뮤니케이션으로 대체할 지는 미리 논의되지 않았다. 결국 그때 그때 이런 것들이 정해 졌고, 이는 요청이 이루어져야 작성이 이루어지는 형태로 나타 났다. 즉 병렬적 업무진행이 되지 않고 직렬적 업무 진행이 되면서 일정과 문서는 더욱 부담으로 다가 왔다. • [검증] 마지막에 할 수 밖에 없는 테스트  이론과 현실의 차이 인지도 모른다. 프로젝트를 진행하면 가장 어려운 부분은 테스트 시점을 당길 수 있는가? 였 다. Iteration 계획이 잘못되어, 기획이 확정되지 않아, 프로토타입이 검증 목적이 아니어서, 지금은 개발하느라 디 버깅할 여력이 없어서, 등등의 이유로 인해 테스트 일정은 뒤로 미뤄 졌다. 물론 개발팀의 성향에 따라 자체 단위 테스트를 진행하는 경우도 있었지만, 이마저도 내부에서 진행되었음을 확인할 뿐, 확인할 만한 어떤 산출물은 나 오지 않았다. 지금까지 KTH에서 진행했던 “Agile 하게 일하는 방식”의 긍정적인 부분과 숙제에 대 해서 살펴보았다. 정리해 보면, 사람들의 패턴은 많이 바뀌었으나, 아직 업무는 기존 방식에서 벗어나고 있지 못한 듯 하다. 물론 첫 술에 배부를 수 없다는 것은 잘 알고 있다. 하지만 밥 첫 술을 어떻게 먹었는지, 제대로 먹긴 했는지 살펴보고 둘째 술에서 는 보다 배부르게 먹어야 하지 않을까? 위 내용 QA 관점에서 바라본 일부 프로젝트의 모습이었다. 그리고 그 모습을 바탕으 로 QA 관점에서 몇 가지 기본적인 제안을 하고자 한다. • 주요 기능 기획은 개발 Iteration계획 전에 확정  계획은 우리가 하고자 하는 바를 어떤 절차로 진행하고, 거기에서 발생할 수 있는 Risk를 예측/대응하여 정해진 일정 내에 완수하도록 고민하는 활동이다. 따라서 하고자 하는 바나 어떻게 할 지가 정해 지지 않은 상태에서 계획 하는 것은, 무언가가 정의됨에 따라 다시 계획하겠다고 하는 것과 마찬가지이다.
  218. 221 스마트 모바일 시장에서의 품질관리 방안  주요 기능에 대한

    기획은 우리가 무엇을 할지를 정하는 활동으로, 여기에서 내용이 나와야 어떻게 진행할 지, 어떻 게 개발할 지가 나오므로 선 정의 되어야 한다.  만일 기획 확정에 고민이 필요하다면, 기획 기간을 늘리고, 보다 많은 사람들이 참여하고, 검증하는 형태로 보완을 고민해야 할 문제이지, Iteration개발과 병행 키신다고 해결되는 문제는 아니다. • Iteration은 하나의 Release가 되도록  Iteration은 설계, 개발, 검증을 반복하는 활동이다. 우리가 처음 하고자 했던 Task(To do)의 달성을 향해 달려가 는 활동인 것이다. 기획 Iteration, 개발 Iteration처럼 기획만 하고 개발만 하는 Iteration이 아니라, Iteration 내 에 개발과 검증, 그리고 Release가 이루어져야 하는 것이다. 그리고 나서 피드백을 받고, 다음 Iteration에서 피드 백의 반영 여부, 수준을 정의하여 To do를 조율해야 한다. 피드백 분석 및 반영 여부/수준은 다음 Iteration 전에 이루어 져야 한다. • 프로젝트 초기, 문서는 정의되어야 한다.  우리의 기억력은 얼마일까? 스토리보드, 예외처리, 정책정의 등 우리가 프로젝트를 진행하며 정해야 하는 것들은 수도 없이 많다. 물론 잦은 커뮤니케이션을 통해 그때 그때 정하고, 그때 그때 적용하는 것이 효율적이지만, 우리 가 모든 것을 기억할 수는 없다. 따라서, 오히려 주요한 것 보다는 사소한 것에 문서화가 필요하다. 가령 워크 플로 우 별 이벤트 예외 처리라던가, 메시지 리스트, 제약범위 등과 같이 소소하지만 서로 동일한 내용을 기억해야 하는 경우 문서화가 필요하다. 초기에 각 담당자들이 모여 필요한 문서를 정의하고, 문서 작성 완료일을 정하는 것이 필 요하다. 위 사항은 기본적인 것들이다. 하지만 진행하다 보면, 이러저러한 이유로 잘 안 되는 부분이기도 하다. 아마 각자의 회사에서 각자가 경험했고, 각자가 생각하는 바가 있을 것이다. 이 세상에 정답이 없듯이 KTH QA가 이야기 하는 것도 정답은 아닐 수 있다. 다만 각자의 위치에서 이러한 부분에 대한 고민과 진행 되는 프로젝트에 대입해 시 뮬레이션 한다면, 곧 각자의 회사에 적합한 프로세스가 만들어 지지 않을까? 예측 해 본다. 품질을 좌우하는 개발자 지금까지 “치열한 시장 환경 속에 사용자의 요구에 민첩하게 대응하기 위한 테스트 전 략 및 프로세스에 대해 고민해 보았다. 그런데 테스트 전략을 잘 수립하여 테스트하 고, 시장에 최적화된 프로세스를 잘 설계하면, 품질을 확보할 수 있을까? 사실 테스트는 확인 방법 중 하나이고, 프로세스는 일하는 방법이다. 이런 것들은 품 질을 위해 필요 조건 중 하나이지 충분 조건은 아니다. 즉 최종 산출물의 품질 향상을 지원하는 도구이지, 품질, 그 자체를 제어하진 못한다. 실제로는 개발자가 얼마나 잘 개발했는가에 따라, 달라지며 프로세스는 달라진 환경 에 따라 “잘 개발할 수 있도록” 지원하는 도구이며, 테스트는 “잘 개발 되었는지” 확
  219. 222 H3 개발자 컨퍼런스 2012 인하는 도구일 뿐이다. 따라서 제품의

    품질은 개발자에게 달려 있다고 해도 과언이 아니다. 더 요구되는 개발자의 역할 개발자가 개발만 잘하면 될까? 사실 이것도 쉽지 않지만, 시장 상황은 그 이상을 요구 하고 있다. 오픈시그널앱스에서 공개한 Android 단말 파편화 자료15에 따르면, 3997개의 Android 기기가 운영되고 있으며, 각기 다른 OS, 해상도, 프로세서, 부가 기능(카메 라, 센서 등)을 가지고 있는 것으로 나타났다. [Android 단말 파편화 현황] 이러한 파편화 양상은 Android 시장이 확대 되면서 더욱 강하게 나타날 전망이며, 이 런 단말시장의 파편화는 앱의 품질을 보증하기 위해, 고려해야 할 사항이 많아 진다는 것을 의미한다. 기획부터 대상모델을 어떻게 가져갈지, 기능 범위를 어디까지 지원할지 고민되어야 하며, 디자인 역시, 해상도 차이를 극복하기 위한 방안을 고민해야 한다. 개발은 말할 것도 없고 품질 역시 지원대상 모델에 대한 테스트 단말 샘플링을 해야 한다. 큰 틀에 서만 봐도 어느 것 하나 만만한 것이 없다. 15 http://opensignalmaps.com/reports/fragmentation.php?
  220. 223 스마트 모바일 시장에서의 품질관리 방안 정보란 보물의 생산자 역할

    그런데, 문제는 여기서 발생한다. 무언가 고민하고 판단하기 위해서는 데이터가 필요 한데, 단말기의 특성 정보는 매우 부족하다는 것이다. 품질 쪽만 놓고 보자. 수많은 단말 중 테스트 단말을 샘플링 하기 위해서는, 제조사, 해상도, OS, 단말 기능과 같이 드러나는 부분뿐 아니라, GPU 정보 및 특성, 앱 구동 메모리 크기, OS별 제약 사항, 등 드러나지 않는 많은 정보가 필요하다. 테스트 역시 개발된 기능 특성과 단말의 HW/SW 적 특성을 고려하여 위험 요소를 식별하고, 그 위 험 요소의 발생 경로를 설계하여 진행하기 위해서는 의미 있는 정보가 필요하다. 또한, 앞서 치열한 시장환경 속에서 개발 주기가 짧아 졌다고 했는데, 실제로 개발 주 기를 짧게 가져가기 위해서도 이러한 정보의 활용은 중요하다. 짧은 개발 주기 내에서 는 하나의 시행착오가 미치는 영향은 커지게 되는데, 가령 6개월 중 1주일 지연이라 면, 납득 할 수 있는 수준이 되지만, 1개월 중 1주일이라면, 1/4 정도가 더 지연되었 다는 것으로 심각하게 볼 수 있다. 따라서 이러한 정보의 공유를 통해 사전에 차단할 수 있는 시행착오를 줄이는 것이 더욱 중요해 진 것이다. 그렇다면, 이러한 정보는 어떻게 마련할 수 있을까? 기획, 디자인, 개발, 품질, 각자 의 역할에서 마련할 수 있겠지만, 가장 정확하고 유의미한 정보는 개발에서 나올 수 있다. 설계 검토, 기능 개발, 디버깅, 등 일련의 개발 활동은 이러한 정보를 생산하고 활용하는 과정이다. 그냥 설계 할 수 있는가? 당연히 제약 사항이나 특성을 고 려할 것이다. 개발 역시 이러한 특성을 고려해서 가능여부, 우회방법을 고민하 고 적용하게 된다. 디버깅 역시 미처 고려하지 못했던 부분을 보완하는 활동이다. 즉 개발 과정은 단말 특성뿐 아니라 우리가 개발하고자 하는 제품의 특성에 대한 정보 를 가득 담고 있는 보물 창고인 것이다. 이제 결론은 명확해 진다. 결국 개발자가 개발만 잘하는 것뿐만 아니라 정보의 “생산 자”로서의 역할을 수행해야 한다는 것이다. 또한 생산자로써 끝나는 것이 아니라 기 획, 디자인 등의 비 개발자도 이해할 수 있도록 가공하여 공유하는 것도 필요하다. 보물 발굴을 위한 개발자의 첫 걸음 개발자가 정보의 생산자로써 역할 수행이 필요하다고 주장했다. 그렇다면 어떻게 해 야 할까? 그 첫 단계는 결함에 대한 정보 기록이다.
  221. 224 H3 개발자 컨퍼런스 2012 흔히들 BTS(Bug Tracking System), ITS(Issue

    Tracking System)라고 부르는 툴들 은 사용해 보면, 결함 하나에도 입력해야 할 다양한 필드들이 있다. 당연히 시스템 개 발사들이 시간이 남아 생각나는 대로 개발한 것이 아니다. 품질과 관련하여, 결함과 관련하여 축적된 경험과 기술, 시장의 요구를 토대로, 필드 하나 하나가 포함된 것이 다. 그럼에도 불구하고 우리는 필요한 몇 가지 필드만 작성하고 만다. 해당 입력 필드 체크가 필요 없어서가 아니다. 하다 보니 귀찮아서 이다. 그러다 보니 거기에는 정보 도 없다. 그냥 이유를 알 수 없는 결함들만 등록되어 있다. 사실 보물 발굴을 위한 첫 걸음은 여기서부터 시작한다. 결함이란 제품이 의도한 데 로, 동작하지 않는 것을 의미한다. 즉 개발자가 단순 코딩 실수를 했던, 고려해야 할 사항 중 놓친 부분이 있든, 아니면 기획자가 상충되게 기획을 했던, 단말 제약 사항이 던, 무언가 결함을 발생 시킨 원인이 있다. 이러한 결함의 원인은 분석 결과에 따라 단 말 제약사항에 대한 정보 일 수 있고, 제품의 특성일 수도 있고, 기술적 정보일 수도 있다. 결함이 보석의 원석이라면, 원인에 대한 분석은 가공하는 단계이고, 파악된 원 인은 보석이 되는 것이다. 실제로 결함 수정을 위해서 원인 파악은 당연히 수행되어야 하고, 수행될 수 밖에 없 는 기본 활동이다. 보물 발굴의 첫걸음은 이런 당연한 내용을 누구나 이해할 수 있게 구체적으로 기록하는 데에서 출발한다. 사실 개발자가 결함의 원인과 처리내용에 대해 기록하는 것은 정보적 가치 측면뿐 아니라 직접적인 제품 품질과도 밀 접하다. 개발자가 발견된 결함에 대해 원인을 적게 되면, 어떤 실수, 문제, 이슈가 있었는지 더욱 오래 기억하게 되며, 동일하거나 유사한 결함을 예방하는 데에 도움이 된다. 특히 짧고 반복적인 개발 주기 내에서는 큰 기능의 추가 보다 는 개발된 기능을 개선하고, 관련한 부가 기능을 추가하는 경우가 많기 때문에 이러한 기억의 효과는 더욱 커진다. KTH 뿐 아니라 이전 회사에서도 앱 개발에 참여 했는데, 최초 신규 개발 시점을 제외하고 이후 Iteration 개발 과정 에서 가장 큰 일정 지연 요소는 결함이었다. 신규 기능의 결함은 물론이고, 이전에 수정 되었던 결함, 정상적으로 되던 기능이었는데 발생하는 결함 등, 매 Iteration 별로 등장하는 결함을 해결하기 위해 매번 같은 수준의 테스트(전체 검 증)와 기간이 필요했다. 이는 결과적으로 Iteration 주기가 늘어난 것과 같았다. 짧아진 개발 주기에서 결함의 감소는 테스트 비용을 낮추고 적기에 제품을 출시 할 수 있는 기본 조건인 셈이다. 개발자가 결함 원인과 처리내용에 대해 기록하게 되면, 최소한 이전에 수정되었던 결함의 재발되는 것을 최소화 시켜 준다. 귀찮고 번거로운 일이지만, 스마트폰 앱 시장에서 반드시 필요한 활동이다.
  222. 225 스마트 모바일 시장에서의 품질관리 방안 스마트 모바일 환경에서의 자동화

    도구를 이용하여 테스트를 자동화하고 지속적인 통합 환경에 적용하는 것은 이미 많 은 SW개발에서 진행되고 있다. 모바일 앱의 출시 후 지속적인 업데이트를 계획하고 있다면, 개발하는 앱의 특성이나 크기를 고려해 적절히 자동화 하는 것이 필요하다. 또한 이번 H3의 DevOps 관련 발표처럼, DevOps 환경에서 품질 확보를 위한 테스트 자동화는 필수 요소다. “모바일에서 테스트 자동화 하기”에서는 모바일에서 동적/정적 테스트 자동화 가능 여 부와 오픈 소스 및 무료 도구를 이용한 몇 가지 방법, KTH의 고민과 적용 사례를 살펴 본다. 모바일에서 테스트 자동화는 가능한가? 가능하다. 다만, 테스트 단계나 테스트 대상(앱/서버)에 따라, 개발하는 앱의 특성에 따라 적용할 수 있는 테스트 단계나 도구, 난이도의 차이가 있다. CI(Continuous Integration)를 이용하지 않는다고 해도, 앱과 서버 모두 기본적으로 단위 테스트의 자동화가 가능하다. 단위 테스트는 개발자 스스로 잘 개발해가고 있는 지 확인하고, 또는 담당자가 바뀌고 만약 인수인계가 잘 되지 않았더라도 코드의 품질 을 확보하는 최소한의 안전장치다. Android, iOS, Windows 8의 SDK는 단위 테스트 를 기본 지원하고, 서버단 개발에도 xUnit 계열의 단위 테스트를 쉽게 사용할 수 있다. 이처럼 단위 테스트의 범위, 수준, 사용하는 프레임워크와 상관없이 단위 테스트는 필 수이므로, 여기에서는 단위 테스트를 다시 살펴보지 않는다. 그러나 모바일, 특히 앱단의 자동화는 아직까지 활용할 수 있는 도구와 자료가 부족하 다. 다행히 서버단은 다른 SW 개발에도 적용되고 있는 분야이므로 관련 도구나 자료 가 상대적으로 다양하다. 통합/시스템 테스트 자동화는 앱과 서버를 구분해서 다음 단 락인 앱단/서버단 자동화에서 살펴본다. 소프트웨어를 직접 실행해서 결함을 찾는 동적 테스트와 별개로, 소프트웨어를 실행 하지 않고 결함을 찾는 정적 테스트인 정적 확인/검증도 적용할 수 있다. 리뷰나 코드 검토처럼 수동으로 수행할 수 있고 PMD, FindBug와 같은 소스코드 분석 도구를 적 용할 수도 있다. 정적 테스트 자동화 역시 PMD를 위주로 다음 단락인 앱단/서비스단 자동화에서 살펴본다.
  223. 226 H3 개발자 컨퍼런스 2012 앱단(Mobile Application-side) 테스트 자동화 방법

    모바일 웹의 경우 Selenium과 같은 도구를 이용해 테스트를 자동화 할 수 있지만, 아 직 앱 내에서 표현하는 웹 앱(Web-App) 방식은 지원하지 않는다. 단위 테스트를 제 외하고 앱단에 적용할 수 있는 대표적인 자동화 도구로는 monkey와 monkeyrunner 가 있으며, record & play 방식으로 테스트하는 도구도 있다. Android 기능 테스트 - monkey와 monkeyrunner monkey16와 monkeyrunner17는 Android SDK에서 지원하는 자동화 도구이며, 이 름은 비슷하지만 테스트 대상이나 작동 방법은 전혀 다른 도구이다. • monkey  monkey는 기능 테스트 도구지만, 스트레스 테스트 도구로도 분류된다. 탭, 이동, 하드웨어 키(홈, 뒤로, 메뉴, 볼륨 키 등) 등 사용자의 이벤트를 랜덤하게 발생시켜 테스트하며 전체 이벤트 개수 및 각 이벤트의 비율을 조정할 수 있다. 명령줄(Command Line)에서 실행시키며, 단말이나 에뮬레이터를 이용해서 테스트한다. • monkeyrunner  monkeyrunner는 테스트를 위한 API로, 외부 코드에서 Android를 제어하는 도구이다. monkeyrunner는 Jython으로 API를 이용하며, 앱의 설치, 실행, 테스트, 결과 스크린샷 캡처 기능을 제공한다. 이 도구를 사용하기 위해서는 테스트 코드를 작성하고, 명령줄에서 실행한다. Record & Play 방식 기능 테스트 더욱 “사용자단(user-side)”의 기능 테스트 자동화를 위해서는 record & play 방식, 즉 정상 진행 결과에 대한 화면을 저장한 후 테스트하면 나온 결과 화면과 비교하는 방법이 있다. KTH의 경우도 반복되는 테스트의 자동화를 위해 record & play 방식의 도구 적용을 검토한 적이 있다. KTH에서 출시하는 대부분의 앱은 서비스 종료 전까지 지속적인 업데이트를 진행하며 짧게는 2주 주기로 업데이트를 진행한다. 개발 중 몇 단계의 테스트를 거치지만, 사람이 진행하는 최종 단계 기능 테스트의 자동화를 고려 하여 몇 가지 상용 도구를 검토했으나 다음의 이유로 도입을 유보했다. • 도입 목적 - 사람의 판단(UX, 보안 등)이 불필요한 최종 단계의 기능 테스트 자동화 16  http://developer.android.com/tools/help/monkey.html 17  http://developer.android.com/tools/help/monkeyrunner_concepts.html
  224. 227 스마트 모바일 시장에서의 품질관리 방안 • 도입 유보 사유

    - 숙련자 기준, 기능 1개의 스크립트를 신규 작성하는데 시간이 많이 걸림(약 2시간) - UI가 변경되면 스크립트를 재작성해야 함 - Android 파편화(특히 해상도 관련)에 대한 재작업이 많음 KTH 앱은 업데이트 시 사내 UX 전문가의 검토 후 UI를 개선하고 알림 공지(내 알림 아이콘에 1, 2 등 숫자를 표시하여 확인하지 않은 개수를 알려주는 것)를 이용하는 앱 이 많다. 따라서 스크립트를 계속 변경해야 하는 도구 보다는 기존처럼 사람이 테스트 케이스 및 경험을 기반으로 테스트 하는 것이 낫다는 판단을 했다. 만약 UI보다 내부 로직 위주로 업데이트를 진행하는 앱이라면 이 방식의 테스트 도구 도입은 효과가 있 을 수 있다. 아직 모바일 앱의 Record & Play 방식 기능 테스트 도구가 성숙한 단계는 아니지만, 기능 테스트의 자동화가 필요하다면 지속적으로 관심을 가질 필요가 있는 분야이다. 정적 테스트 - PMD Java 소스코드 정적 분석 도구인 PMD는 Android 앱 개발에 이용할 수 있다. PMD는 사전에 정의된 룰을 이용해 소스코드를 검증하는데, 기본 지원 룰셋(룰을 종류에 따라 모아놓은 단위)에 Android용 룰셋이 있다. PMD의 Android 룰셋에는 3개의 룰만 있으나, Basic이나 Design 룰셋은 Java 코딩 의 일반적인 권장사항에 대한 내용이므로 Android 앱 개발에서도 충분히 활용이 가능 하다. 예를 들어, 빈 catch 문이나 조건문은 없는지, 활용한 자원은 close() 했는지 등 이 이 룰셋에 포함된다. 다음 표는 PMD에서 지원하는 Android용 룰이다. 룰셋 룰 Android (java) CallSuperFirst Android (java) CallSuperLast Android (java) DoNotHardCodeSDCard [PMD의 Android 룰셋] PMD는 서버단 자동화에 보다 자세히 살펴보자.
  225. 228 H3 개발자 컨퍼런스 2012 서버단(Server-side) 테스트 자동화 방법 서버는

    꼭 앱이 아니더라도 서버-클라이언트 기반 SW에서 사용하였으므로, 모바일 서비스의 서버단이라고 해서 특별히 달라지지는 않는다. 또한 모든 앱이 서버를 사용 하지는 않는다. 그러나 서버가 있는 앱은 그렇지 않은 앱보다 일반적으로 기능 규모나 복잡도가 크다. 그리고 기획/사업단에서 신규 버전 외의 모든 구 버전 앱은 사용자가 업데이트를 하지 않으면 사용이 불가능하게 하는 강력한 사용 제한을 결정하지 않는 다면, 서버는 동일한 앱의 다양한 버전을 지원해야 하고, 또 지속적으로 업데이트 해 야 한다. 또한 사용자는 각 기능이 3초 이내에 응답하는 것을 기대18하고 있으며, 이 에 따라 앱도 최적화 되어야 하지만 서버 API도 가급적 1초 이내에 서비스를 해야 한다. API 테스트 - soapUI 앞서 살펴보았듯이 모바일 앱에서 사용하는 서버는 동일한 앱의 다양한 버전을 지원 해야 하므로, API 테스트를 자동화 하면 서버에서 다양한 앱 버전에 대응하는 API를 유지하는데 도움이 된다. 예를 들어 버전이 2.0인 앱이 3.0으로 업데이트를 해도, 앱 을 업데이트 하지 않는 사용자를 위해 2.0 서비스는 계속 유지해야 한다. 이 경우 기존 2.0의 API와 기능이 추가되고 개선된 3.0 API를 동시에 서버에서 서비스해야 하는데, 서버 업데이트는 주로 3.0 위주로 진행될 것이다. 3.0을 업데이트 하면서도 2.0 API 가 적절히 동작하는지 지속적으로 확인하는데 API 테스트 자동화가 필요하다. 최근 서버를 사용하는 앱은 RESTfull 방식의 API를 주로 이용한다. RESTfull를 포함 한 다양한 방식의 API를 테스트하는 대표적인 도구로 soapUI19가 있으며, 무료 버전 과 유료 버전으로 구분되지만 무료 버전을 사용해도 충분히 테스트 가능하다. soapUI를 이용해서 테스트하는 방법은 다양하겠지만, 앱에서 API에 특정 파라미터 를 넘겼을 때 assertion을 이용하여 응답 값에 특정 문자열(필자의 예에서는 정상 응 답임을 표시하는 “0x02000” 코드로 확인)이 있는지 확인하는 방법도 가능하다. 다 음 그림은 API 응답에서 “0x02000”을 assertion으로 확인하는 soapUI 화면이다. 좌 측 트리에는 API에 대한 정보가, 메인 창에는 이 API의 응답에 대한 정보가, 팝업이 “0x02000”를 assertion으로 검증하라고 지정하는 부분이다. 몇 가지 사내 정보는 모 자이크 처리 했음을 양해해주기 바란다. 18 "국내 주요 웹사이트 및 모바일 사이트 성능 분석 보고서", 2012, Compuware 19 http://www.soapui.org/
  226. 229 스마트 모바일 시장에서의 품질관리 방안 [soapUI로 테스트 케이스 작성]

    이렇게 테스트 케이스를 작성하고 테스트를 하면 다음과 같이 테스트 성공 여부를 알 려준다. 이 때 각 테스트 스텝, 케이스, 스위트 단위로 테스트를 수행하고 결과를 확인 할 수 있다. 테스트가 성공이면 초록색으로, 문제가 발생했다면 빨간색으로 표시된다. [soapUI로 테스트 수행한 결과 – 정상의 경우]
  227. 230 H3 개발자 컨퍼런스 2012 또한 soapUI는 Maven과 연동이 가능하며,

    연동 방법은 soapUI 사이트에 설명20 되 어 있다. 주요 IDE의 플러그인으로 사용할 수도 있으며, Eclipse, IntelliJ 등을 지원 한다. 아직 KTH에서 공식적으로 사용하고 있지는 않지만, 현재 KTH에서 개발 진행 중인 서비스에서 사용을 준비하고 있으며 내년 H3에는 적용 시 고민한 내용과 효과를 공유할 것이다. soapUI는 같은 회사에서 만든 무료 성능 테스트 도구인 loadUI와 쉽게 연동된다. soapUI에서 작성한 테스트 케이스는 loadUI의 성능 테스트 대상으로 변환하여 사용 할 수 있다. 성능 테스트 - loadUI, LoadRunner 앱이 사용자에게 3초 안에 서비스하기 위해서는, 앱 성능, 네트워크 성능, 서버 성능 이 모두 목표를 만족해야 한다. 이 중 네트워크 성능은 우리가 직접 다루기 어려운 부 분이지만, 앱과 서버는 테스트 및 최적화를 반복하며 성능을 향상시킬 수 있다. 성능 테스트는 도구를 이용한 자동화가 필수인 테스트 분야이다. 목표한 성능을 만족 하는지 부하를 발생시키는데 도구가 반드시 필요하기 때문이다. 대표적인 상용 도구는 HP의 LoadRunner가 있지만 라이선스 비용이 높은 편이어서 도입이 쉽지 않으므로, 무료로 사용할 수 있으면서 유용한 기능을 제공하는 loadUI21 를 우선 살펴본다. LoadRunner는 API를 테스트하는데 필요한 스크립트 코드만을 알 아본다. loadUI loadUI는 앞서 말한 soapUI와 쉽게 통합할 수 있으며, soapUI에서 테스트 케이 스로 지정한 API를 불러와 테스트 할 수 있고, soapUI 테스트 시 loadUI를 동시에 테스트 할 수도 있다. soapUI는 부하 발생기, 스케줄러, 흐름 등을 왼쪽에 있는 컴포넌트를 이용하여 생 성하고, 각 컴포넌트를 연결해서 테스트할 구조를 만든다. 다음의 화면은 loadUI 에서 생성한 테스트 케이스를 soapUI에서 불러오고, 0.5초마다 이 API를 호출하 였을 때의 성능 테스트 결과를 보여준다. 20 http://www.soapui.org/Test-Automation/maven-2x.html 21 http://www.loadui.org/
  228. 231 스마트 모바일 시장에서의 품질관리 방안 [loadUI를 이용한 성능 테스트]

    loadUI도 LoadRunner 처럼 다른 컴퓨터에 부하 발생기용 Agent를 설치해서 부하 를 발생시키고 부하량이나 부하 시나리오를 조정할 수 있다. Maven 및 Jenkins 등 CI 환경과 통합할 수 있다는 것이 LoadRunner와 구분되는 장점이다. LoadRunner HP LoadRunner는 업계 표준 성능 테스트 도구이며 오랜 기간 업데이트 되어 높 은 신뢰성 및 다양한 프로토콜 지원의 장점이 있다. 그러나 높은 비용으로 쉽게 도 입하기는 어려운 도구이다. 여기에서는 HP LoadRunner를 이용한 API 성능 테스트 스크립트를 살펴본다. 기 본으로 생성되는 스크립트에 약간의 사용자 코딩을 더하면 soapUI와 비슷한 API 테스트를 성능 테스트와 동시에 진행할 수 있다. 다음 그림은 API 1개를 테스트하며, soapUI와 동일하게 “0x02000” 문자열 체 크를 이용해 정상적으로 처리하는지 확인하는 스크립트다. 이 예에서는 API의 파 라미터를 동일하게 호출하지만, LoadRunner의 기능을 이용해서 다양한 매개 변수 값을 조합해도 정상 처리하는지 확인하도록 수정할 수 있다. 다음 예제는
  229. 232 H3 개발자 컨퍼런스 2012 LoadRunner의 구 버전인 8.0 버전으로

    테스트 하였다(현재 버전은 11.5). 업데 이트를 못한 구 버전에서 Web/HTTP 프로토콜을 이용하면 Web Service 프로토 콜을 이용하지 않아도 API 성능 테스트가 가능하다. [LoadRunner로 API 테스트하는 스크립트] KTH는 기본적으로 API 성능 테스트에 LoadRunner를 이용하지만, soapUI처럼 신규 개발 진행중인 서비스에서 loadUI의 활용을 준비하고 있다. LoadRunner는 Maven 및 Jenkins와의 통합을 지원하지 않아 CI 환경과 연동하거나 개발자 위주 의 사용은 어려움이 있다. 정적 테스트 - PMD KTH에서는 앞서 앱단 정적 테스트에서 잠시 살펴봤던 PMD를 서버단의 정적 테스트 를 위해 사용하고 있다. PMD22는 최근 v5.0이 릴리즈 되었으나, Maven 및 Jenkins 플러그인이 v4.3만을 지원하여 현재는 v4.3을 사용한다. 22  http://pmd.sourceforge.net/
  230. 233 스마트 모바일 시장에서의 품질관리 방안 PMD에는 기본으로 약 300개의

    사전 정의된 룰이 포함되어 있다. 그러나 이 룰에는 XML이나 JSP 룰이 포함되어 있으므로, QA는 개발자와 협의한 후 필요한 룰만 선택 해서 사용하는 것이 좋다. 일례로, KTH는 한 서비스의 신규 개발 시 개발자와 협의를 통해 필요하다고 판단된 70여개의 룰만 선정해서 사용하고 있다. 이렇게 선정한 룰은 하나의 XML 파일로 만들어 웹 서버에 올린 후 이 URL을 개발자에게 배포한다. 메일, 게시판, SCM 등을 이용해서 배포할 수도 있지만, 개발자 IDE, Maven, Jenkins 플러 그인에서 동일한 룰을 사용하고 QA가 효율적으로 룰을 개선/관리하기 위해서는 웹에 올리고 해당 URL을 개발자에게 배포하는 것을 추천한다. 신규 개발 서비스는 PMD 룰을 위반하는 코드가 0인 것을 목표로 한다. 그리고 운영 중인 서비스에 PMD를 적용하는 경우 테스트 코드가 있는 소스코드에 대해서만 룰 위 반을 수정하도록 개발자에게 권고한다. PMD를 Maven에 통합할 경우 룰 위반 시 빌 드 실패를 유도할 수 있다. KTH는 이 기능을 사용하지 않지만, QA의 입장에서 강력 하게 적용하고 싶거나 정적 분석이 반드시 필요한 프로젝트라면 이 기능의 사용을 고 려해보자. 모바일에서 테스트 자동화를 위해서는 앞서 살펴봤듯이, 서버에 비해 앱 단의 자동화 도구는 그 수와 자료가 상대적으로 부 족하다. 그러나 모바일 앱의 활성화에 따라 점점 활용할 수 있는 오픈 소스 및 상용 테 스트 도구는 다양해지고 있다. 모바일 앱 개발, 특히 앱단에 테스트 자동화를 적용하 려면 우선 OS/모바일 단말의 단편화, 앱 업데이트 주기를 고려하자. 그리고 QA가 테스트 자동화를 추진한다고 해도 가장 핵심적인 역할은 개발자가 수행 하므로, 한번에 모든 것을 적용하는 것보다 시니어 개발자에 의한 필요 공감대 형성 및 가이드, 가장 효과가 있는 도구부터 단계적 적용, QA와 개발자의 원활한 의사소통 이 필요하다.
  231. 234 H3 개발자 컨퍼런스 2012 고객 유지율을 40% 향상시기고, 긍정적인

    구전을 두 배 늘려 줄 Startup의 생존 필수 아이템 요약 3,000만명이 넘는 스마트폰 유져가 생겨났고, 100만개 가까이 되는 앱들이 쏟아져 나와도 그 앱에 문제해결 요청이나 제안을 할 수 있는 채널은 없습니다. 고객은 참고 쓰거나 답도 없는 앱스토어 리뷰나, 트위터, 페이스북, 까페에 기약 없는 대자보만 붙 여 대고 있습니다. 개발사는 문제를 알아도 어떤 기종에서, 어떤 버젼에서 발생하는 건지 알수도, 고객에게 물어볼 수도 없습니다. 피차 난감한 상황... 당연한 것으로 생각하는 이러한 현상이 모바일 어플을 만드는 개발사에 어떤 치명적 인 영향을 미치는지, 또 이러한 소통채널 부재로 인해 발생하는 부정적인 소문을 어떻 게 효율적으로 차단할 수 있을지, Start-up 개발사에겐 생존 필수 아이템이 될 [BaaS 모바일 고객센터]가 개발자 분들께 그 대안을 제시해 드립니다. 스타트업 개발사의 생존필수 아이템, baas.io 모바일 고객센터 고객가치혁신팀 유용선 [email protected]
  232. 235 스타트업 개발사의 생존필수 아이템, baas.io 모바일 고객센터 시중에 서비스의

    제작과 마케팅에 대한 많은 자료들이 있는 반면, 서비스 운영, 특히 모바일 서비스 운영에 대해서는 중소 개발사들이 참고하거나 적용할 만한 사례나 정 보들이 전무(全無)에 가까울 정도로 부재한 상황입니다. 이제는 모바일 개발자도 런칭과 동시에 체계적인 운영을 고민 해야 할 시점이 되었습 니다. 그동안 KTH가 서비스를 해오면서 쌓아온 여러 시행착오와 경험들을 공유함으 로써 중소 개발사들이 경쟁력을 높이는데 도움이 될 것으로 생각합니다. 스마트폰 3,000만의 새로운 전장(戰場)에 맞는 생존 필수 아이템. KTH BaaS 모바일 고객센터… 그 가시적,경제적 효과와 손쉬운 탑재 방법을 설명합 니다. 다음의 질문에 답이 망설여 진다면 지금부터 집중^^ 하세요 Q.  10,000명의 다운로드 고객을 확보한 A사와 B사가 있다. A사는 매달 40%씩 신 규고객을 추가로 확보하고 이중 80%고객을 재방문 하도록 한다. 반면 B사는 적 극적인 마케팅으로 매달 80%의 신규 고객을 추가로 유치하지만, 이 전체 고객 의 40%만을 유지한다. 이때, 6개월 후 양사의 보유 고객 수는 어느 쪽이, 몇 배 나 많을까요? Q. 사람들이 어플을 선택하는 기준은 무엇이고 어떤 것을 가장 신뢰할까요? Q.  어플을 쓰면서 불편 경험율은 어느 정도 이고, 이중 매번 또는 빈번하게 불편을 경험하는 비율은 얼마나 될까요? Q. 어플을 쓰면서 고개들은 주로 어디서 문제를 만나고, 어디서 해소 할까요? Q.  불편 해소가 안되면 이 고객들은 [이용감소/부정적 구전/이용 중단]등의 부정적 인 행동을 합니다. 불만해소가 안된 10명이 있다면 몇 명이 이런 행동을 보일까 요? Q.  리뷰나 SNS에 남겨지는 신고로는 Phone, Pad, OS, 단말기, Version별로 다르 게 나타나는 문제를 정확히 파악하거나 취해진 조치 결과를 고객에 알리는 것 도 불가합니다. 해결방법은 어떤 것이 있을까요?
  233. 236 H3 개발자 컨퍼런스 2012 Q.  트위터나 페이스북으로 응대를

    하는 경우 어떤 문제에 봉착하게 될까요? Q.  발생하는 문제중에 공식 트위터나 블로그, 페북으로 들어오는 문제는 몇 %나 될까요? 스마트폰 3,000만 시대의 의미 국내 스마트폰이 3천만을 넘어섰다. 전 세계를 판타지 신드롬에 몰아 넣었던 해리포터의 8년간 8편 누적 국내 고객수가 3 천만명… ‘웰컴 투 동막골’과 ‘말아톤’으로 2005년을 쓸었던 <쇼박스>의 한해 총 23편의 누적 관 객수가 3천만명. 투캅스, 실미도, 공공의 적, 이끼 연출한 강우석 감독의 12년 누적 관객수가 3천만명. 맨날 미어 터지는 우리나라 자동차들. 주차장에서 쉬는 자동차 다 꺼내와도 2천만대 가 안된다. 2011년 현대자동차에서 가장 많이 팔린 최다판매 차량. 아반떼가 국내 달 랑 13만대다. 3천만대의 스마트폰은 적어도 대한민국에서는 어머어마한 수치의 경험치다. 대한민국에서 3천만이라는 의미는 전체 인구의 63%가 쓰고 있다는 소리이고 15살 이상 경제 인구 10명 중 7~8명이 쓰고 있다는 얘기가 된다. 카카오톡의 하루 이용 고객수가 철옹성 네이버의 일간 방문 고객수의 1.6배를 넘었 고, 금융권에서는 은행창구 거래액 보다 모바일 뱅킹 거래가 훨씬 많아졌다. 상장이후 주식이 반토막이 난 페이스북도 모바일 MAU(월간실제사용자수)가 2011년 2Q대비 67% 증가를 했다. 새로운 거대한 시장과 생태계가 만들어 지고 있고, 유행과 트랜드를 지나서 일상의 모 습을 바꾸는 ‘문화’의 단계에 진입을 하면서 크고 작은 개발사들은 대규모의 자본과 인 력이 없어도 도전해 볼 수 있는 모바일 시장으로의 골드러시를 시작했다. 그러나 모바일 시장이 커졌다는 것은 경쟁도 그만큼 많아졌고, 점점 더 스마트 해지는 고객들을 설득하기도 어려워 졌다는 의미이다.
  234. 237 스타트업 개발사의 생존필수 아이템, baas.io 모바일 고객센터 어찌 보면

    대륙을 횡단하고 로키산맥을 넘으면서 샌프란시스코에 도착하기도 전에 수 만 명이 목숨을 잃었던 골드러시 보다 더 험난하고 치열한 생존경쟁이 기다리고 있다. 이 책에서는 Startup 또는 중소 개발사들이 중요하지만 치열한 생존경쟁에서 미처 생 각하지 못하고 있고, 막상 하려니 어떻게 해야 할지 막막한 [서비스 운영, 유입 고객에 대한 유지/확대, 모니터링에 대한 필요성과 구체적인 실행방안]을 제시하려고 한다. 밑 빠진 독이 아닌지 우선 살펴볼 것 배우는 것에는 순서가 있다. 제대로 싸우기 위해서는 맞는 것부터 배워야 하고, 돈도 아끼는 것부터 배워야 한다. 모바일 사업에서도 마찬가지다. 신규 고객의 유입 노력에 앞서 기존 고객에 대한 Care가 가능한지, 유입된 고객이 재 사용으로 이어지는 구조인지를 먼저 살펴봐야 한다. 자! 이해를 돕기 위해 아주 단순화 한 퀴즈를 하나 내려고 한다. 10,000명의 다운로드 고객을 확보한 A사와 B사가 있다. A사는 매달 40%씩 신규고객을 추가로 확보하고 전체 고객 유지율이 80% 다. 반면, B사는 적극적인 홍보로 매달 80%의 신규 고객을 유치하고, 전체 고객의 40%을 유지한다. 이때, 6개월 후 양 사의 보유고객수는 어느 정도 이고 몇 배 차이가 날까? A사와 B사는 동일한 고객수로 시작한다. 차이가 있는 것은 신규고객 확보율과 고객유 지율이 각각 4:8과 8:4으로 엇갈린다는 것이다. 첫 달에 동일한 고객수를 모집한 상태이기 때문에 서비스 매력도나 품질면에서는 큰 차이가 없다고 가정하고, 서비스에 대한 고객들의 평가와 구전(Word of Mouth)도 일
  235. 238 H3 개발자 컨퍼런스 2012 단 배제를 하면 차이가 나는

    것은 <유입과 유지> 어떤 것에 더 비중을 두는가가 유일 한 차이인 것이다. A사는 유입 고객의 유지(Retention)에 조금 더 비중을 두었고, B사는 일단 신규고객 확보를 위한 광고 집행에 더 많은 활동을 벌였다. [양사 보유 고객 수 변화 추이표] B사는 매달 보유고객의 80% 고객을 새로 유입 시킴에도 불구하고, 고객이 감소 하는 모습을 보이다가 6개월 뒤에는 A사의 고객 수에 비교 해서 1/9수준에 이 르게 된다.
  236. 239 스타트업 개발사의 생존필수 아이템, baas.io 모바일 고객센터 상황을 아주

    단순화 하긴 했지만 결과가 주는 의미는 현실에서도 그대로 반영된다. 기업은 우리의 서비스나 상품을 알리고 다운로드(구매) 하는데 많은 활동과 자원을 투자 하지만, 정작 유입된 고객들이 얼마나 남고, 재방문하고, 구매하는지에 대해서는 그리 큰 관심을 두지 않는다. 그러나 유입된 고객들이 서비스에 안착하지 못하면 위의 그래프와 같이 밑 빠진 독에 물 을 붓는 우를 범하게 될 가능성이 매우 높아진다. 고객 유입은 매우 중요한 요소이나 기업 입장에서는 기존고객이 빠져나가지는 않는지, 어떤 불편을 겪고 있는지, 어떤 개선이 필 요한지에 대해 먼저 신경을 써야 한다. 만약 기존 고객들에게서 다음과 같은 반응들이 나온다면 게임은 하나마나인 셈이다. 리뷰 타사사례 특히 경쟁자가 많고, 클릭 한번으로 다른 대체 서비스로 옮겨가기가 쉬운 모바일 업계 에서는 더욱 더 이미 유입된 고객들에 대한 Care가 매우 중요한 역할을 한다. 다음과 같이 경제적 가치나 영향력 측면에서 보면 실 사용고객에 대한 중요성은 더욱 더 커진다.
  237. 240 H3 개발자 컨퍼런스 2012 [고객 성숙도별 가치 비교] 설치와

    재방문을 한 고객은 그렇지 않은 이용자 보다 어플에서의 변화(배너 클릭, 아 이템 가격인상, 새로운 기능 이용 등)를 좀더 쉽게 수용하고 주변 사람들에게 표현하 려는 특성이 있다. 수익과 전파 공헌도가 높은 실제 이용고객, 재방문 고객들을 먼저 잡아야 하는 이 유다. 일시적인 흥미유발성 어플이 아니라 지속적인 버전업과 사용자간 연계, 결제등을 고 려하는 어플이라면 반드시 필요한 것이 [모바일 고객센터]이다. 고객 유입활동에 앞서 우리 어플을 다운 받은 고객이 떠날만한 이탈요소는 없는지, 고 객의 불편함과 니즈는 무엇인지를 알고 개선여부와 이후 계획을 얘기할 수 있는 체계 를 먼저 만들어 놓는 것이 더 효율적이면서도 더 크고 길게 갈 수 있는 [지속 가능한 기업]으로의 첫 걸음이 될 것이다. <KTH BaaS.io모바일 고객센터>를 그 대안으로 제 시 하려고 한다. 이용고객에 대한 운영과 Retention에 대한 기여도는 생각보다 크다.
  238. 241 스타트업 개발사의 생존필수 아이템, baas.io 모바일 고객센터 어플 선택의

    기준... 가장 효과적인 광고는? 선택기준 1위는 리뷰! 전국민의 60~70%가 스마트폰을 쓰게 되었다는 의미는 실제 소비자의 정보 습득 채 널과 이용행태, 커뮤니케이션 방식도 달라졌다는 의미이다. <유무선 광고, 기업 공식 트위터나 페이스북, 앱스토어 리뷰, 지인평가>… 이중 사람 들은 어떤 매체를 더 신뢰할까? 조사 결과 등을 굳이 보여주지 않아도 사람들의 결론은 비슷할 것이다. 신뢰도는 앞선 예의 역순으로 형성된다. 홍보성 기사나 공식 페이스북이나 트워터를 통해 운영자가 올리는 글들을 보고 어플 을 설치하거나 친구에게 추천하기는 쉽지 않다. 고객들은 스마트해졌다. 열 번의 홍보성 기사와 광고를 보더라도 “제대로 안 된다”는 한 줄의 리뷰에 다운로드 취소를 하는 것이 지금의 고객들이다. 매체 지배력이 공중파나 신문, 웹사이트에서 고객들이 직접 만들어 내는 리뷰와 SNS, Buzz등으로 무게 중심을 옮겨가고 있다. 적어도 어플을 선정하는 기준에서는 이런 현 상이 더욱 확실하게 나타나는 것 같다. 실제로 올해 1분기와 2분기 아이폰과 안드로이드 이용고객 총 5,983명을 대상으로 조사한 <어플 선택 영향요소 추이분석>에서는 어플을 선택하는 기준이 ‘유료 인지 무 료인지’를 배제하고 나면 그 첫 번째가 ‘실 이용고객의 리뷰’인 것으로 나타나고 그 영 향력 또한 1분기 대비 증가하는 모습을 볼 수 있다. 기업으로서는 달라진 미디어 환경에 맞게 진화를 하지 않을 수 없게 됐다.
  239. 242 H3 개발자 컨퍼런스 2012 2012년 상반기 아이폰/안드로이드 앱 선택

    영향요소 추이  유/무료 제외시 앱 설치시 영향력 1위는 양진영 모두 ‘리뷰/사용후기’ 출처 : 2012 상반기 앱생태계 정기 동향 보고서_KTH CVI팀 이렇게 사용자 평가에 대한 영향력이 커지는 이유는 이용자가 쓸 수 있는 어플의 수는 제한적인 상황에서 어플의 공급 경쟁이 심해지고 있고, 이런 환경에서 어플을 선택하 기 위한 고객의 피로도가 지속적으로 증가 하고 있기 때문이다.
  240. 243 스타트업 개발사의 생존필수 아이템, baas.io 모바일 고객센터 [2011년 아이튠즈

    월별 액티브 / 신규등록 앱 수]_하루 출시 앱수는 600~700개 출처 : 2011 앱 이용 동향 보고서_KTH CVI팀 수 많은 어플 중에서 고객이 한 달에 깔 수 있고, 써볼 수 있는 있는 어플의 개수는 정 해져 있다. 마냥 깔았다 지웠다를 반복 할 수는 없다. 개발 사 입장에서도 선택 받기 어려운 시장이 됐지만 고객 입장에서도 선택하기 어려운 상황이 됐다. 고객은 자연스럽게 이런 피로도를 줄이기 위한 정보를 수집하는 것이고 그 중에서 회 사가 제공한 광고나 SNS 보다는 실제 이용고객의 평가와 리뷰를 신뢰하고 선호 하게 되는 것이다.
  241. 244 H3 개발자 컨퍼런스 2012 리뷰와 SNS로 채워지지 않는 것들

    따라서 회사는 리뷰(사용후기)에 대한 긍정적인 관리가 필요하지만 개발사의 입장에 서 보면 앱스토어의 리뷰나 SNS로는 모바일 어플의 문제를 인지하기도, 그 원인을 규 명하기도, 취해진 조치결과를 고객에 알리고, 정상 유무를 확인하기도 어려운 것이 현 실이다. SNS의 사용자가 늘어나면서 고객과의 소통채널로 트위터나 페이스북을 이용하는 회 사가 늘고 있고, 이를 통한 커뮤니케이션도 점차 늘어나고 있다. 회사 입장에서는 변화하는 미디어 영향력를 고려하지 않을 수 없는 상황이고, 이에 대 한 도입 시도와 시행착오는 절대적으로 필요하다고 보여진다. 그러나 [홍보, 판촉, 소통, 불만해소]등의 다양한 기능을 SNS 하나에서 수행하려는 데에서 오는 문제점들이 발생하고 있는 것도 사실이기 때문에, 의도한 효과를 제대로 보기 위해서는 전략적인 접근이 필요하다.
  242. 245 스타트업 개발사의 생존필수 아이템, baas.io 모바일 고객센터 결론부터 언급하면

    홍보, 판촉, 소통 측면에서 페이스북이나 트위터, 블로그는 매우 효과적인 수단이지 만 상세 정보가 필요한 [모바일 서비스에 대한 문제 인지와 답변]은 SNS에서 소화가 불가 하기 때문에 채널을 분리해 독립적으로 운영해야 하고, 그 순서도 SNS채널에 앞 서 구축되어야 한다. CS 창구가 없거나 여기서 해소되지 못하는 문제는 기업에서 정성 들여 만들어 놓은 트위터와 페이스북을 타고 공론화 될 가능성이 높기 때문이다. 개발사는 매력적이면서 완성도 높은 모바일 서비스를 만들어야 하지만 다른 OS환경 과, Phone과 Tablet, 수 많은 스마트폰 기종과 버전에서 아무 문제 없이 잘 돌아 가는 어플을 만드는 것은 쉽지 않은 일이다. 이런 복합적인 요소들이 서로 영향을 미치면서 발생하는 문제들이 대부분이기 때문에 문제 없이 어플을 출시 하기도, 문제를 파악하 거나 해결하기도 쉽지 않은 것이 사실이다. 더구나 이런 다양한 환경에서 발생하는 문제를 앱스토어 리뷰나 SNS에서 한 두 줄의 불만성 코멘트에서 정확한 문제를 찾는 것은 불가능에 가깝고, 좀더 세부적인 정보를 파악하기 위해 고객에 질문을 하기도, 조치된 결과를 알리는 것도 불가하다. 결국, 고객은 고객대로 앱스토어를 찾아가서, 해당 어플을 찾고 답변도 안 올 리뷰에 푸념을 하면서 서비스를 이탈하게 되고, 개발사는 개발사대로 대응이 불가능한 상황 에서 속수무책으로 고객의 이탈과 부정적인 구전을 지켜볼 수 밖에 없게 된다. 고객들도 불편하고 서비스의 Risk도 커지는 상황이 되는 것이다. 얼마나 불편을 경험할까? 그 고객들은 어떤 액션을 할까? 모바일 어플 이용자 10명중 7~9명은 서비스를 이용할 때 불편을 느끼고 있지만(매번 또는 자주 경험하는 비율도 38%), 불편 과정에서 문의할 곳을 몰라 해결을 못하는 비 율이 1/3정도가 된다. 블로그나 까페, 메일, 친구에 답변을 얻어도 정보가 부족(30%) 하거나 내용이 어려워(11%) 불편이 완전히 해소되는 비율은 10%내외로 낮은 것으로 나타난다. 불편 경험지점은 서비스 전 영역에 분포되어 있고 문제를 해결하지 못할 경우 10명중 6~7명은 이용을 줄이거나, 부정적인 구전을 하거나, 서비스를 이탈 하는 모습을 보인다.
  243. 246 H3 개발자 컨퍼런스 2012 여러 가지 지표나 현상으로 볼

    때 고객이나 기업모두를 만족시킬 수 있는 소통채널이 필요한 상황으로 보여진다. [불편 경험 빈도(강도)] [불편 경험 지점(상황)] [불편 해결과정에서의 문제점]
  244. 247 스타트업 개발사의 생존필수 아이템, baas.io 모바일 고객센터 [불편 미해결시

    서비스 이용에 미치는 영향] KTH가 당면했던 문제와 해결책 실제 KTH도 같은 문제를 겪었고 여러 시행착오를 거쳐 해결책을 찾았다. 트위터에 KTH의 서비스에 대한 얘기는 많이 있었지만 공식 트위터나 블로그를 통해 유입된 문
  245. 248 H3 개발자 컨퍼런스 2012 제는 실제의 5%만이 접수가 되고

    있었고, 그것도 문제가 다 퍼진 다음에 게재가 되는 수준이었다. 무엇보다도 문제가 발생해도 대응할 수 없는 리뷰나 트위터, Buzz 등에서 돌아다니는 VOC가 월 4천건을 넘을 정도로 너무 많다는 것이 문제였고, 우리가 Control 할 수 없 기 때문에 문제에 대한 인지와 조치도 늦을 수 밖에 없는 상황이었다. 대책은 KTH의 주요 어플 사용 중 불편사항이나 문의 필요성이 생겼을 때, 어플 내에 탑재 되어 있는 [모바일 고객센터]로 접속해서 FAQ검색과 전화/메일/SMS의 대화가 가능하도록 구현 하는 것이었다. [모바일 고객센터 적용사례] Pilot을 거쳐 2011년 5월부터 모바일 고객센터를 탑재 하면서 변화가 생겼다. 우선 앱스토어 리뷰나 트위터로 돌아다니던 4천여건의 Buzz성 외부 VOC들이 내부 VOC로 대부분 전환이 되었고, 고객 불편사항에 대한 부가정보(단말기 기종, 버전, 문 제 발생지점 등)에 대한 자세한 파악이 가능해짐에 따라 내부에서는 빠른 서비스 개선 을, 고객에게는 신속한 불만해소와 만족도 향상이 가능해졌다.
  246. 249 스타트업 개발사의 생존필수 아이템, baas.io 모바일 고객센터 특히 SMS

    상담 적용 후 전체 문의에서 SMS 점유율이 60%로 급증했고, 그 결과 24 시간 주기의 고객 대기시간을 평균 2분으로 단축할 수 있었다. [모바일 고객센터 탑재를 통한 내부 VOC로 전환 효과] 무엇보다 모바일 어플 자체에서 고객의 불만과 니즈를 흡수함으로써 앱스토어에 등록 될 부정적인 리뷰를 큰 폭으로 줄였고, 이를 통해 리뷰나 SNS에서 어플에 대한 긍정 적인 구전이 많아지도록 하는 부가적인 성과도 가능해졌다. BaaS 모바일 고객센터 소개 및 탑재 방법 안내 [KTH BaaS 모바일 고객센터]는 KTH의 운영경험을 통해 이러한 기본 기능과 VOC의 수집에서 개선에 이르기까지 운영 전반에 걸친 프로세스를 묶어서 서비스화 한 모듈 이다. 이러한 고객센터나 운영에 필요한 인프라를 개발사에서 새로 구축해서 운영하기는 쉽 지 않기 때문에 API 형태로 제공해서 어플 개발시부터 적용할 수 있도록 했다.
  247. 250 H3 개발자 컨퍼런스 2012 BaaS 모바일 고객센터가 설치 되면

    어플내에 [모바일 고객센터]가 탑재되고 개발사는 별도의 유무선 관리페이지에서 고객응대는 물론이고, VOC 유입량의 증감, 문제에 대 한 단말기 환경정보, 7개 앱스토어에 대한 자사어플의 리뷰들을 One-stop으로 볼 수 있게 된다. 아울러 문의량이나 불만이 급증하면 개발사는 실시간으로 알림을 받을 수 도 있다. Cf. One-Stop 리뷰보기, 실시간 이상징후 알림은 1.0버전 이후 제공 우리는 자사의 어플을 다운 받은 공헌도 높고, 수익성 높은 고객이 이탈하지 않도록 하고, 불만이 생기더라도 외부로 표출되거나 확산 되는 것을 막는 것이 [BaaS모바일 고객센터]를 통해서 가능하다고 생각한다. 또 이를 토대로 신규 유입을 늘릴 때 비로소 효율적인 비즈니스가 성립되고 개발사가 생존 가능성을 더 키울 수 있다고도 믿는다. 모바일 생태계의 중요한 역할을 담당하는 중소 개발사들이 [BaaS 모바일 고객센터]를 통해서 좀더 단단해지고 그러한 것들이 모바일 산업과 국가 경쟁력으로 이어지는데 조그만 기여를 할 수 있기를 희망한다.
  248. 251 스타트업 개발사의 생존필수 아이템, baas.io 모바일 고객센터 2012년 모바일

    고객센터를 통해 가능해지는 것들 (cf.일부기능은 1.0버전 이후 업데이트 예정) 주체 가치 고객 •  고객은 어플에서 즉시 편하게 문의하고 건의 할 수 있게 됩니다. (일부러 찾아 들어가서, 회신도 받을 수 없는 리뷰나 트위터에 남기지 않아도 됨) • 개발사의 직접 답변을 들을 수 있고 답변 대기시간도 짧아집니다. • (답변과 동시에 메일과 모바일 알림(Push)으로 통지됩니다.) • OS나 App버젼, 핸드폰 기종을 따로 기재하거나 설명하실 필요가 없어집니다. •  고객이 자주 조회하는 도움말은 추천도움말에서 쉽게 찾아볼 수 있어 블로그나 까페, 리뷰등을 찾아 보지 않아도 됩니다. • 등록한 문제에 대한 해결이 빨라집니다. 개발사 • 문제에 대한 유실과 누락이 줄어듭니다. • 문제 인지 속도가 빨라집니다. • 문제에 대해 고객과 직접 커뮤니케이션을 할 수 있게 됩니다. • 응대 속도가 리뷰나 블로그, 트위터보다 현격히 빨라 집니다. •  문의를 유형(불만,일반,칭찬)별, 처리상태(미확인,진행중,완료)별로 구분하여 관리하여 향후 고객분석 에 활용할 수 있습니다. • 문제 유형별 OS/Device환경정보가 제공돼 원인파악이 용이해집니다. • 문제해소를 통해 고객이탈과 부정적인 평가와 구전을 차단/축소할 수 있습니다. •  고객 불만정도, 문제발생 환경, 문제해소여부, 고객 대기시간 등에 대한 주요지표를 365일 24시간 어디서든 한 눈에 볼 수 있습니다. • 이러한 핵심지표를 일간/주간/월간별로 파악하고 비교해서 신속한 경영전략을 수립할 수 있습니다. KTH • Product Seller에서 Process Seller로의 새로운 시장가치를 창출합니다. 이후 순차적으로 업데이트 될 기능들 • 어플의 장애나 이상유무를 실시간으로 알 수 있습니다. • 개발사에서 만든 FAQ 및 메뉴 등을 영어로 변환시켜 드립니다. • 7개 앱스토어 리뷰와 SNS, Buzz를 유무선, 실시간, One-stop으로 보실 수 있습니다. • 해당 App에 대한 설문 구성 및 Push가 가능해집니다. • 고객응대가 어려운 경우 ASP 형대로 응대 대행도 할 수 있습니다. • Etc..
  249. 252 H3 개발자 컨퍼런스 2012 라피드 프로토타이핑, <모두의 도구>를 사용할

    때입니다. H3 Conference는 개발자만의 잔치?! H3 개발자 컨퍼런스에서 다룰법한 주제가 아님에 이 글이 달갑지 않을 수도 있습니 다. 라피드 프로토타이핑 <모두의 도구>는 Develop보다는 UX, UI 디자인 워크프로세 스(Design Workprocess)에 포커싱(focusing)된 글이니까요. 아! 참고로 필자는 개발 자(Developer)가 아닙니다. 그럼에도 불구하고 H3 컨퍼런스에 세션 하나를 맡게된 이 유는 H3 행사가 개발자만의 잔치가 아닌, 모두의 잔치가 되었으면 하는 바람 때문입 니다. 바라면 이루어진다. 그렇게 믿고 있습니다. :-) 모두의 도구로 프로토타이핑을 시작하라! 앱FI팀 지훈 [email protected]
  250. 253 모두의 도구로 프로토타이핑을 시작하라! 프로토타이핑(Prototyping)이란? 좋은 제품이나 서비스는 순식간에

    만들어지지 않아요. 제품 또는 서비스에 대해 고민 하고... 고민하고... 또 고민한 후, 정리된 큰 그림을 그리죠. 여기서 이야기하는 그림 은 모양(꼴, Shape)만은 아니에요. 일반적으로 사람들은 그림 이라고 하면, 모양을 우 선적으로 생각하죠. 혹시 그림을 모양이라고 생각하셨다면 다르게 이야기를 풀어볼까 요? 뭔가를 만들고자 하는 생각을 정리한 것을 설계(Design)라고 한다면, 정리된 생각 을 보다 이해하기 쉽게 모양으로 그려본 것을 설계도(청사진, Blueprint)라고 합니다. 네. 맞아요. 그 그림이 우리가 이야기하고자 하는 그림이에요! 청사진은 실제 제품이나 서비스를 만 들기에 앞서 어떤 기능이 있고, 어떻 게 구성되고, 어떻게 생겼는지를 빠 르게 그려보는 것이죠. 이를 프로토 타이핑(Prototyping)이라고 부릅니 다. 프로토타이핑의 생명은 발빠르 게 정리된 생각을 그려보고 제품이나 서비스로 만들 수 있는지 연구해보길 반복하여 결과를 창출하는 것입니다.
  251. 254 H3 개발자 컨퍼런스 2012 위키피디아(Wikipedia)에서는 프로토타이핑을 개발접근법의 하나로 개발

    초기에 간 단한 모형(원형, Prototype)을 간단히 만들어 보고 사용해 봄으로서, 기능의 추가/변 경/삭제 등을 반영하여 다시 구성 하기를 반복해 나가면서 시스템을 개선시켜 나가는 방법으로 정의(http://is.gd/kN29Xv)하고 있습니다. 응? 프로토타이핑(Prototyping)이 왜 이리 느리지? 프로토타이핑에 대해 간단히 정리해봤는데요. 국내에서는 프로토타이핑이 어떻게 이 루어지는지 궁금해졌습니다. 그래서 몇몇 에이전시에서 종사하는 실무자에게 회사에 서 프로토타이핑이 이루어지는 과정을 들어보았습니다. 다소 차이가 나기는 했지만, 대부분 이루어지는 프로세스가 프로토타이핑이라 보기에는 무리가 있는 듯 싶더군요. 앞에서 프로토타이핑 방법론을 발 빠르게 그려보면서 제품 출하까지 반복적으로 수 행하면서 기능을 추가하거나, 수정/제거하는 것이라고 이야기했죠. 그런데 국내에서 는 반복 수행 과정이 조금 다르더군요. 화면 설계 기획서 받기 전까지 전혀 디자인에 대한 고민이 없다가 기획서를 받는 순간부터 시작하는데 컨펌난 디자인이 나오기까지 무한(?) 반복을 수차례. 상사에, 상사의 상사에, 그리고 그 위에까지 반복하며 컨펌이 나야 개발자에게 디자인이 넘어가는 구조입니다. 그러다 화면설계 기획안이 수정되면 다시 반복 =_=;; 이러니... 오래걸릴 수 밖에...
  252. 255 모두의 도구로 프로토타이핑을 시작하라! 뭔가 이상하죠. 반복되는 프로세스의 포커싱이

    전혀 다르니까요. 이건 프로토타이핑 이 아니죠! 프로토타이핑이 반복하는 사이클은 기획-디자인-개발이지, 기획-디자 인-디자인-디자인-기획수정-디자인... 이 아니니까요. 이렇게 느린 프로토타이핑이 프로토타이핑이라고 부를 수 있는걸까요? 문제가 있어도 한참 있다고 보여집니다. 문 제가 주어지면 해결방도를 강구해봐야겠죠. 문제를 해결하려면 어떻게 해야할까요? 모두의 언어(Global Language)가 필요해! KTH에서는 빠른 프로토타이핑을 위해 필요한 것은 모두가 함께 사용할 도구라고 보 고 있습니다. 부서마다 각기 다른 도구를 사용하다 보니, 비 효율적인 프로세스의 반 복이 이루어진다고 판단한 것이죠. 그래서 UXD실에서는 모두가 함께 사용할 도구를
  253. 256 H3 개발자 컨퍼런스 2012 물색하여 이를 실무에 활용할 수

    있도록 준비하고 있습니다. 실무에 활용하기 위해서 는 당연 사전 학습이 필요하기 때문에 잘 준비된 교육이 필요합니다. 물론 회사 시스 템이 변화되려면 적지 않은 노력과 시간이 필요하기 때문에 빠른 시간 내에 정착하기 란 쉽지 않다고 봅니다. 사람은 바꾸는 것보다 익숙한 것을 더욱 선호하는 동물이니 까요. 그래도 가만있을 수는 없지 않겠어요? 변화는 한 순간에 다가오기보다는 꾸준히 서서 히 다가오니까요. 그래서 필자는 효과적이고 빠른 프로토타이핑이 자리잡을 수 있게! UXD 교육에 열을 올리고 있으며, 절대 포기하지 않습니다. 기획자와 UX, UI 디자이너 가 함께 사용하면서 발빠른 프로토타이핑 환경을 만들고 습관화 해낼 수 있다면, 자연 스레 업무 생산성이 향상될테니까요! 그깟 도구 하나 함께 사용한다고 뭐가 바뀌는데?라 고 의문 부호를 다시는 분들도 계시겠죠? 도구 하나 변화가 크게 작용하지 않을 것이라고요? 과연 그럴 까요? 도구 하나 바꾸는 일이 작아보이겠지만... 이 로 부터 모든 것이 시작될 수 있다는 생각을 해보시는 것은 어떨까요? 작은 행동 하나 로부터 환경은 변화되거든요. 그렇다면 모두가 사용할 빠른 프로토타이핑 도구로 만 족스러울 조건은 무엇일까요? 우선 모두가 사용하기 쉬워야 하며, 모두에게 요구되는 기능이 제공되어야한다고 봅니다. 모두의 도구 선정조건 ▪ 모두가 쉽게 사용 가능 ▪ 모두가 필요로 하는 기능 제공
  254. 257 모두의 도구로 프로토타이핑을 시작하라! 수차례 고민 끝에 KTH UXD실에서는

    Adobe Fireworks 제품이 가장 적합하다는 판단을 내렸습니다. 파이어웍스를 선택한 이유는 우선적으로 디자이너에게 친숙한 Adobe 제품이라 익숙해지는데 어렵지 않고, 기획 단계에서 화면 설계시 만드는 와이 어프레임(Wireframe)을 제작할 때, 매우 유용한 라이브러리가 제공되게 때문입니다. 필자는 이번 지면을 통해 해외와 달리 국내에서는 크게 사용되지 않아 생소한 이 도구 가 왜 <모두의 도구>로 유용한지 다뤄보려 합니다. 기획 단계에서부터 와이어프레임 제작, 그리고 디자인 목업, 화면 단 웹 데이터 제작과정까지 파이어웍스가 각 환경에 서 얼마나 유용한지를 풀어보도록 하죠. 먼저! 모두의 도구로 파이어웍스가 디자이너에게 적합한 이유!
  255. 258 H3 개발자 컨퍼런스 2012 국내의 대다수 디자이너는 해외 디자이너와

    달리 포토샵과 일러스트레이터만 사용합 니다. 상대적으로 파이어웍스 사용자를 찾기 힘들며, 심지어는 파이어웍스가 어떤 도 구인지도 잘 모르는 경우도 있어요. 아마도 모르니까 못쓰는 거라고 생각되네요. 알 면 그렇지 않을텐데 말이죠. 좋은 물건은 자고로 써줘야 하는데... 참 아쉬울 따름입 니다. 사용률이 적은데는 여러 이유가 있겠지만, 가장 큰 이유는 무엇이 좋은지에 대 한 노출 창구가 부족하지 않나 싶네요. 출판 시장의 콘텐츠만 보더라도 포토샵, 일러 스트레이터 책은 매년 홍수처럼 쏟아져 나오지만, 파이어웍스 책은 좀처럼 찾기 힘들 죠. ㅠㅡㅠ 그래서 필자는 편식하는 국내 디자인 환경 변화에 일조하고자 <나눔>을 실천하려 노 력하고 있어요. 파이어웍스가 왜 좋은지, 왜 사용해야 하는지, 사용법은 어떻게 되는 지... 오픈지식 동영상 강의를 만들어 공유하고 있습니다. 착하죠? 칭찬해주세요! 영상 강의이다 보니 책보다 전달이 쉽고, 보면석 학습할 수 있는 실습형이기 때문에 어떤 장점이 있는지 파악하는데 어렵지 않을 겁니다. 영상 강의는 VIMEO로 서비스되 고 있어, 데스크톱은 물론 모바일 환경에서도 시청하실 수 있죠! N-Screen에 대응하 는 강의!! +_+b
  256. 259 모두의 도구로 프로토타이핑을 시작하라! 영상 강의 시청은 어렵지 않아요!

    웹 브라우저 주소를 입력하는 곳 에 https://vimeo.com/yamoo9/라고만 입력해주시면 되니까요 ~ 혹시 입력도 귀찮으신 분은 오른쪽 QR Code를 살포시 찍어주 세요~ 아이고! 본심(?)으로 강의 홍보를 하고 있었군요! 다시 본론으로 돌아가야겠네요. 헤 헤~ 물론 포토샵과 일러스트레이터는 매우 뛰어난 도구입니다. 하지만 프로토타이핑에는 적합하지 않죠. 한 장 그래픽을 완성하는데는 더없이 훌륭하지만, 다수의 페이지로 구 성되는 어플리케이션 제작에서는 그 능력이 반감됩니다. 이유는 포토샵과 일러스트레 이터의 사용 용도가 이미지 제작이지, 페이지 제작 도구는 아니기 때문입니다. 이해를 돕기 위해 책을 예로 들어볼까요? 책은 정보를 다루는 글과 이미지로 구성되며 여러 페이지 묶음으로 제공되죠. 1~6페이지 분량으로 구성되는 포스터, 팜플렛이나 브로슈어와 비교되는 대목은 바로 <묶음>입니다. 그렇기 때문에 포스터, 팜플렛, 브로 슈어 제작에 포토샵, 일러스트레이터가 전면에서 활용되는 경우는 있어도, 책을 만들 때 포토샵, 일러스트레이터를 주 도구로 사용하지는 않습니다. 이유는 여러 페이지를 묶는데 포토샵, 일러스트레이터는 적합하지 않으니까요. 그렇기 때문에 책을 제작할 때는 포토샵, 일러스트레이터가 아닌, 인디자인(InDesign)이나 아이북스(iBooks), 익스프레스(QuarkExpress) 등을 사용하는 겁니다.
  257. 260 H3 개발자 컨퍼런스 2012 마찬가지로 다수의 페이지를 필요로하는 어플리케이션

    제작에 있어 프로토타입을 포 토샵, 일러스트레이터로 만드는 것은 무리가 따릅니다. 그런 점에서 파이어웍스는 포 토샵 일러스트레이터보다 어플리케이션 프로토타이핑에 적합니다. 어떠세요? 이해 잘 되고 계신거죠? 맞죠? 그런 이유로 디자이너 관점에서 모두의 도구는 파이어웍스라고 보는 겁니다. 페이지 (Page) 개념이 인디자인과 마찬가지로 제공되고 있어, 하나의 Fw 문서에서 여러 페이 지를 통합 관리할 수 있죠.. 앞서 이야기했던 책 만드는 이야기. 그것처럼 어플리케이 션 제작에 있어 포토샵, 일러스트레이터보다 파이어웍스를 권하는 이유입니다. 페이지 뿐만 아니라, 마스터 페이지(Master Page) 기능을 지원하기 때문에 일괄적으 로 처리/수정되어야 하는 부분을 관리하기가 용이합니다. 이는 개발 단에서 공통적으
  258. 261 모두의 도구로 프로토타이핑을 시작하라! 로 사용되는 부분을 분리하여 서버

    스크립트를 사용하여 불러들이는(include) 것과 유 사하죠. 만약 이를 포토샵이나, 일러스트로 처리한다면 페이지의 개수가 많으면 많을 수록 삽질이 더해지게 될 겁니다. =_=;;; 예를들어 볼까요? 왼쪽에 자리잡은 1개의 fw.png 파일은 파이어웍스 데이터 파일이 고, 오른쪽에 자리잡은 8개의 psd 파일은 포토샵 파일입니다. 공통적으로 처리되는 영역에 수정사항이 생겼다는 시나리오일 경우, 파이어웍스는 해당 파일을 열어 마스 터 페이지만 수정해주면 간단하게 처리됩니다. 하지만 포토샵의 경우는 8개 파일을 모두 열어서 수정 저장해야합니다. 페이지의 개수가 많아지면 많아질 수록 암담해집 니다. 느껴지시나요? 페이지 개념이 담겨있는 도구와 그렇지 않은 도구의 어마어마한 차이를 말이죠. 페이지 관리 뿐만 아니라, 인터랙션(Hot spot, slice) 기능 또한 프로토타이핑 도구로 서 파이어웍스가 적합한 이유입니다. 물론 포토샵의 경우도 슬라이스(slice) 기능을 제 공하기는 하지만, 외부의 주소만 연결이 가능할 뿐. 파이어웍스처럼 페이지 연결 기능 은 처리하지 못합니다. 포토샵의 슬라이스 기능은 매우 열악하죠.
  259. 262 H3 개발자 컨퍼런스 2012 반면 파이어웍스의 경우는 충실한 슬라이스

    기능 뿐만 아니라, 핫스팟(Hot Spot)도 제공해줍니다. 페이지를 지원하는 파이어웍스에서는 각 페이지로 연결을 손쉽게 처리 되기 때문에 프로토타이핑에 적절한 결과물을 만들 수 있습니다. 다음 이미지에서는 Artwork 페이지에서 개별적으로 작품을 볼 수 있는 페이지 연결을 핫스팟으로 구현해 본 것입니다.
  260. 263 모두의 도구로 프로토타이핑을 시작하라! 파이어웍스로 만든 페이지 프로토타이핑을 결과물로

    내보내면 별도의 코드 작업 없이 도 페이지 연결을 눈으로 확인할 수 있습니다. 페이지별 연결되는 파일을 내보내는 방 법은 메뉴의 File – Export를 누른 후, PDF, Web Data(HTML, CSS 등) 중 원하는 포멧으로 뽑아내면 됩니다. 참 쉽죠? PDF로 뽑아낼 경우, 페이지 이동 인터랙션 뿐만 아니라, 별도의 수정 및 추가사항을 메 모로 남겨 공유할 수도 있습니 다. 책 이미지 교체를 요청하 는 메모를 남겨봤습니다. 디 자이너는 해당 페이지(3/8)의 책 이미지만 변경하여 저장하 면 되겠군요! 알기 쉽고 사용 하기 쉬워 좋군요.
  261. 264 H3 개발자 컨퍼런스 2012 모두의 도구로 파이어웍스가 기획자/UX 디자이너에게

    적합한 이유! 앞서 디자이너 관점에서 파이어웍스의 장점을 알아봤죠? 페이지, 핫스팟, 슬라이스 기능이 프로토타이핑에 유용하다는 점을 확인할 수 있었습니다. 그렇다면 기획/UX 디자이너 관점에서 모두의 도구, 파이어웍스는 어떻게 활용하면 좋을까요? 화면 설계를 구상한 후에 스케치로 대략의 윤곽을 그리기를 수십번... 반복적으로 그 려야 하는 구성요소가 어느새 짜증으로 밀려오기도 하죠? 더구나 그렸던 것을 수정할 땐... 모든 것을 다시 그려야 한다는 압박감은 엄청난 스트레스로 다가옵니다. 스트레 스로 더이상 피곤하고 싶지 않으시다면 파이어웍스를 사용해보세요. 심볼(Symbol)과 라이브러리(Library)를 활용하여 와이어프레임을 보다 빠르게 작성 / 재사용할 수 있 으니까요! 파이어웍스는 벡터(Vector) 기반의 도구인 일러스트레이터, 플래시(Flash)가 그러하 듯이 심볼 기능을 갖추고 있습니다. 심볼은 자주 사용되는 그래픽을 라이브러리에 등 록해놓고, 필요할 때마다 꺼내 사용할 수 있습니다. 뿐만 아니라, 하나의 심볼에 연결 되어 있는 다수의 심볼 인스턴스 파일은 심볼 수정시 일괄적으로 변경되는 편리함도 있죠.
  262. 265 모두의 도구로 프로토타이핑을 시작하라! 위 이미지에서 확인 가능한 것처럼

    이미지 플레이스홀더(Image Placeholder)의 경우, 와이어프레임 작성시 빈번하게 사용됩니다. 이렇게 자주 사용되는 컴포넌트의 경우, 심볼로 등록해놓으면 다시 그릴 필요없이 라이브러리에서 가져다 쓰면 됩니다. 참 편 리하고 쉽죠? :-) 어플리케이션 제작 시, 자주 사용되는 컴포넌트를 정리하여 심볼로 등록해놓으면 다 른 프로젝트 시에 매우 편리할 거에요. 다시 그리지 않아도 되니까요. 슬라이드 갤러 리, 탭 메뉴, 차트, 드래그 리스트, 내비게이션 등등 그리고 심볼 등록~ 재 사용하기 좋으니 와이어프레임도 금방 그릴 수 있을 거에요.
  263. 266 H3 개발자 컨퍼런스 2012 혹시 일일이 그리기 귀찮아서 누군가

    그려놓은 심볼을 활용하고 싶다면? 그 귀차니즘 조차도 파이어웍스는 관대하게 수용해줍니다 :-) 스마트하게도 말이죠. 파이어웍스의 메뉴에서 Windows – Common Library를 찾아 선택하면 자주 사용되는 컴포넌트를 모아놓은 공동 라이브러리 패널이 뜹니다. 어디 한번 둘러볼까요? 공동의 라이브러리를 둘러보면 와이어프레임 제작에 필요한 왠만한 컴포넌트는 모두 심볼로 등록되어 있는 것을 확인할 수 있습니다. 원하는 요소를 선택해서 그대로 드래 그하여 와이어프레임을 그리는 곳으로 드롭하면 바로 사용가능합니다. 어떠세요? 이 렇게 쉽고 빠르게 와이어프레임을 그릴 수 있도록 도와주는 파이어웍스 다시 보게 되 지 않으신지? :-)
  264. 267 모두의 도구로 프로토타이핑을 시작하라! 모두의 도구로 파이어웍스가 프론트-엔드 디자이너에게

    적합한 이유! 마지막으로 다뤄볼 내용은 모두의 도구, 파이어웍스가 프론트-엔드 디자이너(Front- End Designer)에게 어떻게 유용한지에 대해서 이야기 해보려 합니다. KTH에서는 프 론트-엔드 영역을 다루는 팀을 FI라고 부르는데요. Front-End Interaction의 약자로 사용자가 사용하는 화면 단의 마크업/스타일/인터랙션 디자인을 수행하는 역할을 하죠. 프로토타이핑에서는 기획에서 만들어진 와이어프레임을 토대로 구조(Structure) 골 격을 짜게 됩니다. 웹 기반에서는 HTML로 골격이 구성되죠. 동시에 화면에서 필요로 하는 인터랙션을 Javascript로 구성합니다. 이후 디자이너로부터 그래픽 디자인 목업 (Graphic Mockup)이 주어지게 되면, CSS를 사용하여 스타일(Presentation)을 제작 하게 되죠. 빠른 프로토타이핑에서는 기획에서 화면설계가 나옴과 동시에, 그래픽 목업이 나오기 전부터, 사전 작업에 착수할 수 있다는 이야기죠. 기존 프로세스대로 디자인이 완성되 어야 작업에 들어가게 되는 것과는 차이를 보이며, 결과적으로 업무 생산성 및 기간을 대폭 줄여주는 효과를 가져옵니다. 프론트-엔드 디자이너 입장이신 분들은 파이어웍스 파일이나, 포토샵 파일이나 매한 가지 아닐까? 의구심을 가지시는 분들도 있겠죠. 그런데 잘 생각해보면 그렇지도 않 다는 사실을 알게될 겁니다. 가령 포토샵 파일의 경우를 생각해봤을 때, 파일 하나하 나가 절대 가볍지 않다는 사실! 묵과할 수 없죠. 파일 열고 확인하고 작업하고, 다시 다른 파일 열고 반복... 반복... 지연 시간이 축적될수록 업무 시간이 늘어나게 되니까
  265. 268 H3 개발자 컨퍼런스 2012 요. 반면 파이어웍스 파일은 비교적

    가볍습니다. 또한 하나의 파일 안에 통합관리 되 기 때문에 매번 열고, 확인... 다시 열고 확인하는 불필요한 동작이 사라지죠. 이는 머 리로 아는 것과 몸으로 체험하는 것이 상당히 다르기 때문에 체감해봐야 “아~ 정말 그 렇구나!” 하고 생각하실 수 있어요. 또 다른 편의 점으로는 CSS 디자인 시에 활용도가 높은 스프라이트(Splite) 기법 제 작을 손쉽게 도와주는 기능을 제공하고 있어 눈으로 보면서 작업하는데 큰 도움을 줍 니다. 디자인된 화면을 바로 보며 필요한 부분만 선택하여 바로 CSS Splite로 출력 (Export)할 수 있으니 정말 편하게 작업/수정하는 것이 가능하죠! 와우~! 소개한 기능 이외에도 여러 장점으로 똘똘 뭉쳐진 파이어웍스는 모두의 도구로 전혀 손색 없음을 아실 수 있을 거에요. 부정적인 생각보다는 긍정적으로! 눈으로만 보기 보다는 직접 몸소 부딪혀보시길! ‘경험한 만큼 보인다’라고 우선은 사용해보자라고 이 야기 드려보고 싶네요.
  266. 269 모두의 도구로 프로토타이핑을 시작하라! 모두의 도구를 모두가 함께 사용하는

    프로세스! 어느새 정리할 시간이네요. 신나게(?) 집필하다보니 정해진 분량이 다가왔거든요. 아 쉬우시죠? 아니시라고요? ^^;; 우리는 짧은 지면을 통해 빠른 프로토타이핑을 하기 위 해서는 공통의 언어가 필요하며, 모두의 도구를 선정할 필요가 있었음을 이야기했습 니다. 그리하여 모두의 도구로 국내에서는 다소 생소한 파이어웍스에 대해 거론했죠. 그리고 UXD에 있어 각 파트(기획/UX/UI/FI)에서 파이어웍스를 어떻게 활용하면 좋을 지를 세부적으로 다뤄보기도 했습니다. 그런데 세부적으로 다뤄보기는 했으나, 부분 부분을 간단하게 다루었기 때문에 빠른 프로토타이핑에 대한 큰 그림을 그려보는 것 으로 집필 내용을 마무리하면 좋을 것 같습니다. 관습적으로 진행되오던 디자인 워크프로세스를 그림으로 그려보면 기획에서 그래픽 디자인, 그래픽 디자인에서 프론트-엔드 디자인으로 이어지는 흐름이 직렬화되어 있 어 앞 흐름이 끝나기 전까지는 뒤에 있는 흐름은 움직일 수가 없어 생산성이 크게 떨 어집니다. 조그만 수정사항이 생기기만 해도 다시 앞에서부터 흐름이 올 때까지 기다 려야 하기 때문이죠. 전체적으로 생각지 못한 변수로 인해 프로젝트 일정이 지연되는 결과를 초래할 수도 있습니다. 반면 빠른 프로토타이핑 방법을 하나의 도구를 통해 반영하면 결과는 전혀 달리집니 다. 지연시간이 길었던 직렬화의 문제를 병렬식으로 풀어낼 수 있기 때문이죠. 기획 과 동시에 화면 설계된 와이어프레임을 동시에 그래픽 디자인과 프론트-엔드 디자인 에서 받아 진행할 수 있기 때문에 불필요한 지연시간이 줄어들고, 흐름이 끊기지 않고 부드럽게 이어질 수 있어 빠른 프로토타이핑이 가능합니다.
  267. 270 H3 개발자 컨퍼런스 2012 관례대로 따른 워크프로세스는 주어진 일정

    안에 한 사이클이 돌기도 어려워 오픈 일 자에 부랴부랴 결과물이 나오는 구조였지만, 모두의 도구를 사용하여 빠른 프로토타 이핑 환경이 구축되면, 주어진 일정 내에 여러 사이클 순환이 가능하기 때문에 보다 많은 고려 속에 완성도를 높일 수 있게 됩니다. 각기 다른 포멧(format)이 아닌, 하나 로 통일된 포멧으로 데이터 전달 및 검토가 이루어지기 때문에 업무상 발생할 수 있는 변수를 줄일 수 있을겁니다.
  268. 271 모두의 도구로 프로토타이핑을 시작하라! 이렇게해서 필자에게 주어진 내용은 모두

    마무리가 되었습니다. 짧은 지면으로 많은 내용을 전달하기에는 다소 부족했겠지만, 전달하고자 하는 핵심은 잘 전달되었으리라 생각합니다. 혹시 궁금증이 몹시도~ 사/무/치/게 일어 질문이 있으시다면~ 필자가 운영하는 커뮤니티(http://cafe.naver.com/webstandardproject)로 의견 보내주세 요. ^ㅡ^ 감사합니다.
  269. 272 H3 개발자 컨퍼런스 2012 하이브리드 앱이 화제입니다. 쉽게 얘기하자면

    이런거죠. 많은 플랫폼이 HTML5와 JavaScript를 지원하니 해당 언 어로 만들어진 앱을 각 플랫폼에서 돌릴 수 있도록 하는 것. 그런데 여기서 문제가 발 생합니다. 플랫폼에서 따로 지원을 하지 않는다면 하드웨어 기능에 접근하는 것이 불 가능하다는 것이지요. 사실 이런 고민은 웹 언어가 발전하면서 계속 존재 하지 않았나 싶습니다. 그래서 deviceapis라는게 등장합니다. 웹 언어 이면서 하드웨어에 접근이 가능한 api를 공통적으로 선언해보자는 시도이지요. 그 시도 중에 WAC이라는게 있습 니다. 앱스프레소는 이 WAC을 지원하고자 고민하고 또 고민해서 만들게 된 프레임웍 입니다. 하이브리드 앱을 만들기 위한 HTML5와 JavaScript를 지원하면서 해당 언어 로 하드웨어 지원을 하고 그 지원을 위한 api는 WAC이라는 표준규격을 따르는 것이 지요. 이 하이브리드라는 개념을 구현하기 위해 우리가 어떻게 고민을 했는지 설명을 드리도록 하겠습니다. Bridge Over Troubled Water 앱스프레소Lab 이상찬 [email protected]
  270. 273 Bridge Over Troubled Water 다리를 만든다고 생각을 해봅시다. 생각할

    게 한 두가지가 아닐 겁니다. ehow.com에서는 심플하게 다음의 8가지로 다 리 건설을 설명하고 있습니다. 1. 다리의 형태를 결정합니다. 여러 형태 중 적합한 형태를 결정해야 겠지요. 2.  다리의 위치를 결정합니다. 지도를 보고 측량하며 여러 위치 중에 가장 합리적으로 지을 수 있는 위치를 선택해야 겠지요. 3.  다리를 디자인 합니다. 교통량을 계산해서 다리가 얼마나 튼튼해야 할지를 시뮬레이션 해야 하겠지요. 해당 결과 에 따라 다리의 모양이 결정될 것이고 이를 통해 건설 후 보수비용 같은 것도 산출 되겠지요. 4. 지반 공사를 합니다. 다리가 건설될 양쪽 끝에 둑을 지어 지반을 만들고 콘크리트 작업등을 할 것입니다. 5. 철골을 조립합니다. 볼트와 너트를 가지고 장난감 조립하듯이 조립해서 양쪽 교량에 배치하도록 합니다. 6. 다리의 깔판을 제작합니다. 알루미늄이나 신소재를 통해 부식에 강하게 만들어 보수비용을 줄이기도 합니다. 7. 다리를 포장합니다. 다리 포장용 장비로 처리합니다. 8. 개통식을 합니다. 샴페인을 터뜨리고 리본을 자르고 하겠지요. 다리를 만드는 8개의 단계를 앱스프레소에 대입해 보겠습니다. 1.  다리의 형태를 결정합니다. 기존에 존재하는 하이브리드 프레임웍과의 차이를 만들기 위해 어떤 기술을 더 추가 할 수 있을지 생각해봅니다. 앱스프레소는 WAC API를 지원하기로 합니다. 실제로 세계 최초로 WAC을 지원하 는 하이브리드 프레임웍이면서 크로스 플랫폼 개발툴입니다. 2.  다리의 위치를 결정합니다. 그렇다면 WAC을 지원하는 것만을 포지션으로 삼아야 할까요? WAC API가 많은 부 분을 사용가능하도록 하긴 합니다. 가속도계, GPS, SMS 등등을 지원합니다. 하지만 각각의 플랫폼이 가지는 개 성이라는 부분도 있습니다. 너무 그 개성을 존중하지 못하는 것은 아닐까요? 앱스프레소는 각 플랫폼의 개성을 존 중하면서 WAC API를 기능으로 가지도록 할 수는 없을까요? 3.  다리를 디자인합니다. 그래서 이렇게 해보았습니다. WAC API를 구현하기 위한 명세서를 작성해 봅니다. WAC API는 위젯 런타임 즉, WRT를 베이스로 하고 있습니다. 여기에 살을 붙이고 여러가지 객체를 정의하며 현재의 WAC 스펙이 되었다고 보면 됩니다. 우리가 만들 앱스프레소는 해당 스펙을 지원하기 위한 기본 토대가 되는 것 이 최소 조건이 됩니다.  일반적으로 개발하는 통신방식으로 보자면 웹뷰에 있는 HTML 페이지에서 자바스크립트 함수를 부르고 해당 자 바스크립트 함수가 웹뷰에서 작동합니다. 이 자바스크립트 함수가 어떤 리턴값을 받고자 한다면 어떻게 해야 할 까요? 네이티브 코드에서 웹뷰에 직접 자바스크립트 함수를 부르도록 해야 할 것입니다. 안드로이드의 loadURL, iOS 의 stringByEvaluatingJavaScriptFromString 메쏘드로 직접 해당 자바스크립트 코드를 불러야 합니다. 이 방식은 어쨌든 비동기식이지요. 이 방식으로 동기식처럼 보이는 것은 만들 수 있을지 몰라도 동기식은 아닙니다. 그런데, WAC 스펙에는 동기식 함수가 있습니다. 우리는 앱스프레소를 만들기 위해 동기식 함수를 구현할 필요가 있는 겁니다. 어떻게 하면 그럴 수 있을까요? 여러가지 안이 있겠지만 약간의 발상의 전환을 합니다. 자바스크립
  271. 274 H3 개발자 컨퍼런스 2012 트를 동기식, 비동기식으로 모두 처리하기

    위해 자체적으로 서버를 내장하고 호출과 응답을 해당 서버가 관장하도 록 하는 것은 어떨까? 해당 방식이 너무 무겁지는 않을까? 여러가지 테스트를 해보고 여러가지 답을 내어봅니다. 이를 토대로 앱스프레소의 기본이 되는 각 플랫폼 별 런타임을 설계해 나갑니다. 4.  지반 공사를 합니다. WAC 스펙을 토대로 인터페이스가 되는 chronometer를 개발합니다. 앱스프레소 내부에 존 재하는 모듈은 전부 배에 사용되는 부품입니다. 각 부품이 배에서 하는 역할을 생각해보시면 이해하시기도 쉽고 재미도 있을 것 같네요. chronometer를 기본으로 그를 구현하는 sail을 만듭니다. sail에는 기능이 제한적인 서버 가 들어가 있고, 서버와 연결되는 웹뷰가 있으며, 웹뷰에서 함수를 호출 하는데 사용할 여러가지 구현체들이 있습 니다. WAC 스펙에 필요한 filesystem 구현에 필요한 기능, 함수에 호출과 응답에 사용한 JSON 객체 등 여러가 지가 맞물려 돌아가도록 되어 있습니다. 5.  철골을 조립합니다. 지반 공사가 된 앱스프레소 sail을 토대로 해당 sail과 연결되는 플러그인을 제작합니다. 함수 를 호출하고 응답하는 과정을 통해 WAC API를 구현합니다. 여기서 앱스프레소 런타임 개발자들이 중요하게 생 각한 것은 다음과 같습니다. “각각의 플랫폼이 상이한 결과값을 주지 않도록 한다.”라는 것입니다. WAC 스펙도 완전무결한 것은 아니기에 안드로이드에는 지원이 가능하지만 iOS에서는 불가한 기능들이 있습니다. 이런 부분 에 대한 고민을 하며 열심히 각 플러그인을 개발합니다. 6.  다리의 깔판을 제작합니다. 콘크리트만 부으면 되도록 만들려면 어떻게 해야 할까요? 각각의 모듈에 대한 빌드 시 스템을 분리할 필요가 있습니다. Xcode 나 이클립스에서 프로젝트를 전부 모아놓고 한번에 빌드하는건 간단합니 다. 각 IDE에서 지원하는 워크스페이스라는 개념이 있으니까요. 앱스프레소는 기본적으로 개발툴과 함께 제공될 것입니다. WAC API를 지원하며 해당 API가 작동하기만 하는 것이 아니라 개발자가 원하는 대로 플러그인을 추 가하거나 할 수 있는 개발툴이 필요한 것입니다. 우리는 이 개발툴로 이클립스를 선택했고 이를 위해 이클립스 플 러그인을 개발할 필요가 생겼습니다. 해당 모듈을 사용자가 원하는 대로 모아서 빌드하고 각각의 플랫폼에 대응하 는 결과물을 만들어 내며, WAC에 대응하는 여러가지 파라미터를 입력할 수 있도록 하는 에디터를 제공하도록 합 니다. 7.  다리를 포장합니다. 이렇게 각각 작업한 내용에 대해 빌드 명령어를 내리면 이클립스가 앱스프레소 스튜디오가 되 고 각 플랫폼용 런타임이 sail, chronometer, 플러그인 등으로 분리되어 라이브러리 화 됩니다. 8.  개통식을 합니다. 해당 앱스프레소 스튜디오에 버전을 붙여 사이트에 릴리즈 합니다. 이 과정을 거쳐 2011년 3월 15일에 첫 다운로드가 시작되었고, 이렇게 오픈소스가 되기 까지 많은 변화와 기능 추가 등을 해왔습니다. sail 의 설계가 바뀌기도 하고 앱 자체적인 설정파일 구조에 변경을 가하기도 했습니다. 다리란 무엇일까요. Simon & Garfunkel라는 가수를 아시나요? The Boxer 나 The Sound of Silence 등 의 명곡을 부른 가수입니다. 이 가수의 노래 중에 Bridge over troubled water라는 노 래가 있습니다. 이 노래의 가사처럼 세찬 파도가 치는 플랫폼의 바다 위로 튼튼하게 다리를 놓고 싶었습니다. 앱스프레소팀에서 앱스프레소를 설계할 때, 이미 시장에는 여러가지 하이브리드 프레임웍이 있었습니다. 당시에 이미 폰갭이나 앱셀러레이터 등 이 시장에 나와서 어느정도 인지도가 있었습니다. 솔직하게 말하면 이미 굉장한 인지
  272. 275 Bridge Over Troubled Water 도를 가지고 있었다고 볼 수

    있습니다. 당시에 국내에 이미 폰갭 관련 개발 서적이 번 역이 되어 있을 정도 였으니 말이지요. 이미 있는 걸 놔두고 왜 우리는 앱스프레소를 만들었을까요? 이건 굉장히 근본적인 질 문이 됩니다. 그냥 위에서 만들자고 했기때문은 아닌게 확실합니다. 앱스프레소팀은 이런 믿음을 가지고 있습니다. Browser as a Platform. 브라우저 자체가 플랫폼이 된 다고 믿습니다. 플랫폼에서 인터넷에 연결하기 위해 띄우는 사파리나 크롬같은 브라 우저가 그 자체로 플랫폼이 되고 그 자체로 생태계를 가진 어떤 것이 될 것이라고 믿 어 의심치 않았던 겁니다. 그 믿음이 앱스프레소라는 다리를 만드는 원동력이 되었습니다. 브릿지 제작의 어려움에 대해 링크드인에서 아이패드용 앱을 제작하며 있었던 고충에 대해 글을 쓴 적 있습니다. 아 싯 간디라는 이 개발자는 링크드인 엔지니어링 사이트에 해당 글을 올린 바 있는데요. 여러가지 하이브리드 앱 개발 블로그 중 저희의 눈길을 끌었습니다. 왜냐하면 우리도 이 사람처럼 웹 소켓으로 브릿지 방식을 개선할 예정이었기 때문이죠. 신기술이나 빠 른 기술에 좀더 집착을 할 수 밖에 없지만 이 기술이 우리의 구조에서 제대로 작동할 지에 대한 것은 별개의 문제였습니다. 서버를 앱 안에 안착시켜 해당 서버를 다리로 삼아 안전한 교통을 이룩했지만 이 문제가 발목을 잡아 웹페이지를 그대로 옮겨오는 것이 힘들어 지는 원인이 되기도 했습니다. API를 추가하거나 해당 방법에 대한 다른 해법을 제시해왔지만 그것이 꼭 옳은 것은 아닌 것 같다는 생각에 많은 개선을 이루고 자 노력을 했습니다. 문제는 언제나 기존과의 호환성이었죠. 이미 이루어 놓은 것들을 포기하는 것은 때로는 많은 반발을 살 수도 있는 것이기 때문입니다. 앱스프레소 브릿지의 특징 폰갭 대비 해서 얼마가 더 빠르다. 이런 접근이 아닌 앱스프레소에서 자체적으로 개발 한 브릿지가 어떤 것인지를 설명드리고자 합니다. 플러그인은 AxPlugin이라는 인터페이스 시작됩니다. 해당 인터페이스는 AxPluginContext와 AxRuntimeContext를 참조합니다. AxRuntimeContext는 앱스프레소로 만들어진 앱이 실행되는 동안 필요한 정보를 보 유하는 인터페이스입니다. 앱에서 보여지는 웹뷰의 인스턴스나 위젯의 인스턴스, 플
  273. 276 H3 개발자 컨퍼런스 2012 러그인 등의 정보를 가지고 있습니다.

    그외에도 웹뷰에 직접 스크립트를 실행시키는 메소드 등도 가지고 있습니다. AxPluginContext는 앱스프레소 플러그인의 메소드가 실행되는 동안 필요한 정보를 보유하는 인터페이스입니다. 메소드의 이름이나 메소드 실행시에 사용된 파라미터등을 가지고 있습니다. 또한, 현재 불려진 자바스크립트의 리턴값을 보내는 sendResult라는 메쏘드를 가지고 있습니다. AxPlugin에는 3가지의 메소드가 있습니다. 플러그인이 생성되었을 때 불려지는 activate()와 플러그인이 소멸할 때 불려지는 deactivate()가 있으며, 자바스크립트 에서 함수를 호출했을 때 불려지는 execute가 있습니다. execute() 의 아규먼트에 AxPluginContext가 들어갑니다. execute()에서 해당 아규먼트에 들어있는 파라미터 를 참조하여 행위를 하도록 네이티브 프로그램을 짜고, AxPluginContext에 결과값을 보내는 메소드를 실행합니다. test라는 플러그인을 만들었다고 하겠습니다. test라는 플러그인은 자바스크립트를 가 지고 있으며 안에 a라는 함수를 가지고 있다고 하겠습니다. 앱을 실행하면 test라는 이름의 AxPlugin이 생성됩니다. AxPlugin의 activate()가 실행되겠죠. 실행된 웹뷰에서 자바스크립트로 test.a라는 함수를 실행합니다. 해 당 함수는 앱스프레소 브릿지를 타고 내부로 들어가 AxPluginContext를 생성합니 다. test와 a, 그리고 a를 실행하며 함께 보낸 아규먼트를 파라미터화 합니다. 생성된 AxPluginContext는 test라는 이름의 AxPlugin 의 excute() 의 아규먼트로서 사용되 어 실행됩니다. 다음의 그림처럼 말이지요. <앱스프레소 브릿지 구조>
  274. 277 Bridge Over Troubled Water 그렇다면 브릿지 안에는 어떻게 되어

    있을까요? 우선 최소한의 기능을 가진 서버가 내장되어 있습니다. iOS에서는 cocoahttpserver 라는 오픈소스 서버를 사용했습니다. 해당 서버는 필요한 경우 서버에 대한 응답 을 따로 구현 할 수 있도록 해두었습니다. 이렇게 하면 어떨까요? 해당 응답이 들 어올 때, 특정한 머릿말에 대해 우리가 따로 준비한 응답 객체로 넘기도록 구현 합니다. 예를 들자면 “/appspresso/plugin/”으로 시작하는 것이 들어온다면 AppspressoPluginResponse에서 응답을 해주도록 처리합니다. 해당 클래스는 이렇 게 들어온 함수의 정보를 AxPluginContext 화하고 알맞은 AxPlugin을 찾아 excute() 가 실행되도록 합니다. 이 과정에서 여러 가지 디자인 패턴이 사용되었음을 확인하실 수 있을겁니다. 앱스프레소 브릿지 기능을 충분히 활용한 앱스프레소 플러그인을 제작해보자. 앱스프레소 스튜디오에서 기본으로 제공하는 WAC API 나 Extension API는 모두 브 릿지 구조로 작동하는 것입니다. 앱스프레소 스튜디오에서 PDK 기능을 이용해 플러 그인을 개발하는 것은 마찬가지로 해당 브릿지 구조에서 작동하는 코드를 생성하는 것입니다. 때문에 기본적으로 생성되는 플러그인 프로젝트는 앱스프레소 브릿지 구조 의 모든 것을 보여준다고 해도 과언이 아닙니다. 만드는 과정은 다음과 같습니다. (해 당 내용은 appspresso.com 의 Developer Center > Appspresso PDK에 있는 내용 을 발췌한 것입니다.) 앱스프레소 스튜디오 > File > New > Appspresso Plugin을 선택합니다. 프로젝트 이 름, 플러그인의 ID, 버전등을 입력합니다. iOS 모듈을 선택하고, 해당 플러그인의 프 로젝트 이름과 위치를 지정합니다. 모듈의 클래스 명과 해당 플러그인이 지원할 SDK 버전을 선택합니다. 자동으로 생성되는 코드에 echoSync와 echoAsync 함수가 구현되어 있음을 확인하 실 수 있습니다.
  275. 279 Bridge Over Troubled Water 해당 플러그인 프로젝트를 사용할 애플리케이션

    프로젝트를 생성합니다. 플러그인 프 로젝트 추가 버튼을 누르고 방금 생성한 플러그인 프로젝트를 선택합니다. <앱스프레소 플러그인 프로젝트 선택> 이 애플리케이션 프로젝트의 html 파일의 내용을 다음과 같이 변경합니다. <!DOCTYPE html> <html> <head> <script type="text/javascript" src="/appspresso/appspresso.js"></script> <meta http-equiv="pragma" content="no-cache" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script> //activate ax.log(), comment out when you release app ax.runMode = ax.MODE_DEBUG; function errback(err) { alert(err.code + " : " + err.message); } function echoAsync() { myplugin.echoAsync(
  276. 280 H3 개발자 컨퍼런스 2012 function(message) { alert(message); }, errback,

    "call myplugin.echoAsync()"); } function echoSync() { var message = myplugin.echoSync("call myplugin.echoSync()"); alert(message); } </script> </head> <body> <h1>Hello World</h1> <h3>com.axexample.echoapp</h3> <button onclick="echoAsync();">EchoAsync</button> <br> <button onclick="echoSync();">EchoSync</button> </body> </html> 해당 버튼을 누르면 javascript에서 실행한 내용이 네이티브 소스의 excute:로 이동하 였음을 알 수 있을 것입니다. 푸쉬 노티피케이션 이나 광고 보여주기도 단순한 연장선상에 있을 뿐입니다. appspresso.com 의 Developer Center > Plugin Sample을 확인해 보시면 아이폰 용 APNS 샘플과 안드로이드용 C2DM 플러그인, 그리고 공통으로 사용할 수 있는 Daum Ad@m 플러그인을 확인하실 수 있습니다. APNS를 구현하기 위해 플러그인 프로젝트에 델리게이트를 추가하고 해당 메소드를 구현하도록 합니다. 우선 .h 파일에 델리게이트를 추가합니다. #import <Foundation/Foundation.h> #import "AxPlugin.h" @protocol AxContext; @protocol AxPluginContext;
  277. 281 Bridge Over Troubled Water @interface com_example_ax_test_MyPlugin : NSObject<AxPlugin, UIApplicationDele-

    gate>{ @private NSObject<AxRuntimeContext> *_runtimeContext; } @property (nonatomic,readonly,retain) NSObject<AxRuntimeContext>* runtimeCon- text; - (void)activate:(NSObject<AxRuntimeContext>*)runtimeContext; - (void)deactivate:(NSObject<AxRuntimeContext>*)runtimeContext; - (void)execute:(NSObject<AxPluginContext>*)context; @end .m 파일에 구현할 메소드를 추가하고 activate에 몇 가지 함수를 추가합니다. #import "AxRuntimeContext.h" #import "AxPluginContext.h" #import "AxError.h" #import "com_example_ax_test_MyPlugin.h" @implementation com_example_ax_test_MyPlugin @synthesize runtimeContext = _runtimeContext; - (void)activate:(NSObject<AxRuntimeContext>*)runtimeContext { _runtimeContext = [runtimeContext retain]; // UIApplicationDelegate를 구현했음을 Appspresso 런타임에게 알림 [_runtimeContext addApplicationDelegate:self]; // 노티피케이션 서비스를 사용하겠다고 선언. 얼럿, 뱃지, 사운드 모두 사용함 [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRe- moteNotificationTypeBadge | UIRemoteNotificationTypeSound |UIRemoteNotification- TypeAlert)]; } - (void)deactivate:(NSObject<AxRuntimeContext>*)runtimeContext { [_runtimeContext release]; _runtimeContext = nil; } - (void)execute:(id<AxPluginContext>)context { NSString* method = [context getMethod]; if ([method isEqualToString:@"echo"]) { NSString* message = [context getParamAsString:(0)];
  278. 282 H3 개발자 컨퍼런스 2012 [context sendResult:(message)]; } else {

    [context sendError:(AX_NOT_AVAILABLE_ERR)]; } } -(void)application:(UIApplication *)application didFailToRegisterForRemoteNoti- ficationsWithError:(NSError *)error { // 푸시 알림 등록에 실패하면 호출되는 메소드 } -(void)application:(UIApplication *)application didReceiveRemoteNotifica- tion:(NSDictionary *)userInfo { // 푸시 알림 메시지를 수신하면 호출되는 메소드 } -(void)application:(UIApplication *)application didRegisterForRemoteNotifica- tionsWithDeviceToken:(NSData *)deviceToken { // 사용자가 푸시 알림 수신을 허용하면 앱이 실행될 때 마다 디바이스 토큰을 매 개변수로 호출됨 } @end 최초에서 다시 최초로 2011년 3월에 출시된 앱스프레소는 다음과 같은 마일스톤을 거쳐왔습니다. WAC2.0 스펙 지원을 통해 WAC을 지원하는 크로스 플랫폼 개발툴로써 자리를 확고 히 할 수 있었습니다. MWC 2012에 참가하여 WAC 관계자와 친분을 쌓고 해외에 앱 스프레소를 알리는 자리를 가질 수 있었습니다. 온더플라이 빌드 기능을 통해 디버깅의 강화 및 개발의 편의성을 증진하여 개발툴로 써의 새로운 지향점을 제시할 수 있었습니다. 애플이 iOS6에서야 지원되는 웹뷰와 브 라우저의 연결을 통한 디버깅 기능을 앱스프레소는 이미 지원하고 있었습니다. PDK 기능을 추가하여 개발자가 네이티브 코드를 자유롭게 추가할 수 있도록 하였습 니다. 이를 통해 자바스크립트 만으로 제공하기가 힘든 기능을 개발자 스스로 개발할 수 있는 환경을 조성하였습니다.
  279. 283 Bridge Over Troubled Water 짧다면 짧고 길다면 길다고 할

    수 있는 개발기간 동안 많은 우여곡절이 있었습니다. 플랫폼의 대대적인 업데이트나 신기종의 발매로 인한 호환성 문제 등 여러 어려움도 있었고, 개발자들과의 만남을 통한 즐거움도 많았습니다. 그리고 저희가 쌓은 개발 노 하우가 KTH에 도움되는 벅찬 순간도 많았습니다. 그리고 최초의 WAC API 지원 크로스 플랫폼 개발툴은 다시 최초로 그 소스를 공개 하여 좀더 발전을 거듭할 수 있도록 하고자 합니다. 오픈소스화 된 앱스프레소를 보시 고, 지금 이 글을 통해 앱스프레소의 브릿지 구조를 이해하심으로써 조금이나마 도움 이 되길 바랍니다. 참고자료 앱스프레소 홈페이지 : http://www.appspresso.com
  280. 284 H3 개발자 컨퍼런스 2012 모바일 플랫폼의 춘추시대가 끝나고 바야흐로

    애플과 안드로이드 양 강 구도로 굳어 지는 분위기 이다. 두 개 플랫폼 정도는 네이티브 앱으로 별도 제작해도 큰 무리가 없 지 않냐는 의견도 있겠으나 두 O/S의 기반 기술이 절대적으로 달라 각 O/S 별 진입 장벽이 높고 비용도 만만치 않다. 두 마켓을 아우를 수 있는 앱 제작을 위한 방법인 웹 기술과 이를 활용한 멀티플랫폼 지원은 여전히 업계의 중요한 화두이다. 본 세션에서는 웹 기술을 이용해 제작된 푸딩얼굴인식(3.0) 앱의 제작 사례를 살펴 봄 으로써 웹 개발자가 iOS/Android 앱 제작에 부딪히는 어려움을 알아보고 제작에 필요 한 다양한 테크닉을 살펴 보고자 한다. 푸딩얼굴인식을 통해 살펴 본 하이브리드 앱 제작 노하우 앱스프레소Lab 박종순 [email protected]
  281. 285 푸딩얼굴인식을 통해 살펴 본 하이브리드 앱 제작 노하우 하이브리드

    앱과 프레임워크들 구글 검색에서 “mobile app framework”라고 검색해 보면 수많은 프레임워크가 검색 되는데, 웹기술을 이용한 프레임워크는 크게 두 가지 종류로 나누어 볼 수 있다. 첫째. 웹 기술로 만든 웹앱을 네이티브로 감싸 iOS/Android 등의 O/S에 설치 가능 한 앱으로 패키징해 주는 프레임워크로 PhoneGap/Appcelerator/Appspresso 등 이 해당한다. 이들 프레임워크로 하이브리드 앱을 만들 때에는 두번째로 설명 할 다 양한 Javascript 프레임워크를 추가해 개발할 수 있다. (단 Appcelerator 의 경우 별 도의 Javascript 프레임워크 사용을 하지 않는다.) 해외에서는 주로 “Cross platform mobile app framework”란 용어로, 국내에서는 “하이브리드 앱 프레임워크”로 알려 져 있다. 참고 http://phonegap.com http://www.appcelerator.com http://appspresso.com 둘째. 웹 기술로 모바일 앱이나 모바일 웹사이트를 만들기 위한 Javascript 프레임워 크로 jQueryMobile, JQTouch, Sencha Touch 등이 해당한다. 이들 Javascript 프레 임워크는 모바일 플랫폼별 앱 파일로 패키징하는 기능은 제공하지 않으며, 웹 기술을 이용한 다양한 UI 컴포넌트와 페이지 효과 등을 제공한다. 참고 http://jquerymobile.com http://www.sencha.com http://jqtouch.com http://joapp.com 단일페이지 인터페이스 하이브리드앱 제작 시 기본적인 개념으로 반드시 이해하고 넘어가야 할 개념이다. 기존 ajax를 이용한 RIA를 개발해 본 경험이 있다면 기본적인 단일페이지 인터페이스 를 이용해 본 것이다. 논리적으로 하나의 페이지 위에 ajax를 이용한 동적 콘텐츠를 로
  282. 286 H3 개발자 컨퍼런스 2012 딩하는 방식으로 어플리케이션을 구성하며, 페이지

    전환에 따른 세션 정보 공유가 용 이하고, 앱에서 페이지 전환 애니메이션 등을 용이하게 처리할 수 있다. 하이브리드앱에서 단일페이지 인터페이스로 앱 개발 시 cross domain 제약이 발 생한다. (단말에서 실행 되는 앱은 별도의 도메인을 가지고 있지 않으므로 원격 host에 ajax 요청 시 보안 오류가 발생하게 된다.) 앱스프레소에서는 이를 우회 할 수 있는 ax.ext.net 관련 API를 제공하고 있으며 ajax 요청 시 이를 이용하거나, CORS(Cross-origin resource sharing) 설정을 통해 제약을 회피할 수 있다. 단, CORS를 이용한 서버 설정 시 모바일 앱의 경우 모든 host에 대해 접근을 허용해야 하므로 ax.ext.net API를 사용하길 권장한다. 참고 http://enable-cors.org http://msdn.microsoft.com/ko-kr/magazine/cc507641.aspx http://iolothebard.tistory.com/496 http://appspresso.com/api/extension/symbols/ax.ext.net.CurlOpts.html 푸딩 얼굴인식 3.0 기술요소 앱스프레소와 웹 기술을 이용해 제작된 “푸딩얼굴인식 3.0” 앱의 기술요소를 살펴 보자. Javascript Library • jQuery 1.6 • xx - 자체 제작 라이브러리 (페이지 관리, 파일시스템 레퍼, iScroll 레퍼 등) • iscroll4 – 헤더영역을 고정하고 Body에 스크롤 영역을 만들기 위함 + Carousel • jpegencoder - Android에서 canvas를 jpeg이미지로 저장하기 위함 • OAuth 인증을 위한 oauth.js, sha1.js jQueryMobile, SenchaTouch 등 수 많은 오픈 소스 프레임워크가 존재하나 푸딩얼굴 인식 3.0에서는 자체 제작한 xx 라이브러리를 사용 중이다. xx를 별도 제작한 주된 이 유는 오픈 프레임워크의 경우 커스터마이징이 쉽지 않고 만족할 만한 성능이 나오지
  283. 287 푸딩얼굴인식을 통해 살펴 본 하이브리드 앱 제작 노하우 않았기

    때문이다. xx 라이브러리의 초기 버전은 “Appsprsso KitchenSink” 데모 앱에 포함되어 있으니 활용해 보길 바란다. 앱스프레소 내장 API 앱스프레소 1.2에 기본적으로 내장된 API 목록이다. deviceapis로 시작하는 모듈은 WAC API, ax.ext로 시작하는 모듈은 앱스프레소 확장 API이다. 참고 http://appspresso.com/ko/api-reference-ko (앱스프레소 API Reference) 커스텀 플러그인 기본 내장된 Device API로는 구현 불가능한 부분들을 커스텀 플러그인으로 제작 하였 다. 예를 들어 “닮은꼴 배틀”에서 사용되는 카메라의 경우 네 장의 사진을 촬영하고 얼 굴인식까지 처리하는데, 이는 웹 기술만으로 구현이 어려우므로 별도의 카메라 플러 그인으로 제작 된 경우이다. (플랫폼 별로 1명씩의 네이티브 개발자 참여)
  284. 288 H3 개발자 컨퍼런스 2012 . 기타 추가된 커스텀 플러그인은

    광고를 위한 Admob과 기타 통계관련 플러그인이 개 발 되었다. 실전 앱 제작 테크닉 “웹 개발”스러운 “앱 개발” - 앱스프레소 On The Fly 웹 개발을 주로 한 필자에게 하이브리드 앱 개발시 가장 답답했던 점은 소스코드를 수 정하고 단말에서 확인하기 위해 재컴파일이 필요하다는 것이었다. 웹 개발자들은 주 로 코드수정 > 새로고침, 코드수정 > 새로 고침을 반복해 가며 웹 어플리케이션을 개 발하게 되는데, 현재나온 모바일 앱 프레임워크는 이런 식의 개발을 지원하지 않는다. 코드 수정 시 재 컴파일을 필요로 하며 컴파일에 소요되는 시간이 오래 걸리므로 웹 개발처럼 빠른 개발이 진행되지 않았다.
  285. 289 푸딩얼굴인식을 통해 살펴 본 하이브리드 앱 제작 노하우 앱스프레소는

    이를 해소할 방안으로 On the fly building 기능을 제공하고 있으며 이 를 활용해 웹 개발과 마찬 가지로 “코드수정 > 새로 고침”의 개발이 가능하게 되었으 니 꼭 사용해 보시길 바란다. On the fly building을 위한 환경 설정 시 주의할 점은 앱 스프레소 스튜디오를 실행 중인 개발머신과 단말은 같은 네트워크에 있어야 하는데, 다음과 같이 동일한 무선 공유기를 사용하는 것이 가장 빠른 방법이다. 참고 http://appspresso.com/ko/archives/4098 (On the fly building 사용법) Fast button click 웹 페이지에서 버튼 이벤트로 onclick를 사용하는데, 모바일로 넘어오게 되면 onclick 이벤트를 이용한 버튼이 다소 답답하게 느껴지게 된다. 이는 모바일 브라우저에서 터 치 이벤트인지를 판단하기 위해 약 300ms의 delay 타임을 사용하기 때문이다. 네이티브와 같이 빠른 터치반응을 만들기 위한 방법들이 구글 개발자 사이트와 iScroll 을 만든 cubiq.com에 소개되어 있다. 푸딩얼굴인식 앱에서도 이를 참고해 iScroll 요 소를 제외 한 나머지 버튼들에 대해서 onclick 이벤트 대신 touchstart 이벤트를 사용 한다.
  286. 290 H3 개발자 컨퍼런스 2012 var touchEvent = 'touchstart'; //

    touch event를 지원하지 않는 브라우저에서는 mousedown을 이용 if (typeof document.body.ontouchstart === 'undefined' ) { touchEvent = 'mousedown'; } document.getElementById('someElement').addEventListener(touchEvent, function(e){ // do something }, false); 참고 https://developers.google.com/mobile/articles/fast_buttons http://cubiq.org/remove-onclick-delay-on-webkit-for-iphone iScroll 터치 이벤트 처리를 위한 레퍼 헤더바를 고정하고 바디영역을 스크롤로 사용하는 방식은 가장 일반적인 앱의 형태이 다. 하이브리드 앱에서 주로 iScroll 라이브러리를 사용하게 되는데, 실제 앱에 적용할 경우 터치 반응성에 대한 문제가 부딪히게 된다. 예를 들어 유저는 스크롤 하기 위해 화면을 쓸어 내렸는데 터치 판단 되어 버린다던 지, 터치를 의도 했는데 반응이 없는 경우이다. 푸딩 얼굴인식에서는 이 터치 반응성을 높이고 일관되게 iScroll을 객체를 관리하기 위 해 iscroll 레퍼 모듈인 xx.scroll을 추가 하였다. 이 모듈의 주 역할은 터치인지 스크롤 인지를 판단하여 터치인 경우 인자로 넘겨 받은 터치 콜백을 호출해 주는 역할이다. 일반적으로 스크롤을 의도한 경우 터치 시간은 300ms를 넘게 된다. xx.scroll 모듈에 서는 터치 또는 스크롤 유무를 판단하는 기준으로 총 터치된 시간, 터치 후 이동 중인 지 여부, 이벤트가 발생한 페이지의 활성화 유무를 이용 하였다. 1. 터치 타임을 계산하기 위한 이벤트 등록. document.addEventListener('DOMContentLoaded', function(){ var body = document.body, touchEvent = 'touchstart'; if (typeof body.ontouchstart === 'undefined' ) { touchEvent = 'mousedown'; }
  287. 291 푸딩얼굴인식을 통해 살펴 본 하이브리드 앱 제작 노하우 body.addEventListener(touchEvent,

    function(e){ touchStart = new Date().getTime(); }, false); body.addEventListener(touchEvent, function(e){ if (isTouchEvent) { isScrolling = true; } }, false); body.addEventListener(touchEvent, function(e){ isScrolling = false; }, false); }); 2. 터치 유무를 판단하는 onTouchEnd 이벤트 핸들러 function onTouchEnd(e){ var args = this.args, target = e.target, eventPage, i = 10; if (isScrolling) { isScrolling = false; } else { while (i--) { if($(target).hasClass('page')) { eventPage = $(target).attr('id'); break; } target = target.parentNode; } if (!xx.page[eventPage] || xx.page[eventPage].info.isShown) { if(touchTime < 300 && touchTime > 1) { if (args.onTouchEnd) { args.onTouchEnd(e); } } } } } 위 콜백은 iScroll 라이브러리에서 touchend시에 호출되며, 현재 스크롤 중인지 여부 를 체크한 뒤 해당 이벤트가 발생한 페이지가 현재 활성화 유무를 체크한다. 마지막으 로 터치 타임이 300ms미만인 경우에만 최종 touchend callback을 호출한다.
  288. 292 H3 개발자 컨퍼런스 2012 button 이벤트를 담당하는 하나의 이벤트

    delegate iScroll의 터치영역을 제외한 나머지 버튼에 대해서는 하나의 이벤트 delegate를 사용 해 터치를 처리한다. 단일페이지 인터페이스 구조 다음에 touchstart를 이용한 이벤트 처리가 된 앱의 경우 유저가 의도하지 않은 중복 터치를 방어할 방법이 필요하다. 푸딩얼굴인식의 경우 body에 하나의 이벤트 리스너를 등록하고, 터치시 타켓의 테그 네임에 따라 버튼을 처리하는 방식으로 구현 하였다. 이렇게 하나의 리스너 안에 버 튼이벤트 처리를 위임 함으로써 페이지 이동 시 페이지 락이 필요한 경우 등의 처리를 하나의 클래스 안에서 처리하는 효과를 얻게 되었다. 버튼 터치 시 해당 타켓이 버튼 인지 유무를 판단해야 하고, 이벤트가 활성화 된 페이지에서 일어난 것인지 등을 판단 해야 하므로 반응성을 떨어뜨리진 않을까 하는 우려도 있었으나, 실제 동작에는 유저 는 느끼지 못할 정도로 빠른 반응성이 유지 되었다. 다음 코드는 전역으로 정의된 touch start 이벤트 핸들러로 터치가 시작된 이벤트 타 켓을 시작으로 상위 엘리먼트를 따라 올라가며 해당 엘리먼트가 버튼 요소인지를 먼 저 체크한다. (HTML5의 표준 속성 중 커스텀하게 사용 가능한 data-* 속성을 이용 하고 있으며 data-role속성이 button인 경우에만 버튼 콜백을 호출한다.) 버튼요소인 경우 버턴의 누름 휴과를 주기 위해 pressed 클래스를 추가하고 200ms 이후 실제 액션을 담당하는 콜백을 호출하게 된다. document.body.addEventListener('touchstart', function(e) { var target = e.target, btnName, eventPage, i = 10; while(i--) { if (target.tagName === 'BODY') { return; } if($(target).attr('data-role') === 'button') { i = 10; break; } target = target.parentNode; } if (target.getAttribute('data-role') === 'button') { btnName = $(target).attr('title');
  289. 293 푸딩얼굴인식을 통해 살펴 본 하이브리드 앱 제작 노하우 if

    (_DEBUG) { console.log('>>>>>>>> ' + btnName + ' touch'); } $(target).addClass('pressed'); setTimeout(function() { if (xx.page.loadingPage) { console.log('XXX 페이지 로딩 중!!!!', xx.page.loadingPage); return; } $(target).removeClass('pressed'); while (i--) { if($(target).hasClass('page')) { eventPage = $(target).attr('id'); break; } target = target.parentNode; } if (_DEBUG) { console.log('touch action:', eventPage, btnName); } onButtonTouched(btnName, eventPage); }, 200); e.stopPropagation(); e.preventDefault(); } }, false); 다음 코드는 실제 버튼 액션을 담당하는 onButtonTouched 커스텀 이벤트 핸들러이 다. 중복 터치를 방지하기 위해 필요한 경우 _btnGlobalTouchActionFlag = true로 지정하고 있으며, 이 경우 1초동안 터치이벤트를 무시하게 된다. 그리고 이벤트가 발 생한 페이지에 따라 분기처리 하고 있는데, 이렇게 하는 이유는 페이지 전환이 일어나 는 애니메이션 효과 도중 터치가 일어난 경우 엉뚱한 페이지의 버튼 이벤트가 추가로 발생하는 것을 방지하기 위한 용도이다. var _btnGlobalTouchActionFlag = false, _btnGlobalTouchActionTimer = undefined; function onButtonTouched(btnName, eventPage) { if (_btnGlobalTouchActionFlag === true) {
  290. 294 H3 개발자 컨퍼런스 2012 if (_DEBUG) { console.log('두번 터치된

    경우입니다!!!', btnName, event- Page); } if (_btnGlobalTouchActionTimer !== undefined) { g.clearTimeout(_btnGlobalTouchActionTimer); } _btnGlobalTouchActionTimer = setTimeout(function(){ _btnGlobalTouchActionFlag = false; _btnGlobalTouchActionTimer = undefined; }, 1000); return; } switch(btnName) { // basic button case 'btnMy': xx.page.pageMy.show(); break; case 'btnSettings': // 이건 중복 터치가 자주 일어 나므로 중복 터치 방지 _btnGlobalTouchActionFlag = true; xx.page.pageSetting.show(); break; case 'btnBack': case 'btnClose': xx.page.back(); break; } switch (eventPage) { case 'pageMain': if (typeof xx.scroll.wrapperMain === 'undefined') { switch (btnName) { case 'btnFind': xx.page.pageFind.show(); break; case 'btnBattle': xx.page.pageBattle.show(); break; } } break; case '...': }
  291. 295 푸딩얼굴인식을 통해 살펴 본 하이브리드 앱 제작 노하우 if

    (_btnGlobalTouchActionFlag === true) { _btnGlobalTouchActionTimer = setTimeout(function(){ _btnGlobalTouchActionFlag = false; _btnGlobalTouchActionTimer = undefined; }, 1000); } } 초기 앱 로딩 속도 개선 일반적인 하이브리드 앱의 경우 네이티브 앱에 비해 초기 로딩 속도가 느리다는 단 점이 있다. 주된 이유는 단일페이지 인터페이스로 구성되는 앱의 경우 하나의 index. html 안에 사용되는 페이지를 정의하고 있고, 관련 자바스크립트 또한 앱 구동 시에 로딩하는 방식으로 개발 되는데, 웹뷰는 모든 리소스를 읽어 들이기 전까지는 기다려 야 하기 때문이다. 복잡한 앱일 수록 페이지는 늘어나며 웹뷰 입장에서는 관련 DOM 을 파싱하고 관련 리소스까지 로딩 해야 하므로 느릴 수 밖에 없다. 푸딩얼굴인식3.0에서는 이를 해소하기 위한 방안으로 메인 페이지와 인트로를 제외 한 다른 서브 페이지에 대해서는 필요한 경우에만 로딩하는 방식으로 개발 하였다. 이 는 jQueryMobile의 멀티페이지 템플릿에서도 사용되는 기법으로 앱 구동시 웹뷰의 부 담을 최소화 함으로써 빠른 구동을 보장하게 된다. 다음은 index.html에 정의된 페이지 HTML 코드의 일부이다. <!-- page pageFind --> <div id="pageFind" class="page hide ui"></div> <!-- page whois (finding) --> <div id="pageFinding" class="page hide"></div> <!-- page whois result --> <div id="pageFound" class="page hide ui"></div> <!-- page pageBattle --> <div id="pageBattle" class="page hide ui"></div> <!-- page pageBattle --> <div id="pageBattleResult" class="page hide ui"></div> <!-- page pageBattleSearch --> <div id="pageBattleSearch" class="page hide ui"></div>
  292. 296 H3 개발자 컨퍼런스 2012 <!-- page pageBattleSearchStar --> <div

    id="pageBattleSearchStar" class="page hide ui"></div> <!-- page pageBattleSearchStarGallery --> <div id="pageBattleSearchStarGallery" class="page hide ui"></div> 다음은 각 페이지 별 html 파일이다. 필요한 경우 ajax를 이용해 동적 로딩한다. 페이지를 담당하는 xx.page 모듈에서는 해당 페이지의 내용이 없는 경우 bookmarklet 기법을 이용해 관련 스크립트를 로딩하고, html마크업에 대해서는 ajax 로 동적으로 로딩함으로써 필요한 경우에만 페이지 자원을 로딩한다. 다음은 bookmarklet 기법을 이용해 동적으로 스크립트를 로딩하기 위한 addScript 매소드이다. function addScript(url, callback) { if (_DEBUG) { console.log('addScript', url); } if (typeof lazyScriptLoading[url] === 'undefined') { (function(e) { e.onload = callback; e.setAttribute("src", url); document.getElementsByTagName("body")[0].appendChild(e); }(document.createElement("script"))); lazyScriptLoading[url] = true; } else { if (typeof callback === 'function') { callback(); } } }
  293. 297 푸딩얼굴인식을 통해 살펴 본 하이브리드 앱 제작 노하우 jQueryMobile을

    사용해본 개발자라면 pagebeforeshow, pageshow, pagebeforehide, pagehide와 같은 페이지 이벤트에 익숙할 것이다. 이런 페이지 이 벤트는 jQueryMobile 뿐만 아니라 일반적인 자바스크립트 모바일 프레임워크에도 공 통적으로 제공되는 이벤트로 페이지가 전환되는 시점에 개발자 소스코드를 실행하기 위한 용도로 제공된다. xx.page 모듈 역시 페이지 전환 시 후킹을 위한 다양한 이벤트를 구현 하였으 며, 동적 스크립트 로딩을 위해 onPageBeforeLoadForInit 이벤트를 구현 하였다. onPageBeforeLoadForInit 이벤트가 실행되는 시점은 각 페이지의 세부 HTML을 ajax로 로딩한 이후 호출 되는데, 이런 이유로 동적으로 로딩되는 스크립트에서는 해 당 페이지의 DOM 요소를 즉시 접근할 수 있으므로 DOM요소가 로딩되었는지 여부 를 신경 쓸 필요 없이 개발이 가능하다. 다음 코드는 lazy 로딩이 필요한 페이지 정의 코드이다. xx.page.add({ id: 'pageBattleSearchStar', onPageBeforeLoadForInit: function(){ var self = this; app.common.addScript('js/page_battle_search_star.js', function(){ self.info.onPageLoad = function() { app.pageBattleSearchStar.getRecommmendStar(); if (xx.scroll.wrapperBattleSearchStar) { xx.scroll.wrapperBattleSearchStar.refresh(); } }; }); }, onPageBeforeHide: function() { app.pageBattleSearchStar.resetStatus(); }, useAdmob: false, useLocale: true }); 페이지 전환 효과 대부분의 앱은 여러 페이지로 구성되며, 네이티브/하이브리드와 상관 없이 페이지 전 환 시 페이지 전환 효과를 가지고 있다. 페이지 전환효과가 없는 일반적인 모바일 웹 의 경우 로딩 전 하얀 화면이 나타난 이후 점차적으로 콘텐츠가 로딩 된다. 이러한 로
  294. 298 H3 개발자 컨퍼런스 2012 딩시간 동안의 하얀 화면을 방지하기

    위해 하이브리드 앱에서는 단일페이지 인터페 이스로 개발하며, 로딩 이후 네이티브와 유사한 페이지 전환 효과를 자바스크립트나 CSS를 이용해 구현한다. 하이브리드 앱에서의 페이지 전환 효과는 플랫폼 별로 제공하는 효과를 에뮬레이팅 하는 것이어서 네이티브앱에 비해 품질이 많이 떨어지는 단점이 있다. 특히 안드로이 드 고해상도 단말의 경우 최신 CSS기술을 이용한 하드웨어 가속을 이용한 경우가 오 히려 품질이 떨어질 수 있으므로 단말에 따른 분기 처리가 필요하다. HTML5의 transition을 이용한 애니메이션을 이용하는 경우 디바이스의 하드웨어 가 속을 이용한다는 장점이 있다. 다음은 각 페이지의 공통 class로 0.3초 동안의 전환 효과를 정의 한다. .page{ width: 100%; height: 100%; left: 0; top: 0; position: absolute; overflow: hidden; -webkit-transition: all 0.3s ease-out; } 푸딩얼굴인식3.0의 경우 iOS와 Android 일부 단말에서 opacity와 transform scale 을 애니메이션 효과로 사용 하는데, 위 page 클래스에서 정의된 transition 값에 의 해 0.3초 동안 opacity와 scale을 분할하여 애니메이션으로 보여진다. 다음 코드의 useTransition 변수는 H/W가속을 이용한 트랜지션 효과를 사용할지 여부를 담고 있 는데, 안드로이드 고해상도(물리 해상도가 480px 이상) 단말인 경우 하드웨어 가속 없이 자바스크립트만을 이용한 애니메이션을 사용하도록 분기처리 하였다. if (animationType === 'slide') { if(arg.type === 'vertical'){ if (useTransition === false) { $(self).animate({top:0}, animationTime); } else { self.style.top = 0; } }else{ if (useTransition === false) { $(self).animate({left:0}, animationTime);
  295. 299 푸딩얼굴인식을 통해 살펴 본 하이브리드 앱 제작 노하우 }

    else { self.style.left = 0; } } } else { // 푸딩얼굴인식 3.0에서 사용된 애니메이션 if (useTransition === false) { $(self).animate({opacity:1}, animationTime); } else { $(self).css({opacity:1, '-webkit-transform': 'scale(1)'}); } } CSS 개발자와 협업 단일페이지 인터페이스로 제작된 앱에서 멀티페이지 템플릿은 초기 로딩속도에 대한 이점과 더불어 CSS개발자와의 협업에도 큰 도움을 준다. 페이지 별로 구성된 html 파 일은 CSS 개발자에 의해 페이지 레이아웃이 변경 될 경우에도 최소한의 코드충돌로 개발을 진행해 나갈 수 있다. 버튼 이벤트가 필요한 경우 id속성을 지정 하거나 특정 class를 약속하는 방식 등이 많 이 이용 된다. 푸딩얼굴인식3.0의 경우 이와는 별도로 data-role이 button으로 지정 된 마크업에 대해 버튼처리를 한다고 약속 하였으며, CSS 개발자는 버튼에 대해 다음 과 같이 data-role 속성을 지정하고 하위 엘리먼트에 복잡한 마크업을 가능하게 함으 로써 마크업 유연성을 높이고 개발자와의 협업을 용이하게 할 수 있었다. <div class="header"> <div class='left'> <button data-role="button" title="btnBack" class="back"> <img src="image/icon_back.png" alt="back" /> <div class="imgfix">&nbsp;</div> <span class="bg"></span> </button> </div> <div class="center"> <h2 class="title nls" nls-key="battle_headline">닮은꼴 배틀</h2> </div> </div>
  296. 300 H3 개발자 컨퍼런스 2012 다음 코드는 전역으로 정의된 버튼이벤트

    핸들러로 data-role이 버튼인지 확인하고 버튼 이벤트를 처리한다. document.body.addEventListener('touchstart', function(e) { var target = e.target, btnName, eventPage, i = 10; while(i--) { if (target.tagName === 'BODY') { return; } if($(target).attr('data-role') === 'button') { i = 10; break; } target = target.parentNode; } if (target.getAttribute('data-role') === 'button') { // 버튼 이벤트 처리... // ... 다국어 처리 2011년 H3에서 발표된 “푸딩얼굴인식 앱을 통해 본 하이브리드 앱 아키텍처 및 개발 방법” 세션에서 Placeholder HTML Markup과 Marker CSS Class를 활용한 다국어 지원방법이 소개 되었다. 언어별로 하나의 HTML에 지정된 CSS Class에 대해 언어 별로 선언된 messages.json 파일 내용으로 앱 로딩 시에 선택된 언어로 치환하는 방 법으로 아주 효율적이고 유지보수도 쉽다. 푸딩얼굴인식3.0 앱의 경우 멀티 페이지 템플릿을 이용하고 있어 위 기술을 동일하게 이용하기에는 무리가 있었다. 페이지가 전환될 경우 ajax를 이용한 동적 로딩이 되므 로 페이지 별 DOM은 앱 실행시가 아닌 런타임에 생성된다. 이렇게 동적으로 불러진 페이지에 선택된 언어로 업데이트 할 경우 잠깐 기본 메시지로 보여진 이후 업데이트 된 언어로 보이는 어눌한 현상이 발생하게 된다. 이를 방지하기 위해 언어별로 페이지 템플릿 파일을 분리하여 다국어 처리가 끝난 html을 로딩하도록 조치 하였다. 이 경우 언어별로 html파일이 따로 존재해야 하는 관
  297. 301 푸딩얼굴인식을 통해 살펴 본 하이브리드 앱 제작 노하우 리상의

    번거로움은 있으나, html 특성상 언어가 추가되더라도 앱 사이즈에 큰 부담이 없으며, 동적으로 로딩될 DOM요소와 페이지 모듈 스크립트 초기화 중 언어까지 업데 이트 해 주어야 하는 부담을 줄이는 효과를 얻을 수 있었다. 하지만 메인 페이지에 대해서는 Placeholder HTML Markup과 Marker CSS Class 를 활용한 다국어 처리를 하고 있으며, 런타임에서 사용되는 여러 다이얼로그 메시지 들은 messages.json 파일에 정의하고 사용 중이다. function alert(scb, msg) { ax.ext.ui.alert(scb, msg, {'positive': app.nls.get('common_ok')}); }
  298. 302 H3 개발자 컨퍼런스 2012 참고 http://h3.paran.com/2011/session/hybrid-app-architecture-and- development-method.html 파일시스템 레퍼

    푸딩얼굴인식3.0 앱에서 가장 많이 사용된 Device API는 Filesystem 모듈이다. • 1. 푸딩얼굴인식 앱의 “마이 히스토리” 데이터 관리: -폴더별로 json과 이미지 파일을 저장 • 2. OAuth 토큰 json파일로 저장하고, 페이스북 겔러리 썸네일 이미지 캐싱. • 3. 앱의 환경 설정값을 json 파일로 저장 (iOS의 경우 HTML5 LocalStorage가 휘발성으로 바뀌면서 파일로 저장함) 하이브리드앱 제작 시 오프라인을 대응하기 위한 용도로 파일시스템 사용이 빈번 한데, 이 경우 제대로 파일이 저장 되었는지, 저장된 json 파일의 내용은 무엇인지 등 개발 시 손쉬운 파일시스템 접근이 필요해 진다. 앱스프레소 홈페이지에 공개된 “Appspresso KitchenSink” 데모에는 앱 내의 버추얼 파일시스템을 브라우징 할 수 있는 브라우저가 포함되어 있다. 앱 개발시 이를 적절히 활용하면 파일시스템에 저장 된 내용을 앱에서 바로 확인이 가능하여 개발 효율을 높일 수 있다.
  299. 303 푸딩얼굴인식을 통해 살펴 본 하이브리드 앱 제작 노하우 WAC

    Filesystem 모듈의 경우 API 사용법이 개발자 친화적이지 않다. 예를 들어 파 일을 쓰기 위해서는 resolve API를 호출하고 해당파일이 있는 경우 스트림을 open하 고 없는 경우 파일생성을 하는 등 일련의 과정이 복잡하다. 푸딩 얼굴인식 앱에서는 xx.fexplorer 란 이름으로 Filesystem 모듈을 레핑하여 파일 사용의 방법을 간소화 하 였다. (다음은 파일 쓰기 매소드의 예.) /** * 파일 쓰기 매소드 * * @name writeFile * @property {string} path 저장될 파일명을 포함한 풀 경로 * @property {string} text 저장할 텍스트 * @property {boolean} base64 여부. default false * @property {function} scb success callback * @property {function} ecb error callback * @memberOf xx.fexplorer */ function writeFile(path, text, isBase64, scb, ecb) { if (!ax.util.isValidPath(path)) { ecb(new Error('invalid file path:' + path)); return; } var pos = path.lastIndexOf('/'), folder = path.substring(0, pos), filename = path.substring(pos + 1, path.length); if (_DEBUG) { console.log(_module_name, 'writeFile', folder, filename); } var writeStream = function(stream){ if (isBase64) { stream.writeBase64(text.toString()); } else { if (_DEBUG) { console.log(_module_name, 'write text:', text); } stream.write(text.toString()); } stream.close(); if (scb) { scb(); } }; deviceapis.filesystem.resolve( function(dir){ dir.listFiles(function(files){ var i=0, len = files.length, f;
  300. 304 H3 개발자 컨퍼런스 2012 for(i=0; i<len; i++) { f

    = files[i]; if (f.name === filename) { f.openStream(writeStream, ecb, "w", "utf-8"); return; } } var newFile = dir.createFile(filename); newFile.openStream(writeStream, ecb, "w", "utf-8"); }, ecb); }, ecb, folder, 'rw' ); } 푸딩얼굴인식 3.0 앱 개발 후기. 기존의 많은 앱들이 네이티브 기반에서 필요에 의해 웹 기술이 한정적으로 이용한 반 면, 푸딩얼굴인식3.0 앱은 앱스프레소를 이용해 기본적인 기능을 모두 웹 기술을 이 용하고 네이티브 언어는 카메라 등의 확장된 기능을 구현하기 위한 플러그인 제작용 으로 이용되었다. 앱스프레소는 디바이스의 추가 기능 플러그인으로 구현 하는데, 잘 설계된 아키텍처 다음 네이티브 기능을 자바스크립트로 호출하는 인터페이스로 구성 된다. 즉, 특정 네 이티브 기능과 앱 기능 사이의 직접적 연결을 끊어 놓음으로써 웹 개발자는 앱의 기능 에, 네이티브 플러그인 기능 자체에만 집중할 수 있다. 웹 기술과 네이티브 기술이 절 묘하게 결합되어 생산성을 극대화 시킨 완벽한 협업 구조이다. 최소한의 비용으로 최대 효과를 낼 수 있는 하이브리드앱. 보다 많은 웹 개발자들이 앱 개발에 참여해 주길 바라며, 네이티브 개발자들도 멀티플 랫폼 앱에 도전해 주길 기대한다. 그리고 국내 최초의 하이브리드 앱 프레임워크인 앱 스프레소가 좀 더 많은 개발자들에게 도움이 되길, 해외에서도 빛이 나길 바란다.
  301. 305 꽃보다 Scala Before Started... 최근 Scala라는 언어에 대해서 들어본

    분이 많을 것이라 생각됩니다. Scala는 Ruby On Rails 처럼 수많은 관심을 이끌어 내며 화려하게 등장하지는 않았지만, 이미 Twitter, Foursquare, Tumblr 등의 잘나간다하는 소프트웨어 회사들에서 주 언어로 쓰이며 조용히 자신의 존재감을 널리 알리고 있습니다. Scala가 많은 대형 서비스에서 쓰이고 있다는 점은, Scala가 단순히 언어적 화려함이나 문법 설탕(syntactic sugar) 덩어리가 아니라, 그 만큼 강력하며 안정성 있는 언어라는 점을 보여줍니다. 이 글의 목적은 이렇게 요즘 뜨는 Scala라는 언어에 대한 소개와 몇몇 Scala framework들에 대한 소개를 통해 여러분의 지적 욕구를 자극하고 Scala를 널리 알려 여러분을 이롭게 하고자 하는데 있습니다. 꽃보다 Scala PMC팀 김상범 [email protected]
  302. 306 H3 개발자 컨퍼런스 2012 하지만, 익히 알려진데로 함수형 언어에

    익숙지 않고 하나의 언어 (특히 자바) 만을 사 용했던 개발자라면 Scala는 극악의 난이도로 다가올 수도 있습니다. Scala의 창시자 인 Martin Odersky가 저자로 참여한 “Programming in Scala 2nd Edition” 의 머리 말에 보면 이런 문구가 나옵니다. “Scala will challenge you. That’s part of the joy of using it. You won’t understand the full power of its type system by the end of your first day. You won’t understand the zen of objects being functions and functions being objects in your first week. …” 한마디로, Scala는 어렵습니다. 하고자 하는 바도 많고 할 수 있는 것이 많기 때문에 그만큼 유연하고 그만큼 복잡합니다. 그런것을 배워 나가는것 또한 개발자의 큰 즐거 움 아닐까 합니다 :) What is Scala? Scala는 Martin Odersky라는 독일인 컴퓨터 과학자에 의해 2001년에 시작되었으며 2003년에 첫 release가 이루어진, JVM과 .NET을 런타임으로 하는 프로그래밍 언어 입니다. Martin Odersky는 이전에는 Java의 Generic과 Sun의 java compiler를 위해 일했었다고 합니다. Scala라는 이름은 “Scalable Language” 의 약자라고 알려져 있습니다. “scalar” (수 또는 양, <-> vector) 나 “scholar” (학자, 학식이 있는 사람) 등의 단어를 떠오르는게 왠지 나중에 약자를 붙인 게 아닐까 의심이 들기도 합니다만, 이름은 중요하지 않습니 다. 이 Language가 어떤 놈이고 왜 써야하고 얼마나 훌륭한 놈인지가 오늘의 주제이 니까요. * 이하 모든 내용은 JVM을 기반으로 합니다. JVM 기반 언어 Scala는 Groovy나 Clojure 등의 언어처럼 JVM을 실행환경으로 하며, 컴파일러를 통 해 자바 바이트 코드로 컴파일 됩니다. 즉, “.scala” 파일을 컴파일 하면 “.class” 파일
  303. 307 꽃보다 Scala 이 나오며, 이후로는 자바와 동일하게 다뤄도 무방하며,

    Scala는 이를 통해 다음과 같 은 특징들을 가지게 됩니다. 모든 표준 JVM 위에서 구동 가능 Scala는 컴파일되면 “.class” 파일이 되며, 구동시에는 자바에서 컴파일된 class와 차 이가 없습니다. 따라서 모든 표준 JVM에서 구동가능하며, “.class” 파일이 만들어지 기 때문에, Dalvik 위에서도 구동 가능합니다. 수많은 자바 라이브러리 및 툴 사용 가능 Scala는 자바와 상호 운영성(interoperability)를 가집니다. 실행시에는 단순히 “.class” 파일 이기 때문에 아무런 문제 없이 수많은 오픈 소스 라이브러리를 자바와 마찬가지로 그대로 사용 할 수 있습니다. 성능 손실 없음 Scala 컴파일러는 성능 손실을 발생시키지 않습니다. 동일한 목적의 코드라면 Scala 를 사용했다고 해서 자바보다 성능이 떨어질 일은 없습니다. 또한, Scala가 가지는 많 은 강점들은 모두 Compile time에 이루어지며 reflection 등을 이용해 runtime에 이루 어 지지 않습니다. 앞으로 언급할 모든 강력한 Scala의 기능들은 컴파일 타임에 이루 어집니다. 모든것은 컴파일 타임에! 객체 지향 언어 (Object-oriented language) Scala는 객체 지향 언어입니다. 기본적으로 자바와 유사한 형태의 객체 지향을 지원 하지만, Scala는 자바보다 Smalltalk에 가까운 순수한 객체 지향 언어로 자바와는 다 음과 같은 점이 다릅니다.
  304. 308 H3 개발자 컨퍼런스 2012 No primitive type 자바와 달리,

    Scala는 모든 정수/실수 형태의 값 들 역시 객체로 표현되며, operator overloading을 통해 해당 객체에 대한 연산을 지원합니다. 예를 들자면 1+1 의 연산 은 1.+(1) 과 같으며 +는 Int 객체에 정의된 instance method입니다. Trait Scala는 trait이라는 형태의 container를 제공합니다. 기본적으로 자바의 Interface 와 유사하지만, Scala의 trait은 메소드에 대한 구현을 가질 수 있으며 변수 역시 가 질 수 있습니다. 또한, mix-in composition이라 불리는 다중 상속과 유사한 기능 을 제공하며, 부모 클래스에대한 구체적인 명시 없이 코딩을 할 수 있기 때문에 좀더 “pluggable” 한 코드를 작성 가능합니다. * Spring 이나 Guice 같은 별도의 엔진 없이도 DI가 가능합니다. (cake pattern) 함수형 언어 (Functional language) Scala는 함수형 언어(functional language)입니다. 동시에 객체 지향 언어이기 때문 에, 기존의 순수한 함수영 언어인 LISP 계열의 언어와는 조금 다른 표현법을 가지지 만, 기본적으로 함수형 언어의 기본적인 특성을 제공하고 있습니다. First class functions 함수형 언어에서 함수는 1, “a”와 같은 일반적인 값과 다르게 취급되지 않습니다. 함 수는 인자로 전달 될 수 있으며, 변수를 정의하듯 함수 안에서 함수를 정의 할 수 있 습니다. 이런 점을 통해 함수형 언어에서는 함수를 통해 좀 더 강력하고 표현력 있는 control flow를 만들어 낼 수 도 있습니다. Scala에서는 함수를 literal로 표현 할 수 있으며 이는 강력한 표현력을 제공해 줍니다. “callback” 함수를 정의하기 위해 필요도 없는 익명 객체를 정의하거나 listener type 을 별도로 정의할 필요도 없습니다. 함수 자체가 클래스와 동일한 최상위 개념이기 때 문이죠.
  305. 309 꽃보다 Scala Less side effects (Immutable data structure) 또다른

    함수형 언어의 가장 큰 특징은 side effect가 없어야 한다는 점입니다. 함수가 인자로 전달 받은 값 이외에 어떠한 상태 변경도 발생하지 않아야 한다는 것입니다. 즉, 전달 받은 값으로부터 연산 결과를 리턴하지만 이 과정에 어떠한 내부 상태도 변 경되어서는 안된다는 점입니다. 이미 자바에도 String 클래스의 구현이 그러한데, 기본적으로 모든 operation은 immutable 한 상태를 보장하기 때문에 모든 String class의 함수들은 새로운 값을 리 턴합니다. Scala는 기본적으로 immutable 값을 권장하며 때에 따라서는 변경 가능한 변수를 사 용 가능합니다. 즉, 때에 따라서는 명령형(imperative) 스타일로 변수를 사용할 수 있 으며, mutable한 상태를 가질 수 있다는 말입니다. 하지만, 이는 명령형 방식에 익숙 한 개발자들의 편의 및 특정 상황에서 imperative 스타일이 좀 더 명확할 수 있다는 점 에서 제공하는 것이지, 절대로 mutable 변수를 공개하거나 공유하는 것은 피하는 것 이 좋습니다. Why Scala? Scala가 어떤 언어인지 간단히 특징들을 살펴 보았지만, 이것만으로 왜 Scala를 써야 하는지는 충분치 않을 것입니다. 어떤 특징들이 많은 개발자및 소프트웨어 회사들이 Scala를 선택하게 했는지 설명과 코드를 통해 좀 더 살펴 보도록 하겠습니다. Scala is concise 짧은 코드가 항상 간결한 것은 아니지만, 간결한 코드는 짧습니다. 가끔 Scala에 대해 짧게 설명할 필요가 있는 경우, 이해를 돕기 위해 다음과 같은 비유를 들곤 합니다. “자바로 쓰여진 코드는 대서사시 같지만, Scala는 시와 같다” 간결함과 그를 통한 강력한 표현력은 Scala의 가장 큰 언어적 장점입니다. // this is Java class IndexedString { private int index;
  306. 310 H3 개발자 컨퍼런스 2012 private String string; public IndexedString(int

    index, String string) { this.index = index; this.string = string; } } // this is scala class IndexedString(index: Int, string: String) 위의 예제는 int 형값인 index와 string 값을 private 멤버로 가지는 IndexedString이 라는 동일한 클래스를 정의하는 자바와 Scala 코드입니다. * 세미콜론(;)은 생략 가능합니다. 자바 코드와 Scala 코드를 비교해보면, 기존에 아무렇지도 않게 열심히 반복하며 작 성하던 자바 코드가 얼마나 많은 중복을 가지고 있는지 알 수 있습니다. 클래스 이름 은 생성자에서 반복되며 멤버변수 역시 이에 값을 할당해주기 위한 생성자의 지역변 수로 반복되고 있습니다. 여기에 getter와 setter 함수를 추가하고자 한다면 얼마나 많 은 불필요한 반복이 발생할지 쉽게 예측 가능할 것입니다. 뒤에서 다시 언급하겠지만, Scala의 타입 선언 역시 간결한 방식을 택하고 있습니다. 자바의 타입 표현과 달리 Scala는 타입 추론(type inference) 기능을 가지고 있어 타 입 선언시에도 불필요한 반복을 할 필요가 전혀 없습니다. 간단히, “너도 알고 나도 아 는 것”은 언제나 생략 가능합니다. Scala is high-level 프로그램의 복잡도를 낮추기 위해서, 추상화를 통한 개념적인 코딩은 개발자에게 상 당히 중요한 부분입니다. 문자열의 경우, 말 그대로 문자의 열이기 때문에 String class는 Character 의 List로 바라볼 수 도 있어야 합니다. 하지만 다음 예에서 보이듯이 자바에서는 문자열을 다룰 때 문자열 그 자체로만 바라보고 절차적으로 코딩을 해야합니다. //this is java boolean hasUpperCase = false; for (int i = 0; i < string.length(); ++i) {
  307. 311 꽃보다 Scala if (Character.isUpperCase(string.charAt(i))) { hasUppperCase = true; break;

    } } 문자열을 문자열 그대로 문자 하나씩 방문하며 바깥쪽의 변수에 결과를 직접 저장하 며 (side-effect) 수행 후 종료하는 로직까지 직접 작성해야합니다. 이에 반해 Scala에서는, 문자열을 좀 더 고수준으로 character의 sequence로 바라 볼 수 있으며 어떤 캐스팅이나 명시적 변환 없이 collection library에 존재하는 함수를 그대로 사용가능합니다. val hasUpperCase = string.exists(_.isUpper) 위의 예제에서 보듯이, string이라는 문자열을 collection으로 바라보고 collection library에 정의된 exists 함수에 _.isUpper라는 명제(predicate)를 전달해 대문자가 존 재하는지 여부를 체크할 수 있습니다. String에는 exists 함수가 존재하지 않음에도 위 코드는 잘 컴파일이 되어 실행되며 각 문자열의 isUpper라는 함수를 호출하여 true/ false 여부를 체크합니다. 간단히 설명하자면, String을 Character의 Sequence로 바라 볼수 있다는 rule 이 정 의 되어 있으며 컴파일 타임에 이 규칙을 기반으로 컴파일러가 추론을 하여 적절한 타 입으로 변환하는 것입니다.(정확히는, StringOps라는 wrapper class로 둘러싸여집니 다.) 좀더 자세한 설명은 함수 literal 표현과 implicit conversion에서 설명하도록 하겠 습니다. Scala is statically typed 최근 인기 있는 언어들의 특징 중 하나는 대부분의 언어가 dynamic typed라는 점입 니다. 그럼에도 불구하고 가장 최신 언어중 하나인 Scala는 정적 타입 언어이며, 자바 와 같이 모든 타입은 명시되어야 하며, 컴파일 타임에 모든 타입 에러는 검증됩니다. 이에 더 나아가 Scala는 지금까지 언어중 가장 강력한 타입 제한을 하며, 여러 표현법 을 통해 타입에 대해 좀 더 자세히 명시할 수 있습니다. 물론 정적 타입이 언어의 장점이라는 부분은 상당한 논쟁을 불러 일으킬 수 있는 부분 이지만, 적어도 정적 언어가 refactoring 면이나, 함수의 인자나 객체의 property 등에
  308. 312 H3 개발자 컨퍼런스 2012 대한 unit test는 필요 없는

    점, 때로는 타입 자체가 문서화의 기능도 하고 있다는 점 등은 정적 타입언어의 강점이라고 할 수 있습니다. 기본적인 정적 타입 시스템외에 Scala가 가지고 있는 가장 큰 강점은 바로 타입 추론 입니다. 이를 통해 코드를 좀 더 간결하고 명료하게 만들 수 있습니다. (때로는 타입 문서화나 컴파일 타임 검증을 위해 일부로 명시하는 경우도 있습니다.) Type inference Scala에서 모든 타입은 변수나 함수 뒤에 “:”을 통해 명시하게 됩니다. 자바와 달리 뒤쪽에서 타입을 명시하는 데 이런 방식을 택하는 많은 언어들의 특징은 타입이 생략 가능하다는 점입니다. Scala 역시 타입을 생략 할 수 있지만, 모든 생략된 타입은 컴 파일 타임에 컴파일러에 의해 추론되어 바이트코드로 컴파일 되게 됩니다. // generic 타입 생략 val x:Map[Int, String] = new HashMap() //or val x = new HashMap[Int, String] val str = "aaaa" //리턴 타입 생략 def hasUpperCase(str: String) = str.exists(_.isUpper) 위의 예제처럼 간단한 경우부터 복잡한 함수 내부의 구현에서도 추론 가능하다면 대 부분 생략 가능합니다. Scala 설치 및 실행 Install Scala는 http://www.scala-lang.org/downloads에서 다운로드 가능하며 간단한 설 치 과정을 거친 후 $ scala
  309. 313 꽃보다 Scala 명령으로 바로 Scala Interpreter를 실행할 수 있으며,

    각 platform 별로 package manager 등을 이용해 설치 역시 가능합니다. 맥의 경우 Homebrew를 사용하고 있다 면, $ brew install scala 명령으로 바로 설치 가능합니다. 참고로, 모든 Scala 구성 요소는 자바로 구현되어 있는 jar 일 뿐입니다. 필요한 경우 런타임에서 컴파일러나 인터프리터 라이브리에도 접근 가능합니다. 현재(2012.09.10) Scala의 최신 release 버전은 2.9.2이며, 최신 개발 버전은 2.10.0-M7입니다. Compile Scala 의 경우 인터프리터를 제공 하며, 실제 개발 환경에서는 대부분의 경우 SBT(Simple Build Tool)를 이용하기 때문에 직접 컴파일을 할 일은 별로 없습니다. 직접 컴파일이 필요한 경우 다음과 같이 간단히 compile 가능합니다. $ scalac A.scala 기본적으로 package 구조에 맞춰 디렉토리를 생성하고 따로 설정값을 주지 않는 경 우, 현재 디렉토리를 기준으로 하여 class 파일을 저장합니다. Scala 컴파일러는 많은 일을하고 여러 jar를 로딩하기 때문에 상당히 느립니다. 좀 더 빠른 실행을 원할 경우 scalac 대신 compiler daemon을 사용하는 fsc (fast scala compiler) 명령을 사용하는 것이 좋습니다. fsc는 처음 실행시 컴파일러 데몬을 실행하고, 다음 실행부터는 이 데몬을 재사용하여 컴파일 속도를 크게 향상 시킵니다. 다음 예제에서 보이듯이, 두번째 컴파일부터는 매 우 빠른 속도롤 보여줍니다. $ fsc -verbose -d /tmp test.scala ... [Port number: 32834] [Starting new Scala compile server instance] [Classpath = ...]
  310. 314 H3 개발자 컨퍼런스 2012 [loaded directory path ... in

    692ms] ... [parsing test.scala] ... [total in 943ms] $ fsc -verbose -d /tmp test.scala ... [Port number: 32834] [parsing test.scala] \&... [total in 60ms] $ fsc -verbose -shutdown [Scala compile server exited] * 실행한 데몬은 -shutdown 명령으로 중단시킬 수 있습니다. Scala Interpreter Scala는 대부분의 최신 언어와 마찬가지로 Interpreter 또는 REPL(Read-Eval-Print Loop) 이라 불리는 콘솔을 통해 간단한 실행및 테스트가 가능합니다. $ scala scala> 1+1 res13: Int = 2 scala> res13 * 5 res14: Int = 10 scala> println(res14) 10 위의 예제처럼 간단한 연산을 바로 실행 가능하며, 자신의 코드 역시 바로 불러와 테 스트 가능합니다. (물론 자신의 클래스가 classpath 상에 존재해야 하며, import 하거나 full name을 명 시하여 사용 가능합니다.)
  311. 315 꽃보다 Scala Basics Defining variables Scala에는 “val”과 “var”라는 2가지

    타입의 변수가 존재합니다. 전자는 value를 의 미하며 말 그대로 값을 선언할 때 쓰이며, 선언 이후에는 변경 불가능 합니다. 후자 는 variable을 의미 하며 변경 가능한 변수를 의미합니다. val로 선언된 변수는 자바의 final 변수와 동일하기 때문에, 단지 참조가 변경 불가능한 것이며 해당 객체의 멤버 변수가 var로 선언되어 있다면, 당연히 변경 가능합니다. scala> val msg = "Hello, World!" msg: java.lang.String = Hello, World! scala> msg = "Welcome to Scala!" <console>:8: error: reassignment to val msg = "Welcome to Scala!" ^ 위와 같이 val로 선언된 값에 재할당을 할 경우 컴파일 에러가 발생합니다. Block Expression 하나의 표현으로 원하는 값을 나타낼 수 없을때 중괄호({})를 이용해 표현식을 묶을 수 있습니다. 묶여진 표현식의 값은 마지막 표현식이 되며, 중간에 어떤 코드가 들어있고 어떤 side effect가 발생했는지는 전혀 상관이 없습니다. 변수이던 함수 이던 함수의 인자이던 상관없이 block expression은 하나의 값을 나타냅니다. scala> val a= { |println(1) |println("a") | 5 | } 1 a a: Int = 5 scala> a res1: Int = 5
  312. 316 H3 개발자 컨퍼런스 2012 Defining functions 함수의 선언은 def

    keyword로 시작되며 함수 선언부와 구현 부는 “=”로 구분됩니다. 마치 수학의 f(x,y) = x +y와 마찬가지로 말입니다. scala> def f(x:Int, y:Int) = x + y f: (x: Int, y: Int)Int 수학에서 함수 표현과 다른 점은 def로 시작해야하며, 인자의 타입을 명시해야 한다는 점 뿐입니다. 위와 같이 선언된 함수는, scala> f(1,2) res0: Int = 3 이와 같이 사용 가능합니다. 가끔은 Console.println 처럼 “=” 이 사용되지 않고 선언된 함수들이 존재하는데, 이 는 리턴값이 Unit(void)인 경우에 해당 함수가 마치 procedure와 유사하게 보이도록 해주는 문법입니다. def printGreetings(name: String) { printf("Hello, %s", name) } * printf 함수 역시 존재합니다 :) 함수의 구현 부분이 한개의 표현식으로 쓸 수 없는 경우, 앞에서 언급한 block expression을 이용할 수 있으며, 당연히 리턴값은 묶여진 표현식의 마지막 값입니다. Define anonymous function Scala에서는 함수 literal 이라 불리는 표현법으로도 함수 선언이 가능합니다. scala> (x:Int) => x + 1 res0: Int => Int = <function1> 다음 결과로 나타난 expression은 다음과 같은 의미를 가집니다. “res0의 타입은 Int를 주면 Int를 반환하는 인자가 1개인 함수이다(function1)”
  313. 317 꽃보다 Scala 따라서 res0를 함수로 사용하여 다음과 같은 호출이

    가능합니다. scala> res0(3) res2: Int = 4 scala> res0() <console>:9: error: not enough arguments for method apply: (v1: Int)Int in trait Function1. Unspecified value parameter v1. res0() ^ 위 문법을 활용하여 다음과 같이 함수를 인자로 받는 함수에 inline으로 함수를 정의하 여 전달 가능합니다. scala> List(1,2,3,4).foreach(x=>println(x)) 1 2 3 4 또는 축약형으로 쓸 수 도 있습니다. scala> (1 to 10).filter(_ % 2 == 0) res9: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10) 1 부터 10까지의 수 중에서 짝수만을 filtering 하는 코드로, “_ % 2 == 0” 표현식은 “num => num % 2 == 0”의 축약형입니다. 밑줄, “_”는 함수의 인자가 들어갈 자리라는 뜻이며, 함수 인자가 순서대로 해당 자리 에 채워집니다. 참고로, List 관련 예제는 마치 dynamic typed language 처럼 보여지지만, 내부적으 로 다음과 같은 타입 추론 과정을 컴파일 타임에 거치게 됩니다. 1. List 함수는 인자로 전달된 4개의 값의 공통 타입을 추론 2. 멤버들의 타입은 Int로 결정되었으며 전달되는 함수의 인자 역시 Int 여야 함 3. 전달된 함수 x=>println(x)의 인자 x의 type이 명시되지 않았기 때문에 Int로 추론 4. 결과 : List[Int](1,2,3,4).foreach( (x:Int) => println(x))
  314. 318 H3 개발자 컨퍼런스 2012 scala> List(1,2,3,4).foreach((x:String)=>println(x)) <console>:8: error: type

    mismatch; found : String => Unit required: Int => ? List(1,2,3,4).foreach((x:String)=>println(x)) Type and Generics Scala의 generics는 자바와 달리 < > 대신 [ ]로 표현되며, 객체의 상속관계 등의 상/ 하 뿐만 아니라 해당 객체가 다른 객체로 변환될 수 있는지, 또는 바라볼 수 있는지 등 도 명시가 가능하며 모든 타입 선언은 컴파일타임에 검증 됩니다. Scala의 collection library에는 sum이라는 함수가 존재합니다. 말 그 대로 collection 안의 데이터를 더하는 함수 인데, 이런 함수가 generic을 기반으로 하는 collection에 있을 수 있는 이유는, 간단히 숫자가 아닌 값이 들어 있을 경우 compile 이 되지 않기 때문입니다. scala> List(1,2,3,4).sum res2: Int = 10 scala> List(1,2,3.0,4).sum res3: Double = 10.0 scala> List(1,"a",3).sum <console>:8: error: could not find implicitvalue for parameter num: Numeric[Any] List(1,"a",3).sum 위 예제 처럼 직접 List를 명시하지 않고 다른 함수로 부터 얻어온 List에 대해서는 어 떻게 Compile error를 발생시킬 수 있는지 의문을 제기할 수도 있습니다. 간단히 설 명하자면, 모든 함수는 리턴타입이 명시되어 있고 이를 이용해 판단할 수가 있습니다. 함수, 변수를 포함한 모든 표현식은 타입을 가지고 있는 값입니다. 심지어는 이런 표현도 가능합니다. scala> def getLength[T <: {def length(): Int}](obj: T): Int = obj.length getLength: [T <: AnyRef{def length(): Int}](obj: T)Int scala> println(getLength("aaaaa")); 5
  315. 319 꽃보다 Scala 타입 T는 length()라는 함수가 있는 클래스의 하위

    타입 (<:) 이어야 하며, 이런 표현을 통해 interface 선언 없이도 컴파일타임에 강력한 타입 체킹을 할 수 있습니다. 위의 getLength 함수 호출에서도 보여지지만, 대부분의 경우 type parameter는 값으 로 부터 추론 할 수 있기 때문에 생략 가능합니다. * Scala에서는 Array역시 함수 처럼 ( ) 사용합니다. ex) Array(1,2,3)(0)은 1을 리턴 Control flow Expression oriented Scala 대부분의 코드는 문장(statements)이 아닌 표현식(expressions)입니다. 명령 형 언어처럼 절차적으로 명령을 내리는 것이 아닌 모든 표현식은 값을 나타내며, 제어 문 조차 값을 나타냅니다. No break Scala에는 break 문이 없습니다. 대부분의 제어 구조는 함수를 chaining을 통해 이뤄 지며, map/reduce/filter/collect 등 LISP 등과 유사하게 List Processing을 통해 원 하는 흐름을 만들어냅니다. If / Else Scala의 if/else 문은 코드를 분기하기 위한 표현이 아니라 조건에 따라 값을 리턴하는 표현식입니다. scala> val a = "a" a: java.lang.String = a scala> val b = if(a == "a") "b" else "c" b: java.lang.String = b C 계열 언어의 ? 연산자와 비슷한 역할을 하지만, 함수 체이닝을 통해 제어 구조를 완 성 할 수 있습니다.
  316. 320 H3 개발자 컨퍼런스 2012 For Scala의 for 문은 자바와

    유사한 방식으로 사용되기도 하지만, 일반적으로는 if/else 와 마찬가지로 값을 얻어내기 위해서 사용되어지며 자바와 달리 다양한 조건및 여러 collection에 대해 한번에 iterating을 할 수 있는 기능을 제공합니다. scala> for(n <- 1 to 10) yield n.toString res3: scala.collection.immutable.IndexedSeq[java.lang.String] = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) scala> val a = 1 until 10 a: scala.collection.immutable.Range = Range(1, 2, 3, 4, 5, 6, 7, 8, 9) scala> val b = 1 to 10 b: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) scala> for{ | n1 <- a | n2 <- b if n2 % 2 == 0 | } yield (n1, n2) res5: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector((1,2), (1,4), (1,6), (1,8), (1,10), (2,2), (2,4), (2,6), (2,8), (2,10), (3,2), (3,4), (3,6), (3,8), (3,10), (4,2), (4,4), (4,6), (4,8), (4,10), (5,2), (5,4), (5,6), (5,8), (5,10), (6,2), (6,4), (6,6), (6,8), (6,10), (7,2), (7,4), (7,6), (7,8), (7,10), (8,2), (8,4), (8,6), (8,8), (8,10), (9,2), (9,4), (9,6), (9,8), (9,10)) yield 문을 이용하여 리턴된 값은 전체 iterating 후 적절한 collection에 담겨지며, 위 의 예제의 경우 Vector[Tuple[Int, Int]] 타입으로 리턴되었습니다. If/Else와 For 표현식 만을 가지고 제어 구조를 작성하기에는 부족한 것이 사실입니다. 나머지 부분은 Functional Combinators를 이용해 쉽게 chaining 가능하며 다른 챕터 를 통해 자세히 살펴 보겠습니다. Scala scripts Scala는 컴파일 방식의 언어이지만, 스크립트로서도 사용 가능하며 해당 스크립트는 class 나 main 함수 없이도 바로 작성 할 수 있으며, 전달 인자 역시 args라는 배열을 통해 바로 접근 가능합니다.
  317. 321 꽃보다 Scala <Args.scala> //java style in scala println("Java Style")

    var i = 0 while(i < args.length) { println(args(i)) i += 1 // no ++ operater in scala } println("Scala style") args.foreach(arg => println(arg)) //or println("Shorthand form, called a partially applied function") args.foreach(println) 실행결과 $ scala Args.scala a b c Java Style a b c Scala style a b c Shorthand form, called a partially applied function a b c 위 예제에서 첫 번째 방식은 자바 스타일로 var 변수를 사용해서 자바 코드를 그대로 옮겨온 것이며, 두번째와 세번째 방식은 좀 더 Scala 스러운 방식으로 작성한 예제입 니다. * args는 Array 타입으로 Scala에서는 Array 역시 함수이기 때문에 인덱스 값을 함수의 인자처럼 전달하여 해당 인덱스의 값을 얻어옵니다.
  318. 322 H3 개발자 컨퍼런스 2012 Object-oriented Class Scala의 클래스는 생성자와

    접근자를 제외하고는 자바와 거의 유사합니다. 접근자 (Access Modifier) Scala의 접근자는 자바에서의 불편함과 문제점을 해소하기 위해 다음과 같은 다양한 방법을 제공합니다. • public,protected, private은 inner class 등의 상황을 제외하고는 거의 동일합니다. • private[this]와 같은 방식으로 this 객체 내부로 접근 제한이 가능합니다. • private[package_name] 방식으로 package private을 지원합니다. • protected[package_name] 방식으로 package 접근 제한 역시 가능합니다. 생성자 첫번째 예제에서 보여졌듯이, Scala는 생성자와 클래스를 동시에 선언합니다. 만약 추가 생성자가 필요하다면, this keyword를 이용해 가능합니다. class Rational(n: Int, d: Int) { require(d != 0) //if failed, IllegalArgumentException will be raised val numer: Int = n val denom: Int = d def this(n: Int) = this(n, 1) // auxiliary constructor override def toString = numer +"/"+ denom def add(that: Rational): Rational = new Rational( numer * that.denom + that.numer * denom, denom * that.denom ) }
  319. 323 꽃보다 Scala Object Scala에는 static class나 member가 존재하지 않습니다.

    대신에, singleton object를 지원하며, object 키워드를 통해 선언 합니다. 자바의 static과 유사하지만, type으로 쓰일 수 없으며 대부분의 경우 val 멤버 변수만을 사용하기 때문에 동시성 문제도 없으 며, static 클래스의 초기화 문제도 없습니다. 자바의 singleton object 생성 코드입니다. class Singleton{ private static Singleton instance; public void greeting(String name) { System.out.println("Hello, " + name); } private Singleton() {} //prevent constructing from outside public static Singleton getInstance(){ if (instance == null) { synchronized(Singleton.class) { //1 if (instance == null) //2 instance = new Singleton(); //3 } } return instance; } } Thread-safe 하게 만들기 위해서 double checked locking 패턴이 이용되었으며 생 성자를 private으로 만들어 외부에서의 생성을 막습니다. * J2SE 5.0 이후에서는 volatile을 이용해야합니다. 동일한 역할의 Scala 코드입니다. object Singleton { def greeting(name: String) { println("Hello, " + name) } }
  320. 324 H3 개발자 컨퍼런스 2012 훨씬 간결하며, 복잡한 생성 과정에서의

    동시성 문제도 전혀 없습니다. 타입이 아니기 때문에 생성 역시 불가능하며 사용시에는 그냥 객체 이름을 그대로 접근합니다. scala> object Singleton{ | def greeting(name: String) {printf("Hello, %s", name)} | } defined module Singleton scala> Singleton.greeting("wangtao") Hello, wangtao 또한, companion object라 불리는 class와 동일한 이름의 object를 선언하여 factory 용도로 사용하기도 합니다. 일반적으로 여러 생성자를 만들기보다는 이런 형태의 Factory pattern 이 선호 됩니다. //in Rational.scala class Rational(n: Int, d: Int) { require(d != 0) val numer: Int = n val denom: Int = d override def toString = numer +"/"+ denom def add(that: Rational): Rational = new Rational( numer * that.denom + that.numer * denom, denom * that.denom ) } object Rational { def apply(n: Int, d: Int) = new Rational(n, d) def apply(n: Int) = new Rational(n, 1) } appy 함수는 해당 객체를 마치 함수처럼 다룰 수 있게 해주는 syntactic sugar입니다. 다음과 같이 마치 함수를 부르듯 new 키워드 없이 Rational 객체를 생성하고 사용할 수 있습니다.
  321. 325 꽃보다 Scala scala> println(Rational(2,3)) 2/3 Trait Scala에는 interface나 abstract

    class 없으며, trait 이 그 역할을 대체합니다. trait 특 질, 특성이라는 의미를 가지는데, 말 그대로 어떤 class의 부모의 역할을 하기보다는 원하는 특성을 부여하여 기능을 확장시키는 개념으로 이해할 수 있습니다. OOP의 상속 개념에 대해서 설명할 때 자주 예로 드는 것이 자동차와 같이 쉽게 분류 가능한 예를 들곤 합니다. 명확한 부모 클래스와 구체적인 자식 클래스로 나뉠 수 있 기 때문이죠. 하지만 좀 더 정확히 현실세계를 모델링 하고자 한다면, 다중 상속 개념 이 필요 할 수 밖에 없게 되지만 다중 상속의 문제는 너무나 잘 알려져 있고 이를 피하 기 위해 많은 프로그래밍 언어들이 선택하는 방법은 바로 mixin입니다. Scala 역시 trait을 이용해 mixin을 지원하며 클래스 선언시 with 키워드를 이용해 해 당 클래스에 원하는 특성을 부여하게 되며, 이런 방식을 통해 코드를 조각 조각 작게 쪼개어 구현할 수 있게 되고 이를 조립하여 원하는 기능의 객체를 만들어 낼 수 있습 니다. 바로 Lego style이라 종종 불리는 방식이죠. abstract class Person { def schedule:Schedule } trait Student extends Person { private var classSchedule:Schedule = ... override def schedule = classSchedule def learn() = {...} } trait Worker extends Person { private var workSchedule:Schedule = ... override def schedule = workSchedule def work() = {...} }
  322. 326 H3 개발자 컨퍼런스 2012 class CollegeStudent(school:School, company:Company) extends Student

    with Worker { // ... } 출처: http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-5 다음 링크의 좀 더 멋진 예제들 역시 살펴 보시기 바랍니다. • http://joelabrahamsson.com/entry/learning-scala-traits • http://gleichmann.wordpress.com/2009/10/21/scala-in-practice-composing-traits-lego-style/ • http://www.ibm.com/developerworks/java/library/j-scala04298/index.html Package package 선언 역시 자바에 비해 유연하며, 다양한 방식을 지원합니다. 다음처럼 자바 스타일이 가장 일반적이며, package com.kthcorp class A 또는 다음처럼 다양한 방법으로 표현 가능합니다. package com.kthcorp class A //or package com.kthcorp { class A } //or package com { package kthcorp { class A } }
  323. 327 꽃보다 Scala //or package com package kthcorp class A

    class 선언 후에도 하위 package 선언 역시 가능하며, 어떤 형식으로 작성 하던 대부 분의 경우 문제 없이 컴파일이 됩니다. 참고로, 디렉토리 구조및 파일명을 강제하는 자바와 달리 Scala는 하나의 코드에 여 러 클래스를 선언하기도 하며, 디렉토리 구조 역시 소스코드의 경우 지키지 않아도 무 방합니다. 컴파일러가 결과물인 class 파일을 적절한 디렉토리에 저장해줄 것이기 때 문이죠. 다시 한번 강조하지만, 모든 것은 컴파일 타임에 이루어집니다 :) Imports Scala의 import 문 역시 자바의 그것에 비해 매우 유연하고 강력하며, 다음과 같은 특 징을 가지고 있습니다. • 어느 장소에서나 import가 가능하며, 변수의 scope와 동일한 유효 범위를 가집니다. • aliasing이 가능합니다. • object(singleton 객체)나 package 자체 import가 가능합니다. • “*” 대신 “_”를 사용합니다. scala> :paste // Entering paste mode (ctrl-D to finish) object Singleton { def greeting(name: String) { import java.util.{Date => UtilDate} printf("Hello, %s at %s", name, new UtilDate()) } } ^D // Exiting paste mode, now interpreting. defined module Singleton
  324. 328 H3 개발자 컨퍼런스 2012 scala> import Singleton._ import Singleton._

    scala> greeting("wangtao") Hello, wangtao at Tue Sep 11 14:24:54 KST 2012 Implicit Conversion 대부분의 실제 데이터는 하나의 타입 만으로 모델링 하는 것은 쉽지 않습니다. 개념적 으로는 email 같은 경우 문자열로 표현 할 수도 있지만, Email 같은 객체에 담고 언제 든지 문자열로써 사용할 수 있는 것이 더 정확하고 편리할 것입니다. 하지만, 과도한 타입과 객체들은 개발자를 피곤하게 합니다. Type hierarchy를 잘 설계해야 하며, 각 type에 대한 적절한 함수 역시 각각 선언하거나 호출 전에 적절히 변환해야 합니 다. 가장 많이 쓰이는 간단한 숫자 하나에도 타입 문제는 골치거리 중 하나입니다. Int, Double 등 많은 상황에 맞는 효율적인 타입을 쓰는 것은 프로그래밍 언어에서는 당연 한 것이긴 하지만, 각 타입별로 함수를 별도로 작성을 해야 하거나 명시적으로 변환하 는 함수들을 만들어줘야 하니까요. Dynamic 타입 언어들은 이런 문제를 암묵적인 자 동 변환으로 해결합니다. 하지만, 이런 방식은 매우 편리하기도 하지만 디버깅 하기도 쉽지 않은 예상치 못한 문제를 발생시키곤 합니다. Scala는 이에 대한 해결책으로 하나의 데이터를 여러 데이터로 바라볼 수 있게 (Viewable) 해주는 Implicit conversion이라는 기능을 제공합니다. 많이 쓰이는 기본 적인 숫자간의 변환같은 것을 제외하고는 명시적으로 선언을 해야만 작동하며 변환 룰을 import 해야만 하기때문에 scope 역시 변수와 마찬가지로 해당 block 안에서만 유효합니다. 엄격한 언어답게 기본적으로 Int는 Double로 자동 변환 되지만, Double은 Int로 자동 변환 되지 않습니다. scala> def printInt(n: Int) { println(n)} printInt: (n: Int)Unit scala> printInt(3.0) <console>:9: error: type mismatch; found : Double(3.0) required: Int
  325. 329 꽃보다 Scala printInt(3.0) ^ scala> def printDouble(n:Double) {println(n)} printDouble:

    (n: Double)Unit scala> printDouble(3) 3.0 이는 자동 import 되는 scala.Predef object에 해당 변환 룰이 선언되어 있지 않기 때 문입니다. 오직 Int를 Double로 변환하는 룰만 존재하는 것이죠. 다음은 Predef 객체 일부분인데, 보시다시피 Int는 Long, Double, Float로 변환 가능하지만 반대의 경우 는 정의가 없습니다. object Predef extends LowPriorityImplicits { implicit def int2long(x: Int): Long = x.toLong implicit def int2float(x: Int): Float = x.toFloat implicit def int2double(x: Int): Double = x.toDouble } 변환룰은 함수로 정의하며, implicit 키워드를 사용하며 인자의 타입과 리턴타입을 이 용해 적용 여부를 검사합니다. 또한, 컴파일 타임에 해당 함수가 현재 scope 안에서 직접 보여야 합니다. 즉, 함수가 같은 scope 내에서 먼저 선언되거나 함수 자체가 직 접 import 되어야 합니다. 자신이 직접 implicit를 선언한 경우 범위안에서는 당연히 컴파일 타임에 변환 함수 를 호출하는 로직이 끼워질 것이고, 해당 변환이 필요한 경우 변환 함수를 다른 곳에 서 import를 하면 됩니다. 실제 사용 예를 살펴보면 많은 경우 여러 implicit를 하나의 Implicits라는 객체에 모아두곤 합니다. 참고로, 해당 객체가 변환 가능한 객체의 함수도 직접 사용이 가능합니다. Int는 Double로 바라 볼 수 있기 때문에 Double의 모든 함수를 직접 호출 할 수 있으며, 이 는 compile time에 conversion을 발생시킵니다. 또한, 다음처럼 “implicit” 키워드는 함수의 인자에도 사용할 수 있습니다. 자동으로 해당 scope 내의 같은 타입의 implicit로 선언된 변수가 함수 인자로 지정되며, 이는 마치 injection 유사한 개념으로 사용할 수도 있습니다.
  326. 330 H3 개발자 컨퍼런스 2012 scala> implicit val somethingYouKnowAndIKnow: String

    = "Java sucks!" somethingYouKnowAndIKnow: String = Java sucks! scala> def sayTheTruth(implicit truth: String){println(truth)} sayTheTruth: (implicit truth: String)Unit scala> sayTheTruth Java sucks! Scala에서 제공되는 대부분의 conversion은 변환 자체가 가벼우며 손실이 발생하지 않는 것들만 제공되며, 필요한 경우 직접 작성해야 합니다. 단, 자신이 직접 변환룰을 작성할 때는 정확히 이해하고 사용해야하며, 모든 것은 여러분이 구현한 코드에 달려 있습니다. 한마디로, Int를 String으로 변환하거나 String을 Int로 변환하는 룰을 추 가하지는 마십시요 :) * 아이러니 하게도 implicit를 explicit 하게 선언해야 합니다. Type hierarchy
  327. 331 꽃보다 Scala 그림에서 보이듯이, Scala의 최상위 class는 Any이며 값을

    나타내는 AnyVal, 참조를 나타내는 AnyRef가 그 뒤를 잇습니다. Nothing은 bottom type 이라 불리며 모든 타 입의 하위이며, Null은 모든 참조 타입의 최하위 타입입니다. Functional / Collection List, Set, Map, Tuple Scala의 collection library에 존재하는 List, Set, Map 등의 자료 구조 클래스는 대부 분 abstract이며, 객체를 얻기 위해서는 별도의 표현법을 사용하거나 factory object 를 이용해야합니다. scala> val hostPort = ("localhost", 80) hostPort: (String, Int) = (localhost, 80) scala> 1 -> 2 res0: (Int, Int) = (1,2) scala> Map(1->"a", 2->"c") res4: scala.collection.immutable.Map[Int,java.lang.String] = Map(1 -> a, 2 -> c) scala> Set(1,2,3) res5: scala.collection.immutable.Set[Int] = Set(1, 2, 3) scala> Set.apply(1,2,3) res8: scala.collection.immutable.Set[Int] = Set(1, 2, 3) scala> Array("a",1,2) res6: Array[Any] = Array(a, 1, 2) scala> 2 :: 1 :: "bar" :: "foo" :: Nil res14: List[Any] = List(2, 1, bar, foo) scala> Set(Map(1->"a"), Array(3,4), List("a","b",10)) res7: scala.collection.immutable.Set[java.lang.Object] = Set(Map(1 -> a), Ar- ray(3, 4), List(a, b, 10)) scala> List(1,2,3).getClass res13: java.lang.Class[_ <: List[Int]] = class scala.collection.immutable.$- colon$colon
  328. 332 H3 개발자 컨퍼런스 2012 Tuple의 경우 별도의 객체 없이

    ()로 둘러싸서 표현하며, 별도의 class 선언 없이 논리 적으로 연관된 값들을 묶어서 리턴하거나 전달하기 위해서 사용됩니다. Option Option은 일종의 container로, 어떤 값을 가지고 있거나 가지고 있지 않은 상태를 표 현 하기 위해 쓰입니다. * Haksell 이란 언어의 Maybe 타입에 영향을 받은 것으로 알려져 있습니다. Option은 추상 클래스와 유사한, trait으로 선언되어 있으며 다음과 같은 형식을 지닙 니다. trait Option[T] { def isDefined: Boolean def get: T def getOrElse(t: T): T } 보다시피 아주 간단한 container 역할을 하는 추상 클래스로, Some[T]와 None을 concrete child class로 가지고 있습니다. 자바나 C 계열 언어들의 함수는 값을 찾을 수 없는 경우 -1 또는 null을 리턴합니다. 이런 함수 들의 문제점은 -1 이나 null 같은 값의 해석이 documentation에 의존해야 하며, -1이나 null 자체가 의미 있는 값일 경우 해결이 불가능해집니다. Scala에서는 이 문제 해결을 위해 Option 타입을 제공하며, 존재하는 값을 의미하는 Some과 존재 하지 않는 값을 의미하는 None 두가지로 표현을 하는 것입니다. 간단히 기존 언어의 -1, null 리턴하는 경우라면 None을 나머지 경우 Some을 리턴하면 된다는 말입니다. Some을 생성할 경우 실제 값을 전달해야하며, None은 singleton object로 그 자체 가 값입니다. scala> Option(3) res10: Option[Int] = Some(3) scala> Option(null) res11: Option[Null] = None
  329. 333 꽃보다 Scala scala> Some(null) res12: Some[Null] = Some(null) scala>

    Option(-1) res13: Option[Int] = Some(-1) scala> None res14: None.type = None scala> val optionalInt: Option[Int] = None optionalInt: Option[Int] = None scala> val optionalInt2: Option[Int] = Some(3) optionalInt2: Option[Int] = Some(3) Map.get 함수는 Option을 리턴 타입으로 가집니다. Map 자체에 그 값이 있을 수도 있고 없을 수 도 있기 때문입니다. scala> val numbers = Map(1 -> "one", 2 -> "two") numbers: scala.collection.immutable.Map[Int,java.lang.String] = Map(1 -> one, 2 -> two) scala> numbers.get(2) res0: Option[java.lang.String] = Some(two) scala> val n = if(res0.isDefined) res0.get else "not exists!" n: java.lang.String = two scala> numbers.get(3) res1: Option[java.lang.String] = None scala> res1.getOrElse("Not defined") res2: java.lang.String = Not defined 리턴 받은 Option 객체에서 값을 꺼내기 위해서는 위의 Option trait의 정의에 있는 isDefined와 get을 쓰거나 getOrElse를 이용하면 됩니다. 하지만, 좀 더 일반적인 방 법은 사이즈가 1인 collection, 즉 monad로 Option을 바라보는 방식입니다. Monad 부분에서 자세한 설명을 하도록 하겠습니다.
  330. 334 H3 개발자 컨퍼런스 2012 Functional Combinators foreach side effects를

    발생시키기 위한 용도로만 사용합니다. 리턴값이 값이 없다는 의미의 Unit을 리턴하기 때문에 리턴값은 의미가 없으며, 대부분의 경우 block expression 중간에 잠시 사용되거나 더 이상 값을 리턴할 필요가 없는 부분에서 사용할 수 있습 니다. val numbers = 1 to 100 val sum = { var temp = 0; numbers.foreach(n => temp += n) temp } println(sum) //물론 테스트 코드가 아닌, 실 환경에서는... //println(numbers.sum) map / reduce map은 함수형 언어에서 가장 널리 쓰이는 함수로, 각각의 멤버를 방문하며 전달 받 은 함수를 수행 하여 얻은 결과를 동일한 collection에 저장하는 함수입니다. 이에 반해, reduce는 해당 데이터의 개수를 하나로 합치기 위한 함수로 앞 연산의 결 과가 다음 연산으로 전달되며 눈뭉치 처럼 점점 커져가는 방식으로 작동합니다. scala> (1 to 10).map(_*2).map(_.toString).reduce(_ + _) res16: java.lang.String = 2468101214161820 위 과정은 다음과 같이 설명할 수 있습니다. • 1에서 10까지의 collection 생성 (1 to 10) • 1에서 10까지 방문하며 각 숫자 * 2 실행 ( _ * 2) • 2,4,6,8, …, 20 까지 저장된 10개의 멤버를 모두 문자열로 변경 (_.toString) • 첫 두개의 문자열을 합하고 그 결과를 3번째 문자열과 합하고 마지막 멤버까지 합하기 (_ + _) 이처럼 대부분의 경우 특별한 제어문 없이도 데이터 프로세싱이 가능하며 원하는 결 과를 한줄의 function chaining으로 만들어 낼 수 있습니다.
  331. 335 꽃보다 Scala 그외의 functional combinators map/reduce 외에도 filter /

    zip / partition / find / drop / dropWhile / foldLeft / foldRight / flatten / flatMap 등의 다양한 함수들이 제공되며 각 함수를 이해하고 적 재적소 잘 활용하고 뒤에 나올 pattern matching 까지 사용하면 필요한 모든 제어구 조를 표현 할 수 있습니다. Monad Scala 문서를 보다보면 monad (단세포 생물 등), monadic 등의 표현이 자주 나오는 데, 간단히 collection 처럼 다룰 수 있는 사이즈가 1인 대상으로 이해하면 됩니다. 대표적으로 Option 객체가 monad이며 option 객체에는 collection 객체들과 동일한 map/foreach 등의 함수가 존재합니다. 만약 Option 객체가 None, 즉 사이즈가 0인 collection이라면, 인자로 전달된 함수들은 실행 되지 않을 것입니다. scala> :paste // Entering paste mode (ctrl-D to finish) val idToName = Map( 1->"wangtao", 2->"tao.kim", 3->"sangbeom.kim", 4->"sb.kim" ) (1 to 10).foreach(id => idToName.get(id).foreach( name => println("Hello, "+ name) ) ) ^D // Exiting paste mode, now interpreting. Hello, wangtao Hello, tao.kim Hello, sangbeom.kim Hello, sb.kim
  332. 336 H3 개발자 컨퍼런스 2012 테스트를 위해 1부터 10까지의 숫자가

    담긴 collection을 만든 후 해당 숫자 값들을 idToName Map을 통해 이름으로 변경하는 코드입니다. Map.get 함수가 리턴한 Option을 마치 List 처럼 foreach 함수를 사용하여 담고 있는 값에 접근하고 있으며, 이는 Option 객체를 마치 리스트등의 데이터 구조처럼 다룰 수 있다는 말입니다. 이런 방식의 접근은 데이터를 꺼내와서 값이 있는지 없는지 확인하고 코드를 분기하 기 보다는, 값이 있을때 해당 함수가 실행하게 되는 전형적인 functional style로 코드 를 작성하게 해줍니다. 실제로도 Option 객체는 List로 변환 가능하며 Some의 경우 사이즈가 1인 List로 None의 경우 Nil (empty List)로 변환됩니다. Option 외에도 기타 프레임웍들이 사용하는 Future 등의 객체도 monad로 다룰 수 있 도록 API가 설계되어 있습니다. Pattern matching Scala의 가장 강력하며 유용한 기능 중에 하나인 pattern matching은 간단히 switch case와 유사한 case by case 형태의 코드를 작성할 때 매우 유용하며, 다양한 표현법 을 이용해 matching 조건을 선언할 수 있습니다. Matching on values 값을 matching 하는 경우는 switch case와 별반 다를 바 없습니다. val times = 1 times match { case 1 => "one" case 2 => "two" case _ => "some other number" } Matching with guards 조건식을 추가하여 matching 할 수 도 있습니다. times match { case i if i == 1 => "one" case i if i == 2 => "two" case _ => "some other number" }
  333. 337 꽃보다 Scala Matching on type 값에 따른 분기 뿐

    아니라 타입에 의한 분기 역시 가능합니다. def bigger(o: Any): Any = { o match { case i: Int if i < 0 => i - 1 case i: Int => i + 1 case d: Double if d < 0.0 => d - 0.1 case d: Double => d + 0.1 case text: String => text + "s" } } Matching on class members 객체의 멤버 변수 역시 조건식에서 바로 접근이 가능합니다. def calcType(calc: Calculator) = calc match { case calc.brand == "hp" && calc.model == "20B" => "financial" case calc.brand == "hp" && calc.model == "48G" => "scientific" case calc.brand == "hp" && calc.model == "30B" => "business" case _ => "unknown" } 사실 들여쓰기가 조금 더 깔끔해 보일 뿐 더 if / else를 쓴 것과 별차이가 없습니다. 이 런 경우에는 바로 다음에 설명할 case class라는 방식을 이용하는 것이 훨씬 코드를 간결하게 만들 수 있습니다. Case Classes case class는 pattern matching을 지원해주는 class 형태로 일반적으로 자바에서 value object 나 model 이라 불리는 객체들을 주로 case class로 선언하게 됩니다. case class로 선언된 class는 자동으로 factory 함수가 제공되며, equality와 toString 등의 기능 역시 제공됩니다. scala> case class Calculator(brand: String, model: String) defined class Calculator scala> val hp20b = Calculator("hp", "20b") hp20b: Calculator = Calculator(hp,20b)
  334. 338 H3 개발자 컨퍼런스 2012 scala> val hp20B = Calculator("hp",

    "20b") hp20B: Calculator = Calculator(hp,20b) scala> hp20b == hp20B res39: Boolean = true 하지만, case class의 강력함은 생성의 편리함이나 toString, equality 등에 있지 않습 니다. 바로 다음 예제와 같은 pattern matching입니다. def calcType(calc: Calculator) = calc match { case Calculator("hp", "20B") => "financial" case Calculator("hp", "48G") => "scientific" case Calculator("hp", "30B") => "business" case Calculator(ourBrand, ourModel) => "Calculator: %s %s is of unknown type".format(ourBrand, ourModel) } class를 생성하는 함수를 그대로 조건식의 표현으로 사용하여 matching 이 가능합니 다. 이때 생성함수의 인자에 임의의 변수 이름을 지정하여 해당 값을 추출하여 사용할 수 있습니다. 위의 예에서는 마지막 case의 ourBrand와 ourModel 변수를 타입 등의 거추장스러운 표현 없이 바로 매칭되는 값에 할당하여 사용할 수 있습니다. Extracting pattern 이런 pattern matching 이용해 편하고 깔끔하게 변수 선언을 하는 방법이 있습니다. scala> def getLocation = (math.random, math.random) getLocation: (Double, Double) scala> val myLoc = getLocation myLoc: (Double, Double) = (0.24252881689068828,0.17982331409379104) scala> myLoc._1 res3: Double = 0.24252881689068828 scala> myLoc._2 res4: Double = 0.17982331409379104 scala> val (x, y) = getLocation x: Double = 0.6297894678697743 y: Double = 0.799919442582773 scala> x res5: Double = 0.6297894678697743
  335. 339 꽃보다 Scala scala> y res6: Double = 0.799919442582773 예제에서

    보이듯이 리턴된 tuple을 하나의 값으로 받아 각각 쓰기보다는, 한번에 각 멤버를 extract 할 수 있다는 말입니다. val (x, y) 표현은 오른쪽에 있는 표현이 tuple 이기 때문에 성립되며, 이런 방식은 List 나 case class 등에 적용 할 수 있습니다. scala> val List(a,b) = List(1,2) a: Int = 1 b: Int = 2 scala> val Calculator(brand, model) = Calculator("myBrand","myModel") brand: String = myBrand model: String = myModel scala> brand res7: String = myBrand scala> model res8: String = myModel Tools & Frameworks 구슬이 서말이어도 꿰어야 보배라는 말이 있듯이, 아무리 언어가 뛰어나고 훌륭해도 잘 꿰어진 보배가 없다면 별로 쓸모도 없는 언어가 되 버릴 것입니다. 오늘날의 소프 트웨어의 규모와 개발 방식을 보면 툴과 프레임웍 같은 도구들 없이는 개발이 힘든 것 이 사실입니다. 또한, 최근 추세를 보더라도 언어 자체를 배우는 경우보다는, 특정 프 레임웍을 사용하기 위해 언어를 배우는 경우가 더 많아 보입니다. 스칼라는 출시된지 얼마 안된 언어임에도 불구하고, 이미 다방면에서 널리 쓰이고 있 으며 다양한 오픈소스 Tool들과 Framework들이 존재 합니다. 어떤 프레임웍들이 널리 쓰이고 있고 어떤 유용한 것들이 있는지, 또한 이 언어가 배울 가치가 있고 현업 에서 쓸모가 있는지 확인 하실 수 있도록 빠르게 살펴보도록 하겠습니다. 참고 https://wiki.scala-lang.org/display/SW/Tools+and+Libraries#ToolsandLibraries- DevelopmentTools
  336. 340 H3 개발자 컨퍼런스 2012 IDE Support Eclipse와 IntelliJ IDEA

    모두 Scala 지원 합니다. 하지만, 빌드툴인 SBT에 대한 지원 이 Maven 만큼 강력하지는 않습니다. 대부분의 경우 SBT 프로젝트에서 IDE 프로젝 트를 generate 하는 방식으로, 빌드 파일이 변경될때 마다 IDE 프로젝트 파일들을 다 시 만들어줘야 하는 불편함이 있습니다. Eclipse http://scala-ide.org/ IntelliJ IDEA http://confluence.jetbrains.net/display/SCA/Scala+Plugin+for+IntelliJ+IDEA Emacs https://github.com/RayRacine/scamacs http://www.scala-lang.org/node/354 https://github.com/aemoncannon/ensime Netbeans http://java.net/projects/nbscala SBT (Simple Build Tool) 대부분의 Scala 프로젝트는 SBT라는 툴을 이용해 project를 관리합니다. SBT는 Maven 등과 유사한 툴로서 build definition을 정의하기 위해 코드와 유사한 DSL (Domain Specific Language)를 제공하며, 필요한 경우(사실 대부분의 경우) scala 코드를 직접 작성하여 프로젝트의 메타를 정의할 수 있습니다. 라이브러리 의존성 관리를 위해 Ant에서 사용하는 Apache Ivy를 사용하며 대부분의 경우 Maven과 호환성을 가집니다. * 사실, Scala의 가장 큰 진입 장벽 중 하나가 SBT입니다. 너무 유연하고 자유롭게 사용 할 수 있다보 니, 어떻게 배우고 써먹어야 할 지 상당히 난감할 수 있습니다. 기본적인 문서를 읽어 보셨다면, 다음에 소개하는 여러 프로젝트들의 SBT 스크립트를 살펴 보시기 바랍니다.
  337. 341 꽃보다 Scala 참고 https://github.com/harrah/xsbt http://twitter.github.com/scala_school/sbt.html ScalaTest Scala Test Framework으로

    자신에 익숙한 테스트 방식을 선택할 수 있도록 다양한 test suite를 제공하며 기본적으로는 BDD(Behavior-driven Development) 기반의 test framework입니다. 다음은 scalatest.org의 첫 페이지의 소개 예제입니다. import collection.mutable.Stack import org.scalatest._ class StackSpec extends FlatSpec with ShouldMatchers { "A Stack" should "pop values in last-in-first-out order" in { val stack = new Stack[Int] stack.push(1) stack.push(2) stack.pop() should equal (2) stack.pop() should equal (1) } it should "throw NoSuchElementException if an empty stack is popped" in { val emptyStack = new Stack[String] evaluating { emptyStack.pop() } should produce [NoSuchElementException] } } 참고 http://www.scalatest.org/ http://en.wikipedia.org/wiki/Behavior-driven_development
  338. 342 H3 개발자 컨퍼런스 2012 Finagle 최근 Scala 진영에서 가장

    왕성한 오픈 소스 활동을 하고 있는 회사는 다름 아닌 Twitter 일 것입니다. Finagle 역시 트위터에 의해 만들어졌으며, 한마디로 말하자면 분산 비동기 RPC 네트웍 스택입니다. JVM 기반의 클라이언트와 서버 모두 제공 되며 대표적인 주요 기능은 다음과 같습 니다. • HTTP/Thrift 등 다양한 통신 프로토콜 제공 • Apache Zookeeper를 이용한 Service Registration/Discovery • Load balancing / Failover 등 수많은 기능을 보유 하고 있지만, 간단히 말하면 원하는 프로토콜로 RPC 통신을 할 수 있도록 Transport layer에 대한 제반 사항을 Framework 이 제공해 주는 것이며, 개발자는 자신의 로직을 protocol과 상관없이 독립적으로 구현 하면 됩니다. 현재 트 위터 내부적으로 많은 구현들이 Finagle 위에 올려져 있는 것으로 알려져 있습니다. <Twitter Service Stack with Finagle> 참고 http://twitter.github.com/finagle/ https://github.com/twitter/finagle http://engineering.twitter.com/2011/08/finagle-protocol-agnostic-rpc-system. html
  339. 343 꽃보다 Scala Gizzard Gizzard 역시 Twitter가 공개한 오픈 소스

    프로젝트로, backend datastore (SQL, Lucene 등)와 Web application 사이를 잇는 데이터 분산을 위한 middleware입니다. 최근 화두로 떠오르고 있는 빅데이터라는 말 자체의 근원중 하나인 트위터가 자 신들의 datastore에 사용하던 데이터 분산 로직(sharding or partitioning)을 별도 의 Framework으로 분리한 프로젝트로 데이터 분산을 데이터 베이스 자체가 아닌 middleware로 처리하는 Framework입니다.
  340. 344 H3 개발자 컨퍼런스 2012 참고 https://github.com/twitter/gizzard Akka Actor model

    이란 concurrent distributed system을 만들어 내기 위한 수학적인 추 상화 모델로, Erikson이 Erlang이라는 언어를 이용해 telecom system을 성공적으로 만들면서 널리 알려 졌습니다. Akka framework은 Actor model의 Scala 구현입니다. 임의의 역할 담당하는 Actor 들은 서로 우편을 주고 받듯이 메시지를 주고 받으며 각자 할일을 나누어 동시에 진행 하는 event-driven framework입니다. 각 Actor들은 Router에 의해 묶일 수 도 있으며 Round robin 등의 적절한 strategy 를 선택해 일을 할당 받을 수 도 있습니다. 또한 메시지를 주고 받을 때 fire-and- forget 패턴의 tell 방식이나 Promise 패턴을 사용한 ask 방식 모두 지원합니다. 참고로, Scala 자체적으로도 Erlang의 영향을 받은 Actor 모델의 구현을 가지고 있지 만, 2.10 버전 이후에는 별도의 jar로 분리되어 deprecate 될 예정이며 Akka가 그 대 체자로 선택되었습니다. 주요 기능 • Scala로 쓰여졌지만, 자바로도 쉽게 사용할 수 있도록 별도의 wrapping api 를 제공 • Remote Actor 지원 • Supervising, 각 Actor들은 상위 Actor에 의해 관리됨 • Q3 출시 예정인 2.1 버전을 통해 gossip protocol 기반의 위치 투명성을 가지는 Cluster 제공 참고 http://akka.io/ http://en.wikipedia.org/wiki/Actor_model
  341. 345 꽃보다 Scala Play Framework 최근 가장 떠오르는 자바 진영의

    웹 프레임웍입니다. 자세한 설명은 봄날은 간다 세션 을 참고하세요~ 주요 기능 • Akka와 마찬가지로 Java 지원 • Rails 스타일의 COC (Convention Over Configuration) • Netty 기반의 비동기 IO 지원 • Akka 를 middleware로 사용할 수 있도록 연동 기능이 제공 참고 http://www.playframework.org/ Typesafe Stack Scala의 창시자인 Martin Ordersky는 2010년 Typesafe라는 회사를 세우고 Scala 관련 분야에 대해 교육및 컨설팅등의 상업적인 지원을 시작했습니다. 그리고 얼마전 Scala를 기반으로 하고 Akka 2.0을 event-driven middleware로 Play 2.0을 web framework으로 하는 상업적인 지원을 포함한 Typesafe Stack을 발표 했습니다. 참고 http://typesafe.com/ Spray Akka 위에 Restful Web Service를 만들기 위한 framework으로 Play와 같은 웹프 레임웍이라기 보다는 단순히 Akka 위에 REST 스타일 인터페이스를 씌우기 위해 사 용됩니다. Play와 Akka가 Typesafe Stack으로 묶인지가 얼마 안되서 인지, Play의 Akka 연동 기능보다는 View가 필요없는 REST API 서버라면 현재로서는 Spray가 훨 씬 강력하며 편리해 보입니다.
  342. 346 H3 개발자 컨퍼런스 2012 주요기능 • Asynchronous, Non-blocking IO,

    Actor 기반으로 수많은 동시 접속 처리 가능 • 자체 DSL 지원 • REST service에 대한 테스트 용이 참고 https://github.com/spray/spray/wiki 글을 마치며 지금 까지 Scala의 주요 기능과 몇몇 툴에 대해서 두서 없이 쭉 훑어 보았습니다. 많은 분들이 아마도 재미도 없고 부족한 설명으로 이해하지 못한 부분들을 뒤로 한 체 여기까지 오셨을 듯합니다. 전부는 이해하지 못했더라도 한번 공부해 보고 싶으신 마 음이 들었다면 그것으로 충분합니다. 다음 링크들 참고 하셔서 새로운 언어를 통해 앞 으로의 개발자 생명연장의 꿈을 키워 나가시기 바랍니다 :) Scala 보다 더 어렵다는 Scala 도입을 성공적으로 이루셔서 더 많은 곳에서 Scala가 쓰이길 바라며 글을 마칩니다. 참고 문헌 및 자료 Programming in Scala 2nd Edition http://www.scala-lang.org/node/198 http://twitter.github.com/scala_school/ http://en.wikipedia.org/wiki/Scala_(programming_language) http://twitter.github.com/effectivescala/
  343. 347 오픈 소스로 구현하는 Real-time CEP 들어가는 글 본 내용에서는

    실시간 이벤트 처리 시스템 구축을 위한 CEP 개념 소개와 오픈 소스 Esper를 이용한 CEP 애플리케이션 개발 방안에 관해 소개 하고자 합니다. 일반적으로 우리가 구축하는 웹 애플리케이션과 같은 대부분의 시스템은 구조적으로 요청에 응답을 반환하는 시스템입니다. 또는 주기적으로 잡을 실행하는 배치 시스템 입니다. 대부분의 개발자들 또한 이러한 기술에 대해서 잘 알고 있고 전문가입니다. 하지만 실시간 데이터 처리 시스템을 구축해야 하는 요구 사항이 주어진다면, 생각보 다 쉽지 않게 됩니다. 배치 주기를 짧게 하거나 요청에 즉시 응답하는 시스템도 실시 간 시스템이라 할 수 있겠지만 이러한 일반적인 기존 방식으로는 데이터 처리 한계와 성능 이슈에 부딪치게 됩니다. 그래서 실시간에는 실시간 데이터 처리에 적합한 새로 운 아키텍처가 필요합니다. 그러한 요건에 적합한 아키텍처가 이벤트 중심의 패러다 임인 Event-driven Architecture(EDA)입니다. EDA의 기술에는 3가지 종류가 존재합 오픈 소스로 구현하는 Real-time CEP 데이터지능팀 원종석 [email protected]
  344. 348 H3 개발자 컨퍼런스 2012 니다. 그 중에 가장 난위도가

    높은 기술로써 복합 이벤트 처리 기술인 CEP (Complex Event Processing) 가 있습니다. 이 CEP 기술이 제공되면, 그 동안 하지 못 했던 그 리고 보지 못 했던 재미있고 의미 있는 데이터를 볼 수 있게 됩니다. 앞으로 실생활과 밀접한 부분에 적용될 잠재적인 사용 사례가 무궁무진한 기술입니다. 하지만 CEP는 처음 접하게 되면 쉽게 이해되지 않고 매우 난해하게 느껴집니다. 실무 개발에 있어서 도 한 부분이 아닌 종합적인 기술력을 요구합니다. 필자의 경험 공유를 CEP를 이해하 고 활용함에 도움이 되었으면 하는 바람입니다 실시간 이벤트 처리와 CEP 실시간으로 데이터를 처리해야 하는 요구사항에는 다양한 분야에 여러 가지의 유즈 케이스가 있을 수 있습니다. 예를 들어 시스템 모니터링, 주문 상태 모니터링, 최적의 교통 경로 안내 등 시스템적인 것에서부터 실생활과 밀접한 다양한 케이스에 활용 될 수 있습니다. CEP 기술 적용으로 가능한 몇 가지 예를 들어 보겠습니다. 시스템 상태 실시간 모니터링 시스템이 현재 처리하고 있는 처리량(throughput)을 감시하는데 적용 할 수 있습니 다. 처리량 통계를 실시간으로 계산하고 있다가 특정 임계치 이하로 떨이지면 즉시 통 보(alert) 합니다. 좀 더 복잡한 조건으로 모니터링 할 수도 있습니다. 5번 이상 처리량 임계치를 벗어나고 동시에 메모리 사용량 임계치를 벗어나면 통보와 같은 방식도 가 능합니다. 쇼핑 사이트의 지역별 주문 실시간 통계 쇼핑 사이트에서 고객의 주문에 대한 여러 가지 실시간 통계를 계산 할 수 있습니다. 지역 별 주문 비율 통계를 계산하여 실시간으로 어떤 지역에서 어떤 비율로 주문이 일 어나고 있는 지와 변화 추이는 어떻게 되는지를 알 수 있습니다. 주식 자동 매매 (Algorithmic Stock-Trading) 주식 거래에서는 이미 CEP 기술이 활용되고 있습니다. 주식 틱을 모니터링 하다가 어 떠한 복합 조건에 도달하면 자동으로 주식을 매도/매수하는 것이 대표적인 예입니다.
  345. 349 오픈 소스로 구현하는 Real-time CEP 이마트에서 고객 카드에 RFID(Radio

    Frequency Identification) 칩이 적용되었다면 매장에 머물고 있는 고객의 실시간으로 이동 경로와 패턴을 계산합니다. 이제 특정 위 치에 있는 고객에게 카트의 모니터를 통해서 타켓팅 추천을 합니다. 매장의 영역별로 현재 얼마나 많은 고객들이 머물고 있는지 파악하고, 매장을 이동하는 패턴에 따라서 실시간으로 쿠폰을 발행해 줄 수 도 있습니다. 혹은 카트에 물건을 담으면 자동으로 결재 금액을 계산하여 계산대에 도착하자마자 계산합니다. 대기 시간을 줄이고 고객 만족을 높일 수 있을 것입니다. 교통 안내 실시간 교통 상황 정보를 기반으로 운전자에게 실시간으로 최적의 경로를 안내 할 수 있습니다. Complex Event Processing(CEP) 개념 소개 이러한 재미있고 실용적인 다양한 실시간 유즈 케이스들을 CEP 기술을 활용하여 구 축 가능합니다. 먼저 CEP를 개념적으로 이해할 필요가 있습니다. 쉽게 이해할 수 있 는 예를 생각해보겠습니다. 교회라는 장소에서 벨이 울리고 있고 턱시도를 입은 남자 와 꽃을 든 여자가 함께 걷고 있다. 그리고 두 사람 위로는 꽃 잎이 날리고 있다. 라고 사람에 얘기를 해준다면 쉽게 결혼식이라는 것을 떠올릴 것입니다. 이러한 것처럼 시 스템이 여러 가지 이벤트 정보를 받아들이고 이를 기반으로 종합적으로 판단하여 결 혼식이라는 패턴을 알아차리고 반응을 하는 것이 바로 CEP 시스템입니다. CEP의 기술적 소개 CEP는 EDA(Event-driven Architecture) 사상을 기반으로 하는 실시간 복합 이벤트 처리 기술입니다. 수많은 이벤트 속에서 의미 있는 이벤트를 구별해내는 기술입니다. 여기에 의미 있는 이벤트를 찾아내면 즉시 어떤 반응을 하는 것을 포함합니다. 의미 있는 이벤트라는 뜻은 어떤 조건에 부합하거나 임계치도 도달하였거나 어떠한 패턴에 매칭되는 이벤트를 말합니다. 실시간으로 반응하는 시스템이기 때문에 데이터 를 모아서 주기적으로 처리하는 배치 시스템과 상반되는 메커니즘이라고 볼 수 있습 니다. 또는 웹 애플리케이션의 요청에 대한 응답을 하는 스타일의 처리와도 구분됩니
  346. 350 H3 개발자 컨퍼런스 2012 다. 응답(Response)이 아닌 비동기로 반응(Reaction)을

    하는 시스템입니다. 복잡한 상황에 대해서 실시간으로 반응하는 시스템이기 때문에 Intelligence System 이라고 도 합니다. CEP 처리 스타일이 이해하기에 난해한 것 같지만 사실 RDBMS 처리 개념과 비유해 서 생각하면 이해하기 쉽습니다. RDBMS는 데이터를 선 저장한 후 사용자의 질의를 던져서 후 처리하고 응답을 반환합니다. 반면 CEP는 데이터를 저장하지 않습니다. 사 용자 질의를 먼저 저장한 후 데이터를 흘려 보냅니다. 그리고 매칭되는 이벤트에 대해 서 선 처리하고 후 반응합니다. 이렇게 CEP는 RDMBS의 처리 구조를 뒤집은 것이라 고 이해할 수 있습니다. 이렇게 스트림이 흘러가는 구조이기 때문에 CEP는 비동기 스타일로 데이터를 처리 합니다. 이벤트 스트림이 CEP 엔진으로 인입되면 엔진이 직접 이벤트 데이터를 저장 하거나 처리하지는 않습니다. 지속적으로 이벤트를 받아들이고 흘려 보내면서 엔진에 등록된 EPL에 맞는 이벤트가 감지되게 되면 즉시 선 처리를 하게 되고 비동기로 결과 를 후 저장합니다. 이러한 처리 스타일을 Event-driven이라고 합니다. CEP를 구현한 쓸만한 오픈 소스 구현체로는 크게 2가지가 존재합니다. EsperTech 사의 Esper와 Redhat JBoss의 Drools Fusion입니다. 두 가지 모두 Java기반의 구 현체입니다. 그러므로 자바 개발자라면 손쉽게 활용 가능합니다. 또한 이벤트 처리 언 어를 스크립트 방식으로 제공합니다. Drools Fusion은 Rule-oriented 스타일로써 Drools 룰 엔진 위에서 CEP 처리가 가능하도록 확장된 형태입니다. 이벤트 처리 언어 로 룰 스크립트 언어를 제공합니다. 또한 Esper는 구현체로 Java와 .NET 버전을 동 시에 제공합니다. .NET 개발자도 .NET 플랫폼에서 Esper를 기반으로 CEP 시스템을 구축할 수 있습니다. Esper 라이선스는 듀얼 라이선스 정책으로 제공됩니다. 오픈 소 스와 엔터프라이즈 라이선스 두 가지로 제공합니다. Esper의 강점은 이벤트 처리 언 어를 SQL 스타일로 제공하는 것입니다. 프로그래밍 없이 쉽게 배워서 일반적인 데이 터 처리를 하듯이 SQL 스크립트로 작업이 가능한 것입니다. 이것은 CEP 시스템을 사용하는 비즈니스 관련 사용자들이 쉽게 배워서 직접 데이터 처리 문을 구현하고 적 용 할 수 있는 것을 의미합니다. 일반적인 다른 시스템은 비즈니스 담당자로부터 데이 터 처리 요구사항이 들어오면 엔지니어가 직접 코딩을 하여 구현하고 적용해야 하는 데 그것에 비해서 큰 강점이라 할 수 있습니다. 또한 오픈 소스라는 측면에서 Drools Fusion과 Esper는 버전간 하위 호환성을 유지하면서 꾸준하게 버전 업데이트 되고 있 고 커뮤니티 활동이 활발한 신뢰할 수 있는 오픈 소스 프로젝트입니다.
  347. 351 오픈 소스로 구현하는 Real-time CEP EDA(Event-driven architecture)의 개념 소개

    EDA(Event-driven architecture)는 이벤트 처리에 대한 가장 추상화된 아키텍처 패 턴입니다. CEP는 EDA의 구체화된 기술로써 난해하게만 느껴지는 CEP를 이해하 기 위해서는 그 아버지에 해당하는 EDA에 대한 이해가 간단하게나마 필요합니다. EDA는 이벤트의 생산(production), 감지(detection), 소모(consumption)와 반응 (reaction)을 위한 구조를 정의한 아키텍처 패턴입니다. 이는 인간의 감각 기관과 유사 하게 비유가 가능합니다. 눈과 같은 감각기관도 이벤트 드리븐 아키텍처입니다. SOA 와 비교를 많이 하는데 SOA 보다도 더욱 loosely-coupled한 구조를 갖습니다. 참 고로 Event를 정의하는 표준 스펙은 표준을 정의하는 논의가 OASIS라는 단체에서 Common Base Events라는 이름으로 진행 중에 있습니다. EDA의 처리 모델을 보면 요청에 응답을 하는 처리 구조가 아닌 반응하는 구조라는 점에 주목해야 합니다. 이것 이 가장 분명하게 일반적인 시스템 구조와 구별되는 포인트입니다. 데이터 처리 패러 다임에서도 분명한 차이가 있습니다. 일반적인 시스템이 데이터를 선 저장하고 후 처 리하는 패러다임인 반면, EDA는 선 처리 후 저장 패러다임입니다. 이벤트가 발생하자 마자 즉시 처리 한 후 그 결과를 저장합니다. 앞에서 언급한 CEP와 동일한 구조입니 다. CEP가 EDA 아키텍처를 기반으로 하기 때문입니다. 이벤트 생산자(event producer)는 이벤트가 실제로 발생하는 주체를 말합니다. 또한 발생한 이벤트를 이벤트 처리 엔진으로 전달하는 에이전트 같은 것을 포함하는 개념 입니다. CEP에서 이벤트를 받아들이는 입력 어댑터(input adapter)에 해당합니다. 이벤트 소비자(event consumer)는 이벤트 처리 엔진에 의해서 감지된 어떤 이벤트에 대해서 미리 정의된 반응을 하는 것을 말하는 개념입니다. CEP에서 이벤트 처리 결과 를 수행하는 출력 어댑터(output adapter)에 해당합니다. Event-driven Architecture
  348. 352 H3 개발자 컨퍼런스 2012 이벤트 처리 스타일 3가지 EDA에서는

    처리 복잡도, 즉 난위도에 따라 SEP, ESP, CEP 3가지 프로세싱 타입을 정의하고 있습니다. • SEP(Simple Event Processing) • ESP(Event Stream Processing) • CEP(Complex Event Processing) SEP(Simple Event Processing)는 가장 단순한 형태로써 싱글 이벤트 프로세싱으 로 하나의 데이터 스트림에 대해서만 처리합니다. 대표적인 예로 ESB(Enterprise Service Bus)나 JMS(Java Message Service) 등이 있습니다. 특징은 상태가 없는 이벤트 처리로써 SEP에서는 상태가 이벤트에 담긴 메시지 그 자체를 의미합니다. ESP(Event Stream Processing)와 CEP(Complex Event Processing)는 복수의 이 벤트 스트림을 대상으로 하며 아직까지 표준 스펙은 존재하지 않고 구현체 제품만 존 재합니다. ESP는 이벤트 스트림에 대한 처리로써 일반적인 모든 이벤트 계산, 처리 등을 정의합니다. CEP를 ESP와 구별 짓는 것은 패턴 감지 능력입니다. 복합 이벤트 로부터 상황 조건을 바탕으로 패턴을 감지하는 능력을 포함합니다. 예를 들어 “30분 간의 구글 주식의 평균값 계산하기”는 ESP인 반면, “야후! 주식이 10%이상 떨어진 후 구글 주식이 5%이상 2번 연속으로 오른다면...”은 CEP라고 할 수 있습니다. Event의 정의 이벤트(event)는 무엇이라 정의 할 수 있을까요? 또 어떤 것을 이벤트로 정의 할 수 있 을까요? 이벤트란 실제로 발생한 어떤 일, 사건을 말합니다. 이것을 가만히 생각해보 면 어떤 변화가 일어났다는 것입니다. 변화가 있다는 것은 어떤 상태가 있다는 의미 가 됩니다. 즉 이벤트란 어떤 것의 상태가 변화한 것입니다. 상태를 가지고 변화하는 모든 것이 이벤트로 정의 될 수 있습니다. 달라이 라마와 도올과 같은 사상가의 말씀 이 세상의 모든 것은 변화한다고 합니다. 세상의 모든 것을 이벤트로 정의 할 수 있습 니다. 어떤 것이든 이벤트로 추상화하여 EDA 스타일로 정의할 수 있는 것입니다. 즉 아주 다양한 요건에 적용 가능합니다. CEP에서도 가장 먼저 해야 할 것이 바로 이벤 트 정의입니다. 이벤트의 예를 들어보면 주식 거래 틱, 비밀번호 변경, 10초마다 실내 온도 측정, 서비스 응답 시간, 위치 이동 등과 같이 매우 다양하며 수치나 값으로 표현 가능합니다.
  349. 353 오픈 소스로 구현하는 Real-time CEP Event Type의 선택 이벤트

    타입은 이벤트를 추상화하여 표현한 이벤트 스키마를 프로그래밍적으로 표현 한 것입니다. DBMS의 테이블 스키마 및 테이블과 유사한 개념으로 생각할 수 있습니 다. 이벤트 타입을 표현하는 데이터 포맷은 POJO, Map, XML, JSON, CSV등으로 일반적인 데이터 포맷을 사용하여 표현 할 수 있습니다. 각 포맷 마다 특징과 성능의 차이가 있습니다. XML은 성능상 가장 나쁘지만 사람이 이해하기 쉬운 텍스트 포맷이 라는 장점이 있고 POJO는 성능상 가장 좋지만 바이너리이므로 사람이 내용을 들여다 보기 어렵습니다. 성능상의 관점에서는 어댑터와 엔진에서 변환이 가장 적은 이벤트 타입을 선택하는 것이 좋습니다. 하지만 실제 요건에 따라 가장 적절한 이벤트 타입을 선택하는 것이 일반적입니다. Event Stream의 개념 이벤트 스트림이라는 말과 개념은 언뜻 쉽게 이해할 수도 있고 어렵게 느껴질 수도 있 습니다. 이벤트 스트림의 의미는 이벤트가 어떠한 채널을 통해서 시간의 흐름과 함께 시작과 끝이 없이 지속적으로 발생하고 흘러가는 것을 의미합니다. 예를 들면 자동차 가 다니는 차도가 있고 하나의 자동차가 하나의 이벤트라고 정의한다면, 차도의 차의 흐름이 끊임없이 흘러가는 것을 하나의 이벤트 스트림으로 볼 수 있습니다. 이 흐름이 언제부터 시작했고 언제 끝날 것이라는 것은 중요한 것이 아닙니다. 정리하면 시간의 순서대로 시작과 끝이 없는 이벤트의 연속된 흐름이라고 할 수 있습니다. CEP 시스템의 사용 사례 CEP의 적용 분야를 정리하면 다음과 같습니다. 일반적인 ETL 데이터 처리부터 OI, 업무 처리, 예측 분석까지 다양한 분야에 적용 가능합니다. • Algorithmic Stock-Trading • Operational Intelligence(OI) • Real-time analytics • Predictive analytics • Event-driven business process management • BAM - Business Activity Monitoring
  350. 354 H3 개발자 컨퍼런스 2012 • BI - Business intelligence

    • BRMSs - Business rule management systems • Network and System Management • MOM- Message-oriented middleware • Stream computing • ETL(Extract, Transform, Load) CEP 제품 소개 Oracle, IBM, Microsoft, SAP 등 대형 벤더들은 이미 CEP 솔루션 제품을 제공하 고 있습니다. 이들은 벤더가 직접 개발하거나 CEP 전문 솔루션 기업 인수합병을 통 해서 자신들의 제품 군에 CEP 영역을 확보하고 있습니다. Oracle CEP의 경우는 CEP 엔진으로 오픈 소스 Esper를 기반으로 하고 있습니다. 사실 이 제품은 Oracle 로 인수된 Bea의 제품이었습니다. 재미있는 것은 CEP가 표준은 없지만 모든 CEP 제품의 아키텍처와 제품 구성이 동일합니다. EDA 아키텍처를 기반으로 하고 다양 한 Input/Output Adapter를 제공합니다. 또한 고성능 CEP 엔진 제공 및 CEP 서비 스 개발도구 제공 및 시스템 관리/모니터링 도구를 패키징하여 엔터프라이즈 CEP 솔 루션으로 제공하고 있습니다. 업계 최고의 제품으로는 TIBCO 제품을 꼽고 있으며 StreamBase는 CEP 전문 기업으로 정교하게 잘 만들어진 CEP 제품으로 유명합니 다. IBM InfoSphere Streams는 9.11 테러 이후에 테러 방지 목적으로 미국 정부의 의뢰로 개발된 솔루션을 제품화 한 것이라고 합니다. 벤더 제품명 Oracle Oracle CEP IBM InfoSphere Streams (멀티미디어 스트림 프로세싱 가능) WebSphere Business Events Microsoft StreamInsight SAP Sybase Event Stream Processor Informatica RulePoint TIBCO TIBCO BusinessEvents StreamBase Systems StreamBase CEP
  351. 355 오픈 소스로 구현하는 Real-time CEP 오픈 소스 Esper 기반으로

    CEP 애플리케이션 구현하기 상용 제품을 구매하여 사용하면 보다 빠른 시간에 비즈니스에 적용 할 수 있겠지만 CEP 제품 라이선스 비용은 매우 고가에 속합니다. 또한 플랫폼 도입이 아닌 작은 한 부분에 CEP 기능을 적용하고 싶은데 상용 제품의 플랫폼을 도입하는 것도 맞지 않습 니다. 이러한 와중에 아주 잘 만들어진 CEP 오픈 소스가 있다는 것은 매우 반가운 일 입니다. 오픈 소스를 찾아보면 없는 것이 없지만 정말 제대로 만들진 건지, 쓸만한 것 인지 의구심이 들 때도 있습니다. 필자의 경험으로 말씀 드리면 Esper는 신뢰할 수 있 는 잘 만들어진 CEP 오픈 소스라고 말씀드릴 수 있습니다. 성능 또한 C기반의 CEP 시스템과의 벤치마킹에서도 문제 없는 성능을 확인한 바 있습니다. 이제부터는 처음 접하는 독자들을 위해서 Esper 오픈 소스를 기반으로 CEP 애플리케이션을 구현하는 방법에 대해서 간단하게나마 중요한 점들을 짚어가면서 알아보겠습니다. EsperTech Esper 소개 EsperTech에서 배포하고 있는 오픈 소스 Esper는 CEP를 구현한 오픈 소스 중에서 가장 정교하고 수준이 높습니다. 또한 유료 기술 지원도 가능합니다. 2004년부터 토 마스 버나드(Thomas Bernhardt)가 시작한 오픈 소스로써 꾸준한 버전업을 제공하고 있습니다. 직접 오픈 소스 프로젝트를 만들게 된 계기는 증권사에서 일을 하면서 주식 거래에 대한 모니터링을 하기 위해서 만들기 시작했다고 합니다. • 엔터프라이즈 버전 사이트: http://espertech.com/ • 오픈 소스 커뮤니티 사이트: http://esper.codehaus.org/ Esper는 CEP 처리를 위한 정교한 이벤트 처리 언어인 EPL(Event Processing Language)을 제공합니다. SQL 스타일의 언어로써 배우기 쉽고 사용법에 대해서 공 식 문서를 참조하거나 샘플 예제를 실행을 통해서 배울 수 있습니다. Esper의 또 하나 의 강점으로 매우 잘 정리된 공식 문서를 제공합니다. Esper를 기반으로 구현하면 필 요한 거의 모든 내용을 참조 할 수 있습니다. 이벤트 처리 모델과 EPL 문법 및 사용 예, 어댑터 사용법, 성능 관련 튜닝팁등 매우 방대한 내용을 제공하고 있습니다. • Esper 공식 문서: http://esper.codehaus.org/esper/documentation/documentation.html
  352. 356 H3 개발자 컨퍼런스 2012 런타임 스타일 사실 Esper는 엔진

    API만을 제공합니다. 명령으로 구동시킬 수 있는 패키징 형태나 실행 가능한 런타임 환경은 제공하고 있지 않습니다. 그러므로 테스트 시에 많은 어려 움이 있습니다. 하지만 어느 시스템의 어느 위치이든지 임베디드될 수 있는 장점이 있 습니다. 어떤 웹 애플리케이션의 하나의 기능으로 배치 될 수 도 있고, 자바 stand- alone 스타일로 구동 될 수 도 있습니다. Esper는 2가지 스타일을 제안하고 있습니다. Java EE 런타임 환경에서 WAR(Web Application Archive) 형태로 구동되는 방법과 OSGi 환경에서 번들(bundle) 형태로 구동되는 것입니다. Java EE 환경에서는 웹 애 플리케이션이나 MDB(Message-Driven Bean)에서 임베디드 되어서 구동 될 수 있습 니다. OSGi는 OSGi 번들 형태로 패키징 되어서 자바 stand-alone 스타일로 구동 될 수 있습니다. 쓸만한 오픈 소스 엔터프라이즈 OSGi 서버로 Eclipse의 Virgo Server가 있습니다. 개발 프레임워크로는 Spring의 OSGi 모듈인 Spring Dynamic Module을 사용 할 수 있습니다. 필자는 이러한 기술들을 기반으로 CEP 시스템 구축 시 OSGi 환경을 선택한 적이 있습니다. 그 이유는 실시간 처리의 특성상 Zero-downtime과 EPL을 동적으로 적용하는 요건을 구현하기 위해서였습니다. Virgo 서버를 통해서 OSGi + WAR 형태도 구성이 가능합니다. 다만 OSGi 환경의 가장 큰 문제는 의존성 라이브러리들을 모두 OSGi 번들로 다시 번들링 해주어야 하는 작업에 부담이 매우 크 다는 점입니다. 이를 해결하면 CEP의 특성을 OSGi 환경에서 잘 구현 할 수 있습니다. Esper + Java EE 런타임 환경 구성 Esper + OSGi 런타임 환경 구성
  353. 357 오픈 소스로 구현하는 Real-time CEP Esper기반 CEP 애플리케이션 아키텍처와

    개발 요소 Esper를 기반으로 CEP 애플리케이션을 구현하기 위해서는 필요한 시스템 구조와 개 발이 필요한 부분에 대한 이해가 필요합니다. 시스템의 구조는 Input adapter와 CEP 엔진 그리고 Output adapter 이렇게 3개의 모듈로 구성됩니다. 데이터의 흐름은 단 방향으로 Input에서 엔진을 거쳐 Output으로 흘러가는 구조입니다. CEP 애플리케이션 아키텍처 심플 뷰 Input adapter는 TCP/IP 또는 HTTP와 같은 통신 프로토콜에 맞게 이벤트를 받아들 이고 CEP 엔진으로 전달하는 역할을 합니다. Output adapter는 엔진의 처리 결과를 받아서 적절한 리액션을 하는 역할을 합니다. 여기에서 우리가 개발을 해야 하는 영역 은 Input / Output adapter입니다. CEP 엔진에는 데이터 처리를 위해 작성한 EPL을 등록해 주어야 합니다. 좀 더 구체적인 사례로써 실시간으로 로그 수집하면서 ETL 처 리하는 예를 보겠습니다. 대용량 로그 실시간 처리 CEP 애플리케이션 아키텍처 적용 사례 Facebook Scribe 로그 수집기를 이용하여 분산된 서버로부터 로그를 실시간으로 수 집하여 실시간으로 필터링 ETL 처리를 하여 Hadoop HDFS 분산 파일 시스템으로 저 장하는 시나리오를 보겠습니다. 이를 구현하기 위해서 먼저 Scribe Input Adapter 개 발이 필요 합니다. Scribe 로그 수집기로 부터 로그 이벤트를 받아들이고 CEP 엔진으
  354. 358 H3 개발자 컨퍼런스 2012 로 전달하는 역할을 합니다. 데이터

    ETL 처리를 위해 필터링을 정의한 EPL을 작성합 니다. 마지막으로 EPL 결과를 받고 HDFS로 저장 할 수 있는 HDFS Output Adapter 를 구현합니다. 크게 이 3가지만 구현되면 실시간으로 HDFS로 로그를 수집하면서 실 시간으로 데이터 처리를 할 수 있습니다. 다른 구체적인 예로써 원격의 로그 이벤트를 HTTP로 수집하여 실시간 데이터 처리 결과를 원격의 HTTP 서버로 전송하고 동시에 로컬 파일 시스템에 CSV로 저장하는 시나리오가 있을 수 있습니다. HTTP는 사실 비용이 많이 드는 통신 프로토콜이지만 개발/테스트/운영이 용이하고 다른 시스템과 연동하기 좋기 때문에 실무에서 많이 사 용됩니다. 원격의 로그를 수집하여 HTTP로 전송하는 일종의 에이전트 같은 클라이언 트 애플리케이션과 로그 이벤트를 리스닝하는 HTTP Input Adapter, 로그 이벤트 처 리를 위한 EPL, HTTP 클라이언트 기능을하는 HTTP Output Adapter, 로컬 파일 시 스템 저장 기능을 구현한 CSV Output Adapter 개발이 필요합니다. CEP 애플리케이션 아키텍처 적용 사례 정리하면, 이벤트를 받아들이는 Input Adapter를 요건에 맞게 개발해야 하고 EPL 문을 작성해야 하며, 처리 결과에 대한 저장이나 메일 발송 등을 할 수 있는 Output Adapter 개발이 필요합니다. 실제 구현 시 어려운 점은 CEP 처리 가능 용량에 비해서 Input Adapter의 성능이 떨어지지 않게 하는 것입니다. 그냥 보통 개발하듯이 개발하 여 붙이면 거의 100% Input Adapter가 성능상 병목 지점이 되는 것입니다. 이를 방지 하기 위해서 고성능 Input Adapter 개발이 필요하게 되고 이를 위해서 더 최적화된 기 술이 요구되며 통신 프로토콜의 효율성에 대해서도 따져보아야 합니다.
  355. 359 오픈 소스로 구현하는 Real-time CEP Esper EPL(Event Processing Language)

    Esper의 EPL은 SQL을 기반으로 실시간 처리를 위한 타임 윈도우 개념을 확장 구현 한 SQL-like 한 이벤트 처리 언어입니다. EPL은 업계 표준은 아니지만, SQL기반 이 때문에 배우기 쉽고 매우 직관적인 편입니다. 엔지니어가 아닌 일반 비즈니스 담 당자들도 배워서 사용 할 수 있을 정도입니다. 이것은 마치 Apache Hive와 유사합니 다. Hadoop에서 데이터 처리를 위해서는 MapReduce라는 프로그래밍 스타일로 일 일이 코딩을 해야 했던 것을 일반 분석가들도 쉽게 사용 할 수 있도록 SQL형태로 제 공을 하고 자동으로 MapReduce로 변경시켜주는 기능을 제공합니다. 또한 EPL은 Hibernate의 HQL(Hibernate Query Language)과 상당히 유사합니다. 하나의 이벤 트가 자바의 클래스(POJO)로 표현되기 때문에 객체지향적 쿼리가 가능합니다. 간단한 EPL의 예를 보겠습니다. select itemId, count(*) as cnt from OrderEvent.win:time(30 min) group by itemId 이 EPL의 의미는 지난 30분동안 발생한 주문 이벤트에 대해서 상품별 주문 카운팅 통 계를 계산 합니다. 이와 같이 SQL과 유사하면서도 .win:time(30 min)이라는 시간 범 위 개념이 추가되어있습니다. SQL 스타일을 기반으로 하기 때문에 서브 쿼리나 조인 도 지원됩니다. 또한 EPL과 RDBMS의 SQL 간의 조인이 가능합니다. 사용자 정의 함수(UDF) 또는 NoSQL과도 조인이 가능합니다. 그러므로 하나의 EPL 쿼리에 복수 개의 RDBMS와 File Data 또는 캐시 데이터, NoSQL 데이터와 동시에 조인이 가능한 특징이 있습니다. EPL과 외부 데이터 소스 조인
  356. 360 H3 개발자 컨퍼런스 2012 RFID 도메인 예제 Esper에서 제공하는

    좀 더 완전한 예제를 보겠습니다. 시나리오는 이렇습니다. RFID(Radio Frequency Identification) 센서가 장착된 어떤 자산(asset)들이 영역 (zone)을 이동합니다. 이 자산들의 움직임을 실시간으로 추적하는 예제입니다. 먼저 위치 이동 이벤트를 정의하는 LocationReport 이벤트를 정의합니다. 여기에는 자산 의 식별자(asset id)와 위치(zone) 정보가 있습니다. 추적하고자 하는 구체적인 시나리오는 다음과 같습니다. 기본 통계로써 “Asset이 이 동할 때마다 각 zone의 asset 카운트 통계를 계산하라”와 좀 더 복잡한 조건으로 “어 떤 zone에서 다른 zone으로 이동할 때 전체 asset의 부분만 이동하고 10초 이상 머 무르면, 경보를 알려라”입니다. 이에 대한 EPL 정의는 다음과 같습니다. 먼저 Asset의 이동 시마다 실시간 위치기반 카운트 통계를 계산합니다. Asset이 이동 하면 LocationReport 이벤트가 발생하고 CEP 엔진으로 이벤트가 인입됩니다. 이에 Asset 1, 2, 3 이 있는 위치 마다의 카운트 통계를 실시간 계산하고 CountZone이라는 Data Window에 계산 결과를 담습니다. insert into CountZone select zone, count(*) as cnt from LocationReport.std:unique(assetId) where assetId in (1, 2, 3) group by zone
  357. 361 오픈 소스로 구현하는 Real-time CEP 이제는 패턴 매칭 EPL을

    정의합니다. 앞에 EPL로 생성된 CountZone 데이터 윈도우 에 담긴 값을 기반으로 패턴 매칭을 수행합니다. 모든 Asset이 동일한 하나의 zone에 있다가 어떤 asset이 다른 zone으로 이동하고 10초 이상 유지되면 해당 zone 값을 반환합니다. select Part.zone from pattern [ every Part=CountZone(cnt in (1, 2)) -> (timer:interval(10 sec) and not CountZone(zone=Part.zone, cnt in (0, 3)))] 이 예제는 Swing GUI를 제공합니다. 예제를 실행하면 그림과 같은 화면을 통해서 사 용자가 마우스를 드래그하면 이벤트가 발생하는 것으로 되어 있습니다. CEP 애플리케이션 개발 전략 실시간 CEP 애플리케이션 개발을 위해 필요한 전체 과정을 정리해보겠습니다. 스텝 으로 정리하면 다음과 같습니다. • 이벤트 정의하기 • 이벤트 타입(포맷) 정의하기 • EPL 정의하기 • EPL문 CEP엔진에 배포하기 • Output Adapter 등록하기 • Input Adapter 등록하기
  358. 362 H3 개발자 컨퍼런스 2012 이벤트 정의하기 가장 먼저 처리

    대상에 대해서 어떻게 이벤트로 추상화하여 표현 할 것인지 고민해보 아야 합니다. 이것은 객체 지향 시스템 설계에서 어떻게 객체로 표현 할 것인가와 비 슷한 고민입니다. 예로 온라인 쇼핑몰에 주문이 있습니다. 주문을 이벤트로 추상화하 여 정의 할 수 있습니다. 그리고 이벤트 처리에 필요한 속성만을 정의합니다. 주문 이 벤트에 상품명, 가격이라는 속성만을 정의해보겠습니다. 이벤트 타입(포맷) 정의하기 이벤트 정의를 실제 프로그래밍적으로 표현하는 과정입니다. POJO, Map, Array, XML등으로 이벤트 타입을 정의 할 수 있습니다. 다음은 주문 이벤트를 POJO(Plain- Old Java Object) 스타일로 정의한 예입니다. 속성으로 상품명과 가격을 정의하고 타 입을 정의하였습니다. 주문 이벤트 타입 정의하기 /** * 주문 이벤트 클래스. */ public class OrderEvent { private String itemName; private double price; ... } EPL 정의하기 이제 이벤트 타입을 정의하였으면 EPL을 작성할 수 있습니다. 이벤트를 처리하고자 하는 시나리오에 맞춰서 EPL을 작성합니다. 이벤트 타입을 SQL의 테이블과 같은 개 념으로 EPL을 작성 할 수 있습니다. EPL 작성은 Esper 공식 문서를 참조하면서 작 성하는 것이 좋습니다. EPL 참조 문서: http://goo.gl/xFrkG 다음 EPL은 주문 이벤트에 대해서 30분 동안의 상품별 주문 통계를 계산합니다. 주문 통계 계산 EPL select itemId, count(*) as cnt from OrderEvent.win:time(30 min) group by itemId
  359. 363 오픈 소스로 구현하는 Real-time CEP EPL문 CEP엔진에 배포하기 정의한

    EPL을 CEP 엔진에 등록해야 합니다. 등록 방법은 API 적으로 다음 코드와 같 습니다. CEP 엔진에 해당하는 EPServiceProvider 클래스에 등록하고 EPStatement 객체를 얻습니다. 이 EPStatement 레퍼런스를 통해서 등록한 EPL의 라이프 사이클 관리를 할 수 있습니다. EPL 실행 시작/중지/해제 등의 관리를 할 수 있습니다. EPL 등록하기 // CEP 엔진 초기화 Configuration config = new Configuration(); EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider(con- fig); // EPL 등록하기 String expression = "select itemId, count(*) as cnt from OrderEvent.win:time(30 min) group by itemId"; EPStatement statement = epService.getEPAdministrator().createEPL(expression); Output Adapter 등록하기 등록한 EPL로부터의 결과를 리스닝하고 반응하기 위한 Output Adapter 추가 작업이 필요합니다. 이를 위해 Esper는 API 적으로 UpdateListener 인터페이스를 제공합니 다. 주문 이벤트를 예로 보면 UpdateListener를 구현한 MyListener 클래스를 정의합 니다. MyListener 인스턴스를 생성하고 이를 EPL을 등록하고 얻은 EPStatement 인 스턴스에 등록합니다. 이제 EPL의 결과가 발생하면 MyListener의 update() 메소드가 호출됩니다. update() 메소드 내에서 EPL문 select 절에서 정의 값들을 받고 사용 할 수 있습니다. 예제 코드에서는 콘솔로 값을 프린트하고 있습니다. 이러한 방식으로 UpdateListener 인터페이스를 구현하여 다양한 Output Adapter를 구현 할 수 있습니다. RDBMS 저장, HDFS 저장, 이메일/SMS 발송 등등의 어댑터 구현이 가능합니다. Listener 등록하기 public void run() { ... EPStatement statement = epService.getEPAdministrator().createEPL(expres- sion); // Listener 등록하기 MyListener listener = new MyListener();
  360. 364 H3 개발자 컨퍼런스 2012 statement.addListener(listener); } // Output Listener

    public class MyListener implements UpdateListener { public void update(EventBean[] newEvents, EventBean[] oldEvents) { EventBean event = newEvents[0]; System.out.println("itemId=" + event.get("itemId")); System.out.println("cnt=" + event.get("cnt")); } } 구조적인 측면에서 보면 그림처럼 하나의 엔진에 복수 개의 EPL 등록이 가능합니다. 또한 EPL을 표현하는 Statement에 복수개의 Listener 등록이 가능합니다. 각 컴포넌 트들은 각자의 라이프 사이클을 갖고 있습니다. 이것은 OSGi 환경에서 구현할 때 궁 합이 잘 맞는 부분이라 할 수 있습니다. Input Adapter 등록하기 이제 CEP 처리를 위한 모든 것이 준비된 상태입니다. 이제는 누군가가 CEP 엔진으로 이벤트만 전달해주면 모든 시스템의 흐름이 시작됩니다. 바로 맨 마지막 단계로 Input Adapter 등록입니다. 실제로 이벤트가 발생하는 대상으로부터 이벤트를 받아들이고 CEP 엔진으로 전달하는 역할을 하는 것입니다. API 적으로 이벤트를 CEP 엔진으로 전달하는 방법은 다음과 같습니다. CEP 엔진에 해당하는 EPServiceProvider 인스턴 스를 얻고 sendEvent() 메소드 호출합니다. HTTP Input Adapter라면 HTTP 요청을 리스닝하는 HTTP Server가 필요합니다. HTTP Server를 구동하고 인입되는 요청을 파싱하여 이벤트로 변환하고 CEP 엔진으로 전달하도록 개발해야 합니다. 이벤트 전달하기 // CEP 엔진 초기화 Configuration config = new Configuration(); EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider(con- fig);
  361. 365 오픈 소스로 구현하는 Real-time CEP // 이벤트 생성 및

    전달 OrderEvent event = new OrderEvent("shirt", 74.50); epService.getEPRuntime().sendEvent(event); CEP 애플리케이션 개발 주요 포인트 마지막으로 CEP 애플리케이션 구축 시에 고려해야 할 사항들을 정리해보겠습니다. • Runtime 환경 결정 • Zero-downtime 지원 여부 결정 • Runtime시 EPL 업데이트 지원 여부 결정 • Input/Output Adapter 성능 고려 • Event의 타입과 용량 결정 Runtime 환경 결정 운영을 위한 실행 환경을 결정해야 합니다. Java EE 기반과 OSGi 환경 또는 스탠드 얼론 스타일을 선택할 수 있습니다. Zero-downtime 지원 여부 결정 실시간 처리는 지속적으로 이벤트를 처리하고 반응해야 하기 때문에 시스템 재시작 을 해버리면 모든 것이 처음부터 다시 시작하게 됩니다. 요건에 따라 엄격한 zero- downtime 지원이 필요한 경우는 운영 중에 변경 사항을 반영할 수 있는 OSGi 런타임 서버 기반이 대안이 될 수 있습니다. Runtime시 EPL 업데이트 지원 여부 결정 Esper는 내부적으로 모든 컴포넌트들이 생명주기를 가지고 있고 각 컴포넌트간에 등 록/해제를 할 수 있게 되어있습니다. 그러므로 운영 중에 필요에 따라 EPL을 변경하 고 즉시 적용 할 수 있습니다. 시스템 재시작 없이 이러한 동적 업데이트 기능을 지원 할 것인지에 따라서 런타임 환경과 시스템 설계를 해야 합니다.
  362. 366 H3 개발자 컨퍼런스 2012 Input/Output Adapter 성능 고려 CEP

    시스템에서 성능에 직접적으로 영향을 미치는 것이 Adapter입니다. CEP 엔진 이 아무리 고성능 처리가 가능해도 Adapter에서 병목이 일어나면 CEP가 충분히 일 을 할 수가 없습니다. 사실상 이것이 대부분 쉽게 발생하는 케이스입니다. Adapter 영 역에서 고성능이 보장되도록 하는 것이 중요한데 사실 이것이 기술적으로 매우 어렵 습니다. 일반적인 처리가 가능한 Adapter는 개발하기 그렇게 어렵지 않지만 1초에 10 만건, 100만건 받아들일 수 있는 고성능 Adapter 구현은 높은 기술 수준을 필요로 합 니다. 통신 프로토콜 선택 또한 중요합니다. 고성능이 필요하다면 바이너리 통신을 하 는 TCP/IP 서버가 답입니다. HTTP는 비용이 많이 들기 때문에 성능상에 한계가 있습 니다. NIO기반의 non-blocking 모드 통신 구현을 추천합니다. Event의 타입과 용량 결정 이벤트를 어떤 포맷으로 정의하느냐 또한 성능에 영향을 미칩니다. XML또는 Map으 로 정의하는 경우 엔진에서 처리하기 전에 파싱하는 과정에서 비용이 많이 소모됩니 다. 반면, Array이나 POJO 스타일로 정의하면 성능상 최적화를 할 수 있습니다. 또한 Event로 전달되는 데이터 사이즈 또한 성능에 영향을 미칩니다. 사이즈가 클 수록 네 트워크에서 전송될 수 있는 이벤트 수가 줄어들고 처리 성능이 떨어지기 때문에 이벤 트 타입 정의 시 불필요한 이벤트 속성은 정의하지 않는 것이 좋습니다. 마치며 최근 트렌드가 되고 있는 빅데이터 플랫폼에서 특히 실시간 영역이 화두가 되고 있 습니다. 지금까지 함께 본 CEP는 사실 실시간 빅데이터 처리의 핵심 기술입니다. Twitter와 Facebook에서도 최근에는 실시간 분석에 엄청난 투자를 하고 실제 적용 을 통해 새로운 수익을 기대하고 있습니다. 앞으로 지금보다 훨씬 많은 부분에서 실생 활과 밀접하게 실시간 기술들이 활용 될 것입니다. 결국 비즈니스와 수익에 큰 영향을 미치게 될 것입니다. 이를 구현하기 위해서는 Esper CEP와 함께 무한 scalability가 보장되는 Twitter Storm, Apache S4 등의 분산 ESP 기술도 필요하게 될 것입니다. 실시간 CEP와 분산 ESP 그리고 배치 Hadoop을 적절히 통합 및 연계하여 전에 없던 새로운 서비스와 비즈니스의 기회를 제공 할 것으로 기대합니다.
  363. 367 로그 속에 있는 사용자 발자국 들여다 보기 BY DAISY

    들여다 보기 로그(Log)를 어디에 사용하시나요? 시스템 로그와 사용자 로그가 중요한 자료라고 생각하시나요? 개발자가 생각하는 로그는 내가 만든 시스템 운영, Batch job, 서버 Process 등 다양한 부분의 잘 진행되고 있는지를 계속적으로 기록하고 장애와 같은 응급상황에 대처할 때 원인 파악 용으로 사용하시지 않나요? 사실 잘 되고 있을 땐 시 스템 로그에 관심이 없지만, 장애가 났을 때는 맨 처음 보는 것이 로그이지 않을까 합 니다. 여기에서는 시스템로그 이야기가 아닌 서비스를 사용자 행동을 기록하는 사용자로그 에 대해 이야기 하고자 합니다. 장애에 대처하는 로그 보는 법이 아닌 사용자 로그 속 에 어떤 정보가 숨어 있는지, 우리 사용자는 어떤 스타일의 사람들인지 자칫 우리가 감으로만 생각했던 로그 속 사용자들과 이야기를 해볼까 합니다. 로그 속에 있는 사용자 발자국 들여다 보기 데이터지능팀 김남미 [email protected]
  364. 368 H3 개발자 컨퍼런스 2012 가장 간단하게는 수집된 로그를 기준으로

    호출된 API 빈도 수 Check하기부터 서비 스 라이프 타임 분석을 통해 보는 우리서비스 사용자 들의 서비스 사용 패턴들까지 다양하게 분석 할 수 있습니다. [로그 속에 있는 사용자 발자국 들여다보기]에서는 Episode 형식으로 데이터지능팀의 DAISY 프로젝트를 통해 얻게 된 시사점 중심으로 서비스 분석에 대한 내용을 공유합니다. Episode#1. 로그 속 사용자 발자국 찾기 서비스와 사용자는 서로 어떤 관계일까요? 사용자가 서비스를 사용해야 서비스가 살 아 남을 수 있고, 사용자 없는 서비스는 없습니다. 누구나 대박 서비스를 꿈꾸고 있지 만 사용자가 서비스를 어떻게 사용하고 어떤 흔적을 남기는지 알아보고 있으신가요? 서비스 버전 업그레이드에 밀려 로그분석을 소홀하게 하지 않으셨나요? 누구나 서비 스 로그가 중요하다고 생각하지만 로그를 설계하고 수집하고 로그를 분석할 수 있는 로그분석시스템이 없으면 개발자와 기획자들이 사용자 로그를 쉽게 접근하고 사용자 의 행동 패턴을 측정하고 그 결과를 서비스에 적용하기 쉽지 않습니다. 비정형데이터를 수집하여 정형화된 데이터로 만들고 해석하고 특정 패턴을 추출하는 과정이 생각만큼 쉽지도 않고 측정된 결과를 가지고 서비스 개선에 적용하고 적용된 결과 로그를 다시 측정하는 과정을 반복하면서 로그 속에 사용자의 발자국을 찾아내 는 것은 어쩌면 매우 귀찮은 과정이라고 할 수 있습니다. 하지만 로그 수집하고 분석 할 수 있는 시스템이 있고 이를 기반으로 분석할 수 있는 서비스 정보 분석가들이 있 다면 조금은 쉽지 않을까 합니다. 들어가기 전 실제로 사용자 로그 분석을 하기 위해 가장 힘든 과정은 서비스관련 이해관계자들과 의 커뮤니케이션이라고 생각합니다. 서비스를 책임지는 다양한 분야의 의사결정자들 을 이해시키고 분석된 결과를 이해하고 공감하는데 시간이 걸립니다. 서비스정보분석 에 대한 인식은 회사 중역들뿐만 아니라 누구나 중요하다고 생각하지만 정보분석결과 를 기준으로 개선을 하겠다는 부분에는 아직도 적극적이지 않습니다. 정보분석결과를 통해 얻게 되는 개선의 필요성보다 자신의 ‘감’이 더 좋아 보이는 게 사실입니다. 데이 터 분석을 통해 얻게 될 크나큰 가치에 대해 활용을 못하는 것들이 많지만 이러한 과 정이 회사내부에서 정보분석의 가치에 대해 인식하게 되면 서비스 성공을 위한 당연 한 과정이라고 생각할 것입니다. 그 첫걸음이 사용자가 무슨 생각을 하는지 어떤 행동 을 하는지 들여다 보는 것입니다.
  365. 369 로그 속에 있는 사용자 발자국 들여다 보기 BY DAISY

    서비스 분석의 첫걸음 by DAISY DAISY(Data Intelligence System)는 서비스에 대한 수집/분석을 위한 인프라와 서비 스 분석을 하며, 이를 통해 서비스에 필요한 개선사항 도출 및 검증할 수 있는 시스템의 이름입니다. 딱딱한 이름보다는 데이지란 꽃 이름이 주는 다양한 상상 속에 아이디어가 생각나지 않을까요? DAISY는 Hadoop기반의 데이터 저장과 분석을 위한 Hive, 수집을 위한 Kafka로 구 성되어 있습니다. KTH의 서비스인 114전국전화, 아임리얼맛집, 푸딩.투, Playy 서비 스에서 로그(DB, File)수집이 진행되거나 예정되어 있으며, 배치형태의 수집/분석 처 리가 가능하게 완성되어 운용 중입니다. DAISY를 통해 분석된 결과는 서비스에 지속 적으로 제공되고 있으며, 114전국전화의 경우 사용자에게 시간과 요일에 따른 테마 전달을 위해 DAISY 분석 결과를 사용하고 있습니다. 114전국전화 DAISY 기반 분석 Flow DAISY 플랫폼 Layer 구성 DAISY는 현재 계속 진행 중이며, 현재까지 구축 완료되어 운영되고 있는 Layer 내용 입니다.
  366. 370 H3 개발자 컨퍼런스 2012 구분 분야 모듈 설명 Analysis-

    Application 로그 수집 Data Agent 로그 수집 Agent로 실제 로그가 생성되는 원격의 서버에서 로그를 수집하여 Kafka로 전송 배치/실시간 수집 지원 Data Collector Kafka로 부터 로그 데이터를 가져와 HDFS저장 저장과 동시에 Hive에서 데 이터 조회와 분석이 가능 데이터 분석 Apache Hive SQL-like한 HiveQL 문을 이용한 데이터 조회와 분석 기본의 RDBMS 기반 분석을 Hadoop 기반 병렬 분석 구조로 마이그레이션 (Sqoop 활용하여 쉽게 Migration 가능) 신규 분석 Hive기반 분석 방법 제공 Apache Pig Pig Script 문을 이용한 데이터 조회와 분석 데이터 통합 Apache Sqoop 분석 결과를 RDBMS로 저장 RDBMS의 데이터를 실시간으로 HDFS 및 HIVE로 이전할 수 있으며, 반대 의 경우도 가능 Script를 이용하여 자동화 가능 데이터 Import/Export시 발생할 수 있는 다양한 이슈 해결 가능 Visualization RStudio 분석 결과를 차트로 제공 복잡한 차트를 위한 계산과 렌더링 담당 amCharts 분석 결과를 차트로 제공하며 웹 페이지를 통해 제공 OpenAPI Mashup 분석 결과를 Mashup해서 새로운 유용한 정보로 재생산하여 제공 Analysis- Infra 데이터 연계 허브 Kafka Cluster 안정적인 로그 수집을 위한 로그 데이터 Queue이자 유연한 허브 역할 다양한 요건 처리 가능 분산 파일 시스템 Hadoop Cluster 원본 로그 데이터를 저장하고 분석을 위한 MapReduce기반의 병렬 처리 플 랫폼을 제공 시스템 관리 RHQ 운영에 필요한 모든 리소스의 모니터링과 관리 지원 DAISY 시스템에 관한 GUI로써 단일 진입 포인트 역할 HDFS Browser Open Source를 활용한 분석된 데이터 파일 조회를 위한 편리한 HDFS 브 라우저 제공 파일 Upload, Download, 삭제, 이동 기능 제공 DAISY 분석 도구 HIVE 간단 소개(like SQL) Hadoop만 설치하면 빅데이터 수집이 그냥 될 꺼 같은 생각이 들지 않았나요? 빅데이 터 관련하여 갖춰야 하고 운영되어야 할 인프라가 너무나 많습니다. DAISY는 현재 분석과 기초통계를 위해 HIVE Query 기반으로 배치를 생성하고 생성 된 결과를 서비스에 제공합니다. HIVE는 거의 SQL문법과 비슷합니다. 그래서 개발자 분들도 쉽게 접근 할 수 있고, 대용량 데이터 분석을 하는데 알맞습니다. Hive Query와 MySQL Query를 보면 문법이 비슷하다는 것을 알 수 있습니다. 하지 만 깊이 파고 들면 다른 점도 있고 RDBMS가 제공하는 기능 전부를 제공하지 않지만 HIVE는 UDF(User Define Function)를 제공하고, 기본적으로 다양한 함수가 내장되 어 있습니다. HIVE와 MySQL의 기본 Query와 DDL문을 간단 비교해 보았습니다.
  367. 371 로그 속에 있는 사용자 발자국 들여다 보기 BY DAISY

    자세히 내용은 HIVE 튜토리얼 사이트를 참고해주세요. (https://cwiki.apache.org/ confluence/display/Hive/Tutorial) 구분 MySQL HIVE COUNT Select count(A.USER) From DAISY_DB1 A Where A.DATE>=’2012-09-10’ Group by A.USER Order by A.USER desc Select count(A.USER) From DAISY_HDB1 A Where A.DATE>=’2012-09-10’ Group by A.USER Order by A.USER desc Create Table CREATE TABLE ` DAISY_DB1` ( `USER` VARCHAR(20) NOT NULL, `DATE` DATETIME NOT NULL ) COLLATE=’utf8_general_ci’ ENGINE=InnoDB; create table DAISY_HDB1 ( USER string, DATE string, ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘,’ STORED AS TEXTFILE Drop Table drop table DAISY_DB1 drop table  DAISY_HDB1 HIVE Query 예 DAISY 프로젝트는 현재 진행 중입니다. 제가 하고 있는 업무는 주로 서비스분석입 니다. Hadoop을 직접 설치하지 않았고, Data 수집 모듈을 직접 만들지 않았습니 다. DAISY 프로젝트는 각 팀원들의 전문적 역량이 합쳐져 진행 중입니다. 혼자서는 이 모든 것들을 진행할 수 없었겠죠. 서비스분석은 사용자의 행동 패턴을 보는 것부터 가 첫 단계라고 하면 DAISY 프로젝트는 그 첫 단계를 진행 할 수 있는 역할을 합니다. DAISY 가 KTH에서 안착하고 서비스에 필요한 Insight를 지속적으로 제공하고 서비 스와 함께 발전할 수 있기를 바랍니다. Episode#2. 사용자가 말해주는 서비스 라이프 타임 전 아침에 일어나 회사를 가고, 회사에서 일도 열심히 하고 점심도 먹고 회의도 하고 동료들과 차를 마시며 약 8시간 이상의 시간을 회사에 투자하고 있습니다. 출퇴근 시 간을 합치면, 10시간 이상의 시간을 온전히 회사에서 보낸다고 할 수 있습니다. 모든 사람들이 저와 같은 라이프 사이클을 가지고 있을까요? 그래서 생각해 보았습니다. 우리서비스 라이프 타임은 어떨까? 여기서 라이프 타임이란 사용자가 서비스를 사용 하는 시간들에 대한 이야기입니다. 우리서비스인 글로벌 사진 SNS기반의 ‘푸딩.투’ 서 비스와 생활 밀착형 서비스인 “114전국전화”의 서비스 라이프 타임을 예로 들었을 때 서로 완전히 다른 라이프타임그래프를 가집니다.
  368. 372 H3 개발자 컨퍼런스 2012 들어가기 전 잠깐 다른 이야기를

    하자면 서비스 분석 업무를 시작하면서, 분석 아이템 즉 어떤 주 제로 분석을 해야 하나가 가장 큰 고민이었습니다. 처음에는 제가 서비스에 가장 궁 금한 부분을 파헤쳐 보기로 하고 사용자 데이터뿐만 아니라, GA(Google Analytics), KM(KissMetrics), 사용자 로그 등 이것저것 서비스담당자에게 물어보기도 하면서 분 석결과물을 정리하였습니다. 사용자 로그를 기반으로 분석된 결과는 서비스의 기본 적인 사용자 행동 패턴을 분석하고 이를 기반으로 문제점과 개선사항 등을 도출 할 수 있습니다. 혹시 사용자가 서비스를 이렇게 생각하고 있을 것이다. 라고 추측하지 않았 나요? ‘감’보다는 숫자를 통해 얻는 사용자 행동에 대해 믿어 볼 것을 추천합니다. 푸딩.투 서비스의 라이프 타임 분석 푸딩.투에 대해 잠깐 언급하자면, 글로벌 사진 SNS 서비스입니다. 국내에서는 사진기 반 SNS로는 유일하며, 푸딩카메라의 예쁜 필터기능도 갖춰져 있으니 모르시는 분들 은 스마트폰에 설치하시고 어떤 서비스인지 체험해 보시면 이해가 빠르실 거라고 생 각합니다. 푸딩.투에는 사용자가 올린 사진 중에 일정 조건에 충족되는 인기사진을 제공하는 기 능을 서비스 합니다. 인기사진에 선정 된 후 사진에 대한 like, comment, follower 증 가에 대한 자료분석을 통해 인기사진에 선정되면 사용자에게 어떤 영향을 미치는지 조사를 하면서 follower, like, comment가 증가하지 않았던 사용자 그룹에 대해 궁금 했습니다. 그래서 왜 영향도가 없었을까?라는 궁금증을 가지고 재분석을 하였습니다. 처음에는 일정한 패턴이 없는 것 같았는데 분석결과물을 들여다 보면서 제가 하나 간 과했다는 것을 알았습니다. 내가 보고 있는 사용자의 업로드 시간은 내시간과 다른 시 간이다. 즉 Time zone을 기준으로 분석하니 결과적으로 대부분은 새벽 시간대에 인 기사진에 선정된 사용자들이었고, 그때 인기사진에 선정되면 인기사진 선정에 대한 영향도가 미미한 것을 알 수 있었습니다. 푸딩.투 서비스의 라이프 타임 그래프 현재 푸딩.투의 인기사진 서비스의 선정관련 서버의 Batch Time zone은 UTC(Universal Time coordinated) 기준입니다. 글로벌 서비스에서는 몇 개의 Time zone을 고려해야 할까요? 300개 이상 되는 나라의 수도기준으로 모두다 고려해서 서
  369. 373 로그 속에 있는 사용자 발자국 들여다 보기 BY DAISY

    비스 해야 할까요? 너무 어려운 작업입니다. 그래서 사용자가 가장 많은 나라 10개를 선택하여 각 나라별 서비스 사용 시간대를 분석하였습니다. “서울과 말레이시아 서비스 라이프 그래프 비교” 위 두 개의 그래프뿐만 아니라 대부분 나라의 Peak Time은 오후 10시 그리고 Cold Time은 오전 3시부터 7시~8시까지 라는 걸 알 수 있었습니다. 나라별로 푸딩.투 서 비스를 사용하는 시간대는 비슷하다는 것을 알 수 있었습니다.
  370. 374 H3 개발자 컨퍼런스 2012 푸딩.투 서비스 라이프 타임 그래프

    위 그래프는 누구나 쉽게 푸딩.투 서비스를 사용하는 평균 시간대에 대해 알 수 있습 니다. 글로벌 사용자들의 Lifetime은 Peak: 22시, Low:05시로 새벽 5시에는 대부분 수면시간이라는 걸 알 수 있었습니다. 그럼 여기서 한가지 아 ~ 하고 끝낼 것이 아니 라 사용자의 활동 시간대와 비활동 시간대를 구분하여 서비스에서는 사용자에게 언제 반응을 보냈을 때 효과적인지에 대해 생각해 볼 수 있는 지표가 생겼습니다. 글로벌 서비스 푸딩.투 그런데 한가지 문제점은 서비스의 라이프타임 그래프를 도출 한 것 까지는 괜찮은데 그냥 그대로 서버에 적용되어 있는 UTC기준으로만 사용자에게 반응을 하는 것은 문 제가 있다는 것을 알 수 있었습니다. 나라별 24시간 기준이 서로 다르기 때문에 나의 시간과 내 이웃의 시간이 서로 달라서 Time zone에 따른 시간차이 개념을 적용해야 합니다. 예를 들어 UTC기준으로 3시간마다 인기사진을 선택한다고 하면 각 나라별 로 현재가 서비스 사용에 있어 Cold Time인지 Hot Time인지 구분하여 사용자 Time zone에 따른 활동성 구분을 해야 할 것입니다.
  371. 375 로그 속에 있는 사용자 발자국 들여다 보기 BY DAISY

    다음 표를 보면 UTC기준으로 나라별로 시간이 얼마나 차이가 나는지 알 수 있습니다. 적어도 글로벌 서비스로 나아가길 원한다면, 나라별로 잠자는 시간은 피해주는 센스 가 있어야 합니다. UTC ASIA/Seoul LA New York GMT 00 09 17 20 00 03 12 20 23 03 06 15 23 02 06 09 18 02 05 09 12 21 05 08 12 15 00 08 11 15 18 03 11 14 18 21 06 14 17 21 글로벌 서비스가 아니더라도 사용자가 서비스를 사용하는 시간에 대해 의미 부여를 한다는 것은, 기본적으로 우리가 생활하는 평일 아침은 일어나서 회사를 가고 12시면 점심을 먹고 6시 이후엔 퇴근을 하고, 주말엔 가족들과 휴식을 보내는 일정한 패턴이 있듯 서비스가 어떤 요일에 많이 사용하고 어떤 시간대에 사용하는지 알고 있어야 하 겠습니다. 그래서 푸딩.투 서비스에서는 인기사진을 선정할 때 각 나라별 시간과 배치 서버 시간 을 고려하여 활동이 없는 시간대의 사용자 사진을 인기사진에 선정하지 않습니다. 이 런 간단한 규칙으로 서비스의 Detail을 살릴 수 있습니다. 114전국전화 라이프 타임 분석 114전국전화는 생활형 모바일 앱서비스라고 해야 할까요? 전화번호를 모를 때 물어 보던 114서비스의 모바일이라고 생각하셔도 무방합니다. 하지만 아주 유용한 정보들 을 무료로 모바일로 몇번씩 사용해도 절대 전화비가 나가지 않습니다. 거기에 무료통 화도 제공하는 유용한 앱입니다. 114전국전화는 저녁에 치킨이 생각날 때, 또는 중국 집이 생각날 때 배달메뉴에 대해서 내 위치 주변에 있는 상점을 안내 합니다. 또한 병 원 관련하여 굿닥과 제휴하여 응급환자가 생겼을 때나, 근처 병원을 갈 때 사용할 수 있는 생활에 유용한 앱이라고 생각합니다. SNS 형 서비스가 아닌 생활 정보형 모바일 서비스는 어떤 라이프 타임을 갖고 있을까요?
  372. 376 H3 개발자 컨퍼런스 2012 “114전국전화 서비스 요일별 라이프 타임

    그래프” “114전국전화 서비스 요일별 빈도 그래프와 평균 라이프 타임 그래프” 그래프를 보고 어떤 생각을 하셨나요? 114전국전화는 두 번의 Peak를 갖는 서비스 라이프타임을 갖고 있습니다. 토요일의 사용 비율이 조금 올라가는 걸 제외하고는 특 정요일이 아닌 평일에는 비슷한 사용 패턴을 보입니다. 요일에 상관없이 Peak Time 은 동일합니다. 시간대를 보면 점심시간대인 12시와 오후 6시였습니다. 왠지 점심과 저녁을 찾는 건 아닐까요? 라는 생각이 들게 하네요. 기초적인 114서비스의 사용자의 시간대를 살펴보았습니다. 114서비스의 기초적인 타임그래프를 그렸던 이유는 서비 스 개발 PM님이 분석요청을 해주셨고 목적은 사용자에게 상황 별 테마를 제공하고자
  373. 377 로그 속에 있는 사용자 발자국 들여다 보기 BY DAISY

    한다는 것이었습니다. 114전국전화서비스는 검색도 가능하지만, 메인 테마 메뉴들을 선택하면 바로 검색결과들을 볼 수 있습니다. 치킨과 중국집, 피자, 뭐 먹을까, 병원 시즌 테마메뉴까지 첫 화면에 사용자가 쉽게 찾을 수 있게 테마아이콘들이 메인에 배 치되어 있습니다. 그래서 지난 1년간의 로그성 데이터를 분석하고 이를 기준으로 상황 별 즉 조건별 테 마를 제공하는 시스템 개선에 대한 아이디어가 나왔습니다. 조건을 미리 나누고, 나눈 조건별로 통계 결과를 서비스에 지속적으로 제공하고 다양한 통계 결과를 조합하여, 114전국전화를 사용하는 사용자에게 맞는 메뉴를 제공하는 것으로 관리시스템을 개 선하기로 하였습니다. 통계를 기준으로 메뉴를 재배치하면, 사용자에게도 필요한 정 보를 제공하지만 개발자와 기획자에게도 쉽게 의사결정을 내릴 수 있는 편리성을 주 는 것입니다. 하지만 한가지 고민은 조건별 테마에서 조건을 어떻게 분리할 것이냐?였습니다. 그때 고려됐던 것이 위에 서비스 타임그래프였습니다. 사용자가 서비스를 사용하는 타임을 그룹화하고 요일을 주말과 평일, 금요일로 구분 짓고 시즌 즉 계절까지 고려하여 총 18개의 조건을 추출하였습니다. 물론 처음에는 일일이 손으로 분석하고 뜯어보고 해야 하지만, 그 분석결과를 통해 사 용자의 패턴을 찾으면 개선할 아이템에 대한 의사결정을 쉽게 할 수 있습니다. 또한 114전국전화에 경우 메인 테마를 사용자 상황에 맞는 아이템으로 자동화 할 수 있으 니, 인력 Cost가 줄어들고 패턴을 지속적으로 측정하여 변화된 패턴을 재 적용하면 사 용자가 서비스에서 찾고자 하는 것이 무엇인지, 서비스에서 개선해야 할 것이 무엇인 지 찾을 수 있습니다. Episode#3. 통계의 진실 혹은 거짓 얼마 전 빅데이터 관련 기획시리즈 시사기획 ‘창’의 한 예로 나왔던 제약회사의 빅데이 터 분석 이야기를 잠깐 하고자 합니다. 유유제약회사라는 곳에서는 어린아이들이 멍 이 들었을 때 바르는 약을 개발하게 됩니다. 전통적으로 제약회사들은 약을 최종적으 로 사용할 고객의 의견대신 의사와 약국에 잘 팔릴까를 물어봤다고 합니다. 하지만 전 통적 판매전략만으로는 예전만큼 판매가 잘 되지 않는 것에 대해 새로운 방법이 필요 했고 새로운 판로와 경쟁제품을 분석하기 위한 방법으로 26억 건의 멍에 관련된 SNS 및 블로그 데이터를 분석하고 얻은 의외의 결과에 놀라게 됩니다. 멍에 바르는 연고의
  374. 378 H3 개발자 컨퍼런스 2012 가장 큰 경쟁제품은 붙이는 파스도,

    물파스도, 안티푸라미도 아닌 민간요법인 소고기 와 달걀이었다는 것을 알게 되었습니다. 멍들었을 때 한번씩 달걀을 사용하셨던 거 기 억하시나요? 전통적인 제약회사 판매전략으로는 절대 나올 수 없었던 결론이었을 거 라고 생각합니다. 이제껏 고객의 원하는 것을 알고 있다고 착각하고 생각만으로 기획 을 하거나 서비스 기능개선을 하지 않았나요? 데이터 분석을 통해 최종 고객이 어떤 생각과 행동을 하는지 알 수 있습니다. 서비스는 사용자의 패턴을 의무적으로 읽고 사 용자와 서비스가 공감한다면 최종적으로 어떤 것을 사용자에게 제공하면 성공 할 수 있을지에 대한 판단을 할 수 있습니다. 들어가기 전 수집된 데이터에 대한 평균을 내어봅니다. 가령 방문자 수에 대한 전체 평균을 내어보 고 요일별 데이터 평균 시간대별 평균을 내어 봅니다. 전체 평균으로 보이지 않은 사 용자들이 요일별로 시간별로 어떻게 사용하는지 알 수 있습니다. 패턴을 찾아 내면 그 패턴은 유지되고 있는 듯 보이지만 어느 날 패턴에 변화가 있다면, 서비스에서 어떤 Push를 보내거나, 사회적으로 이슈가 있을 수 있습니다. 사용자는 어떤 패턴을 유지 하지만 어떤 이슈에 반응을 하며 패턴이 변화합니다. 114전국전화서비스의 경우에는 평일 어느 저녁에 급격하게 치킨검색어가 올라갔습니다. 이유는 국가대표 축구경기가 있었던 날입니다. 평일 날 갑자기 올라간 치킨검색어가 축구경기와 연관이 있을까?라 고 생각하기가 쉽지 않습니다. 수치 하나를 보고는 쉽지 않지만 데이터 분석을 하게 되면 패턴의 연관성을 발견할 수 있지 않을까요? 평일 어느 날 사용자가 왜 그런 패턴 을 보였는지 진실을 파헤쳐야 할 것입니다. 통계의 진실 혹은 거짓 이번 여름은 유난히 길었던 열대야와 런던 올림픽이 있었습니다. 여름의 긴 열대야와 올림픽은 서비스에 어떤 영향을 주었을까요? 사용자들은 어떤 패턴을 보였을까요? 뉴 스와 같은 매체에서는 연일 열대야로 인해 편의점의 매출과 야식 배달이 늘었다고 하 는데 그와 함께 114전국전화에는 어떤 영향도가 있는지 “114전국전화 서비스와 열대 야와 올림픽에 대한 영향도 분석’을 진행하였습니다. 열대야와 연관이 있다면 열대야 가 언제부터 언제 였는지 알고 있어야 합니다. 기상청 데이터를 참고하여 분석하는데 사용하였습니다.
  375. 379 로그 속에 있는 사용자 발자국 들여다 보기 BY DAISY

    케이웨더 “기상청 과거날씨” 서울 열대야는 기상청에서는 오후 6시 01분부터 다음날 오전 9시까지 최저 기온이 25도 이상을 열 대야라고 합니다. 분석을 위해 조금 열대야 기준을 살짝 낮춰서 최저기온 24도이상 최고기온 30도 이상 으로 정하고 열대야 기간을 7월 21일부터 31일까지를 열대야 기간으로 정하게 되었 습니다. 날씨는 생활과 밀접한 정보입니다. 과거 날씨 데이터를 찾고자 하면 다음 사이트를 참 고 하세요. 기상청: http://www.kma.go.kr/index.jsp 케이웨더: ttp://www.kweather.co.kr/main/index.htm
  376. 380 H3 개발자 컨퍼런스 2012 열대야 영향도 분석을 위해 Daily

    검색추이와 콜 클릭 추이를 7월 한달 동안 그려보았 습니다. 열대야와 관련된 추이가 보이시나요? 아니면 올림픽 관련해서 찾을 수 없었 습니다. 하지만 분석 중에 Peak치는 그래프가 의미하는 것을 찾을 수 있었습니다. 대 표팀 축구경기와 일치하는 패턴을 발견하게 되었죠. 7월 6일은 서비스에 발송한 Push 의 영향이 있었습니다. 생각했던 열대야와 올림픽은 영향도가 없다고 판단했습니다. 다음 그래프에서 보면 열대야 기간과 평일 114전국전화 추이와는 비슷해 보이며 크게 영향도가 없다고 판단했습니다. 올림픽기간도 물론 영향도가 없는 걸로 판단하고 대 표팀 축구경기에 치킨 검색어 영향이 높다는 것에 대해 분석 결과를 알렸습니다. 여기 서 제가 하나 놓친 것은 무엇일까요? 열대야는 그렇다 치고 올림픽 기간을 간과 했습니다. 올림픽 기간이 7월 25일부터 8 월 12일까지였지만 7월 31일까지 그래프를 잘라서 보니 7월 26일부터 그래프가 평균 을 보이기 시작한 부분이 보이지 않았습니다. 요일마다 편차가 있었던 그래프가 일정 수준을 지속적으로 유지하기 시작한 부분을 놓쳐 통계속 진실을 놓치고 다른 결론을 낼 수 있었던 것입니다. 여기서 중요한 것은 데이터에 패턴을 보고자 할 때 놓치지 말아야 할 것들입니다. 일 정한 기간과 분석을 위한 충분한 모수 확보, 그리고 사용자들이 반응하는 사회적 또는
  377. 381 로그 속에 있는 사용자 발자국 들여다 보기 BY DAISY

    환경적 이슈와 서비스이슈입니다. 사회적 이슈는 올림픽, 축구경기와 같은 것이고, 환 경적 이슈는 날씨, 지역적 차이 등, 서비스 이슈는 업데이트, Push, 이벤트 등 다양하 지만 이런 변화에 어떻게 사용자가 반응하는지 발견하고 패턴을 정의하는 것이 중 요합니다. 쉽지는 않지만 최대한 객관적이고 정확하게 패턴을 읽어 내는 것이 중요 합니다. 그래서 올림픽기간을 고려한 영향도 패턴을 다시 그려보았습니다. 원래대로면 7월 한 달 동안 그려졌던 들쑥날쑥 한 그래프 패턴이어야 하지만 올림픽 기간 동안은 일정 수 준을 유지 하였고 서비스를 통해 전화를 한 수치도 평균 이상 증가하였습니다. 114전 국전화 사용자들은 국가대표 스포츠에 반응하는 패턴을 찾을 수 있었습니다. 다음 그 래프는 “KTH ‘114전국전화’, 올림픽 전후 야식 주문량 분석 및 발표”라는 제목으로 보 도자료로 활용되었습니다. 현재 114전국전화는 굿닥과 제휴하여 병원정보를 제공하고 있습니다. 치킨, 중국집 이 1,2위를 다투던 검색어 순위에서 병원정보가 더 풍부해지면서 검색어 1위를 할 때 도 있습니다. 이 경우 질좋은 병원정보가 서비스에서 제공하였기에 사용자는 정보에 만족한 결과를 통해 변화된 패턴을 보이는 것입니다. 사용자의 행동 패턴을 발견하는 것도 중요하지만 서비스의 변화에 따라 사용자의 행동이 긍정적인지 아닌지도 패턴을 보고 판단할 수 있지만, 조심해야 할 것은 사용자 패턴이 정확한 것인지 다각적으로 검증하고 판단해야 합니다.
  378. 382 H3 개발자 컨퍼런스 2012 통계 주의사항 하나. 허수 주의

    전체 평균에 영향을 주는 허수 발견 무심코 생각했을 때 는 우리 서비스가 평 일은 화요일에 많은 사용량 평균을 보이 는구나 라고 생각할 수 있습니다. 하지만 대부분 사람 들의 평일은 화요일 이라고 달라 지지 않 습니다. 화요일날 어떤 검색 어가 많은지 봤더니 패스트푸드에 대한 검색어가 많았는데 6만건 이상이 들어 오면서 평균에 영향을 주고 있었습니다. 허수 발견 화요일 그래프 가 왜 다른지 파헤쳐 보니, 화요일 어느 저 녁 6만 건 이상 의 파파이스 검 색어가 1분 안 에 검색된걸 알 수 있었습니다. 서비스에서 Test 시뮬레이터를 돌렸는데 발견하지 못했다면, 아마도 114전국전화는 화요일 패스트푸드를 찾는 고객이 많다. 이렇게 결론이 났을 겁니다. A. 허수를 생각하지 못했던 그래프 B. 허수를 제외한 그래프
  379. 383 로그 속에 있는 사용자 발자국 들여다 보기 BY DAISY

    평균이 생각했던 것보다 높거나 다른 인자들의 수치와 비교했을 때 다른 점을 발견한 다면 ‘왜’ 인지 찾아 보세요. 여러 요인의 평균을 패턴을 가지고 있으면 때로는 허수를 찾기도 하고, 서비스를 모니 터링 하며 서비스의 이상유무를 판단할 수 있는 척도가 되기도 합니다. 두 번째. 그래프의 함정 눈속임 동일한 데이터에 대한 상반된 그래프의 결과를 어떻게 해석할까요? 다음 두 그래프는 6개월 동안 창출된 이익을 월별로 정리한 그래프입니다. A그래프를 참고하면 10월 제 외하고는 급격하게 증가하는 것처럼 보이지만, B그래프는 6개월 동안 일정 수준을 유 지하고 있는 것으로 보입니다. 왜 같은 데이터를 그래프로 그렸는데 다른 결론을 유 도할 까요? 그 답은 Y축 범위에 있습니다. A형의 그래프는 수직축의 값이 0이 아닌 2부터 시작 하고 있습니다. 최소값으로 시작하여 수직 축의 값의 범위를 늘려가므 로 언뜻 보기에는 엄청난 이익이 매월 증가하고 있는 것으로 보이고 있습니다. B형 그래프는 이익의 변 화가 월별로 거의 비슷하 다고 보여집니다. 매월 발생하는 이익의 수 직축을 0을 기준으로 하였 기 때문에 A형 그래프와 다 르다는 것을 알 수 있습니다.
  380. 384 H3 개발자 컨퍼런스 2012 위 그래프는 엑셀에서 간단하게 그려봤습니다.

    엑셀은 스스로 판단하고 최적의 그래 프를 그려주지 않습니다. 그래서 편리하지만 때로는 눈을 속이기도 한다는 것을 이해 해 주셨으면 합니다. 우리가 분석하고자 하는 데이터는 업무와 서비스에 맞춰 그래프 를 선택하고, 데이터가 효율적인 방식으로 표현되도록 만들고, 원하는 메시지가 전달 되도록 만드는 것은 분석하는 사람 본인이겠습니다. 인용: Head First Statistics (출판사: O’REILLY) 밖에서 보기 이쯤에서 위 내용에 대해 마무리를 하고자 합니다. 사실 데이터 분석 업무를 정식으 로 시작한지 얼마 되지 않아서, 전문적인 이야기 보다는 하면서 느꼈던 부분에 대해 이야기 했습니다. 좀더 업무의 전문성을 찾게 되면 데이터분석에 대해 좀더 잘난 척 을 할 수 있지 않을까 생각합니다. 로그를 들여다보며 사용자의 행동 패턴에 관심을 가졌다면 최대한 밖에서 결론을 내 는 것을 추천합니다. 밖에서 결론을 낸다는 것은 분석결론을 최대한 객관적인 결론을 내어야 데이터 분석자체가 가치가 있다고 할 수 있습니다. 때로는 서비스 문제점을 지적하는 것으로부터 시작할 수 있습니다. 그래서 제가 생각하는 서비스 분석 업무는 서비스팀이 아닌 별도의 팀으로 존재해야 한다고 생각합니다. 서비스를 최대한으로 객관적으로 볼 수 있어야 하기 때문에 회사내부에서 분석업무의 독립성이 유지되어 야 한다고 생각합니다. 마무리 의미 전달 통계는 흩어져 있는 데이터로부터 의미를 찾아냅니다. 복잡한 것을 간단하게 만들고, 그 안에서 어떤 일이 벌어지고 있는지 파악할 수 있습니다. 하지만 숫자로 나열했을 때 뭐가 뭔지 모르는 경우가 많은데 그것을 시각화해서 다른 사람들에게 전달할 필요 가 있습니다. 핵심 접근 많은 수들 사이에서 일정한 패턴이나 흐름을 파악하기는 어렵습니다. 큰 그림을 파 악하려고 할 때 평균을 구하는 것이 할 일의 첫 단계인 경우가 많습니다. 평균을 알면 많은 데이터들의 대표적인 값이 무엇인지 쉽게 파악할 수 있고 이를 토대로 의사결정 을 할 수 있습니다.
  381. 385 로그 속에 있는 사용자 발자국 들여다 보기 BY DAISY

    불확실성 1분 후에 갑자기 어떤 일이 일어날지 정확히 알 수 없습니다. 때로는 1분 후에 손으로 물컵을 쳐서 책상 위 노트북에 손상을 입힐 수 도 있지만, 서비스에 대한 사용자 행동 패턴을 알고 있다는 것은 사용자들이 1분 후에 어떤 행동을 할 것인지 예측하고 그렇 게 행동을 할 가능성이 높다는 것을 알 수 있습니다. 사용자들이 어떤 순간에 어떤 행 동을 할지 아는 것은 정보에 기초해 있기 때문에 불확실성에 대한 해답이 될 수 있습 니다. 도전하기 마지막으로 요즘 화두인 빅데이터에 대해 잠깐 언급하고 싶네요? Hadoop전문가 또 는 데이터과학자 어떤 것에 도전 하고 싶으시다면 Hadoop이야기는 나오지 않지만 빅 데이터 관련 동영상 두 편을 추천합니다. 분석의 의미라고 할까요? 왜 해야 할까?에 대한 개념을 가질 수 있습니다. • 시사기획 창 ‘빅데이터, 세상을 바꾸다’ http://news.kbs.co.kr/news/actions/VodPlayerAction?type=2&cmd=showMP4& vod_info=D%7C10%7C/ssam/2012/01/31/10.mp4%7CN%7C%7CF%7C10%7C/ ssam/2012/01/31/1000k/10.mp4%7CN&news_code=2428163 • 시사기획 창 ‘빅 데이터, 비즈니스를 바꾸다’ http://news.kbs.co.kr/news/actions/VodPlayerAction?type=2&cmd=showMP4&v od_info=D%7C10%7C/ssam/2012/09/11/10.mp4%7CN%7C%7CF%7C10%7C/ ssam/2012/09/11/1000k/10.mp4%7CN&news_code=2534149 분석의 다른 쪽 이야기 제 이야기를 잠깐 할까 합니다. 저는 지리학과 출신이고 처음 시작을 GIS로 시작하였 습니다. GIS전문과정에서 “대구지역의 바람길 분석”이라는 공간분석관련 프로젝트 를 시작하여, 첫 직장인GIS전문회사에도 “NOAA 위성영상을 통한 광역가뭄분석”, 홍 수범람예측분석 등 다양한 공간분석에 대한 프로젝트를 수행하였습니다. 그래서 말을 하면 GIS개발자이며, 주로 공간분석에 관련된 업무가 많았고 모든 공간이 포함된 정 보에 주목하고 공간적 관점에 조금은 많이 치우쳐 있습니다. 현재 KTH에서는 개발자라고 하기엔 뭔가 부족하고 약간 애매해졌다고 할까요? 그래 서 떠듬떠듬 코딩을 한다고 개발 잘하냐고 물으면? “…………….”요렇게 애매하다고
  382. 386 H3 개발자 컨퍼런스 2012 할 수 있지만, Client개발자였고 Visual

    Studio로 개발하던 제가 Linux명령어를 외워 가며 서버에서 Batch를 실행하리라곤 KTH에 들어와서도 예상하지 못했습니다. 그래 서 제가 요건 전문분야라고 이야기 할 수 있는 공간분석 이야기를 잠깐 할까 합니다. 또 다른 분석: 공간분석(Spatial Analysis) GIS쪽에서는 ESRI의 Jack Danger mond CEO를 MS의 빌게이츠와 같이 평가합니다. 전세계 60%정도를 ESRI 社의 Arc제품을 상용합니다. GIS의 꽃 은 공간분석이다 라고 Jack 사장이 이 야기 합니다. 인상 좋은 옆집 할아버지 같죠! 그래서 시작했던 건 아니지만 GIS시작 을 Arc와 함께 했고, Spatial Analysis를 통해 다양한 분석을 할 수 있었습니다. 처음 GIS회사를 들어가서 시작한 공간분석작업에 대한 애착은 현재도 여전합니다. 우리나라의 경우 종이지도에 전자지도로 바뀌게 시작한지 얼마나 되었을까요? 1995 년부터 국가에서 GIS의 필요성이 대두되며 지자체와 공공기관 중심으로 전산화 작업 이 시작되었습니다. 현재는 전 국토가 디지털 정보로 저장되어 있지만 20년이 안 되는 시간 동안 GIS산업도 크게 성장하고 발전하게 되었습니다. 하지만 여전히 지적도와 같은 경우에는 일제시대부터 작성된 종이지도를 그대로 전산화하여 실측에 대한 이슈 가 아직 존재합니다. 20년 전에는 여행가는 데 필수적으로 종이지도가 필요했습니다. 그런데 GIS는 종이지도를 전산화하는 작업을 의미하지 않습니다. 공간상의 정보를 의 미하고 이를 기반으로 과거정보와 현재정보를 융합하여 미래정보를 예측하기도 하고, 재난정보를 위해 유용하게 사용됩니다. 가령 홍수, 지진, 산불, 해일 등에 대한 피해사 항 분석 또는 예측분석을 합니다. 미국이나 해외의 경우엔 GIS분석이 적극적으로 사 용되지만 우리나라는 아직 미국의 FEMA정도의 수준은 아니니 좀더 발전하기를 진심 으로 바랍니다. 그럼 여기서부터 공간분석이야기를 소개 해볼까요?
  383. 387 로그 속에 있는 사용자 발자국 들여다 보기 BY DAISY

    공간분석을 정식으로 하면 어려운 용어의 나열이어서 생략하고 분석한 사례 이야기를 통해 공간분석에 대한 흥미유발 정도만 하고자 합니다. 우리회사 ‘아임IN’ 에 대한 공간분석이야기입니다. 먼저 발도장 위치정보로만 만들어본 서울 지도와 한반도 지도 한번 구경할까요? 첫 번째 그림은 발도장 X,Y 좌표를 디스플레이한 결과입니다. 옆에 윤 곽선은 서울지역경계선입니다. 아임IN 발도장이 서울을 뒤덮고 있 습니다. 좀더 밝게 보이는 곳이 강 남일대와 명동일대입니다. 아임IN 발도장이 만들어 낸 한반도 지도에요. 서울 및 광역시 위주로 점들이 뭉쳐 있는 게 보이시나요? 이렇게 보면 대충 어디에 발도장을 많이 찍는구나 라고 감이 오시나요? 그런데 정확하게 어느 지역에 발도장 밀도가 가장 높은지 이야기 해줘! 라고 하면, 면 적 2Km* 2km 기준으로 이야기 해줘 이렇게 구체적으로 물어본다면 명확히 답변 가 능할까요? 그래서 정확한 답변을 위해 발도장 Point를 기준으로 X,Y좌표만 가지고 밀도분석을 수행하였습니다. 발도장 찍은 빈도 가중치는 주지 않았습니다.
  384. 388 H3 개발자 컨퍼런스 2012 뭐가 보이시나요? 위에 발도장 Point로

    만들어 논 지도와 별반 다른 게 없어 보이시나요? 하지만 좀 다릅니다. 요거는 1km*1km격자에 몇 개의 발 도장을 포함하고 있는지 알고 있는 GRID 파일입니다. 이제 공간분석을 할 수 있는 발도장 밀도 데이터 하나가 만들어 졌습니다. 발도장 밀도 GRID 파일을 범례마다 색깔을 달리하 여 그림처럼 디스플레이 합니다. 그럼 우리나라 지역에서 발도장이 하나도 없는 녹 색지역이 눈에 보입니다. 여기는 휴전선 일대와 산 악지역으로 이루어 져 있 는 것을 알 수 있습니다. 그럼 여기서 가장 많은 밀도지역을 어떻게 찾아 보면 될까요? 아직도 찾기 힘듭니다. 한번 더 가공을 해야 합니다. 값에 범위를 주고 범위에 따라 값을 재정의 하면 재정의 된 값을 기준으로 한번 찾아 보겠습니다.
  385. 389 로그 속에 있는 사용자 발자국 들여다 보기 BY DAISY

    밀도 값을 기반으로 Reclassification을 수행합니다. 기존 데이터범위 값을 일정 범위 별로 값을 재정의 하는 것입니다. 1에서 20까지 의 값이 설정되었습니다. 요걸 가지고 정확한 지역을 뽑기 위해서는 어떤 분석이 남았을까요? 상위 값 즉 값이 20인 지역만 추출하거나 반대로 발도장이 10개 이하인 2이하인 값만 추출할 수 있는 데이터 구조가 되었습니다. 일단 서울지역을 한번 펼쳐 보았습니다. 확인해볼까요?
  386. 390 H3 개발자 컨퍼런스 2012 1㎢ 격자가 동일한 값들끼리 뭉쳐

    놓았습니다. 서울지역이 전체가 높은 값을 갖고 있 지 않습니다. 20이라는 숫자가 보이는 곳이 보이시나요? 여기에 행정동 경계를 올려 서 비교하면 서울지역의 어느 지역 발도장 밀도가 높은 지역인지 정확히 알 수 있습니 다. 녹색으로 보이는 곳은 산이 아니라 3의 값을 가지고 있고 발도장 수는 100개 이상 정도입니다. 서울지역을 1㎢ 격자의 면적으로 비교해보면 발도장이 어디는 부족하고 어디에 밀집되어 있는지 알 수 있습니다. 이러한 분석을 통해 서비스에서는 사용자의 위치가 현재 20에 위치해 있거나 1에 위치해 있을 때 다른 추천을 해줘야 하겠죠? 이렇게 발도장 밀도를 기준으로 분류를 했는데 서비스에 써먹기 위해서는 좀더 작업 을 해야 합니다. 일단 만들어 논 Data는 Shape형태입니다. 공간정보와 속성정보가 같이 있는 3개의 파일이 기본적으로 있어야 하는 파일입니다. 사용자 위치 X,Y 가 들 어 왔을 때 검색을 통해 현재 밀도등급이 높은 지역인지 아닌지 판단해서 발도장 리스 트를 다르게 가져옵니다. ** 아래 구성도와 같이 PostGIS와 PHP로 구성하여 Prototype을 구성해서 테스트 진행 해보았습니다. PostGIS는 꽤나 안정적이고 다양한 공간함수를 포함하고 있어 MySQL로 감당하기 힘든 위치 분석을 간단히 제공합니다. 속도도 일단 비교 안될 만 큼 빠릅니다. 공간분석도 마찬가지로 서비스 개선의 요소로써 사용될 수 있습니다. 하지만 서비스 기획자와 개발자가 아인IN밀도 등급도를 좌표체계라는 말을 들먹이며, 공부하고 적용 하기엔 사실 힘들다고 생각됩니다. 주변에 GIS개발자가 찾아보면 있습니다. 그때는 GIS를 공부하는 것보다는 도움을 요청하는 게 조금 빠를 수 있습니다. 여기까지 아임 IN서비스의 발도장을 기준으로 만들어 본 분석내용 공유는 마무리하겠습니다.
  387. 391 로그 속에 있는 사용자 발자국 들여다 보기 BY DAISY

    제가 GIS회사에 다닐 때 만들어본 분석 예제 몇 가지만 아래 잠깐씩 공유하고 마치겠 습니다. 지형분석의 기본 DEM이라고 들어 보셨나요? Data Elevation Model이란 뜻으로 지표면의 높이를 의 미합니다. 보통공간분석이라고 하면 기본적으로 위치기반의 분석을 하는데 정통적인 지형분석을 위해서는 DEM과 같은 격자형(GRID) 모델을 사용하고 격자형 파일들을 중첩하여 사용합니다. 위에서 잠깐 언급한 바람길 분석이나 홍수범람 예측을 만들 때 주로 사용하는 공간분석의 기본 데이터 들입니다. 등고선이라고 들어 보셨을 겁니다. 지도가 전산화 되면서 공간분석을 할 수 있게 되었습니다. 다음 그림처럼 데이터변환 을 통해 까맣게 보이는 DEM자료를 가지고 홍수예측분석을 하는 기본자료로 활용됩 니다. DEM을 만드는 과정도 단순하지 않습니다. 등고선과 표고의 높이값을 기준으로 삼각망 TIN으로 변환하고 이를 다시 GRID로 변화하여 DEM작성합니다. DEM을 기반으로 홍수가 어느 지역에 발생했을 때 얼마나 잠길지 예측분석을 하기 도 합니다. 예를 들어 저수지가 홍수로 범람했을 때 주변이 어디까지 잠길지 계산합니 다. 물은 절대적으로 거슬러 올라갈 수 없죠. 즉 높은 곳에서 낮은 곳으로 흘러가기 때 문에 물에 양이 예측이 되면 계산이 됩니다. 다음 그림은 물에 양과 DEM과 중첩분석 후 최종 침수되는 높이 값이 얼마인지 알려주는 그림입니다.
  388. 392 H3 개발자 컨퍼런스 2012 하천이 흐르는 방향에 대한 분석도

    DEM을 통해 가능합니다. 이런 분석은 하천관리 와 하천지류가 포함하고 있는 물의 양 유역분석을 하기 위해 사용되는 분석들입니다. Hydro DEM은 하천 분석하기 위해 수계 데이터를 DEM에 재입력하는 과정을 거쳐 만 든 DEM입니다. 물에 흐름에 대한 결과값을 위에 로직에 따라 재정의 할 수 있고 각 격자에 값에 따라 어떤 방향으로 흘러갈지 알 수 있게 됩니다. 이런 종류의 데이터들은 농촌공사와 같이 저수지 유량관리를 통해 가뭄시 효율적인 대응을 하기 위해 사용되는 기본 데이터 들 입니다.
  389. 393 로그 속에 있는 사용자 발자국 들여다 보기 BY DAISY

    위 Hydro 분석을 거쳐 옆 그림처럼 하 천이 지류마다 유역을 지정해주고 ID를 부여하여 시스템화 하고 정보관리를 합 니다. 농촌공사와 같은 경우 수리시설물과 분 석데이터를 매칭하여 정확한 관리를 위 해 시스템 개발을 하기도 합니다. 공간분석에 대한 이야기는 여기까지 하고 다음 번 공유할 수 있는 기회가 있다면 정식 으로 진행하겠습니다. 긴 이야기 읽어 주셔서 감사합니다.
  390. 395 로그 속에 있는 사용자 발자국 들여다 보기 BY DAISY

    01 _ AMAZON RDS에 서비스 런칭 이후, 빛과 그림자 – 성동찬 02 _ 오픈 소스의 또 다른 진영, MYSQL 쌍둥이 형제 MARIA DB – 성동찬 03 _ 하이브리드 앱의 스크롤 성능 개선하기 – 김남훈 04 _ ANDROID에서 SQLITE를 이용한 반경 내의 위치기반 정보 QUERY – 홍성훈 05 _ 메모리 기반 RDBMS, MEMSQL을 알아봅시다. – 성동찬 06 _ 연령 낮을수록 ‘스크린샷’, 높을수록 ‘앱설명’ 보고 앱 선택 – 이경은 07 _ 앱 설치 시 사용자들의 리뷰 영향력 높아져 – 김일화 08 _ 앱스토어! BLUE OCEAN인가? BLOOD OCEAN인가? – 김일화 09 _ 위대한 PRODUCT LEADER 되기 – 하용호 KTH 개발자 블로그 BEST
  391. 396 KTH 개발자 블로그 베스트 지난 해 말 글로벌 서비스를

    겨냥하여 Amazon 가상 플랫폼 상에 인증 서비스를 오픈 하였고, 올해 초에는 푸딩.투 서비스 또한 런칭하여 서비스 중에 있습니다. 그리고 서 비스를 위한 데이터 저장소로는 아마존에서 제공하는 가상 관계형 DBMS인 Aamzon RDS를 채택하였습니다. 처음에는 사전 지식이 전혀 없이 영문 매뉴얼만을 참고하고 직접 부딪혀서 적응하는 상황이 대부분이었지만, 서비스 오픈 후 운영을 하면서 그에 못지 않게 좋은 경험을 축적할 수 있는 기회였습니다. 이 장에서는 Amazon RDS를 사용하면서 겪었던 경험에 대해 공유하고자 합니다. Amazon RDS에 서비스 런칭 이후, 빛과 그림자 성동찬
  392. 397 Amazon RDS에 서비스 런칭 이후, 빛과 그림자 Amazon RDS에서

    현재 사용 가능한 DB 엔진은 MySQL, Oracle, SQL Server 세 가 지가 있습니다. 원하는 지역에 DB 인스턴스를 생성하고, 접근 제어만 설정하면 10분 안에 간단하게 새로운 DB 인스턴스를 사용할 수 있습니다. DBMS 자체가 가상 형상 으로만 동작하는 것일 뿐 다른 가상화 플랫폼과 구조는 동일합니다. 설명하기에 앞서서 Amazon RDS에 대한 특성을 간단하게 살펴보도록 하겠습니다. Amazon RDS 특징 Virtual Database Instance Amazon RDS는 Virtual Database Instance입니다. DBMS는 데이터를 처리하는 미 들웨어이고, 미들웨어는 OS 기반 위에서 동작합니다. 일반적인 상황이라면 OS에 접 근하여 그에 맞게 DBMS를 설치하고, 관련 파라메터도 정의를 해야만 하지만, 모든 것이 웹 콘솔 상에서 간단하게 처리합니다. 웹 콘솔에서 “Launch DB Instance” 버튼을 누르면 하단과 같은 레이어가 나오는데, 사용할 DBMS를 선택하고 DB 인스턴스 정보 몇 가지만 입력하여 생성을 하면 즉시 사용이 가능합니다.
  393. 398 KTH 개발자 블로그 베스트 MySQL, Oracle, SQL Server 등

    일반적으로 많이 사용하는 DBMS를 사용할 수 있 습니다. 가상 DB 인스턴스이기 때문에 직접적으로 OS에 접근하여 조작은 불가합니다. DB 튜 닝을 위해 파라메터를 변경하는 경우에도 직접적으로는 불가하며, rds-cli라는 클라이 언트 툴을 사용해서 조작해야 합니다. 다음은 Slow Log를 사용할 수 있도록 설정하는 간단한 샘플입니다. $ rds-modify-db-parameter-group testDB \ --region us-west-1 \ --parameters "name=slow_query_log, value=on, method=immediate" 이러한 접근은 얼뜻 불편할 수도 있습니다. 하지만 모든 OS관련된 사항들을 RDS 클 라이언트 API Call을 통해서 이루어지고, 특별히 OS에 대해서 관리할 사항 또한 없기 때문에 상당 부분 DB 운영 이슈가 사라지게 되는 것이죠. Multi-AZ (Availablity Zone) Amazon RDS에서 High Availablity를 구현하는 대표적인 방법입니다. 가용 Zone 에 두 개의 인스턴스(기본 인스턴스/예비 인스턴스)를 띄우고, 기본 인스턴스DB에 서 데이터 변경 즉시 동기화합니다. Replication이 비동기적인 방식으로 동작하지만, Multi-AZ은 동기화 방식이라는 점에서 큰 차이가 있습니다. MySQL Replication의 고질적인 문제인 실시간 데이터 동기화 지연 문제와, 장애 시 빠른 복구가 어려운 문 제를 단번에 해결할 수 있는 방안이죠. 하지만 꼭 기억해야할 몇 가지 사항이 있습니다. 첫째 Multi-AZ 기능은 High Availablity 구현을 위한 방법입니 다. 예비 인스턴스는 단지 기본 인 스턴스에서 일어난 이벤트를 적용 할 뿐 Read/Write 트래픽을 분산 하지 않습니다. Read는 바로 다음 에 설명할 Replication으로 어느정 도 분산이 가능하나, Write은 데이터 Sharding 기법 외에는 방법이 없습니다.
  394. 399 Amazon RDS에 서비스 런칭 이후, 빛과 그림자 둘째 Multi-AZ은

    같은 Zone에서만 구성 가능 합니다. Amazon RDS에는 Region과 Zone 개념이 있습니다. Region은 “미국 서부 캘리포니아”, “일본”, “싱가폴” 등과 같 이 큰 대륙 혹은 지역을 의미합니다. 그리고 대륙 간에는 인터넷 라인으로 연결되어 있습니다. Region 안에는 여러 개의 Zone이 있습니다. Zone은 Region에 포함된 몇 개의 IDC 센터입니다. 각 Zone은 전용선으로 연결되어 있으며, 지역적으로 수십 혹은 수백 킬로미터 떨어져 있습니다. Zone 사이에는 전용선으로 데이터 전송 속도 및 신뢰성이 보장되기 때문에, 기본 인 스턴스 반영 시 즉각적인 동기화가 가능합니다. 그러나 Region는 상황이 다릅니다. 인터넷 망으로 연결되어 있기 때문에, 데이터 동기화가 즉시 불가한 것이죠. Data Replication Amazon RDS에서 Multi-AZ이 HA 구현을 위한 방법이라면, DB Scale-Out을 위한 방안으로는 전통적인 MySQL의 복제 기술, 즉 MySQL Replication을 제공합니다. 슬 레이브 DB를 추가하는 방법은 간단합니다. 웹 콘솔에서 “Create Read Replica” 버튼 을 누르고 몇 가지 정보만 넣으면 됩니다. 인스턴스에서는 최대 5개의 복제 서버를 가질 수 있으며, 데이터는 MySQL Replication과 동일하게 “’비동기로 데이터 일관성이 유지”됩니다. 즉, 언제든지 마스 터/슬레이브 간 데이터 동기화 지연 현상이 발생할 수 있습니다.
  395. 400 KTH 개발자 블로그 베스트 Amazon RDS 장점 No Maintenance

    가상 DB 인스턴스인만큼, 설치/설정를 비롯하뎌 대부분의 DB 시스템적인 관리 이슈 를 크게 신경쓰지 않아도 됩니다. 비용만 지불하면, 원하는 사이징에 해당하는 DB 인 스턴스를 바로 할당받을 수 있으며, Amazon RDS에 최적화된 환경을 제공합니다. Amazon RDS를 사용할 때 DBA에게 필요한 항목은 “시스템 역량”보다는 오히려 효 과적인 “SQL을 작성하는 역량”입니다. MySQL의 특성을 정확하게 파악하고, 특성에 맞게 데이터 설계를 하며, 최적화된 쿼리로 데이터를 질의하는 역량이 전체적인 DB 성능에 가장 중요한 요소인 것이죠. 물론 물리 서버에서도 마찬가지지만, 적어도 물리 서버에서는 디스크를 SSD로 고도화할 수도 있고, 네트워크 카드를 재배치하는 시스 템 레벨의 튜닝이 가능합니다. 백업, 복구, 모니터링 등 DB 운영에 중요한 요소 대부분 쉽게 처리할 수 있는 것이죠. 매일 새벽에 자동으로 데이터가 백업되며, 해당 백업 본을 사용하여 장애시 쉽게 데이 터를 복원할 수 있습니다. OS 상에서 굳이 DB를 재구성하는 작업은 필요 없으며, 원 하는 시간만 웹 콘솔에서 정의를 해주면, 해당 시점의 DB 인스턴스가 신규로 구성이 되는 것이죠. Easy to Use 서비스를 위한 신규 DB 준비는 참으로 쉽습니다. 장비 구매 및 소프트웨어 라이선스 정책을 알아보기 위해 여기저기 찾아볼 필요가 없습니다. 단지 웹 콘솔에서 “Launch DB Instance” 버튼만 누르고 몇 가지 정보만 입력하면, 서비스를 위한 DBMS를 10분 안에 준비할 수 있습니다. 그리고 생성한 인스턴스의 비용만 지불하면 모든 것이 해결 됩니다. 물론 세세한 파라메터 변경을 위해서는 RDS 클라이언트를 통해서 변경할 수 는 있으나, 그 외 사항은 웹 콘솔에서 해결할 수 있습니다. Auto Failover 앞서서 설명드렸던 Multi-AZ 기능을 사용한다면, 특정 IDC에서 정전 혹은 장애가 발 생 시에도 서비스에는 큰 영향이 없습니다. 이미 수십 킬로미터 떨어진 독립된 IDC 위 에서 구동 중인 예비 DB 인스턴스에서 서비스를 바로 재계하기 때문이죠.
  396. 401 Amazon RDS에 서비스 런칭 이후, 빛과 그림자 MySQL Replication으로

    Active-Standby를 구현하였다면, 데이터 Corruption과 Replication 동기화 오류와 같은 상황에 대비해야 합니다. Multi-AZ에서는 데이터 변 경 시 바로 예비 DB 인스턴스에도 바로 데이터를 동기화하기 때문에, 데이터 유실 없 이 전체적으로 서비스에는 영향이 거의 없는 것입니다. Amazon RDS 그림자 하지만 Amazon RDS가 무조건 좋은 방안은 아닙니다. 클라우드에서 서비스하는 것 이 최고의 대안처럼 보이지만, 실제로 들여다보면 여러가지 안좋은 요소와 제약 사항 들이 있습니다. Amazon RDS는 결코 저렴하지 않음 클라우드에서 서비스를 한다고 무조건 가격이 저렴하지 않습니다. 운영 이슈가 거의 없어지는 면을 보면 효율적인 듯 보이지만, 실제 가격을 따져보면 상당히 비용이 발생 하는 것이죠. 위 표는 Amazon RDS 싱글 인스턴스 가격 정책입니다. 라지DB 인스턴스를 기준으 로 하면, 한단 30일 기준 327.6달러 비용이 소요되죠. 참고로 라지DB 인스턴스는 7.5GB 메모리에 2-코어(가상 코어 포함 시 4-코어) 스펙입니다. 고가용성을 위해 Multi-AZ 사용 시 위 2배 비용, 즉 매월 655.2달러가 소요됩니다.
  397. 402 KTH 개발자 블로그 베스트 여기까지는 오직 스토리지를 제외한 서버

    가격만을 책정한 것입니다. 스토리지는 별 도로 계산을 해야하며 가격 정책은 다음과 같습니다. 싱글 인스턴스 기준이며, Multi-AZ 사용 시 마찬가지로 2배 비용이 소요됩니다. Amazon RDS에서 예약 인스턴스라는 저렴한 금액을 일시불로 결제할 수 있는 옵션 이 있기는 하지만, 결과적으로 국내 IDC에 구성하는 것보다 비용이 획기적으로 저렴 하지는 않습니다. Amazon RDS 성능은 물리 서버의 30% 정도일 뿐! Amazon RDS에서 DB 테이블 재구성하는 이슈가 있어서 물리 장비 테스트 후 Amazon RDS에 적용한 적이 있습니다. 사용하고 있는 Amazon RDS 인스턴스가 성 능이 나쁘지 않은만큼 물리 장비 대비 크게 뒤쳐지지 않을 것이라고 예상을 했습니다. 그러나, 실제 적용해본 결과, 물리 서버 대비 30%정도 퍼포먼스만 발휘하는 결과가 나왔습니다. 로컬 물리 DB에서 15분 걸리던 작업이, Amazon RDS에서는 45분 이상 소요가 된 사례가 있습니다. 예상 시간보다 상당히 오래 걸려서 크게 당황을 했었죠. 무엇보다 MySQL은 단일 쓰레드에서 Nested Loop 방식으로 SQL을 처리하기 때문 에, CPU의 성능이 전체적인 DB 퍼포먼스에 직접적인 영향을 미칩니다. 병렬 처리가 없다는 MySQL 특성이 Amazon RDS에서 가장 큰 병목이 되는 것입니다. Amazon RDS 만의 제약사항 Amazon RDS만이 가지는 제약 사항도 상당히 있습니다. Amazon RDS 사용 시 사전 에 분명히 인지하고 있어야하는 사항들입니다. 단순 Master/Slave 형태로만 리플리케이션을 구성 가능 효과적인 DB 사용을 위해 일부 사용하는 링 구조, 피라미드 구조 그리고 다중 마
  398. 403 Amazon RDS에 서비스 런칭 이후, 빛과 그림자 스터 구조는

    Amazon RDS에서는 사용할 수 없습니다. 또한 Read관련 Scale- Out은 가능하나 Write 관련 Scale-Out은 불가능한 MySQL 본질적인 한계를 극 복할 수 없습니다. 최대 10개의 DB 인스턴스를 가질 수 있음 Amazon RDS에서는 사용자가 최대 10개의 DB 인스턴스를 가질 수 있습니다. Write 퍼포먼스를 늘리기 위해 인스턴스 별로 데이터를 샤딩 구성한다고 할 지라 도, 최대 10개만 가능하다는 한계점에 봉착하는 것이죠. 인스턴스는 최대 1TB 스토리지 용량만 가질 수 있음 각 인스턴스는 최대 1TB라는 저장 공간을 가지기 때문에, 로그성 누적 데이터를 저장하기에는 결코 적합하지 않습니다. 사용자가 최대 10개의 인스턴스를 가질 수 있다는 점을 생각해보면, DB 데이터 사이즈는 10TB 안으로만 유지할 수 있다는 점을 시사하는 것이죠. 제한적인 DBA 권한 Amazon RDS에서는 대부분의 DB운영이 자동으로 수행되도록 구성되어 있습 니다. 그렇기 때문에 자연스럽게 DBA로서의 권한도 축소되는 것이죠. 예를 들어 Slow Query를 수집하기 위해 Slow_log 옵션을 활성시키는 것은 DB 프롬프트가 아닌 RDS 클라이언트를 통해서만 적용할 수 있습니다. 게다가 테이블 단위 누적 된 Slow Query를 제거하기 위한 것도 테이블에 직접 Truncate 구문을 날리지 못 하고, 내부 프로시저를 호출해야만 가능합니다. Amazon RDS 제약을 극복하기 Amazon RDS에서는 사용하는 모든 리소스가 비용과 연관되기 때문에, 무조건 성능 이 좋은 장비만을 고집할 수는 없습니다. 게다가 서버 자체 퍼포먼스 또한 일반 물리 장비보다 크게 떨어지며, 기타 여러 제약사항으로 인하여 효과적인 사용이 어려운 것 도 사실입니다. 그러나 분명 Amazon RDS가 가지는 장점이 있는 만큼, 기존 제약 사항을 최대한 극 복하는 노력이 필요한 것이죠.
  399. 404 KTH 개발자 블로그 베스트 비용 아끼기 비용 문제를 해결하기

    위해서는 서버 스펙을 미리 과투자할 필요는 없는 것이죠. 참 고로 글로벌 인증 서비스에서는 Slave 없이 Multi-AZ만으로 구성하였습니다. 물론 Read 트래픽을 고려한다면, 난색을 표할 수도 있겠지만, 어플리케이션 레이어에서 캐 시를 적절하게 사용한다면 Read 트래픽을 최소화할 수 있는 방안이 있습니다. 성능 한계 극복하기 앞에서 언급한 것처럼 물리DB 대비 대략 30% 정도의 성능을 발휘합니다. 그리고 디 스크를 여러 개의 배열로 묶어서 Raid 구성한다면 I/O 작업이 많다면 더욱 성능차가 발생할 수도 있겠죠. 게다가 디스크가 안된다면 SSD까지 고려할 수 있기 때문에, 성 능 고도화 측면에서는 Amazon RDS는 결코 따라올 수 없습니다. 1.  인덱스 사이즈를 최소화하기 위해 Trigger + CRC32 기법을 적용하였습 니다. CREATE TRIGGER trg_usermast_insert BEFORE INSERT ON usermast FOR EACH ROW BEGIN SET NEW.umid_crc = CRC32(LOWER(TRIM(NEW.umid))); SET NEW.name_crc = CRC32(LOWER(TRIM(NEW.name))); SET NEW.email_crc = CRC32(LOWER(TRIM(NEW.email))); END$$ 그리고 위 테이블에서 이메일 검색 시 다음과 같이 질의합니다. SELECT * FROM usermast WHERE email_crc = CRC32(LOWER(TRIM('[email protected]'))) AND email = '[email protected]'; 물론 추가적인 Where 조건에 Function 연산이 발생하지만, 인덱스 사이즈가 커지 면서 발생할 디스크 I/O를 방지하는 면에서는 훨씬 효율적입니다. 글로벌 인증에서 문자열로 이루어진 인덱싱이 필요한 경우 대부분 적용하였으며, 인덱스 사이즈를 획기적으로 줄였습니다. 다음은 특정 테이블 Insert 시 다음과 같 은 트리거로 해시 타입의 인덱스를 생성하였습니다. Update 시에도 마찬가지입 니다.
  400. 405 Amazon RDS에 서비스 런칭 이후, 빛과 그림자 2. 쿼리를

    MySQL 특성에 맞게 더욱 세심하게 작성하였습니다. 연산에 필요한 데이터만 가져오도록 최대한 유도하였으며, 불필요한 조인 혹은 서 브쿼리는 과감하게 제거하였습니다. AS-IS TO-BE SELECT A.UID AS ID, A.TOKEN AS TOKEN, A.UUID AS UUID, A.USER_TOKEN AS USER_TOKEN, A.USER_UUID AS USER_UUID, B.TIMEZONE AS TIMEZONE FROM USER A LEFT JOIN SETTING B ON A.UID = B.UID WHERE B.COL01 = 1 AND B.COL02 = 1 AND B.COL03 = 1 AND B.COL04 = 2 AND B.COL05 != B.COL04 ORDER BY A.UID ASC LIMIT 0, 1000 SELECT BB.UID AS ID, BB.TOKEN AS TOKEN, BB.UUID AS PLATFORM, BB.USER_TOKEN AS USER_TOKEN, BB.USER_UUID AS USER_UUID, AA.TIMEZONE AS TIMEZONE FROM( SELECT A.UID, A.TIMEZONE FROM USER A WHERE A.COL01 = 1 AND A.COL02 = 1 AND A.COL03 = 1 AND A.COL04 = 2 AND A.COL05 != A.COL04 ORDER BY A.UID ASC ) AA LEFT JOIN SETTING BB ON AA.UID = BB.UID LIMIT 0, 1000; 위에서 얼뜻 보면 큰 문제가 없어보이는 쿼리이지만, SQL 조인에 불필요한 데 이터를 READ하면서 관련 퍼포먼스 저하가 발생한 쿼리입니다. 조인 WHERE조 건에서 모든 조인 조건에 필요한 데이터(UID)와 SELECT를 질의를 위한 데이터 (TIMEZONE)만을 서브 쿼리로 가져오고, 그 결과를 SETTING 테이블과 조인을 함으로써, 메모리 효율을 최대한 살린 것이죠. 3. 서버 분석 시 세션 변수를 변경하여 처리 서버 분석 시에는 세션 변수를 일부 변경하여 tmp_table_size와 max_heap_ table_size 집계성 쿼리를 처리하였습니다. ## Temporary Table 관련 세션 변수 변경 set tmp_table_size = 2 * 1024 * 1024 * 1024; set max_heap_table_size = 2 * 1024 * 1024 * 1024; ## 집계 정보 질의
  401. 406 KTH 개발자 블로그 베스트 select a.col01, a.col02, count(*) from

    tab01 a inner join tab02 b on a.id = b.id group by a.col01, a.col02 물론 MySQL에서는 Nested Loop 방식으로만 데이터 조인이 이루어지기는 하지만, 집계 데이터 추출 시 발생하는 Temporary Table 이슈를 제거함으로써 한층 질의 속 도를 빠르게 유도하였습니다. Replication에서 Master/Slave 지연을 최소화하기 위해 Binary Log 포멧을 Row로 유도를 하려고 하였으나 안타깝게도 세션 레벨에서 binlog_format 변수를 변경할 수 없었습니다. 그러나 MySQL에서는 isolation_level에 따라 자연스럽게 Binary Log 포 멧이 Statement에서 Row 포멧으로 변경이 됩니다. 즉 무거운 쿼리 결과를 바로 질의 하는 업데이트 경우 isolation Level을 READ COMMITTED로 변경하여 처리함으로써 Master/Slave 간 데이터 동기화 지연을 최소화 유도한 것이죠. set session transaction isolation level read committed; 참고로 Binary Log 포멧에 대한 간략한 설명입니다. Statement-based MySQL 3.23 이후로 도입된 방식 실행된 SQL을 그대로 Binary Log에 기록 Binary Log 사이즈는 작으나, SQL에 따라 결과가 달라질 수 있음 (Time Function, UUID, User Defined Function) Row-based Type MySQL 5.1부터 도입된 방식 변경된 행을 BASE64로 Encoding하여 Binary Log에 기록 특정 SQL이 변경하는 행 수가 많은 경우 Binary Log 사이즈가 비약적으로 커질 수 있음 Mixed Type 기본적으로 Statement-Based Type으로 기록되나, 경우에 따라 Row-base Type으로 Binary Log에 기록 Replication에 대한 간략한 설명은 http://j.mp/OimNya 참고하세요. ^^ 스토리지 효율적으로 쓰기 Amazon RDS는 인스턴스 당 최대 1TB만 데이터만 가능합니다. 그리고 물리 DB가 아닌만큼 Amazon RDS에서 허용하는 Disk I/O 이상으로 튜닝은 불가능하죠. 예를 들면 SSD죠.
  402. 407 Amazon RDS에 서비스 런칭 이후, 빛과 그림자 결국, 기존

    스토리지 공간을 최대한 아껴쓰고, Disk I/O가 최소로 발생하도록 유도하 는 것이 제일 중요합니다. 그래서 MySQL 내부적으로 innnodb_file_format을 Barracuda로 설정하고 1/2로 데이터를 압축하여 테이블을 재구성하였습니다. INNODB 1.1부터 사용 가능하며, MySQL 5.5부터는 기본적으로 설치되어 있습니다. 각 테이블을 다음과 같이 속성을 변경할 수 있습니다. ALTER TABLE TEST ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; 참고로 과거 관련 BMT를 진행해보니, 압축/압축해제에 소요되는 자원보다 Disk I/O 로 인한 비효율이 훨씬 큰 것으로 나왔기 때문이죠. 출처 : http://dev.kthcorp.com/2011/12/14/database-performance-report-on-disk-bottleneck/ 위 테스트에서는 1/4로 압축한 결과이며, 건 수가 많아져도 안정적인 성능을 유지하 는 것을 확인할 수 있습니다. 물론 이후 스토리지 사용률이 일반 대비 1/2로 줄었으 며, 대략적으로 인스턴스 당 2TB데이터 사이즈까지 수용 가능할 것으로 예측합니다. 기타 제약 사항 극복하기? MySQL Replication의 기본적인 위상을 변경해보고자 했지만 불가능했습니다. 또 한 정해진 DBA 권한 외 Super 권한을 할당 받을 수도 없습니다. 모든 것이 Amazon RDS 고유의 정책이기 때문이죠. 인스턴스 한계 또한 변경 가능한지 여부를 문의해보 았으나, 현재로서는 기약할 수 없다는 답변을 얻었습니다. ^^; 즉, MySQL 특성을 최대한 반영하여 DB 장비 효율을 높이는 방법밖에는 없습니다.
  403. 408 KTH 개발자 블로그 베스트 데이터 복구 사례 예전에 개발

    부서 실수로 테이블에서 패스워드를 공백으로 업데이트한 장애가 발생하 였습니다. 로컬에 DB가 있다면, 간단하게 시점 풀 백업본에 Binary Log를 적용하여 장애 바로 이전 시점으로 데이터를 돌릴 수 있으나, Amazon RDS이기 때문에 로컬 DB에서처럼 복원은 불가합니다. Amazon RDS에서는 다음과 같이 데이터를 복구할 수 있습니다. 백업 인스턴스 DB 생성 먼저 웹 콘솔의 Amazon RDS 항목에 들어가면 “Restore To Point In Time” 버튼이 있습니다. 버튼을 클릭하면 다음과 같이 DB 인스턴스 생성을 위한 옵션을 입력하는 레이어가 뜹 니다.
  404. 409 Amazon RDS에 서비스 런칭 이후, 빛과 그림자 여기서 장애가

    발생했던 시점 바로 이전으로 시간을 설정하고 몇 가지 정보 입력 후 “Launch DB Instance”를 누르면 새로운 DB 인스턴스가 생성됩니다. 여기서 시간은 UTC 기준이므로 한국 시간에서 적절하게 UTC 시간으로 변경하여 입력하세요. ^^; DB 인스턴스가 생성되는 과정은 기존 운영되고 있는 서비스 DB에는 영향을 주지 않 습니다. 새벽에 스냅샷 형태로 풀 백업된 DB 이미지에 Binary Log 변경 사항을 내부적으로 취 합하기 때문이죠. ^^ 일정 시간 후 웹 콘솔을 확인해보면, 다음과 같이 정상적으로 백 업 DB 인스턴스가 구동 중인 것을 확인할 수 있습니다. 위 그림에서는 가장 하단에 나온 호스트로 MySQL을 접근하면 해당 시점의 데이터를 볼 수 있는 것이죠.
  405. 410 KTH 개발자 블로그 베스트 데이터 추출 및 복원 장애

    이전 시점으로 DB 인스턴스를 생성하였으니, 데이터를 운영 DB로 이관하기 위 한 임시 테이블을 생성합니다. Primary Key 외, 불필요한 인덱스는 과감하게 삭제합 니다. 빠른 데이터 보정을 위해서는 Primary Key외에는 필요없기 때문이죠. ## 서비스 장비에서 수행 create table tb_repair_tmp like tb_repair; drop index idx_tb_repair_indt on tb_repair_tmp; drop index idx_tb_repair_closedt on tb_repair_tmp; 이제, mysqldump 유틸리티를 활용하여, 백업 인스턴스 DB에서 서비스 DB의 임시 테이블로 데이터를 이관합니다. mysqldump -udbuser -pxxxxx \ --single-transaction \ --no-create-db \ --no-create-info \ --triggers=false \ --comments=false \ --add-locks=false \ --disable-keys=false \ --host=xx-master-restore.xx.us-east-1.rds.amazonaws.com \ --port=3306 \ --databases targetdb \ --tables tb_repair \ | sed -r 's/^INSERT INTO `tb_repair`/INSERT INTO `tb_repair_tmp`/gi' \ | mysql -udbuser -pxxxxx \ --host xx-master.xx.us-east-1.rds.amazonaws.com \ --port 3306 targetdb 단 여기서 mysqldump에 들어가는 host는 백업 DB 인스턴스 End Point이고, mysql에 들어가는 host는 복원할 서버 End Point입니다. 데이터 보정 장애 발생 원인에 따라 세 가지로 나누어서 데이터를 보정합니다. 1. 테이블을 Drop한 경우 테이블이 없는 상태이기 때문에 테이블 명을 Rename하여 간단하게 해결합니다. Rename table tb_repair_tmp to tb_repair;
  406. 411 Amazon RDS에 서비스 런칭 이후, 빛과 그림자 2. 데이터를

    Delete한 경우 테이블에 데이터는 없으나, 지속적으로 누적되고 있는 경우입니다. 이 경우는 누 적되는 데이터를 선별해서 데이터를 복원해야 합니다. 하단과 같이 임시 테이블에 는 존재하나 원본 테이블에는 없는 데이터를 선별해서 데이터를 복원합니다. DB 에 무리가 가지 않도록 10만 건씩 나눠서 데이터를 복사합니다. 여기서 seq는 각 테이블의 Primary Key입니다. insert into tb_repair select a.* from tb_repair_tmp a left join tb_repair b on a.seq = b.seq where b.seq is null limit 100000; 3. 특정 필드를 Update한 경우 특정 필드(여기서는 passwd 필드)를 업데이트한 경우 다음과 같이 보정합니다. 공백으로 업데이트한 데이터를 찾아서 복구하는 방법이며, seq로 적절하게 일괄 변경 건 수를 체크합니다. update tb_repair a inner join tb_repair_tmp b on a.seq = b.seq set a.passwd = b.passwd where a.passwd = '' and a.seq between 1 and 100000; 마치며.. DB를 가상화 환경에서 구동하는 Amazon RDS를 사용하면 DB 시스템적인 이슈가 최소화되는 것은 사실입니다. 그리고 사용한 용량만큼만 비용을 지불하므로, 초기 IT 투자가 과도하게 발생하지 않을 수도 있는 것이죠. 하지만, 기본적인 MySQL특성과 Amazon RDS 제약 사항을 고려하지 않고 서비스를 설계하게 되면, DB 자원이 비효율적으로 사용될 것이고 비용 측면에서도 큰 낭패를 볼 수 있습니다. 이제는 시스템 성능으로 퍼포먼스를 늘리는 것이 아닌 데이터 시스템 자체를 효율적 으로 잘 사용하는 역량이 더욱 중요시되는 추세인 것 같습니다.
  407. 412 KTH 개발자 블로그 베스트 MariaDB란? MySQL이 Sun Microsystems로 넘어가면서

    당시 MySQL AB 출신들이 따로 나와 서 MySQL을 기반으로 한 다른 오픈 소스 기반의 DBMS를 배포했다고 합니다. 바로 MariaDB가 그것이며 MySQL과 유전 정보를 그대로 고수한 “진짜” 오픈 소스 기반의 DBMS입니다. 현재 Monty Program AB와 MariaDB Community에서 개발하고 있으며, MySQL과 기본적으로 구조 및 사용 방법 등 모두 동일합니다. (동일 소스에서 개발되고 있으니 당연한 말입니다.) Monty Program AB에 따르면 많은 기능들이 MariaDB에서 먼저 구현을 하고 그 후 MySQL에도 반영이 된다고 하는데, 마치 CentOS와 Redhat 리눅스 관계 같다는 생 각이 듭니다. 또한 GPL v2  라이선스에 따르기 때문에, Oracle의 횡포로부터 상당히 자유롭습니다. 사실 Oracle에서 MySQL 관련하여 현재는 오픈 소스 정책을 고수하고 있지만, 언제 갑자기 그들의 정책을 폐쇄적으로 바꿀 지 모르기 때문에 상당히 호기심이 가는 제품 입니다. 오픈 소스의 또 다른 진영, MySQL 쌍둥이 형제 MariaDB 성동찬
  408. 413 오픈 소스의 또 다른 진영, MySQL 쌍둥이 형제 Maria

    DB MariaDB vs MySQL 설치 방법 설치 방법은 MySQL과 동일합니다. 물론 컴파일 시에는 사용하고자하는 스토리지 엔 진 기능 on/off를 위해 추가/변경이 될 수 있겠지만, RPM방식 혹은 TAR 압축 해제하 여 DB를 설치해도 잘 구동됩니다. 스토리지 엔진 “MariaDB 5.3″에서 기본적으로 제공하는 스토리지 엔진은 다음과 같습니다. 기본 제공되는 스토리지 엔진 중 다음 3개를 눈여겨볼 필요가 있습니다. FEDERATED (트랜잭션 제공) 원격 DB 서버 테이블에 네트워크로 접근하는 스토리지 엔진으로 기존 원격 DB에서 로컬 DB로 결과 값만 전달한다는 점에서 MySQL에 기본으로 장착된 FEDERATED와 가장 큰 차이점이 있습니다. MariaDB에서는 FEDERATEDX라는 새로운 네이밍을 사용합니다.
  409. 414 KTH 개발자 블로그 베스트 Aria 차세대에 MyISAM 스토리지 엔진을

    대체하기 위해 개발된 것으로 MyISAM에서 파생되었습니다. Crash-Safe를 목표로 진행 중, 부분적으로 Transaction을 제공 PBXT(트랜잭션 제공) Transaction Log에 선 기록 없이 바로 DB에 기록하는 구조이나, Maria5.5부터는 더이상 유지보수를 제공하지 않으므로 기본 스토리지 엔진에서 제외된 상태입 니다. 위 기본 스토리지 엔진 외에 Plugin으로 제공되는 스토리지 엔진을 추가로 설치할 수 있습니다. OQGRAPH Graph 기능을 제공하는 스토리지 엔진입니다. Maria5.5에는 기본으로 Plugin이 들어있지 않으나 다음과 같이 간단하게 확장 가능합니다. SphinxSE Full-Text Searching이 필요할 때 사용할 수 있는 스토리지 엔진. 단, SphinxSE 은 어디까지나 Sphinx의 일부분이며, 스토리지 엔진 사용을 위해서는 Sphinx 데 몬을 별도로 설치 필요. 참고로 MySQL 5.5에서 기본적으로 제공하는 스토리지 엔진 리스트입니다
  410. 415 오픈 소스의 또 다른 진영, MySQL 쌍둥이 형제 Maria

    DB SQL Join MariaDB 5.3으로 넘어오면서 조인 퍼포먼스가 향상되었는데, 그 중 괄목할 만한 사 항은 Semi-join 서브쿼리 성능 향상에 관련된 내용입니다. 예를 들어서 다음과 같은 SQL이 유입되었다고 가정해 봅니다. select * from Country where Continent=›Europe› and Country.Code in (select City.country from City where City.Population>1*1000*1000); MySQL 5.5 인 경우 위 쿼리는 다음과 같이 Country -> City 테이블 순으로 쿼리가 실행되며, Continent 조건이 없는 경우 Full-Table Scan이 발생합니다. 게다가 인덱 스가 있을지라도 Continent=’Europe’ 결과 값 만큼 City 테이블을 스캔하면서 데이터 유효성을 체크합니다. 그러나 MariaDB5.3에서는 반대로 City -> Country 서브쿼리 부분이 먼저 풀리고 결 과적으로 외부 테이블과 조인 연산하는 방식으로 데이터를 처리합니다. City 테이블에 는 단 한번 스캔을 하고 중간 결과를 바탕으로 데이터 유효성을 체크하는 것이죠.
  411. 416 KTH 개발자 블로그 베스트 조건절에 IN을 써서 간단하게 작성할

    수 있는 SQL 경우(설혹 조건이 10건 미만일 지 라도)에도 어쩔 수 없이 Inner Join으로 풀어야 하는 경우가 많았기 때문에, 정말로 반 가운 내용입니다. 무엇보다  Optimizer Switch를 확인해보면 Optimizer의 선택의 폭이 MySQL 5.5 대 비 상당히 다양한 것을 볼 수 있습니다. 먼저 MariaDB를 확인해보면 다음과 같습니다. MariaDB> SELECT @@optimizer_switch\G @@optimizer_switch: index_merge=on ,index_merge_union=on ,index_merge_sort_union=on ,index_merge_intersection=on ,index_merge_sort_intersection=off ,index_condition_pushdown=on ,derived_merge=on ,derived_with_keys=on ,firstmatch=on ,loosescan=on
  412. 417 오픈 소스의 또 다른 진영, MySQL 쌍둥이 형제 Maria

    DB ,materialization=on ,in_to_exists=on ,semijoin=on ,partial_match_rowid_merge=on ,partial_match_table_scan=on ,subquery_cache=on ,mrr=off ,mrr_cost_based=off ,mrr_sort_keys=off ,outer_join_with_cache=on ,semijoin_with_cache=on ,join_cache_incremental=on ,join_cache_hashed=on ,join_cache_bka=on ,optimize_join_buffer_size=off ,table_elimination=on 이에 비해 MySQL은 상당히 적습니다. mysql> SELECT @@optimizer_switch\G @@optimizer_switch: index_merge=on, index_merge_union=on, index_merge_sort_union=on, index_merge_intersection=on, engine_condition_pushdown=on MariaDB vs MySQL 성능 벤치마킹 조인 알고리즘 튜닝에 따라 몇 가지 쿼리 성능 벤치 마킹을 수행해 보았습니다. Index Condition Pushdown DB 엔진은 데이터를 처리하여 클라이언트에게 전달하고, 스토리지 엔진은 물리적 장 치에서 읽어와 DB 엔진에 전달하는 역할을 합니다. 서로 역할은 명확하게 구분되어 있으며, DB 엔진이 저장 장치로부터 데이터를 읽기 위해서는 반드시 스토리지 엔진 API에 맞게 데이터 요청을 해야하는 합니다. 이런 구조이기에 MySQL이 다양한 스토리지 엔진으로 확장할 수 있었지만, 그에 따라 내부적인 비효율이 발생합니다.
  413. 418 KTH 개발자 블로그 베스트 예를 들어 다음과 같은 쿼리를

    호출한다고 할 때, keycol1과 key_col2로 인덱스를 만 든다고 하더라도, between문으로 인하여 key_col2 조건이 적용되지 않습니다. 물론 하단 조건에서는 Like 검색에 따라 두번째 인덱스 칼럼은 쿼리에서 사용되지 않겠죠. select * from tbl where key_col1 between 10 and 11 and key_col2 like '%foo%'; 그러나 MariaDB 5.3.3부터 Index Condition Pushdown 기능이 추가되면서, 인덱스 데이터 구조를 활용하여 한번 더 필터링하여 필요한 데이터만 테이블 데이터에서 읽 고 DB 엔진에 전달합니다.
  414. 419 오픈 소스의 또 다른 진영, MySQL 쌍둥이 형제 Maria

    DB 실제 이 기능에 따른 성능 향상 관련 벤치마킹을 내부적으로 진행하였습니다. 테이블 스키마는 다음과 같으며, 약 1000만 건 정도의 데이터를 무작위로 생성하였습 니다. CREATE TABLE `dbatest` ( `i` int(11) NOT NULL AUTO_INCREMENT, `c1` int(11) NOT NULL, `c2` int(11) NOT NULL, `c3` varchar(255) DEFAULT NULL, PRIMARY KEY (`i`), KEY `c1` (`c1`,`c2`) ) ENGINE=InnoDB AUTO_INCREMENT=10603662 DEFAULT CHARSET=utf8; 데이터 패턴은 다음과 같습니다.
  415. 420 KTH 개발자 블로그 베스트 | 1 | 386687 |

    1329942800 | abc15607efg | | 2 | 386716 | 1329942800 | abc11645efg | | 3 | 440646 | 1329932800 | abc11407efg | | 4 | 440665 | 1329922800 | abc22097efg | | 5 | 386735 | 1329932800 | abc76266efg | | 6 | 386727 | 1329922800 | abc15040efg | | 7 | 386376 | 1329932800 | abc46402efg | | 8 | 386387 | 1329942800 | abc86889efg | | 9 | 386368 | 1329922800 | abc95239efg | 위 테이블에 수행할 쿼리는 다음과 같습니다. select c1, c2, count(*) from dbatest where c1 between 10917 and 100920 and c2%10000 = 1 and c3 like '%12%' group by c1, c2; MySQL에서 실행 계획과 프로파일링 정보는 다음과 같습니다. 실행계획 프로파일링
  416. 421 오픈 소스의 또 다른 진영, MySQL 쌍둥이 형제 Maria

    DB 수행 속도는 InnoDB에 어느정도 데이터가 들어간 경우에는 1.12초 소요되었으나, 데 이터가 메모리에 없는 상황에서는 1분 19초라는 시간이 걸렸습니다. 위 결과와 MariaDB결과를 비교해보도록 합니다. 실행계획과 프로파일링 정보는 다음 과 같습니다. 실행계획 프로파일링 수행 속도는 InnoDB에 어느정도 데이터가 들어간 경우에는 0.22초 소요되었으며, 데 이터가 메모리에 없는 상황에서는 0.75초라는 황당한 퍼포먼스를 보였습니다. 앞선 MySQL의 결과(1.12초, 1분 19초)에 비추어 볼 때 엄청나게 쿼리 실행 속도가 좋아 졌습니다.
  417. 422 KTH 개발자 블로그 베스트 Multi Range Read optimization 실제

    데이터를 가져올 때 Rowid 기준으로 정렬하여 디스크에 요청하기 때문에, 디스 크 1번 회전 당 데이터 스캔 효율이 크게 늘어나는 구조입니다. MySQL 5.6 부터 관 련 신 기능이 추가되며, MariaDB에서는 현재 버전에서 제공하는 기능이죠. 사용 유무에 따른 성능 비교를 위해 앞에서 사용한 테이블을 재활용하였습니다. CREATE TABLE `dbatest` ( `i` int(11) NOT NULL AUTO_INCREMENT, `c1` int(11) NOT NULL, `c2` int(11) NOT NULL, `c3` varchar(255) DEFAULT NULL, PRIMARY KEY (`i`), KEY `c1` (`c1`,`c2`) ) ENGINE=InnoDB AUTO_INCREMENT=10603662 DEFAULT CHARSET=utf8; MySQL 5.5에는 아직까지는 Multi Range Read(MRR) 기능이 없기 때문에 MariaDB 에서만 성능 테스트를 진행하였습니다. set optimizer_switch=’mrr=off’;와 같은 설정 선언으로 간단하게 온/오프할 수 있으며, 테스트를 위해 다음과 같은 쿼리를 호출하였 습니다. select * from dbatest where c1 between 50000 and 60000; 여기서 MRR 기능을 사용하지 않는 경우 실행계획입니다.
  418. 423 오픈 소스의 또 다른 진영, MySQL 쌍둥이 형제 Maria

    DB 실행 시간은 1분 14초 소요되었는데, 동일한 쿼리를 다음과 같이 MRR 기능을 켠 상 태로 테스트 해보면 수행 시간이 20초로 크게 단축됩니다. set optimizer_switch=’mrr=on’; select * from dbatest where c1 between 50000 and 60000; 관련 실행 계획을 살펴보면, Using Index Condition 외에 Rowid-ordered scan이 추가되어 쿼리가수행되는 것을 확인할 수 있습니다. 마치며.. 앞서 소개한 대부분의 기능과 벤치마킹한 결과는 상용 장비에서는 당연한 결과입니 다. 디스크 성능이 일반적으로 서버에서 가장 큰 병목이기도 하기 때문에, 관련 알고 리즘에 따라 DB 성능이 크게 좌우됩니다. 상용 DB에서는 오히려 조금은 오래된 이야 기일 수도 있겠죠. 또한 앞으로 SSD가 더욱 일반적으로 사용되게 되면, MRR과 같은 알고리즘은 큰 의미가 되지 않는 요소일 수도 있습니다. 그러나 단순 데이터 처리 혹은 작은 데이터 조각만을 취급하는 소규모 DBMS로 인식 되어 왔던 MySQL이 대용량 데이터를 처리하기 위한 방안을 고안하고 있다는 면에서 큰 의미가 있습니다. 물론 아직까지는 옵티마이저 기능이 좋지 않기 때문에, 쿼리를 최대한 유도하도록 작성을 해야하지만, MySQL은 오픈소스이며 현재 문제점은 차근 차근 해결될 것이기에 MySQL오픈 소스 진영의 다음 행보가 상당히 기대됩니다.
  419. 424 KTH 개발자 블로그 BEST The Problem 네이티브 앱, 웹

    앱, 하이브리드 앱 구분 없 이 모바일 앱에서 가장 많이 사용하는 화면 구성은 옆 그림처럼 헤더 영역은 고정되어 있고 리스트 뷰 형태의 컨텐츠 영역만 스크 롤 되는 형태일 것입니다. 그러나 모바일 웹 브라우저에서는 페이지의 특정한 요소만을 고정해 두고 나머지 부분 만 스크롤할 수 없기 때문에 웹 앱과 하이브 리드 앱의 경우 iScroll 같은 스크롤 라이브 러리를 사용해서 위 그림과 같은 형태의 화 면을 구성하곤 합니다. iScroll은 touch start, touch move, touch end 이벤트를 하이브리드 앱의 스크롤 성능 개선하기 김남훈
  420. 425 하이브리드 앱의 스크롤 성능 개선하기 이용하여 스크롤 되어야 할

    양을 계산하고, 리스트 엘리먼트에 CSS translate 값을 주 어 상하로 이동시키는 방식으로 동작합니다. 또 다른 방식으로 리스트 엘리먼트의 부 모 엘리먼트의 스크롤 바를 상하로 이동시키는 라이브러리나 프레임워크들도 있으나 근본적인 동작 원리는 비슷합니다. 문제는 어떤 방식이든 소프트웨어적으로 스크롤을 시뮬레이션 하고 있기 때문에 성능이 매우 낮고 사용자 경험이 좋지 못하다 는 것입니다. 옆 QR 코드를 스캔하거나 단축 URL을 모바일 브 라우저에 입력해서 iScroll을 이용한 샘플 웹 앱을 실행해 보시 기 바랍니다. 샘플 웹 앱을 스크롤하면 footer에 FPS(초당 프레 임 수)가 나타납니다. iPhone의 경우 FPS가 비교 적 높게 나오지만 Android의 경우 FPS가 매우 낮 을 뿐 아니라 스크롤이 손가락의 움직임을 잘 따라 오지 못한다는 느낌을 받게 됩니다. 다음의 스크린 샷은 Nexus One(Android 2.3.6) 단말기에서 샘 플 웹 앱을 실행한 결과인데 평균 FPS가 8.9에 그 치고 있습니다. An idea iScroll이 스크롤 처리를 위해 수행하는 계산은 그다지 복잡하지 않기 때문에 성능 문 제의 주범으로 지목하기는 어렵습니다. 다양한 테스트 결과 단말기의 해상도가 높아 질수록 성능이 더욱 떨어지고 있었으므로 렌더링 성능이 병목이라는 사실을 유추할수 있었습니다. 그리고 리스트 아이템들이 많아져 리스트의 크기가 커질수록 성능도 선 형적으로 저하되고 있었으므로 화면 밖에 있는 엘리먼트들도 렌더링 성능에 영향을 미치고 있다고 판단되었습니다. 따라서 화면이 스크롤됨에 따라 화면 밖으로 밀려 나 가는 리스트 아이템들은 숨기고 화면 안으로 들어 온 리스트 아이템들만 렌더링 되도 록 하면 성능을 향상시킬 수 있겠다는 가설을 세울 수 있었습니다. http://goo.gl/Qr6Mg
  421. 426 KTH 개발자 블로그 베스트 엘리먼트를 숨기는 방식은 몇 가지

    있는데 가장 간단한 것은 visibility: hidden 스타 일을 부여하는 것입니다. 이 방식을 적용하여 테스트한 결과 Nexus One(Android 2.3.6)에서 평균 FPS가 8.9에서 20 가까이로 증가하였습니다. visibility: hidden 스 타일은 레이아웃에 영향을 미치지 않으므로 부담 없이 적용할 수 있는 데 반해 비교적 큰 성능 향상을 얻을 수 있다는 장점은 있으나 여전히 저사양 단말기에서는 20 프레임 이 채 안되기 때문에 매끄럽게 스크롤된다는 느낌을 받을 수는 없습니다. 리스트 아이템에 display: none 스타일을 부여해서 렌더링 개체를 아예 제거해 버려 야 가장 성능 향상이 클 것입니다. 그러나 이렇게 하면 다음 그림과 같이 제거된 리스 트 아이템의 다음에 있던 모든 리스트 아이템들이 위로 이동을 하게 되어 버립니다. 리스트의 크기가 변경되면서 다시 리스트의 위치를 수정해 주어야 하는데, 이렇게 하 면 iScroll이 수정한 리스트의 위치를 재차 수정하게 되는 것이므로 사실상 사용할 수 없는 스크롤이 되어버립니다. 이 문제를 다음과 같은 아이디어로 해결했습니다. 레이아웃이 끝나 모든 리스트 아이템들의 위치가 정해진 후 리스트 아이템들에게 position: absolute 스타일을 부여하여 위치를 고정시킨다. 어차피 리스트 아이템들이 화면에서 밀려 나가는지 혹은 들어 오는지 판단하기 위해 각 리스트 아이템들의 offset을 계산해야 하므로 각 리스트 아이템들의 top position 값도 추가적인 오버헤드 없이 자연스레 알 수 있습니다. 옆의 QR 코드와 단축 URL로 이 방식을 적용한 웹 앱을 모바일 브라우저에서 테스트할 수 있습니다. http://goo.gl/7KhPP
  422. 427 하이브리드 앱의 스크롤 성능 개선하기 iPhone에서는 별 다른 차이가

    없지만 Android 에서는 비약적인 성능 향상이 있습니다. 동일한 Nexus One 단말기에서 테스트한 결과인데 평균 FPS가 61로 visibility: hidden 방식 대비 3배, 순 수하게 iScroll만 사용한 경우에 대비하여 6배 향상 되었습니다. FPS가 상승하면서 스크롤이 매끄럽 다는 느낌을 받을 수 있으며 스크롤이 사용자의 손 가락을 따라 다닌다는 느낌을 받을 수 있습니다. Implementation 테스트용 샘플 앱은 단순한 master list view page - detail page, 2페이지 구성으로 제작되었습니다. 컨텐츠는 flickr RSS 데이터와 임의의 문자열을 조합해서 만들었고, 항상 동일한 내용을 보여주기 때문에 비교 테스트에 적합합니다. 성능은 애니메이션 상태에서 FPS를 측정합니다. Modifying iScroll iScroll의 소스를 수정하지 않을 수 있다면 더욱 좋겠지만 iScroll에서 계산한 이동 거 리를 정확히 알아야 하므로 onPositionChange라는 callback을 하나 추가해야 합니다. 그리고 성능 측정을 위해 애니메이션의 시작과 끝에 callback을 하나씩 추가하였습니 다. 수정된 사항은 iscroll.js 파일에 대한 github diff 페이지에서 확인할 수 있습니다. unloader.js 아이디어를 구현한 스크립트는 unloader.js입니다. 이 스크립트는 setup(), reset(), onmove() 세 개의 메서드를 갖는 인터페이스 Unloader를 글로벌 스코프에 노출합니 다. 이 인터페이스를 사용하는 곳은 웹앱의 메인 로직을 담당하는 gnb.js 파일의 다음 부분입니다.
  423. 428 KTH 개발자 블로그 베스트 [cc lang="javascript"] var wrapper =

    d.querySelector('#page-master .scroller'), unloader = new Unloader(wrapper, 'li'); masterScroll = new iScroll(wrapper, { onRefresh: function() { unloader.setup(this.x, this.y); }, onPositionChange: function(x, y) { unloader.onmove(x, y); } }); [/cc] 생성자에는 iScroll 객체에 전달하는 것과 동일한 wrapper 엘리먼트와 함께 unload 의 대상이 되는 엘리먼트에 대한 CSS 셀렉터를 전달합니다. 그리고 iScoll에 원 래 존재하던 onRefresh callback에서 unloader.setup()을 호출하고 새로 추가한 onPositionChange callback에서 unloader.onmove()를 호출합니다. Unloader 인터페이스의 생성자에서는 wrapper 엘리먼트와 CSS 셀렉터로 자료구 조를 준비합니다. unloader.setup() 메서드에서는 position: absolute로 스타일을 변 경하는 것과 동시에 초기 상태에서 보이고 감춰야 할 부분을 결정합니다. 마지막으로 unloader.onmove() 메서드에서는 iScroll에서 계산한 이동 거리를 이용해 리스트 아 이템들을 보이거나 숨깁니다. 샘플 앱에서는 unloader.reset 메서드는 사용하지 않았는데 이 메소드는 position 속 성을 원래대로 되돌리는 것으로서 리스트 뷰에 항목을 추가하거나 제거하기 전에 사 용합니다. Test results 두 웹 앱을 Nexus One(Android 2.3.6)과 Galaxy S2(Android 2.3.5)에서 기본 브라우저로 비교 테스트한 결과입니다. (좌측부터 Nexus One, Nexus One with unloader.js, Galaxy S2, Galaxy S2 with unloader.js)
  424. 429 하이브리드 앱의 스크롤 성능 개선하기 min max avg Nexus

    1 7.88 11.08 8.91 Nexus 1 (mod) 56.94 76.41 61.54 Galaxy S2 13.43 19.73 15.38 Galaxy S2 (mod) 80.38 108.14 100.8
  425. 430 KTH 개발자 블로그 베스트 단말의 성능에 차이가 있어 측정된

    수치는 다르지만 두 단말 모두 600% 이상의 성능 개선 효과가 있었습니다. Conclusions 하이브리드 앱에서 스크롤 성능은 자주 제기되는 이슈 중 하나입니다. 이 포스트에서 는 리스트 항목들에 대해 absolute positioning과 display: none 스타일을 적용하여 스크롤 성능을 6배 이상 끌어 올릴 수 있는 방법을 제시했습니다. 애니메이션이 아닌 터치한 상태에서 손가락을 움직여 드래그할 때의 성능은 측정할 방법이 없어 정량적 으로 제시하지는 못하지만 이 동작도 unloader.js를 적용한 경우에 네이티브 앱의 스 크롤과 비슷한 사용감을 느낄 수 있습니다. -webkit-overflow-scrolling: touch iOS 5부터는 별도의 스크롤 라이브러리를 사용하지 않고 CSS 코드 두 줄로 헤더 를 고정한 상태에서 리스트 아이템들만 스크롤할 수 있게 되었습니다. (Native style momentum scrolling to arrive in iOS 5) Android는 3.0 허니컴부터 이 기능이 지원 되고 있었지만 실제로 적용해 보면 iOS와는 달리 스크롤 바도 표시되지 않거니와 무 엇보다 스크롤이 매끄럽지 않아 사용감이 떨어집니다. 사실 iOS 5의 구현도 완벽하다 고 볼 수는 없습니다. jQuery Mobile 에서 정리한 A few downsides에 따르면 jQuery Mobile에서는 이 기능이 안정적이지 않다고 판단하여 1.1.0 버전에서 deprecate시켰 습니다. 결국 언젠가는 이 기능이 안정화되어 별도 스크롤 라이브러리를 사용할 필요가 없어 질 것입니다. 하지만 아직은 iScroll 같은 소프트웨어 스크롤을 사용할 수 밖에 없는 것 이 현실이므로 스크롤 성능이 문제가 된다면 다음 순서에 따라 unloader.js를 프로젝 트에 추가하는 것을 검토해 보시기 바랍니다. 1. iScroll 스크립트에 callback이 추가되어야 합니다. 여기에서 받을 수 있습니다. 2. unloader.js 파일을 프로젝트에 추가합니다. 3.  샘플앱에서 하고 있는 것 처럼 다음과 같이 iScroll 객체를 초기화 할 때 Unloader 객체를 초기화 하고 callback 을 설정해 줍니다. [cc lang="javascript"] var wrapper = d.querySelector('#page-master .scroller'), unloader = new Unloader(wrapper, 'li'); masterScroll = new iScroll(wrapper, {
  426. 431 하이브리드 앱의 스크롤 성능 개선하기 onRefresh: function() { unloader.setup(this.x,

    this.y); }, onPositionChange: function(x, y) { unloader.onmove(x, y); } }); [/cc] 4.  unloader.js가 적용된 iScroll 객체에 refresh 메서드를 호출해야 할 경우 그 전에 unloader.reset()을 호출해야 합니다. unloader.js가 동작하고 나면 리스트 뷰의 항목들이 absolute position으로 고정되기 때문에 unloader. reset() 메서드를 통해 원래대로 되돌려 놓아야 refresh 함수가 제대로 동작합니다. Appendix 개발한 코드와, 알려진 이슈들, 그리고 스크롤 라이브러리 들에 대해 조사한 내용입 니다. project home github 에 공개되어 있습니다. gnb.perfo.test 프로젝트 페이지에서 전체 소스 코드를 확인할 수 있습니다. Appspresso 개발자는 프로젝트의 landing page에서 앱스프레 소 애플리케이션 프로젝트를 zip 파일로 제공하므로 import하여 바로 테스트해 볼 수 있습니다. known issues 1. 세로 방향 스크롤에만 대응한다. 2. absolute positioning 처리를 하기 때문에 wrapper 엘리먼트에 추가적인 CSS 작업이 필요해 진다. scroll lib 현황 iScroll 4 가장 지원하는 플랫폼이 많습니다. 여러 fallback을 가지고 있어서 다양한 상황에 대 응이 가능합니다.
  427. 432 KTH 개발자 블로그 베스트 Scrollability iOS 전용. 특이하게 webkit

    animation을 사용해서 구현되었고, 수식 계산을 잘 했 는지 스크롤이 제일 자연스러우면서 부드럽습니다. 그런데 iOS5 에는 -webkit- overflow-scrolling: touch를 사용할 수 있기 때문에, 어차피 iOS 전용으로 만들것이 라면 이 라이브러리를 사용할 필요가 없어진다는 문제가 있습니다. Sencha Touch 2 Android 에는 scrollTop 조절하는 방식으로 동작하고, iOS에서는 iScroll과 마찬가 지로 webkitTransform: translate3d(x, y z) 값 변경 방식으로 동작합니다. 성능을 위해서 이렇게 나눴다고는 하는데, 복잡한 컨텐츠의 아주 긴 리스트뷰를 대상으로 scrollTop 조절 방식을 테스트 해보니, translate3d 방식보다 성능이 떨어졌습니다. (Nexus One, Android 2.3.6) Overthrow 프로젝트의 목적이 overflow: scroll 지원 안되는 플랫폼에 polyfill을 만들어주는 것. 그렇기 때문에 iOS 에서는 그냥 overflow: scroll 모드로 동작합니다. 목적 자체는 훌 륭한데 정작 안드로이드의 polyfill 코드가 스크롤바도 안나오고, 수식 계산의 문제인지 애니메이션이 상당히 부자연스러운 문제가 있습니다. 게다가 스크롤 마지막에 고무줄 같이 추가로 더 당겨지는 (overscroll?) 기능이 android polyfill 코드에 없어서 사용감 이 떨어집니다. jQuery Mobile jQuery Mobile에는 고정영역 스크롤을 소프트웨어적으로 구현해주는 기능이 없습 니다.
  428. 433 Android에서 SQLite를 이용한 반경 내의 위치기반 정보 Query Android는

    SQLite DB를 지원해주고 있으 며, Query를 통해 얻어진 Cursor를 이용 하여 쉽게 앱을 구현할 수 있습니다. 하지 만, Custom function을 지원하지 않아 기 능에 제약이 다소 있습니다. 반경 내의 위치기반 정보를 Query하기 위 해서는 sin, cos 등의 연산이 필요하지만, 이런 function을 지원하지 않으며, 앱에서 따로 custom function도 구현할 수 없습 니다. 이번 포스트를 통하여, Custom function을 사용하지 않고 구현하는 방법에 대해 알아 보려고 합니다. 샘플 코드도 함께 제공되니, 개발에 도움이 되었으면 합니다. 샘플 코드 : https://github.com/kthcorp/Snippets/tree/master/SQLiteDistanceDemo Android에서 SQLite를 이용한 반경 내의 위치기반 정보 Query 홍성훈
  429. 434 KTH 개발자 블로그 베스트 어디에 쓸까? LBSNS Client App에서

    POI, Timeline을 서버에서 받아오기 전에 아무것도 보여줄 수 없다면, 그동안 사용자들은 빈화면만 봐야합니다. 사용자입장에서 보면 얼마나 따 분할까요? 그렇다면, 어떤 정보를 보여줘야 사용자에게 의미있을까요? 트위터처럼 Cache된 정보를 보여준다면 어느정도 의미있다 생각했습니다. 하지만 트 위터와 다른점은 Timeline외에 위치 정보가 들어간다는 점입니다. 우선, 사용자들의 생활 패턴을 생각해 보겠습니다. 보통 사람들은 그다지 복잡하지 않은 생활 패턴을 가지고 있습니다. 하루에 이동하는 위치를 생각해보면 많아야 5~6곳 정도일 것입니다. (물론, 영업하시는 분들은 그 이 상이겠지만 예외로 보겠습니다.) 위 그림을 보면 A, B지점이 있습니다. • A, B지점에서 각각 주변의 정보가 1000건 정도 Cache되어 있다고 보겠습니다. • A, B지점의 중간 지점인 C지점에 있을 때, A, B와 겹쳐지는 부분의 정보는 이미 Cache되어 있을 것입니다. 이 정보를 먼저 사용자에게 보여준다면 어떨까요? 위치기반 정보와 DB - SQLite? MongoDB? CouchDB? 위치기반 정보에 최적화된 DB를 생각해보니 MongoDB가 가장 먼저 떠올랐지 만, 아직 Android를 지원해주지 않고 있습니다. 그래서 대체할 만한 DB를 찾던중 CouchDB를 찾아냈습니다.
  430. 435 Android에서 SQLite를 이용한 반경 내의 위치기반 정보 Query CouchDB는

    Android를 지원해주고 있으며, 이미 PhoneGap에서는 JavaScript를 통 해 CouchDB를 사용할수 있습니다. 하지만, CouchDB를 사용한다면 공부도 해야하고, feasibility도 검토해야하니 시간이 족히 몇달은 소모될 것같아 망설이던 차에, 사내 위치기반 정보관련 전문가를 통해 조 언을 구하였습니다. 다행히 방법을 찾았고, 몇 달이 될 수도 있었던 시간을 세이브할 수 있었습니다. 이미 파란 개발자 블로그를 통해 Where 2.0 참관기를 소개해주신바 있고, 도움을 주신 로 컬 기술팀 유종필 팀장님과 같은 팀의 최태영 PD님께 특별히 감사드립니다. 반경을 이용한 SQLite Query와 Partial distance [cc lang="sql" width="100%" lines="-1"] SELECT id, ( 6371 * acos( cos( radians(lat1) ) * cos( radians( lat2 ) ) * cos( radians( lng2 ) - radians(lng1) ) + sin( radians(lat1) ) * sin( radians( lat2 ) ) ) ) AS distance FROM TEST_TABLE WHERE distance < 5 ORDER BY distance; [/cc] 위의 Query문은 현재 위도(lat1), 경도(lng1)를 기준으로 5km 반경안에 있는 정 보를 가지고 오는 Query 문입니다. lat2, lng2는 DB의 위도 경도 값입니다. 결국, distance를 SQLite의 function으로 구하여 alias를 준 후에, 5km보다 적은 값 을 가진 정보를 Query하는 것이죠. 앞에서도 말했듯이 sin, cos, acos과 같은 function을 지원해주지 않습니다. 그래서, 바로 distance를 구할 수 없습니다. 다른 방법을 찾기 위해, 두 지점의 거리를 구하는 공식을 분석해보겠습니다. [cc lang="sql" width="100%" lines="-1"] distance = 6371 * acos( cos( rad(lat1) ) * cos( rad( lat2 ) ) * cos( rad( lng2 ) - rad(lng1) ) + sin( rad(lat1) ) * sin( rad( lat2 ) ) ) [/cc] acos 안에 있는 계산식을 x라고 봤을 때,
  431. 436 KTH 개발자 블로그 베스트 [cc lang="sql" width="100%" lines="-1"] distance

    = 6371 * acos(x) [/cc] 즉, 6371 = distance * cos(x)입니다. 6371은 지구의 반경, 즉 6371km입니다. x값 을 통하여도 구할 수 있는 것이죠. 여기에서 x를 partial_distance라고 하겠습니다. partial_distance와 distance의 관계를 보면, 다음 그래프와 같습니다. 즉, partial_distance가 1이면 distance는 0, partial_distance가 1보다 작을 수록 distance는 멀어지는 것을 알 수 있습니다. 그리고, partial_distance를 Query문으로 계산하여 alias를 줄 수 있다면 반경으로 Query를 할 수 있습니다. 다음의 공식을 보시겠습니다. [cc lang="sql" width="100%" lines="-1"] partial_distance = cos( rad(lat1) ) * cos( rad(lat2) ) * cos( rad(lng2) - rad(l- ng1) ) + sin( rad(lat1) ) * sin( rad(lat2) ) [/cc] cos( rad(lat2) ), sin( rad(lat2) )는 미리 계산하여 db에 넣어 놓을 수 있지만, cos( rad(lng2) - rad(lng1) )는, lng1이 어떤 값이 될지 모르는 변수이기 때문에 미리 넣어 놓을 수 없습니다. 따라서 여기에서 cos(rad(lng2) - rad(lng1))을 분리시킬 필요가 있습니다.
  432. 437 Android에서 SQLite를 이용한 반경 내의 위치기반 정보 Query “cos(x-y)

    = cos x cos y + sin x sin y” 이므로, [cc lang="sql" width="100%" lines="-1"] partial_distance = cos( rad(lat1) ) * cos( rad(lat2) ) * ( cos( rad(lng2) ) * cos( rad(lng1) ) + sin( rad(lng2) ) * sin( rad(lng1) ) ) + sin( rad(lat1) ) * sin( rad(lat2) ) [/cc] 이제, lat2, lng2에 대해서 sin, cos 값을 미리 넣어놓으면 입력되는 lat1, lng1에 따 라 partial_distance를 구할 수 있습니다.(Stackoverflow : query-to-get-records- based-on-radius-in-sqlite 참고) 구현 코드 설명 먼저, sampleMapLocationOverlayActivity.java에서 Dummy 데이터를 DB에 쓰는 부분입니다. [cc lang="java" width="100%" lines="-1"] ArrayList list = new ArrayList(); for(int i = 1; i <= 1000 ; i++) { ContentValues values = new ContentValues(); String index = Integer.toString(i); double longitude = NumberUtils.getRandomNumber( (double)125.92319053333333f, (double)127.92319053333333f); double latitude = NumberUtils.getRandomNumber( (double)36.4922565f, (double)38.4922565f); values.put(DemoDB.Post.LATITUDE, latitude); values.put(DemoDB.Post.LONGITUDE, longitude); values.put(DemoDB.Post.COS_LATITUDE, Math.cos(LocationUtils.deg2rad(latitude))); values.put(DemoDB.Post.SIN_LATITUDE, Math.sin(LocationUtils.deg2rad(latitude))); values.put(DemoDB.Post.COS_LONGITUDE, Math.cos(LocationUtils.deg2rad(longi- tude))); values.put(DemoDB.Post.SIN_LONGITUDE, Math.sin(LocationUtils.deg2rad(longi- tude))); list.add(values); } ContentValues[] result = new ContentValues[list.size()]; list.toArray(result); getContentResolver().bulkInsert(DemoDB.Post.CONTENT_URI, result); [/cc]
  433. 438 KTH 개발자 블로그 베스트 Dummy로 넣을 위치기반 정보에 미리

    위도, 경도의 sin, cos 값을 넣어 놓습니다. 앞에서 설명드렸듯이 partial distance를 구하기 위함입니다. DemoProvider.java의 Query 부분입니다. [cc lang="java" width="100%" lines="-1"] String latitude = uri.getQueryParameter(DemoDB.Post.PARAM_LATITUDE); String longitude = uri.getQueryParameter(DemoDB.Post.PARAM_LONGITUDE); String partialDistance = uri.getQueryParameter(DemoDB.Post.PARAM_DISTANCE); if(partialDistance != null && latitude != null && longitude != null) { String sql = "SELECT *" +", "+buildDistanceQuery(Double.valueOf(latitude), Double.valueOf(longitude)) +" AS "+DemoDB.Post.PARTIAL_DISTANCE +" FROM "+DemoDB.Post.TABLE_NAME +" WHERE "+DemoDB.Post.PARTIAL_DISTANCE+" > "+partialDistance; if(limit != null && limit.length() > 0) { sql = sql + " LIMIT "+limit; } Log.e(TAG, "Sql =>"+sql); Cursor rawCusor = db.rawQuery(sql, null); return rawCusor; } [/cc] Query할때 buildDistanceQuery 함수는 다음과 같습니다. [cc lang="java" width="100%" lines="-1"] public static String buildDistanceQuery(double latitude, double longitude) { final double coslat = Math.cos(LocationUtils.deg2rad(latitude)); final double sinlat = Math.sin(LocationUtils.deg2rad(latitude)); final double coslng = Math.cos(LocationUtils.deg2rad(longitude)); final double sinlng = Math.sin(LocationUtils.deg2rad(longitude)); return "(" + coslat + "*" + DemoDB.Post.COS_LATITUDE + "*(" + DemoDB.Post.COS_LONGITUDE + "*" + coslng + "+" + DemoDB.Post.SIN_LONGITUDE + "*" + sinlng + ")+" + sinlat + "*" + DemoDB.Post.SIN_LATITUDE + ")"; } [/cc]
  434. 439 Android에서 SQLite를 이용한 반경 내의 위치기반 정보 Query 입력받은

    distance를 partial distance로 변환하고, DB의 위치기반 정보의 partial distance와 비교하여 반경내의 위치기반 정보를 얻어냅니다. 다음 사진은 데모 앱을 사용하여 반경으로 검색 된 정보를 지도상에 표시한 사진입니다. 주의하실 점은, 구글 맵을 사용하므로 Map Api key는 직접받아 수정해주시기 바랍니다. 정리 클라이언트 앱은 어느정도 서버에 의존적일 수 밖에 없습니다. 서버가 데이터를 내려 주기 전에는 확실한 데이터를 보여줄 수 없죠. 하지만, 서버가 내려주는 정보에만 의 존하는 클라이언트는 게으르다 생각합니다. 서버가 데이터를 잘못 내려줘도 클라이언트는 절대 죽어서는 안됩니다. 이건 기본이 죠. 거기에 한가지 더 더하고 싶습니다. “서버에 의존적인 클라이언트 앱은 게으르다” 서버에 의존하지 않고도 사용자에게 의미있는 정보를 보여 주는 것, 이것이 Detail의 시작이며 Quality라고 생각합니다. 이 포스트가 많은 개발자들에게 도움이 되었으면 합니다.
  435. 440 KTH 개발자 블로그 베스트 MemSQL이란? MemSQL은 디스크 병목을 최소화하기

    위해 만들어진 메모리 기반의 관계형 DBMS 입니다. 메모리 기반으로 데이터 처리가 이루어지기 때문에, 엄청난 속도로 Read/ Write이 가능하며, 기존의 NoSQL 또는 캐시로만 가능했던 퍼포먼스 향상이 있습니 다. 실제로 디스크 기반 DBMS 대비 약 30배 이상의 성능 향상이 있다고 하니, 놀라 울 따름입니다. 최근 들어 메모리 가격이 하루가 다르게 저렴해지고 있기 때문에 메모리 사이즈를 최 대한 늘려서 가격 대비 성능 비를 최대로 이끌어 내는 DB입니다. 메모리 기반 RDBMS, MemSQL을 알아봅시다 성동찬
  436. 441 메모리 기반 RDBMS, MemSQL을 알아봅시다 MemSQL 특징 강력한 SQL기반의

    통신 SQL 기반으로 통신하며, MySQL API를 따릅니다. 그렇기 때문에 기 존 MySQL을 사용하는 서비스 경우 로직 변경이 불필요하다고 합니다. 하다못해 라이브러리 또한 기존 MySQL에서 사용하던 그대로 재사용해도 상관 없습 니다. SQL기반이기 때문에 복잡한 데이터 처리에 유연하며, DB 레이어가 구분되므로 어 플리케이션에 영향을 의존적이지 않습니다. 사실 NoSQL이 강력한 성능을 발휘하기는 하지만, DB Schema와 같은 기반 요소가 어플리케이션에 녹아있고 사용이 어렵습니다. 그리고 데이터 처리 시 개발자 개인 역 량에 따라 전체적인 성능에 엄청난 영향을 주기도 하죠. 내구성이 좋은 구조 MemSQL은 서버가 예기치 않게 종료가 된다고 하더라도 데이터 유실이 거의 없습 니다. 서버 장애가 발생한다고 하더라도 Snapshot으로 특정 시점의 풀 백업 데이터 와 WAL(Write Ahead to Log)로 쌓인 데이터 변경 이력을 조합하여 “장애 시점 이전” 으로 데이터 버전을 되돌릴 수 있습니다.
  437. 442 KTH 개발자 블로그 베스트 물론 데이터 영속성이 불필요한 프로세스

    경우에는 "durability = off" 옵션으로 비활성 할 수 있습니다. 하지만, 이 경우 서버 재시작 후 메모리에 있는 모든 데이터는 소멸되 므로 사용 시 주의를 해야겠죠. ^^;; 쉬운 설치 및 사용 MemSQL은 설치가 정말로 쉬우며, 관련 Configure 파일도 단순합니다. 그리고 MySQL 진영에서 개발을 했었다면, 쿼리 사용에도 큰 무리가 없습니다. Transaction 기능 MemSQL은 트랜잭션을 단일 쿼리 레벨에서 Read Committed 레벨로 데이터를 처 리합니다. 사용자 레벨로는 Transaction을 제공하지 않기 때문에 복잡한 Transaction 이 요구되는 부분에서는 분명 한계가 있습니다. 만약 being, commit, rollback과 같은 구문을 어플리케이션에서 사용한다고 하더라 도, Warning 메세지와 함께 DB 내부에서 무시됩니다. 즉, 데이터 변경 질의가 완료되 는 바로 그 순간 다른 세션에서도 변경된 데이터를 바로 읽을 수 있습니다. Repeatable Read(Snapshot Read) Isolation Level은 내부적으로 Database Snapshot을 생성하기 위해 사용되는데, snapshot-trigger-size 임계치에 도달하여 새로운 Snapshot을 생성할 때 사용합니다.
  438. 443 메모리 기반 RDBMS, MemSQL을 알아봅시다 동시성과 퍼포먼스를 위한 인덱스

    기능 Hash Index Hash 인덱스는 1:1로 매칭되는 경우 최상의 성능을 발휘하며, Hash 인덱스를 사용하 기 위해서는 인덱스 필드에 Unique 옵션이 있어야 가능합니다. 그리고 Hash 인덱스 생성 시 BUCKET_COUNT 옵션을 별도로 줄 수 있고, 512에서 2^30까지 설정할 수 있는데, 데이터 사이즈에 따라 적절하게 파라메터 값을 지정해야 합니다. 파라메터 값 이 너무 작으면, Hash 효율이 크게 저하되고, 반대로 너무 크면 Hash Bucket을 위해 메모리가 불필요하게 많이 사용되기 때문이죠. 예를 들어 파라메터 값이 너무 작으면 빨간 색 그림처럼 한 개의 Hash 타깃에 여러 개 의 데이터가 포함되어 있으므로, 원하는 타깃 데이터를 선별하는 부분에서 로드가 발 생합니다. 그렇다고 파라메터를 너무 크게 잡으면 파란 그림처럼 메모리 공간만 잡고 아무 것도 포인팅하고 있지 않는 결과가 발생하죠. MemSQL측에서는 누적될 수 있는 데이터 최대치 Row 수의 50%로 설정하는 것이 바람직하다고 합니다. 즉, 하나의 Hash키에서는 평균 2개까지 중복되는 것이 성능 및 공간 효율적으로 최적이라는 것을 의미하는 것이죠. Skip List B-Tree는 일반적으로 RDBMS에서 제공하는 인덱스 구조이며, MySQL에서도 관련 기능을 제공합니다.
  439. 444 KTH 개발자 블로그 베스트 둘의 차이점은 MySQL은 디스크 기반으로

    B-Tree를 수행하나, emSQL은 메모리 기 반의 Skip List 구조로 데이터를 찾아냅니다. 데이터 접근 속도가 더욱 빠른 것이죠. 하단과 같이 인덱스를 ASC 옵션으로 생성된 경우, "Order By r ASC"로 Skip List로 빠르게 데이터에 접근할 수 있습니다. 그러나 “Order By r DESC” 경우에는 Skip List 를 사용하지 않기 때문에 상대적으로 속도가 느리다고는 합니다. 물론 DESC 옵션으로 추가적인 인덱스를 생성하면 동일하게 Skip List의 강점을 이용 할 수도 있겠지만, 인덱스 또한 공간을 잡아먹는 데이터이기 때문에 사용 상 주의가 필요합니다. [code lang="mysql"] memsql> CREATE TABLE tbl ( -> name VARCHAR(20) PRIMARY KEY, -> r INT, -> INDEX i USING BTREE (r ASC) -> ); memsql> EXPLAIN SELECT name FROM tbl ORDER BY r ASC; +-------------+------+------+-------+ | select_type | type | key | Extra | +-------------+------+------+-------+ | SIMPLE | ALL | i1 | | +-------------+------+------+-------+ memsql> EXPLAIN SELECT name FROM tbl ORDER BY r DESC; +-------------+------+------+-----------------------+ | select_type | type | key | Extra | +-------------+------+------+-----------------------+ | SIMPLE | ALL | i1 | memsql: requires sort | +-------------+------+------+-----------------------+ [/code]
  440. 445 메모리 기반 RDBMS, MemSQL을 알아봅시다 SQL을 선행 컴파일하여 처리

    SQL 실행 순서는 Oracle과 거의 흡사합니다. Parse → Code Generate → Plan Cache → Execute 단계를 거칩니다. Plan Cache에 적재된 SQL 실행 속도는 빠르지만, 처음 실행되는 SQL은 상당히 느립니다. 처리 단계를 조목조목 설명하겠습니다. • Parse 쿼리가 유입되면 SQL에 포함된 정수 혹은 문자열 파라메터를 특정 문자로 변환하는 과정입니다. 예를 들어 SELECT * FROM users WHERE id = 'gywndi';라는 쿼리는 SELECT * FROM users WHERE id = @;와 같이 변환됩니다. 물론 이 SQL Parsing 단계는 DB에 오버헤드가 거의 없습니다. • Code Generate Parsing 단계에서 생성된 SQL을 DB가 쉽게 처리할 수 있는 C++ 기반으로 변환하는 단계입니다. DB에서는 원 본 SQL이 아닌 데이터를 조회하기에 최적화된 코드에 따라서 데이터를 질의합니다. 결과는 바로 다음 단계인 Plan Cache 영역에 저장됩니다. • Plan Cache 전 단계에서 컴파일된 실행 계획을 Plan Cache 메모리 영역에 저장하며, 이후 동일한 타입의 SQL 유입 시 SQL 컴파일 단계 없이 Plan Cache에 있는 정보로 바로 처리합니다. • Execute 데이터 추출은 오직 선행 컴파일된 Plan정보로만 수행됩니다. 이제 SQL을 더이상 순차적으로 읽으며 분석하지 않 아도 되기 때문에 마치 NoSQL Solution처럼 혹은 그 이상의 속도를 낼 수 있는 것입니다. 처음 SQL 질의 요청이 들어오면 Parse → Code Generate → Plan Cache → Execute 단계를 거쳐서 데이터를 뽑아냅니다. 기존에 SQL을 실행하여 이미 Plan Cache에 관련 실행 계획이 저장된 경우에는 Parse → Plan Cache → Execute 단 계로 수행을 합니다. 실행 계획 생성 없이 Plan Cache에 저장된 정보로 바로 데이터 를 조회할 수 있습니다.
  441. 446 KTH 개발자 블로그 베스트 Concepts 메모리 기반의 RDBMS인 MemSQL은

    두 가지 컨셉으로 만들어졌습니다. Lock이 없는 Hash인덱스와 Skip List를 활용한 B-Tree인덱스를 사용함으로써 일반 CPU 에서도 강력한 데이터 처리가 가능합니다. 그리고 MVCC를 제공하기 때문에 엄청난 Writing이 발생함에도 절대 Reading 시 장애가 발생하지 않습니다. 두 가지 특징에 초점을 맞추어 개발을 하였고, 기존 디스크 기반 데이터 처리 속도 대 비 30배 이상 빠르다고 합니다. MemSQL 테스트 후기 Sysbench 툴을 사용하여 벤치마킹을 시도하려 하였으나, DB 특성이 다르다보니 테 스트를 할 수 없었습니다. 대신 다른 몇 가지 부분만 짚어서 단일 쿼리 테스트로 진행 을 하였고, 테스트 기간 동안 데이터 현황을 한번 살펴보았습니다. MemSQL Requirement가 일단은 CentOS 6.0 이상이었고, 해당 OS는 제 개인 블로 그 서버에만 설치되어 있었기 때문에 어쩔 수 없이 저사양 PC에서 테스트하였습니다. ^;; 테스트 환경 • CPU : E-350 (1.6GHz) • Memory : 8G • Disk : 3.5’ SATAII 5400 rpm Single • Data : 100만 건 Sysbench 툴로 100만 건 데이터를 생성하고, 해당 데이터로 간단한 질의 몇개와 기 본적인 차이점을 위주로 살펴보았습니다. MemSQL은 물론 메모리 안에 모두 데이터 가 존재하며, MySQL 또한 데이터 사이즈가 크지 않기 때문에 메모리에 전체 데이터 가 들어있다고 봐도 무관합니다.
  442. 447 메모리 기반 RDBMS, MemSQL을 알아봅시다 테스트 결과 100만 건

    일괄 업데이트에서는 MySQL이 더 빠릅니다. InnoDB Buffer Pool도 결국에는 메모리에 존재하기 때문이 아닐까 합니다. 그리고 업데이트 도중 다 른 세션에서는 현재 변경되고 있는 데이터 현황을 확인할 수 없는 것에서 쿼리 단위로 트랜잭션이 보장되는 것을 추측할 수 있었습니다. MemSQL에서 SQL이 처음 실행되는 순간, 즉 컴파일이 필요한 시점에는 상당히 느 립니다. 그러나 동일 타입의 쿼리가 다시 호출되는 경우 MySQL대비 10배 이상 빠른 결과를 보였습니다. MemSQL에는 Plan Cache가 있는데 이것에 관한 현황은 다음과 같이 조회할 수 있 습니다. [code lang="mysql"] memsql> SHOW PLANCACHE\G ************** 1. row ************** Database: sysbench QueryText: select * from sbtest where id = @ Commits: 113 Rollbacks: 0 RowCount: 2606 ExecutionTime: 5 LogBufferTime: NULL LogFlushTime: NULL RowLockTime: NULL ************** 2. row ************** Database: sysbench QueryText: select k, count(*) from sbtest group by k Commits: 7 Rollbacks: 0 RowCount: 53 ExecutionTime: 3611 LogBufferTime: NULL LogFlushTime: NULL RowLockTime: NULL ************** 3. row ************** Database: sysbench QueryText: INSERT INTO sbtest(k, c, pad) VALUES (?,?,?) Commits: 100 Rollbacks: 0 RowCount: 1000000 ExecutionTime: 19503 LogBufferTime: 0 LogFlushTime: 0 RowLockTime: 0 [/code]
  443. 448 KTH 개발자 블로그 베스트 각 정보는 누적된 결과이며, Plan

    Cache에 들어있으면, 그 이후로는 SQL 실행 시간 이 엄청하게 빨라집니다. (1번 쿼리는 평균 0.00005초 미만입니다.) 그러나! 질의를 만드는 도중 몇 가지 제약 사항을 알게 되었는데.. 기존에서 큰 무리 가 없던 쿼리 사용이 불가하다는 것입니다. 간단하게 두 개 정도 쿼리 예를 들겠습니다. [code lang="mysql"] memsql> update sbtest -> set k = cast(rand()*100000 as unsigned); ERROR 1707 (HY000): This query contains constructs not currently supported by MemSQL. The query cannot be executed. memsql> select count(*) -> from ( -> select id from sbtest -> where id between 1 and 100 -> ) t; ERROR 1707 (HY000): This query contains constructs not currently supported by MemSQL. The query cannot be executed. [/code] Update쿼리에는 함수가 아닌 상수 값이 지정되어야 하며, 위와 같은 타입의 서브쿼 리는 지원하지 않습니다. 즉 MySQL에서 MemSQL로 데이터를 이관한다고 하더라도 상당 부분 SQL 변경을 해야할 것 같네요^^;; 위 두 가지 외에도 더욱 많은 제약 사항들이 있을 것 같네요. Conclusion 트랜잭션을 지원하는 메모리 기반 DBMS이기 때문에 많은 기대를 하였으 나, 서비스에 직접적인 투입을 하기에는 아직까지는 한계가 있어 보입니다. 풍부한 기능을 가진 MySQL과 테스트에서는 기능적인 요소 뿐만 아니라 편의성 부분 에서도 부족합니다. MySQL 프로토콜을 사용기 때문에 접근성은 타 NoSQL보다는 수훨하나, 기 존 MySQL에서 데이터 이관 시 쿼리 또한 상당 부분 변경이 필요합니다. 그리고 Replicaion 기능과 Sharding에 관한 내용을 MemSQL에서는 소 개를 하였으나, 활용할 수 있는 메뉴얼을 현재까지 찾을 수 없었습니다. (현재 개발되고 있는 버전이 아닐까 생각이 드네요.)
  444. 449 메모리 기반 RDBMS, MemSQL을 알아봅시다 하지만 메모리 기반이고, NoSQL보다는

    접근성이 뛰어나며 단순 Select 테스트에서 도 MySQL대비 10배 이상 빠른 성능을 보인 것으로 보아 지속적으로 눈여겨 볼 필요 가 있는 제품일 것 같네요. ^^; DB 목적을 정확하게 정의하고 데이터 그룹 메타 정보 보관 혹은 해시 성격의 데이터 를 관리하는 시스템에서라면.. (SQL 종류가 다양하지 않은 단순 질의) 꽤나 좋은 성능 을 보이지 않을까요? 물론 서비스에 투입하기 이전에 DB 안정성 및 데이터 견고성에 관한 보장이 선행되어 야겠죠.^^ 참고자료 http://developers.memsql.com/
  445. 450 KTH 개발자 블로그 베스트 CVI(Customer Value Innovation)팀 내 조사/분석파트는

    시장동향분석, 고객리서 치, 고객데이터 분석 등을 통해 고객 Needs 및 Unmet Needs를 발굴하여 서비스 개선과 활성화를 위해 노력하는 조직입니다. 이번 조사의 목적은 이미 멋진 아이디어와 실력을 가진 개발사 또는 인디 개발자 분들 께서 이용자가 원하는 서비스를 만들기 위해 이용자관점에서 생각하고, 이용자 관 점에서 고민하는 기회를 가졌으면 하는 바램으로 기획되었습니다. 향 후에도 개발자 입장이 아닌 이용자 입장에서 고민하는 내용으로 많이 찾아 뵙도록 노력하겠습니다. 그럼 다음의 2012년 1분기 스마트폰 이용자조사에 대한 리뷰를 시 작해 보겠습니다. 2012년 1분기 스마트폰 이용자 조사 ▶ 조사제목 : 2012년 1분기 스마트폰 이용자 조사 ▶ 조사대상 : 스마트폰(팟게이트)이용자 총 7,815명 (아이폰 5,175명+안드로이드폰2,027명) 응답 ▶ 조사기간 : 2012년 3월29일 ~ 4월13일 ▶ 신 뢰 도 : 95% 신뢰수준의 오차범위 ± 1.11% 참고) 용어의 정의 : 구글 플레이는 쉬운 이해를 위해 안드로이드 마켓으로 표시하였습니다.(구글플레이=안드로이 드마켓) 연령 낮을수록 ‘스크린샷’, 높을수록 ‘앱설명’ 보고 앱 선택 이경은
  446. 451 연령 낮을수록 ‘스크린샷’, 높을수록 ‘앱설명’ 보고 앱 선택 모바일

    어플리케이션! 레드오션에에서 가능성을 찾아라. 다음 결과에 따르면 한달 평균 어플 설치수는 아이폰 6.6개, 안드로이드 폰 5.2개로 아이폰이 안드로이드폰 이용자보다 1.4개 높은 설치개수가 나타났고[참조-그래프1], 한달 평균 실제 이용하는 어플 수는 아이폰 13개 안드로이 드폰 11개로 2개 차이가 있었는데 달리 말하면 한 달에 출시되는 수 많은 어플 중 실 제 스마트폰에 설치되는 어플은 애플 앱스토어에서는 6.6개, 안드로이드 마켓에서는 5.2개 밖에 안 되는 치열한 레드오션 시장이기도 하다. 그러나 유선Web과 같이 1등이 고착화되어 있는 시장과는 달리 앱스토어이든, 안드로 이드마켓이든 1등 유지기간이 일주일이 넘기 힘들 정도로 유연함이 있고, 그 유연함 에서 오는 기회는 분명 있다. [참조:그래프2] [그래프1] 한달 평균 설치 어플수 [그래프2] 한달 평균 실제 이용하는 어플 수
  447. 452 KTH 개발자 블로그 베스트 어플 성공을 위해서는 대형마트 시식코너가

    되어야 한다. 이용자들이 어플 설치 시 가장 많은 영향을 미치는 요소 3가지를 물어본 결과, 아이 폰/안드로이드폰 이용자 모두 “유료/무료”를 고려한다는 항목이1위를 차지했다. 이용 자가 유료 어플에 대한 장벽을 얼마나 높게 생각하는지 알 수 있는 결과다. 이 결과에 따르면 아무리 잘 만든 어플이라도 무조건 돈을 지불해야 사용할 수 있다면 이용자들 이 최초 선택에서 아예 배제 될 확률이 높다는 것이다. 엄청난 마케팅 비용을 가지고 있는 대기업 개발사가 아닌 이상 처음부터 유료화로 접 근하여 이용자에게 선택 받을 확률을 스스로 낮추는 것 방법보다, 대형 마트의 시식코 너와 같이 적절한 양을 선정하여 ‘무료버전’ 또는 ‘어플 내 구입’ 방식을 통한 매출 발생 이 바람직할 것으로 보인다. [참조:그래프3~4] [그래프3] 아이폰 어플 설치 시 영향요인3가지 [그래프4] 안드로이드폰 어플 설치 시 영향요인 3가지
  448. 453 연령 낮을수록 ‘스크린샷’, 높을수록 ‘앱설명’ 보고 앱 선택 젊은

    스마트폰 이용자를 잡으려면 스크린샷/미리보기에 올인해라. 어플 설치에 영향을 미치는 요소 중 아이폰/안드로이드폰 이용자 모두 연령별로 공통 특성이 나타나는데 연령대가 높을수록 앱설명(아이폰이용자)/어플설명(안드로이드폰 이용자)이 연령대가 낮을수록 스크린샷(아이폰이용자)/미리보기(안드로이드폰이용자) 가 어플설치에 큰 영향을 받는다고 답했다. 이 결과에서 높은연령 이용자에게는 쉽고 자세한 어플설명을 제공하고, 젊은 연령층 에게는 스크린샷/미리보기를 통해 한정된 스크린샷 개수에서 어플의 특장점을 어떻 게 넣을지 전략이 필요하다. 이 결과를 미루어 볼 때  많은 개발자들이 스크린샷 중에 서도 가장 중요한 첫번째 스크린샷을 등록할 때 어플 실행 시 로딩화면을 등록 하는것 에 대해서는 큰 고민이 필요한 할 것으로 보인다. [참조:그래프5~6] [그래프5] 아이폰 어플 설치 시 영향요인 3가지-연령별 [그래프6] 안드로이드폰 어플 설치시 영향요인 3가지-연령별
  449. 454 KTH 개발자 블로그 베스트 디테일이 곧 높은랭킹을 보장한다. 이용자들이

    어플 설치 시 가장 많이 찾는 메뉴가 애플 앱스토어는 인기25, 안드로이드 마켓은 인기무료 메뉴로 나타났다. 어플 성공을 위해서는 우리가 만든 어플을 어떻게 든 인기25, 인기무료메뉴에 상위에 랭크 시켜야 한다. 이유는 상위에 랭크 되면 다시 다운로드가 되고, 다운로드 되면 다시 상위로 올라가는 선 순환이 일어나기 때문이다. 따라서 이용자들은 어떤 내용을 보고 우리 어플을 설치하는지? 이용자들이 보고 있 는 접점에서 우리어플이 얼마나 효과적으로 노출되고 있는지? 디테일을 고민해야 한 다. 그 디테일이란? [그래프5][그래프6]에서 보듯이 앱스토어에서는 리뷰/스크린샷/ 별점/앱설명, 안드로이드 마켓에서는 사용후기/어플설명/미리보기/별점/어플이름이 이에 해당할 것이다. [참조:그래프7~8] [그래프7] 아이폰 어플 설치 시 많이 찾는 메뉴 [그래프8]안드로이드마켓에서 어플설치 시 많이 찾는 메뉴
  450. 455 연령 낮을수록 ‘스크린샷’, 높을수록 ‘앱설명’ 보고 앱 선택 이용자의

    언어로 말하라~ 검색되지 않으면 존재하지 않는다. 이용자들이 어플 설치시 가장 많이 찾는 메뉴에 대해 연령별 분석을 해 본 결과 아이 폰/안드로이드폰 모두 낮은 연령층에서는 트랜드를 반영하는 인기메뉴의 선호가 나타 나고, 높은 연령일수록 검증된 추천메뉴에 대한 선호가 나타났다. 여기에서 아이폰의 검색 메뉴가 눈에 띄는데 만약 시간이 갈수록 어플 수가 많아진다 고 가정 한다면, 내가 필요한 어플을 앱스토어에서 찾는 게 더욱 어려워 질 것이고, 결 국 검색의 중요성이 부각될 것이다. 이는 우리의 과거 십수년간 PC Web에서의 이용행태를 보면 알 수 있는데 PC Web 의 초창기 때 인터넷 사용방법은 도메인을 외워서 홈페이지에 접근 했었고(URL직접 입력), 정보량이 조금 늘었을 때에는 잘 정리된 카테고리 홈페이지 사이트를 이용 했 었고(야후), 정보량이 엄청난 현재에는 검색사이트(구글) 이용할 수 밖에 없는 이유와 같다. 따라서 개발자는 어플 등록 시 이용자들이 검색으로 쉽게 찾을 수 있게 이용자 의 언어로 어플 이름을 만들고 어플을 등록할 때 입력하는 키워드 또는 태그를 충분히 고려하여 입력해야 한다. [참조:그래프9~10] [그래프9] 아이폰 어플 설치 시 많이 찾는 메뉴-연령별 [그래프10] 안드로이드마켓에서 어플설치시 많이 찾는 메뉴-연령별
  451. 456 KTH 개발자 블로그 베스트 타이밍과 완성도는 고객의 입장에서 생각하라

    모든 서비스 담당자는 런칭시점이 다가오면서 항상 같은 고민에 부딪 치는데, 그것은 타이밍과 완성도에 대한 고민이다. 보통 우리가 타이밍과 완성도의 우선순위를 정하 는 방법은 진입장벽이 낮으며 아이디어가 핵심인 어플인 경우는 선점의 우위를 점하 기 위해 타이밍이 우선이고, 유사 어플이 이미 출시 되었거나 경쟁이 치열한 어플인 경우는 완성도가 우선이다.는 결정이 힘을 받는다. 그럼 무엇이 정답일까? 아래 조사 항목에서 확인해 보자 아래 결과에서 보듯이 어플 삭제 후 재 설치경험의 58.6%이다, 58.6%의 수치를 긍정 적으로 본다면 약 10개중 6개는 재설치가 가능하고 우리어플도 6개에 해당될 수 있다 는 것이고, 58.6%의 수치를 부정적으로 본다면 약 10개중 4개는 재설치는 불가능하 고 우리어플은 4개에 해당되고, 순간의 판단 착오로 몇개월의 노력이 날라갈 수도 있 다는 것이다. 따라서, 만약 완성되지 않은 채 어플을 출시해야 한다면 사업자의 입장이 아니라 고객 의 입장에서 타이밍과 완성도를 충분히 고민해야 한다.[참조:그래프11~12]                                       게임은 타깃별 선호가 분명한 장르이므로 타깃별로 전략을 세워야 한다. 국내 이용자들의 선호게임장르를 알아본 결과 전체 선호게임장르는 퍼즐/보드로 나타 났고, 성별구분으로는 남성은 RPG/스포츠/디펜스게임, 여성은 퍼즐보드/아케이드/ SNG로 그 선호가 분명하게 나타났다. 신규 게임 장르 진출을 고민하는 개발자인 경 우 타깃 이용자의 선호 장르를 고려해 접근해야 하낟.[참조:그래프13~16] [그래프11] 어플삭제 후 재 설치경험          [그래프12] 어플 삭제 후 재설치경험 - OS별
  452. 457 연령 낮을수록 ‘스크린샷’, 높을수록 ‘앱설명’ 보고 앱 선택 [그래프13]

    선호게임 장르          [그래프14] 선호게임장르 - OS별 [그래프15] 선호게임 장르 - 성별                                         [그래프16] 선호게임 장르 - 연령별OS별 어플의 가장 중요한 시점은 출시 후 한 달이다. 실제 이용자 게임을 설치한 후 집중 플레이 시간을 알아 본 결과 일주일 정도 집중적 으로 플레이 한다는 이용자가 36.3%로 가장 많았고, 약 84.7%가 한달이내 플레이 한 다고 한다. 이는 디바이스별/성별/연령별로 상관없이 공통적으로 나타나는 현상이다. (단, 게임장르에 따라 SNG 게임 같은 경우는 집중플레이 기간이 2달을 넘게 한다는 내용이 상위에 있음) 게임을 한 달간 집중적으로 플레이 한 후 더 이상 이용하지 않는다는 결 론을 봤을 때, 개발사 입장에서는 한달 이내 투입비용을 모두 회수해야 손익분기을 맞출 수 있다는 결론이 나온다. 달리 말하면 그 만큼 모바일 게임이 트랜 드에 민감하고 수명이 짧기 때문에 앞선 기획을 해야하며 적절한 투입자원 고려가 게 임 어플 수익창출의 큰 변수가 된다는 것을 알 수 있다.
  453. 458 KTH 개발자 블로그 베스트 [그래프17]설치 후 집중 플레이 기간           

                            [그래프18] 설치 후 집중 플레이 기간 - OS별 [그래프19]설치 후 집중 플레이 기간 - 성별                            [그래프20] 설치 후 집중 플레이 기간 - 연령별 이번 조사를 진행하면서 짐작으로 알고있는 내용을 확인하는 내용도 있고, 생각 지도 못했던 내용을 알 수 있는 기회도 되었지만 가장 중요한 것은 이 자료가 공유 되면서 동일한 데이터를 보면서 다양하게 해석 될 수 있는 기회가 생겼다는 것인 것 같습니다. 혹시 의견 및 제안 내용이 있으시면 언제라도 댓글로 작성해 주시고, 주신 의견은 다음 조사 진행 시 적극 반영하도록 하겠습니다. 대단히 감사합니다.~~^^ ▶ 조사제목 : 2012년 1분기 스마트폰 이용자 조사 ▶ 조사대상 : 스마트폰(팟게이트)이용자 총 7,815명 (아이폰 5,175명+안드로이드폰2,027명) 응답 ▶ 조사기간 : 2012년 3월29일 ~ 4월13일 ▶ 신 뢰 도 : 95% 신뢰수준의 오차범위 ± 1.11%
  454. 459 앱 설치 시 사용자들의 리뷰 영향력 높아져 CVI(Customer Value

    Innovation)팀 내 조사/분석파트는 시장동향분석, 고객리서치, 고객데이터 분석 등을 통해 고객 Needs 및 Unmet Needs를 발굴하여 서비스 개선 과 활성화를 위해 노력하는 조직입니다. “스마트폰 이용자 분석”의 목적은 스마트폰 서비스를 제작하셨거나 계획하고 계신 개 발사 또는 인디 개발자분들께 이용자 관점에서 생각하고, 고민하는 기회를 가졌으면 하는 바램으로 기획 되었고, 지난번 «2012년 1분기 스마트폰 이용자 조사”에 이어 2 번째 조사로 1분기 조사의 추이분석을 중심으로 작성 되었습니다. “2012스마트폰 이용자 조사 시리즈”는 2012년 분기마다 제공될 예정이며, 해당 자 료가 스마트폰 서비스를 개발/운영 하시는데 조금이나마 도움이 될 수 있도록 노력 하겠습니다. 앱 설치 시 사용자들의 리뷰 영향력 높아져 김일화
  455. 460 KTH 개발자 블로그 베스트 2012년 2분기 스마트폰 이용자 조사

    ▶ 조사제목 : 2012년 2분기 스마트폰 이용자 조사 ▶ 조사기간 : 2012년 6월26일 ~ 7월 6일 ▶ 신 뢰 도 : 95% 신뢰수준의 오차범위 ± 1.27% ▶ 조사대상 : 스마트폰(팟게이트)이용자 총 5,983명(아이폰 4,088명+ 안드로이드폰2,027명)응답 참고) 용어의 정의 : 구글 플레이는 쉬운 이해를 위해 안드로이드 마켓으로 표시하였습니다.(구글플레이=안드로이드 마켓) "리뷰/사용후기"의 솔직한 관리 필요 어플 설치 시 가장 영향을 많이 받는 요소를 마켓별로 보면 아이폰인 경우는 "유 료/뮤료 > 리뷰 > 랭킹 > 스크린샷 > 별점 > 앱설명" 순이며, 안드로이드폰인 경우 는 "유료/무료> 사용후기 > 다운로드 수 > 랭킹 > 미리보기 > 별점" 순으로 나타났 다. 1분기 조사때와 순위변동은 없었으나, 2개의 마켓 모두 "리뷰(사용후기)"에 대한 영향이 공동 상승했음을 보여주고 있다. [참조:그래프1~2] “리뷰(사용후기)”가 어플 다운로드에 많은 영향을 준다고 해서 간 혹 지인들을 동원 한 리뷰 조작의 유혹에 빠져 버릴 수 있는데, 그 유혹을 이기지 못하고 한쪽으로 편중 된 별점과 의미없는 리뷰가 등록 되면 이용자들이 금방 '알바'로 인지하게 되며, 장기 적 관점에서 리뷰(사용후기)라는 소중한  소통채널을 잃어버리거나, 서비스 자체의"기 대관리"를 저해하는 결과로 되돌아오기도 한다. 따라서 "리뷰(사용후기)"에 대한 긍정적인 관리가 필요한데 그 방법으로 ①부정적인 리뷰에 나타난 서비스오류 등을 개선한 후 안내의 창으로 이용②급한버그 발생시 공 지사항으로 이용 ③자주하는 질문 등의 답변창구로 이용 등등이 올바른 예이다. 사실 부정적인 "리뷰/사용후기" 보다 더 안 좋은 상황은 아예 "리뷰/사용후기"가 등록 되지 않은 것인데 이 때는 고객의 리뷰작성을 기다리는 것아 이니라 적극적으로 리 뷰를 요청하는 기획이 필수이다. 그렇다고 전체고객에게 일괄 리뷰 요청할 것은 초보 기획자들이 흔히 범하는 실수일 것이다. 그 이유는 고객이 우리 서비스를 이용하면서 부정적인 경험을 하고 있는 타이밍에 리뷰가 요청될 수 있기 때문이다. 따라서, 이용 자들이 우리 서비스를 이용하면서 가장 행복한 지점이 어디인지(?) 고민하고 리뷰를 요청하는 센스가 필요하다.
  456. 461 앱 설치 시 사용자들의 리뷰 영향력 높아져 [그래프1] 아이폰-어플

    설치에 영향 요인 3가지(%)    [그래프2] 안드로이드폰-어플 설치에 영향 요인 3가지(%) 가장 많이 찾는 메뉴는 여전히 "인기/추천" 메뉴 어플 설치 시 가장 많이 찾는 메뉴는 아이폰인 경우 "인기25, 추천"이며, 안드로이드폰 인 경우는 "인기무료어플리케이션, 추천어플리케이션" 이다. 이는 1분기 조사와 변화 가 없으며, 이 결과는 다운로드를 많이 받기 위해 우리 어플이 "인기/추천"메뉴에서 눈 에 잘 띄기 위해 상위순위에 진입해야 하고, 상위 순위를 진입해서 다운로드를 많이 받게되면, 다시 상위 순위를 유지할 수 있는 선순환 구조를 만들어야 함을 이야기 한 다. 그렇다면 최초 상위순위를 어떻게 하면 들어갈 수 있을까? 에 대한 고민이 필요 하다. 만약 어플을 출시한 개발자분들 중 마케팅을 하지 않았는데, 출시 하자마자 갑자기 1~2일정도 순위가 갑자기 상승한 경험을 한 분들이 있을 것이다. 우린 그런 현상
  457. 462 KTH 개발자 블로그 베스트 을 자동차의 "신차효과"의 말을 빌어

    "What's new 효과"라고 명명 하는데, 이런 현상 은 앱스토어인 경우는 "신규"메뉴에 안드로이드마켓인 경우는 "새 인기 유/무료 어플 리케이션" 메뉴에 노출되기 때문에 나타나는 현상이다. 그렇다면 아무런 마케팅 액션 없어도 누구에게나 어플 출시 당일에 한번의 상승 기회 가 있다는 것인데, 만약 마케팅을 준비하고 있다면 그 효과를 극대화 할 수 있는 시점 또한 그 출시 당일이 될 것이다.  마케팅 예산만 많으면 한번 순위가 하락해도 다양한 마케팅 활동으로 순위를 상승시키면 되지만, 그렇지 않다면 무료로 얻게되는 상승시 점에 탄력을 붙여 올리는 처음이자 마지막 기회를 놓치지 말자. 만약, 서비스 런칭을 위해 몇일 밤을 보냈다면 런칭 시점을 조금 늦추는 것도 차선책이 될 수 있을 것이다. [참조:그래프3~4] [그래프3] 아이폰-어플 설치시 가장 많이 찾는 메뉴 [그래프4] 안드로이드폰-어플 설치시 가장 많이 찾는 메뉴
  458. 463 앱 설치 시 사용자들의 리뷰 영향력 높아져 어플 뿐

    아니라 "모바일웹의 이용률이 높아짐" 스마트폰 이용자에게 모바일웹과 어플 이용 행태를 작년 4분기 결과와 비교해 보니 모 바일 웹 이용량은아이폰(18% > 30%)과 안드로이드폰(25%>37%) 모두 증가하였고,어 플 이용량은 아이폰(55%>44%)과 안드로이드폰(46%>36%)로 모두 감소하였다. 이는 스마트폰이 PC의 대체제의 역할을 하면서 PC의 웹서핑 이용패턴이 스마트폰으 로 전이 되었다고 볼 수 도 있으며, 네이티브 어플에서만 제공할 수 있었던 사용자 경 험(User eXperience)을 굳이 어플로 만들지 않아도 모바일웹에서도 제공해 줄 수 있 는 많은 기술들이 나타난 결과로도 볼 수 있다. 또한, 다음 그래프에서 결과가 주는 많은 시사점 중에 한 가지는 이용자들이 모바일 웹의 사용량이 지속적으로 증가 된다면 모바일 시대로 넘어가면서 개발자들이 쏟아 지는 신기술을 습득해야 하는 스트레스 중 Xcode를 가지고 "Hello World"를 찍기 위 해 받는 스트레스는 조금은 덜게 되지 않을까? 조심스럽게 예상해 본다. [※참고 : 아래 "모바일웹 VS 어플 이용비중" 그래프는 반기(6개월)에 한번씩 진행되는 조사항목으로 2012년 2Q 는 2011년 4Q와 비교된 그래프임 ][참조:그래프5~6]    [그래프5] 아이폰-모바일웹 VS 어플 이용비중
  459. 464 KTH 개발자 블로그 베스트 [그래프6] 안드로이드폰-모바일웹 VS 어플 이용

    비중 어플 시장은 아직 "도전이 가능한 시장" 주 이용어플의 고착화 정도를 물어보는 질문에서 "내가 사용하고 있는 어플이 정해 져 있다"라는 답변이 아이폰(67% > 56%)과 안드로이드폰(60%>57%) 모두 감소하였 다. 지속적으로 추이변화와, 이용률이 감소된 개별 종류도 확인해야 하겠지만, 아직까 지 유선시장과 달리 어플 시장은 유동적인 것으로 확인 된다. 이 결과는 기존 메이저 어플들도 끊임없는 도전을 받는 시장이고, 신규어플에게는 끊 임없이 도전할 수 있는 시장임을 말해 준다. [※참고: 아래 "주 이용어플 고착화 정도"는 반기(6개월)에 한번씩 진행되는 조사항목으로 2012년 2Q는 2011년 4Q와 비교된 그래프임 ] [참조:그래프7~8]    [그래프7] 아이폰 주 이용어플 고착화 정도
  460. 465 앱 설치 시 사용자들의 리뷰 영향력 높아져 [그래프8] 안드로이드폰-주이용어플

    고착화 정도 어플이름 및 키워드(TAG)의 중요성 대두 이용자들이 2011년 4분기에 비해 당일 설치한 어플들을 당일 삭제하는 않는 비율이 증가 하였다. 이유는 첫번째 이용자가 당일 설치 후 어플을 즉시 확인하지 않아 나타 나는 현상일 수 있으며, 두번째 본인이 필요한 어플을 설치하였기 때문에 즉시 삭제하 지 않았을 것으로 예상되는데, 만약 두번째, 필요한 어플을 본인이 찾아 설치하는 비 율이 높아졌다면 아이폰, 안드로이드폰 모두 검색의 중요성이 높아질 것이므로, 어플 등록시 이용자들에게 자사어플을 잘 검색될 수 있도록 “어플이름/키워드(TAG)”에 더 욱 많은 노력이 필요할 것이다. [※주의: 다음"설치 당일 어플 삭제 비율"은 반기(6개월)에 한번씩 진행되는 조사항목으로 2012년 2Q는 2011년 4Q와 비교된 그래프임 ][참조:그래프9~10]
  461. 466 KTH 개발자 블로그 베스트 [그림9]아이폰-설치 당일 어플 삭제 비율

    [그림10]안드로이드폰-설치 당일 어플 삭제 비율 스마트폰 게임 성장은 당분간 지속 2분기 스마트폰 게임 이용경험을 묻는 질문에서 아이폰(84% > 87%), 안드로이드폰 (72% >76%) 이용자 모두 상승하였다. 명확한 수익모델 기획이 가능한 카테고리중 하 나가 게임 카테고리이기 때문에, 개발사 입장에서도 수익이 목표라면 타 카테고리에 비해 매력적인 카테고리인 임에는 분명하다. 따라서, 더 많은 개발사가 게임 카테고리에 도전할 것이고, 양질의 게임이 출시되면 이용율은 더욱 높아질 것으로 예상된다. 게임 개발사 입장에서는 이용자가 많이 찾는
  462. 467 앱 설치 시 사용자들의 리뷰 영향력 높아져 카테고리에 있다는

    것만으로 기회일 수 있지만, 그 만큼 치열한 경쟁이 예상되므로 더 욱 철저히 준비해야 하는 상황이다. [참고:그래프11~12] [그래프 11] 아이폰-모바일게임 이용경험 [그래프 12] 안드로이드폰-모바일게임 이용경험 다운로드 이후 두달 이상 플레이하는 게임장르는 SNG 게임 집중 플레이 기간을 일주일이 가장 많은 비율을 차지하고 있으며, 폰별로는 안드 로이드폰이 2달이상 플레이하는 비율이 아이폰보다 2.3% 높으며, 연령이 높을수록 남성보다는 여성이 오랜기간 게임을 플레이 하며, SNG 게임장르가 타 장르에 비해 오랫동안 게임을 플레이하는 것으로 나타났다.
  463. 468 KTH 개발자 블로그 베스트 게임 수명을 연장을 위해서는 게임레벨

    조정을 통해 일주일 이내에 흥미를 잃지 않게 만들어야 하며, 초기에 떠나는 10~20대 층과 남성을 잡기 위한 전략을 일주일이내 에 진행해야 하며, 게임장르는 SNG게임이 조금 더 유리한 것으로 예상 된다. [참고: 그래프13~16]    [그래프13] 집중 플레이 기간 - 폰별 [그래프14] 집중 플레이 기간 - 연령별
  464. 469 앱 설치 시 사용자들의 리뷰 영향력 높아져    [그래프15]

    집중 플레이 기간 - 성별 [그래프16] 집중 플레이 기간 - 장르별 아이폰이 안드로이드폰 보다 수익률이 10% 높음 아이폰이 안드로이드폰보다 10% 정도 유료구매 경험이 많고, 아이폰은 1천원~2천 원, 1만원이상 구매금액범위에서 높이 나타나 양극화 되는 현상을 보이며, 안드로이 드폰은 아이폰과 동일하게 1천원~2천원대 구매가 가장 많지만 2천원~5천원까지 구 매 범위가 고루 분포됨을 알 수 있다. 어떤 종류의 앱부터 만들어야하지? 고민 한다면 통계적으로 10% 높은 수익이 보장되는 아이폰 어플을 먼저 출시하는 것이 바람직할 것으로 보인다.
  465. 470 KTH 개발자 블로그 베스트    [그래프17] 유료 게임어플 구매경험

    [그래프18] 유료 게임어플 구매금액 위 내용 중에는 너무 당연한 결과도 있고, 예상과 다른 데이터와 해석도 있습니다. 1 분기 조사 에서도 말씀 드렸듯이 이 자료가 공유되면서 동일한 데이터를 보면서 다 양하게 해석될 수 있으므로 많은 의견/조언/제안 등을 주시면 차 후 조사 진행시 적 극 반영하도록 하겠습니다. 대단히 감사합니다.~~^^ ▶ 조사제목 : 2012년 2분기 스마트폰 이용자 조사 ▶ 조사기간 : 2012년 6월26일 ~ 7월 6일 ▶ 신 뢰 도 : 95% 신뢰수준의 오차범위 ± 1.27% ▶ 조사대상 : 스마트폰(팟게이트)이용자 총 5,983명(아이폰 4,088명+ 안드로이드폰 2,027명)응답
  466. 471 앱스토어! Blue Ocean인가? Blood Ocean인가? 이번에 진행 된 분석결과는

    2011년 1월1일부터 2012년 6월30일까지 국내 앱스토어 무료 300위까지의 순위 데이터를 반기별(6개월)로 그룹핑하여 이용자의 3반기 (1반 기=6개월) 추이를 분석한 내용입니다. 이번 고객기반의 분석자료가 현재 어플을 준비하고 계시거나, 운영하고 계시는 개발 자 분들께서 고객관점에서 고민할 수 있는 계기를 마련하는데 조금이라도 도움이 되 었으면 좋겠습니다.~ ▶ 주 제 : 애플 KR앱스토어 이용자 행태분석 추이 ▶ 부 제 : 앱스토어! Blue Ocean인가? Blood Ocean인가? ▶ 분석대상 : 국내 애플 앱스토어 무료어플 랭킹 300위 어플 ▶ 분석기간 : 2011년 1월 1일 ~ 2012월 6월 30일(18개월) ▶ 분석방법 : “2011년 상반기/2011년 하반기/2012년 상반기” 3반기로 그룹핑하여 추이분석 ▶ 자료제공 : ODDM - 팟게이트 (Rawdata 제공) 애플 KR앱스토어 이용자 행태추이 분석 앱스토어! Blue Ocean인가? Blood Ocean인가? 김일화
  467. 472 KTH 개발자 블로그 베스트 300위 내 랭크 되는 어플이

    1년전 대비 36% 증가 애플 앱스토어 무료 300위 내 랭크 된 어플 개수가 2011년 상반기 2,097건 대비 2012년 상반기 2,842건으로 36% 증가 되었다. 어플 개수의 증가는 어플시장의 치열 함을 말해 주고 있다. [참조:그래프1] [그래프2]에서는 1위에 랭크 된 어플의 개수가 일정한 패턴을 갖는 것은 아니지 만 2011년 상반기 66건 대비 2012년 상반기에는 58건으로 감소 되었다. 동일 기간에 1위하는 개수가 감소되었다는 말은 1위하기가 더욱 힘들다는 것을 말 해 준다. (단, 몇 개의 스타 어플이 1위를 오랫동안 유지할 경우 개수추이에 큰 영향을 줄 수 있으므로, 1위 어플 개수 증감을 통한 해석은 주의할 필요가 있다.) [참조:그래프2] [그래프1] 순위별 어플 개수 [그래프2] 동일순위 연도별 증감추이
  468. 473 앱스토어! Blue Ocean인가? Blood Ocean인가? 300위 내 많은 어플이

    랭크되어도 1위에 랭크되는 어플은 경쟁력 있는 2~3%의 어플에 불과 300위 내 어플 중 1위를 한번이라도 하는 어플의 비율을 보면 약 2~3%이고, 추이 는 시간이 갈 수록 “2011년 상반기(3.1%) > 2011년 하반기(2.9%) > 2012년 상반 기(2.0%)”로 줄어 들어드는 것으로 확인되었다. 1번 결과에서 보면 300위내 랭크되 는 수가 많아지고 있지만 이 중 경쟁력 있는 몇 개의 어플만이 1위를 차지하는 것으로 보인다. [참조:그래프3] [그래프3]300위 내 어플 중 자체 최고순위 개수 비율 시간이 갈수록 상위 순위에 랭크되기 어려움 300위내 어플의 최고 순위를 다음 [그래프4]와 같이 구간별로 비교해 보면, 시간 이 지날수록 “1~5위”, “1~10위” 이내로 랭크되는 어플의 수는 줄어드는 것으로 확 인 되었다. 즉 시간이 갈수록 상위 순위에 랭크되는 것이 어렵다는 것을 알 수 있다 [참조:그래프4~5] [그래프4]300위 내 어플 중 순위별 현황
  469. 474 KTH 개발자 블로그 베스트 [그래프5]300위 내 어플 중 순위별

    현황 상위(25위내) 유지일수가(8.2일 > 6.9일 > 6.4일)로 시간이 갈수록 짧아짐 앱스토어 첫 페이지에 노출되는 25위를 대상으로 25위내 유지일수가 몇 일인지? 확 인 한 결과 2011년 상반기는 평균 8.2일, 2011년 하반기는 평균 6.9일, 2012년 상 반기는 평균 6.4일로 시간이 갈수록 25위 내 유지기간이 짧아지고 있었다. [참고:그 래프6~8] [그래프9]에서 반기별 추이를 보면 유지일수의 최고봉이 시간이 갈수록 좌측으로 이 동하는 것으로 볼 때, 25위내 순위 유지가 힘들다는 것을 다시 한번 확인할 수 있다. [참고:그래프9] [그래프6] 25위 유지일 2011년 상반기
  470. 475 앱스토어! Blue Ocean인가? Blood Ocean인가? [그래프7] 25위 유지일 2011년

    하반기 [그래프8] 25위 유지일 2012년 상반기 [그래프9] 25위 유지일 2011년 상반기~2012년 하반기
  471. 476 KTH 개발자 블로그 베스트 성장하는 인기 카테고리는 “게임”, “사진및비디오”,

    “소셜네트워킹”, “건강 및 피트니스” 국내 앱스토어에서 인기 카테고리 추이를 3반기 연속 증가한 카테고리로 확인 해보면 “게임”, “사진및비디오”, “소셜네트워킹”, “건강 및 피트니스” 순이며, 엔터테인먼트 카 테고리의 하락은 기존에 엔터테인먼트에 속해 있던 게임이 2011년 11월 한국스토어 에서 오픈 후 게임카테고리로 이동했기 때문으로 분석된다. [참고-그래프6] [그래프6]300위 내 반기별 카테고리 어플개수 추이 오랜기간 사랑받는 카테고리는 “소셜네트워킹”, 가장 많은 개수의 어플이 사랑받는 카테고리는 “게임” 앱스토어 첫 페이지인 25위 내에 가장 많은 어플을 랭크시킨 카테고리는 3반기 공통 으로 “게임”, “엔터테인먼트”이며, 25위 내 오랫동안 어플을 머무르게 한 카테고리는 3반기 공통으로 “소셜네트워킹”이 차지했다. 그러나 [그래프7~9]에서 보듯이 “엔터테인먼트”, “게임” 같은 경우는 많은 어플을 출 시함에도 불구하고 오랫동안 상위권에 머무르지 못하는 특징을 보였다. 그 이유는 1) 워낙 많은 어플들이 출시되기 때문일 수도 있고 2) 이용자들이 바라보는 “엔터테인먼 트”, “게임” 카테고리의 수명이 길지 않다고 할 수도 있겠다. 그럼에도 불구하고 개발자들이 “게임” 카테고리에 이렇게 치열하게 도전하는 이유 는 첫 번째가 고객들이 많이 찾는 카테고리라는 것이고, 두 번째 광고 이외에 명확 한 수익모델이 없는 다른 카테고리에 비해 “유료게임”이라는 비교적 고객들이 인지 하고 있는 수익모델을 통해 수익을 창출 할 수 있다는 가능성이 보이기 때문이라고 생각해 볼 수 있다.
  472. 477 앱스토어! Blue Ocean인가? Blood Ocean인가? 그에 반에 “소셜네트워킹” 카테고리는

    서비스 특성상 초기 관계형성을 실패할 경우, 아예 상위에 랭크 되지도 못하는 경우도 있지만, 소셜네트워킹 서비스의 핵심인 관계 형성이 캐즘(Chasm)을 돌파할 경우 기하급수적으로 이용자가 늘어나 오랫동안 상위 에 랭크 될 수 발판을 만들 수 있는 카테고리이라 할 수 있겠다. 만약 위의 내용을 바탕으로 아주 친밀한 “소셜네트워킹” 기반의 “게임”을 개 발한다며 고객이 원하는 니즈를 충족해 줄 수 있지 않을까? 예상해 본다. [참고:그래프7~9] [그래프7]25위 카테고리별 어플개수 및 유지일-11년(상) [그래프8]25위 카테고리별 어플개수 및 유지일-11년(하)
  473. 478 KTH 개발자 블로그 베스트 [그래프13]25위 카테고리별 어플개수 및 유지일-12년(상)

    스타 어플들이 1위를 오랫동안 유지하는 형태로 앱스토어가 변화됨 1위 어플의 1위 유지일을 반기별로 확인한 결과, 5일 이상 1위를 유지한 어플이 2011 년 상반기에는 7개였지만, 2012년 상반기에는 약 2배 수준인 13개의 어플이1위를 유 지 하였다. 즉, 위 1~2번 결론에서 보듯이 2012년에 많은 어플이 출시 되었음에도 불구하고 1위 에 랭크되는 어플의 숫자가 적은 이유가 2012년 상반기에는 소위 잘나가는 (스타어플) 들이 오랫동안 1위에 머무르면서 일어나는 현상으로 확인 되었다. [참조:그래프14] [그래프14] 반기별 1위 어플의 1위 유지일 (5일이상 1위를 한 어플만 추출하여 표시)
  474. 479 앱스토어! Blue Ocean인가? Blood Ocean인가? 메신저어플 > TV시청어플 >

    사진관련 어플로 트랜드 변화 중 1개월(30일)이상 25위 내 유지한 어플을 반기별로 분석한 결과 2011년 상반기에는 “카카오톡”, “마이피플”,”올리브폰”과 같이 메신저 어플들이 높은 유지일을 보였고, 2011년 하반기에는 “카카오톡”의 롱런과 함께 pooq의 인기가 나타났으며, 2012년 상반기에는 “KakaoStory”를 비롯하여 사진관련 어플이 주요 트랜드로 확인되고 있으 며 당분간 유지될 것으로 예상된다. 따라서 과거 디카의 보급 및 뽀사시 기능의 발전이 싸이월드 전성기와 비례했다는 것 을 볼 때, KakaoStory와 같은"사진SNS"가 발전할 수록 더 좋은 사진을 등록하고자 하는 고객니즈가 있을 것이므로, 해당 어플에서 제공하지 않고 있는 다양한 필터, 편 집, 꾸미기 기능 등을 제공하는 어플이 출시 된다면, 사진관련 SNS 인기 상승과 함께 부가적인 혜택을 누릴 수 있는 기회가 될 것으로 예상된다. [참조:그래프15] [그래프15]반기별 25위내 30일 이상 유지한 어플 리스트 위 결과를 전체적으로 정리해 보면 앱스토어 시장이 시간이 갈수록 어플 출시는 많이 되고, 경쟁이 치열하며, 상위권에 진입하기 조차 힘들고, 비록 상위권에 진입한다고 해도 오랫동안 상위권을 유지하기가 쉽지 않게 되었다. 또한 몇몇의 스타어플들이 상위권을 오래 유지하는 구조가 나타나서 어플 간에 빈 부 격차가 심화되고 있음을 보여 주고 있으므로 과거 어플을 만들기만 하면 관심 받 던 “Blue Ocean”의 시대는 지났고, 완벽한 준비와치열한 경쟁을 통해서만 성공하는 “Blood Ocean” 시대으로 진입한 것으로 예상된다. 따라서, “선 출시 후 수정”이라는 초기시장의 타이밍 전략보다는, 고객관점으로 서비 스를 고민하고, 치밀한 준비와 높은 품질로 승부하는 중기시장 전략을 가져가야만 앱 스토어에서의 결실을 볼 수 있을 것이다.
  475. 480 KTH 개발자 블로그 베스트 요약 ① 300위내 랭킹 경쟁

    어플이 1년사이 35%가 증가되었다. ② 아무리 많은 어플이 출시되어도 경쟁력 있는 2~3%만 1위를 한다. ③ 시간이 갈수록 상위 순위에 랭크되기 어려움 ④  앱스토어 첫 페이지인 25위 유지율 일수는(8.2일 > 6.9일 > 6.4일)로 시간이 갈수록 짧아 진다. ⑤ 성장하는 카테고리는 “게임”, “사진및비디오”, “소셜네트워킹”, “건강 및 피트니스” 이다. ⑥ 오랜기간 사랑받는 카테고리는 “소셜네트워킹”, 가장 많은 수의 어플이 사랑받는 카테고리 는 “게임” ⑦ 스타 어플들이 1위를 오랫동안 유지하는 특징이 나타난다. ⑧ 메신저어플 > TV시청어플 > 사진관련 어플로 트랜드 변화가 있다.
  476. 481 위대한 Product Leader 되기 바쁘신 분들을 위한 핵심 요약

    Product Leader란 어떤 역할을 해야할까요? 우리가 어떤 시합을 하고 있고, 어떤 상 태가 성공한 상태인지 측정하는 방법을 알고 공유해야 합니다. 당장 수행해야할 다음 계획들에 대한 명확한 우선순위 리스트도 물론이죠. 이 외에도 팀의 일을 되게 만드 는 작업이라면 무엇이든 챙겨야 합니다. 제품 스펙정하기, 예외상황처리, 시간/기능 의 트레이드오프 다루기, 우리것과 상대쪽 제품 분석등을 포함해서 말입니다. 위대한 Product Leader라면 변화가 생겨나고 일을 되게 만듭니다. 이 글의 저자와 주제에 대하여 이 글의 저자인 Adam Nash는 기술분야의 매니저로써 오랜 활동을 했던 사람입니다. 직업 인맥 SNS로 유명한 LinkedIn의 전 부사장이자, Product Manager로 4년간 매 우 성공적으로 활동했으며, 2011년 10월부터 Greylock이라는 벤처캐피털에 합류하 였습니다. 기술 전반을 파악하고, 제대로 된 제품 또는 서비스를 뽑아내는 일을 직업 으로 해오다가, 이제는 신생 벤처회사들을 찾아내고 투자하고, 또 자신의 경험을 이용 해 그들의 멘토가 되어 지도하는 그러한 일을 하고 있습니다. 위대한 Product Leader 되기 김일화
  477. 482 KTH 개발자 블로그 베스트 오늘 살펴 볼 글은 http://blog.adamnash.com

    에 포스팅된 “Be a Great Product Leader” 란 글입니다. 당연하겠지만 이 글에서 말하는 Product는 실제 손에 잡히는 공업제품이라기 보단, 우리가 만들어내는 서비스나 소프트웨어를 이야기 합니다. 이 것들을 만들 때 팀의 Product Leader(PL)이나 Product Manager(PM)이 어떤 역할 을 해줘야 하는지에 대해 기술한 글입니다. 위대한 Product Leader가 되기 (Be a Great Product Leader) – 번역 전문 원문(http://blog.adamnash.com/2011/12/16/be-a-great-product-leader/) 저자 : Adam Nash (저자는 수동형 표현을 즐겨 쓰지만, 우리말로 쉽게 이해하기 위해 일부 표현을 능동 형으로 의역하였습니다.) 저를 잘 아는 사람들은 제가 Product Management라는 것에 열성적이라는 것을 알 고 있습니다. 저는 믿고 있습니다, 제대로 할 수만 있다면, 강력한 Product Leader는 훌륭한 기술자와 디자이너들이 모여 이루어진 다분야협력팀(CFT : Cross Functional team)의 힘을 몇 배로 증폭시키는 증폭제가 된다는 것 말입니다. (역자주 : 참조. Cross Function Team이란 목표를 이루기 위해 다양한 분야의 전문 가들이 모여서 만들어진 팀을 이야기 합니다. 이와 비슷한 것으로 kth는 ‘스마트 서클’ 이라는 제도를 가지고 있습니다. 기획, 개발, 디자인, 사업 등 각자 자기 분야를 가진 사람들이 모여서 하나의 프로젝트를 진행해 나가는 편제를 이야기 합니다. 같은 분야 의 전문가로만 이루어진 전통적인 팀에서는 보통 일을 하다 보면 자기 분야로 시야가 국한되거나, 전문 분야 넘어서는 경계 부분에서 일의 속도가 떨어지기 쉽습니다. 그에 비해 Cross Function Team은 그러한 일을 팀 안에서 빠르게 진행해 나갈 수 있어 상 대적으로 빠른 속도와 일의 완결성을 추구할 수 있는 장점이 있습니다. 스타트업 회사 가 속도가 빠른 것은 적은 인원의 특수성 때문에 시작부터 CFT이기 때문입니다.) 하지만 불행히도 Product Manager가 뭘 하는 사람인가에 대한 설명은 너무 모호하 거나 (예를 들어 "제품에 책임을 지는 사람입니다.") 너무 세세해져 버리는 경향 ("제
  478. 483 위대한 Product Leader 되기 품 설계 명세서를 쓰는 사람입니다")이

    있습니다. 방금 말한 것 둘 다 훌륭한 product manager가 되려는 사람들에게 도움이 되는 설명은 아닙니다. 저는 많은 시간을 product manager가 어떠한 가치인지를 명쾌히 전달하는 방법을 찾 는데 노력하였습니다. 다기능(CFT)팀의 사람들에게 그들이 product leader에게 무엇 을 기대해야 하는지, 또 새 product manager에게는 그들이 실제로 어떤 역할을 해주 어야 하는지 말입니다. 시간이 흘러, 이러한 이야기들을 딱 세 개의 책임으로 함축할 수 있게 되었습니다. ‘전략’, ‘우선순위 결정’, ‘실행’ 세가지 말입니다. 책임 #1: 제품 전략 일류 비즈니스 스쿨에서 전략에 대한 풀 코스를 가르치긴 합니다. 하지만 제품 전략 (Product Strategy)이 다음과 같은 방식으로 논의 되었었는지는 의심스럽군요. 단순히 말해, product manager의 일은 다음 두 가지를 명확하게 하는 일입니다. •우리는 어떤 시합을 하고 있는가?(What game are we playing?) •경기 기록은 어떻게 할 것인가?(How do we keep score?) 이 두 가지를 올바르게 한다면, 엔지니어링과 운영, 품질, 디자인, 마케팅 등에 재능 있는 개인 기여자(individual contributor)들의 모임이 갑자기 하나의 방향으로 단합하 여 달리기 시작할 겁니다. 하지만 위 두 가지를 잘 하지 못한다면, 어떤 우선순위 결정 과 과업관리도 도움이 안됩니다. 대단한 소프트웨어를 만드는 것은 다양한 재능을 필 요로 하고, 핵심이 되는 혁신적인 아이디어가 다양한 곳에서 나올 수 있어야 가능합니 다. 팀이 하고 있는 시합이 어떤 것인지 명확히 설명되고, 어떤 상태가 성공한 것인지 알 수 있는 명확한 측정 기준이 주어진다면, product manager가 바로 곁에 없어도 독 립적으로, 팀 사람들은 수행할 만한 가치가 있는 일들을 순서를 정하고 결정할 수 있 을 겁니다. 역자주 : individual contributors의 번역이 어렵습니다. 전체를 지휘하는 Manger의 반대되는 뜻 으로, 자기 분야에만 집중하는 개별 분야 전문가를 이야기하기 위해 주로 사용됩니다. 때에 따라, 팀원은 아니지만, 일을 완수하기 위해 모인 사람들 개별 분야 사람을 이야기하기도 합니다. 우리회사의 ‘스마트 서클’ 제도에서 이에 참여한 개개인이 individual contributors에 해당할 수 있겠네요. 각자 자기 소 속은 따로 있지만, 스마트 서클에서 자신의 전문분야로서 공헌하니까 말입니다.
  479. 484 KTH 개발자 블로그 베스트 당신이 하고 있는 시합을 명확하게

    정의하는 일에는, 그 제품에 대한 당신의 비전과, 그것이 고객에게 제공하는 가치, 그리고 경쟁자들 대비 상대 우위점 등이 포함됩니다. 하지만 더욱 더 중요한 것은, 당신의 팀에게 어떻게 해야 시장에서 승리할 수 있는 지 를 명확하게 해주는 것입니다. 당신이 적절한 측정방법을 골랐다면, 팀의 모든 사람들 은 어떠한 상태가 게임에서 이기는 것인지에 대해 명확하게 이해하게 될 겁니다. 적어도 2주간 정도 일을 한 product manager라면 언제든 위의 질문들을 받을 수 있 고, 또 또렷할 뿐만 아니라 설득력 있는 대답을 줄 수 있어야 합니다. 결과물 : 합치된 노력, 더 나은 동기, 혁신적인 아이디어, 변화를 일으킬 수 있는 제품 (역자주 : 저자는 소프트웨어 또는 서비스 만드는 일을 ‘게임’ 또는 ‘시합’이라는 비유 를 사용하여 표현했습니다. 우리가 하는 것이 축구라면, 공격수, 수비수, 골키퍼가 필 요하다는 것을 알게 될 겁니다. 공을 상대편 골대로 몰고 가서, 골대 안에 집어 넣어 야 이기는 것이라는 명확한 목표도 설정되게 됩니다. 저자는 또 How do we keep score?(어떻게 점수기록을 할 것인가?) 라고 물었는데 이 부분이 중요합니다. keep score란 점수를 기록한다는 사전적 의미도 있지만, 좀 더 디테일하게 야구등에서 볼, 스트라이크, 안타개수, 홈런개수, 출루 등을 세세히 기록하는 것을 이야기하기도 합니 다. 즉 ‘어떤 상태가 성공한 상태인가?’ - 우리가 무엇을 얼마나 하는 것이 잘하는 것 인지 -를 알기 위한 측정방법을 의미합니다. 사실 일을 하다 보면 어떤 것이 성공인지 에 대한 명확한 측정기준 없이 ‘그냥 잘’ 이라고 뭉뚱그려져 버린 채 작은 부분에 집착 하게 되는 경우가 있습니다. ‘무엇인지 알고’, ‘어떤 것이 잘하는 것인지 잴 수 있는 기 준을 찾는 것’이라는 측면을 강조할 수 있는 점에서 시합, 또는 경기는 매우 좋은 비유 라고 봅니다) 책임 #2 : 우선순위 정하기 팀이 하고 있는 시합이 어떤 것인지, 어떤 기준으로 점수를 채점해야 하는지 알게 되 었다면, 우선순위 정하기는 무척 쉬워집니다. 이것은 product manager의 두 번째 책 임입니다. - 전략과 결과측정에 대한 초창기 작업을 확실히 하면 프로젝트와 기능이 실제 작업 국면으로 넘어갑니다. 훌륭한 인재를 가진 회사라면, 분명히 넘치는 좋은 아이디어들이 있을 것입니다. 그 런데 규모가 커진다고 해서 더 상태가 나아지지는 않는데, 이것은 회사에 사람들이 더 많이 늘어날 수록, 가능 불가능 따지지 않고 무조건 아이디어를 가져오는 경향이 있기 때문입니다. 그 결과로 냉혹한 우선순위 정하기가 반드시 필요합니다.
  480. 485 위대한 Product Leader 되기 비즈니스에서는 훌륭한 아이디어 전체 리스트를

    만드는 게 궁금한 부분이 아닙니다. 팀이 바로 다음에 목표로 삼고 수행해야 할 딱 세 개가 궁금한 것입니다. 진행단계를 잘 정하여 밟아 나가는 것은 기업가의 노력들 중에서 핵심적인 부분입니 다. 많은 제품과 회사들은 훌륭한 아이디어가 없어서 실패하는 게 아니라, 어떤 것을 우선해서 수행하고, 어떤 것을 나중에 해야 하는지 정하는데 실수해서 실패합니다. 개인적으로, 모든 것을 하나의 기준으로 줄 세우는 우선순위 정하기가 긴 안목에서 효과적인 것 같지는 않습니다. 제가 주창하는 방법인 '세 개의 바구니' 라는 우선순위 정하기 방식에 대해서 별도의 포스팅(http://blog.adamnash.com/2009/07/22/ guide-to-product-planning-three-feature-buckets/)에 기술하였습니다. (역자주 : ‘세 개의 바구니’ 포스팅은 수행해야 할 일들을 ‘고객의 실제 요구’, ‘시장 상 황을 변경시키는 기능’, ’고객을 기쁘게 할 수 있는 방법’의 세가지 바구니에 배치하라 는 것입니다. 일반적으로 처음에 뭐하고, 다음에는 뭘 해야지 하는 하나의 리스트에서 의 나열이 아니라, 구현하려는 기능을 위 바구니 중에 하나에 배치하려고 고민하는 것 자체가 과연 이것이 누구를 만족시키기 위해서 이고, 무엇을 위한 것인지에 대해 더 명확하게 알게 하고, 또 한 구석에 치중되는 것을 막는다고 이야기 합니다. 또 위와 같 은 관점에서 기능을 나누면 1~2주짜리 짧은 개선들을 빠르게 수행해 나갈 수 있다는 점도 거론합니다.) 적어도 2주 이상 product manager로써 일했다면 모든 팀 사람들이 이해하고 지지할 수 있는, 깔끔하고 합리적인 우선순위 정하기가 적용된 작업 우선 순위 리스트를 제공 할 수 있어야 합니다. 책임 #3: 수행 Product manager들은 사실 엄청나게 많은 종류의 일을 합니다. 그 결과, product manager들은 움직이는 배가 되어야 하는데 무슨 말인고 하니, product manager들은 작업하는데 있어 처리 되야 하는 간극들을 메워 줘야 한다는 뜻입니다. 때때로 그들은 서비스 본문 내용을 쓰기도 하고, 때로는 디자인의 구멍도 메워야 합니다. 때로는 QA역할을 합니다. 때로는 PR을 합니다. 제품을 성공시키기 위해 필요한 일은 사람이 할 수 있는 일이면 무엇이든지 합니다. 하지만 이런 일들 중 팀에게 매우 매우 중요한 부분이 (다음에) 있습니다. 이것이 없으 면 작업은 극단적으로 비효율적이 됩니다.
  481. 486 KTH 개발자 블로그 베스트 • 제품 스펙 정하기 -

    팀이 만들고 있는 것을 명확하게 해줄 수 있는 수준의 디테일 레벨이 필요합니다. •  특이 케이스 결정 - 매우 자주, 예상치 못한 복잡한 특이 케이스가 발생합니다. 일반적으로 product manager 는 제품의 다른 여러 부분에 영향을 줄 수 있는 이러한 판단을 즉시 해내야 합니다. •  프로젝트 운영 - 어떤 기능이든 ‘투자 시간 / 결과물 품질’ 라는 트레이드 오프가 존재합니다. 이러한 것들을 정 하는 것은 작업 사이클 내내 강요됩니다. 따라서 product manager는 최종 제품이 시장에서 적절한 시점에 출 시되는 것과, 시장에서 성공하는 것 둘 사이의 적절한 밸런스를 맞추도록 늘 몇 발 앞서 볼 수 있어야 합니다. •  분석 - 결국 팀은 product manager가 비용을 산정하고, 어떤 기능이 성공하는데 필수적인 부분인지 잘 파악 하는 것등에 크게 의지 합니다. 또한product manager는 기존 기능들의 퍼포먼스에 대해서도 깊은 이해를 가 져야 합니다. (또한 경쟁자가 있다면 그들의 것도요) 일이 되게 하는 것 결국 위대한 product manager는 일이 되게 합니다. 평범한 사람이 아니라 위대한 Product manager를 팀에 추가했다면 분명히 표가 나게 되어있습니다. 왜냐하면 일 들이 매우 빨리 제대로 돌아가기 시작했기 때문입니다. 버그 고치기나 기능 고치기가 시작됩니다. 데이터에 대한 깔끔한 분석이 나옵니다. 프로젝트에서 새로 우선순위가 책정됩니다. 그리고 얼마 지나지 않아 중요한 숫자지표들이 증가방향을 보일 겁니다. 위대한 product leader가 되세요 번역 후 약간의 첨언 먼저 이 글을 PL이나 PM들이 읽는 글이라고만 생각해서는 안됩니다. 반대로 팀원들 역시 '나는 무엇이 중요한 것인지 잘 이해하고 있었나? 이들에 대해 잘 공유하고 있었 나'하고 반성하게 되는 글이기도 합니다. 이 글에서 가장 인상 싶은 부분은 Product Leader의 첫 번째 역할인 ‘우리가 어떤 시합을 하고 있는가?’와 ‘경기 기록은 어떻게 할 것인가?’의 정의와 공유에 대한 이야기였습니다. ‘우리가 어떤 시합을 하고 있는가?’를 정할 때, 디자인/UI/개발 등등 다양한 파트들이 함께 작업을 하고 있는 만큼, 각 파트가 모두 참여하여 공통되고 합의되는 ‘시합’에 대 한 정의를 내릴 수 있어야 합니다. 하지만 대부분의 회사에서 ‘그런 것은 기획이 하는 일’이라고 기획도, 다른 파트도 인식해버리고 놓고 있는 것이 아닌가 하는 생각이 들었 습니다.
  482. 487 위대한 Product Leader 되기 또 설사 초창기 이런 논의를

    모두가 진행하였다 하더라도, 작업을 진행하면서 변화되 는 방향성이나 새로운 목표들이 모두에게 공유되지 않는 점이 아쉬웠습니다. 시간이 지남에 따라 서로의 생각을 공유하고 동기화 하는 작업은 점차 기획의 일로 다시 전담 되어 버리고, 나머지 파트는 사내하청과 비슷한 형태로 업무가 변해버리는 것이 종종 프로젝트가 등산을 시작하는 일과 관계 있다고 보입니다. 지속적으로 프로젝트의 전 체상을 전체 멤버가 공유하도록 하는 것이 Product Leader의 가장 큰 일이라는 것을 다시 생각하게 됩니다. 하지만 이것은 우리가 지속적으로 Product Leader에게 요구 해야 하는 것이기도 합니다. 또 ‘경기 기록은 어떻게 할 것인가?’에서 거론한 ‘성공을 판단하기 위한 측정 방법’을 정하고 공유하는 것 역시 필수적이라 생각됩니다. 서비스란 무형의 것인 만큼, 전체 를 숫자로 표현하기는 힘듭니다만, 세부적으로 ‘앱의 첫 화면은 몇 초 안에 나와야 한 다’ 라던가, ‘하나의 인터액션에 세번 이상의 전환은 피한다’ 등의 세세한 단위의 메 트릭 등은 충분히 정하고 공유하고 토론할 수 있다고 봅니다. 이러한 것들의 대한 서 로 나눔이 같은 고민이나 실패를 반복하지 않고, 우리가 회사에서 ‘모여’ 있다는 장점 을 살릴 수 있는 방법이라 생각합니다. 이런 세부적인 것은 처음부터 끝까지 Product Leader의 머릿속에서 나오기는 무리입니다. 오히려 개별 분야 전문가가 자신만의 지 식이나 아쉬움으로 남기지 않고 전체에게 전달할 채널로써의 Product Leader를 적극 적으로 이용(?)해야 한다는 생각을 해봅니다. 결국 본 포스팅에서 말한 핵심 질문 두가지, ‘우리는 무엇을 만들고 있는가?’, ‘어떤 상태가 성공한 상태인가?’는 결국 Product Leader뿐만 아니라 해당 팀의 모든 구성 원이 대답할 수 있는 상태가 되어야 합니다. 그렇지 않다면 무엇인가가 막혀있는 상태 인 것이지요. 다른 말로 훌륭한 Product Leader라면 이러한 상을 모두가 제대로 공유 하고 있는지 확인하고 업데이트하고 다시 공유하게 만들어야 합니다. 동시에 팀원들 역시 저 두 가지 질문을 스스로에게 물어 답할 수 없다면 끊임없이 Product Leader와 동료들에게 물어서 자신을 업데이트 해야 하는 것은 당연하겠죠.
  483. 490 KTH 소개 Smart Mobile company KTH KTH는 모바일 빅뱅시대를

    맞아 고객 여러분이 만나는 모든 윈도우를 통해 다양한 컨 텐츠와 서비스를 경험할 수 있는 유무선 융합 서비스를 제공하고 있습니다. 24시간 연결된 내 손안의 컴퓨터인 스마트폰과 태블릿PC 등 모바일 디바이스가 ‘생 활’로 자리잡은 ‘스마트 모바일’ 시대에 KTH는 고객 여러분이 서로 소통과 교감을 이 룰 수 있는 서비스를 제공하여 진정한 모바일 라이프의 고객 가치를 실현하고자 합 니다. 고객 여러분이 어디에서 무엇을 하든지 끊김 없이 KTH를 만날 수 있도록 스마트한 모 바일 세상을 열어가겠습니다. KTH 소개
  484. 491 KTH 사업영역 KTH 사업 영역 스마트 모바일 사업 KTH는

    아임IN, 푸딩 등 전략 서비스의 성공적 시장 안착을 이루어 냈습니다. 향후 과 감한 Open Platform 전략을 통해, 서비스들을 Social 기반의 platform으로 확대/성장 시켜 나가고자 합니다. 컨텐츠 사업 KTH는 N-Screen 환경이 필요로 하는 컨텐츠 유통 역량을 보유하고 있으며, 이를 기 반으로 언제 어디서든 컨텐츠를 즐길 수 있는 플랫폼 서비스인 ‘PLAYY’를 출시하였습 니다. 향후 컨텐츠 유통사업과 플랫폼 사업의 선순환구조 확립을 통해 N-Screen의 강자가 되고자 합니다. 그룹 시너지 사업 KTH는 링고, Olleh존 등 Value Added Service 개발/운영뿐 아니라, Software Engine & Platform Enabler로서 KT 그룹의 Ecosystem 구축을 지원하고 있습니다.
  485. 492 KTH 소개 KTH의 기업문화 KTH는 모든 구성원들이 신뢰와 자부심,

    성장이라는 핵심 가치를 바탕으로 BCD라고 하는 독특한 기업 문화를 공유하고 있습니다 BCD는 일에 대한 열정과 주인 의식을 갖춘 문화를 뜻하는 Basic(베이직), 수평적이고 원활한 소통을 통한 협업 문화를 뜻하는 Chorus(코러스), 그리고 프로 정신으로 끊임 없이 도전하고 혁신하는 문화를 뜻하는 Detail(디테일). 이렇게 3가지 문화가 유기적으 로 결합 된 KTH만의 기업 문화입니다. 시작은 BASIC하게, 과정은 CHORUS하게, 마무리는 DETAIL하게라는 슬로건을 바 탕으로 구성원 모두가 자발적으로, 때로는 창조적으로 회사와 함께 성장해 나가고 있 습니다.