React Native 테스트 스위트는 모두 통과(green)되었지만, 실제 기기에서 사용자는 “Continue”를 눌러도 아무 반응이 없다고 보고합니다. 컴포넌트 테스트는 모킹된 JavaScript 환경에서 버튼을 찾고 핸들러를 호출하며 예상된 화면을 확인했습니다. 하지만 네이티브 권한 prompt, 키보드 동작, 애니메이션, 플랫폼 API, 또는 실제 네비게이션 스택은 검증하지 못했습니다.
이러한 간극 때문에 팀은 잘못된 확신을 갖게 됩니다. React Native Testing Library 컴포넌트의 렌더링과 사용자 상호작용에 대한 반응을 테스트하는 데는 탁월하지만, 디바이스 테스트나 성능 측정을 대체할 수는 없습니다. 가장 확실한 전략은 각 레이어를 해당 레이어가 찾아낼 수 있는 오류를 검증하는 데 사용하는 것입니다.
목차
- 사용자 중심 테스트가 모든 것을 바꾸는 이유
- 실제로 작동하는 설치 및 설정 방법
- 핵심 API: Query와 Assertion 설명
- 컴포넌트, Hook, Navigation을 위한 실전 패턴
- Flaky Test 디버깅, CI 및 성능 체크
- 종합 정리 및 향후 방향
사용자 중심 테스트가 모든 것을 바꾸는 이유
흔한 테스트 실패는 코드를 작성하기 전부터 시작됩니다. 개발자가 컴포넌트의 props를 검사하거나, state에 직접 접근하거나, 대규모 snapshot을 비교하는 이유는 그 세부 사항들이 단언(assert)하기 쉽기 때문입니다. 테스트는 통과하지만, 리팩터링으로 사용자 경험은 그대로인데 컴포넌트 구조만 바뀌면 테스트 스위트가 깨집니다. 더 나쁜 점은, 단언문이 사용자가 실제로 봐야 할 내용을 정의하지 못했다면 사용자에게 보이는 동작이 잘못되었음에도 테스트는 계속 통과할 수 있다는 것입니다.
React Native Testing Library는 정반대의 접근 방식을 취합니다. 컴포넌트를 렌더링하고, 눈에 보이는 컨트롤을 통해 상호작용한 뒤, 사용자가 관찰할 수 있는 결과를 단언합니다. 이러한 접근 방식은 React Native Testing Library의 사용자 중심 예시뿐만 아니라, 테스트를 짧게 유지하고, 각 테스트가 한 가지에만 집중하며, 뷰와 비즈니스 로직 및 state를 분리하고, 내부 구현 세부 사항보다는 눈에 보이는 출력이나 accessibility helper를 우선시하라는 React Native의 테스트 가이드와도 일치합니다.

