자바스크립트로 구현된 싱글 페이지 애플리케이션의 요구사항이 점차 복잡해짐에 따라 애플리케이션 상태를 유지하는 것은 더욱 까다로워졌다. 애플리케이션 상태는 서버 또는 API 응답, 로컬 컴포넌트의 상태 및 페이징, 활성화된 라우트, 선택된 탭과 같은 UI 상태로부터 생성될 수 있다. 이러한 애플리케이션의 상태값은 애플리케이션 내부에서 직접 혹은 간접적인 모델로, 또는 UI 상호 작용을 통해 변경될 수 있다. 이로 인해 어느 순간부터 상태가 언제, 왜, 어떻게 변경됐는지를 통제할 수 없게 될 수도 있다. 이러한 문제는 플럭스(Flux) 같은 상태 관리 디자인 패턴과 리덕스(Redux), Mobx, 리코일(Recoil), 리매치(Rematch), Vuex 같은 라이브러리로 해결됐다.
적절한 상태 관리 솔루션을 선택하는 것은 중대형급 리액트 애플리케이션에서 매우 중요하다. 이번 장을 읽고 나면 플럭스 패턴과 리덕스 아키텍처, 핵심 원칙, 주요 컴포넌트, 비동기 데이터 흐름의 처리, 사가(Saga), 썽크(Thunk) 같은 미들웨어 및 디버깅을 위한 리덕스 개발자 도구(Redux DevTools)에 관한 질문에 유창하게 답할 수 있게 될 것이다.
이번 장에서 다루는 주요 주제는 다음과 같다.
플럭스 패턴과 리덕스의 이해
리덕스의 핵심 원칙, 컴포넌트 API
리덕스 미들웨어: 사가와 썽크
리덕스 로직을 RTX를 이용해 정규화 하는 법
리덕스 개발자 도구로 애플리케이션 디버깅하기
처음에 리덕스는 리액트 애플리케이션을 위해 만들어졌으며, 현재 사용 가능한 상태관리 라이브러리 가운데 꽤 많은 인기를 누리고 있다. 다음 절에서 플럭스 패턴, 리덕스의 기초 및 핵심 개념에 대해서 더 자세히 알게 되면 리덕스 라이브러리에 대한 이해가 더욱 깊어질 것이다.
플럭스 패턴과 리덕스 이해하기
플럭스는 리액트 애플리케이션의 데이터 흐름을 관리하기 위한 디자인 패턴이다. 이 패턴은 옵저버 패턴을 약간 수정한 것으로 한 객체의 상태 변경이 다른 모든 객체에 알림을 주고 이를 구독해서 확인하는 일련의 매커니즘을 의미한다.
리덕스 라이브러리는 2015년에 처음 소개됐다. 리덕스는 최초에 플럭스 아키텍처에 영감을 받았지만 실제 구현에는 차이가 있다. 다음의 몇 가지 질문은 리덕스 상태 관리 라이브러리를 위한 플럭스와 리덕스의 핵심 개념에 초점이 맞춰져 있다.
플럭스 패턴이란 무엇인가? 데이터 흐름에 대해 설명할 수 있는가?
플럭스란 애플리케이션에서 단방향 데이터 흐름을 관리하는 패턴으로, 전통적인 MVC 패턴을 대체한다. 플럭스는 프레임워크나 라이브러리가 아니라 클라이언트 사이드 웹 애플리케이션 상태 관리 복잡성을 해결하기 위한 새로운 종류의 아키텍처다. 페이스북이 리액트 애플리케이션을 작업하는 동안 내부적으로 개발해서 사용됐다.
플럭스의 데이터 흐름에는 다음과 같은 네 가지 주요 컴포넌트인 액션, 디스패치, 스토어, 뷰가 있다. 각각에 대한 자세한 설명은 다음과 같다.
액션(Action) : 데이터 흐름을 트리거하는 디스패처로 보내지는 자바스크립트 객체를 의미한다.
디스패처(Dispatcher) : 스토어를 업데이트하기 위한 콜백을 위한 싱글턴 레지스트리로, 플럭스 애플리케이션 내의 데이터 흐름의 중앙 허브 역할을 담당한다. 디스페처는 실제로 별도 로직이 존재하지 않으며, 단순히 액션에서 스토어로 페이로드만 전달하는 역할을 한다.
스토어(store) : 애플리케이션 상태와 로직을 보관하는 곳이다.
뷰(view) : 스토어로부터 데이터를 받아 애플리케이션을 다시 렌더링한다. 뷰는 사용자 상호 작용에 따른 액션을 트리거하기도 한다.
앞서 언급된 컴포넌트를 기반으로 한 플럭스 아키텍처의 단계별 데이터 흐름은 다음과 같다.
사용자가 UI 상호 작용을 수행하면 이벤트가 생성되고, 뷰는 디스패처에 액션을 보낸다.
디스패처는 해당 액션을 각 스토어에 보낸다.
스토어는 상태를 업데이트하고 뷰에 다시 렌더링하도록 알린다.
다음 다이어그램은 플럭스 기반 웹 애플리케이션에서 데이터 흐름이 어떻게 일어나는지 보여준다.
플럭스 데이터 흐름
대부분의 애플리케이션에서는 액션 객체를 생성할 뿐만 아니라 액션을 디스패처에 전달하는, 이른바 액션 생성기(action creator)를 일종의 라이브러리로 생성해서 사용한다.
플럭스의 장점은 무엇인가?
플럭스 아키텍처에는 다음과 같은 장점이 있으며, 클라이언트 사이드 웹 애플리케이션에서 사용하기에 유용하다.
단방향 데이터 흐름으로 인해 이해하기 쉽다.
플럭스 컴포넌트는 서로 분리되어 각 컴포넌트가 자체적인 책임을 지닌다.
프레임워크나 라이브러리가 아닌 오픈소스 아키텍처다.
설계로 인해 발생하는 런타임 오류가 감소한다.
유지보수가 용이하다.
플러스 아키텍처는 API 통신, 캐싱, 지역화 코드를 뷰 또는 UI 계층에서 분리하는 데 도움이 된다.
MVC와 플럭스의 차이점은 무엇인가?
MVC(Model, View, Controller) 디자인 패턴은 1976년 스몰톡 프로그래밍 언어에서 처음 소개됐다. 애플리케이션의 규모가 점점 커짐에 따라 이 패턴은 다중 데이터 흐름으로 인해 복잡해진다. 페이스북 팀은 플럭스 아키텍처를 도입해서 이 문제를 해결했다. MVC와 플럭스 디자인 패턴 간의 주요 차이점은 다음과 같다.
MVC
플럭스
데이터 흐름이 양방향이다.
데이터 흐름이 단방향이다.
컨트롤러가 로직을 다룬다.
스토어가 로직을 처리한다.
스토어와 같은 개념이 없다.
여러 개의 스토어가 존재할 수 있다.
동기적으로 이뤄진다.
비동기적으로 이뤄진다.
양방향이라 디버깅하는 데 어려움이 있다.
디스패처로 디버깅하기가 용이하다.
클라이언트 및 서버 사이드 프레임워크 모두에서 사용 가능하다.
클라이언트 사이드 프레임워크에서만 사용 가능하다.
플럭스가 MVC와 완전히 다른 접근법을 가지고 있는 것은 아니지만 MVC 보다 한층 더 향상된 모습을 가지고 있다. 애플리케이션이 복잡하고, 복잡한 데이터 모델을 가지고 있다면 MVC 보다 플럭스를 적용하는 것이 더 낫다.
리덕스란 무엇인가?
리덕스는 클라이언트, 서버, 네이티브 환경에서 일관되게 동작하는 자바스크립트 애플리케이션을 위해 설계된 예측 가능한 상태 관리 도구로 많은 인기를 누리고 있다. 또한 테스트하기도 용이하다. 리덕스는 페이스북의 플럭스 아키텍처에서 영감을 받았다. 게다가 플럭스 패턴에 존재했던 불필요한 복잡성을 제거했다.
애플리케이션에 컴포넌트가 많지 않을 때는 컴포넌트의 상태를 사용하기가 비교적 간단하다. 그러나 컴포넌트 수가 증가하고 애플리케이션이 점차 커짐에 따라 애플리케이션 내에 각 컴포넌트의 상태를 유지하는 것이 어려워진다. 이 경우 리덕스는 전역 스토어를 생성해서 대규모 애플리케이션의 상태를 관리하며, 상태가 필요한 모든 컴포넌트는 이 전역 스토어를 사용하고 컴포넌트 사이에 props를 내려주는 것이 불필요해진다.
♣ 참고 : 리덕스는 모든 의존성을 포함하더라도 2KB 밖에 되지 않는 가벼운 라이브러리다.
플럭스와 리덕스의 차이점은 무엇인가?
리덕스가 플럭스에 영감을 받았다고 하더라도 다음 표와 같은 몇 가지 주요 차이점이 있다.
플럭스
리덕스
페이스북이 개발
댄 아브라모프와 앤드류 클라크가 개발
애플리케이션 상태 관리를 위한 애플리케이션 아키텍처
상태를 관리하기 위한 오픈소스 자바스크립트 라이브러리
애플리케이션에 여러 스토어를 제공
리덕스 패턴 내에서는 애플리케이션 내부에 단 하나의 스토어만 존재
액션, 디스패처, 스토어, 뷰라는 4개의 주요 컴포넌트로 구성됨
액션, 리듀서, 스토어라는 3개의 주요 컴포넌트로 구성됨
스토어가 로직을 다룸
리듀서가 로직을 다룸
싱글턴 디스패처 존재
디스패처를 사용하지 않음
스토어 상태는 변할 수 있음(mutable)
스토어 상태는 변할 수 없음(immutable)
앞서 설명한 차이점 외에도 리덕스는 함수 합성(functional composition)을 통해 복잡성을 줄이는 반면, 플럭스는 콜백을 등록하는 방법을 사용한다.
언제 리덕스를 사용해야 하는가?
리덕스는 애플리케이션 전반에 걸쳐 데이터를 유지하고 업데이트하기 위해 사용되며, 여러 컴포넌트에 상태를 공유할 수 있다. 그러나 모든 종류의 애플리케이션에 필요한 것은 아니다. 리덕스의 학습 곡선은 가파른 편이며, 작성해야 하는 코드의 양 또한 늘어난다.
다음은 리덕스를 사용하기에 유용한 경우를 정리한 것이다.
애플리케이션에 포함된 수많은 상태를 앱 내부의 여러 컴포넌트에서 공유하는 경우
애플리케이션의 상태가 단일 진실 공급원을 따라야 하는 경우
애플리케이션의 상태가 자주 업데이트되는 경우
일정 기간 동안 상태 업데이트가 어떻게 일어나는지 모니터링해야 하는 경우
애플리케이션 코드가 소규모가 아니며 많은 팀 구성원이 함께 작업해야 하는 경우
또한 리액트나 다른 프런트엔드 프레임워크 자체에서 상태를 관리할 수 있다면 리덕스를 사용할 필요가 없다.
리덕스는 단순히 작은 라이브러리가 아니다. 핵심 원칙에 기반한 패턴으로도 볼 수 있으며, 세가지 주요 컴포넌트를 기반으로 동작하며, 리덕스 애플리케이션에서 일반적인 사용 사례를 다루기 위해 여러 가지 추가 기능과 광범위한 API를 제공한다. 다음 절에서 이러한 주제를 깊이 파고 들어 보자.