일레클 Android TDD 도입기 (2/3)

일레클 Android TDD 도입기 (2/3)

최정인
elecle
8 min readMar 3, 2022

--

안녕하세요! 일레클 서비스를 운영하는 나인투원 Mobile 팀에서 안드로이드 개발을 하고 있는 최정인입니다.

일레클 Android TDD 도입기의 두 번째 포스팅입니다. 본 포스팅에서는 Mobile팀 구성원들이 다함께 테스트 코드 작성을 연습하기 위해 추진했던 리팩토링 세션의 진행 방식을 소개합니다.

일레클 Android TDD 도입기 (1/3) → TDD를 도입하기까지의 배경, 본격적으로 도입하기까지의 기나긴 과정

일레클 Android TDD 도입기 (2/3) → 리팩토링 세션을 통한 테스트 코드 작성 연습, 컨벤션 맞추기

일레클 Android TDD 도입기 (3/3) → 본격적으로 테스트 주도 개발 방식을 적용해서 스프린트를 진행한 과정

리팩토링, 근데 이제 테스트 코드를 곁들인

지속적인 리서치와 페어 프로그래밍 세션들을 통해, 일레클 Mobile 팀원들은 서서히 테스트 코드에 익숙해졌고 점차 팀 내 consensus가 모아졌습니다. 하지만 바로 테스트 주도 개발 방식(Test Driven Development, 이하 TDD)을 적용하기는 무리일 것 같아서 적절한 마일스톤이 뭐가 있을지 고민했습니다. 레거시 코드를 리팩토링하는 과정에서 테스트 코드를 작성해보며, 본격 TDD 전에 맛보기 에디션을 체험해보면 좋겠다고 생각했습니다.

step 1) 리팩토링 대상 선정하기

이전 글에서 언급했듯이, 성급한 리팩토링은 오히려 더 큰 문제를 일으킬 수 있습니다. 리팩토링을 진행할 스코프가 명확해야 하고, 해당 스코프 내에서 발생하는 모든 경우의 수가 잘 처리되는지 확인해야 합니다. 그렇기 때문에 저희는 리팩토링 대상을 정하는 단계부터 신경을 썼습니다.

리팩토링 대상을 선정하는 과정에서 작성했던 표

쉽게 말해서 “많고 많은 패키지들 중에서 어디부터 뜯어볼 것인지” 그 우선순위를 판단해보는 과정입니다. 위와 같이 표를 만들어서 정렬해보고, 나름의 기준을 설정해서 우선순위를 판단해봤습니다. 단, 여기서 “우선순위”는 기능 상 중요도와 다른 의미를 갖습니다.

중요도가 매우 높은 기능이거나, 코너 케이스가 많을 경우 리팩토링 이후에 QA를 위해 많은 리소스를 들여야할 것입니다. 일레클 서비스를 예시로 든다면, 자전거를 대여하고 반납하는 로직은 유저 경험에 매우 큰 영향을 미치기 때문에 단시간 내에 리팩토링을 하기 어렵습니다. 더구나 저희 팀원 모두 android testing에 대한 경험이 충분하지 않았기 때문에 테스팅 자체의 기술적 허들도 존재했습니다.

그렇기 때문에 리팩토링 규모와 테스팅 복잡도를 고려해서 “적당히 해볼만한 것”부터 시도하는 것이 좋겠다고 판단했습니다. 이를 위해 아래와 같은 기준을 적용해보았습니다.

해당 패키지가 MVVM 구조를 사용하고 있는가?
AS-IS의 코드 규모/복잡도/의존성이 얼마나 큰지?
난이도가 높은/아직 해보지 않은 테스팅 요소가 존재하는가?
리팩토링을 하게 된다면 예상되는 QA 리소스는 얼마나 되는가?

각각에 대해 엄밀히 점수를 매기며 판단하지는 않았습니다. 리팩토링 세션을 추진하는 과정에서 ‘ㅇㅇ부터 해보는 것이 좋을 것 같다’, ‘ㅁㅁ를 그 다음으로 하는 것이 좋겠다’ 식의 마일스톤을 제시할 때, 설득의 근거를 마련하기 위해 기준들을 세워봤을 뿐입니다. 🤗

step 2) 줄글로 테스트 시나리오 작성하기

테스트 시나리오를 줄글로 작성해보면서 모든 경우의 수를 나열하고, AS-IS의 문제/개선점들을 정리해보는 단계입니다.

“테스트 시나리오”라는 것은 기획서 상 user requirement나 마찬가지입니다. 리팩토링 대상의 user requirement가 존재한다면 해당 기획서를 참고하는 것이 가장 정확합니다. 하지만 기획서를 참고하기 어려운 상황이거나, 단순한 패키지일 경우 직접 줄글로 테스팅 시나리오를 작성해보는 것도 좋습니다.

줄글로 작성한 테스트 시나리오 예시

한 팀원이 주도적으로 테스트 시나리오 초안을 작성해보고, 팀원들에게 공유하면서 같이 다듬는 식의 과정을 반복하는 것을 추천드립니다! 실제로 해보면 정말 번거로운 과정이 맞습니다. 😅 하지만 반복되는 형태가 보이고 관계성들이 자연스럽게 파악되면서, 곧 이어 소개될 ‘step 3 이상적인 구조 설계하기’에도 도움이 됩니다.

