라인웍스의 개발 문화 – (1) Code Coverage

2021.09.14

라인웍스의 개발 조직은 코드 안정성을 중요하게 보고 있습니다. 

라인웍스의 제품들의 기능은 주로 대부분 큰 데이터를 다룹니다. 데이터의 크기가 크다보니 기능을 직접 테스트하는데 시간이 많이 걸리고 분석 결과의 정확성에 대한 판단을 직접 하기가 어렵습니다. 이러한 이유 때문에 최대한 개발 단계에서 많은 부분을 테스트하여 해당 부분에 대한 안정성을 보장하고, 추후 다른 기능의 개발로 인해 이전 기능이 영향을 받지 않는지 지속적으로 확인하는 것이 아주 중요합니다.

라인웍스의 개발 조직은 테스트 코드를 작성하는 것을 지향하며 일정 산정시 이를 위한 시간을 항상 고려합니다. 또한, 테스트 코드가 잘 작성되고 있는지, 테스트 되고 있지 않은 부분은 어딘지 파악하기 위해 Code Coverage(코드 커버리지)를 확인하고 일정 수준(글 작성 시점: 80%) 이상 유지하는 것을 목표로 잡고 개발을 진행하고 있습니다.

이번 글에서는 Code Coverage가 무엇인지, 측정하는 방법은 어떤 것이 있고, 라인웍스에서는 어떤 것을 중요하게 생각하는지 공유를 드리려고합니다.

Code Coverage(코드 커버리지)

Code Coverage란 테스트 코드가 실행될 때 얼마나 많은 코드가 실행되었나를 나타내는 지표입니다. 직접 실행해보지 않으면 에러를 확인할 수 없는 python, javascript 등의 인터프리터 언어를 사용하고 있는 상황에서 특히 중요하다고 볼 수 있습니다.

Code Coverage를 측정하는 방법은 기준에 따라 Statement Coverage, Branch Coverage, Condition Coverage, Line Coverage, Function Coverage 등으로 나누어집니다. 이 방법 중, 라인웍스에서는 Statement Coverage와 Branch Coverage를 중요하게 생각하고 이 두 가지 지표를 향상시키는 것을 목표로 잡았습니다.

Statement Coverage(구문 커버리지)

Statement를 기준으로 측정하는 방법입니다. Line(코드 줄)을 기준으로 하는 Line Coverage와 비슷하지만 한 line에 여러 개의 statement가 들어가거나 한 statement가 여러 line으로 나누어져 있는 경우가 있을 수 있어서 수치는 약간 다르게 나옵니다. Statement는 코드의 기본 단위이기 때문에 Statement Coverage도 기본적인 coverage 측정 방법이라고 할 수 있습니다.

Branch Coverage(분기 커버리지)

if 등 특정 조건을 기준으로 실행 분기가 나누어지는 것을 기준으로 측정하는 방법입니다. Decision Coverage(결정 커버리지)라고도 합니다. Statement Coverage만을 기준으로 한다면 실행되는 statement가 적은 분기 조건의 경우는 coverage 수치에 제대로 반영이 되지 않을 수 있습니다. 이를 보완하기 위해 Branch Coverage를 또 하나의 기준으로 설정했습니다.

아래 코드 예시를 보시면 하나의 분기문을 가진 함수가 정의되어 있고, 이 함수에 true 값만 준 상태로 테스트가 실행되고 있습니다.


void someFunction(bool someCondition) {
  if (someCondition) {
    true_statement1;
    true_statement2;
    true_statement3;
    true_statement4;
  } else {
    false_statement1;
  }
}

void testSomeFunction() {
  someFunction(true)
}

조건이 true일 경우엔 4개의 statement가 실행됩니다. 전체 statement가 총 5개(true_statement 4개 + false_statement 1개)이므로 Statement Coverage 80%입니다. 하지만 Branch Coverage의 경우, branch가 총 2개(someCondition이 true인 경우, someCondition이 false 인 경우)이고 이 중 한 경우만 실행이 되었으니 50%입니다.

Statement와 Branch, 두 가지 기준을 선택한 것이 서로의 단점을 보완하며 안정성을 확보하기 위한 최선의 방법이라고 생각했습니다. (테스트 코드 만드는 사람의 피로도도 줄이면서…😅)

Coverage를 낮추는 요인

Code Coverage를 목표로 잡았지만 이 목표가 항상 지켜지지는 않습니다. 이 목표보다 우선 순위가 더 높은 목표는 항상 있고, Coverage를 올리기 위해 작업을 하는 것이 에너지 낭비가 되는 경우도 있습니다. 라인웍스의 업무 특성상 테스트로 쉽게 커버하기가 어려운 일도 있습니다.

더 높은 우선 순위

항상 제품을 완성하는 것이 우선이 됩니다. 특정 기능을 개발을 완료하는 일정이 빡빡하게 잡혀 있고, 그 후에 바로 다음 기능을 개발하기 위한 일정도 잡혀있다면 테스트 코드에 신경을 쓰지 못할 수 있습니다. (많은 경우, 직접 한 번 실행해 보는 것이 테스트 코드를 만드는 것보다 빠르니까요.😅)

임시 기능 구현

임시로 기능을 구현하는 경우가 있습니다. 서비스 관리자의 제품 관리를 위한 기능을 만든다던가, 정식으로 기능에 대한 작업이 시작되기 전에 빠르게 프로토타이핑을 해본다던가 하는 등의 작업이 진행되는 경우가 있을 수 있습니다. 이런 경우, 대부분 추후에 해당 기능이 정식으로 추가되거나, 삭제되기 때문에 테스트 코드를 만드는데 시간을 쓰는 것이 낭비가 될 수 있습니다. 하지만, 잠시동안 프로젝트의 Code Coverage 지표는 하락하게 될 것 입니다.

실행 시간이 긴 코드

라인웍스는 의료 데이터 분석을 주로 합니다. DB가 아주 큰 경우가 많고 이를 정교하게 다룹니다. 이 때문에 (테스트용으로 데이터 크기를 줄인다고 해도) 실행 시간이 길어지는 코드들이 많아집니다. 이러한 코드들을 모두 테스트한다면 개발자의 피로감이 올라갈 것입니다. (테스트 돌릴 때마다 1시간..😅)

위와 같은 어려운 점들이 있습니다. 하지만 Code Coverage를 목표로 설정했기 때문에 이를 달성하기 위하여

  • 테스트 코드 작성을 고려한 일정을 산정하고,
  • 함수를 더 작은 단위로 분리하여 테스트를 수월하게 만들고,
  • 오래 걸리는 테스트를 위한 테스트용 서버를 따로 구축하는 등

이를 극복하기 위한 방법을 항상 생각하고 노력을 할 수 있었습니다.

마치며

라인웍스 개발 그룹의 중요한 목표인 Code Coverage와 목표 달성을 저해하는 요인에 대해 이야기했습니다. 이런 목표를 설정하고 개발을 진행한 결과, 목표였던 80%를 훨씬 뛰어넘는 95%이상의 Coverage를 달성한 프로젝트도 있습니다.

라인웍스의 개발자들은 Coverage를 올리는 것과 더불어 효과적인 테스트를 어떻게 만들어야하는가에 대한 고민도 함께 하고 있습니다. 더 상세한 고민을 알고 싶으시면 이전 글(https://blog.linewalks.com/archives/6848)을 참고하시면 좋겠습니다.

Jungwoo Chae

Engineer

Jungwoo Chae