이전 글에서 테스트 자동화 도구들의 개념에 대해 공부해보며, 현재 나의 학습 단계와 프로젝트 규모 등을 고려했을때 가장 잘 맞는 툴로 vitest와 cypress를 선택했다. 이제 실제로 코드를 작성하며 체득할 차례다. 내가 갖고있는 개인 프로젝트 중에 가장 가볍고 인터랙션이 직관적인 '포트폴리오 사이트'에 vitest부터 적용해보기로 했다.
직접 세팅하며 마주한 에러 해결 과정과 실무적인 고민을 기록해본다.✍️
의존성 설치 및 환경 설정
일단 터미널에 cli 명령어로 필요한 패키지를 설치했다.
npm install -D vitest @testing-library/react @testing-library/jest-dom @vitejs/plugin-react
그리고 vite.config.ts에 테스트 환경을 설정했다.
대규모 프로젝트나 모노레포 환경에서는 빌드 설정과 테스트 설정의 관심사를 분리하고, 프로덕션 빌드 성능을 최적화하기 위해 vitest.config.ts 파일을 별도로 분리하는게 일반적이다. 하지만 나의 포트폴리오 사이트처럼 가벼운 프로젝트라면, 과도한 파일 쪼개기보다 vite.config.ts 파일 하나로 통합 관리하는 것이 DX 측면에서 훨씬 실용적이라고 판단했다.
/// <reference types="vitest" />
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
test: {
environment: 'jsdom', // 브라우저 DOM 환경 에뮬레이션
globals: true, // describe, it, expect 등을 전역 변수로 허용
setupFiles: './src/test/setup.ts',
},
});
그런데 이걸 설정하니까 tsconfig.json에서 기존 레거시 설정들이 deprecated 되었다며 에러가 났다.😅
- Option 'target=ES5' is deprecated
- Option 'moduleResolution=node10' is deprecated
테스트 툴을 붙이려다 뜻밖에도 빌드 툴 체인의 고도화 작업(?)을 마주하게 되었고, tsconfig.json을 모던한 스펙에 맞춰 아래와 같이 수정하여 해결하였다.
{
"compilerOptions": {
"target": "ES2020",
"moduleResolution": "Bundler", // 모던 빌드 툴(Vite)에 최적화
"types": ["vitest/globals", "vite/client"] // 테스트 코드에서 describe, expect를 인식하도록 설정
},
"include": ["src", "*.ts"] // 루트의 ts 설정 파일 및 Vitest setup 파일까지 타입 감지 범위 확장
}
테스트 유틸 관리를 위한 환경 구축
vitest는 기본적으로 순수 자바스크립트 로직만 검사할 줄 아는 로봇이다. 하지만 우리는 리액트 컴포넌트를 테스트해야 하므로, "화면에 버튼이 존재하나? (toBeInTheDocument)" 같은 브라우저 DOM 전용 테스트 문법(Matcher)을 사용해야 한다. 기본형 vitest 로봇이 이 리액트 전용 문법들을 알아들을 수 있도록 '단어 사전'을 주입해 주는 과정이 필요한데, 이를 위해 /src/test/setup.ts파일을 만들고 아래 한 줄을 적어두었다. 이 설정을 거치고 나면 vitest가 리액트 컴포넌트의 상태를 자유자재로 검증할 수 있는 상태가 된다.
import '@testing-library/jest-dom';
이건 공통 설정을 다루는 파일이어서 /src/test 위치에 작성했고, 실제 파일 단위의 유닛 테스트 코드들(*.test.tsx)은 테스트 대상 파일과 같은 위치에 작성하기로 결정했다.
실무에서도 유닛 테스트 파일은 소스 코드 바로 옆에 나란히 두는 것이 가독성과 유지보수 측면에서 압도적으로 유리하여, 일반적으로 많이 사용하는 방식이라고 한다. 테스트 파일들을 별도 폴더에 따로 모아두면, 컴포넌트의 위치를 옮기거나 구조를 리팩토링할 때 테스트 코드의 경로가 전부 깨져 유지보수가 극도로 힘들어지기 때문이다.
명령어 스크립트 세분화
로컬 개발 환경과 향후 구축할 CI/CD 파이프라인을 고려해서, package.json에 실무 스타일로 스크립트를 나눠서 작성했다.
"scripts": {
"test": "vitest", // 실시간 감시 모드
"test:run": "vitest run", // CI/CD 환경용 단발성 실행
"test:ui": "vitest --ui", // 전용 대시보드로 시각적 디버깅 가능
}
이렇게 하고, 실제 테스트코드를 작성한 후에 npm run test 명령어를 입력해보았다. 터미널이 상시 대기 모드로 전환되며, 내가 코드를 수정할 때마다 연관된 테스트만 실시간으로 빠르게 재실행하고 결과를 출력해줬다.👍

npm run test:ui 명령어를 입력하면 @vitest/ui가 설치되고, 자동으로 브라우저를 통해 아래와 같은 대시보드를 오픈하여 시각적 디버깅을 가능하게 해준다. 내가 작성한 테스트 코드들이 트리구조로 보여지고, 어떤 요소의 어느 코드에서 실패했는지를 직관적으로 알 수 있어서 좋았다.👍

이번에 내 손으로 직접 테스트 환경을 구축해보며, 테스트 자동화의 핵심은 어떤 코드에 테스트가 필요할지 '판단'하는 능력이라는 것을 가장 크게 느꼈다.
프로젝트의 모든 컴포넌트와 코드에 전부 테스트를 심는 것은 엄청난 리소스 낭비이다. 중요한 것은 "버그가 생길 가능성이 가장 높은 곳" 혹은 "UX에 결정적인 영향을 미치는 핵심 인터랙션이나 기능"을 선별해내는 능력이다. 포트폴리오처럼 가벼운 사이트라면, 엉뚱한 정적 텍스트를 검증할 게 아니라, 유저가 누르는 핵심 버튼이나 데이터가 화면에 뿌려지는 로직을 방어해야 한다.
첫 단추인 Vitest 세팅은 성공이다. 이제 다른 핵심 기능들에 대한 테스트 코드를 작성하고, 실제 내 포트폴리오 화면에서 E2E 테스트가 되도록 cypress 구축을 해봐야겠다!

'💻 Frontend > JS, TS' 카테고리의 다른 글
| 테스트 자동화 프레임워크 입문 과정 (cypress 적용) (0) | 2026.05.28 |
|---|---|
| 테스트 자동화 프레임워크 개념 정리 (cypress, playwright, puppeteer) (0) | 2026.05.25 |
| 테스트 실행기 기본 개념 정리 (jest, vitest) (0) | 2026.05.22 |
| 쿠키 설정하기 (0) | 2025.07.04 |
| 교차상태 감지 웹 API - IntersectionObserver() (0) | 2025.04.23 |
