DS log

내가 테스트를 작성하며 고민한 것들 본문

트러블 슈팅

내가 테스트를 작성하며 고민한 것들

DS log 2026. 4. 6. 21:40
728x90

 

요즘 AI를 사용하여 개발할 때 테스트 시나리오를 먼저 생각하는 것은 기본이 된 거 같습니다.

불과 1년전만 하더라도 테스트 시나리오부터 생각하지 않았는데 말이죠.

이제는 개발을 할 때 구현할 Spec을 정해놓은 다음에 고려한 테스트 시나리오를 전부 입력한 다음에 테스트 시나리오가 성공할 때
까지 딸깍합니다.

그러곤, 다음 할 것으로 넘어가서 다음에 무엇을 할 지 생각하곤 합니다.

왜 테스트를 작성해야할까?


왜 테스트를 작성해야할까? 인제는 개발을 AI가 하기 때문에 사실상 제가 할 수 있는 게 테스트 시나리오를 생각하고 구상하는 것뿐입니다.
식상한 이야기지만, 최근에 개발하고 있는 서비스가 대대적으로 개편이 되고 있습니다.

벌써부터 머리가 아픈데, 기존 API에 대해서 하위 호환성을 지켜야합니다. 하위 호환성 이것을 지키기 위해서라도 테스트를 통해서 특정 구간을 지켜(?)줘야 한다고 생각합니다.

또, 테스트 자체가 AI에게 하나의 가이드 라인이 되는 것도 있습니다.

테스트를 어떻게 작성하는 게 좋을까요?

테스트를 작성하는 방법은 크게 고전파 방식과 런던파 방식이 있습니다.

런던파는 테스트 대상이 의존하는 모든 객체를 테스트 대역(Mock)으로 대체하여 테스트 단위를 완전히 격리해야한다! 라고 보는 입장입니다.

- 테스트 대상 코드를 협력자로부터 완전히 분리
- 단일 클래스의 독립적 테스트 지향
- 객체 간의 협력 구조 자체가 검증 대상

 

반면, 고전파는 단위 테스트에서 모든 의존성을 대역으로 바꾸는 것을 지양하는 입장입니다.

- 공유 상태를 유발하는 외부 의존성(DB, 파일 시스템 등)만 테스트 대역 사용
- 가능한 실제 객체를 사용하며 테스트 간 격리 유지
- 의존성 자체를 교체하기보다 실제 동작의 결과에 집중


저는 고전파 방식을 선호하는 편입니다. 어처피 각 Entity에 대해서 Fixture 클래스를 잘 만들어놓고. 테스트 시나리오를 입력해놓으면 AI가 다 만들어주는데 이왕이면 정확히 하는 게 좋지 않을까 합니다.

다만, 외부 API를 호출하는 경우는 테스트 대역을 사용하는 게 좋습니다.

이에 대해서 고민한 구글의 사례가 있습니다. 참고해보면 좋을 듯 합니다.

구글은 모의 객체 프레임워크를 만능으로 여겼던 시기를 거쳐, 현재는 이를 최소화하고 실제에 가까운 테스트를 작성하는 방향으로 선회했습니다. Mock 위주의 테스트는 작성하기는 쉽지만 버그를 잡아내는 능력이 떨어지고, 코드 수정 시 테스트도 함께 보수해야 하는 비용이 크다는 교훈을 얻었기 때문입니다.

 

 

테스트 데이터 어떻게 생성하는 게 좋을까?

제가 개발하는 서비스는 사용자의 상태에 따라 비즈니스 로직이 동적으로 변하는 구조입니다. 따라서 테스트 데이터가 각 케이스마다 존재했어야했습니다. 또한, 문진 데이터가 많기 때문에 고정된 디폴트 데이터가 많았습니다.

우선, 문진 데이터의 경우 서비스의 핵심이기 때문에 프로젝트 내부에서 Flyway를 사용해서 관리하는 방식을 선택했습니다.

 

기존에는 문진 데이터가 관리되고 있지 않고 있었습니다. 이로 인해서 인수인계도 힘들고, 개발자마다 로컬 데이터가 달라서 쉽지 않았습니다..

 

동적 데이터의 경우 Fixture Monkey 라이브러리를 사용해서 생성하였습니다. 선택한 이유는 엔티티에 선언된 Validation 관련 애노테이션을 참고해서 그거에 맞게 테스트 데이터를 만들 수 있기 때문입니다.

 

 

테스트 우선순위

 

아쉽게도 회사에서 Claude Max를 지원해주지 않습니다. 그래서 토큰을 아껴써야하는데요..  그 방법(?) 중에 하나가 테스트 우선순위를 정하는 것입니다.

모든 레이어를 테스트하면 좋겠지만, 아쉽게도 그럴 여건이 안 됩니다. 그래서 제 나름대로 테스트 우선순위를 정했습니다.

1순위: API 통합 테스트

대상: Controller 진입점부터 DB까지의 Happy Path + 주요 예외 케이스.

목표: "이 API가 스펙대로 동작하고 DB에 잘 저장되는가?"를 검증.

 

2순위: 도메인 단위 테스트

대상: 복잡한 계산식이나 상태 변경 로직이 담긴 Entity 및 POJO.

목표: 다양한 경계값에서도 비즈니스 로직이 깨지지 않음을 보장.



레거시 코드 어떻게 다룰 것인가?

 

"테스트 코드 없이 레거시 코드를 다 감수하시겠습니까?"라는 우아한형제들 기술 블로그의 글을 참고해서 실무에 적용중인데 아주 유용합니다.

테스트 코드 없이 레거시 코드를 다 감수하시겠습니까? 우아한형제들 기술 블로그



테스트 환경 어떻게 구축할 것인가?

 

기존에는 개인 로컬 DB를 사용해서 개발을 진행하고 있었습니다. 이는 개발자마다 데이터 상태가 달라 테스트 신뢰도를 떨어뜨리는 문제가 있었습니다. 이를 해결하기 위해 두 가지 대안을 검토했고, 최종적으로 Testcontainers를 선택했습니다. 그 이유는 '관리하기 편해서' 입니다.

 

그래서, 팀원분들과 이야기를 한 후에 테스트 환경을 구축을 하고 하나하나 테스트를 만들어갔습니다. 다행히(?) 테스트가 없는 백지 환경이어서 오히려 편했습니다...

 

Docker Compose를 통해 테스트 환경을 구축할 수 있었지만 테스트 전에 수동으로 해당 컨테이너를 실행해줘야하기 때문에 불편했습ㄴ디.



지금까지 테스트를 작성하며 했던 고민들을 간략하게 정리해봤습니다. 감사합니다.




728x90