애자일 기법을 활용한 LINE TODAY 서비스

개요

이번 블로그에서는 애자일 기법으로 LINE TODAY 서비스를 개발한 과정에 대해 이야기해보겠습니다. LINE TODAY는 2016년 초에 대만, 태국, 인도네시아, 미얀마, 미국에 출시한 모바일 뉴스 서비스로서, 2016년 7월 30일 기준으로 하루 3천만 페이지 뷰(Page View, PV)를 기록하고 있습니다. 일본에서는 LINE TODAY와 유사한 서비스를 LINE News라는 명칭으로 제공하고 있습니다.

LINE TODAY 개발 프로젝트는 여러 국가의 사용자, 고객, 개발자, 기획자를 아우르는 다국적 프로젝트입니다. 이 프로젝트는 다수의 개발자, 기획자, QA 엔지니어, UIT 엔지니어, 디자이너, 사업 담당자들로 구성되었는데 팀원들의 근무지가 대만, 대련, 한국 오피스에 분산되어 있었습니다. 게다가 LINE TODAY 개발 프로젝트 팀은 완전히 신생 팀이었습니다. 개발자 상당수가 LINE 개발 환경과 기술에 익숙하지 않은 신참이었고 전체적인 제품 개발 프로세스를 잘 아는 팀원이 없었습니다.

또한 이 서비스는 대만, 태국, 인도네시아 등 여러 국가에 출시할 계획이었기 때문에 여러 나라의 다양한 요구 사항을 고려해야 했습니다. 예를 들어, CP(Content Provider) 업체마다 선호하는 콘텐츠 피드 메커니즘이 다르다는 점을 염두에 두어야 했습니다. 대만 CP는 FTP를 선호하고 태국, 인도네시아 CP는 RSS를 선호했습니다.

이 프로젝트는 기한이 매우 촉박했습니다. LINE TODAY 서비스는 FastTrack, RegularTrack 버전으로 나누어 두 번 출시되었습니다. FastTrack 버전에서는 사업 수익성을 평가하는 Proof of Concept을 수행하였고, 이를 바탕으로 지속적인 서비스 운영을 목적으로 RegularTrack 버전을 출시했습니다. 그런데 FastTrack 버전은 설계, 개발, 테스트, 출시를 단 6주 내에 완수해야 했고, 그로부터 3개월 이내에 RegularTrack 버전을 출시해야 했습니다.

유일한 해결책은 기민한 대응, 즉 “애자일”이다

스크럼(Scrum)은 복잡한 프로젝트에 적합한 솔루션으로 알려져 있습니다. 그래서 이 프로젝트에 스크럼 기법을 채택하게 되었고 다음의 4개 원칙을 실천했습니다.

  • 팀 스피릿(team spirit)
  • 자율적인 관리와 개발(self-management and self-development)
  • 커뮤니케이션 방법론
  • 개발 방법론

지금부터 LINE TODAY 개발 프로젝트에서 애자일 개발 프로세스와 스크럼 기법을 어떻게 적용했는지 소개하겠습니다. (이해를 돕기 위해 스크럼 용어는 밑줄로 표시했습니다. 예를 들어, daily stand-up meeting)

팀 스피릿(Team Spirit)

진정으로 “애자일”한 팀이 되려면 팀 스피릿이 강해야 합니다. 개발 프로젝트의 핵심적인 성공 요인은 스크럼 활동을 수행하면서 항상 팀 스피릿을 유지하는 것입니다.

신뢰와 약속(Trust and Commitment)

스크럼 마스터는 개발자와 개발자 사이, 개발자와 기획자 사이, 기획자와 사업 담당자 사이의 신뢰 구축에 최선의 노력을 기울여야 합니다. 이를 위해 개발자가 스케줄을 산정하고 실행 계획을 수립하는 과정에 적극 참여하였습니다. 매니지먼트 팀이 일방적으로 의사 결정을 내리지 않았습니다. 개발자들은 본인들이 스스로 약속한 스케줄을 지키기 위해 최선을 다했습니다. 개발자가 약속한 기한에 맞춰 완수한 덕분에 기획자는 개발자를, 주요 담당자들은 기획자를 믿는 신뢰가 형성되었습니다.

