Develop
Jest로 Next.js 단위 테스트 작성 가이드 — 컴포넌트와 유틸 함수를 테스트하는 방법
Next.js App Router 프로젝트 환경에 테스팅 프레임워크인 Jest와 React Testing Library를 구성하고, 서버 컴포넌트 제약 하에서 클라이언트 컴포넌트 및 핵심 비즈니스 로직 유틸 함수를 안전하게 검증하는 노하우를 공유합니다.

- ·Next.js 13+은 Jest 설정을 자동화해주는 next/jest 변환기를 제공해 별도 바벨 설정 없이 Jest를 사용할 수 있다
- ·@testing-library/react는 내부 구현이 아닌 사용자 관점에서 컴포넌트를 테스트하는 철학을 따른다
- ·jest.mock()으로 외부 모듈이나 API 호출을 모킹해서 단위 테스트를 외부 의존성으로부터 격리할 수 있다
- ·msw(Mock Service Worker)를 쓰면 실제 네트워크 요청 레벨에서 API를 모킹할 수 있다
처음 Next.js App Router 환경에 테스팅 도구를 이식할 때, 비동기 서버 컴포넌트(Server Component)를 Jest 상에서 검증하려다 브라우저의 DOM API 모의 환경인 `jsdom` 내에 자바 환경변수나 Web API 사양이 누락되어 빨간 에러 메시지를 얻어 맞으며 큰 좌절을 겪었습니다. 이 트러블을 디깅한 후, 가상 서버 컴포넌트의 테스팅은 무거운 Cypress나 Playwright 같은 E2E 테스팅으로 덜어내고, Jest로는 결합 밀도가 낮은 유틸 함수와 클라이언트 비즈니스 컴포넌트 단위 테스트에 올인하는 실속형 검증 분할 전술을 수립하게 되었습니다.
1. 테스트 인프라 및 트랜스파일러 셋업
설정 피로도를 해소하는 Next.js 공식 Jest 개발 환경 빌드 방법
TypeScript와 리액트 마크업이 결합된 Next.js 환경에 바닐라 Jest를 직접 셋업하려 들면 바벨 트랜스파일러 설정이 꼬여서 컴파일 에러 콘솔에 치여 탈진합니다. 고맙게도 넥스트 진영은 next/jest 라는 전용 헬퍼 변환 팩을 제공하여, 별도 복잡한 .babelrc 가입 없이도 넥스트가 내부적으로 사용하는 고성능 SWC 컴파일러를 Jest 테스팅 러너 단에 다이렉트 연동시켜 줍니다. jest.config.ts 를 만들고 nextJest 로 감싸주기만 하면 귀찮은 빌드 가상 패스 매핑(paths)까지 깔끔하게 상속 처리됩니다.
2. 사용자 관점의 컴포넌트 검증
사용자 인터랙션을 시뮬레이션하는 Jest 기반 컴포넌트 테스트 요령
React Testing Library는 컴포넌트의 '내부 상태(state)가 잘 바뀌었는지' 따위의 세부 구현을 검증하는 안티 패턴을 경계하고, '사용자의 눈에 화면 버튼이 제대로 보이는지' 의 실제 UX 접근성 관점을 추앙합니다. screen.getByRole 이나 screen.getByText 처럼 HTML 웹 문서 정보의 시각적 요소를 타격해 요소를 획득하죠. 이후 @testing-library/user-event 모듈을 연동해 사용자가 실제로 마우스를 밀어 클릭하는 듯한 비동기 입력 인터랙션을 시뮬레이션하고, 그에 따른 화면 텍스트 변동 결과를 예측 검증하는 방식으로 견고한 테스트 명세서를 디자인해 나갑니다.
// components/SimpleButton.test.tsx - 사용자 관점의 Jest 테스트 코드 구현
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { SimpleButton } from './SimpleButton';
interface SimpleButtonProps {
onClick: () => void;
label: string;
}
describe('SimpleButton 컴포넌트 단위 검증', () => {
it('지정된 라벨 텍스트를 화면에 올바르게 인쇄하고 클릭 이벤트를 발송한다', async () => {
const mockClick = jest.fn();
render(<SimpleButton onClick={mockClick} label="저장하기" />);
// 1. 접근성 역할(role) 기반으로 사용자가 인지할 버튼 요소를 획득
const btn = screen.getByRole('button', { name: '저장하기' });
expect(btn).toBeInTheDocument();
// 2. 가상 클릭 인터랙션 발송
await userEvent.click(btn);
expect(mockClick).toHaveBeenCalledTimes(1);
});
});3. 의존성 통제와 API 모킹
Jest 모듈 모킹(Mocking) 기법을 활용한 단위 테스트 격리법
외부 타사 API 라이브러리나 Next.js 내장 useRouter 내비게이션 훅에 강하게 의존하고 있는 컴포넌트는, 테스트 가동 시점의 가상 렌더링 단계에서 정의되지 않은 함수 널 에러를 내뱉으며 사망합니다. 이때 jest.mock('next/navigation', ...) 구문을 활용해 훅이 반환할 목(Mock) 객체의 껍데기 정보를 강제 바인딩 매핑해 주어야 합니다. 실제 서버 호출 없이도 컴포넌트 순수 렌더링 동작만을 오롯이 격리 검증할 수 있는 단위 테스트 무균실이 마련됩니다.
네트워크 레벨을 모킹하는 MSW 결합을 통한 Next.js API 테스트
한 단계 더 진화하여, 컴포넌트 내부에서 발생하는 모든 원격 HTTP 네트워크 요청 전송 단계를 원천 캡처하여 모의 응답을 주입하고 싶다면 MSW (Mock Service Worker) 패키지를 연동하는 것이 정석입니다. 실제 브라우저와 Node 가상 머신 환경의 네트워크 레이어를 가로채어 작동하므로, 코드가 TanStack Query나 Axios를 쓰든 상관없이 미리 작성해 둔 가상 JSON 목 응답을 뱉어주게 통제하여, 실제 외부 서버가 뻗은 상태에서도 완벽하게 일관성 있는 배포 단위 테스트를 가동할 수 있습니다.
// mocks/handlers.ts - MSW를 이용한 가상 네트워크 요청 제어
import { http, HttpResponse } from 'msw';
export const handlers = [
// 백엔드 API 요청 주소를 가로채서 모의 JSON 데이터를 응답 주입
http.get('/api/users', () => {
return HttpResponse.json([
{ id: 1, name: '테스터 홍길동' }
]);
})
];자주 묻는 질문
Jest unit test 환경에서 next/image 컴포넌트가 'src' 속성 에러를 뿜으며 터집니다. 해결법이 있나요?+
Next.js의 Image 컴포넌트는 이미지 크기 강제 추론 등 복잡한 내부 프레임워크 링킹 로직이 들어있어 일반 테스팅 돔(jsdom)에서 실패할 수 있습니다. `jest.setup.ts` 파일 내에 `jest.mock('next/image', () => (props: any) => <img {...props} />)` 처럼 단순 HTML img 태그로 모킹 오버라이딩을 해두시면 깔끔히 해결됩니다.
Jest 실행 시 코드 커버리지(Coverage) 목표 수치를 꼭 100% 달성해야만 프로덕션 배포를 할 수 있나요?+
실무에서는 모든 단순 UI 레이아웃 코드까지 100% 테스트를 짜는 것은 과도한 인적 낭비이자 주객전도입니다. 데이터 포맷팅이나 정산 로직 같은 순수 비즈니스 유틸리티 함수나 상태 변경 액션 등 버그 발생 시 치명적인 핵심 영역 위주로 커버리지 70~80% 선을 타겟하여 유지하는 것이 생산성 면에서 합리적입니다.
관련 글
TypeScript strict 모드 설정 완벽 가이드 — tsconfig 옵션과 자주 만나는 타입 오류 해결
TypeScript 개발 시 런타임에 터지기 쉬운 치명적인 예외 버그들을 컴파일 타임에 안전하게 색출해 내는 strict 모드의 핵심 작동 구조와 자주 마주치는 null/any 에러 클리어 방법을 알기 쉽게 정리합니다.
GitHub Actions로 Node.js CI/CD 파이프라인을 구성하는 방법 — 빌드부터 자동 배포까지
Jenkins 없이 GitHub 저장소 안에서 CI/CD를 완결하고 싶다면 GitHub Actions가 가장 빠른 선택이다. workflow 파일 작성부터 Secrets 관리, SSH 배포까지 순서대로 정리했다.
ESLint, Prettier TypeScript 설정 가이드 — 팀 코드 스타일을 통일하는 방법
TypeScript 개발 프로젝트 환경에서 코드의 문법 결함과 논리 오류를 차단해 주는 ESLint와, 들여쓰기 및 괄호 서식을 맞춰주는 Prettier 간의 규칙 충돌을 미연에 봉쇄하고 팀의 스타일 표준을 완벽 강제하는 정석 파이프라인 설정을 정리했습니다.