2021 리액트 생태계 현황

이글은 State of the React Ecosystem in 2021을 Dave Ceddia의 허락하에 번역한 글입니다. 궁금하신 점 있으시면 daveceddia.com를 참조하시기 바랍니다.


2021년 리액트 앱을 만들기 위한 최고의 방법은 무엇일까? 2016년으로 부터 무엇이 바뀌었을까? 모든 사람들이 어떤 라이브러리를 사용하고 있을까?

저는 2016 년에 리액트를 사용하고 가르치기 시작했습니다. 지난 몇 년 동안 리액트 자체에 큰 변화가 있었고 생태계도 상당히 발전했습니다.

2021년의 생태계 현황은 이렇습니다.

리액트 핵심 키워드: 이전과 비슷함

리액트를 2016년도와 비교 했을 때 핵심 기술은 지난 몇 년 동안 크게 변하지 않았습니다. 단방향 데이터 흐름, props, state, JSX의 개념은 여전히 리액트의 근간이며, 어떤 컴포넌트가 데이터를 소유해야하고 어떤 컴포넌트가 데이터를 표시 해야하는지 결정하는 것과 마찬가지로 설계를 컴포넌트로 분할 할 수 있는 것과 같은 작업은 여전히 ​​중요합니다.

저는 많은 라이브러리를 추가하기 전에 순수한 “바닐라” 리액트를 배우는 것을 여전히 지지합니다. (물론 저는 그것에 대해 을 썼지 만 진지하게 – 한 번에 하나씩 배우는 것이 훨씬 쉽습니다)

Hooks vs Classes: 대부분의 새로운 리액트 컴포넌트는 Hooks를 사용합니다

최근 몇년동안, 리액트에서 가장 큰 변화는 Class에서 Hooks로의 변화 입니다. Hooks는 16.8 (2월 2019)에 리액트에 추가 되었고, 사람들이 리액트 컴포넌트를 작성하는 표준 방식으로 되고 있습니다. 제가 처음 발표했을 때 작성한 Hooks 인트로를 확인할 수 있습니다. 지금은 이전과 동일하게 작동합니다.

처음에는 Hooks가 이상해 보입니다. 특히 프로그래밍을 한 적이 있다면 더욱 그렇습니다. 함수 호출 사이에 상태를 유지하는것 처럼 보이는 변수는 꽤나 마법처럼 보입니다. 하지만 이것은 마법보단 배열에 관한 것입니다.

Hooks의 작동방식에 익숙해지고 useState에 대한 이해가 생기면 그 다음 극복해야할 장애물은 useEffect Hooks입니다.

useEffect는 함수 구성 요소에서 수명주기 함수를 수행하는 방법입니다. useEffect의 정신적인 모델을 파악하는게 중요합니다. 그러면 그 다음 부턴 점점 쉬워집니다.

2021년 최고의 리액트 라이브러리

커뮤니티에서 좋아하는 라이브러리는 수년 동안 계속 바뀌었고 발전하고 있다.

Routing

React Router는 여전히 최고의 라우터입니다. (이런 이름을 가지고 있어도 리액트의 일부는 아닙니다.) 현재 v5 (거의 v6)이고 API는 이전 버전 이후로 조금 바뀌었다.

최상위 경로를 선언 하는것 보단 경로가 구성 요소(Component)입니다. 어디든 렌더 하세요.

v5 문서v6 문서는 여기서 확인 할 수 있습니다. v6 API는 실제로 v3의 거의 흡사하고 그렇게 사용되고 있습니다, 제 생각에는 좋은 API가 될 것 같습니다.

State Management

Redux는 여전히 많은 앱에서 30-50% 정도로 사용되고 있습니다. 공식적으로 새로 나온 Redux Toolkit도 훌륭합니다. Redux Hook와 함께 보일러 플레이트를 줄여주는데 많은 도움을 줍니다. Redux를 사용하실 예정이면 Redux Toolkit을 반드시 확인 하세요.

Redux는 사실상 예전 보다는 표준에서 멀어지고 있습니다. 더 많은 사람들이 React에 내장되어 있는 상태 관리가 많은 상황에서, 특히 단순하게 사용하기에는 충분히 좋다고 알고 있습니다.

또한 Redux를 대체 할 수 있는 몇가지 라이브러리리가 새로 나오거나 이전 부터 존재 하고 있었습니다.

MobX는 아마 React에 내장되어 있는 Context API외에 가장 인기있는 대안일 것입니다. Redux가 대부분 명시적이고 기능적이라면 MobX는 반대 접근 방식을 취합니다. ES6 프록시를 사용하여 변경 사항을 감지하므로 변경하는 데이터는 = 연산자를 사용하는 것 처럼 쉽게 할당이 가능합니다.