방향 제시 – 혁신과 창의

개발자가 창의적인 아이디어를 낼 수 있도록 혁신을 장려하고 Pros/Cons 분석을 통해 아이디어를 함께 검토했습니다. 이 과정은 planning meeting에서 실행 계획을 논의하고 태스크를 분할할 때 이루어졌습니다. 예를 들어, 데이터베이스 프레임워크를 선택하거나 데이터 스키마를 정할 때 모든 개발자가 Pros/Cons 분석에 참여하고 의견을 내었습니다.

Why, What, How, When

첫째, 기획자는 planning meeting이나 backlog grooming에서 “What To Do(해야 할 일)”와 “Why To Do(해야 하는 이유)”를 개발자에게 설명했습니다. 이 활동의 핵심은 개발자가 user story의 중요성을 이해하는 것입니다. 둘째, 개발자는 planning meeting에서 기획자에게 “How To Do(어떻게 할 것인지)”와 “When To Do(언제까지 할 것인지)”를 알려주었습니다. 개발자는 그 user story를 구현하는데 얼마의 시간이 필요한지 알리고(complexity estimation), 기획자는 비용 효율을 분석해서 우선순위를 조정했습니다. 셋째, 기획자와 개발자가 상호 합의한 우선순위를 바탕으로 개발자는 이번 스프린트에서 어떤 user story를 완료할지 알리고 어떻게 구현할 것인지 정했습니다(task breakdown: 태스크 분할).

자율적인 관리와 개발(self-management and self-development)

LINE TODAY 팀은 뛰어난 팀 스피릿을 가지고 있었기 때문에 팀 리더가 보다 수월하게 자율적인 관리와 개발을 추구하면서 스크럼 활동을 수행하는 팀으로 이끌 수 있었습니다.

Planning Meeting

Planning meeting은 일반적으로 1, 2 단계로 나뉩니다. Planning meeting 1의 주요 활동은 기획자가 개발자에게 product backlog에 작성한 user storyepic을 설명하는 것입니다. Planning meeting 2의 주요 활동은 개발자가 user story를 선택하고 태스크를 분할하는 것입니다.

LINE TODAY 스크럼 팀은 1 단계와 2 단계를 명백하게 구별하지 않았습니다. 대신 핵심 개념, 즉 기획자가 아직 구상 중인 user story들을 개발자가 조기에 파악하고 이해하는 것에 주력했습니다. 또한 개발자가 처음 들은 user story를 그 스프린트에서 바로 완료하라고 요구하지 않았습니다. 필요하면 backlog grooming 미팅을 열어서 기획자가 상위 user story나 epic을 상세하게 설명하는 시간을 가졌습니다. 기획자는 또한 daily stand-up meeting이 30분을 넘지 않는 범위 내에서 하위 user story를 설명했습니다.

User story를 수행하는 활동에는 King and Servant 모델을 활용했습니다. 한 개발자가 해당 스프린트에서 king 역할을 맡아 user story를 선택하고 on-time-delivery, 품질, blocker 이슈 해결을 포함한 모든 것을 책임졌습니다. 그리고 다른 개발자들은 servant로서 king을 도와 user story를 완료했습니다.

Daily Stand-up Meeting

Daily stand-up meeting은 약 15분에서 30분을 할애하여 각자의 진행 상황을 간단하게 업데이트하는 시간입니다.

스크럼 마스터는 daily stand-up meeting에서 아주 중요한 책임을 맡고 있습니다. 팀원들의 진행 경과를 업데이트할 뿐 아니라 팀의 운영 모델을 수립하고 관계를 구축해야 합니다. 이 역할은 새로 생긴 스크럼 팀에게 특히 중요합니다. 신생 팀은 서로 협력하는 방식을 스스로 찾아야 하고 점차 성숙해야 합니다. 리더는 Top-Down 방향으로 명령을 내리는 사령관이 아니라 제안과 조언을 통해 팀원들이 스스로 운영 모델을 찾도록 도와주는 사람입니다. 대략 두 달이 지나자 LINE TODAY 스크럼 팀은 개발 팀워크를 발휘하는 자율적인 조직으로 발전했습니다.

