본문으로 건너뛰기

· 약 7분
Mitchell

기존 프로젝트는 Vue2와 내부적으로 Webpack을 사용하는 Vue CLI를 통해서 개발 및 프로덕션 빌드를 진행하고 있었습니다. 현재까지는 그 규모가 크지 않아 Vue CLI로 계속해서 개발해도 큰 문제가 있었던 것은 아닙니다만, Vue CLI가 유지보수 모드로 전환되면서 Vite기반으로 시작할 것을 권고하고 있으며 Vite를 통해 확실한 성능상의 이점과 설정에 대한 간편함 때문에 충분히 고려해볼만 했습니다.

· 약 16분
Mitchell

들어가기 전에

이전 글에서는 LoginForm 컴포넌트에 대한 단위테스트(Unit test) 코드를 작성하면서 리팩토링까지 해보았습니다. 이번에는 여러 컴포넌트의 상호작용에 대한 통합테스트를 작성하겠습니다.

정보

단위테스트에 대한 내용은 아래 링크를 통해서 확인하실 수 있으며, 이 글을 이해하는데에도 도움이 됩니다.
단위테스트

선수지식

이 글에서는 사용되는 기술에 대한 상세한 사용법은 설명하지 않습니다.

  • React
  • React-toastify
  • React Router, TanStack Query
  • Vitest, testing-library, msw
  • Vite

통합테스트란?

이름 그대로 통합적으로 테스트하는 개념의 테스트입니다. 이전 글에서는 LoginForm 컴포넌트에 대해 한정적으로 테스트를 구현하였었는데요. 그러한 작은 단위를 테스트하는 것을 단위테스트(Unit test)라고 합니다. 반면에 통합테스트(Integration test)는 여러 작은 컴포넌트로 구성된 큰 컴포넌트나 페이지 같이 통합된 형태를 테스트하는 것을 목적으로 합니다. 통합테스트의 주요 목표는 두 가지로 분류해 볼 수 있습니다.

  • 서버와의 통신에 대한 테스트
  • 컴포넌트 간의 상호작용에 대한 테스트

그래서 이번에는 서버와의 통신에 대한 테스트로 useLogin 커스텀훅을 테스트해보고 마지막으로 LoginFormuseLogin 등 컴포넌트와 훅 등이 상호작용하는 LoginPage에 대한 테스트를 진행하겠습니다. 테스트를 진행하면서 발생하는 트러블들을 해결하는 과정을 통해 msw 사용법에 대해서도 익히실 수 있습니다.

· 약 3분
Mitchell

개발환경 속에서 테스트하고, 빌드해보고 확인까지 다 해보았는데 CI에서 빌드 상의 에러가 발생하였습니다.

다름 아닌 테스트가 실패하였다는 내용이였는데요. 아래와 같은 메시지와 함께 실패합니다.

act(...) is not supported in production builds of React.

testing-library의 act는 Production 환경에서는 지원되지 않는다는 메시지입니다.

왜 Production에서는 지원되지 않을까?

Production용 빌드에서는 package.jsondevDependencies에 명시된 패키지는 모두 제외하고 빌드하게 됩니다. 실제 프로덕션용 코드에서는 필요가 없는 코드이기 때문입니다. 그렇기 때문에 환경변수 NODE_ENV가 Production인 경우 의도치 않게 테스트 환경에서 필요한 것들이 누락될 가능성이 있을 것으로 예측됩니다.

그래서 jest에서는 별도의 설정이 없다면 NODE_ENV를 'test'로 설정해 테스트를 돌리게 됩니다.

어떻게 해결해야 하나요?

위에서 바로 말했듯이 별도의 설정이 없다면, NODE_ENV는 'test'이기 때문에 에러가 발생하지 않습니다. 그러나 여러 실무에서는 다양한 목적(개발, QA, 프로덕션)에 따라 환경을 분리하고 그에 맞는 모드 설정을 가지고 있습니다.

저희도 그에 맞는 환경이 설정되어 있고, CI Shell 안에서 다음과 같은 메시지도 확인되었습니다.

