![[React] 좋은 리액트 코드 작성을 위한 환경 구축하기](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbP72E%2FbtsH2kwlObW%2F4VlYLevZG1M0kBTzIA3k6K%2Fimg.png)
(해당 게시글은 모던 리액트 Deep Dive 를 참고해서 작성한 글입니다.)
ESLint를 활용한 정적 코드 분석
버그와 예기치 못한 작동을 방지하기 위해 여러 가지 방법이 있는데 그 중에 정적 코드 분석이 있다.
정적 코드 분석이란?
코드의 실행과는 별개로 코드 그 자체만으로 코드 스멜(잠재적으로 버그를 야기할 수 있는 코드)을 찾아내어 문제의 소지가 있는 코드를 사전에 수정하는 것
자바스크립트에서 가장 많이 사용되고 있는 정적 코드 분석 도구가 바로 ESLint 이다.
ESLint 살펴보기
ESLint 는 어떻게 자바스크립트 코드를 읽어서 분석할까?
- 자바스크립트 코드를 문자열로 읽는다.
- 자바스크립트 코드를 분석할 수 있는 파서(parser)로 코드를 구조화한다.
- 2번에서 구조화한 트리를 AST(Abstract Syntax Tree)라 하며, 이 구조화된 트리를 기준으로 각종 규칙과 대조한다.
- 규칙과 대조했을 때 이를 위반한 코드를 알리거나(report) 수정한다(fix).
ESLint 는 파서(parser) 기본값으로 espree 를 사용하여 분석하면 JSON 형태로 구조화된 결과를 얻을 수 있는데, 여기엔 단순한 내용만 파악하는 것이 아니라 코드의 정확한 위치와 같은 아주 세세한 정보도 분석해서 알려준다.
(https://astexplorer.net/ 에서 직접 파서를 사용하여 JSON 으로 바꿔준 결과를 확인해 볼 수 있다.)
그래서 코드를 espree 로 분석한 결과를 바탕으로 어떤 코드가 잘못되었고 어떻게 수정해야 정해야 되는데, 이를 ESLint 규칙(rules)이라 하며 특정한 규칙의 모음을 plugins 라고 한다.
eslint-plugin과 eslint-config
eslint-plugin
규칙들을 모아놓은 패키지이다.
- eslint-plugin-import: 다른 모듈을 불러오는 import와 관련된 다양한 규칙 제공
- eslint-plugin-react: 리액트 관련 규칙 제공
eslint-config
eslint-plugin 을 묶어서 완벽하게 한 세트로 제공하는 패키지이다.
- eslint-config-airbnb: 가장 손에 꼽는 eslint-config
- @titicaca/triple-config-kit: 한국 커뮤니티에서 운영되며, 일반적인 npm 라이브러리 구축 및 관리를 위한 시스템이 구축되어 있음
- eslint-config-next: next.js 기반으로 코딩하는 데 유용한 각종 기능 제공
주의할 점
1. Prettier와의 충돌
코드 포매팅을 도와주는 Prettier 가 ESLint 와 서로 충돌을 일으킬 수 있다. 해결 방법에는 두가지가 있다.
- 서로 규칙이 충돌되지 않게끔 규칙을 잘 선언
- 자바스크립트, 타입스크립트는 ESLint 에, 그 외 파일은 모두 Prettier 에 맞기기
- 자바스크립트에 필요한 Prettier 관련 규칙은 eslint-plugin-prettier 사용
2. 규칙에 대한 예외 처리, 그리고 react-hooks/no-exhaustive-deps
만약 일부 코드에서 특정 규칙을 임시로 제외시키고 싶다면 eslint-disable- 주석 사용한다.
리액트를 개발하다보면 eslint-disable-line no exhaustive-deps 를 사용해본 경험이 있을 것인데, 이 규칙은 useEffect 나 useMemo 와 같은 의존성 배열이 필요한 훅에 의존성 배열을 제대로 선언했는지 확인하는 역할을 한다. 일반적으로 의존성 배열이 너무 길어지거나, 빈 배열을 넣어 컴포넌트가 마운트되는 시점에 한 번만 강제로 실행되게 하고 싶을 때, 혹은 임의로 판단해 없어도 괜찮다고 생각될 때 등에 사용된다. 하지만 이것은 위험한 발상이며, 잠재적인 버그를 야기할 수 있다. 그러니 적절한 값을 넣어 규칙을 지키는 것을 권장한다.
리액트 팀이 권장하는 리액트 테스트 라이브러리
테스트란 개발자가 만든 프로그램이 코딩을 한 의도대로 작동하는지 확인하는 일련의 작업을 의미한다. 이를 통해 처음에 설계한 대로 프로그램이 작동하는지 확인할 수 있고, 버그를 사전에 방지할 수 있는 등 안정적인 서비스를 제공할 수 있는 원동력이 된다.
React Testing Library란?
리액트 애플리케이션을 테스팅하는 방법으로 가장 널리 사용되는 React Testing Library 가 있다.
React Testing Library 란?
DOM Testing Library를 기반으로 만들어진 테스팅 라이브러리로, 리액트를 기반으로 한 테스트를 수행하기 위해 만들어짐
DOM Testing Library 란?
순수하게 자바스크립트로 작성된 jsdom 라이브러리로, 자바스크립트 환경에서 HTML이 있는 것처럼 DOM 을 불러오고 조작할 수 있음
자바스크립트 테스트의 기초
기본적인 테스트 코드를 작성하는 방식은 다음과 같은 과정을 거친다.
- 테스트할 함수나 모듈 선정
- 함수나 모듈이 반환하길 기대하는 값을 적음
- 함수나 모듈의 실제 반환 값 적음
- 3번의 기대에 따라 2번의 결과가 일치하는지 확인
- 기대하는 결과를 반환한다면 테스트는 성공이며, 만약 기대와 다른 결과를 반환하면 에러를 던짐
테스트할 함수
function sum(a, b) {
return a + b;
}
테스트 코드 (Jest)
test.('두 인수가 덧셈이 되어야 한다.', () => {
expect(sum(1, 2)).toBe(3);
})
test.('두 인수가 덧셈이 되어야 한다.', () => {
expect(sum(2, 3)).toBe(3); // 에러
})
자바스크립트의 테스팅 프레임워크이며, 메타에서 작성한 오픈소스 라이브러리인 Jest 를 리액트에서 테스팅 라이브러리로 널리 쓰이고 있다. 작성한 테스트 코드를 실행하기 위해 npm run test
를 입력하여 결과를 얻을 수 있다.
리액트 컴포넌트 테스트 코드 작성하기
기본적으로 리액트에서 컴포넌트 테스트는 다음과 같은 순서로 진행된다.
- 컴포넌트를 렌더링한다.
- 필요하다면 컴포넌트에서 특정 액션을 수행한다.
- 컴포넌트 렌더링과 2번의 액션을 통해 기대하는 결과와 실제 결과를 비교한다.
1. 프로젝트 생성
create-react-app 에는 기본적으로 react-testing-library 가 포함되어 있다.
일반적으로 특정한 무언가를 지닌 HTML 요소 여부를 확인하기 위한 방법에는 크게 3가지가 있다.
- getBy... : 인수 조건에 맞는 요소 반환하며, 해당 요소가 없거나 두 개 이상이면 에러 발생, 복수개를 찾고 싶으면 getAllBy... 사용
- findBy... : getBy... 와 유사하지만 Promise 를 반환, 즉 비동기로 찾음. 두 개 이상이면 에러 발생해 findAllBy... 사용
- queryBy... : 인수 조건에 맞는 요소를 반환하는 대신 찾지 못하면 null 반환. 두 개 이상이면 에러 발생해 queryAllBy... 사용
2. 정적 컴포넌트
테스트를 원하는 컴포넌트를 렌더링하고 테스트를 원하는 요소를 찾아 원하는 테스트를 수행하면 된다.
- beforeEach : 각 테스트(it)를 수행하기 전에 실행하는 함수
- describe : 비슷한 속성을 가진 테스트를 하나의 그룹으로 묶음
- it : test 와 완전 동일하며, test 의 축약어
- testId : 리액트 테스팅 라이브러리의 예약어
3. 동적 컴포넌트
- setup 함수 : 내부에서 컴포넌트를 렌더링하고, 테스트에 필요한 button, input 등을 반환
- userEvent.type : 사용자가 타이핑하는 것을 흉내내는 메서드
- jest.spyOn : 어떠한 특정 메서드를 오염시키지 않고 실행 됐는지, 또 어떤 인수로 실행됐는지 등 실행과 관련된 정보를 얻고 싶을 때 사용
- mockImplementation : 해당 메서드에 대한 모킹 구현을 도와줌
사용자 정의 훅 테스트하기
react-hooks-testing-library 를 사용해 훅을 더욱 편리하게 테스트할 수 있다.
테스트를 작성하기에 앞서 고려해야 할 점
테스트 커버리지를 100% 끌어올릴 수 있는 상황은 드물다. 그리고 테스트 코드를 작성하기 이전에 애플리케이션에서 가장 취약하거나 중요한 부분을 파악하는 것이 중요하다. 그래서 애플리케이션에서 가장 핵심이 되는 부분부터 테스트 코드를 하나씩 작성해 나가는 것이 중요하다.
그 밖에 해볼 만한 여러 가지 테스트
- 유닛 테스트 : 각각 코드나 컴포넌트가 독립적으로 분리된 환경에서 의대된 대로 정확히 작동하는지 검증
- 통합 테스트 : 유닛 테스트를 통과한 여러 컴포넌트가 묶여서 하나의 기능으로 정상적으로 작동하는지 확인하는 테스트
- 엔드 투 엔드 : 실제 사용자처럼 작동하는 로봇을 활용해 애플리케이션의 전체적인 기능을 확인하는 테스트
마치며...
eslint 를 그동안 설정할 때, airbnb 를 사용하여 엄격한 규칙은 제거하는 방식으로 진행햇었는데 airbnb 말고 다른 eslint config 가 있다는 것을 알게 되었다. 또한 eslint config 와 pulgin 의 차이점을 모르고 있었는데 어떤 차이가 있으며 또한 eslint 를 직접 만드는 법도 알게 되었다.
다음으로 테스트는 이전에 프로젝트를 할 때 테스트 코드를 작성한 경험이 있었는데 그 때는 그냥 대부분 모든 코드들의 테스트를 작성했었다. 그 때 작성하면서 스스로도 좀 비효율적이라고 생각했었는데 책의 마지막에 단순히 테스트를 작성하는 것 보다는 취약하거나 중요한 부분을 작성하는 것이 더 중요하다고 했었다. 이런 내용과 책에 있는 테스트 방법을 다시 제대로 익혀 나중에 테스트 코드를 사용해보고 싶다.
'💜 리액트 > React' 카테고리의 다른 글
keydown 2번 실행되는 이유 (feat. 타입스크립트, NativeEvent) (0) | 2024.06.25 |
---|---|
[React] axios 로그인 유저 기능 구현 (feat. 토큰) (0) | 2024.06.17 |
개발자 도구로 React 애플리케이션 분석 (0) | 2024.06.15 |
컴포넌트 forwardRef 로 감싸기 (feat. 타입스크립트) (0) | 2024.06.15 |
[React] useEffect 클린업(Clean Up) 함수로 메모리 누수 방지 (2) | 2024.06.14 |
FE 개발자가 되고 싶은 짱잼이
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!