Live Demo

기획자, 주요 담당자에게 지금까지의 작업 성과를 설명하는 것은 중요한 일입니다. 이를 위해 스프린트 종료 시점마다 live demo 시간을 가졌습니다. 일반적으로 라이브 데모에서는 사용자 관점에서 user story를 설명합니다. 반면 우리 개발자들은 라이브 데모에서 API 혹은 테스트 자동화 같은 엔지니어링 태스크와 관련한 user story를 설명했습니다. User story의 king 역할을 맡은 개발자는 라이브 데모를 통해 소프트웨어 디자인을 설명하고, unit test와 smoke test를 실시하며, 성능 지표를 제시하는 등 본인의 성과물을 보이도록 했습니다.

이 활동은 개발자의 스킬과 실력 향상을 위해 중요합니다. 또한 기획자나 다른 담당자는 라이브 데모를 통해 어째서 본인들의 예상보다 더 많은 개발 시간이 필요한 것인지 이해할 수 있기 때문에 기획자와 개발자 사이에 신뢰를 쌓는데에도 도움이 되었습니다.

Retrospective

Retrospective는 자율적인 관리와 개발이 가능한 팀을 만드는데 중요한 활동입니다. 팀원들은 retrospective를 통해 주요 개선점을 파악했습니다. 모든 문제점을 시정하는 게 목적이 아니라 조금씩 매일 스스로 개선하는 것을 목표로 했습니다.

초기 몇 번의 스프린트 동안 팀은 coding convention, code branch/merge, CI 등 협력 개발(co-development) 프로세스 개선에 초점을 맞췄습니다. 이는 LINE TODAY 스크럼 팀이 성숙한 시스템 개발 모델을 수립하기 위해 필수적인 개선 사항들이었습니다.

또한 retrospective에서 한가지 흥미로운 활동을 했습니다. 각 팀원는 모두의 앞에서 어떤 부분이 잘 되었고, 어떤 부분이 개선되어 하며, 누구에게 감사하고 싶은지 말했습니다. 그리고 마지막으로 스크럼 마스터의 주도 하에 팀원들이 다음 스프린트에서 노력할 주요 개선점을 한두 개 정했습니다. 스크럼 마스터는 daily stand-up meeting에서 개선점을 지속적으로 상기시키고 다음 retrospective에서 결과를 검토했습니다.

커뮤니케이션 방법론

내부(Inner) 커뮤니케이션과 외부(Outer) 커뮤니케이션

효율적인 커뮤니케이션을 위해 내부(Inner) 커뮤니케이션과 외부(Outer) 커뮤니케이션 채널을 만들었습니다. 내부적으로는 대만 기획자가 한국 기획자의 제품 요구 사항까지 합쳐서 전달하는 단일 창구 역할을 했습니다. 그리고 외부적으로는 대만 기획자가 한국 기획자, 한국 프로젝트 매니저, 그리고 각 나라별 사업 부서 담당자와 외부 커뮤니케이션을 수행했습니다.

Product Backlog, Epic, User Story, Task

팀원 모두가 개발 태스크와 진행 경과를 동일하게 알 수 있도록 JIRA Scrum Board를 도입했습니다. LINE TODAY 스크럼 팀은 기획자, 프로젝트 매니저의 관점에서 혹은 개발자 관점에서 user story를 한눈에 알아보기 위해 “Product Features”라는 이름의 특별한 epic을 만들고 1-tier, 2-tier epic으로 관리했습니다. 또한 기획자나 매니지먼트 팀이 전체 백로그를 보고 진행 상황을 손쉽게 파악할 수 있도록 Product Features의 user story에 관련 user story나 task에 대한 종속 관계(dependency)를 설정했습니다. 이런 방식으로 개발자, 기획자, 관련 담당자 모두가 제품 백로그를 보다 쉽게 볼 수 있도록 했습니다.

