
useState를 사용해 숫자를 세고, 조건에 따라 경고 메시지를 보여주었습니다.
하지만 컴포넌트 코드를 다시 한번 살펴볼까요?
화면을 그리는 코드(JSX)와 숫자를 계산하는 코드(Logic)가 한곳에 섞여 있습니다.src/hooks 폴더를 만들고, 컴포넌트에 있던 로직을 useCounter.ts라는 파일로 옮겨보겠습니다.
이 과정은 테스트 코드를 수정하지 않고 내부 구조만 바꾸는 import { useState } from 'react';
// [로직] 숫자를 관리하고 증가시키는 기능만 담당합니다.
export default function useCounter() {
const [count, setCount] = useState(0);
const increment = () => {
setCount((prev) => prev + 1);
};
// 컴포넌트에서 필요한 값과 함수를 반환합니다.
return {
count,
increment,
};
}Counter.tsx는 직접 계산하지 않고, 방금 만든 Hook을 가져다 쓰기만 하면 됩니다.import CountButton from './CountButton';
import useCounter from '../hooks/useCounter'; // Hook import
export default function Counter() {
// [수정] 직접 useState를 쓰지 않고 Hook을 사용합니다.
const { count, increment } = useCounter();
return (
<div>
<p>현재 숫자: {count}</p>
{/* 함수 이름이 handleClick에서 increment로 바뀌었음에 주의하세요 */}
<CountButton label="+" onClick={increment} />
{count >= 3 && (
<p style={{ color: 'red' }}>
숫자가 너무 커요!
</p>
)}
</div>
);
}useCounter가 잘 동작하는지 테스트해야 합니다.
그런데 Hook은 컴포넌트가 아니라서 render(<useCounter />)처럼 사용할 수 없습니다.
이때 필요한 도구가 바로 renderHook과 act입니다.src/hooks/useCounter.test.ts 파일을 만들고 아래 코드를 작성합니다.
이번에도 로그를 통해 상태 변화를 추적해 봅시다.import { renderHook, act } from '@testing-library/react';
import useCounter from './useCounter';
import { describe, test, expect } from 'vitest';
describe('useCounter Hook 동작 테스트', () => {
test('초기값은 0이며, increment 함수를 호출하면 값이 1 증가한다', () => {
// 1. Hook 렌더링 (가상 환경)
const { result } = renderHook(() => useCounter());
console.log(`[Step 1] 초기값 확인: ${result.current.count}`);
// 초기값 검증
expect(result.current.count).toBe(0);
// 2. 상태 변경 (act 사용 필수!)
console.log('[Step 2] increment 함수 실행');
act(() => {
result.current.increment();
});
console.log(`[Step 3] 변경된 값 확인: ${result.current.count}`);
// 3. 결과 검증
expect(result.current.count).toBe(1);
});
});npm test
[Step 1] 초기값 확인: 0
[Step 2] increment 함수 실행
[Step 3] 변경된 값 확인: 1
PASS src/hooks/useCounter.test.ts
PASS src/components/Counter.test.tsxact 함수 안에서 increment를 호출한 직후, result.current.count 값이 0에서 1로 변한 것을 확인할 수 있습니다.Counter.test.tsx도 여전히 git clone https://github.com/PROMLEE/my-tdd-app.git
cd my-tdd-app
git checkout part7act 함수로 감싸야 다음 시간에는 실제 웹 애플리케이션의 핵심인8편. 비동기 로직 테스트를 다뤄보겠습니다.