개발자의 애질리티

2021. 10. 14

이 글은 토스페이먼츠에 입사하신, 혹은 입사를 고려 중인 개발자분들을 위해 작성된 글입니다.

애자일하게 일하기

애자일하게 일한다는 것은 어떠한 의미일까요? 한 시간을 일하면 한 시간 만큼의 가치를 만들어 내는 방식이 아닐까 합니다. 예를 들어, 동작하는 함수를 구현하거나 난해한 개념을 이해하는 식으로요. 

Big up-front 설계

과거에는 프로젝트 진행 초기부터 분석과 설계에 많은 시간을 투자했습니다. 전체 프로젝트의 ⅓ 이상이 분석과 설계일 정도로요. 문제는 프로젝트 기간의 ½ 시점에 요구사항이 크게 변한다면 결과물 하나 없이 다시 새로 시작해야 한다는 점이었습니다. 세상의 변화속도가 엄청나게 빨라진 지금, 초기 설계 비용이 큰 big up-front 설계가 항상 잘 들어맞지 않는다는 사실을 이제는 대부분의 사람이 알게 되었습니다.

애자일 개발 방법론

애자일 개발 방법론에서는 애초에 크게 설계하지 않습니다. 간단한 사용 시나리오를 작성하고 그것의 구현을 목표로 하는 짧은 주기를 가집니다. 거대한 아키텍처를 설계하지 않고 이번 주기(이터레이션(Iteration) 혹은 스프린트(Sprint))에서 달성할 수 있는 만큼의 설계를 추구합니다. (앞으로는 주기가 아닌 스프린트라고 표현하겠습니다.)

예를 들어 카드 승인이 100가지의 하위 기능으로 구분할 수 있다면, 이번 스프린트의 목표를 그중에 3가지로 결정할 수 있습니다. 나머지 기능을 함께 확인하고 싶으면 어떻게 하냐구요? 애초에 3가지 기능 외에는 개발하지 않는다는 목표로 일을 진행하기 때문에 스프린트 목표 달성 여부를 확인할 때에도 오직 이 3가지 기능만 확인합니다. 이번 스프린트를 성공적으로 달성했다면 팀은 최소한 3개의 작은 기능을 획득할 수 있게 됩니다. 

개발자들은 요구사항 전체가 아닌 이번 스프린트에 필요한 요구사항에 더 집중할 수 있게 되고, 만약 스프린트가 성공적으로 진행되었다면 3개의 기능을 제공하는 소프트웨어를 가지게 됩니다. 팀은 점진적으로 비즈니스에 대한 학습을 진행하면서 작지만 동작하는 일부 기능을 확실히 정복해 갈 수 있게 되는 것이죠. 이런 방식으로 팀은 매 스프린트 목표에 맞추어 성장하고, 그에 맞추어 제품도 계속 성장해 나가게 됩니다. 나아가 다음 스프린트에 전혀 다른 기능을 개발하더라도 충분히 다시 쓸 수 있는 동작하는 코드를 확보하게 됩니다. 이러한 점에서 애자일 개발 방법론은 투자한 만큼의 가치를 만드는 방식이라고 볼 수 있습니다.

그림: 애자일 프로젝트에서의 기능과 시간의 관계
그림: big up-front 설계가 적용된 프로젝트에서의 기능과 시간의 관계

애자일 프로젝트는 시간에 비례하여 기능의 수가 증가하고, 비-애자일 프로젝트에서는 상대적으로 후반부에 기능이 집중적으로 증가함을 표현해 봤습니다.

품질과 생산성

어떤 코드를 보고 최고의 품질인지 판단하는 것은 매우 어려운 일입니다. 피카소조차도 더 탁월한 화가를 만난다면 자신의 작품에 몇 점을 매겨야 할지 애매할 수 있습니다.

평범한 화가가 심혈을 기울인다고 하여 피카소 만큼 훌륭한 그림을 그릴 확률 역시 극히 낮을 것입니다. 이러한 논리는 개발자에게도 그대로 적용 가능합니다. 개인의 품질 역량을 10이라고 가정했을 때 평균적으로 8정도의 품질을 보여줄 확률이 높으며, 상당한 노력을 투입해야 10의 품질을 만들어 낸다고 생각할 수 있습니다. 따라서 11의 품질을 추구하게 된다면 생산성이 극적으로 저하될 수 있습니다. 

기존의 코드를 개선하여 품질을 높이고자 한다면 어느 정도의 품질 개선을 목표로 해야 할까요? 만약 전체 코드를 복제한다면 품질 개선율 0%, 공정률 100%를 즉시 달성할 수 있습니다. 만약 품질 개선율 1%, 생산 공정률 100%를 달성하고자 한다면 전체 코드의 1%를 개선하는 만큼의 시간을 더 사용해야 합니다.

