15장: 리액트 애플리케이션 테스트하기
React 테스트, 이제는 필수입니다
리액트로 웹 앱 개발을 하다 보면, '이 컴포넌트가 정말 원하는 대로 동작할까?', '수정이 전체 화면에 영향을 주진 않을까?' 같은 고민이 생깁니다. 복잡해질수록 작은 변화로도 시스템 전체가 흔들릴 위험이 커지죠. 여기서 테스트의 가치가 빛을 발합니다. 코드의 완성도를 높이고, 신뢰할 수 있는 앱을 만드는 데 테스트는 더 이상 선택이 아닙니다.
React 애플리케이션 테스트, 어떻게 시작할까?
대표적인 리액트 테스트 도구로는 Jest와 React Testing Library가 있습니다. Jest는 테스트 실행과 Mock, Spy 등 환경 관리 기능을 제공하고, React Testing Library는 실제 사용자처럼 컴포넌트를 다루는 방식을 지원합니다. 최근에는 Vite 기반 프로젝트에서 Vitest와 같이 빠른 실행을 제공하는 테스트 러너도 각광받고 있습니다. 거의 모든 React 스타터(예: create-react-app)는 Jest, React Testing Library를 기본 포함하니, 어렵지 않게 첫 테스트를 작성할 수 있습니다.
테스트의 3가지 접근법
테스트에는 세 가지 중요한 축이 있습니다. 스마트하게 코드를 보호하려면 다음을 기억하세요:
단위 테스트: 개별 함수·컴포넌트 단위로 동작을 검증합니다.
통합 테스트: 여러 컴포넌트가 함께 협력하는 과정을 점검합니다.
엔드 투 엔드(E2E) 테스트: 사용자의 실제 행동을 모방해 전체 애플리케이션 흐름을 검증합니다.
실전에서는 단위 테스트로 각 컴포넌트를 단단히 다진 뒤, 주요 사용자 시나리오는 통합·E2E 테스트로 덮어주는 전략이 유효합니다.
React Testing Library, 사용자 시점의 테스트
React Testing Library를 쓰면 내부 구현 대신, 화면에 무엇이 보이는지와 사용자의 상호작용에 집중하여 테스트할 수 있습니다. 버튼 클릭, 입력, 메시지 확인 등 실제 브라우저 환경과 비슷하게 코드를 검증할 수 있지요. 이런 행위 주도 테스트(BDD) 방식은 UI 변경에도 테스트 코드가 덜 민감해지기 때문에, 유지보수가 용이합니다.
import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';
test('카운터가 클릭에 따라 증가한다', () => {
render(<Counter />);
// 초기값: 0
expect(screen.getByText('0')).toBeInTheDocument();
// 버튼 클릭: +1
fireEvent.click(screen.getByText('증가'));
expect(screen.getByText('1')).toBeInTheDocument();
});
이처럼 render
로 컴포넌트를 띄우고, 화면에서 실제 보이는 텍스트를 기준으로 동작을 점검할 수 있습니다.
실전 프로젝트에서의 테스트 베스트 프랙티스
테스트는 가능한 사용자 관점에서 써라: 내부 구현이 바뀌어도 사용자 경험이 유지된다면 테스트도 함께 깨질 필요가 없습니다.
신뢰도 높은 케이스만 작성해라: 모든 코드를 강박적으로 테스트할 필요는 없습니다. 주로 비즈니스 룰이나 중요 UI 흐름 위주로 우선순위를 두세요.
테스트 코드도 코드다: 가독성, 유지보수성을 고려해서 적절히 분리하고, 의미 있는 이름을 붙여야 합니다.
TDD(테스트 주도 개발)도 도전해보자: 먼저 테스트를 작성하고 구현을 따라가는 방식은 버그 확률을 크게 줄여줍니다.
마치며
React 테스트는 개발자의 생산성, 코드 품질, 나아가 서비스 전체의 안정성으로 이어지는 중요한 관문입니다. 처음에는 단순한 버튼 클릭, 입력값 변화부터 출발해 차츰 상태 관리, API 연동, 다양한 컴포넌트간 상호작용까지 범위를 넓혀보세요. 실전의 React 앱은 테스트 코드와 함께 성장합니다.