이번 편에서는 React를 하면서 만나는 여러 이슈와 그 때에 고려할 수 있는 라이브러리를 간단하게 소개하겠습니다.

목차 간소화를 위해 하위에 넣은 분류도 있지만, 각각을 하나의 독립적인 분류로 보는 것이 좋습니다.

CSS 스타일링

React에서 CSS 스타일링은 CSS를 직접 사용하는 방법과 LESS, SASS가 대표적인 CSS Module, styled-components, emotion이 대표적인 CSS in JS 등 굉장히 다양한 방법이 있습니다.

최근에는 styled-components가 각광을 받고 있으며, 이전에는 SASS가 주로 쓰였습니다.

CSS 프레임워크

빠른 구현 혹은 편의성 등 위해서 CSS 프레임워크를 도입하고자 할 수 있습니다. 그런 때에는 Ant Design, Material UI, Semantic UI 등 라이브러리를 알아볼 수 있습니다.

컴포넌트 문서화

화면을 구성할 때에는 크게 하강식top-down 방식과 상향식bottom-up 방식이 있습니다. 하강식은 큰 그림을 먼저 그린 후 세부적으로 작은 그림을 그리고, 상향식은 작은 그림을 먼저 그린 후 그것을 조합하는 방식이라고 할 수 있습니다.

여러 컴포넌트를 작성하다 보면 확인 버튼과 같이 비슷비슷한 컴포넌트가 존재합니다. 그런 컴포넌트는 미리 작성해 어떻게 사용하는지 문서화를 해둔다면 편리할 것입니다. 이런 목적을 위한 것 중에는 storybook이 있습니다.

상태 관리State Management

상태 관리는 React 뿐만 아니라 어떤 프로젝트를 하더라도 어려운 이슈입니다.

React Hooks 등장 이전부터 널리 쓰이는 라이브러리로는 react-redux와 MobX가 있습니다. react-redux는 기본적으로 작성해야 할 코드가 많지만 보다 고수준의 상태 관리 코드를 작성할 수 있고 추가적인 다양한 최적화를 할 수 있으며, MobX는 라이브러리에게 상태 관리를 맡기지만 Decorator라는 확장문법을 이용해 적은 코드로 상태 관리를 할 수 있습니다.

  • react-reduxRedux를 React에서 적절히 사용할 수 있게 감싼 형태의 라이브러리입니다.

이 강좌의 중심인 React v16.8부터는 React Context와 React Hooks를 조합해 상태 관리를 유연하게 할 수 있습니다. 이를 기반으로 하면 대부분의 React에서의 상태관리 이슈는 해결할 수 있지만, React 사용경험에 따라 코드 퀄리티 격차가 클 수 있습니다.

라우팅Routing

여러 페이지를 가진 웹어플리케이션을 구현하려면 브라우저의 URL을 직접 다루어야 한다는 큰 어려움이 있습니다. 이와 관련해 가장 널리 쓰이는 라이브러리는 react-router-dom입니다. 사실상 표준 정도로 쓰이고 있습니다.

불변성Immutablity

불변성은 데이터를 변경할 수 없는 것이라고 할 수 있습니다. 게임으로 보면, 캐릭터가 데미지를 받아서 체력이 깎여야 한다면 해당 캐릭터의 체력을 깎는 것이 아니라 '체력이 깎인 새로운 캐릭터' 로 대체하는 느낌으로 볼 수 있습니다. 비효율적이라는 느낌이 들 수 있지만 React는 이렇게 해도 충분한 퍼포먼스를 낼 수 있으며 버그를 쉽게 잡거나 새로운 기능을 추가하는 등 여러 이점이 있다는 것을 증명한 라이브러리입니다.

JavaScript는 이러한 불변성을 문법적으로 지원을 하지는 않기 때문에 직접 혹은 라이브러리를 통해 개념적으로 사용해야 합니다. 널리 쓰이는 라이브러리로는 immutable.jsimmer.js가 있습니다. 하위호환성 이슈가 없다면 immer.js를 우선적으로 고려하는 것을 추천합니다.

