(번역) 리액트와 함께 일반적으로 사용되는 라이브러리들

sehyun hwang·2023년 2월 23일
117

FE 번역글

목록 보기
17/30
post-thumbnail

원문 : https://www.frontendundefined.com/posts/summaries/common-react-libraries/

리액트를 처음 사용하는 경우, 함께 사용하는 라이브러리가 너무 많아서 압도될 수 있습니다. 이 글에서는 여러분이 방향을 잘 잡을 수 있도록 라이브러리들에 대한 간략한 요약을 제공하려고 합니다. 모든 라이브러리를 일일이 나열하지는 않겠지만, 전체적인 모습을 알게 됨으로써 어떤 라이브러리가 있는지 파악하는 데 도움이 되길 바랍니다.

시작하기 전 참고 사항

라이브러리를 도입하기 전에 정말 필요한지 생각해보세요. 처음에는 라이브러리가 시간을 절약해줄 수 있지만, 시간이 지남에 따라 라이브러리 자체의 버그와 제약 때문에 더 많은 시간을 쏟게 될 수 있습니다.

목차

정리된 상태를 유지하기 위해 라이브러리를 목적별로 분류했습니다.

로직

이 섹션에서는 앱의 동작을 구현하기 위한 라이브러리를 소개합니다.

상태 관리

리액트에서 상태를 이용하는 가장 간단한 방법은 useState 훅을 사용하는 것입니다. 이렇게 정의한 상태는 훅이 정의된 컴포넌트 내부에서만 접근할 수 있는데, 앱이 커지면서 상태를 여러 컴포넌트 간에 공유해야 할 필요성이 생기게 됩니다. "상태 끌어올리기"나 컨텍스트 내에 상태를 저장하는 등 리액트 훅만을 이용해서 상태를 공유할 수도 있지만, 이 접근 방식은 문제가 있습니다. 만약 손자 컴포넌트에서 해당 값이 필요하다면 상태를 끌어올린 후 여러 컴포넌트 계층을 통해서 값을 전달해야 합니다. 리액트 컨텍스트는 상태 관리를 목적으로 만들어진 게 아니며, 부주의하게 사용할 경우 앱의 대부분에서 리렌더링이 발생하게 됩니다. 여러 컴포넌트간에 상태를 공유하기 위해 상태 관리 라이브러리가 필요한 이유도 여기에 있습니다.

Flux 패턴을 이용한 상태 관리

리액트에서 가장 오래되고 일반적인 상태 관리 방법은 전체 상태를 단일 "스토어"에 저장하고 이를 컴포넌트에 전달하면서 별도의 액션을 통해 상태를 업데이트하는 것입니다. 이는 페이스북에서 리액트 초기에 상태 관리 방식으로 도입한 flux 패턴이며, 가장 유명한 상태 관리 라이브러리인 리덕스(Redux)가 이 패턴을 사용하고 있습니다. 초기 버전의 리덕스는 여러 파일 설정이 필요했기 때문에 커뮤니티 내에서 "무겁다" 거나 "보일러 플레이트로 가득 차 있다"라는 평판이 자자했습니다. 하지만 리덕스 툴킷(Redux toolkit)의 출시로, 라이브러리에서 제공하는 유틸리티를 통해 많은 필수 설정값을 줄일 수 있게 되었습니다. 최근 커뮤니티에서는 flux 패턴을 몇 가지 커스텀 훅으로 구현한 Zustand가 점점 인기를 얻고 있습니다.

프록시 상태 관리

flux 패턴의 초기 대안은 상태가 JS proxy에 저장되는 프록시 상태 관리 패턴이었습니다. 프록시 패턴은 상태 변경을 감지하여 관련된 리액트 컴포넌트를 리렌더링 합니다. 변경 불가능한 상태를 갖는 스토어 기반의 상태 관리 방식과 다르게, 프록시 상태 관리 라이브러리에서는 관리되는 상태를 변경할 수 있습니다. MobX는 이 패턴을 구현한 가장 잘 알려진 상태 관리 라이브러리이며, Valtio는 몇 가지 훅을 기반으로 더 간단하게 작성된 라이브러리입니다.

아토믹 상태 관리

아토믹 상태 관리를 이용하면 아톰이라고 불리는 상태 조각들을 정의하고 이를 여러 컴포넌트에서 가져와서 사용할 수 있습니다. RecoilJotai가 이 패턴의 예시로 가장 잘 알려져 있습니다.