#16 2.479 devDependencies: skipped because NODE_ENV is set to production

따라서 테스트가 돌아가는 환경 안에서만은 NODE_ENV를 'test'로 강제하도록 설정하면 됩니다. 아래와 같이 package.json 파일의 "test" 커맨드안에서 명시해주면 간단하게 해결할 수 있습니다.

package.json
{
...
"scripts": {
...
"test": "NODE_ENV=test jest",
...
}
...
}

· 약 13분
Mitchell

들어가기 전에

늘어가는 기능과 화면에 비례해서 버그 또한 늘어나기 마련입니다. 그런데 그 버그를 수정하면 또 다른 곳이 터져버리는 불상사가 눈앞에 펼쳐지게 됩니다. 사람은 실수를 하기 마련이고 그것을 줄이기 위해서는 더 많은 시간을 쏟아야 합니다. 이러한 이유 때문이더라도 테스트코드는 결국 필요하게 됩니다.

따라서 이 글에서는 React로 작성된 <LoginForm /> 컴포넌트에 대해 단위테스트를 작성하고, 그 과정에서 기존 코드의 문제점을 분석하고 테스트 가능한 코드로 리팩토링 하겠습니다.

· 약 8분
Mitchell

색상표현을 중심으로 비트마스킹, 시프트연산자를 활용하면 가장 효율적으로 색상의 표현을 변경할 수 있습니다. 이를 통해 쉽게 접할 수 없었던 비트마스킹과 시프트연산자에 대해 이해해볼 수 있습니다.

들어가며

프로젝트 내에서 색상을 palette 변수에 저장해서 필요한 곳에서 사용하고 있었습니다. 주로 Hexadecimal(16진수)로 표현된 값으로 저장하였는데요, 예를 들어 palette.white = '#ffffff' 이런식입니다.

특정 상황에서 엘리먼트에 색상이 제대로 반영되었는지 확인하기 위한 테스트 코드도 존재하였습니다. 아래의 예시에서는 element의 글자색상이 #ffffff인지 검사합니다.

// 엘리먼트에 포함된 CSS 속성들을 가져옵니다.
const styles = getComputedStyle(element)

expect(styles.color).toBe(palette.white)

그러나 테스트는 실패하게 되는데요. 왜냐하면 브라우저에서는 주어진 색상을 RGB로 변환하여 화면에 렌더링하기 때문입니다. 따라서 선언한 값(palette.white)과 계산된 값(styles.color)이 다르다는 테스트 결과를 받게됩니다.

· 약 17분
Mitchell

들어가기 전에

컴포넌트 단위 테스트를 작성할 때의 주요 관심사가 무엇일까요? 서버나 외부에서 데이터가 정상적으로 전달되었다는 것을 가정하고, UI가 의도대로 렌더링되는가에 관심을 둡니다.

그런데 통합테스트 단계에서는 그러한 데이터가 전달되는 상황을 Mocking 해야할 필요가 있습니다. 그래서 msw와 같은 라이브러리를 활용하여 하여 테스트를 서버로부터 오는 단방향 통신에 대해 Mocking 하여 통합테스트를 마무리할 수 있게 됩니다.

그러나 msw에서는 WebSocket과 같은 양방향 통신에 대한 지원이 존재하지 않아 채팅과 같은 실시간서비스의 통합테스팅을 작성하는데는 적합하지 않습니다. 따라서 Socket.IO가 제공하는 테스팅 예제를 활용하여 서버와의 양방향 통신을 Mocking 할 수 있는 방법을 공유해보겠습니다.

· 약 18분
Mitchell

대표적인 CSS in JS 라이브러리인 Emotion의 소스코드를 분석하면서 동작원리를 이해해보겠습니다. 동작원리를 이해하게 되면 장점을 극대화하고, 단점을 최소화하여 라이브러리를 효과적으로 쓸 수 있는 방법을 발견해낼 수 있습니다. 이 글에서는 @emotion/react와 cssProp를 중심으로 설명합니다.