뉴욕타임스는 최근 React 18로의 업그레이드를 진행하면서 기존에 사용하던 Enzyme 테스트 라이브러리를 React Testing Library(RTL)로 마이그레이션하는 대규모 프로젝트를 수행하였습니다. 이번 전환은 단순한 라이브러리 변경을 넘어 테스트 철학 자체를 변화시키는 작업이었으며, 수백 개의 테스트 파일을 변환하는 데 수개월이 걸렸습니다. 이를 통해 테스트의 유지보수성 및 신뢰성을 높이고, React의 최신 기능과의 호환성을 확보하는 것이 주요 목표였습니다.
1. Enzyme에서 React Testing Library로 전환한 이유
기존에 뉴욕타임스는 Enzyme을 활용해 React 컴포넌트를 테스트하고 있었습니다. 하지만 Enzyme의 경우 컴포넌트의 내부 구현 세부 사항에 크게 의존하는 테스트 방식을 사용하므로, 컴포넌트 내부 코드 변경 시 테스트가 쉽게 깨지는 문제가 있었습니다.
React가 18 버전으로 업그레이드되면서 Concurrent Mode(동시성 모드) 등 새로운 기능이 도입되었고, 이로 인해 Enzyme은 최신 React와의 호환성 유지에 어려움을 겪고 있었습니다. 특히, React 팀이 공식적으로 Enzyme을 지원하지 않기로 결정하면서 장기적인 유지보수가 불가능하다는 판단이 내려졌습니다.
이에 따라 뉴욕타임스는 **React Testing Library(RTL)**로의 마이그레이션을 결정했습니다. RTL은 사용자의 실제 상호작용을 기반으로 테스트를 수행하는 방식이기 때문에 React 애플리케이션의 동작을 보다 현실적으로 검증할 수 있으며, 내부 구현 변경에도 강한 테스트 코드를 작성할 수 있는 장점이 있습니다.
2. 마이그레이션을 위한 전략
뉴욕타임스는 마이그레이션을 진행하기 위해 다양한 접근 방식을 고려했으며, 크게 세 가지 방법을 검토했습니다.
- 일괄 처리(Bulk Migration) 방식
- 모든 테스트 파일을 한 번에 변환하는 방법
- 빠른 전환이 가능하지만, 문제가 발생할 경우 원인을 추적하기 어려움
- 대규모 프로젝트에서 실용성이 떨어질 가능성이 있음
- 팀 합의 기반 순차적 전환(Consensus-based Migration) 방식
- 팀 내에서 변환 우선순위를 정하고, 논의를 거쳐 점진적으로 변환
- 협력적인 접근 방식이지만, 변환 속도가 느리고 일정이 길어질 가능성이 있음
- 점진적 마이그레이션(Incremental Migration) 방식
- 테스트 파일을 개별적으로 변환하여 점진적으로 진행
- 기존 코드베이스에 대한 영향이 최소화되며, 변환 중에도 기존 기능을 유지할 수 있음
- 협업이 용이하고, 리스크를 효과적으로 관리할 수 있음
뉴욕타임스는 **세 번째 방법(점진적 마이그레이션 방식)**을 선택하여, 기존 Enzyme 기반 테스트를 하나씩 React Testing Library로 변환하는 방식으로 프로젝트를 진행했습니다.
3. 마이그레이션 과정에서 직면한 문제 및 해결 방법
1. Enzyme의 shallow rendering 제거
Enzyme에서는 shallow()
함수를 이용하여 컴포넌트의 하위 요소를 렌더링하지 않는 방식으로 테스트를 수행하는 경우가 많았습니다. 하지만 React Testing Library는 이러한 shallow rendering을 지원하지 않으며, 대신 사용자 입장에서 컴포넌트를 렌더링하고 상호작용하는 방식을 권장합니다.
해결 방법:
shallow()
기반 테스트를 RTL의render()
함수로 변환- 불필요한 내부 상태 검증 대신 화면에 표시되는 요소를 중심으로 테스트를 수정
2. find()
및 instance()
메서드 제거
Enzyme에서는 .find()
및 .instance()
메서드를 사용하여 특정 컴포넌트의 인스턴스를 가져오고 내부 메서드를 호출하는 방식의 테스트가 많았습니다. 하지만 React Testing Library에서는 DOM 요소에 대한 접근을 중심으로 테스트하도록 설계되어 있기 때문에, 이런 방식의 테스트를 그대로 사용할 수 없었습니다.
해결 방법:
.find()
대신getByText()
,getByRole()
,queryByTestId()
등의 RTL 메서드를 활용하여 요소를 찾도록 변경instance()
를 통한 내부 상태 접근을 없애고, UI에 나타나는 결과값을 기반으로 테스트하도록 수정
3. 비동기 코드 처리 (act()
문제)
React Testing Library는 React의 **비동기 업데이트(예: 상태 변경, API 응답 처리 등)**에 대한 테스트를 보다 직관적으로 작성할 수 있도록 돕지만, 기존 Enzyme 테스트에서는 act()
를 명시적으로 사용하지 않는 경우가 많았습니다.
해결 방법:
- 비동기 상태 업데이트를 감지할 수 있도록
await waitFor()
사용 act()
사용이 필요한 경우 명확하게 적용하여 React 상태 변경이 완료된 후 테스트가 실행되도록 보장
4. 마이그레이션 결과 및 기대 효과
뉴욕타임스는 점진적 마이그레이션 방식을 통해 기존 Enzyme 기반 테스트를 React Testing Library로 성공적으로 변환하였습니다. 이를 통해 다음과 같은 주요 개선 효과를 얻었습니다.
- 테스트의 유지보수성이 향상됨
- 내부 구현이 아닌 사용자 경험을 기반으로 한 테스트 작성이 가능
- React 업데이트 시 테스트가 깨질 가능성이 줄어듦
- 테스트 신뢰성이 높아짐
- 실제 사용자 인터랙션을 기반으로 한 테스트 작성으로 인해 버그를 사전에 방지할 가능성이 커짐
- React 최신 기능과의 호환성이 보장됨
- React 18 및 이후 버전과 완벽하게 호환되는 테스트 환경을 구축
결론: 왜 React Testing Library인가?
뉴욕타임스의 마이그레이션 사례를 통해, React Testing Library가 단순히 새로운 도구가 아니라, React 애플리케이션 테스트 방식 자체를 변화시키는 철학적인 전환임을 확인할 수 있습니다.
Enzyme처럼 컴포넌트 내부 구현에 의존하는 방식이 아니라, 사용자 입장에서 애플리케이션이 어떻게 동작하는지를 검증하는 방식으로 테스트를 작성하게 됨으로써, 보다 신뢰성 높은 테스트 코드를 유지할 수 있습니다.
React Testing Library로의 전환을 고려하는 개발자라면, 단순한 API 변경이 아닌, 테스트 패러다임 자체를 어떻게 개선할 수 있을지를 고민해야 한다는 점을 기억해야 합니다.
TI Tech Lab 이유진 연구원
Add comment