croissant_code
테스트코드와 커버리지의 의미 본문
PR 전에 테스트를 돌리는 이유와 커버리지 문서가 의미하는 것
개발을 하다 보면 이런 말을 자주 듣게 됩니다.
“테스트 코드는 안정성을 위해 필요하다.”
“PR 올리기 전에 테스트부터 돌려야 한다.”
“커버리지 리포트 확인해 봐라.”
그런데 막상 처음 테스트를 접할 때는 이런 생각이 듭니다.
- 그냥 기능이 되면 되는 거 아닌가?
- 왜 굳이 테스트 코드를 또 작성해야 하지?
- 커버리지 숫자가 높으면 뭐가 좋은 거지?
- 테스트 후 생성되는 HTML 문서나 리포트는 뭘 의미하는 걸까?
이번 글에서는 왜 테스트 코드를 작성하는지, 왜 PR 전에 테스트를 먼저 해야 하는지, 그리고 테스트 후 생성되는 문서와 커버리지가 어떤 의미를 가지는지를 “왜 사용하는가” 중심으로 정리해보겠습니다.
1. 테스트 코드는 왜 작성할까?
테스트 코드는 단순히 “코드가 실행되는지 확인하는 용도”가 아닙니다.
더 본질적으로는 기능이 의도대로 계속 유지되는지 확인하는 장치입니다.
개발에서는 새로운 기능을 추가하거나 기존 코드를 수정하는 일이 반복됩니다.
이때 가장 무서운 것은 내가 수정한 코드가 전혀 다른 기능까지 망가뜨리는 것입니다.
즉, 테스트 코드의 가장 큰 목적은 다음과 같습니다.
1) 기존 기능이 깨지지 않았는지 확인하기 위해
하나의 기능을 수정했는데 전혀 관련 없어 보이던 다른 기능이 깨질 수 있습니다.
테스트가 있으면 이런 문제를 빨리 발견할 수 있습니다.
2) 사람이 매번 수동으로 확인하는 비용을 줄이기 위해
기능이 많아질수록 매번 클릭하고, 입력하고, 결과를 눈으로 확인하는 것은 비효율적입니다.
테스트 코드는 이 과정을 자동화합니다.
3) 리팩토링을 안전하게 하기 위해
코드 구조를 개선하고 싶어도 테스트가 없으면 “혹시 깨질까?” 하는 불안 때문에 손대기 어렵습니다.
테스트가 있으면 구조는 바꾸되, 결과는 유지되는지 확인할 수 있습니다.
4) 요구사항을 코드로 남기기 위해
좋은 테스트는 “이 기능은 이렇게 동작해야 한다”는 규칙을 문서처럼 보여줍니다.
즉, 테스트 코드는 실행 가능한 명세서 역할도 합니다.
2. 간단한 예시로 이해해보기
예를 들어 온라인 쇼핑몰에서 주문 금액을 계산하는 함수가 있다고 가정해봅시다.
- 상품 가격: 30,000원
- 수량: 2개
- 50,000원 이상이면 무료배송
- 그 외에는 배송비 3,000원
이 기능을 개발한 뒤 눈으로 한 번 확인해서 잘 동작했다고 넘어갈 수 있습니다.
그런데 나중에 누군가 할인 기능을 추가하면서 계산 로직을 수정했고, 그 과정에서 무료배송 조건이 깨졌다고 해봅시다.
사용자는 60,000원을 주문했는데도 배송비가 붙어버립니다.
이런 문제는 실제 서비스에서 발견되면 늦습니다.
하지만 테스트 코드가 있었다면 바로 잡을 수 있습니다.
예를 들어 이런 테스트를 작성할 수 있습니다.
- 50,000원 미만이면 배송비가 붙는가?
- 50,000원 이상이면 배송비가 면제되는가?
- 수량이 늘어났을 때 총액이 정확히 계산되는가?
- 할인 적용 후 무료배송 기준이 의도대로 동작하는가?
이런 테스트는 단순해 보여도, 나중에 로직이 바뀔 때 매우 큰 힘을 발휘합니다.
3. 왜 PR 전에 테스트를 먼저 할까?
PR(Pull Request)은 보통 “내가 작성한 코드를 다른 사람에게 검토받기 위해 올리는 요청”입니다.
그런데 테스트도 하지 않은 상태로 PR을 올리면 어떤 문제가 생길까요?
1) 리뷰어의 시간을 낭비하게 된다
테스트도 안 된 코드를 리뷰하면, 리뷰어는 코드 품질을 보기 전에 기본적인 오류부터 마주하게 됩니다.
예를 들어:
- 함수가 아예 실행되지 않음
- 기존 테스트가 깨짐
- 간단한 예외 처리 누락
- 예상 가능한 케이스를 고려하지 않음
이런 상태의 PR은 리뷰 품질을 떨어뜨립니다.
2) “이 코드는 최소한 검증되었다”는 신뢰가 필요하다
PR 전에 테스트를 통과했다는 것은
“적어도 작성자가 기본적인 동작은 확인했다”는 신호입니다.
즉, 테스트는 단순한 기술 절차가 아니라 협업을 위한 최소한의 책임이기도 합니다.
3) 머지 후 장애를 줄이기 위해
PR 단계에서 테스트로 잡을 수 있는 문제를 놓치면, 결국 main 브랜치나 배포 환경에서 문제가 터질 수 있습니다.
그래서 PR 전에 테스트를 돌리는 것은 배포 안정성을 위한 첫 번째 방어선입니다.
4. PR에서 테스트가 가지는 실제 의미
PR에서 테스트는 “코드가 돌아간다”는 확인을 넘어서, 보통 아래 의미를 갖습니다.
1) 새 기능이 기존 규칙을 깨지 않았는지 검증
기존 로직과 충돌하는지 확인합니다.
2) 요구사항이 코드에 반영되었는지 검증
단순히 코드를 작성한 것이 아니라, 기능이 의도한 대로 동작하는지 보여줍니다.
3) 팀 차원의 품질 기준 유지
테스트가 통과하지 않은 PR은 머지하지 않는 문화가 있으면, 프로젝트 전체 안정성이 올라갑니다.
즉, 테스트는 “개발자 개인의 확인”이 아니라
팀 전체의 품질 보증 절차로 사용됩니다.
5. 테스트 후 생성되는 문서나 리포트는 무슨 의미가 있을까?
테스트를 실행하면 보통 여러 결과물이 나옵니다.
- 테스트 통과/실패 결과
- 어떤 테스트가 실패했는지 보여주는 로그
- 커버리지 리포트
- HTML 형식의 테스트 결과 문서
- CI 화면에서 보는 테스트 요약
이런 문서는 단순한 기록이 아니라 현재 코드 상태를 보여주는 품질 보고서입니다.
1) 어떤 기능이 검증되었는지 보여준다
테스트 결과 문서는 “무엇이 테스트되었고, 무엇이 통과했는가”를 보여줍니다.
2) 어디가 취약한지 보여준다
커버리지 문서를 보면 어느 파일은 테스트가 잘 되어 있고, 어느 파일은 거의 테스트되지 않았는지 한눈에 볼 수 있습니다.
3) 팀원 간 공통된 판단 기준이 된다
“이 기능은 테스트가 충분한가?”를 감으로 이야기하는 것이 아니라, 실제 결과를 보며 논의할 수 있습니다.
즉, 테스트 후 생성되는 문서는
코드의 상태를 눈으로 확인할 수 있게 만든 가시화 자료입니다.
6. 커버리지란 무엇인가?
커버리지는 쉽게 말해,
“테스트를 실행했을 때, 내 코드가 실제로 얼마나 실행되었는가”
를 숫자나 리포트로 보여주는 지표입니다.
많은 분들이 커버리지를 “점수”처럼 생각하지만, 실제로는 테스트의 사각지대를 찾는 지도에 가깝습니다.
7. 각 커버리지는 어떤 의미를 가질까?
도구마다 표현 방식은 조금 다르지만, 보통 다음 개념들을 많이 봅니다.
7-1. Line Coverage (라인 커버리지)
가장 많이 보는 커버리지입니다.
코드 한 줄 한 줄이 테스트 실행 중 실제로 수행되었는지를 나타냅니다.
예를 들어 어떤 파일에 100줄의 실행 가능한 코드가 있고, 테스트 실행 중 80줄이 실행되었다면 라인 커버리지는 80%입니다.
왜 사용할까?
라인 커버리지는 가장 직관적입니다.
“아직 테스트가 한 번도 지나가지 않은 코드가 어디인지” 빠르게 파악할 수 있습니다.
하지만 한계도 있다
라인 커버리지가 높다고 해서 충분한 테스트가 되었다는 뜻은 아닙니다.
한 줄이 실행되었다고 해도, 그 안의 다양한 조건이 모두 검증된 것은 아닐 수 있기 때문입니다.
7-2. Branch Coverage (브랜치 커버리지)
브랜치 커버리지는 if/else 같은 조건 분기에서 모든 경로가 테스트되었는지를 보여줍니다.
예를 들어:
- 재고가 있으면 주문 성공
- 재고가 없으면 예외 발생
이런 로직이 있다면, 재고 있는 경우만 테스트해서는 부족합니다.
재고가 없는 경우도 테스트해야 브랜치 커버리지가 올라갑니다.
왜 사용할까?
실제 버그는 보통 “예외 케이스”, “실패 케이스”, “특정 조건에서만 발생하는 케이스”에서 많이 나옵니다.
브랜치 커버리지는 이런 숨은 분기 누락을 찾는 데 유용합니다.
실무적으로 더 중요한 이유
라인 커버리지는 높은데 브랜치 커버리지는 낮다면,
“코드는 대충 지나갔지만 중요한 조건은 제대로 검증하지 못했다”는 뜻일 수 있습니다.
7-3. Function Coverage / Method Coverage (함수 커버리지)
어떤 함수나 메서드가 테스트 중 호출되었는지를 보여줍니다.
왜 사용할까?
프로젝트에 함수가 많은 경우,
“아직 한 번도 테스트에서 호출되지 않은 기능”을 찾는 데 도움이 됩니다.
다만 함수가 호출되었다고 해서 내부 로직이 충분히 검증되었다는 뜻은 아니므로, 이 역시 참고 지표로 보는 것이 좋습니다.
7-4. File Coverage (파일 단위 커버리지)
파일별로 커버리지를 보여주는 방식입니다.
예를 들어 어떤 리포트에서는 파일마다 다음과 같이 나옵니다.
- order_service.py: 85%
- payment_service.py: 42%
- discount_policy.py: 91%
왜 사용할까?
어떤 영역이 테스트에 강하고, 어떤 영역이 취약한지 우선순위를 잡기 좋습니다.
예를 들어 결제 로직 파일의 커버리지가 낮다면,
그 파일은 위험도가 높은데도 테스트가 부족하다는 뜻일 수 있습니다.
8. 커버리지는 왜 사용하는가?
여기서 중요한 질문은 이것입니다.
왜 굳이 커버리지를 확인할까?
이유는 크게 세 가지입니다.
1) 테스트되지 않은 코드를 찾기 위해
사람은 “대충 다 테스트한 것 같다”고 느끼기 쉽습니다.
하지만 커버리지 리포트를 보면 실제로는 특정 파일이나 특정 조건이 전혀 테스트되지 않았을 수 있습니다.
2) 테스트 우선순위를 정하기 위해
모든 코드를 한 번에 완벽하게 테스트하는 것은 현실적으로 어렵습니다.
이럴 때 커버리지는 “어디부터 보강해야 하는지” 알려줍니다.
예를 들어:
- 결제, 주문, 환불처럼 위험한 영역은 먼저 보강
- 단순한 DTO나 매핑 코드는 후순위
이런 식으로 접근할 수 있습니다.
3) 품질 상태를 팀이 함께 보기 위해
커버리지는 단순히 개발자 개인이 보는 수치가 아니라,
팀 전체가 현재 품질 상태를 파악하는 기준이 될 수 있습니다.
9. 예시로 보는 커버리지의 의미
다음과 같은 주문 함수가 있다고 가정해봅시다.
- 상품이 비활성 상태면 주문 불가
- 재고가 없으면 주문 불가
- 결제 금액이 0 이하이면 예외
- 정상 조건이면 주문 생성
테스트를 하나만 작성해서 “정상 주문”만 검증했다면 어떨까요?
이 경우:
- 함수는 호출되었으니 함수 커버리지는 올라갈 수 있습니다.
- 몇몇 줄은 실행되었으니 라인 커버리지도 어느 정도 나올 수 있습니다.
- 하지만 비활성 상품, 품절, 잘못된 금액 같은 분기는 전혀 검증되지 않았습니다.
즉, 수치상 일부 커버리지는 나와도 실제 품질은 여전히 취약합니다.
반대로 다음 테스트를 모두 작성했다면 의미가 달라집니다.
- 정상 주문 성공
- 비활성 상품이면 실패
- 재고가 0이면 실패
- 결제 금액이 잘못되면 실패
이제야 비로소 이 함수의 중요한 규칙들이 검증되었다고 볼 수 있습니다.
10. 커버리지가 높으면 무조건 좋은 걸까?
그렇지는 않습니다.
이 부분은 꼭 짚고 넘어가야 합니다.
커버리지가 90%라고 해서 테스트 품질이 좋은 것은 아닙니다.
반대로 커버리지가 60%여도 핵심 비즈니스 로직을 잘 검증하고 있다면 더 가치 있을 수 있습니다.
예를 들어 이런 경우는 조심해야 합니다.
- 함수만 호출하고 assert가 약한 경우
- 정상 케이스만 테스트한 경우
- 예외 케이스를 전혀 다루지 않은 경우
- mock만 과도하게 사용해서 실제 로직 검증이 부족한 경우
즉, 커버리지는 목표가 아니라 보조 지표입니다.
11. 그렇다면 실무에서는 어떻게 보는 게 좋을까?
실무에서는 보통 이렇게 생각하는 것이 좋습니다.
1) 숫자 자체보다 “핵심 로직이 테스트되었는가”가 더 중요하다
결제, 주문, 재고, 할인, 인증 같은 기능은 커버리지 숫자보다도 테스트 품질이 중요합니다.
2) 전체 커버리지보다 우선순위가 중요하다
프로젝트 전체를 한 번에 다 테스트하려 하기보다, 실패 시 위험한 영역부터 테스트하는 것이 현실적입니다.
3) 커버리지 리포트는 “빠진 구간 찾기”용으로 본다
커버리지 리포트를 보고 “몇 점이네?”보다
“어느 파일이 안 닿았지?”, “어떤 예외 분기가 빠졌지?”를 보는 것이 더 중요합니다.
12. PR과 커버리지 문서는 함께 어떤 의미를 가질까?
PR 단계에서 테스트와 커버리지 문서는 함께 이런 메시지를 전달합니다.
- 이 코드는 최소한 자동 검증을 거쳤다
- 기존 기능이 깨지지 않았는지 확인했다
- 아직 테스트가 부족한 영역도 확인 가능하다
- 리뷰어는 더 본질적인 코드 리뷰에 집중할 수 있다
즉, 테스트와 커버리지 문서는 단순한 부가 자료가 아니라
협업 품질을 높이는 근거 자료입니다.
13. 한 문장으로 정리하면
테스트 코드는 기능이 계속 올바르게 동작하도록 지켜주는 안전장치이고,
커버리지 리포트는 그 안전장치가 어디까지 닿아 있는지 보여주는 지도입니다.
그리고 PR 전에 테스트를 먼저 하는 이유는
내 코드가 팀의 코드베이스에 들어가기 전에 최소한의 신뢰를 확보하기 위해서입니다.
마무리
처음 테스트 코드를 작성할 때는 “일이 두 배로 늘어난 것 같다”는 느낌이 들 수 있습니다.
하지만 시간이 지나면 테스트는 개발 속도를 늦추는 것이 아니라, 오히려 불필요한 확인과 장애 대응 비용을 줄여주는 장치라는 것을 체감하게 됩니다.
특히 PR 전에 테스트를 실행하고, 그 결과 문서와 커버리지 리포트를 확인하는 습관은
혼자 개발할 때도 유용하고, 팀으로 협업할 때는 더 큰 가치를 가집니다.
결국 테스트를 하는 이유는 단 하나입니다.
코드를 믿기 위해서입니다.
'SW' 카테고리의 다른 글
| 스타트업 투자유치 단어 지표 (0) | 2026.04.08 |
|---|---|
| 테스트 코드 종류 (0) | 2026.03.13 |
| 이커머스에서 장바구니와 주문은 왜 Cart / Cart Item 구조로 설계할까 (0) | 2026.03.13 |
| 원격 SSH 접근 환경 만들기 (1) | 2025.11.25 |
| 리액트 올인원-4-React.js (0) | 2025.10.16 |