단위 테스트
Unit Testing
단위 테스트란?
- 작은 코드 조각을 자동 검증
- 고쳐도 안 망가졌는지 확인
- 안심하고 빠르게 개선
단위 테스트가 실제로 바꾸는 것은 코드가 아니라 팀의 의사결정 방식입니다. 테스트가 없는 코드베이스에서는 '저 함수 건드리면 어디가 터질지 모른다'는 이유로 개선 제안이 회의에서 번번이 밀립니다. 그래서 낡은 로직을 걷어내는 대신 조건문을 하나 더 얹어 우회하고, 파일은 해가 갈수록 두꺼워집니다. 테스트가 깔려 있으면 판단 기준이 '고치고 돌려보면 된다'로 바뀝니다. 5년 된 결제 모듈을 입사 3개월 차 개발자가 손대도, 몇 초 만에 도는 테스트가 빨간불을 켜 주면 그 자리에서 되돌릴 수 있습니다.
실무에서는 테스트의 층을 구분해서 씁니다. 단위 테스트는 DB·외부 API·파일 시스템을 타지 않고 함수 하나만 떼어 밀리초 단위로 돌리는 것이고, DB 연결이나 API 호출이 들어가는 순간 통합 테스트, 브라우저를 띄워 사용자 시나리오를 따라가면 E2E 테스트입니다. 외부 의존은 가짜 객체(목·스텁)로 대체해 속도와 재현성을 지킵니다. 빠르고 많이 도는 단위 테스트를 아래에 두껍게, 느린 E2E를 위에 얇게 쌓는 구성이 일반적이고, 커버리지도 결제·정산처럼 돈이 걸린 모듈부터 올리는 것이 순서입니다. 전체 평균 숫자보다 어디가 덮였느냐가 훨씬 중요합니다.
어긋나는 지점은 대개 셋입니다. 첫째, 커버리지 80%를 KPI로 걸면 검증문 없이 함수만 호출해 숫자를 채운 테스트가 늘어납니다. 지표는 녹색인데 장애 건수는 그대로입니다. 둘째, 내부 구현에 달라붙은 테스트입니다. 호출 순서나 내부 변수까지 검증하면 리팩터링할 때마다 수십 개가 깨지고, 개발자는 테스트를 고치는 대신 주석 처리합니다. 셋째, 깨진 테스트를 하루 넘게 방치하면 그 테스트는 죽은 것입니다. 빨간불이 일상이 되면 아무도 보지 않습니다. 덧붙여 단위 테스트는 QA나 인수 테스트를 대체하지 않습니다 — 부품이 전부 멀쩡해도 조립이 틀릴 수 있습니다.
소프트웨어 공학의 검증 기법으로, 테스트 주도 개발(TDD)·자동화 도구의 확산과 함께 표준 관행이 됐습니다.
가상의 사례로 살펴보겠습니다. 임직원 240명 규모로 물류 SaaS를 운영하는 A사 개발팀 이야기입니다. 월 2회 정기 배포 때마다 평균 3건씩 장애가 터져 새벽 롤백이 반복됐고, 6년 된 정산 모듈은 아무도 손대려 하지 않았습니다. 테스트 코드는 있었지만 전체 커버리지 8% 수준이었습니다.
- 개발팀장 김 차장이 지난 1년 장애 47건을 모듈별로 분류해 보니 절반이 정산·요금 계산 두 곳에서 나왔고, '전부 덮지 말고 여기부터 덮자'로 범위를 좁혔습니다.
- 요금 계산 함수에는 실제 장애 티켓 내용을 그대로 테스트로 옮겼습니다. 심야 할증, 도서지역 가산, 반품 수수료 등 32개 케이스를 2주에 걸쳐 작성했습니다.
- 외부 배송사 API 호출은 목 객체로 걷어내 전체 실행 시간을 11분에서 40초로 줄였고, 커밋이 올라올 때마다 CI에서 자동으로 돌게 걸어 뒀습니다.
- 빌드가 깨진 채 이틀이 흐르자 김 차장이 '빨간불로 퇴근하지 않는다'를 팀 규칙으로 못 박았고, 이후 깨진 테스트 평균 복구 시간이 반나절 안으로 들어왔습니다.
- 6개월 뒤 두 모듈 커버리지는 76%가 됐고, 배포당 장애는 3건에서 0.5건으로, 새벽 롤백은 분기 4회에서 0회로 줄었습니다. 미뤄 두던 정산 모듈 개선 건도 3년 만에 다시 일정에 올랐습니다.