들어가며
《구글 엔지니어는 이렇게 일한다》 중 테스트 관련한 장을 읽을 때, 테스트와 관련된 고민이 생겼었다. 가장 하고 싶으면서도 하지 못하는 것이 유닛 테스트를 비롯한 자동화 테스트였기 때문이었다. 그러던 중 테스트와 관련하여 다른 분과 이야기할 기회가 생겼었다. 이전에 테스트와 관련된 고민을 이야기했었던 것 때문이었다. 그분과 테스트에 관한 이야기를 하면서 테스트를 바라보는 내 시선이 바뀌었다. 아래에서는 주로 유닛 테스트와 관련된 부분이 주가 될 것이다.
프론트는 못 해
지금도 완전히 완치된 것은 아니었지만, 《클린 아키텍처》를 읽으면서부터 「프론트는 못 해」 병에 걸려 있었다. "프론트는 클린아키텍처 못 해", "프론트는 테스트 못 해" 와 같이 프론트는 못하는 것이 많다 생각했다.
《클린 아키텍처》를 읽으면서 나는, "UI는 세부사항이라면서? 프론트는 UI인데? 프론트는 클린 아키텍처 못 해"라 생각했다.
테스트 관련 글을 읽으면서 나는, "화면 테스트는 너무 비용이 많이 들어, 프론트는 너무 자주 바뀌는걸, 그래서 프론트는 테스트 같은 건 못 해"라 생각했다.
「프론트는 못 해」 라는 병이 무서운 이유는, 개발자가 개선하려고 하는 의지를 꺾기 때문이다.
쓰다보니 주제와 어긋나는 이야기인 것처럼 보여서, 이와 관련된 부분은 별도의 글로 작성할 것이다.
테스트의 목적
프론트엔드 개발자에게 있어서 프론트엔드 테스트의 목적은 무엇일까? 물론 품질관리라는 측면에서 접근할 수도 있지만, 단순히 개발자라고 생각한다고 가정한다면 말이다. 결국 버그를 줄이는 것이 목적이다. 프론트엔드 개발자가 테스트를 도입하게 만든 동기는 버그가 발생했을 때의 비용이 테스트를 도입하는데 드는 비용보다 크기 때문이다.
프론트엔드의 무엇을, 어떻게 테스트할까?
테스트의 종류는 무수히 많다. 유닛 테스트를 비롯한 각종 테스트들이 많다. 각각이 테스트하는 것이 다르고, 비용도 다르다. 그러나 일반적으로 사람들이 기대하는 테스트는 최대한 자동화된 테스트일 것이다. 인력으로 진행되는 테스트의 비용은 매우 비싼 데다가, 시간도 오래 걸리기 때문이다.
자동화된 테스트라 해서 저렴하지 않다. 결국 테스트는 사람이 작성해야 하는 것이다. UI를 테스트 하고자 한다면, 유닛 테스트보다 훨씬 많은 비용을 치뤄야할 것이다. 그렇기에 테스트를 신중하게 골라야한다.
중요한 것을 테스트하기
가장 중요한 것이다. 변경 가능성이 존재하며, 중요한 비즈니스 로직을 테스트하는 것이 최우선이다. 변경 가능성이 없는 로직의 테스트는 얻을 수 있는 효용이 제한적이다. 또한, 중요하지 않은 비즈니스 로직을 테스트하는 것은 중요한 비즈니스 로직을 테스트하는 것보다 우선시 되어야 한다. 중요한 비즈니스 로직이면서 리팩토링 대상이라면, 적절한 테스트 대상이라고 할 수 있다.
필요한 것을 테스트하기
필요 없는 테스트를 작성하는 것은 필요한 테스트를 작성하지 않은 것보다 더 나쁘다. 테스트를 깨지게 하는 것은 매우 많기 때문이다. 사소한 변경에도 테스트는 계란처럼 깨지기 쉽다. 게다가, 깨진 테스트가 많아지다 보면 아예 무시하는 경우도 많아질 것이고, 결국 테스트가 없었던 때로 돌아가기도 할 것이다. 그렇기에 필요하지 않은 테스트를 작성하는 것은 깨지기 쉬운 계란을 양손 가득 넘치게 들고서 걷는 것과 다를 것이 없다.
차근차근 테스트하기
특히, 이미 개발된 기능들이 많은 상항에서 테스트를 도입하려고 하면 매우 막막하다. 해야 할 것이 많아 보인다. 테스트 커버리지는 0%를 가리키고 있고, 이걸 언제 다 할까 싶은 생각이 든다. 그럴 때일수록 차근차근 테스트해야 한다. 위에서 언급한 변경 가능성이 있으며 중요하기도 한 비즈니스 로직을 테스트하는 것을 우선순위로 둔다면, 막상 그렇게 많지 않을 수도 있다. 테스트에 대한 중압감은 대부분 모든 것을 테스트하려고 하기 때문이다.
테스트 커버리지
항상 들리는 테스트와 관련된 조언 중 하나는, 커버리지에 신경 쓰지 말라는 것이 있다. 그럼에도 숫자로 딱 떨어지는 커버리지를 신경 쓰지 않기는 어렵다. 왠지 채워야 할 것 같은 남은 퍼센트는 우리를 무의미한 테스트를 만들도록 한다. 퍼센트의 유혹에서 벗어나야 한다. 물론 커버리지를 채우려는 마음을 테스트를 좀 더 작성하도록 만드는 원동력으로 삼을 수 있다. 하지만 커버리지를 위한 테스트를 작성한다면, 무의미한 테스트와 중요하지 않은 테스트를 남발할 가능성이 높아진다. 위에서 언급해듯이 이러한 테스트들은 테스트의 효용을 떨어트리게 된다.
프론트엔드의 구성요소별 테스트
아래는 개인적인 생각이기에, 실제 프로젝트와는 다를 수 있다.
1. UI는 변경 가능성이 높고, 테스트 비용도 많이 든다. 가장 최후로 선택할 테스트라 생각한다.
2. API 연결을 포함하는 테스트는 Mock 서버를 구현해야 하는 등의 작업이 수행된다. 설령 이런 문제가 없다라도, 아키텍처에 따라 한 번에 테스트하는 코드가 많을 수 있다. 이것 역시 우선순위가 낮다고 생각한다. API 응답이 올바른지를 테스트하는 것은 서버 측의 역할이라 생각한다.
3. 상태가 포함된 채로 로직을 테스트하는 것은, 의존성이 많아지면서 깨질 확률을 높인다. 거대한 Mock 객체를 만들어야 할 수도 있다.
4. 비즈니스 로직을 순수 함수로 분리한 다음, 이를 테스트하는 것이 가장 옳다고 생각한다. 언제 테스트를 실행해도 동일한 결과를 내보낼 것이라 예측할 수 있으며, 주요 로직을 작게 나눌 수 있도록 도와준다. 테스트를 수행할 수 있는 코드로 만들면서 리팩토링도 같이 되는, 가장 좋은 테스트 항목이라 생각한다.
마치며
맨 위의 대화는 대략 한 달 전에 있었다. 이 글을 쓰는데도 1주일 정도가 걸렸다. 부끄러운 이야기지만, 이 글을 쓰는 날(8/29)까지도 프론트엔드 테스트를 도입하지는 못했다. 하지만 그렇다고 해서 위에서 언급한 것이 의미 없다고는 생각하지 않는다. 테스트를 도입하는 데 있어서 가장 염두할 것은 위의 내용이기 때문이다.
'Programming' 카테고리의 다른 글
모바일 디바이스를 위한 웹 최적화가 필요한 이유 (0) | 2022.04.05 |
---|---|
뜯어 고치기 vs '2' 추가하기 (2) | 2022.02.21 |
커밋을 잘게 쪼개자 - 커밋은 언제 하는 것이 가장 좋을까? (0) | 2022.01.18 |
개발자들이 꼭 알아야할 KJDD 방법론 (0) | 2022.01.04 |
TypeScript 4.5의 변경 사항 요약 (0) | 2021.11.22 |