사용자가 의존하는 동작을 테스트하세요
로그인 폼이 요청이 진행되는 동안 제출 버튼을 비활성화한다고 가정해 봅시다. 취약한 테스트라면 disabled 특정 컴포넌트 인스턴스를 확인하거나 상태 변수가 변경됐는지 검증합니다. 더 강한 테스트는 접근 가능한 “Sign in” 컨트롤을 누르고, 로딩 인디케이터를 기다린 뒤, 에러 메시지나 목적지 화면이 나타나는지 확인합니다.
두 번째 테스트는 폼이 로컬 state를 쓰는지, reducer를 쓰는지, 커스텀 hook이나 다른 버튼 구현을 쓰는지 신경 쓰지 않습니다. 앱이 올바른 결과를 전달하는지에만 집중합니다.
실무 원칙: 사용자가 관찰할 수 없는 부분이라면, 컴포넌트 동작 테스트에 포함되어야 하는지 의문을 가져보세요.
접근성 레이블과 역할 기반 쿼리는 또한 더 나은 제품 code를 이끌어냅니다. 의미 있는 레이블을 노출하는 화면은 보조 기술로 사용하기 쉽고 테스트하기도 더 쉽습니다. 이 연결은 더 넓은 앱 사용자 경험을평가할 때 중요합니다. 테스트 가능성과 사용성은 종종 함께 향상되기 때문입니다.
통과한 테스트가 증명하지 못하는 것
사용자 중심 컴포넌트 테스트는 JavaScript가 예상 분기를 렌더링하고 시뮬레이션된 누름에 반응하는지 증명할 수 있습니다. 하지만 biometric prompt가 올바르게 열리는지, 네이티브 카메라가 사용 가능한 결과를 반환하는지, 결제 흐름이 플랫폼별 라이프사이클 동작에서도 유지되는지는 증명할 수 없습니다.
이 경계는 라이브러리의 약점이 아닙니다. 오히려 테스트 계층을 정직하게 유지해야 하는 이유입니다. 컴포넌트 동작에는 RNTL을 사용하고, 네이티브 통합, 실제 네비게이션, 권한, 인증, 결제, 핵심 앱 기능이 결과를 바꿀 수 있는 흐름에는 디바이스 기반 테스트를 남겨두세요.
실제로 작동하는 설치와 설정
최신 설정은 scoped 패키지로 시작합니다:
@testing-library/react-native
예전 react-native-testing-library npm 패키지 이름은 과거의 흔적으로 남아 있지만, 현재 프로젝트에서는 Testing Library 계열에서 관리하는 scoped 패키지를 사용해야 합니다. 이 프로젝트의 GitHub 리포지토리 설명은 이를 올바른 테스트 관행을 장려하는 React Native 유틸리티로 소개하며, 릴리스 히스토리를 보면 이 라이브러리가 정적인 헬퍼에 머물지 않고 React Native와 함께 계속 변화해 왔음을 보여줍니다.
기존 Jest 환경에 라이브러리를 설치하세요. Expo 프로젝트는 보통 Expo Jest preset을 사용하며, bare React Native 프로젝트는 React Native preset을 사용할 수 있습니다:
npm install --save-dev @testing-library/react-native jest
Expo라면, 프로젝트에서 이미 사용 중인 preset을 추가하세요:
{
"scripts": {
"test": "jest"
},
"jest": {
"preset": "jest-expo"
}
}
bare React Native 애플리케이션이라면 대신 해당 React Native Jest 설정을 사용하세요. preset을 프레임워크 버전에 맞춰 유지하세요. RNTL 문제처럼 보이는 많은 실패는 실제로 React renderer, Babel transform, Jest preset이 서로 맞지 않아 발생합니다.
setup 파일은 명시적으로 유지하세요
모든 테스트에서 mock을 반복하지 말고, 공통 환경 설정은 setup 파일에 넣으세요:
// jest.setup.js
import '@testing-library/react-native/extend-expect';
그다음 Jest에서 이를 참조하세요:
{
"jest": {
"preset": "jest-expo",
"setupFilesAfterEnv": ["<rootDir>/jest.setup.js"]
}
}
앱에서 React Navigation, Reanimated, gesture handling, safe-area context 또는 storage 모듈을 사용한다면, 테스트 환경에 꼭 필요한 mock만 설정하세요. 애플리케이션의 동작을 바꾸는 전역 mock은 모든 테스트를 통과하기 쉽게 만들지만, 테스트 스위트의 신뢰도는 떨어뜨립니다.
TypeScript도 마찬가지로 주의가 필요합니다. Jest가 다음 파일을 변환하도록 설정하세요: .ts 및 .tsx preset이나 Babel 설정을 통해 파일을 변환하고, 컴파일러가 테스트 타입을 인식할 수 있도록 유지해야 합니다. 로컬에서는 실행되지만 타입 체크를 거치지 않는 테스트는 잘못된 query 이름, 유효하지 않은 navigation 파라미터, 또는 안전하지 않은 mock 형태를 놓칠 수 있습니다.
릴리스 기록을 확인하면 오래된 설정 가이드를 진단할 때 유용합니다. 프로젝트에는 다음과 같이 127개의 릴리스가 있습니다, 2026-06-23에 태그된 v14.0.1이 있으며, 2024-11-27에 출시된 v12.9.0에서는 React Native 0.77 및 Expo 52에 대한 공식 지원이 추가되었습니다. 2025년 3월 v14 alpha 라인에서는 기존의 deprecated된 React Test Renderer 대신 Universal Test Renderer로 전환하며 React 19 전용 지원을 준비했습니다. 자세한 내용은 다음에서 확인할 수 있습니다: RNTL 릴리스 히스토리, 따라서 앱 버전을 확인하지 않고 오래된 튜토리얼의 renderer 의존성을 그대로 복사하지 마세요.
실용적인 Jest 기반을 마련하려면, 다음 내용을 참고하여 설정을 비교해 보세요. JavaScript 유닛 테스트 가이드, 그 다음 navigation 및 native mock을 추가하기 전에 작은 컴포넌트 테스트를 먼저 실행하세요.

