목차
“테스트를 짜자”고 하면 다 같은 테스트를 떠올리기 쉽다. 그런데 테스트는 무엇을 얼마나 붙여서 확인하느냐로 층이 갈리고, 층마다 값과 비용이 다르다.
테스트도 종류가 있다
같은 “테스트”라도 얼마나 넓게 붙여 보느냐가 다르다. 크게 세 층으로 나눈다.
- 단위 테스트 - 작은 조각 하나(함수·클래스)만.
- 통합 테스트 - 여러 조각이 맞물려 도는지, 진짜 의존성(DB 등)을 붙여서.
- E2E 테스트 - 사용자가 하듯 처음부터 끝까지.
셋은 경쟁하는 게 아니라 역할이 다르다. 무엇을 확인하려는지에 따라 층을 고른다.
단위 테스트: 작은 조각 하나
가장 아래층이다. 함수나 클래스 하나만 떼어, 딸린 의존성은 가짜로 갈아끼우고 검사한다.
“할인 계산이 맞나”, “잔액보다 크면 거부하나” 같은 로직 하나를 콕 집어 확인한다. 딸린 게 없으니 아주 빠르고(수천 개가 몇 초), 깨지면 어디가 문제인지 바로 안다 - 조각 하나만 봤으니까.
통합 테스트: 조각들이 맞물리나
단위가 다 통과해도 이음매는 못 본다. 서비스와 진짜 DB가 실제로 맞물리는지, 쿼리가 정말 도는지는 붙여 봐야 안다.
통합 테스트는 진짜 의존성을 붙여 여러 조각을 함께 돌린다. 단위에서 가짜로 뭉갰던 부분(DB·외부 호출)을 진짜로 바꾸는 것이다. 그만큼 느리지만, 단위가 절대 못 잡는 버그를 잡는다. 자세한 건 통합·E2E 글에서.
E2E 테스트: 사용자처럼 끝까지
맨 위층이다. 브라우저를 실제로 띄워 로그인 → 상품 담기 → 결제를 사람처럼 끝까지 밟는다.
가장 현실에 가깝다 - 사용자가 겪는 그대로를 확인하니까. 대신 가장 느리고 가장 불안정하다. 전체가 다 떠 있어야 하고, 네트워크·타이밍에 흔들리고, 깨져도 어느 조각이 범인인지 바로 안 보인다.
아래로 갈수록 싸고 빠르다
세 층의 성질을 겹쳐 보면 방향이 하나다.


| 층 | 속도 | 비용·불안정 | 깨졌을 때 원인 찾기 |
|---|---|---|---|
| E2E | 느림 | 높음 | 어려움 |
| 통합 | 중간 | 중간 | 중간 |
| 단위 | 빠름 | 낮음 | 쉬움 |
아래층은 싸고 빠르고 원인이 명확하다. 위층은 비싸고 느리고 원인이 흐리다. 대신 위층은 더 현실에 가깝다.
그래서 아래를 두껍게
이 트레이드오프가 개수를 정한다. 싸고 빠른 단위 테스트를 많이, 비싸고 느린 E2E를 조금. 그림이 아래는 넓고 위는 좁은 피라미드가 되는 이유다.
대부분의 로직은 단위로 잡고, 이음매는 통합으로 몇 개, 진짜 중요한 사용자 흐름만 E2E로 최소한. 그러면 빠르게 자주 돌리면서 현실성도 조금 챙긴다.
뒤집히면 아이스크림콘이 된다
거꾸로 하면 어떻게 될까. 단위는 안 짜고 E2E만 잔뜩 쌓으면 위가 뚱뚱한 모양 - 아이스크림콘 안티패턴이다.
- 스위트 전체가 몇십 분씩 걸려 아무도 안 기다린다.
- 자주 깨지는데(느리고 불안정) 원인은 안 보인다.
- 결국 믿지 못하는 테스트가 되어 방치된다.
E2E가 현실적이라고 그것만 늘리면, 느리고 불안정한 성질까지 통째로 떠안는다. 그래서 위층은 아껴서 쓴다.
실무에서: 층은 이름표가 아니라 목적이다
- 단위·통합의 경계는 팀마다 조금씩 다르다. “DB를 붙이면 통합”이라는 딱지 논쟁보다 **“무엇을 확신하려는가”**로 고른다 - 로직이면 아래층, 이음매면 통합, 사용자 흐름이면 E2E.
- 비율은 목표가 아니라 결과다. “단위 70%“를 억지로 맞추지 말고, 각 층이 제 역할만 하게 두면 자연히 피라미드가 된다.
- 층을 섞어 같은 걸 여러 층에서 중복 검증하지 않는다 - 아래서 이미 잡은 로직을 E2E로 또 잡으면 느림만 산다.
정리
- 테스트는 단위·통합·E2E 세 층 - 무엇을 얼마나 붙여 보느냐로 갈린다.
- 아래로 갈수록 빠르고 싸고 원인이 명확, 위로 갈수록 느리고 불안정하지만 현실적.
- 그래서 단위를 많이, E2E를 조금 - 피라미드. 뒤집히면 느리고 못 믿는 아이스크림콘이 된다.
- 층은 이름표가 아니라 **“무엇을 확신하려는가”**로 고른다.
다음 글은 아래층을 빠르게 만드는 열쇠, 진짜 의존성을 떼어내는 테스트 더블로 간다.