포스트

[이제와서 시작하는 React 마스터하기 #17] React 테스팅 입문

[이제와서 시작하는 React 마스터하기 #17] React 테스팅 입문

React Day 17 - “테스트 코드 작성”이라고 하면 어렵게 들리죠? 하지만 알고 보면 버그를 미리 잡는 든든한 보험이에요!

오늘 배울 내용

  • ✅ 테스트가 뭔가요?
  • ✅ 왜 필요한가요?
  • ✅ 간단한 테스트 맛보기
  • ✅ 다음 학습 방향

테스트가 뭔가요?

테스트 코드는 내가 작성한 코드가 제대로 작동하는지 자동으로 확인해주는 코드예요.

일상 비유 🧪

요리를 만들고 나서:

테스트 없이:

  • 손님에게 바로 내놓아요
  • 짜거나 탔는지 모르고 제공
  • 문제 발견 → 손님이 불평 😢

테스트 있으면:

  • 손님에게 내놓기 전에 맛을 봐요
  • 문제 발견 → 바로 고쳐요
  • 손님에게 완벽한 요리 제공 ✨

왜 테스트가 필요한가요?

1. 버그를 미리 잡아요

1
2
3
4
5
6
7
8
9
10
11
// 테스트가 없으면...
function add(a, b) {
  return a - b;  // 버그! 더하기인데 빼기를 했어요
}

// 사용자가 발견 → 큰 문제!

// 테스트가 있으면...
test('add 함수는 두 수를 더해야 해요', () => {
  expect(add(2, 3)).toBe(5);  // 실패! 즉시 발견!
});

2. 자신감 있게 코드를 수정할 수 있어요

1
2
3
4
5
// 테스트 없이 코드 수정
"이 코드를 고치면... 다른 부분이 망가질까? 😰"

// 테스트 있고 코드 수정
"테스트가 통과하면 OK! 안심하고 수정 가능 😎"

3. 문서 역할을 해요

1
2
3
test('로그인 버튼을 클릭하면 로그인 폼이 나타나요', () => {
  // 이 테스트 이름만 봐도 기능을 알 수 있어요!
});

React 테스팅 도구

React는 기본적으로 두 가지 도구가 함께 설치돼요:

1. Jest

  • 테스트를 실행하는 프레임워크
  • test(), expect() 같은 함수 제공

2. React Testing Library

  • React 컴포넌트를 테스트하는 라이브러리
  • 사용자 관점에서 테스트
1
2
# Create React App으로 만든 프로젝트는 자동 설치!
# 별도 설치 필요 없어요

간단한 테스트 예제

예제 1: 함수 테스트

1
2
3
4
5
6
7
8
9
10
11
12
// utils.js
export function greet(name) {
  return `안녕하세요, ${name}님!`;
}

// utils.test.js
import { greet } from './utils';

test('greet 함수는 인사말을 반환해요', () => {
  const result = greet('홍길동');
  expect(result).toBe('안녕하세요, 홍길동님!');
});

테스트 실행:

1
npm test

결과:

1
2
3
✓ greet 함수는 인사말을 반환해요 (5ms)

Tests: 1 passed, 1 total

예제 2: 컴포넌트 테스트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Button.js
export default function Button({ text, onClick }) {
  return <button onClick={onClick}>{text}</button>;
}

// Button.test.js
import { render, screen, fireEvent } from '@testing-library/react';
import Button from './Button';

test('버튼이 제대로 렌더링되어요', () => {
  render(<Button text="클릭하세요" />);

  // 화면에 "클릭하세요" 텍스트가 있는지 확인
  const button = screen.getByText('클릭하세요');
  expect(button).toBeInTheDocument();
});

test('버튼을 클릭하면 onClick이 호출되어요', () => {
  const handleClick = jest.fn(); // 가짜 함수
  render(<Button text="클릭" onClick={handleClick} />);

  const button = screen.getByText('클릭');
  fireEvent.click(button);  // 클릭!

  expect(handleClick).toHaveBeenCalled();  // 호출됐나요?
});

예제 3: 입력 폼 테스트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// LoginForm.js
import { useState } from 'react';

export default function LoginForm({ onSubmit }) {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    onSubmit({ username, password });
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        placeholder="아이디"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
      />
      <input
        type="password"
        placeholder="비밀번호"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
      />
      <button type="submit">로그인</button>
    </form>
  );
}

// LoginForm.test.js
import { render, screen, fireEvent } from '@testing-library/react';
import LoginForm from './LoginForm';

test('폼에 입력하고 제출할 수 있어요', () => {
  const handleSubmit = jest.fn();
  render(<LoginForm onSubmit={handleSubmit} />);

  // 아이디 입력
  const usernameInput = screen.getByPlaceholderText('아이디');
  fireEvent.change(usernameInput, { target: { value: 'testuser' } });

  // 비밀번호 입력
  const passwordInput = screen.getByPlaceholderText('비밀번호');
  fireEvent.change(passwordInput, { target: { value: 'password123' } });

  // 로그인 버튼 클릭
  const submitButton = screen.getByText('로그인');
  fireEvent.click(submitButton);

  // onSubmit이 올바른 데이터로 호출됐는지 확인
  expect(handleSubmit).toHaveBeenCalledWith({
    username: 'testuser',
    password: 'password123'
  });
});

테스트 작성 기본 패턴

모든 테스트는 3단계로 작성해요:

AAA 패턴

1
2
3
4
5
6
7
8
9
10
11
12
13
test('설명', () => {
  // 1. Arrange (준비)
  // 테스트에 필요한 것들을 준비해요
  const user = { name: '홍길동' };

  // 2. Act (실행)
  // 테스트할 동작을 실행해요
  const result = greet(user.name);

  // 3. Assert (검증)
  // 결과가 예상과 맞는지 확인해요
  expect(result).toBe('안녕하세요, 홍길동님!');
});

언제 테스트를 배워야 하나요?

🟢 지금 당장 배우면 좋은 경우

  • 실무 프로젝트를 준비해요
  • 팀 프로젝트를 진행해요
  • 코드 수정이 무서워요 (버그가 생길까봐)
  • 복잡한 기능을 만들고 있어요

🟡 나중에 배워도 되는 경우

  • React 기초가 아직 부족해요
  • 간단한 개인 프로젝트만 해요
  • 코드를 자주 바꾸지 않아요

결론: 테스트는 중요하지만, React 기초를 먼저 탄탄히 하세요!


테스트의 종류

실무에서는 여러 종류의 테스트를 작성해요:

1. 단위 테스트 (Unit Test)

  • 함수나 컴포넌트 하나만 테스트
  • 가장 빠르고 간단해요
1
2
3
test('add 함수', () => {
  expect(add(2, 3)).toBe(5);
});

2. 통합 테스트 (Integration Test)

  • 여러 컴포넌트가 함께 작동하는지 테스트
1
2
3
test('로그인 폼과 에러 메시지', () => {
  // 로그인 폼 + 에러 표시 컴포넌트
});

3. E2E 테스트 (End-to-End Test)

  • 실제 사용자처럼 전체 앱을 테스트
  • 느리지만 가장 확실해요
1
2
// Cypress나 Playwright 사용
// "로그인 → 상품 보기 → 장바구니 → 결제"

입문자는 단위 테스트부터 시작하세요!


정리

테스트란?

  • 코드가 제대로 작동하는지 자동으로 확인하는 코드
  • 버그를 미리 잡아주는 든든한 보험
  • 실무에서 필수 기술

장점

✅ 버그를 미리 발견 ✅ 자신감 있게 코드 수정 ✅ 문서 역할 ✅ 유지보수 쉬워짐

단점

❌ 작성하는 시간이 필요해요 ❌ 배울 게 조금 많아요 ❌ 작은 프로젝트에는 부담


다음 학습 로드맵

테스트를 더 배우고 싶다면?

1단계: 기초

  • Jest 기본 문법 (test, expect)
  • React Testing Library 기본
  • 간단한 컴포넌트 테스트

2단계: 실전

  • 사용자 이벤트 테스트 (클릭, 입력)
  • 비동기 테스트 (API 호출)
  • Mocking (가짜 데이터)

3단계: 고급

  • 통합 테스트
  • E2E 테스트 (Cypress)
  • 테스트 커버리지

추천 학습 자료

📚 공식 문서:

🎥 온라인 강의:

  • “React Testing Library 입문” 유튜브 검색
  • Kent C. Dodds의 Testing JavaScript

💻 실습:

  • 간단한 버튼부터 테스트 작성
  • 기존 프로젝트에 테스트 추가해보기

다음 포스트 예고

다음 시간에는 고급 패턴들을 가볍게 소개할게요!

Compound Components, Render Props, HOC 같은 패턴들을 실무에서 언제 어떻게 쓰는지 알아봐요.

“늦었다고 생각할 때가 가장 빠를 때입니다. 테스트로 안전한 코드 만들어보세요! ✅”


React 완벽 가이드 시리즈

  1. React란 무엇인가?
  2. 첫 React 앱 만들기
  3. useState - 클릭하면 바뀌는 화면
  4. Props - 컴포넌트끼리 대화하기
  5. useEffect - 컴포넌트 생명주기
  6. 조건부/리스트 렌더링
  7. Context API - Props 지옥에서 탈출하기
  8. Custom Hooks 만들기
  9. React Router 완벽 가이드
  10. 폼 처리와 유효성 검증
  11. React 성능 최적화
  12. 에러 바운더리와 Suspense
  13. 상태 관리 라이브러리
  14. 서버 상태 관리
  15. React와 TypeScript 맛보기
  16. Next.js 맛보기
  17. React 테스팅 입문 ← 현재 글
  18. 고급 패턴 소개
  19. 실전 프로젝트 아이디어
  20. React 배포하기

관련 자료

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.