핵심 API: Queries 및 Assertions 설명
RNTL 테스트는 query가 사용자가 보고, 찾고, 조작할 수 있는 요소와 일치할 때 신뢰할 수 있습니다. API 자체는 작지만, 구현 세부 사항을 드러내는 selector를 선택하면 테스트 통과 결과가 오해를 불러일으킬 수 있습니다.
시작하기 render:
const screen = render(<LoginForm />);
사용자와 가장 관련성이 높은 query를 선택하세요. 컴포넌트가 지원한다면 접근성 중심의 query를 우선 사용하고, 텍스트가 동작의 핵심이라면 visible text를 사용하세요. 그리고 testID 의미 있는 사용자용 selector가 없거나 안정적인 integration hook이 필요한 경우에만 사용하세요.

타이밍과 의도에 따라 query 선택하기
각 쿼리 유형은 다음과 같은 목적을 가집니다:
- 동기식 존재 확인: 사용하세요:
getByRole,getByText, 또는 다른getBy요소가 이미 존재해야 하는 시점의 쿼리입니다. 요소가 없으면 즉시 테스트가 실패합니다. - 비동기식 등장 확인: 사용하세요:
findByRole또는findByText렌더링이나 상호작용으로 인해 비동기 업데이트가 발생하는 경우에 사용합니다. - 부재 확인: 사용하세요:
queryByText또는queryByTestId요소가 없을 수 있어 예외 대신 null 결과를 기대하는 경우입니다. - Fallback 셀렉터: 사용하세요:
getByTestId의도적으로 사용합니다. 복잡한 컨트롤에 안정적인 hook을 제공하지만, 앱 전체의 접근성 레이블을 대체해서는 안 됩니다.
특정 이벤트 테스트의 경우, fireEvent.press 가 더 직접적입니다:
fireEvent.press(screen.getByRole('button', { name: 'Save' }));
사용하세요: userEvent 설치된 버전이 더 현실적인 상호작용 시퀀스를 지원하는 경우에 사용합니다. 어느 쪽이든 결과 UI를 assert하세요:
expect(await screen.findByText('Saved')).toBeTruthy();
핸들러 assertion은 공개 컨트랙트가 이벤트 콜백인 컴포넌트에 적합합니다. 사용자 흐름이 동작한다는 유일한 증거로는 약합니다.
스냅샷보다 구체적인 assertion을 선호하세요
좋은 assertion은 화면을 설명합니다:
expect(screen.getByText('Account created')).toBeTruthy();
expect(screen.getByRole('button', { name: 'Continue' })).toBeEnabled();
접근성 상태, 선택 상태, 눈에 보이는 유효성 검사 피드백도 확인할 수 있습니다. 내부 구현을 검사하는 것은 피하세요:
expect(screen.getByTestId('submit-button').props.onPress).toBeDefined();
해당 assertion은 prop의 존재 여부를 증명할 뿐, 기능이 제대로 작동하는지를 보장하지는 않습니다. 작고 의도적인 snapshot은 구조적 변화를 잡아낼 수 있지만, 규모가 큰 navigation이나 screen snapshot은 불필요한 리뷰를 양산하고 원인 모를 업데이트를 무심코 승인하게 만들 위험이 있습니다.
Testing Library 패키지는 더 넓은 범위의 testing-library npm 조직에 속해 있습니다. 현재 활발히 관리되는 패키지는 @testing-library/react-native이며, 버전은 2026년에 출시된 13.3.3입니다 프로젝트의 repository 정보에 따르면입니다. 공통된 query 컨벤션은 플랫폼 간 활용에 도움이 되지만, 어떤 assertion이 제품의 실제 동작을 나타낼지는 결정하지 않습니다.
Jest 컴포넌트 테스트 관행에 대한 더 폭넓은 비교는 다음 가이드를 참고하세요: React unit testing 가이드. RNTL은 여전히 JavaScript로 렌더링되는 컴포넌트 경계까지만 지원합니다. Native permissions, 실제 navigation stack, 디바이스 키보드, 프레임 타이밍, 메모리 동작 등은 컴포넌트 mock을 늘리기보다 E2E나 성능 측정 도구를 사용해야 합니다.
아래 영상에서 실제 상황에서의 query 및 assertion 워크플로우를 확인할 수 있습니다.
컴포넌트, Hook, 네비게이션을 위한 실전 패턴
유용한 테스트 스위트는 애플리케이션의 구조를 따라야 합니다. Presentational 컴포넌트는 직접적인 동작 테스트가 필요하고, Hook은 제어 가능한 입출력이 필요하며, 네비게이션은 충분히 현실적인 Provider가 필요합니다. 또한 Native module은 실제 기기 검증과 명확히 구분되는 Mock이 필요합니다.