상태 머신

여러 단계의 애니메이션 작업과 같은 경우에는, 다른 컴포넌트의 상태나 일정 시간 간격에 따라 상태를 변경하거나, 또는 특정 조건에서 상태 변경을 막아야 하는 경우가 있습니다. 이러한 상태 전환은 useState와 useEffect 훅의 조합으로 처리할 수 있지만, 로직이 여러 훅에 분산되어 있어서 코드를 이해하기 어렵게 됩니다. 이때 유한 상태 머신을 도입하면 큰 도움이 될 수 있습니다. 가장 잘 알려진 자바스크립트 유한 상태 머신 라이브러리는 xstate입니다. xstate에는 리액트와 함께 사용할 수 있는 훅과 유틸리티가 포함된 전용 @xstate/react 패키지가 있습니다.

데이터 페칭

서버로부터 데이터를 다운받는 데이터 페칭은 프런트엔드 앱의 가장 일반적인 작업 중 하나입니다. 이를 수행하는 기본적인 방법은 내장된 Fetch API를 사용하는 것이지만, 많은 경우에 Fetch API가 어색하므로 Axios와 같은 대안을 사용하는 것을 더 선호합니다. 그러나 앱이 커지면서 더 많은 데이터를 다운로드하고, 더 많은 로딩과 에러 상태를 처리하고, 리페칭이나 캐싱, 그리고 사용자 경험 향상을 위한 낙관적 업데이트 등을 진행해야 합니다. 이러한 작업은 직접 구현하기가 매우 까다로우므로 데이터 페칭 라이브러리가 도움이 될 수 있습니다.

기존에 React Query로 알려진 TanStack Query 그리고 SWR은 데이터를 페치하고, 리페칭 및 캐싱을 다루는 리액트 훅을 제공합니다. 리덕스를 사용하는 경우, RTK query는 데이터 페칭을 위한 애드온입니다.

앞서 소개한 모든 라이브러리는 REST API와 함께 사용하도록 되어있습니다. REST API의 일반적인 문제는 백엔드 코드를 수정하지 않고는 변경할 수 없는 고정된 데이터 구조를 갖고 있다는 것입니다. GraphQL은 프런트엔드에서 원하는 데이터를 정확하게 선택할 수 있도록 함으로써 이러한 문제를 해결하는 것을 목표로 합니다. Apollo Client는 리액트와 함께 사용되는 가장 일반적인 GraphQL 구현체이며 기본적으로 많은 데이터 페칭 기능을 제공합니다.

유틸리티 함수 라이브러리

자바스크립트는 배열객체를 조작할 수 있는 많은 내장 메서드를 제공합니다. 하지만 이런 메서드는 객체 키 순환, 중첩된 데이터 구조 평탄화 또는 깊게 중첩된 구조의 불변 복제 등 특정 연산에 사용하기에 번거로울 수 있습니다. 이때 일반적인 연산을 위해 유틸리티 함수를 제공하는 Lodash와 같은 라이브러리가 유용할 수 있습니다.

함수형 자바스크립트를 선호한다면, lodash에는 변경 불가능하고 커링(currying)을 지원하는 fp variant도 있습니다. Ramda는 함수형을 우선으로 하는 대체 유틸리티 함수 라이브러리입니다.

클라이언트 사이드 라우팅

웹 초창기에는 모든 웹페이지가 고유한 URL을 가진 별도의 html 파일이었습니다. 프런트엔드 프레임워크의 부상과 함께, 단일 페이지에서 자바스크립트를 통해 다른 콘텐츠를 보여주며 여러 페이지의 느낌을 모방하는 단일 페이지 애플리케이션(SPA)이 인기를 얻게 되었습니다. SPA에서 사용자가 특정 뷰로 이동할 수 있도록, 별도의 html 파일을 로드하지 않고도 브라우저에서 History API를 사용하여 URL을 변경하면서 자바스크립트가 URL을 읽고 다른 콘텐츠를 표시하는 클라이언트 사이드 라우팅이 탄생했습니다.

React router는 사실상 리액트에서 클라이언트 사이드 라우팅의 표준이며, URL을 파싱하고 브라우저 히스토리를 조작하는 작업을 처리하여 URL과 이에 맞게 표시해야 하는 컴포넌트를 간단히 지정할 수 있도록 해줍니다.

인증

