레거시 코드를 어떻게든 테스트하기

June 10, 2025 김영현 조회수 1,627

테스트하기 어려운 레거시 코드를 어떻게든 테스트하는 방법을 설명합니다.

들어가며

안녕하세요. VD 사업부에서 TV 소프트웨어를 개발하는 평범한 개발자 김영현입니다. 지난번에 “레거시 코드와 놀기”라는 글에서 레거시 코드를 개선하는 방법이 아주 쉬운 것처럼 이야기했는데요. 우선 반성합니다. 레거시 코드를 개선하기란 쉽지 않습니다. 개선을 위해서는 테스트 코드가 필요하고 테스트 코드를 개발하려면 레거시 코드를 테스트하기 쉽게 고쳐야 하는 물고 물리는 일들이 아주 많이 발생합니다. 테스트를 논하지 않고 레거시 코드를 개선할 수는 없습니다. 


그나마 쉬운 방법은 레거시 코드의 수정은 최소화하고 외부에서 테스트를 진행하는 것입니다. 블랙박스 테스트를 하면 좋지만 레거시 코드가 블랙박스 테스트를 수행하기 쉬운 형태로 개발됐을 리는 없으니까요. 이 글에서는 레거시 코드를 어떻게든 테스트하는 방법에 대해 이야기하려고 합니다. 

기존의 틀 깨트리기



그림 1. 콜럼버스의 달걀


제가 하려는 이야기는 “아! 나도 아는데”라고 할 법한 내용입니다. 읽고 나면 더 쉽고 읽지 않아도 생각해 낼 수 있을 테죠. 하지만 당연하게 받아들여지는 기존 틀을 깨트리는 것은 깨트린 후엔 쉽게 느껴집니다. 제 경우엔 다음과 같은 작업이 당연하게 받아들여졌고 다들 그렇게 했습니다.


  • 레거시 코드와 동일한 개발 언어를 사용하여 테스트 코드 개발
  • TV에서 테스트 코드 실행

저는 C++를 사용해서 TV 소프트웨어를 개발합니다. 테스트 코드를 개발하는 경우 다음과 같은 단계가 필수적입니다. 당연히 필요한 단계지만 이런 비효율이 없습니다.


  1. 테스트 코드 컴파일 및 실행 파일 생성
  2. TV에 설치
  3. TV에서 테스트 실행

테스트 코드를 한 줄만 고쳐도 1번과 2번 단계가 필요합니다. 코드를 고치는 시간보다 더 많은 시간이 1번과 2번 단계에서 소모됩니다. 그런데 이 틀을 벗어나자 모든 게 쉬워졌습니다.“도구는 일을 거들 뿐 목적이 될 수 없다”는 것이 제 지론입니다. TV 외부에서 Python으로 테스트 코드를 개발해 보았습니다. 1번과 2번 단계가 사라지고 테스트 코드 개발 효율이 전과 다르게 올라갔습니다.

동작하는 테스트 코드

Python으로 테스트 코드를 만들려면 필요한 테스트를 위해 TV를 제어하는 방법이 있어야 합니다. 즉, 테스트 대상이 되는 레거시 코드에 입력을 전달하고 출력을 확인할 수 있어야 합니다. “어떻게든 테스트하기”라는 표현이 이때 필요합니다. 필요한 테스트를 구현하기 위해 TV에 탑재된 모든 것을 사용해야 합니다.  TV 기능 중 하나인 HDMI 기기 자동 인식 기능을 테스트하는 코드를 만들어 보겠습니다. 기기 자동 인식 기능의 흐름은 다음과 같습니다.


(1) HDMI 포트에 Genie TV 셋톱박스 기기를 연결하면 기기 인식 앱이 실행되고 자동 인식이 진행됩니다.

 


그림 2. HDMI 기기 인식 진행 화면


(2) 기기 인식이 완료되면 인식된 HDMI 기기 이름과 대표 아이콘이 표시됩니다.

 


그림 3. HDMI 기기 자동 인식 완료


레거시 코드 변경 없이 해당 기능을 테스트하려면 기존 흐름을 가급적 그대로 재현해야 합니다. 필요한 단계는 다음과 같습니다.

  1. HDMI 케이블 탈착(물리적으로 탈착되어야 기기 인식 앱이 실행됨)
  2. 기기 인식 앱 실행
  3. 기기 인식 진행 및 완료

테스트 코드를 통해 물리적으로 HDMI 케이블을 탈착할 수 없으므로 HDMI 기기를 미리 TV에 연결한 상태로 테스트를 진행해야 합니다. 또한 HDMI 케이블을 탈착한 것과 같은 효과를 낼 수 있는 코드를 만들고, 기기 인식 앱이 기기 인식을 완료하면 미리 연결된 HDMI 기기와 인식 정보가 일치하는지 확인한 후 테스트를 마무리해야 합니다. 


