본문 바로가기

카테고리 없음

[React] React에서의 테스트 주도 개발(TDD) 가이드

반응형

1. TDD란 무엇인가?

테스트 주도 개발(Test-Driven Development, TDD)은 소프트웨어 개발 방법론 중 하나로, 실제 코드를 작성하기 전에 테스트 코드를 먼저 작성하는 방식입니다. TDD의 기본 사이클은 다음과 같습니다:

  1. 실패하는 테스트 작성 (Red)
  2. 테스트를 통과하는 최소한의 코드 작성 (Green)
  3. 코드 리팩토링 (Refactor)

이 과정을 "Red-Green-Refactor" 사이클이라고 부릅니다.

2. React에서 TDD를 적용하는 이유

React 애플리케이션에 TDD를 적용하면 다음과 같은 이점이 있습니다:

  • 버그 조기 발견 및 수정
  • 코드의 품질과 신뢰성 향상
  • 리팩토링 시 안전성 확보
  • 명확한 요구사항 정의 및 구현

3. React TDD 도구

React 애플리케이션의 TDD를 위해 주로 사용되는 도구들은 다음과 같습니다:

  • Jest: Facebook에서 만든 JavaScript 테스트 프레임워크
  • React Testing Library: React 컴포넌트를 테스트하기 위한 라이브러리
  • Enzyme: Airbnb에서 만든 React 컴포넌트 테스트 도구 (최근에는 React Testing Library를 더 많이 사용하는 추세)

4. React TDD 실습

간단한 카운터 컴포넌트를 TDD 방식으로 개발해보겠습니다.

4.1 실패하는 테스트 작성 (Red)

먼저, Counter 컴포넌트에 대한 테스트를 작성합니다.

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

test('Counter가 0부터 시작하고 증가 버튼을 누르면 1이 된다', () => {
  const { getByText } = render(<Counter />);

  expect(getByText('0')).toBeInTheDocument();

  fireEvent.click(getByText('증가'));

  expect(getByText('1')).toBeInTheDocument();
});

이 테스트를 실행하면 당연히 실패합니다. Counter 컴포넌트가 아직 없기 때문입니다.

4.2 테스트를 통과하는 최소한의 코드 작성 (Green)

이제 테스트를 통과할 수 있는 최소한의 코드를 작성합니다.

// Counter.js
import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <span>{count}</span>
      <button onClick={() => setCount(count + 1)}>증가</button>
    </div>
  );
}

export default Counter;

이제 테스트를 다시 실행하면 통과할 것입니다.

4.3 코드 리팩토링 (Refactor)

현재 코드는 이미 간단하지만, 실제 프로젝트에서는 이 단계에서 코드를 개선합니다. 예를 들어, 스타일을 적용하거나 더 복잡한 로직을 추가할 수 있습니다.

5. 복잡한 컴포넌트에 대한 TDD

실제 프로젝트에서는 더 복잡한 컴포넌트를 다루게 됩니다. 예를 들어, API 호출이 필요한 컴포넌트를 TDD로 개발해보겠습니다.

5.1 실패하는 테스트 작성 (Red)

// UserList.test.js
import React from 'react';
import { render, waitFor } from '@testing-library/react';
import UserList from './UserList';

// API 호출을 모킹
jest.mock('../api', () => ({
  fetchUsers: jest.fn(() => Promise.resolve([{ id: 1, name: 'John Doe' }]))
}));

test('UserList가 사용자 목록을 표시한다', async () => {
  const { getByText } = render(<UserList />);

  await waitFor(() => {
    expect(getByText('John Doe')).toBeInTheDocument();
  });
});

5.2 테스트를 통과하는 최소한의 코드 작성 (Green)

// UserList.js
import React, { useState, useEffect } from 'react';
import { fetchUsers } from '../api';

function UserList() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetchUsers().then(setUsers);
  }, []);

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

export default UserList;

5.3 코드 리팩토링 (Refactor)

이 단계에서는 에러 처리, 로딩 상태 표시 등을 추가할 수 있습니다.

6. TDD의 장단점

장점:

  • 높은 코드 품질과 신뢰성
  • 명확한 요구사항 정의
  • 리팩토링 용이성
  • 테스트 문서화 효과

단점:

  • 초기 개발 속도가 느릴 수 있음
  • 학습 곡선이 있음
  • 모든 상황에 적합하지 않을 수 있음 (예: 프로토타이핑)

React에서의 TDD는 높은 품질의 코드를 작성하는 데 도움이 되는 강력한 방법론입니다. 초기에는 시간이 더 걸릴 수 있지만, 장기적으로는 유지보수가 쉽고 버그가 적은 애플리케이션을 만드는 데 도움이 됩니다.

 

TDD를 시작할 때는 작은 컴포넌트부터 시작하여 점진적으로 복잡한 컴포넌트로 확장해 나가는 것이 좋습니다. 또한, 팀 전체가 TDD 방식에 동의하고 실천하는 것이 중요합니다.

 

React와 TDD를 함께 사용하면, 더 견고하고 유지보수가 쉬운 웹 애플리케이션을 개발할 수 있습니다. 여러분의 다음 React 프로젝트에서 TDD를 시도해보는 것은 어떨까요?

반응형