저는 프로젝트에서 MobX State Tree를 사용했고 꽤나 즐거운 경험이였습니다. 관리 할 상태가 많고 모델을 사용하여 그 주위에 구조를 생성하려는 경우에도 좋습니다.

RecoilZustand는 Redux를 대체 할 수 있는 가벼운 상태 관리 옵션이 될 수 있습니다.

어느 때 보다 선택할 수 있는 상태 관리가 많아지고 있습니다.

Context API

전역 상태가 거의 변경되지 않는 몇가지 항목(현재 유저, 현재 테마,현재 언어 등)으로 구성 되어 있는 경우 상태 관리 라이브러리가 꼭 필요하지 않을 수 있습니다.

Context API + useContext는 useReducer가 관리 하는 간단한 전역 상태를 전달하는 데 좋습니다.

Context API는 React 16.3에서 다시 정리 되었습니다. 오래된 contextType 문제는 사라졌으며 라이브러리 관리자가 아닌 한 Context를 피하는 것에 대한 오래된 지침은 한동안 사라졌습니다. useContext Hook는 사용하기 정말 좋습니다.

Context 또는 Redux를 사용할지 여부와 둘간의 차이점이 무엇인지에 대해 오랫동안 논의 되었습니다. Mark Erikson의 블로그에서 Context vs Redux의 심층 분석은 둘을 이해하는데 도움이 될 것입니다.

Data Fetching

Redux나 아님 전역 스토어에 모든 것을 저장하기 위한 데이터를 가져 오는 전략은 점점 사용 되지 않고 있습니다.

react-query는 데이터를 가져오고 로딩/ 성공/ 에러 상태를 관리 하는데 효과적입니다. Redux나 Context API 처럼 컴포넌트 간 props drilling없이 전역 데이터를 캐시화 하여 유지 관리 할 수 있습니다. 제 생각에는 추상화(아래 언급)를 가져올 수 있고, 보기에도 충분히 좋습니다.

Why react-query?

특정 라이브러리 보다는 패턴에 관한 것입니다. (swr도 하나의 대체제가 될 수 있습니다.)

ListPage / DetailPage를 기본적인 시나리오로 생각해보겠습니다. ListPage를 열면, 모든 데이터를 받습니다.

일반적으로 해당 데이터를 Redux 또는 다른 곳에 보관하여 DetailPage 중 하나를 클릭하면 해당 항목이 이미 불러져 올 수 있습니다. (하지만 사용자가 DetailPage 경로로 직접 들어온다면 어떻게 됩니까? 그렇다면 해당 항목을 일회성으로 가져와야 합니다.)

그런 다음 사용자가 뒤로가기를 클릭하면 다시 ListPage로 돌아 오지만 이미 데이터를 가지고 있으므로 그 데이터를 보여줄 수 있습니다.

모두 잘 동작하지만, 이안에는 예외 사항이 있습니다. 만약에 ListPage를 들어가서 DetailPage를 클릭하는 시간의 간격이 오래되면 어떻게 될까요? DetailPage에 있는 동안 일부 항목이 목록에 추가되면 어떻게 될까요?

해당 데이터를 언제 다시 가져와야 할까요? 그리고 전체 목록을 대체 할 수 있는 목록과 하나의 항목 만 대체 해야하는 단일 항목의 데이터 병합은 어떻게 처리 할까요? Redux에서는 reducer에서 핸들이 가능하지만 대부분 로직을 수동으로 넣어주어야 합니다.

이것은 pagination에 대한 구상을 하고, 페이지를 캐시 할지, 아니면 모든 페이지를 다시 가져올 지 등을 생각하면 모든 것이 훨씬 복잡해집니다.

제 생각에는 이 모든 것들이 “클라이언트 데이터 관리”에 속하며 우리는 이를 위해 오랫동안 일반 상태 관리 라이브러리를 사용해 왔습니다. 그리고 우리는 이러한 문제를 반복해서 해결해야 합니다. 그렇지 않으면 무시하고 문제가 발생하지 않기를 바라거나 문제가 발생할 때 패치합니다.

react-query와 같은 라이브러리는 문제를 다르게 분리합니다.

데이터를 가져올 것임을 알고 있으며 해당 데이터를 key (items나 아님 items[id])를 사용하여 전역적으로 캐시하려 한다는 것을 알고 있습니다. 또한 일정 시간 마다, 유저가 앱을 켜놓고 한동안 사용하지 않다가 다시 그 탭으로 돌아왔을때 등등 이런 상태에서 데이터를 업데이트 하고 싶어 한다는 사실을 알고 있습니다.

