Redux가 필요하다는 것을 언제 알 수 있나요?

이 글은 Simon Schwartz의 "When do I know I’m ready for Redux?"를 번역한 글입니다.

이 포스팅은 당신이 Redux 사용을 고려해야 하는 시점이 언제인지, Redux가 해결해준 우리의 문제가 무엇인지, 우리가 찾아낸 이점들은 무엇인지에 대한 것입니다. 이 글은 우리가 React 앱을 키워나가면서 배운 것들을 기반으로 쓰였습니다.

만약 당신이 상태가 무엇인지 모르거나, Redux에 대해 들어본 적이 없다면 앞으로의 내용이 별로 와닿지 않을 것입니다. 이러한 개념들에 대해 생소한 분들을 위해 간단한 개요가 아래에 있습니다. 생소하지 않다면 본문으로 넘어가시면 됩니다.

상태란 무엇인가요?

상태는 단지 데이터입니다. 현재 사용자의 이름이나, 로그인 여부나, 페이지가 로딩 중인지에 대한 것들과 같은 애플리케이션 데이터의 집합이라고 생각하세요. 앱의 상태는 사용자의 동작이나 API 응답 등에 의해 바뀔 수 있습니다. 앱은 어떤 UI를 보여주어야 할지 결정하기 위해 상태를 읽어오게 됩니다.

Redux는 무엇인가요?

Redux는 앱의 상태를 관리하기 위한 도구입니다. React 앱에서는 매우 일반적으로 쓰입니다.

우리가 Redux를 사용하기로 한 이유

섣부른 최적화는 만악의 근원이다 — 도널드 커누스

이것이 제가 소프트웨어를 만들 때면 따르는 격언입니다. 우리가 Australian Broadcasting Corporation을 위한 React 앱을 만들기 시작하면서 우리 앱의 상태를 지역 컴포넌트 상태를 이용해 관리하기로 한 이유죠.

처음 몇 주 동안은 이게 잘 통했지만 앱에 기능을 추가할수록 상태 관리에 문제가 생겼습니다.

우리 앱에서 상태의 변화를 추적하기가 정말 힘들어졌습니다. 우리 앱의 상태를 변경하는 함수는 여러 React 컴포넌트들에 흩어져 있었습니다. 몇몇 컴포넌트들은 상태를 관리하는 함수들 때문에 너무 비대해졌습니다. 모든 것이 지저분해졌고 코드 베이스가 점점 커다란 그릇에 담긴 스파게티처럼 보이기 시작했습니다.

그러면 앱이 커지면서 제가 겪은 것들을 차례차례 보여드리겠습니다.

1일 차

우리는 React의 지역 컴포넌트 상태에서 시작했습니다.

React는 '일방향 데이터 흐름'을 가집니다. 컴포넌트가 상태를 props로 내려보내 준다는 뜻입니다.

우리는 최상위 컴포넌트에 상태를 설정하고 props로 데이터를 내려주었습니다. 쉽죠.

5일 차

우리는 기능들을 좀 더 추가했습니다. 불행하게도 몇몇 컴포넌트들이 상태를 공유해야 했지만 부모-자식 관계는 아니었습니다.

다행히도 우리는 상태를 끌어올리는(Lifting) 것으로 이를 해결했습니다. 상태(와 이를 변경하는 함수들)를 가장 가까운 조상(컨테이너 컴포넌트)까지 끌어올렸다는 뜻이죠. 우리는 함수들을 컨테이너 컴포넌트에 바인드한 다음 이들을 props로 내려보냈습니다. 자식 컴포넌트들은 부모 컴포넌트의 상태 변경을 일으킬 수 있고 트리 내의 다른 모든 컴포넌트가 업데이트될 겁니다. 좋아요.

20일 차

우리는 몇 가지 기능을 더 추가했고 앱의 상태 흐름은 이렇게 보이기 시작했습니다...

당신도 볼 수 있듯이 상태가 업데이트 되고 앱 전체로 퍼뜨려지는 방식이 점점 복잡해지기 시작했습니다. 우리가 앱을 키우면서 고통스러웠던 부분들은 아래와 같습니다:

  • 컴포넌트의 구조는 앱의 UI를 따릅니다. 앱의 상태는 UI를 따를 필요가 없습니다.
  • 앱 상태의 형태가 여러 컴포넌트에 걸쳐 퍼져있습니다.
  • 상태를 바꾸는 함수가 여러 컴포넌트에 걸쳐 퍼져있습니다.
  • 앱 상태의 개요를 파악하기 위해서는 마음속에 앱 구조에 대해 모델을 가지고 있어야 합니다.
  • 여러 단계의 컴포넌트에 걸쳐 같은 props를 전달해야 합니다.
  • 디버깅할 때 상태 변경을 추적하기가 점차 힘들어졌습니다.

당신이 위의 문제들에 맞닥뜨린다면, Redux를 사용할 때가 된 것입니다.

Redux는 어떻게 작동하나요?