User story를 “single source of truth”로 관리하기 위해 다음의 규칙을 정했습니다.

  • 기획자는 user story 티켓에 상세 요구 사항을 추가하거나 요구 사항 링크를 걸어야 한다. 그래야 사람들이 요구 사항을 쉽고 빠르게 찾을 수 있다.
  • 개발자는 user story의 태스크 티켓에 code commit log의 링크를 걸어야 한다. 그래야 본인이 수행한 일을 다른 개발자나 QA가 알 수 있다.
  • 모든 요구 사항 변경은 user story 티켓으로 escalate해야 한다. 그래야 변경 이력(change history)을 추적할 수 있다.

이런 규칙을 적용함으로써 기획자가 예상치 못한 요구 사항 변경을 작성하는 경우 등 기획자와 개발자 사이에 발생하는 고질적인 커뮤니케이션 혼선을 줄일 수 있었습니다.

일상적인 커뮤니케이션 툴

일상적인 커뮤니케이션에 LINE 메신저, HipChat, 비디오 컨퍼런스를 이용했습니다. 어떤 툴을 사용하든 가장 효과적인 수단은 “얼굴을 맞대고 대화하는 것”입니다. 그래서 개발자가 작업을 진행하다가 질문이 생기면 기획자나 담당자를 직접 보고 대화하는 것을 장려했습니다.

개발 방법론

진정한 애자일 팀이 되려면 팀 스피릿뿐 아니라 어떤 개발 방법론을 도입하는가 여부도 중요합니다.

기존 리소스 재사용

LINE은 글로벌 플랫폼과 공유 솔루션을 활용하는 글로벌 기업입니다. 따라서 여러 거점에 구축되어 있는 Timeline Content API, OBS, CDN 등의 기존 리소스를 적극적으로 도입했습니다. 기존 플랫폼이나 툴을 재사용하면 개발 노력을 절감하고 time-to-market을 더 잘 맞출 수 있습니다.

실제 OBS/CDN 도입은 높은 성능을 유지하면서 단일 서버 팜(server farm)으로 5개 국가에 LINE TODAY 서비스를 제공하기 위해 꼭 필요한 요소입니다. CDN의 Dynamic Site Accelerator는 사용자 커멘트를 API 서버의 캐시 메커니즘으로 처리해서 동적 콘텐츠 모듈을 효율적으로 운영할 수 있도록 도와줍니다.

CI(Continuous Integration)와 CD(Continuous Delivery)

CI/CD는 오늘날 대부분의 인터넷 기업이 활용하는 소프트웨어 엔지니어링 기법입니다. 여기서는 CI/CD에 대한 설명은 생략하고 우리가 무엇을 했으며 이 프로젝트에 어떻게 유용한지 설명하겠습니다.

Pre-commit/commit build에서 unit test, coding convention을 적용하는 것은 개발 품질을 위해 매우 중요하다. 특히 협력 개발을 수행하려면 강력한 unit test 프레임워크를 반드시 구축해야 합니다.

코드 리뷰는 품질 관리뿐 아니라 팀워크 형성과 인재 개발에도 기여합니다. LINE TODAY 프로젝트 팀은 앞에서 설명한 King/Servant 기법을 바탕으로 Git Flow와 PR 리뷰 단계를 직접 만들었습니다. 특정 분야를 잘 아는 개발자들이 king 역할을 맡아 그렇지 않은 다른 개발자들의 역량 개발을 도왔다. 그리고 양쪽 개발자 모두 코드 리뷰에서 습득한 내용(lessons learned)을 숙지했다.

테스트 자동화(Test Automation)

LINE TODAY 프로젝트 팀에는 테스트 자동화를 전담하는 대만 QA가 있었습니다. 또한 대련에는 수동 테스트를 전담하는 QA TF도 있었습니다. 목표는 테스트를 최대한 자동화하는 것이었습니다. 테스트 자동화는 저렴하지 않지만 이러한 고비용은 그만한 가치가 있습니다.

실질적인 테스트 자동화는 RegularTrack 시점부터 구축했습니다. QA 엔지니어는 Live Demo 시간에 테스트 자동화를 시각적으로 보여주고 어떤 혜택이 있는지, 어떤 리스크를 방지하는지 설명했습니다. Retrospective 시간에는 개발자도 피드백을 주고 테스트 자동화로 어떤 도움을 받았는지 설명했습니다.

Extensibility 및 Scalability