서버측 렌더링Server-Side Rendering

React는 기본적으로 클라이언트측 렌더링Client-Side Rendering입니다. 게임으로 보면 화면을 그리는 프로그램(게임 클라이언트)을 만들기 위한 라이브러리라고 할 수 있습니다.

서버측 렌더링은 클라이언트측 렌더링과 반대로 화면을 그리는 방법을 서버측에서 제공하는 것입니다. 게임으로 보면 게임서버가 화면을 보내주는 것입니다.

프로젝트의 요구사항에 검색엔진최적화SEO, 초기화 시점 퍼포먼스 등 이슈가 있다면 서버측 렌더링을 고려해볼 수 있습니다.

대표적으로 Next.js는 서버측 렌더링을 중심으로 하는 React 기반 프레임워크입니다. 몇몇 규칙을 따라 프로젝트를 작성하면 알아서 서버측 렌더링을 할 수 있지만, Next.js를 기반으로 해도 해결하기 어려운 부분이 어려울 때에는 hydration 등의 방법을 고려해야 합니다.

코드 분할Code-Splitting

웹어플리케이션을 작성하다 보면 코드가 점점 늘어납니다. React를 기반으로 여러 컴포넌트와 파일로 분리해서 작성하기는 하지만 클라이언트(유저)에게는 결과적으로 1개의 스크립트 파일로 전달합니다. 프로젝트가 작다면 충분히 만족스러운 퍼포먼스를 낼 수 있겠지만 어느 순간부터는 퍼포먼스가 부족하다는 느낌이 들기 시작합니다.

이와 관련해서 React에서는 lazy라는 함수로 코드 분할을 지원합니다. 해당 모듈과 그 모듈이 사용하는 것을 적절히 분리해서 유저에게 전달하는 방식입니다. 현재로서는 서버측 렌더링에서는 사용할 수 없으므로 서버측 렌더링도 고려를 해야 한다면 loadable-components도 추가적으로 알아보는 것이 좋습니다.

  • 정확히 lazy 함수는 webpack을 통해 코드 분할을 지원합니다.

테스트Test

TDD, Unit Test, BDD, etc. 웹프론트엔드에도 테스트 요구가 늘고 있습니다.

테스트는 중요합니다. 테스트 코드를 작성하면 매번 인간이 직접 확인해야 하던 사항을 문서화 및 자동으로 체크할 수 있으며 이 외에도 여러 장점이 있지만, 웹프론트엔드는 데이터 구조 뿐만 아니라 컴포넌트가 화면에 어떻게 보이는지도 테스트를 해야 하기 때문에 테스트를 어떻게 해야 하는지 난해합니다.

React 기반 프로젝트는 주로 Jest, Enzyme 등 라이브러리를 이용해 테스트를 합니다. Jest는 React를 작성한 Facebook에서, Enzyme은 Airbnb에서 발표했습니다.

타입 시스템Type System

JavaScript는 타입을 명시하지 않는 언어입니다. 그러다 보니 프로젝트가 크다면 가독성, 유지보수성, 협업용이성 등 어려움을 느끼는 순간이 오며, 그런 때에는 타입을 명시하는 언어의 필요성을 검토해야 합니다.

React는 Flow(JavaScript에 타입을 명시하는 언어 중 하나)로 작성한 라이브러리입니다. 따라서 Flow를 지원하며 TypeScript, ReasonML 등 여러 언어를 지원합니다. React 초기에는 FlowTypeScript가 서로 경합을 펼쳤으나, 최근에는 TypeScript의 강력한 React 지원에 힘 입어 TypeScript를 기반으로 하는 프로젝트가 많습니다.

  • Flow는 타입 체커라고 하는 것이 조금 더 정확하지만, 이해편의상 언어로 표현했습니다.