Presentational 컴포넌트
컴포넌트 테스트는 공개된 인터페이스(Public contract)에 집중하세요:
const onSelect = jest.fn();
render(
<PlanCard
title="Team"
description="Shared workspace"
onSelect={onSelect}
/>
);
fireEvent.press(screen.getByRole('button', { name: 'Choose Team' }));
expect(onSelect).toHaveBeenCalled();
레이블은 UI와 정확히 일치해야 합니다. 중요한 점은 테스트가 사용자나 접근성 서비스와 동일한 방식으로 컨트롤을 찾아내고, 유의미한 시각적 결과나 콜백을 확인하는 것입니다. 모든 자식 컴포넌트를 기본적으로 Mocking하지 마세요. 테스트하려는 동작을 방해하는 무거운 작업이나 관련 없는 경계 지점만 Mocking하세요.
커스텀 Hook의 경우, 다음을 사용하세요: renderHook 설치된 RNTL 버전에서 지원하는 경우:
const { result } = renderHook(() => useSearch());
await act(async () => {
await result.current.submit('query');
});
expect(result.current.status).toBe('success');
Hook 테스트는 앱 전체를 재현하는 것이 아니라 네트워크나 레포지토리 경계를 제어해야 합니다. 화면은 별도로 테스트하여 Hook의 상태가 유효한 UI로 이어지는지 확인하세요.
네비게이션과 비동기 데이터
네비게이션 동작을 위해 실제 NavigationContainer 모든 네비게이션 메서드를 Mocking하는 것보다 작은 테스트용 네비게이터를 사용하는 것이 더 가치 있는 경우가 많습니다. 보이는 컨트롤을 누르고, 목적지 콘텐츠가 나타날 때까지 기다린 후, 새 화면의 출력을 검증하세요. 직접적인 useNavigation 타입화된 라우트를 디스패치하는 역할만 하는 작은 버튼에는 여전히 mock이 적합하지만, 라우트 등록, 파라미터 또는 중첩된 navigator 동작까지 검증할 수는 없습니다.
API 또는 repository 응답을 mock하고, 화면을 렌더링한 뒤, 로딩 상태를 확인하고, 요청을 resolve한 다음 성공 또는 에러 출력을 확인하는 방식으로 동일한 원칙을 적용해야 합니다. 이때 findBy 기대하는 요소가 나타날 때까지 기다리는 queries를 사용하고 거절된 요청(rejected requests)을 명시적으로 처리하세요. 그렇지 않으면 컴포넌트가 의도한 분기에 도달하지 못했음에도 테스트가 통과될 수 있습니다.
Native module 모킹
AsyncStorage, 권한, 카메라, 생체 인식 및 platform API에 대한 mock은 결정론적인 JavaScript 테스트를 위해 유용합니다. 하지만 이것이 native 기능이 작동한다는 증거는 아닙니다. mock 동작을 모듈 컨트랙트에 가깝게 유지하고, 테스트 간에 호출을 초기화하며, happy path뿐만 아니라 실패 응답도 포함하세요.
| 시나리오 | RNTL 권장 | E2E 검증 필요 |
|---|---|---|
| 폼 유효성 검사 및 에러 메시지 표시 | 예 | 일반적으로 해당 없음 |
| mock된 repository를 통한 로딩, 성공, 에러 UI | 예 | 중요한 프로덕션 플로우용 |
| 등록된 스크린 간의 네비게이션 | 네, 테스트 네비게이터 사용 시 가능 | 제스처, 딥링크, 플랫폼 동작이 중요할 때 가능 |
| AsyncStorage 상태 결정 로직 | 네, 제어된 mock 사용 시 가능 | 앱 실행 및 영속성이 네이티브 라이프사이클과 상호작용할 때 가능 |
| 카메라, 생체 인식, 권한 또는 플랫폼 API | JS 폴백 및 분기 로직 | 네, 실제 기기 또는 유사 기기에서 가능 |
| 레이아웃, 렌더링 성능 및 네이티브 code | 아니요 | 네, 디바이스나 전문 도구를 사용하면 가능합니다 |
실용적인 경계는 이렇습니다. 의존성을 mock 처리하여 JavaScript 로직을 테스트한 다음, 디바이스 테스트를 실행해 의존성의 실제 동작을 확인하세요.
Flaky Test 디버깅: CI 및 성능 체크
Flaky test는 대개 제어되지 않는 시간, 공유 상태, 또는 UI와 경합하는 assertion 때문에 발생합니다. 타임아웃을 늘리기 전에 어떤 조건이 문제인지 먼저 파악하세요. 타임아웃만 늘리면 스케줄링 문제를 숨기면서 테스트 스위트만 느려질 수 있습니다.
사용하세요: findBy 업데이트 후 나타날 것으로 예상되는 요소에는 다음을 사용하세요. waitFor 상태 조건이나 mock 호출에는 다음을 사용하세요. fake timers가 활성화된 경우, 상호작용이 필요한 시점에 타이머를 진행시킨 후 실제 타이머로 복구해야 합니다. act warning은 React가 예상된 상호작용 경계 밖에서 업데이트를 감지했음을 의미합니다. 누락된 await를 해결하거나, 경고를 무시하는 대신 사용자 상호작용 또는 타이머 flush를 수정하세요.
CI 실패를 재현 가능하게 만들기
신뢰할 수 있는 CI 작업은 lockfile로부터 설치하고, 로컬에서 사용한 것과 동일한 Jest command를 실행하며, mock 상태를 격리합니다. 테스트 사이에 mock 호출을 초기화하고, 모듈 수준의 상태가 동작에 영향을 준다면 모듈을 리셋하며, 실행 순서에 의존하지 않도록 하세요. Jest caching은 피드백 속도를 높여주지만, 의존성이나 설정이 변경되면 적절한 cache invalidation이 필요합니다.
CI에서만 발생하는 실패는 컴포넌트를 다시 작성하기 전에 환경 비교가 필요합니다. Node, 패키지 매니저, Jest worker 설정, 타이머 구성 및 환경 변수를 확인하세요. 가능한 경우 로컬에서 동일한 명령어를 재현한 뒤, 실패하는 테스트를 차이점이 드러나는 최소한의 상호작용 단위로 축소하세요.
Observability는 또 다른 격차를 메워줍니다. 앱 상태 모니터링은 실제 기기 및 native 통합과 관련된 실패를 포함하여, 모킹된 컴포넌트 테스트로는 재현할 수 없는 프로덕션 에러 context를 제공합니다.
보안이 중요한 여정에는 두 번째 경계가 필요합니다. 컴포넌트 테스트로 검증과 상태 전환을 확인한 다음, 핸드오프 및 native 동작에 대한 디바이스 레벨 커버리지를 추가하세요. 일회성 code 흐름의 경우, 다음 가이드를 참고하여 SMS 인증 흐름을 테스트하는 방법 해당 통합이 여정의 일부인 경우를 대비하세요.
성능은 단언(assertion)이 아닌 측정의 대상으로 다루세요
기능 테스트는 리스트가 렌더링되는지 확인할 수 있습니다. 하지만 테스트 런타임이 노이즈를 추가하기 때문에, 리팩토링이 렌더링 시간이나 횟수를 변경했는지 신뢰성 있게 판단할 수는 없습니다. Reassure는 특정 시나리오의 값을 측정하고, 변동성을 줄이기 위해 시나리오를 반복하며, 유의미한 변화를 보고하기 전에 통계 분석을 적용합니다. Reassure의 성능 테스트 문서에는 CI 및 pull-request 리뷰에 적합한 보고 기능도 포함되어 있습니다.
“렌더링이 특정 임계값 이내에 완료되어야 한다”와 같은 고정된 단언(assertion)은 피하세요. CI 워커가 바쁘면 오탐(false failure)이 발생할 수 있고, 임계값이 너무 높으면 실제 성능 저하를 놓칠 수 있습니다. 회귀 신호를 파악하려면 반복 측정을 사용하고, 비교 결과 유의미한 차이가 발견되면 컴포넌트와 디바이스 프로필을 점검하세요.
측정 규칙: 기능 테스트는 동작이 올바른지를 확인합니다. 성능 도구는 측정된 시나리오가 변했는지를 확인합니다. 이 두 질문을 명확히 분리하세요.
종합 및 향후 방향
React Native Testing Library는 테스트 전략 중 넓고 빠른 계층에 속합니다. 컴포넌트 동작, 가시적인 상태 변화, 접근성 결과, 유효성 검사, 모킹된 데이터 상태, 그리고 JavaScript 컴포넌트 간의 통합을 다뤄야 합니다. 이러한 테스트는 사용자가 관찰할 수 있는 것에 집중해야 하며, 실패 시 거대한 렌더링 트리 전체가 아닌 특정 동작을 지목하도록 만드세요.
모킹이 실제와 다를 수 있는 흐름은 더 작은 디바이스 기반 계층에서 보호해야 합니다. React Native의 테스트 개요 RNTL은 완전한 React Native 런타임을 제공하지 않으며 네이티브 기능을 테스트할 수 없다는 점을 명시합니다. 따라서 인증, 결제, 핵심 앱 기능과 같은 크리티컬한 흐름은 컴포넌트 테스트와 함께 Detox 같은 E2E 도구를 병행할 것을 권장합니다.
실질적인 마이그레이션 경로
기존 테스트 스위트를 한 번에 모두 다시 작성할 필요는 없습니다.
- 가치 있는 비즈니스 테스트는 유지하세요. 순수 상태 및 도메인 로직은 명확한 피드백을 줄 수 있는 집중적인 유닛 테스트로 옮기세요.
- 먼저 구현 세부 사항에 대한 검증을 제거하세요. props나 내부 상태 확인 대신, 화면에 보이는 출력값, 접근성 상태, 그리고 상호작용 결과로 검증 방식을 바꾸세요.
- 스냅샷 크기를 줄이세요. 리뷰어가 이해하고 유지보수할 수 있는 스냅샷만 남기세요.
- 네이티브 경계 영역의 커버리지를 추가하세요. 모킹(mock)된 주요 모듈마다, 여전히 검증이 필요한 디바이스 동작이 무엇인지 파악하세요.
- 핵심 사용자 여정(critical journeys)을 보호하세요. 인증, 결제, 핵심 네비게이션, 권한 요청 등 네이티브 동작이 결과에 영향을 줄 수 있는 흐름에 E2E 커버리지를 추가하세요.
- 민감한 화면은 별도로 측정하세요. Jest 실행 시간으로 추측하는 대신, 리스트, 피드, 비용이 큰 렌더링 경로에 대해 반복적인 성능 비교를 수행하세요.
릴리스 신뢰도를 높이려면, 테스트 스위트를 다음 항목과 연결하세요. CI/CD 통합 테스트 또한 배포 전 적절한 테스트 레이어를 거쳐야 합니다. 검증된 JavaScript 또는 에셋 수정 사항을 사용자에게 전달해야 하는 경우, Capgo를 통해 CapacitorJS 및 Electron 애플리케이션의 특정 채널로 서명된 웹 번들을 전달할 수 있으며, 이때 롤아웃 제어 및 롤백 보호 기능을 사용할 수 있습니다. 이 배포 워크플로우가 React Native의 디바이스 테스트를 대체하는 것은 아니지만, '실행되는 레이어에서 동작을 검증한다'는 동일한 원칙을 보여줍니다.
핵심은 React Native Testing Library가 앱 전체를 테스트할 수 있느냐가 아닙니다. 불가능하며, 공식적인 경계(boundary)를 이해하는 것이 유용합니다. 진짜 중요한 질문은 각 주요 리스크를 노출할 수 있는 환경에서 테스트가 실행되고 있는가입니다.
Capgo는 검증된 JavaScript 및 에셋 변경 사항을 CapacitorJS 및 Electron 팀을 위한 제어된 배포 프로세스로 연결합니다. 타겟 채널 지정, 롤아웃 가시성 및 롤백 보호 기능을 제공합니다. 자세한 내용은 Capgo 를 방문하여 컴포넌트, E2E 및 CI 테스트 워크플로우와 어떻게 함께 사용할 수 있는지 확인해 보세요.