전역적으로 액서스 가능한 캐시에 저장되기 때문에 액서스가 필요한 모든 구성요소는 useQuery('items', fetchItems)를 호출하여 해당 데이터를 가져올 수 있으며 아직 사용할 수 없는 경우 자동으로 가져옵니다. 또한 로딩 / 에러 / 성공 상태도 가져올 수 있습니다.

Promise-returning 함수가 필요하기에 fetch, axios 또는 그 외에 비슷한 라이브러리와 함께 사용해야 합니다.

이것이 바로 추상화가 된 것 같다고 말했을 때의 의미 입니다. HTTP 호출을 위해 주로 사용하는 라이브러리들을 이용할 수 있습니다. 하지만 대부분 데이터를 가져 올때 일반적으로 자주 반복되는 비효율적인 작업을 처리하기 위해 react-query를 사용합니다.

State Machines는 찐입니다

XState는 복잡한 논리를 표현하는데 탁월한 상태 머신을 구축하기 위한 라이브러리입니다. 사실, 그것들은 그렇게 복잡하지 않은 논리에도 꽤나 좋습니다. 많은 boolean 값들을 핸들하거나 많은 변수들을 업데이트 할때 XState을 확인 하세요. egghead.io에 Kyle Shevlin의 course on XState의 강의가 있습니다.

그 외에도 Robot이란 대체제와 상태 머신이 어떻게 유용 할 수 있는지 알아보고 싶다면 제가 이전에 작성했던 build a confirmation modal flow 튜토리얼도 있습니다.

Bundlers

Webpack은 여전히 어디에서든 사용되고 있습니다. 이제 버전 5입니다. 구성 구문(config syntax)이 v2에서 v3사이에 많은 변경이 있었습니다.

대부분의 사람들은 Create React App을 사용하여 새로운 앱을 만들기 시작합니다. CRA는 매우 훌륭하며 실제로 사용자 정의를 따로 할 필요가 없는 한 Webpack으로 부터 사용자를 보호 합니다. 기본값도 매우 짜임새가 좋습니다. 맞춤 설정이 필요한 경우 craco를 확인 하시길 바랍니다.

간단한 데모를 만드는데 있어 CodeSandbox는 훌륭합니다. 그리고 https://react.new URL로 접속하면 새로운 프로젝트를 바로 시작할 수 있습니다.

Forms

Forms에 대한 이야기는 계속 진화하고 있습니다. 저는 몇 년 전에 redux-form을 사용했던 것을 기억하고, 그때 제가 키를 누를 때마다 앱이 어떻게 멈추는지 생각했던 것을 돌이켜 봤을 때, ‘모든 상태를 Redux에 유지’라고 생각했던 것은 결코 좋은 생각이 아니였습니다.

Formikreact-hook-form은 현재 Hook-form 에서 가장 선호되는 라이브러리인 것 같습니다.

Suspense

React에서 오랫동안 기다려온 Suspense 기능은… 아직도 기다리고 있습니다. 이 기능은 React에 있으며 사용해 볼수 있습니다. 하지만 이건 실험 모드에 있으며 이를 사용하여 프로덕션 코드를 빌드하는 것은 권장되지 않습니다. API는 계속 변경 될 수 있습니다.

Server Components

최신 발전은 서버에서 렌더링 되는 구성 요소이며 React 주변의 서버 측 프레임 워크와 결합됩니다. 이것들도 여전히 실험적입니다. 그래도 매우 멋지고 생태계가 상당히 바뀔 것이라 생각합니다. 자세한 내용은 React팀의 공식 발표 및 데모 비디오를 확인 하세요.

번역 하고 나서

2016년도의 React와 2021년도의 React는 생태계가 많이 달라졌다는 것을 느끼게 되었습니다. 이제는 전세계에서 React를 사용하여 프론트엔드 개발을 하고 많은 리액트 전용 라이브러리들이 나옴에 따라 개발에도 그 트렌드를 확인하고 방향성을 잡아야 하지 않을까 생각합니다.

필요한 라이브러리를 사용하여 반복되는 보일러플레이트 코드량을 줄여 side effect에 대비하고 적재적소에 효과적인 라이브러리를 사용하여 보다 가독성 좋은 코드를 작성하면 유지 보수에 도움이 되지 않을까 생각합니다.

처음으로 번역을 해서 아직 미숙하지만 많은 응원 부탁드립니다.

읽어 주셔서 감사합니다.


Written by@Chaehoon Lim
운동 코딩 맥주

GitHubTwitter