재사용성과 테스트는 둘 다 의존성을 드러내고 경계를 나눌 때 좋아진다

재사용성과 테스트는 종종 따로 이야기된다. 하나는 코드 중복을 줄이는 문제처럼 보이고, 다른 하나는 품질 보증 문제처럼 보인다. 하지만 실제 설계에서는 둘이 자주 같은 방향으로 움직인다. 의존성이 명확하고 경계가 잘 나뉜 코드는 다른 곳에서 다시 쓰기도 쉽고, 시험하기도 쉽다.
반대로 외부 시스템에 강하게 묶여 있고, 객체가 너무 많은 일을 하며, 숨은 상태 변화가 많은 코드는 둘 다 어려워진다. 재사용하려고 꺼내도 주변을 함께 끌고 와야 하고, 테스트하려고 해도 너무 많은 것을 같이 올려야 한다.
테스트하기 쉬운 코드는 보통 경계가 선명하다
마틴 파울러가 설명한 의존성 주입은 객체가 필요한 협력자를 스스로 만들어 붙잡기보다, 바깥에서 주입받도록 설계하는 방식이다. 이렇게 하면 실제 구현과 테스트 대역을 바꾸기 쉬워진다.
이 구조는 테스트만을 위한 편법이 아니다. 의존성을 밖으로 드러내면 그 모듈이 어디까지 책임지는지도 선명해진다. 그래서 다른 곳에서 재사용할 때도 덜 얽힌다.
재사용은 범용성보다 분리가 먼저다
재사용 가능한 코드를 만들겠다고 처음부터 너무 일반화하면 오히려 실패하기 쉽다. 많은 경우 재사용성은 여러 상황에 맞춘 거대한 만능 모듈보다 한 책임만 잘 수행하는 작은 경계에서 나온다.
이런 경계는 테스트에도 유리하다. 입력과 출력이 비교적 명확하고, 부수효과가 적으며, 외부 시스템 접근이 제한되어 있기 때문이다.
테스트와 재사용이 함께 좋아지는 설계 습관
보통 다음 습관이 둘을 함께 끌어올린다.
- 외부 의존성을 숨기지 않고 드러낸다
- 상태 변경과 계산을 가능한 한 분리한다
- 한 모듈의 책임을 작게 유지한다
- 입출력 경계를 명확히 한다
이런 구조는 코드를 예쁘게 보이게 하기보다, 바꾸고 확인하고 옮겨 쓰는 비용을 줄여 준다.
마치며
재사용성과 테스트를 따로 최적화하려고 하면 일이 복잡해 보일 수 있다. 하지만 둘 다 결국 얼마나 덜 얽혀 있는가, 어디까지가 한 단위인가라는 같은 질문으로 수렴하는 경우가 많다.
좋은 설계는 코드를 한 번 더 쓰게 만드는 동시에, 한 번 더 확인하기 쉽게 만든다. 그래서 테스트하기 쉬운 구조를 고민하는 일은 종종 재사용성까지 함께 개선하는 일과 맞닿아 있다.