step 3) 이상적인 구조 설계하기

각종 design pattern, SOLID principle, MVC/MVP/MVVM architectural design pattern 등, “글로 읽으면 무슨 말인지 안 와닿던” 그것들을 실무에 적용해볼 기회입니다.

설정 화면, 가장 만만해 보였던 우리의 첫 타겟

추상적인만큼 막막하기도 한 단계입니다. 서비스에서 지향하는 구조에 맞게 각 요소들을 정리하고, 기존 코드가 그에 맞지 않는 부분이 있다면 제거하고 추가해나가는 과정이지요. 이렇게 리팩토링을 하는 과정에서 더 많은 시행착오들을 겪다 보면, 구조 설계에 대한 노하우도 더 많이 생기지 않을까 싶습니다. 😙

step 4) 테스트 코드 작성하기

  • 브랜치, 패키지 세팅

팀원들과 함께 브랜치 룰을 명확하게 정하고 작업을 시작하거나, 별도의 패키지를 마련해놓는 것이 좋습니다. 배포 시점에 맞추지 못하게 될 가능성을 고려해야 하기 때문입니다. 저희의 경우 대상 패키지를 통째로 복제해준 뒤, 복제된 패키지 내에서 모든 리팩토링을 진행했습니다. 작업을 다 끝낸 이후 아예 기존 패키지를 날려주고 새 패키지/클래스들의 이름을 변경해주었습니다.

  • 주석의 적절한 활용

Given-When-Then 형식에 맞춰 주석을 먼저 작성해준 뒤, 테스트 코드를 작성하니 보기에도 깔끔하고 구현할 때도 편리했습니다. 함수명만 보고 어떤 테스트 케이스인지 와닿지 않는 복잡한 케이스의 경우, 아예 주석에 한글로 설명을 적어놓는 것도 좋습니다.

  • 커버리지 리포트의 중요성

“내가 테스트 코드를 잘 작성하고 있는건가” 하는 회의감이 들 수 있습니다. 이 때 중요한 기준점을 제시해줄 수 있는 것이 바로 커버리지 리포트입니다. 빠진 브랜치가 있는지, 테스팅을 빼먹은 함수가 있는지 등을 확인할 수 있는 지표로 커버리지를 활용할 수 있습니다. 커버리지 리포트를 확인하지 않고 테스트 코드를 짠다는 것은 마치 채점하지 않고 문제집을 계속 풀어나가는 것과 같습니다!

JaCoCo 커버리지 리포트
아직은 처참한 커버리지라 모자이크 처리했습니다.

일레클 Mobile 팀에서는 JaCoCo 라이브러리를 활용해서 커버리지를 추출하고 있습니다. 또한, github workflow를 활용하여 CI/CD 파이프라인(테스트 실행 → coverage report 추출 → coverage 뱃지 달기 → 빌드 → 슬랙 채널에 apk 파일 업로드)을 구축해놓았습니다.

JaCoCo로 추출한 커버리지 리포트에서는 C0 커버리지와 C1 커버리지를 모두 볼 수 있고, 파일을 클릭할 경우 어떤 라인/브랜치가 커버되지 않았는지 확인할 수 있습니다. 자세한 내용은 공식 문서를 참고하시기 바랍니다.

이 모든 과정들을 겪고 나면..

일레클 Mobile팀은 이 시기에 정말 많은 컨벤션을 정하고, 프로세스를 확립했습니다. 테스트 코드 작성 컨벤션도 점차 구체화 되었고, 코드 리뷰 시스템도 점차 체계를 갖추어 나가게 되었습니다. 팀 별 데일리 스탠드업을 통해 “짧게 자주 공유하자”라는 것을 몸소 실행하고, 다같이 그 효과를 실감했습니다.

21년 11월 말 회고록, 정말 훈훈하네요

일레클 Mobile팀 데일리 스탠드업 미팅에서는 업무 논의용 안건들 외에 서로에게 공유하고 싶은 사항들도 자유롭게 꺼내볼 수 있습니다. 이를테면 저는 테스트 코드를 작성하는 과정에서 알게 된 새로운 정보들을 종종 공유하곤 했는데요, 그럴때마다 동료 분들이 항상 잘 반응해주셔서 감사했습니다. 🙇🏻‍♀️

Mobile팀 데일리 스탠드업 미팅록 일부

혹시나 팀에 TDD를 도입하고 싶지만 뭐부터 어떻게 할지 모르겠어서 막막하시는 분들께 이 시리즈가 도움이 될 수 있다면 좋겠습니다! 이번 포스팅에서는 리팩토링 세션의 진행방식을 step by step으로 소개했습니다. 다음 포스팅에서는 본격적으로 테스트 주도 개발 방식을 적용해서 스프린트를 진행한 과정을 적어보겠습니다. 🥳

시리즈 전체 보기

일레클 Android TDD 도입기 (1/3) → TDD를 도입하기까지의 배경, 본격적으로 도입하기까지의 기나긴 과정

일레클 Android TDD 도입기 (2/3) → 리팩토링 세션을 통한 테스트 코드 작성 연습, 컨벤션 맞추기

일레클 Android TDD 도입기 (3/3) → 본격적으로 테스트 주도 개발 방식을 적용해서 스프린트를 진행한 과정

--

--