개발자들이 extensibility, scalability 관점에서 시스템 설계를 논의하는 것을 적극 장려했습니다.

오늘날 시스템 설계는 extensibility와 scalability를 위해 클라우드 솔루션을 도입하는 추세입니다. 우리도 이 추세를 따라 MongoDB, Crawler4j, gclusterfs, Redis, RabbitMQ, Elasticsearch 등의 클라우드 기반 솔루션을 사용하고 있습니다. 시스템을 설계하고 새로운 기술을 모색, 습득하는데 더 많은 시간이 들지만 그래도 모든 개발자들에게 그러한 시도를 장려합니다. 개발자가 sizing(규모 측정)을 하고 성능 지표의 수치를 예측하면 QA나 개발자가 모니터링 환경을 구축하고 베타, 프로덕션 사이트에서 해당 수치를 관측했습니다. Sizing 결과를 공유, 논의하는 미팅을 열어 설계가 어떻게, 그리고 왜 extensibility와 scalability를 검토했습니다.

LINE TODAY – Popular Articles feature

지금부터 LINE TODAY 서비스의 주요 기능 중 하나인 Popular Articles를 소개하겠습니다.

LINE TODAY 서비스는 홈페이지에서 기사를 카테고리 별로 제공합니다. 이 페이지에 현지의 뉴스 에디터가 게시한 기사뿐 아니라 사용자들이 많이 읽는 인기 기사를 빠르게 확인할 수 있는 “스마트 모듈”을 추가했습니다.

이 기능을 완성하기 위해 여러 기술적 난제를 해결해야 했습니다.

  • 실시간 갱신(응답성): 기사를 읽거나 커멘트를 다는 등의 사용자 작업을 실시간으로 수집, 분석하여 인기 기사 목록을 동적으로 갱신합니다.
  • 유연성: 원시 데이터를 가져오거나, 사용자 작업을 처리하거나, 기사 컨텐츠를 구성하는 등의 전반적인 Trending 메커니즘이 포괄적이어야 합니다. 많은 노력과 시간을 들이지 않고도 인기 기사를 선별하는 로직을 유연하게 변경하고 모듈을 업데이트할 수 있어야 합니다.
  • 확장성과 안정성(Scalability and Robustness): 인기 기사 목록을 생성하려면 여러 서비스 구성 요소에서 대량의 사용자 작업을 처리해야 합니다. 그런데 사용자 작업량이 매일 약 3천만 뷰에 달합니다. 이처럼 방대한 양의 트래픽을 처리하려면 시스템이 안정적이고 확장성이 뛰어나야 합니다.

전반적인 아키텍처는 다음과 같이 설계되었습니다.

Web API Server는 사용자 작업을 수집하는 주요 구성 요소입니다. 데이터를 실시간 수집하면서 Web API Server에 발생하는 오버헤드를 줄이기 위해 데이터를 임시 스토리지 큐에 저장합니다.

RabbitMQ는 대용량 처리가 가능하고 여러 단계의 데이터 영속성을 보장하기 때문에 이 서비스에 적합한 후보입니다. Trending Server는 사용자 작업 로그를 처리하고 수집된 로그를 바탕으로 인기 기사를 실시간 생성하는 일을 합니다.

인기 기사를 선별하는 로직을 유연하게 구성하기 위해 사용자 작업 데이터를 정해진 규칙에 따라 사전 집계(pre-aggregation)하지 않고 원시 데이터 그대로 보존합니다. 인기 기사 목록의 생성은 검색 엔진에서 쿼리를 실행해서 처리합니다.
Elasticsearch는 실시간 데이터 분석을 수행하는 강력한 프레임워크입니다. 인기 기사 목록을 생성하는데 필요한 요구 사항을 맞추기 위해 필터 쿼리와 일반적인 버켓 집계 방식(bucket aggregation)을 결합했습니다.
또한 스크립트 기반의 집계(scripted aggregation)를 통해 쿼리를 확장함으로써 보다 복잡한 경우도 처리할 수 있도록 만들었습니다. Bulk API는 효율적이고 유연한 쿼리 사용을 지원할 뿐 아니라 사용자 데이터를 삽입할 때 인덱싱 속도를 높여줍니다.
Trending 관련 구성 요소가 모두 준비되면 Trending Server가 백그라운드에서 매우 짧은 시간 간격으로 쿼리 명령을 실행하고 결과물을 Redis에 캐싱합니다. 그러면 Web Server의 웹 페이지 작성 모듈이 가장 최신의 인기 기사 목록을 가져옵니다.
대만, 태국, 인도네시아를 비롯한 전 세계에 뉴스 기사를 전달하는 데 걸리는 로딩 시간을 가능한 짧게 하기 위해 기사 컨텐츠를 CDN에 캐싱합니다. 그리고 브라우저가 가장 가까운 엣지(edge) 서버로부터 해당 컨텐츠를 가져오도록 해서 다운로드 시간을 단축합니다.

