본문 바로가기
React

React에서 Test-Driven Development(TDD) 적용하기

by 굿센스굿 2024. 12. 16.
반응형

 

소프트웨어 개발에서 Test-Driven Development(TDD)는 안정성과 유지 보수성을 높이는 강력한 방법론으로 자리 잡았습니다. 특히 React와 같은 UI 라이브러리에서는 컴포넌트 기반 아키텍처와 TDD가 자연스럽게 잘 어우러집니다. 이 글에서는 React 프로젝트에 TDD를 적용하는 방법을 단계별로 알아보고, TDD를 통해 얻을 수 있는 이점과 함께 실제 개발 시의 팁을 제공합니다.


TDD란 무엇인가?

TDD는 테스트 주도 개발(Test-Driven Development)의 약자로, 코드를 작성하기 전에 테스트를 먼저 작성하는 소프트웨어 개발 방법론입니다. TDD는 다음과 같은 세 단계로 이루어집니다:

  1. Red: 실패하는 테스트를 작성합니다. (코드가 아직 없기 때문에 실패해야 합니다.)
  2. Green: 테스트를 통과하는 최소한의 코드를 작성합니다.
  3. Refactor: 코드를 리팩터링하여 품질을 개선하고 중복을 제거합니다. 테스트는 계속 통과해야 합니다.

이 과정을 반복하며, 코드는 테스트로 검증되고 점진적으로 개선됩니다.


TDD가 React 개발에 적합한 이유

React는 컴포넌트 기반 라이브러리로, 각 컴포넌트가 명확한 역할을 가지며 재사용 가능하도록 설계됩니다. 이러한 특성은 TDD의 세부적인 테스트 접근법과 잘 맞아떨어집니다. 주요 이유는 다음과 같습니다:

  • 컴포넌트 단위 테스트: React 컴포넌트는 작은 단위로 나눠지기 때문에 TDD로 테스트를 작성하기 용이합니다.
  • UI와 비즈니스 로직 분리: TDD를 통해 UI 컴포넌트와 로직을 테스트하면서 각각의 역할을 명확히 구분할 수 있습니다.
  • 안정성 확보: React 애플리케이션은 상태 관리와 사용자 이벤트 처리에 민감합니다. TDD를 통해 불안정한 코드와 오류를 사전에 방지할 수 있습니다.

TDD 환경 설정

React에서 TDD를 적용하기 위해 필요한 기본 환경을 설정해보겠습니다.

1. 프로젝트 생성 및 기본 설정

React 프로젝트를 생성하고 필요한 의존성을 설치합니다:

npx create-react-app tdd-example --template typescript
cd tdd-example

2. 테스트 라이브러리 설치

React에는 기본적으로 JestReact Testing Library가 포함되어 있습니다. 추가적인 설정이 필요하지 않지만, 이외의 라이브러리가 필요한 경우 설치합니다:

npm install --save-dev @testing-library/react @testing-library/jest-dom

3. 테스트 스크립트 실행 확인

package.json에 설정된 테스트 명령어를 실행하여 환경이 제대로 구성되었는지 확인합니다:

npm test

React에서 TDD를 적용하는 단계

React 컴포넌트를 TDD 방식으로 개발하는 구체적인 과정을 알아보겠습니다. 예제로 간단한 "할 일 목록(To-Do List)" 애플리케이션을 만들어 보겠습니다.

1. 요구 사항 정의

할 일 목록 애플리케이션의 요구 사항은 다음과 같습니다:

  1. 사용자는 새로운 할 일을 입력할 수 있어야 합니다.
  2. 입력된 할 일은 목록에 표시됩니다.
  3. 사용자는 할 일을 완료 상태로 표시할 수 있어야 합니다.

2. 실패하는 테스트 작성 (Red 단계)

첫 번째 요구 사항인 "사용자가 새로운 할 일을 입력할 수 있어야 한다"를 테스트합니다. App.test.tsx 파일을 작성합니다:

import { render, screen, fireEvent } from "@testing-library/react";
import App from "./App";

test("새로운 할 일을 추가할 수 있다", () => {
  render(<App />);

  const input = screen.getByPlaceholderText("할 일을 입력하세요");
  const button = screen.getByText("추가");

  fireEvent.change(input, { target: { value: "React 배우기" } });
  fireEvent.click(button);

  expect(screen.getByText("React 배우기")).toBeInTheDocument();
});

이 테스트는 아직 작성되지 않은 UI와 동작을 기반으로 합니다. 따라서 실행하면 실패합니다.

3. 최소한의 코드 작성 (Green 단계)

테스트를 통과시키기 위해 최소한의 코드를 작성합니다. App.tsx를 아래와 같이 구현합니다:

import React, { useState } from "react";

const App = () => {
  const [todos, setTodos] = useState<string[]>([]);
  const [input, setInput] = useState("");

  const addTodo = () => {
    setTodos([...todos, input]);
    setInput("");
  };

  return (
    <div>
      <input
        placeholder="할 일을 입력하세요"
        value={input}
        onChange={(e) => setInput(e.target.value)}
      />
      <button onClick={addTodo}>추가</button>
      <ul>
        {todos.map((todo, index) => (
          <li key={index}>{todo}</li>
        ))}
      </ul>
    </div>
  );
};

export default App;

이제 테스트를 실행하면 통과합니다.

4. 코드 리팩터링 (Refactor 단계)

리팩터링 단계에서는 중복된 코드나 불필요한 로직을 제거합니다. 예를 들어, 입력값을 다루는 로직을 별도의 커스텀 훅으로 분리할 수 있습니다.

import React, { useState } from "react";

const useInput = (initialValue: string) => {
  const [value, setValue] = useState(initialValue);
  const onChange = (e: React.ChangeEvent<HTMLInputElement>) => setValue(e.target.value);
  const reset = () => setValue("");

  return { value, onChange, reset };
};

const App = () => {
  const { value: input, onChange, reset } = useInput("");
  const [todos, setTodos] = useState<string[]>([]);

  const addTodo = () => {
    setTodos([...todos, input]);
    reset();
  };

  return (
    <div>
      <input
        placeholder="할 일을 입력하세요"
        value={input}
        onChange={onChange}
      />
      <button onClick={addTodo}>추가</button>
      <ul>
        {todos.map((todo, index) => (
          <li key={index}>{todo}</li>
        ))}
      </ul>
    </div>
  );
};

export default App;

리팩터링 후에도 테스트는 여전히 통과해야 합니다.


TDD의 이점

React에서 TDD를 적용하면 다음과 같은 이점을 얻을 수 있습니다:

  1. 신뢰성 향상: 테스트가 코드의 동작을 보장하므로, 자신감을 가지고 리팩터링할 수 있습니다.
  2. 디자인 개선: TDD는 자연스럽게 단일 책임 원칙(SRP)을 따르도록 유도합니다.
  3. 문서화: 테스트 코드는 애플리케이션의 동작 방식을 명확히 보여줍니다.
  4. 버그 감소: 예상하지 못한 버그를 사전에 방지할 수 있습니다.

결론

React 애플리케이션에서 TDD를 적용하면 코드 품질과 유지 보수성을 높이고, 개발자가 실수를 방지할 수 있습니다. "할 일 목록" 예제는 단순한 사례지만, 이를 시작으로 더 복잡한 애플리케이션에도 TDD를 적용할 수 있습니다.

TDD를 실천하는 과정은 처음에는 익숙하지 않을 수 있지만, 반복을 통해 생산성과 코드 품질이 눈에 띄게 향상되는 것을 느낄 수 있을 것입니다. 오늘부터 React 프로젝트에 TDD를 도입해보세요!

반응형