# Clean Agile ## 애자일 소개 ### 폭포수 모델 (Waterfall) `철저한 분석 -> 상세한 계획 -> 실행하여 완성`하는 것에 관한 이야기 1970년대부터 30년 동안 산업을 지배했지만 결국 실패했다. ### 익스트림 프로그래밍 (Extreme Programming, XP) ![](https://i.imgur.com/TGSQoy8.png) XP의 실천 방법을 설명하는 그림, 일명 '삶의 순환<sub>(Circle of Life)</sub>' - 모든 애자일 프로세스 중에서 XP가 가장 잘 정의되어 있고, 가장 완전하며, 가장 덜 혼란스럽다. - 사실상 다른 모든 애자일 프로세스는 XP의 부분 집합이거나 XP의 변종이다. - **XP는 애자일의 프로토타입이자, 최고의 대표주자이며, 본질이고, 핵심이다.** ### 애자일 (Agile) 폭포수 모델같은 기법이 처절하게 실패하는 이유는, 그 기법을 사용하는 관리자가 소프트웨어 프로젝트의 근본 물리 법칙을 이해하지 못하기 때문이다. 이 물리 법칙은 **모든 프로젝트가 일종의 트레이드오프를 벗어날 수 없다**는 것이다. 프로젝트 관리자는 `좋음`, `빠름`, `저렴함`, `완성` 중 세 개만 고를 수 있다. 애자일은 이 네 가지 속성의 가중치를 관리한다. 애자일은 프로젝트 일정을 일정한 크기로 더 작게 나눈다. 이것을 반복 주기 또는 **스프린트**<sub>(sprint)</sub>라고 부른다. - 스프린트의 길이는 일반적으로 1주일 혹은 2주일이다. - 첫 번째 스프린트에서는 **스토리**라고 부르는 기능 목록을 만들고, 개발 환경을 준비하고, 스토리의 크기를 추산하고 최초의 계획을 세운다. - 스토리를 쓰고, 크기를 추산하고, 계획을 세우고, 설계를 하는 이 과정은 매 **스프린트에서 끝없이 반복한다.** - 스프린트를 여러 번 돌면서 계획했던 스토리를 모두 완료하는 데 얼마나 걸릴 지를 예측한다. - 주어진 일정 마감 시한을 초과하는 것으로 예측되는 경우, **일정을 변경**하거나 **인력을 추가**하거나 ~~품질을 떨어뜨리거나~~ **개발 범위를 변경**한다. #### 애자일 선언 - **공정과 도구보다 개인과 상호작용** - 전체 팀, 메타포, 공동 소유, 짝 프로그래밍, 지속 가능한 속도 - **포괄적인 문서보다 작동하는 소프트웨어** - 인수 테스트, 테스트 주도 개발, 단순한 설계, 리팩터링, 지속적 통합 - **계약 협상보다 고객과의 협력** - 작은 릴리스, 계획 게임, 인수 테스트, 메타포 - **계획을 따르기보다 변화에 대응하기** - 작은 릴리스, 계획 게임, 지속 가능한 속도, 테스트 주도 개발, 리팩터링, 인수 테스트 ## 왜 애자일인가 쓰레기같은 소프트웨어를 개발하지 않기 위함이고, **전문가답게** 소프트웨어를 개발하기 위함이다. 윤리적인 직업의 기반을 이루는 권리, 기대, 규율을 한데 모은 것이 애자일이다. ## 비즈니스 실천 방법 ### 계획 세우기 소프트웨어 개발자를 위한 좋은 추정 요령은, **확실한 시간 범위를 고르되 이 시간 범위를 가능한 한 좁히**기 위해 약간의 시간을 투자하는 것이다. #### 삼변량 분석<sub>(trivariate estimation)</sub> - 최악의 경우 (이 안에 끝날 것이 95% 확실한 시간) - 일반적인 경우 (50% 확실한 시간) - 최선의 경우 (5% 확실한 시간) 위 세 개의 숫자로 이루어졌으며 대형 과제 추정에 매우 유용하다. 하지만 일상적 관리 용도로 사용하기에는 너무 정밀도가 낮다. #### 스토리 추정하기 스토리는 **시스템의 기능을 사용자 관점에서 간략하게 설명한 것**이다. 스토리의 문구는 단순해야 한다. 세부 사항을 정하기에는 아직 이를 때이므로 **세부 사항은 생략**해야 한다. 세부 사항을 정하는 일은 늦추면 늦출수록 좋다. 스토리를 개발하기 직전까지 미뤄 두어도 좋다. 스토리를 요약한 형태로 놔둠으로써 나중에 대화하기로 약속하는 것이다. 스토리는 프로젝트 전체에 걸쳐서 언제나 만들어지고, 바뀌고, 버려지고, 개발된다. 새로운 스토리가 나타나거나 기존 스토리에 관한 새로운 소식이 있을 때 회의를 소집할 수 있으며, 이런 미팅은 일상적으로 스프린트마다 꾸준하게 열릴 것이다. **회의 길이는 스프린트 길이의 1/20 정도가 좋다.** (2주 단위라면 4시간) 첫 번째 스프린트 (스프린트 0) 회의에서 스토리들에 포인트를 매긴다. (e.g., `로그인` 스토리에 3포인트, `로그아웃` 스토리에 1포인트) #### 스프린트 1 계획하기 스프린트는 **스프린트 계획 회의**<sub>(Iteration Planning Meeting, IPM)</sub>로 시작한다. 회의 길이는 전체 스프린트 길이의 1/20 정도가 좋다. 2주 단위의 스프린트라면 4시간 정도를 회의에 할애하는 정도다. - 팀 전원이 참석해야 한다. - 이해관계자는 회의에 앞서 추정한 스토리들을 읽고, 비즈니스 가치 순서로 정리해 와야 한다. - 이해관계자는 스프린트 동안 프로그래머와 테스터가 구현할 스토리를 골라야 한다. - 그러려면 이해관계자는 프로그래머의 속도를 알아야 한다. - 이 속도는 적당히 짐작하는 것이다. - 이 속도는 약속이 아니다. 여기서 30포인트의 스토리를 처리한다고 짐작했다고 치자. #### 투자 수익률 이해관계자는 가치와 비용을 놓고 고민해야 한다. - 가치가 높고 비용이 낮은 스토리는 바로 작업해야 한다. - 가치는 높지만 비용이 높으면 나중에 한다. - 가치는 낮고 비용이 낮으면 언젠가는 할 것이다. - 가치는 낮고 비용이 높으면 절대 하지 않을 것이다. #### 중간 확인 스프린트 둘째 주의 첫날인 월요일 아침, **중간 검토 회의**를 진행한다. 완료한 스토리를 더해보니 10포인트밖에 처리하지 못했다. 이해관계자는 계획했던 스토리를 줄여 남아있던 포인트를 20에서 10으로 낮춘다. 금요일 오후, 데모와 함께 스프린트가 끝난다. 최종적으로 18포인트를 처리하였다. 이번 스프린트는 실패일까? 아니다! 스프린트에 실패란 없다. 스프린트의 목표는 관리자에게 데이터를 제공하는 것이다. 스프린트 동안 작동하는 코드를 만든 것은 물론 좋은 일이지만, 그렇게 하지 못했더라도 데이터는 만들어 냈을 것이다. #### 어제의 날씨 이제 우리는 스프린트 한 번에 약 18포인트를 처리할 수 있다는 것을 안다. 다음 스프린트의 목표는 몇 포인트가 되어야 할까? 당연히 18포인트다. 그런데 이번 스프린트 중간 검토 회의에서 벌써 12포인트나 완료하는 일이 일어났다. 이해관계자는 계획에 6포인트를 추가해서 스프린트의 계획이 총 24포인트가 되었다. 실제로 스프린트가 끝나고 보니 계획과 달리 22포인트를 완료했다. 다음 스프린트에는 22포인트만큼 스토리를 고를 것이다. #### 프로젝트 종료 이렇게 흘러간다. 스프린트가 끝날 때마다 속도 차트에 스프린트의 속도를 기록하므로, 누구나 이 팀이 일을 진행하는 속도를 알 수 있다. 스프린트는 스토리 더미에서 투자 수익률을 퍼내서 낮추는 펌프와 같다. 요구 사항을 계속해서 탐색하면서 스토리를 추가하면, 스토리의 평균 투자 수익률은 다시 올라간다. 올라가는 투자 수익률이 퍼내는 투자 수익률보다 더 많다면, 프로젝트는 계속된다. 프로젝트는 스토리를 모두 구현함으로써 끝나는 것이 아니다. 프로젝트는 스토리 더미에 구현할 가치가 있는 스토리가 더 이상 없을 때 끝난다. #### 스토리 **사용자 스토리는 기능을 기억하기 위해 쓰는 짧은 설명이다.** 스토리를 쓸 때 너무 많은 세부 사항을 적으면 안 된다. 세부 사항은 쉽게 바뀌기 때문이다. 세부 사항은 나중에 **인수 테스트** 형태로 작성한다. 스토리를 쓸 때는 다음 여섯 가지를 지켜야 한다. (INVEST) 1. 가능한 서로 **독립적**이면 좋다. 독립적이란, 서로 순서가 무관하다는 한다는 말이다. 2. 개발자가 사업 부서가 **협상할 수 있어야** 한다. 개발 비용을 관리할 수 있는 기회다. 3. 언제나 **비즈니스 가치가 있는 일**이어야 한다. 리팩터링, 아키텍처는 스토리가 될 수 없다. 4. **작업량을 추정**할 수 있을 정도로 **구체적**이어야 한다. '시스템 속도가 빨라야 함' 같은 스토리는 그 뜻이 분명하지 않아 추정할 수가 없다. 5. 개발자 한두 명이 스프린트 한 번 이내에 구현할 수 있을 정도로 **작아야 한다.** 6. 스토리 완료를 증명하는 **테스트 가능 여부**를 제시할 수 있어야 한다. #### 스토리 추정 - 날아다니는 손가락<sub>(Flying Fingers)</sub> - 스토리에 대한 논의를 끝낸 후, 개발자들은 모두 한 손을 등 뒤에 안 보이게 감추고, 자신이 생각하는 스토리 포인트를 손가락으로 표시한다. 그리고 하나 둘 셋을 세면 동시에 손을 공개한다. - 편차가 크지 않고, 평균값이 명백하면, 숫자를 스토리 카드에 적고 다음 스토리로 넘어간다. - 편차가 크다면 토론하고 합의될 때까지 위를 반복한다. - 계획 포커<sub>(Planning Poker)</sub> - 피보나치 수열 비슷한 숫자가 적힌 카드를 이용한다. (0, 1/2, 1, 2, 3, 5, 8..., ♾) - 큰 스토리를 추정할 수 있다는 장점이 있다. #### 쪼개기, 합치기, 스파이크 - 스토리를 합칠 때는 합칠 스토리의 포인트를 다 더한다. - 스토리를 쪼갤 때는 INVEST를 지키면서 쪼갠다. - 스파이크는 메타스토리<sub>(meta-story)</sub>라고 부르는 **스토리를 추정하는 스토리**다. - 구현해본 적이 없어서 추정하기 힘든 기능을 담은 `스토리 X`가 있다고 치자. 그럴 때는 `X 추정하기`라는 스토리를 만든다. #### 스프린트 관리하기 각 스프린트의 목표는 스토리를 처리하여 데이터를 얻는 것이다. 모든 스토리를 각각 80% 완료한 것보다는 완료한 스토리 수가 전체 스토리 수의 80%인 것이 훨씬 더 낫다. **스토리를 완료하는 데 집중하라.** 스프린트 계획 회의가 끝나면, 개발자들은 각자 어떤 스토리를 담당할지 골라야 한다. 조직에 따라서 스토리를 하나씩만 골라 가져간 뒤, 각자 완료한 뒤 추가로 고르는 방식을 사용하기도 한다. 어떤 방식이든 **개발자가 스스로 스토리를 골라야 한다.** #### QA와 인수 테스트 (인수 테스트란, 실제 사용자 환경에서 사용자의 입장으로 테스트를 수행하는 것을 말한다.) QA는 계획 회의 이전부터, 늦어도 계획 회의가 끝나자마자 자동화된 인수 테스트 작성을 시작해야 한다. **인수 테스트는 스프린트 초반에 빨리 만들어야 한다.** 스프린트의 절반이 지나도 인수 테스트가 다 만들어지지 않았다면 개발자도 작업을 멈추고 인수 테스트 작성을 도와야 한다. 그러다 보면 스프린트에 계획했던 스토리를 다 끝내지 못할 수도 있지만, 어차피 인수 테스트가 없으면 스토리를 완료할 수 없다. 다만 주의해야 할 점은, **특정 스토리를 구현하는 개발자가 그 스토리의 인수 테스트까지 작성하면 안 된다**는 것이다. **개발자와 QA는 인수 테스트 이야기를 많이 해야 한다.** 어떻게 테스트를 구성할지, 어떻게 나누어 작성할지 상의해야 한다. 아예 짝 프로그래밍으로 함께 작성하는 것도 좋다. **'완료'의 정의는 '인수 테스트 통과'다.** #### 데모 이해관계자에게 완료한 스토리의 데모를 간단히 시연하는 것으로 스프린트가 끝난다. 데모할 때는 모든 인수 테스트와 단위 테스트를 통과하는 것도 보여 주어야 한다. 과거 스프린트 동안 완료한 스토리의 인수 테스트도 모두 포함해야 한다. 이해관계자가 직접 시스템을 사용해 볼 수 있다면 제일 좋다. #### 속도 스프린트를 마치면서 속도 그래프와 번다운 차트를 기록한다. 스프린트가 몇 번 지나면, 그래프의 기울기가 보이기 시작할 것이다. **번다운 차트의 기울기를 보면 다음 주요 마일스톤을 언제 달성할지** 알 수 있다. **속도 그래프의 기울기를 보면 팀 관리가 얼마나 잘 되고 있는지** 알 수 있다. **속도는 측정하는 것이지 목표하는 것이 아니다. 측정하려는 대상에 압력을 가하지 말라.** 속도가 꾸준히 계속 떨어진다면, 코드 품질에 문제가 있을 가능성이 제일 크다. 리팩터링을 충분히 하지 않아서 아마 코드가 썩고 있을 것이다. 리팩터링을 충분히 하지 않는 이유 중 하나는 단위 테스트를 충분히 쓰지 않아서다. 리팩터링으로 무언가 망가질까 봐 두려운 것이다. **변경을 두려워하지 않게 만드는 것도 팀 관리의 주요 목표**가 되어야 하는데, 결국은 모두 테스트 규율의 문제다. 속도가 떨어지면 팀에 압박이 가해질 수 있고, 그러면 포인트 인플레이션<sub>(스토리 포인트를 무의식적으로 조금씩 올려서 추정하는 것)</sub>이 발생해서 떨어지던 속도가 다시 일정해질 수 있다. #### 기준 스토리 포인트 인플레이션을 막는 한 가지 방법은, 스토리 추정 결과를 계속해서 예전에 정한 스토리 기준과 비교해 보는 것이다. ### 작은 릴리스<sub>(Small Release)</sub> 작은 릴리스 실천 방법은 개발팀이 소프트웨어를 최대한 자주 릴리스할 것을 권장한다. 90년대 말, 애자일 초기에는 이것이 '한두 달'에 한 번 릴리스하는 것이라고 생각했지만, 요즘에는 훨씬 더 짧아야 한다. 그래서 새로운 목표는 지속적 배포<sub>(Continuous Delivery)</sub>다. 변경 사항이 생길 때마다 코드를 서비스에 배포하는 것이다. ### 인수 테스트 인수 테스트는 애자일 실천 방법 중 아는 사람이 가장 적고, 드물게 사용되며, 많이들 오해하는 실천 방법이다. 기반이 되는 발상은 '**사업 부서가 요구 사항을 명시해야 한다**'는 것이다. 여기서 문제는 '**명시<sub>(specify)</sub>**'라는 단어가 무엇을 뜻하느냐다. 사업 부서는 애매하고 불분명한 용어로 동작을 설명하고 명시했다고 말하고, 개발자는 픽셀 하나하나의 위치와 색깔까지 정확하게 정의해주기를 바란다. 그렇다면 '**명세<sub>(specification)</sub>**'란 뭘까? 명세란 그 본질상 테스트다. > 사용자가 올바른 사용자 아이디와 비밀번호를 입력하고 '로그인'을 클릭하면, 시스템은 '환영합니다' 페이지를 표시해야 한다. 확실한 명세고, 확실한 테스트다. 이 테스트를 자동화할 수 있다는 것도 분명하다. 인수 테스트는 가능한 한, 시스템의 요구 사항을 자동화된 테스트 형태로 작성해야 한다. 사업 부서가 요구 사항을 명시해야 하므로 **인수 테스트는 사업 부서가 작성해야 한다.** #### 실천 방법 사업 부서에서 각 사용자 스토리의 동작을 설명하는 테스트를 형식에 맞게 작성하고, 개발자는 이를 자동화한다. 인수 테스트는 업무 분석가<sub>(business analyst)</sub>와 QA가 작성한다. 개발자는 이 테스트를 지속적 빌드<sub>(continuous build)</sub>에 통합한다. #### 업무 분석가와 QA - 업무 분석가는 정상적으로 성공하는 경로만 기술한다. - QA는 정상에서 벗어난 경로를 담당한다. - 개발자는 테스트가 기술적인 관점에서 타당한지 확인한다. #### QA 이렇게 되면 QA의 역할이 완전히 달라진다. 에러나 빠진 요소를 뒤늦게 검사해 알려 주는 것이 아니라, 문제를 예방할 수 있도록 초기부터 개발팀을 안내하게 된다. 이렇게 되면 다음의 장점이 있다. - 프로세스 막바지에 QA에게 집중되는 부담이 완화된다. - 프로세스 막바지에 일정 압박을 받은 QA가 테스트를 건너 뛸 상황을 만들지 않는다. #### 개발자가 테스트를 돌린다 QA는 인수 테스트를 작성하지만, 테스트를 돌리고 테스트를 통과하는지 확인하는 사람은 개발자다. 개발자가 테스트를 돌려보는 것이 스토리 완료 여부를 알 수 있는 유일한 방법이다. ### 전체 팀 전체 팀<sub>(Whole Team)</sub> 실천 방법은 원래 현장 고객<sub>(On-Site Customer)</sub>이라고 불렀었다. 기본적인 생각은 사용자와 개발자가 물리적으로 가까이 있을수록 의사소통하기 더 좋을 거라는 것이었다. 여기서 고객은 사용자가 필요로 하는 것을 잘 알면서 개발팀과 같은 곳에서 일하는 사람이나 그룹을 가리키는 메타포다. 이 실천 방법의 이름을 전체 팀으로 바꾼 것은, 개발팀이 단순히 고객과 개발자 둘만으로 이루어진 것이 아니라는 점을 명확히 하기 위해서다. 개발팀에는 고객과 개발자 외에도 관리자, 테스터, 테크니컬 라이터 등 많은 역할이 있다. **전체 팀의 목표는 각 역할을 하는 사람들 사이의 물리적 거리를 최소화하는 것이다.** #### 떨어져서 일할 때의 대안 1990년대, 노동 임금이 월씬 낮은 나라에서 개발자 인력을 채용하여 비용을 절감할 수 있으리라 믿었지만 잘 실현되지 않았다. 물리적인 거리와 시차, 언어 장벽, 문화의 차이가 큰 문제였고, 의사소통 오류가 만연했다. 품질은 형편없었다. 그 이후로 기술이 어느 정도 발전해서 화상 회의나 스크린 공유를 일상적으로 할 수 있게 되었지만, 이런 식으로 애자일팀이 잘 굴러갈지는 의문이다. 가능하다는 얘기를 듣기는 했지만 성공적으로 운영되는 것을 본 적은 없다. 팀 동료가 집에서 일하면, 비언어적 의사소통에서 손해를 보는 부분이 분명 있다. 우연히 생기는 대화도 훨씬 줄어든다. 인터넷 대역폭이 아무리 넓어도, 같은 곳에서 일하는 사람끼리 하는 의사소통에 비할 바는 아니다. 오해하지 말기를 바란다. 90년대 초반, 나는 내 동업자들과 뿔뿔이 흩어져 있는 팀을 성공적으로 관리한 적이 있다. 우리는 잘 해냈다. 하지만 **우리가 모두 같은 방에서 일할 수 있었다면 훨씬 더 잘 해낼 수 있었을 것이다.** ## 팀 실천 방법 팀 실천 방법은 팀 구성원 사이의 관계, 그리고 팀원과 팀이 만드는 제품 사이의 관계를 다룬다. ### 메타포<sub>(Metaphor)</sub> 애자일 선언 전후 수년간 메타포 실천 방법에 대해 어떻게 설명해야 할지 몰랐다. 중요하다는 것은 알았지만 정확한 뜻을 효과적으로 표현할 수가 없었다. 기본적인 아이디어는 이렇다. **팀 내에서 효과적으로 의사소통을 하려면, 개념을 나타내는 어휘와 용어를 명확하게 정의하여 일관되기 사용**해야 한다는 것이다. 프로젝트를 팀원 모두가 잘 아는 무언가에 비유하는 일이기 때문에 이 실천 방법에 메타포라는 이름을 붙였다. #### 도메인 주도 설계<sub>(Domain-Driven Design)</sub> `<Domain-Driven Design: Tackling Complexity in the Heart of Software>` 라는 책에서 메타포보다 더 어울리는 이름인 유비쿼터스 언어<sub>(Ubiquitous Langunage)</sub>라는 표현을 제안하였다. 도메인 주도 설계에서는 해결하려는 문제 도메인의 모델을 모든 사람<sub>(개발자, QA, 관리자, 고객, 사용자...)</sub>이 동의하는 어휘로 표현해야 한다. 유비쿼터스 언어는 프로젝트의 모든 곳에서 쓰인다. 사업 부서에서도 사용하고, 개발자도 사용한다. QA도, 운영팀이나 데브옵스도 사용한다. 심지어는 고객도 유비쿼터스 언어 중 적절한 것을 사용할 수 있다. 유비쿼터스 언어는 경영 사례에도 쓰일 수 있고, 요구 사항이나 설계, 아키텍처, 인수 테스트에도 쓰일 수 있다. 프로젝트의 모든 단계에 걸쳐서 사용되어, 전체 프로젝트를 일관성 있게 연결한다. ### 지속 가능한 속도 #### 초과 근무 내가 가장 말도 안 되는 실수를 하는 때는 늦은 밤 정신없이 일하는 도중이었다. 밤에 저지른 실수를 만회하느라 진짜 제정신인 시간을 계속해서 써야만 했다. #### 마라톤 소프트웨어 프로젝트는 단거리 경주가 아니라 마라톤이다. **좋은 성적을 내려면 자신에게 맞는 속도를 찾아야 한다.** 관리자가 당신에게 무리하게 더 빨리 달리라고 할 수도 있다. 그 말을 따르면 안 된다. **끝까지 일할 수 있도록 당신 자신을 관리하는 일은 당신의 몫이다.** #### 헌신 고용주에게 당신이 얼마나 헌신적인지 보여 주고 싶을 때, **야근은 좋은 방법이 아니다.** 야근이 증명하는 것은 당신이 계획을 잘못 세운다는 것, 동의하지 않았어야 하는 일정에 동의했다는 것, 하지 말았어야 하는 약속을 해 버렸다는 것, 전문가가 아니라 다루기 쉬운 초보자라는 것 뿐이다. #### 잠 **개발자의 삶을 구성하는 성분 중 가장 소중한 것은 바로 충분한 수면**이다. 자신의 몸이 몇 시간을 자야 하는지 잘 파악하고, 이 시간을 확보해야 한다. 내 경험상 잠이 한 시간 부족하면 낮에 대략 두 시간은 날리게 된다. 잠이 두 시간 부족하면 낮에 여섯 시간은 날리게 된다. 잠이 세 시간 부족하면 당연히 생산적인 일을 아예 못하게 된다. ### 공동 소유<sub>(Collective Ownership)</sub> 애자일 프로젝트에서는 아무도 코드를 소유하지 않는다. 코드는 팀 전체가 공동으로 소유한다. 내가 수백 개의 모듈로 이루어진 시스템을 개발할 때, 팀의 누구도 특정 모듈을 소유하지 않았다. 물론 누군가는 다른 사람보다 특정 모듈에 더 익숙하긴 했지만, 구성원 전부가 모든 모듈을 공부하고 개선하기 위해 노력했다. 우리는 경험을 집중시키지 않고 퍼트리기 위해 애썼다. 공동 소유가 당신이 전문성을 더 키울 수 없다는 뜻은 아니다. 시스템이 복잡해질수록 반드시 전문성이 필요해진다. 하지만 전문성을 키우면서도 넓게 알아야 한다. **전문성을 발휘할 수 있는 업무와 그 외 분야의 코드에 대한 업무를 두루 맡아야 한다.** 언제나 잘하는 영역을 벗어나서 일할 수 있어야 한다. 공동 소유를 실천하면, 지식이 팀 전체에 퍼진다. 팀 구성원 모두가 모듈 사이의 경계나 전반적인 시스템 동작을 더 잘 이해하게 된다. 그 결과, **팀 내 의사소통이 훨씬 원활하게 이루어지고 더 좋은 결정을 내릴 수 있게 된다.** 개발자가 제각각 모듈을 소유하고, 다른 사람은 건드릴 수 없는 조직은 완전히 망가져서 서로를 오해하고 비난하느라 바빴다. 담당자가 자리를 비우면 해당 모듈의 작업은 모두 멈췄다. 다른 사람이 소유한 모듈은 감히 작업할 엄두도 내지 못했다. ### 지속적 통합 애자일 초기에는 지속적 통합이 한두 시간에 한 번 정도 소스 코드를 체크인하고, 주 브랜치에 머지한다는 뜻이었다. 모든 단위 테스트와 인수 테스트는 계속 통과해야 한다. 기능 브랜치가 통합되지 않은 채 남아 있어서는 안 된다. 배포할 때 동작하면 안 되는 기능은 토글로 비활성화시켜야 한다. 젠킨스와 같은 지속적 빌드 도구가 나온 뒤로 '한두 시간'은 '몇 분'으로 바뀌었다. '지속적 통합'은 '지속적 체크인'이 되었다. 지속적 빌드는 절대 깨지지 않아야 한다. ### 스탠드업 미팅 '일일 스크럼'이나 '스탠드업 미팅'에 대한 많은 오해가 수년간 이어져 왔는데, 진짜 스탠드업 미팅이란 이런 것이다. - 미팅 참석은 필수가 아니다. 대부분의 팀에서는 한 명쯤 빠져도 된다. - 꼭 매일 할 필요는 없다. 각 팀에 맞는 일정을 잡으면 된다. - 10분이 넘게 걸리면 안 된다. 팀이 크더라도 말이다. - 회의는 다음과 같이 단순한 방식으로 진행한다. - 기본적으로 팀 구성원이 둥글게 둘러서서, 세 가지 질문에 대한 답을 한다. 1. 지난 스탠드업 미팅 이후 무엇을 했는가? 2. 다음 스탠드업 미팅까지 무엇을 할 것인가? 3. 어떤 장애물이 있는가? 이게 전부다. 토론은 없다. 꾸미는 것도 없다. 자세한 설명도 없다. **모든 사람이 30초 정도 안에 세 가지 질문에 대한 답을 해야 한다.** 그리고 스탠드업 미팅이 끝나면 다시 일을 시작한다. #### 감사 인사 내가 시도해 본 것 중 괜찮았던 것이 있는데, 다음 질문을 네 번째 질문으로 추가하는 것이었다. - 누구에게 감사하고 싶은가? 당신을 도와준 사람이나 칭찬받아 마땅하다고 생각하는 사람에게 가볍게 감사를 표하는 것이다. ## 기술 실천 방법 이번 장에서 소개할 실천 방법은 지난 70년간 개발자가 일해온 방식과 완전히 다르다. 이 실천 방법은 매분 매초 강박적인 행동을 엄청나게 시키는데, 처음 접하는 개발자라면 대부분 정신 나간 짓이라고 생각할 만하다. 사실 그래서 많은 개발자가 애자일을 시도할 때 기술 실천 방법은 빼놓는다. 하지만 이런 시도는 실패하기 마련이다. **기술 실천 방법이야말로 애자일의 진짜 핵심**이기 때문이다. ### 테스트 주도 개발<sub>(Test-Driven Development, TDD)</sub> 테스트 주도 개발은 제대로 설명하려면 별도로 책이 한 권 필요할 만큼 이야기할 것이 많고 복잡한 주제이므로, 이번 장에서는 동기와 도입 이유에 더 집중해서 간단히 살펴보겠다. 개발자는 TDD를 공부할 때, **기능을 한 번에 하나씩만 추가**하라고 배운다. 실패하는 테스트 형태로 먼저 하나 추가하고, 이 테스트를 통과하게 만드는 제품 코드 형태로 다시 추가한다. 이렇게 하면 오류를 빠르게 찾을 수 있다. TDD는 회계에서의 복식 부기<sub>(모든 거래를 장부에 두 번씩 기록하는 것)</sub>와 같다. **구현해야 하는 동작을 두 번씩 입력한다. 한 번은 테스트로, 그리고 한 번은 이 테스트를 통과하게 만드는 제품 코드로 말이다.** 프로그래밍이 우리 사회에 필수로 여겨일 만큼 중요해졌는데도 TDD는 아직 법으로 강제되지 않았다. 하지만 엉망으로 만들어진 소프트웨어의 동작 때문에 잃어버린 생명과 재산을 고려한다면, 이런 법이 만들어지는 일이 그저 상상만은 아닐 것이다. #### TDD의 세 가지 규칙 - 해당 코드가 없어서 실패하는 테스트 코드를 쓰기 전에 **제품 코드를 먼저 쓰면 안 된다.** - 테스트 코드를 쓸 때는 실패하도록 만들기 위해 **필요한 것보다 더 많이 쓰면 안 된다.** 컴파일 실패도 실패로 간주한다. - 실패하는 **테스트를 통과시키기 위해 필요한 코드보다 더 많은 제품 코드를 쓰면 안 된다.** 세 가지 규칙을 따르면 테스트 코드와 제품 코드를 쓰는 시간은 각각 수초 정도밖에 되지 않고, 개발자는 끝없이 왔다갔다 하게 된다. 제품 코드를 쓰다가 멈춰서 테스트 코드를 쓰고, 또 제품 코드를 쓰다가 멈춰서 테스트 코드를 쓰고, 함수 하나를 만들려면, 아니 간단한 `if` 문이나 `while` 루프를 쓰는 데도 몇 번씩이나 왔다갔다 하게 될 것이다. 대부분의 개발자가 처음에는 이런 방식이 생각의 흐름을 끊는다고 여긴다. 세 가지 규칙 때문에 계속해서 작업이 중단되면, 작성하는 코드의 흐름을 제대로 파악하기 어려워진다고 말이다. 세 가지 규칙을 지키느라 좀처럼 집중할 수 없다고 느끼는 경우도 많다. 하지만 어떤 개발자 집단이 세 가지 규칙을 잘 지킨다고 상상해 보자. 그리고 특정한 순간에 이들 중 한 명을 고른다고 해 보자. 이 개발자가 작업하던 코드는 아무리 길어도 1분 전까지는 실행 가능했고, 테스트를 모두 통과했다. 누구를 고르더라도 아무리 길어도 1분 전까지는 모든 것이 작동했다. #### 디버깅 언제나 1분만 거슬러 올라가면 모든 것이 작동한다는 것은, 맞딱드리는 거의 모든 오류가 1분 전에는 없었다는 소리다. 1분도 채 안 되는 시간 전에 추가한 것 때문에 오류가 생겼다면, 원인을 찾기 위해 디버거를 사용할 필요조차 없을 것이다. TDD를 하면 디버거를 쓸 일이 별로 없기 때문에 디버거에 익숙해질 수가 없다. 하지만 세 가지 규칙을 실천하면 버그의 횟수나 심각한 정도는 크게 줄일 수 있다. #### 문서화 개발자는 보통 기술 문서를 읽을 때 본문을 건너뛰고 코드 예제를 본다. 코드는 거짓말을 하지 않기 때문이다. TDD의 세 가지 규칙을 따르다 보면 만들어지는 테스트는 전체 시스템의 코드 예제가 된다. 코드와 늘 함께 갱신된다. 개발자에게 완벽한 형식의 문서가 있다면, 코드 형태의 테스트일 것이다. #### 완벽함 사후 테스트 추가 방식으로는 제대로 된 테스트를 만들기 힘들다. 그 이유는 테스트 가능 여부를 생각하지 않으면서 코드를 작성하고, 설계할 때도 테스트를 고려하지 않았기 때문이다. 이 코드의 테스트를 만들려면 코드의 구조를 뜯어고쳐야 하는데, 이미 잘 작동하는 코드를 고치는 것은 쉽지 않다. 그래서 자기 합리화를 하며 테스트에 구멍을 남겨 놓는다. **불완전한 테스트 묶음으로는 아무런 결정을 할 수 없다.** TDD의 세 가지 규칙을 잘 따랐다면, 모든 제품 코드는 테스트를 통과하게 만들려고 쓴 것이다. 따라서 테스트 묶음이 아주 완벽할 것이다. 테스트가 통과했다면 우리는 '배포'를 하는 결정을 내릴 수 있다. **시스템을 배포해도 되는지 알려주는 자동화된 테스트 묶음을 만드는 것**이 우리의 목표다. 하지만 현실적으로 100%의 테스트 커버리지를 달성할 수는 아마도 없다. 하지만 90% 후반 정도면 배포 결정을 내리기에 충분하다. ##### 경고 - 테스트 커버리지는 팀 내부용 지표이지 관리 지표가 아니다. 관리자는 테스트 커버리지를 목표나 목적으로 삼아서는 안 된다. - 커버리지가 낮다고 빌드에 실패한 것으로 보아서는 안 된다. 이렇게 하면, 개발자는 커버리지를 높이기 위해 의미 없는 테스트를 추가할 것이다. #### 설계 사후 테스트 추가가 힘든 이유는 테스트하기 쉽계 설계하지 않았기 때문이다. 제품 코드를 먼저 쓰고, 테스트를 나중에 덧붙이기 때문이다. 하지만 테스트를 먼저 쓴다면 테스트하기 쉬운 설계가 나오는 것은 당연하다. 테스트할 수 있다는 것은 분리했다는 것과 같은 뜻이다. 테스트를 먼저 쓰면 예전에는 생각조차 못해 본 방식으로 시스템을 쪼갤 수 있게 된다. 그래서 TDD를 설계 기술로 보기도 한다. #### 용기 TDD를 하는 진정한 이유는 디버깅을 줄이는 것도, 재미나 완벽함을 얻기 위한 것도, 시스템을 분리하기 위한 것도 아닌 **용기를 얻기 위해서다.** 오래된 코드를 수정해야 할 때, 혹시나 코드가 망가지는 것이 두려워서 곪아 터지도록 놔두는 것을 막기 위해서다. 모든 구성원이 이렇게 행동하면 코드는 반드시 썩는다. 여기에 무언가 생산적인 작업을 하는 것은 불가능에 가깝다. 관리자는 좌절하고 나머지 전체 시스템을 밑바닥에서부터 다시 만들자는 개발자들의 요구를 수용하고 말 것이고, 역사는 반복될 것이다. **완벽한 테스트 묶음이 있으면 코드를 고치는 두려움이 사라진다.** 따라서 코드를 정리할 것이고, 시스템 설계를 건강하게 유지할 것이다. 이것이 우리가 TDD를 하는 이유다. TDD는 용기를 준다. 용기가 있어야 전문가답게 행동할 수 있다. ### 리팩터링 리팩터링은 코드의 구조를 개선하면서 동작은 바꾸지 않는 실천 방법이다. 다시 말해서, 테스트를 깨 먹지 않으면서 이름이나 클래스, 함수, 표현식을 변경하는 것이다. 두려움 없이 리팩터링하려면, 무언가 깨 먹지 않았다는 확신을 얻을 수 있는 테스트 묶음이 필요하다. #### 빨강/초록/리팩터링 본질적으로 리팩터링은 TDD의 세 가지 규칙을 반복함으로써 이루어진다. 리팩터링에서는 빨강/초록/리팩터링 주기라고 부른다. 1. 먼저, 실패하는 테스트를 만든다. 2. 그리고 이 테스트를 통과하게 만든다. 3. 그리고 코드를 정리한다. 4. 1단계로 돌아간다. 여기서 핵심은 작동하는 코드를 쓰는 것과 코드 정리하기라는 두 가지를 다른 측면으로 분리한 것이다. 두 가지 측면을 동시에 다루는 것은 어려울 수밖에 없기 때문이다. 쉽게 말하면, 깨끗한 코드를 만드는 것은 고사하고, 그저 테스트를 통과하게 만드는 것만으로도 충분히 어렵다. 그러니 일단 머리에 떠오르는 어떤 지저분한 수단이든 동원해서 작동하는 코드를 만드는 데 집중하자. 그리고 일단 작동하면 테스트는 통과했을 것이고, 이제 그동안 만든 지저분한 것들을 정리하자. 이렇게 보면 **리팩터링은 연속적인 과정**이라는 것이 명확해진다. 따로 일정을 잡고 하는 것이 아니라는 말이다. 1분 혹은 2분 동안 조금 헝클어뜨리고는, 바로 치우는 것이다. **리팩터링이라는 단어가 일정에 나타나서는 안 된다.** 리팩터링할 시간을 따로 할당해서도 안 된다. 리팩터링은 소프트웨어를 작성할 때 몇 분마다, 혹은 몇 시간마다 하는 일상적인 작업의 일부일 뿐이다. #### 더 큰 리팩터링 가끔은 요구 사항이 바뀌어서 시스템 구조를 꽤 많이 바꿔야 할 수도 있다. **이런 변경도 빨강/초록/리팩터링 주기 안에서 일어나야 한다.** 설계 변경이 목적인 프로젝트를 만들어서는 안 된다. 그보다는 조금씩 조금씩 코드를 바꿔 나가야 한다. 일반적인 애자일 주기에 따라 계속해서 새로운 기능을 추가하면서 말이다. ### 단순한 설계<sub>(Simple Design)</sub> 단순한 설계 실천 방법은 리팩터링의 목표 중 하나다. 단순한 설계는 최대한 단순하고, 작고, 표현력이 뛰어난 구조를 바탕으로 최소한의 코드만 작성하는 실천 방법이다. 단순한 설계의 규칙은 다음과 같다. 1. 모든 테스트를 통과할 것 2. 의도를 드러낼 것 3. 중복을 없앨 것 4. 구성 요소를 줄일 것 규칙의 순서는 실행하는 순서이면서 동시에 중요한 순서이기도 하다. 1번은 자명하다. 2번은 코드가 일단 작동하면 다음으로 표현력 있게 만들어야 한다는 것이다. 읽기 쉽고, 따로 설명이 필요 없어야 한다. 보통은 이 규칙 때문에 간단하고 보기 좋게 만들기 위한 리팩터링을 많이 하게 된다. 3번은 코드가 가능한 한 이해하기 쉽고, 표현력 있게 만들어진 후, 코드 내의 중복을 찾아서 제거해야 한다는 뜻이다. 단순한 경우 중복인 부분을 함수로 때낸 다음, 이 함수를 호출하도록 바꾸기만 하면 될 때도 있다. 하지만 디자인 패턴과 같은 더 흥미진진한 해결책을 사용해야 하는 경우도 있다. 4번은 중복을 제거한 후에는, 클래스나 함수, 변수 같은 구성 요소의 수를 줄이기 위해 노력해야 한다는 것이다. 단순한 설계의 목표는 코드의 '설계 무게'를 가능한 한 가볍게 만드는 것이다. #### 설계 무게 설계의 복잡도와 기능의 복잡도 사이에서 균형을 잡는 것이 단순한 설계의 목표다. 개발자는 단순한 설계 실천 방법을 사용하여 끊임없이 시스템의 설계를 리팩터링한다. 그래서 요구 사항과 설계의 균형을 유지하고, 궁극적으로 높은 생산성을 유지한다. ### 짝 프로그래밍<sub>(Pair Programming)</sub> 짝 프로그래밍 실천 방법에 대하여 오랫동안 논란과 헛소문이 많았다. 일단 먼저 짝 프로그래밍을 꼭 해야 하는 것은 아니다. **누구도 짝 프로그래밍을 강요해서는 안 된다.** 둘째로, 짝 프로그래밍은 잠깐씩 하는 것이다. 짝 프로그래밍이 차지하는 업무 비중은 30%~80% 정도가 좋다. 팀에서 혹은 각자가 선택하기 나름이다. #### 짝 프로그래밍이란 무엇인가? 짝 프로그래밍은 프로그래밍 문제 하나를 두 사람이 함께 해결하는 행위다. 컴퓨터를 몇 대 쓰건, 모니터와 키보드를 어떻게 쓰건 상관없다. 짝 프로그래밍을 할 때 각자 역할을 나누기도 하지만, 역할 구분 없이 하는 경우가 제일 많다. 개발자들은 마우스와 키보드를 공유하며 서로 힘을 모아 동등한 관계에서 코드를 작성한다. 짝 프로그래밍 일정은 따로 잡지 않는다. 개발자가 원하는 대로 짝을 만들었다가 없앨 수도 있다. 관리자가 짝 프로그래밍 일정을 잡거나, 짝 배정을 하려고 해서는 안 된다. 짝 프로그래밍의 길이는 길어야 하루 정도고, 대부분은 한두 시간 안에 끝나야 한다. 15분이나 30분 정도의 짧은 짝 프로그래밍도 많은 도움이 된다. 짝이 스토리를 담당하지는 않는다. 짝이 아니라 개발자 한 명 한 명이 스토리를 완성할 책임을 져야 한다. 한 주를 통틀어 보았을 때, 각 개발자는 짝 프로그래밍 시간의 절반은 다른 사람의 도움을 받아 자신이 담당한 작업을 진행하는 데 쓰고, 나머지 절반은 다른 사람의 작업을 도와주는 데 써야 한다. 고급 개발자는 다른 고급 개발자보다는 초급 개발자와 더 자주 짝을 지어야 한다. 초급 개발자는 다른 초급 개발자에게 도움을 청하기보다 다른 고급 개발자에게 도움을 청해야 한다. 전문 분야가 따로 있는 개발자는 짝 프로그래밍 시간 중 상당 부분을 해당 분야 이외의 일을 하는 개발자와 보내야 한다. **짝 프로그래밍을 목표는 지식을 모으는 것이 아니라 퍼트리고 교환하는 것이다.** #### 짝 프로그래밍을 하는 이유 우리는 팀이 되기 위하며 짝 프로그래밍을 한다. 짝 프로그래밍은 구성원끼리 지식을 공유하고, 지식의 칸막이가 생기지 않게 만드는 단연코 최고의 방법이다. **팀에 빠지면 안 되는 사람이 생기지 않게 만드는 최고의 방법**이다. 짝 프로그래밍 덕분에 에러를 줄이고, 더 나은 설계를 할 수 있었다는 보고가 많이 있다. 어떤 문제든 눈이 둘 넘게 있는 편이 확실히 더 낫다. 그래서 많은 팀에서 코드 리뷰를 짝 프로그래밍으로 대체했다. #### 비용은? 측정하기 어렵지만, 가장 눈에 띄는 비용은 하나의 문제를 풀기 위해 두 사람이 일한다는 것이다. 그렇다고 해서 문제를 해결하는 비용이 두 배가 되지는 않을 것이다. 여러 연구에 따르면 직접적인 비용 증가는 15% 정도라고 한다. 업무 시간의 50%를 짝을 지어 일한다고 가정하면, 대충 계산했을 때 생산성이 8% 정도 떨어진다. 하지만 짝 프로그래밍으로 코드 리뷰를 대체할 수 있다면, 결과적으로 **생산성 감소는 전혀 없을 가능성이 크다.** 그리고 서로 가르쳐 주며 이루어지는 지식 교환이나, 강도 높은 협업에서 오는 이득도 고려해야 한다. #### 둘이서만? 가끔은 셋이나 넷, 혹은 더 많은 사람이 문제를 함께 해결할 수도 있다. 셋 이상이 하는 짝 프로그래밍을 '몹 프로그래밍<sub>(mob programming)</sub>'이라고도 부른다. #### 관리자 짝 프로그래밍을 한다고 해서 잔소리하는 관리자는 본 적이 없지만, 그런 관리자가 있다면 '내가 전문가고, 관리자가 아닌 내가 나의 일하는 방식을 정한다.'고 전하라. 절대 짝 프로그래밍을 해도 되는지 허락받지 말라. 당신이 전문가다. 당신이 결정하라. ## 애자일해지기 XP의 규칙과 실천 방법을 지키는 것은 쉬워 보이지만, 애자일해지려고 시도했다가 실패하는 조직의 수를 보면 애자일해지기란 매우 매우 어려운 것 같다. 실패의 원인은 아마 많은 조직이 생각하는 애자일이 사실은 애자일이 아니어서일 것이다. ### 애자일의 가치 애자일의 네 가지 가치는 용기, 소통, 피드백, 단순함이다. - 용기 - 합리적인 정도로 위험을 감수하는 것이다. - 어느 정도 공격성을 띠는 것이 소프트웨어 프로젝트를 관리하는 최고의 방법이다. - 소통 - 여러 경로를 통한 직접적이고 빈번한 소통에 가치를 둔다. - 직접 얼굴을 보고, 편안하게 사람과 사람으로서 대화하는 것을 중요하게 여긴다. - 같이 앉아서 자주 소통하는 팀이 기적을 일구어 낼 수 있다. - 피드백 - 사실상 모든 애자일 규칙은 중요한 결정을 내리는 사람에게 빠른 피드백을 제공하는 데 초점이 맞춰져 있다. - 애자일팀은 피드백을 즐긴다. - 피드백은 팀이 효과적으로 일하도록 만들며, 프로젝트가 유용한 결과물을 내도록 만든다. - 단순함 - 단순함은 직접성이다. - 문제를 확인하고도 조용히 다른 사람에게 넘어가게 놔두었다면 당신은 간접적인 행동을 한 것이다. 결과가 끔찍할 것을 알면서도 관리자가 고객의 요구에 응할 때, 당신은 간접적인 접근을 한 것이다. - 팀에서는 이런 간접성이 훨씬 적게 필요하다. ### 신기한 동물쇼 **세상에 나와 있는 수많은 애자일 방법론은 무시하라.** XP로 시작하든, 스크롬으로 시작하든 어떤 방법론을 택하든 상관없이, 결국에는 프로세스를 필요에 맞게 고치고 다듬게 될 것이고 결국에는 같은 곳에 도착할 것이다. 가장 중요한 조언은 전체 생애 주기에 걸쳐 애자일 방법론을 도입하는 것이다. 특히 **기술 실천 방법은 꼭 지켜야 한다.** 팀 전체의 동의를 구하고 시작하라. ### 전환 비애자일에서 애자일로의 전환 장벽은 중간 관리층이다. 이들은 위험을 감수하지 않고, 직접성을 피하며, 최소한의 소통으로 명령 체계를 따르고, 집행하기 위하여 채용된다. 이것이 조직의 딜레마다. 조직의 맨 위층과 맨 아래층은 애자일 사고 방식을 높이 사지만, 중간층은 반대한다. ### 코치하기 애자일팀에는 가끔 코치가 필요하다. 코치와 트레이너는 다르다. - 애자일 트레이너 - 애자일팀이 어떻게 행동해야 하는지 가르친다. 트레이너는 보통 회사 밖에서 고용하거나 회사 내 다른 팀에서 초빙한다. - 트레이너의 목표는 애자일 가치를 심어주고, 애자일 규칙을 가르치는 것이다. - 트레이너의 활동 기간은 짧아야 한다. - 열 명 남짓의 개발자로 구성된 팀이라면 교육 기간이 1~2주를 넘어서는 안 된다. - 더 배울 필요가 있는 것은 애자일 트레이너가 무엇을 말하고 보여 주었나에 관계없이 모두 스스로 배워나가야 한다. - 애자일 코치 - 대개 애자일 코치는 트레이너가 아니다. 애자일 코치는 팀 구성원이면서, 팀 내에서 프로세스를 지키는 역할을 한다. - 개발의 열기가 달아오르다 보면 개발자가 프로세스를 건너뛰고 싶은 유혹에 빠질 수 있다. **이것을 발견하고, 팀원들을 지적하는 것이 코치의 임무**다. - 코치는 언제나 팀원들이 스스로 한 약속과 지키기로 동의한 가치를 일깨우며, 팀의 양심 역할을 한다. - 이 역할은 보통 필요에 따라 그때그때 상황에 맞게 팀원끼리 돌아가며 맡는다. - 오랫동안 함께 일한 성숙한 팀은 코치가 필요 없다. - 코치는 관리자가 아니다. - 코치의 역할은 절대적으로 팀 내에 국한되어야 한다. 관리자도 고객도 누가 코치인지, 심지어 코치가 있는지도 몰라야 한다. #### 스크럼 마스터 스크럼에서는 코치를 스크럼 마스터라고 부른다. 안타깝게도 이 용어가 등장하면서 코치의 역할과 프로젝트 관리자의 역할이 합쳐지는 결과를 낳고 말았다. 요즘에는 스크럼 마스터가 코치 역할을 하는 게 아니라 사실상 그냥 프로젝트 관리자인 경우를 너무 많이 본다. 프로젝트 관리자가 늘 해왔던 일을 하는데도 불구하고, 스크럼 마스터라는 이름과 인증이 그들에게 애자일팀에 대한 영향력을 과도하게 부여하는 것 같다. ### 대규모 애자일 애자일은 4~12명 사이의 소프트웨어 개발자로 구성된 작은 팀을 운영하는 수단으로 알려졌다. 이 숫자는 딱 정해진 게 아니었지만, 수천 명의 개발자가 소속된 거대한 팀에는 적절하지 않다는 것은 모두가 이해하고 있었다. 그럼에도 불구하고, 큰 팀에 대규모 애자일을 적용하는 것에 대한 의문이 따라왔다. 스크럼의 창시자들은 '스크럼의 스크럼'이라는 기법을 제안하기도 했지만, 나는 이 접근 방법을 시도해 보지 않았고, 책도 읽어 보지 않았으므로 이 주제에 대하여 이야기하는 것은 무책임하다. 하지만 나는 애자일은 절대 큰 팀을 위해 만들어진 것이 아니라는 확고한 생각을 갖고 있다. **애자일은 작은 소프트웨어팀을 운영할 때 적용하는 특별한 기법**이다. 소프트웨어 개발과 비슷한 일은 거의 없다. ### 애자일 도구 현명한 목수라면 복잡한 도구를 도입하기 전에 간단한 도구부터 완전히 익히기 마련이다. 먼저 간단한 도구의 한계를 파악해야 언제 더 강력한 도구가 필요한지 알 수 있다. #### 소프트웨어 도구 소프트웨어 개발자는 반드시 몇 가지 핵심 도구에 능숙해져야 한다. - 최소 한 가지의 프로그래밍 언어, 대부분의 경우 여러 언어 - 통합 개발 환경이나 프로그래밍용 편집기(vim, Emacs 등) - 다양한 데이터 형식(JSON, XML, YAML 등)과 HTML 등의 마크업 언어 - 운영 체제의 명령 줄 및 스크립트 기반 대화형 인터페이스 - 소스 코드 저장소 도구(Git) - 지속적 통합/빌드 도구(Jenkins, TeamCity, GoCD 등) - 배포/서버 관리 도구(Docker, Kubernetes, Ansible, Chef, Puppet 등) - 의사소통 도구(이메일, Slack, 국어) - 테스트 도구(단위 테스트 프레임워크, Cucumber, Selenium등) 요즘 세상에는 여기서 하나만 빠져도 무언가 만드는 것이 불가능하다. 그런 의미에서 이 도구들은 '간단한 도구'에 해당한다고 볼 수 있다. 대부분의 도구는 효과적으로 사용하려면 힘들게 기술을 익혀야 한다. 하지만 그 와중에도 시장의 도구들은 계속 바뀐다. 요령 있는 개발자라면 도구를 익히는 데 최소한의 노력으로 최대한의 효과를 볼 수 있는 방법을 찾기 마련이다. 어떻게 해야 투자 대비 효용을 극대화할 수 있을까? #### 무엇이 효과적인 도구를 만드는가? 훌륭한 도구는 다음과 같은 특징이 있다. (예를 들어 Git) - 사람들이 원하는 일을 성취하도록 돕는다. - 금방 '충분히 잘' 배울 수 있다. - 사용법이 명료해서 도구에 신경 쓰지 않고 쓸 수 있게 된다. - 주어진 요구 사항에 쉽게 적응한다. 원래 의도하지 않은 의도로 확장적응도 한다. - 가격이 적절하다. #### 애자일 생애 주기 관리<sub>(Agile Lifecycle Management, ALM)</sub> 시스템을 살 돈이 있을 때 ALM은 애자일팀의 데이터를 모으고, 백로그 같은 긴 기능 목록을 관리하고, 복잡한 그래프를 만들어 주고, 연관된 팀들을 모아서 보여 주고, 몇 가지 숫자 계산까지 해 준다. 이런 일을 도와주는 자동화된 시스템이 있으면 편리할 것 같아 보이지만, 온갖 기능과 상업적인 성공에도 불구하고 ALM 도구는 절대 훌륭한 도구가 아니다. ALM 도구의 실패는 반면교사로 삼을 만하다. - ALM은 복잡한 경우가 많다. 교육을 받은 후에도, 분명 단순한 일인데 어떻게 하는지 몰라서 검색을 해 봐야만 하는 경우가 많다. - 회의를 하다 보면 도구를 조작하는 사람이 헤메는 것을 다른 팀원들이 구경하는 상황이 늘 벌어진다. ALM 도구는 항상 긴장하고 사용해야 한다. - ALM 도구는 필요에 맞게 바꾸기 어려울 때가 많다. - ALM 도구 사용 비용은 매우 비싸다. - ALM 도구가 실제로 팀이 일하는 방식에 맞는 경우는 별로 없다. 사실 ALM도구의 기본 설정이 애자일 방법론과 맞지 않는 경우도 많다. 어떤 ALM 도구는 면박판<sub>(pillory board)</sub>을 제공하기도 하는데, 개개인의 업무량이나, 가동률, 진도, 남은 업무 현황 등을 모아서 보여 주는 기능이다. 면박판은 진정한 애자일에서 하듯이 완성에 이르기까지의 업무 흐름을 잘 보여주고 공동의 책임을 강조하기보다는, 개발자를 더 열심히 오래 일하라고 압박하는 무기로 사용된다. 언젠가 ALM이 위대한 도구가 되지 말란 법은 없다. 만약 카드 더미를 관리하는 데 소프트웨어를 꼭 사용해야 한다면, Trello같은 범용 도구를 사용하라. 간단하고, 빠르고, 싸고, 확장이 쉽고, 사용자를 초조하게 만들지 않는다. ## 장인 정신 ### 소프트웨어 장인 정신 전문 소프트웨어 개발의 기준을 높이고, 애자일이 처음에 품었던 목표를 재정립하기 위하여, 일군의 개발자가 2008년 11월 시카고에 모여서 '소프트웨어 장인 정신<sub>(Software Craftsmanship)</sub>'이라는 새로운 운동을 만들었다. 그리고 애자일 선언을 바탕으로 새로운 선언을 만들어 발표했다. > 미래의 소프트웨어 장신으로서 우리는 전문 소프트웨어 개발의 기준을 높이려 한다. 이를 위하여 높은 수준의 개발을 실천하고, 다른 사람이 기술을 배우는 것을 도울 것이다. 이 작업을 통하여 우리가 동의한 가치는 다음과 같다. > - 작동하는 소프트웨어뿐 아니라, **잘 만들어진 소프트웨어** - 변화에 대응할 뿐 아니라, **꾸준히 가치를 더하기** - 개인과 상호작용뿐 아니라, **전문가 커뮤니티** - 고객과의 협력뿐 아니라, **생산적인 동반 관계** > 왼쪽에 있는 것을 추구하다 보면, 오른쪽에 있는 것이 필요해진다는 것이다. > ### 소프트웨어 장신 정신도 실천 방법이 있나요? 소프트웨어 장인 정신은 실천 방법이 없다. 대신 더 나은 실천 방법과 일하는 방법을 끊임없이 찾아보라고 권한다. ### 실천 방법이 아니라 가치에 집중하라 **사람들은 그 가치를 깨닫기 전에는 일하는 방식을 바꾸지 않는다.** 팀원들에게 TDD를 들이밀기 전에 먼저 전체 시스템을 테스트하기 위해 들이는 시간을 줄이는 일에 어떤 가치가 있는지 의견을 모아 보면 어떨까? 투자 대비 효율이 괜찮을까? 우리 삶을 더 낫게 만들어 줄까? 믿을 만한 소프트웨어를 더 빠르게 릴리스할 수 있게 될까? 만약 여기에 대한 답이 "예"라는 것에 동의한다면 이 가치를 달성하기 위한 실천 방법에 어떤 것이 있을지 이야기를 해 볼 수 있을 것이다. 자연스럽게 TDD를 선택할 것이다. TDD를 탐탁지 않아 하는 사람이 있다면 어떤 실천 방법을 선호하는지 물어보아야 한다. 제안하는 실천 방법은 동의한 목표에 있어 TDD 이상의 가치를 가져다주어야 한다. **실천 방법을 논의할 때는 반드시 달성할 목표에 먼저 공감해야 한다. 다만 더 나은 대안 제시 없이 실천 방법을 거부하는 것은 용납할 수 없다.** ### 장인 정신이 개인에게 끼치는 영향 장인 정신은 개인에게 지대한 영향을 준다. 장인 정신은 소프트웨어 개발자를 전문가로 만든다. 전문가란 단순히 직업이 있는 사람을 가리키는 말이 아니다. 전문가라면 출근이 지겨운 일이 되어서는 안 된다. 일은 우리 인간에게 기쁨을 주고 성취감을 준다. 전문가는 일에서 삶의 의미를 찾는다. ## 결론 애자일은 그동안 있었던 소프트웨어 프로세스와 방법에 관한 많은 혁신 중에서 가장 중요하고 오래 지속되고 있는 혁신이다. 켄트 벡의 `<Extreme Programming Explained>`에 나오는 가치와 원칙, 실천 방법이 기본이다. 마틴 파울러의 `<Refactoring>`에 나오는 동기와 기법, 실천 방법이 기본이다. 이 기본은 오래되고, 검증된, 진짜다. 새로운 뜨내기가 가장자리에 엉겨붙든 말든, 이 기본은 변함이 없다. 여전히 유효하고, 여전히 애자일 소프트웨어 개발의 핵심이다. 이 책을 최대한 이용하자. 영향을 끼칠 수 있는 사람들에게 권하자. 성공적인 소프트웨어 개발을 가능하게 만들자. 조직의 목표를 이룰 수 있게 만들자. 상황을 더 좋게 만드는 프로세스를 만들자.