품질을 더 개선하고 싶은데 스스로 해내기가 쉽지 않다고 판단된다면 다양한 주변 환경(동료, 메이트, 멘토, 팀, 단위 테스트 등)을 활용하여 성장 환경을 만들어 가는 것이 중요한 것 같습니다. 특히 토스페이먼츠에는 기술 논의를 즐기는 기술 덕후들이 꽤 많습니다. 내 주변이 나 때문에 활기 넘치게 만들어 보세요.

핵심은 코드 리딩의 생산성

대부분의 회사에는 다른 개발자들이 생산한 코드가 항상 산적해 있습니다. 어떤 기능을 개선하고 싶다면 다른 사람이 작성한 코드를 읽어야 하죠. 그래서 보통은 코드를 읽는 시간이 작성하는 시간보다 훨씬 깁니다. 따라서 읽기 좋은 코드를 만드는 것은 개발자의 삶에 굉장히 중요합니다.

기존 코드를 읽는 것에 과도한 시간을 써야 한다면 기능 개선을 위한 준비 작업에만 상당한 시간을 소비하게 되어 생산성이 떨어지게 됩니다.읽기 좋은 코드를 만들어서 코드 리딩의 생산성을 향상시키는 것이 중요한 이유입니다.

가능하다면 코드를 읽을 때 리팩토링 기술(Rename Method, Extract Method 등)을 활용하는 것이 좋습니다. 이러한 리팩토링을 Michael Feathers는 ‘탐색적 리팩토링(Exploratory Refactoring)’ 이라고 부르며, 이 과정에서 수정된 코드가 최종적으로 코드 저장소에 반영되지 않는다고 하더라도 충분히 가치있는 일입니다. 제가 느끼기에 Exploratory Refactoring은 정말로 효과적인 학습 프로세스이기 때문입니다.Exploratory Refactoring을 수행하게 되면 코드를 읽은 즉시 나의 해설을 표시하기 때문에 굉장히 적극적으로 코드 리딩이 되며, 코드 리딩의 주도권을 자연스럽게 리더(reader)가 가져가게 됩니다. 책을 읽었는데도 이해가 안되서 다시 읽어야 하는 것과 같은 수동적인 상태에서 벗어날 수 있게 됩니다. 따라서 Exploratory Refactoring은 탁월한 개발자가 탁월해지게 만들어주는 진정한 OP 기술입니다.

리팩토링의 가치

개발자들이 리팩토링의 욕구를 강하게 느낄 때는 보통 유지보수 비용이 과도한 경우입니다. 유지보수 비용이 높은 이유는 기능을 수정해야 하는데 어느 코드를 수정해야 할지, 몇 줄의 코드를 바꿔야 할지, 변경을 했다면 올바르게 변경했는지 등을 파악하기 어렵기 때문입니다.

따라서 요구사항에 대응하는 코드가 어디인지 명확하게 찾아낼 수 있고, 수정한 부분의 동작이 정확한지 파악하기 쉽다면 유지보수 비용을 낮출 수 있습니다. 리팩토링의 목적은 이러한 부분을 달성하는 데 있습니다.

따라서 리팩토링이 잘 수행되었다면 새로운 개발자(혹은 미래의 자신)가 기능 변경 요청을 받았을 때 아래의 3가지를 쉽게 해낼 수 있습니다.

  1. 코드 위치 파악
  2. 코드 수정 
  3. 기능 테스트

리팩토링으로 잘 설계된 코드는 이러한 핵심 과업을 쉽게 이행하는데 큰 도움이 됩니다.

결론

애자일 기법은 요구사항이라는 큰 덩어리를 작지만 동작하는 작은 기능으로 나누고 매 스프린트 마다 목표한 바를 착실히 정복해가는 방식이라고 할 수 있습니다.

이 때 안전하게 기능을 수정 혹은 추가하기 위해서는 3개의 핵심 과업을 잘 수행해야 하는데요,

  1. 코드로부터 도메인 파악하기(a.k.a. 코드 고고학)
  2. 수정에 필요한 코드 파악하기
  3. 수정된 코드 쉽게 검증하기

토스페이먼츠에서는 애자일하게 일하는 방법을 동료들과 함께 일 하면서 쉽게 터득할 수 있는 좋은 문화와 프로세스를 만들기 위해 서툰 실험을 계속하고 있습니다.

강병훈

Head of Technology

토스페이먼츠에서 Head of Technology 역할을 수행하고 있습니다. 성장하는 문화라는 비옥한 토지를 만드는데 관심이 많습니다.

토스팀이 만드는 수많은 혁신의 순간들

당신과 함께 만들고 싶습니다.
지금, 토스팀에 합류하세요.
채용 중인 공고 보기