아래 테스트 코드는 방금 기술한 흐름을 구현합니다.

 


그림 4. HDMI 기기 자동 인식 테스트 코드


각 단계를 살펴보면 다음과 같습니다.


1) TV의 HDMI1 포트에 연결된 기기의 이름에 “Genie” 포함 여부 확인

TV의 HDMI1 포트에 연결된 기기의 이름을 get_hdmi_device_name 함수로 가져옵니다. 그리고 기기의 이름이 “Genie”를 포함하는지 확인하는 과정을 통해 HDMI1에 Genie TV가 연결된 테스트의 선조건(Pre-condition)을 확인합니다.

 



Python을 사용하는 경우 필요한 C API가 구현된 Shared Library를 통해 C API를 아래와 같이 호출하는 코드를 작성할 수 있습니다. 그리고 Tizen SDB(Samsung Device Bridge)를 사용해 Python 코드를 TV 상에서 실행해 특정 HDMI 포트에 연결된 기기의 이름을 반환할 수 있습니다.

 



2) TV의 HDMI1 케이블 탈부착 

물리적으로 HDMI 케이블을 탈부착하는 방법이 있습니다. API는 없지만 TV 상에서 특정 명령어를 다음과 같이 실행하면 됩니다. 0은 탈착을, 1은 부착을 의미합니다.

 


HDMI1 케이블을 탈부착하면 기기 자동 인식 앱이 실행되는데 해당 앱이 실행됐는지 여부를 확인하는 코드는 다음과 같습니다. 

 


3) 기기 인식 앱이 Genie TV 셋톱박스를 인식했는지 확인

기기 인식 앱이 실행된 후 다음 단계는 인식 앱을 통해 기기가 정확하게 인식됐는지 확인하는 것입니다. 기기 인식 앱은 인식이 완료되면 TV 상에 해당 정보를 기록합니다. 앞서 언급한 정보를 바탕으로 기기 인식 완료를 확인하는 코드는 다음과 같습니다.

 


기기 인식이 정상적으로 완료됐다면 기기 정보에 “Genie”라는 이름이 포함되고 테스트가 정상적으로 완료됩니다.




 

잘 동작합니다. 다만 코드의 의미가 충분히 드러나지 않는 부분이 있습니다. 테스트를 위해 잘 정제된 API가 있었으면 하는 아쉬움이 있지만 아직 그런 API는 신기루에 불과한 것 같습니다. 제 주위엔 저를 포함해서 테스트 코드를 작성하는 개발자보다 그렇지 않은 개발자가 더 많기 때문이죠. 우선은 테스트 코드를 만들고 만든 테스트 코드에서 필요한 API를 추출하는 과정을 거치는 것이 마땅해 보입니다.


그럼 코드에 주석을 추가할까요? 없는 것보다는 낫겠지만 주석은 그다지 좋은 방법은 아닙니다. 가장 좋은 방법은 테스트 코드의 각 단계를 함수로 분리하는 것입니다. 하지만 그걸로 마무리하기엔 살짝 아쉬운 마음이 듭니다. 다음 장에서는 함수로 분리하는 것에 그치지 않고 지금의 “동작하는 테스트 코드”를 누구나 이해할 수 있는 테스트 코드로 바꿔 보겠습니다.

누구나 이해할 수 있는 테스트 코드

개발에서 가장 어려운 부분이 이름을 짓는 것입니다. 제가 사용하는 자연어로 코드를 설명할 수 있는 방법이 있다면 참 좋을 텐데 말입니다. 그래서 방법을 찾아보았고 결국 찾았습니다. 사실은 10년도 더 전에 찾았지만 이제서야 사용해 봅니다. 뜸 들이면 재미가 반감되는데요. “동작하는 테스트 코드”에서 살짝 개선된 테스트 코드입니다.


 

그림 5. 기기 자동 인식 테스트(auto_detection.feature)


Python 코드를 바로 보여드리겠습니다. 

 


그림 6. 기기 자동 인식 스텝 코드(auto_detection_steps.py)


관찰력이 좋으신 분들에겐 설명이 필요 없을 수도 있습니다. 위의 Python 코드를 보면 @given, @when, @then과 같은 부분이 있고 해당 부분에 포함된 자연어 문장들은 그림 5의 기기 자동 인식 테스트 코드에 기술된 것과 동일합니다.  테스트 코드를 실행하면 아래와 같은 스텝으로 동작합니다. (실행 화면에 표시되는 자연어 테스트 코드와 스텝 코드의 이름이 앞서 공유한 코드와 살짝 다르지만 이해하는 데 무리가 없으리라 생각됩니다.) 


(1)  Given TV의 HDMI1 포트에 KT STB 연결됨