대부분의 웹 앱은 멀티 테넌트이며 동시에 여러 사용자가 함께 이용합니다. 이를 위해 각 사용자는 그들의 신원을 증명해야 하며, 일반적으로 비밀번호나 제삼자를 통해 사용자의 신원을 보장받는 소셜 로그인을 통해 이뤄집니다. 이것이 바로 인증이며, 이를 구현하려면 사용자를 생성하고, 로그인/로그아웃, 그리고 비밀번호 초기화 등의 공통된 기능 집합이 필요합니다. auth0의 유니버설 로그인과 같은 서비스는 이러한 기능 대부분을 제공하며 SDK를 통해 리액트에 쉽게 통합할 수 있습니다. 다른 선택지로는 오픈 소스이며 자체 호스팅이 가능한 SuperTokens가 있습니다.

폼 제어

상태가 변경될 때 리액트는 기본적으로 모든 자식 컴포넌트를 리렌더링 합니다. 이는 많은 제어 입력창이 있는 폼의 경우, 단일 입력창의 변경이 전체 폼의 리렌더링을 발생시킬 수 있다는 의미입니다. React Hook Form과 같은 라이브러리는 이러한 문제를 피하고 입력 유효성 검증을 위해 더 간단한 인터페이스를 제공합니다. 또 다른 대안으로는 가장 초창기 리액트 폼 제어 라이브러리 중 하나인 리덕스 폼을 계승한 React Final Form이 있습니다.

스키마 유효성 검증

유효성 검증은 사용자 입력을 시스템에서 허용하기 전에 부정확하거나 악의적인 데이터의 입력 위험을 줄이는 작업입니다. 중첩된 데이터 구조의 여러 입력값에 대해 유효성을 검증하려면 코드가 복잡해질 수 있습니다. 이때 스키마 유효성 검증 라이브러리인 yup 그리고 zod가 도움이 될 수 있습니다. 이 라이브러리를 통해 직접 구현한 유효성 검증 함수보다 훨씬 이해하기 쉽게 유효성 검증 규칙을 선언할 수 있습니다.

국제화

전 세계에는 수천 개의 언어와 다양한 시간, 날짜, 숫자 그리고 통화 형식이 있습니다. 주로 i18n으로 축약해서 표현하는 국제화는 애플리케이션에서 다양한 언어와 형태를 사용할 수 있도록 만드는 과정입니다. 이는 사용자 설정에 따라 앱 내에서 사용되는 텍스트와 데이터 형식을 바꾸는 과정을 포함합니다. 직접 구현할 수도 있지만, react-i18nextFormatJS와 같은 라이브러리는 국제화를 위한 코드와 확립된 규칙을 제공합니다.

날짜 라이브러리

자바스크립트의 날짜는 이상합니다. 게다가 날짜를 포매팅하거나, 문자열에서 파싱하거나, 시간 단위를 늘리거나 줄이는 방식으로 날짜를 조작하는 작업은 순수 자바스크립트에서 매우 번거로운 작업입니다. 이때 날짜 라이브러리와 날짜 작업을 위해 제공되는 헬퍼 함수가 도움이 될 수 있습니다. MomentJS는 가장 인기 있고 유용한 라이브러리였지만, 이젠 더 이상 활발히 개발되고 있지 않습니다. 그리고 Moment의 창시자는 Luxon이 비슷한 기능을 갖추고 있고 여러 가지 면에서 Moment를 개선(불변성, 트리셰이킹 지원, 네이티브 Intl기반) 했으므로 대신 사용할 것을 권장했습니다. 간단한 사용 사례에서는 date-fns 또는 Day.js가 더 좋은 선택지일 수 있습니다.

스타일링

이 섹션에서는 앱의 스타일링을 도와주는 라이브러리를 소개합니다. 웹에서의 스타일링은 CSS를 통해 이뤄지기 때문에 다음의 라이브러리는 CSS로 더 쉽게 작업하는 방법을 제공합니다.

CSS in JS

우리는 종종 리액트 컴포넌트 내부의 상태에 따라 다른 스타일을 적용하기를 원합니다. 리액트만으로 이 작업을 하려면 style 속성을 변경하거나 클래스를 변경해야 합니다. classnames나 더 작은 clsx와 같은 라이브러리가 클래스 이름 문자열을 더 쉽게 조작하도록 도와주지만, 자바스크립트와 CSS에서 클래스 이름을 동기화하는 것은 여전히 번거로운 작업입니다. CSS in JS 라이브러리는 컴포넌트와 함께 쉽게 CSS를 자바스크립트로 선언할 수 있도록 도와주며, 보간(interpolation)을 통해 상태나 속성에 따라 쉽게 변경할 수 있습니다. emotionstyled components가 가장 자주 사용되는 CSS in JS 라이브러리입니다.

