개념
화면 조각도 "단위"가 될 수 있다
레슨 1에서 단위 테스트를 "함수 하나를 독립적으로 검증"하는 것으로 배웠다. 프런트엔드에서는 이 "단위"가 버튼, 입력 폼, 상품 카드 같은 화면 컴포넌트 하나가 된다. 컴포넌트 테스트는 이 화면 조각을 실제 브라우저 전체를 띄우지 않고도 독립적으로 검증한다.
구현이 아니라 사용자가 보는 것을 테스트한다
컴포넌트 테스트에서 가장 중요한 원칙은, "내부 코드가 어떻게 짜였는지"가 아니라 "사용자가 화면에서 무엇을 보고 어떻게 조작하는지"를 기준으로 테스트한다는 것이다.
// 나쁜 예 — 내부 구현(CSS 클래스 이름)에 의존
expect(wrapper.find(".btn-primary-disabled")).toHaveLength(1)
// 좋은 예 — 사용자가 실제로 인식하는 것(버튼 텍스트, 비활성화 상태)에 의존
const button = screen.getByRole("button", { name: "구매하기" })
expect(button).toBeDisabled()CSS 클래스 이름은 디자인이 바뀌면 언제든 바뀔 수 있는 구현 세부사항이다. 반면 "구매하기라는 이름의 버튼이 비활성화되어 있다"는 것은 실제 사용자가 화면에서 확인하는 사실 그대로다. 이 원칙을 지키면, 내부 코드를 리팩터링해도(겉모습이 그대로면) 테스트가 깨지지 않는다.
사용자 행동을 흉내 내기
render(<CouponForm />)
const input = screen.getByLabelText("쿠폰 코드")
fireEvent.change(input, { target: { value: "SAVE10" } })
const applyButton = screen.getByRole("button", { name: "적용" })
fireEvent.click(applyButton)
expect(screen.getByText("10% 할인이 적용되었습니다")).toBeInTheDocument()이 코드는 실제 사용자가 하는 행동(쿠폰 코드 입력 → 적용 버튼 클릭)을 그대로 흉내 내고, 그 결과 화면에 무엇이 보이는지(할인 적용 안내 문구)를 확인한다. 모듈 3에서 배운 테스트 케이스의 절차·기대결과 구조와 본질적으로 같다.
어디까지가 컴포넌트 테스트의 영역인가
- 컴포넌트 테스트가 확인하는 것: 이 화면 조각이 주어진 상태에서 올바르게 표시되는가, 사용자 조작에 올바르게 반응하는가
- 컴포넌트 테스트가 확인하지 않는 것: 실제 서버 API 호출이 제대로 되는가(통합 테스트나 E2E 테스트의 영역), 여러 화면에 걸친 전체 흐름(모듈 5의 탐색적 테스팅이나 E2E의 영역)
컴포넌트 테스트는 API 호출 부분을 레슨 3에서 배운 테스트 더블로 대체해서, "화면 로직만" 독립적으로 검증하는 경우가 많다.
실무에서 왜 필요한가
프런트엔드 개발자가 "이 컴포넌트는 테스트로 커버돼 있어요"라고 할 때, 그 테스트가 실제 화면 요소(버튼 이름, 표시되는 텍스트) 기준인지, 아니면 내부 구현(CSS 클래스, 컴포넌트 내부 상태 변수) 기준인지 QA가 구분할 수 있으면, "이 테스트는 디자인이 바뀌면 오히려 깨지기 쉬운 구조네요"처럼 유용한 피드백을 줄 수 있다. 이건 스테이지 4(UI 자동화)에서 다룰 E2E 테스트 설계 원칙과도 그대로 이어진다.
실습 과제
과제 1 — 구현 세부사항 vs 사용자 관점 구분하기 (10분)
다음 두 테스트 접근 중 어느 쪽이 사용자 관점에 더 가까운지 판단하고 이유를 적는다.
wrapper.state('isOpen')을 확인해 모달이 열렸는지 검증screen.getByRole('dialog')로 모달이 화면에 나타났는지 검증
과제 2 — 사용자 시나리오를 테스트로 옮기기 (10분)
"장바구니 아이콘을 클릭하면 담긴 상품 개수가 배지로 표시된다"는 기능을, 이 레슨에서 본 패턴(요소 찾기 → 행동 흉내 → 결과 확인)을 참고해 의사코드(pseudocode) 형태로 작성한다.
자가 체크리스트
- 화면 컴포넌트도 단위 테스트의 대상이 될 수 있다는 것을 설명할 수 있다
- 구현 세부사항 기준 테스트와 사용자 관점 기준 테스트의 차이를 예시로 구분할 수 있다
- 컴포넌트 테스트가 확인하는 범위와 확인하지 않는 범위를 설명할 수 있다
- 사용자 관점 테스트가 리팩터링에 더 강한 이유를 설명할 수 있다
흔한 실수
- CSS 클래스 이름이나 내부 상태 변수에 의존하는 테스트를 그대로 받아들인다. 디자인이 조금만 바뀌어도 테스트가 깨지는 취약한 구조다.
- 컴포넌트 테스트가 전체 사용자 흐름(E2E)까지 다 검증한다고 착각한다. 컴포넌트 테스트는 화면 조각 하나의 범위에 머문다.
- 실제 서버 응답을 테스트 더블 없이 그대로 기다리게 만든다. 컴포넌트 테스트는 API 호출 부분을 레슨 3의 더블로 대체하는 것이 일반적이다.
참고 자료
- Testing Library 공식 문서 — Guiding Principles — "사용자 관점으로 테스트하라"는 원칙의 공식 설명
- Kent C. Dodds — Testing Implementation Details — 구현 세부사항 테스트의 문제점을 다룬 대표 아티클