단위 테스트
Unit Test
방법
함수나 모듈 하나만 떼어 값을 넣고 결과가 기댓값과 같은지 자동으로 확인하는 가장 작은 테스트입니다.
등장 배경
코드를 고친 뒤 제대로 됐는지 확인하는 일을 손으로 하던 시절이 있었습니다. 화면을 띄우고 로그인하고 해당 기능까지 눌러 들어가서 값을 넣어 봅니다. 한 번 확인에 2분이 걸리니 경우를 열 가지 보려면 20분이고, 그 20분을 하루에 몇 번씩 쓸 수는 없습니다. 그래서 대개 두세 가지만 눌러 보고 넘어갔습니다.
넘어간 자리에서 사고가 났습니다. 태오가 할인 계산을 고치고 화면에서 1만 원, 5만 원, 10만 원 세 경우를 확인했습니다. 잘 됐습니다. 그런데 할인이 적용돼 결제 금액이 0원이 되는 경우에 결제가 실패했고, 그 사실은 무료 쿠폰을 받은 고객이 문의를 보내 알았습니다. 0원은 화면에서 만들어 보기가 번거로워서 확인 목록에 들어가지 않았던 것입니다.
손으로 확인하는 방식에는 두 가지 한계가 같이 있었습니다. 시간이 들어서 경우를 다 볼 수 없고, 화면을 거쳐야 하니 만들기 까다로운 경우는 아예 빠집니다. 계산하는 함수만 떼어 놓고 값을 직접 넣어 보면 두 문제가 같이 풀립니다. 0원과 음수와 소수점을 넣는 데 화면이 필요하지 않고, 스무 가지 경우를 넣어도 1초 안에 끝납니다.
사용 절차
떼어 낼 수 있는 가장 작은 덩어리를 고르는 것으로 시작합니다. 다섯 단계입니다.
- 단위를 고릅니다. 값을 받아 값을 돌려주는 함수가 가장 쉽습니다. 화면이나 데이터베이스에 붙지 않은 계산일수록 떼어 내기 쉬워서, 요금 계산이나 권한 판정이 첫 대상이 됩니다.
- 준비, 실행, 확인 세 토막으로 씁니다. 입력값을 만들고, 함수를 한 번 부르고, 돌려받은 값이 기댓값과 같은지 비교합니다. 한 테스트에서 한 가지만 확인하는 것이 요령입니다. 여러 개를 한 번에 확인하면 빨간불이 떴을 때 어느 조건이 깨졌는지 다시 찾아야 합니다.
- 경계값을 목록으로 만듭니다. 흔한 값 하나만 넣어 보면 통과하는 테스트가 되기 쉽습니다. 금액이라면 0, 음수, 소수점, 아주 큰 값, 빈 값을 적어 두고 각각을 한 건씩 만듭니다. 사고는 대개 이 목록 안에서 납니다.
- 밖에 기대는 부분을 끊습니다. 목은 진짜 대신 흉내만 내는 가짜인데, 카드사에 실제로 요청을 보내지 않도록 성공이라고만 답하는 가짜를 놓고 돌립니다. 현재 시각이나 무작위 값처럼 매번 달라지는 것도 고정해 둬야 언제 돌려도 같은 결과가 나옵니다.
- 자동으로 돌게 붙입니다. 파일을 저장할 때, 그리고 변경을 합치기 전에 돕니다. 한 건이 1000분의 1초 안에 끝나므로 2,000개를 모아 돌려도 1분이 안 걸립니다.
테스트를 먼저 쓰고 구현을 나중에 하는 순서도 있습니다. 테스트 주도 개발이라고 부르고, 만들기 전에 무엇이 완성인지 정하게 되는 것이 그 값입니다.
적합한 상황과 한계
규칙이 복잡한 계산에서 값이 가장 큽니다. 요금제별 금액 계산, 권한 판정, 날짜와 기간 처리처럼 조건이 여러 갈래로 갈리는 자리입니다. 구조만 바꾸는 작업을 앞두고 안전망으로 깔 때도 좋고, 버그를 하나 잡을 때 그 버그를 재현하는 한 건을 남겨 두는 용도로도 씁니다.
반대로 맞지 않는 자리가 있습니다. 화면에 요소가 어떻게 배치되는지, 여러 조각을 이어 붙였을 때 잘 도는지, 실제 결제가 카드사까지 가서 승인되는지는 이 방법으로 확인할 수 없습니다. 각각 통합 테스트와 E2E 테스트의 몫입니다.
한계는 셋입니다.
- 각각 통과해도 이어 붙이면 깨집니다. 계산 함수와 저장 모듈이 따로 멀쩡한데 둘을 연결하면 값의 단위가 어긋나 있는 식입니다.
- 숫자로 안심하기 쉽습니다. 테스트 커버리지는 테스트가 훑고 지나간 코드의 비율인데, 이 값이 80퍼센트라도 훑기만 하고 결과를 확인하지 않은 줄이 섞여 있을 수 있습니다.
- 가짜를 많이 쓰면 실제와 멀어집니다. 가짜 결제사가 언제나 성공이라고 답하도록 만들어 두면, 실제 카드사가 돌려주는 거절 응답을 처리하지 못하는 코드가 테스트를 전부 통과합니다.
여기에 유지비가 하나 더 붙습니다. 함수 안에서 무엇을 어떤 순서로 부르는지까지 확인하는 테스트를 쓰면, 결과가 같은데 구조만 바꾼 작업에서도 테스트가 깨집니다. 확인할 것은 구현 방식이 아니라 돌려받는 값입니다.
실무 용례
"이 계산은 단위 테스트로 덮을 수 있어요. 화면까지 안 올려도 됩니다."
떼어 내기 쉬운 자리라 빠르고 싸게 확인할 수 있다는 말입니다.
"0원과 음수 경우가 빠졌습니다. 경계값부터 채워 주세요."
흔한 값만 확인하고 사고가 나는 구간은 비어 있다는 지적입니다.
"이 테스트는 구현을 확인하고 있어요. 결과만 보게 고치죠."
내부 구조에 매달려 있어 정리 작업마다 깨진다는 뜻입니다.
페이지덱은 요금 계산과 권한 판정에 단위 테스트를 몰아 두었습니다. 태오가 0원 결제 사고 뒤에 그 함수의 경계값을 열한 건으로 만들었고, 그 뒤로 같은 종류의 실수는 저장하는 순간 잡혔습니다. 전체 2,300건이 한 바퀴에 50초쯤 걸립니다.
지현은 버그를 닫을 때 재현 테스트가 붙었는지 함께 봅니다. 고친 코드만 올라오면 같은 고장이 반년 뒤에 다시 날 수 있어서, 버그 하나가 테스트 한 건을 남기는 것을 규칙으로 정해 뒀습니다.
흔한 오해
커버리지 숫자가 높으면 안전하다고 읽는 경우가 가장 많습니다. 비율이 90퍼센트면 코드의 열 중 아홉이 검증된 것처럼 보입니다. 하지만 이 값은 테스트가 지나간 줄을 센 것이고 제대로 확인했는지는 세지 않습니다. 함수를 부르기만 하고 결과를 비교하는 줄이 없는 테스트도 커버리지를 올립니다. 이 오해를 그대로 두면 팀은 숫자를 올리는 쉬운 방법을 찾게 되고, 90퍼센트를 채운 채로 사고는 그대로 납니다.
테스트를 쓰면 개발이 느려진다는 오해도 흔합니다. 코드 말고 다른 것을 더 써야 하니 그렇게 느껴집니다. 실제로 느려지는 구간은 처음 두 주 정도이고, 그다음부터는 손으로 확인하던 20분이 1분으로 줄고 같은 자리를 두 번 고치는 일이 줄어듭니다. 이 오해가 남은 팀에서는 마감이 가까워질 때마다 테스트를 먼저 생략하는데, 그 시기가 하필 실수가 가장 많이 나는 시기입니다.
자주 헷갈리는 용어
| 용어 | 무엇을 보는가 | 단위 테스트와의 차이 |
|---|---|---|
| 통합 테스트 | 여러 요소를 이어 붙인 상태에서 도는지 | 연결을 봅니다. 느리고 원인을 짚기 어렵지만, 각각 멀쩡한데 이어 붙이면 깨지는 자리를 잡습니다 |
같이 보면 좋은 페이지
연관 용어
마지막 업데이트 2026-09-16