모든 React 앱이 Redux를 사용할 필요는 없다고 먼저 말해두겠습니다. 사실 정말 간단한 React 앱은 Redux에서 얻을 수 있는 이득이 전혀 없습니다.

Redux에 관한 가장 일반적인 불평들은 장황하고 익히는데 시간이 걸린다는 점입니다. Redux는 개발자가 앱의 상태를 어떻게 업데이트할지 액션과 리듀서를 통해 명시적으로 서술하도록 요구합니다. 이를 통해 앱의 상태를 단일한 지역 컴포넌트 상태 대신 하나의 전역 스토어로 관리하게 해줍니다.

아래는 Redux의 구조에 대한 개요입니다.

액션

액션은 이벤트에 대한 정보에 불과합니다. Redux로 상태를 업데이트하고 싶으면 반드시 액션을 보내는 것으로 시작해야 합니다. 액션은 반드시 액션의 이름(타입)을 포함해야 하고 함께 보내고 싶은 정보를 포함할 수 있습니다. 액션이 타입을 가져야만 리듀서가 구분할 수 있습니다. 간단히 말해, 액션은 상태 변경을 일으키는 이벤트에 대한 정적인 정보입니다.

리듀서

보내진 액션은 리듀서로 전달됩니다. 리듀서는 각 액션이 스토어를 어떻게 업데이트하는지 기술하는 순수 함수입니다. 순수 함수는 같은 입력에 대해 항상 같은 출력을 반환하는 함수입니다. 리듀서는 언제나 새 앱 상태를 반환한다는 점도 중요합니다. 결코 스토어를 변형(mutate)하지 않습니다.

스토어

스토어는 객체로 저장되는 앱의 상태입니다. React 컴포넌트는 스토어를 구독해서 스토어가 업데이트될 때마다 컴포넌트를 업데이트할 수 있습니다.

이제 어떻게 생겼는지 보여드리겠습니다. Redux를 사용했을 때의 도식을 추가했습니다.

기억하세요: Redux에서 액션을 보내면, 리듀서 함수를 작동시켜서, 스토어를 업데이트합니다.

우리가 배운 것

우리가 Redux로 업데이트하고 나서 다음과 같은 이점들을 발견했습니다:

단순해진 React 컴포넌트들

  • React 컴포넌트 구조를 평평하게 할 수 있었고 몇몇 컨테이너 컴포넌트들은 제거할 수 있었습니다. 데이터를 아래로 전달하기 위해 컴포넌트의 계층구조를 만들 필요가 없어졌기 때문입니다.
  • 몇몇 클래스 컴포넌트들을 함수형 컴포넌트로 변경할 수 있었습니다.

관심사의 분리

  • 앱에서 액션과 리듀서 함수들을 모은 분리된 부분을 가짐으로써 신규 개발자들이 앱의 비즈니스 로직에 대한 개요를 한 곳에서 쉽게 볼 수 있게 되었습니다.
  • React 컴포넌트들이 상태와 상태를 업데이트하는 함수들 때문에 비대해지는 일이 줄어들었습니다. 컴포넌트가 사용자 인터페이스를 관리하는데 집중할 수 있고 가독성이 더 좋아졌다는 뜻이죠.

품질

마무리

섣부른 최적화는 만악의 근원이다 — 도널드 커누스

아직도 저는 이 격언이 진실이라고 생각하지만, 대부분의 React 앱에서 Redux를 일찍부터 도입하는 것은 올바른 접근이라고 믿습니다. 우리의 경험에서 핵심은 지역 상태를 사용하는 것이 꽤나 빠르게 성가신 일이 된다는데에 있었습니다.

당신의 앱이 아래 기준 중 몇몇과 일치한다면, 저는 Redux를 즉시 도입하는 것이 최고의 접근법이라고 봅니다.

  • UI가 앱의 상태에 따라 크게 바뀐다.
  • 상태가 항상 선형으로, 일방향으로 흐르지는 않는다.
  • 일반적으로 사용자가 앱을 사용하면서 여러 상태 업데이트와 연관된다.
  • 관련 없는 여러 컴포넌트가 같은 방식으로 상태를 업데이트한다.
  • 상태 트리가 단순하지 않다.
  • 상태가 여러 다른 방식으로 업데이트된다.
  • 사용자 액션을 되돌릴 필요가 있다.

우리 앱에서 어떤 컴포넌트에서는 지역 상태만 한 것이 없었습니다. 예를 들어 우리는 폼 화면 컴포넌트를 몇 개 가지고 있었는데 폼 유효성 검증은 지역 상태를 이용하는 것이 가장 좋았습니다. 우리가 폼 화면에서 지역 상태를 그대로 둔 이유는 아래와 같습니다.

  • 컴포넌트가 마운트 해제된 후에는 폼 상태를 유지하고 싶지 않았습니다.
  • 폼 유효성 상태는 컴포넌트 밖에서 공유되지 않습니다.

바로 시작하려면?

제가 Redux를 배울 때 사용했던 리소스들입니다.

읽어주셔서 감사합니다!

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.