이처럼 여러 구성 요소들이 함께 일련의 작업을 수행하여 인기 기사를 불러오게 됩니다. 그런데 테스트 단계에서는 좀더 어려운 문제가 있습니다. 사용자 작업 로그가 워낙 방대하다 보니 사용자 작업 로그에 사용자 작업 시퀀스까지 더해지면 변동성이 매우 커집니다. 그래서 기능을 수동으로 테스트하고 검증하는 것이 거의 불가능합니다.

우선 여러 레벨의 유닛 테스트(unit test)를 통해 각 서비스 구성 요소를 검증합니다. 그런 다음 QA 팀이 자동 실행되는 통합 테스트 스크립트를 사용하여 사용자 작업을 시뮬레이션하고 Trending Server에서 다양한 사용자 작업을 조합하여 생성한 인기 기사 목록을 검증합니다. 테스트 스크립트는 Jenkins에 구축되어 있으며 산출물이 예상과 다르면 알림 메일을 발송합니다.

모니터링 환경을 구축해서 실제 운영 환경에 릴리스하기에 전에 서비스 구성 요소가 정상적으로 작동하는지 확인합니다. LINE은 iMON, nSight 등의 사내 툴을 다양하게 사용합니다. 이러한 툴은 시스템 레벨에서 애플리케이션 레벨에 이르기까지 전체적으로 모니터링하면서 알림을 제공합니다. RabbitMQ와 Elasticsearch는 웹 모니터링 인터페이스를 통해 대량의 서비스 통계 데이터를 제공합니다. 이렇게 하면 필요할 때마다 상태를 체크할 수 있어서 매우 편리합니다.
하지만 문제를 방지하려면 보다 적극적인 접근법이 필요합니다. Health check 스크립트는 특정 서비스가 정해진 한계치를 초과하면 알림을 보냅니다. 이 스크립트에는 RabitMQ management API와 Elasticsearch cluster/stats/status API가 통합되어 있습니다. 큐 사이즈가 계속 증가하거나 클러스터가 작동을 멈추는 등의 비정상적인 상황을 손쉽게 탐지할 수 있습니다.

결론

지금까지 LINE TODAY 프로젝트 팀이 어떻게 진정한 애자일을 실현하고 있는지 팀 스피릿, 프로세스, 플로우, 툴, 방법론 등의 다양한 측면에서 설명했습니다. 우리는 애자일을 실무에 적용했고 진정한 애자일 개발이 가져오는 혜택을 입증했습니다. 다시 한번 팀 스피릿이 가장 중요하다는 사실을 강조하고 싶습니다. 이것이 모든 것의 시작이고 팀을 한 방향으로 이끄는 원동력입니다. 모든 개발자와 기획자가 팀 스피릿을 발휘해서 함께 해결책을 찾기 위해 노력했습니다. 이는 또한 훌륭한 소프트웨어 엔지니어링 프랙티스가 확립되어 있었기에 가능했습니다. 이러한 프랙티스 덕분에 품질을 보장하는 동시에 신속한 릴리스를 달성할 수 있었습니다.

저자 소개

Marco Chen: LINE TODAY 프로젝트의 개발 리더 겸 스크럼 마스터로 스크럼 팀을 편성하고 프로세스와 연계 모델을 구축했습니다.

Yang Ya-Chu: 서버 개발자로, LINE TODAY에서 Trending Service 시스템의 설계를 담당하고 있습니다.