CSS 유틸리티

일반적으로 우리는 CSS 파일을 빈 파일에서 시작하여 진행하면서 점점 규칙을 추가하는 방식으로 처음부터 작성합니다. 하지만 종종 유사한 모습을 가진 컴포넌트를 생성해야 할 때가 있습니다. 이 경우 새로운 선택자로 CSS 규칙을 중복하거나, 기존 CSS 선택자를 재사용하거나, 같은 모습의 컴포넌트에 모두 적용할 수 있는 새로운 제네릭 CSS 선택자를 생성할 수 있습니다. Adam Wathan는 두 가지 선택지 모두 좋지 않다고 주장하며 원하는 모습을 얻기 위해 믹스앤매치 시킬 수 있는 사전 정의된 스타일 조합을 사용할 것을 제안했습니다. Tailwind CSS는 이 접근 방식을 기반으로 구현되었습니다.

컴포넌트

이 섹션에서는 프로젝트에 추가하여 동작이나 스타일을 직접 구현할 필요 없도록 도와주는 리액트 컴포넌트를 소개합니다.

컴포넌트 라이브러리

때때로 UI 라이브러리라고도 불리며, 이 패키지들은 일반적으로 사용되는 UI 집합을 컴포넌트로써 제공합니다. MUI, Ant Design, Chakra UI 그리고 Mantine와 같은 라이브러리는 사전에 정의된 스타일을 이용하며, 각 라이브러리는 공통된 디자인 미학을 따르기 때문에 모든 컴포넌트가 서로 잘 어우러집니다. Radix UI는 직접 구현할 수 있도록 스타일링이 없는 컴포넌트를 제공합니다.

개별 컴포넌트

이 글에 모든 리액트 컴포넌트 패키지 목록을 각각 나열하는 것은 불가능합니다. 따라서 몇 가지 일반적인 문제를 해결할 수 있는 몇몇 패키지를 나열해 보겠습니다.

파일 업로드

웹에서 파일을 다루는 네이티브 방식은 파일 input 요소를 사용하거나 File API와 함께h="300">

파일이나 리스트의 아이템을 재정렬하는 경우, 드래그 앤 드롭은 훨씬 더 나은 사용자 경험을 제공합니다. 순수 HTML의 드래그 앤 드롭 기능은 요소를 draggable로 표시하고 드래그 이벤트를 수신하여 드래그된 요소에서 발생하는 작업을 처리합니다. React DnD 그리고 dnd kit과 같은 라이브러리는 코드를 직접 작성할 필요 없이 대부분의 드래그 앤 드롭 사용 사례를 다룰 수 있도록 미리 만들어진 컴포넌트와 컨벤션을 제공합니다.

애니메이션

웹에서의 애니메이션은 일반적으로 CSS transitionCSS animation을 활용합니다. 리액트에서 이를 다루려면 인라인 스타일이나 클래스 명을 통해 요소의 애니메이션 상태를 유지하고 추가해야 하므로 상당히 번거로운 작업일 수 있습니다. react-springFramer Motion 같은 라이브러리는 애니메이션을 훨씬 직관적인 방식으로 정의한 컴포넌트를 제공하여 이를 해결하고자 합니다. 또한 내장된 애니메이션 easing 기능을 통해 애니메이션을 더욱 자연스럽게 느껴지도록 합니다.

게다가 리액트에서 컴포넌트가 마운트 또는 언마운트될 때 진입 그리고 종료 애니메이션을 구현하는 것도 까다롭기 때문에 이를 간단히 처리하기 위해 React transition group이 존재합니다.

3개의 댓글

comment-user-thumbnail
2023년 2월 27일

그림이 ㅋㅋㅋㅋㅋ 귀엽네요

답글 달기
comment-user-thumbnail
2023년 3월 3일

This article is really amazing. Thanks for the sharing.

ThirtyOneToday.com

답글 달기
comment-user-thumbnail
2023년 3월 3일

Thanks for the information, I found a lot of interesting information here. Keep sharing such informative post. Partner Net HEB

답글 달기