리덕스(Redux)는 JavaScript(자바스크립트) 상태관리 라이브러리이다.리액트(React)뿐만 아니라 앵귤러(Angular), 제이쿼리(jQuery)등 다양한 프레임워크와 작동되게 설계하였다.
상태(state)란 무엇인가?
상태는 단지 데이터이다. 사용자의 이름, 주소 이거나, 로그인 여부, 페이지가 로딩 중인지에 대한 것들과 같은 어플리케이션 데이터 집합이라고 생각하면 될것 같다. 어플리케이션의 상태는 사용자의 동작이나 API 응답 등으로 인해 언제든 바뀔수 있다.
리덕스(Redux)가 등장하기 전 프론트엔드에서의 데이터 흐름을 관리하는 방식은 MVC 패턴이었다.
MVC패턴은 큰 특징이 있는데 '양방향 데이터 흐름'이라는 것이다. Model이 변경되면 View 또한 변경되고, 사용자에 의해 View에서 변경이 되면 Model 또한 변경이 되기 때문에 양방향성 데이터 흐름인 것이다.
이런 흐름은 설계가 간단하고 코드 또한 작성하기 쉬운 장점이 있는데 단점은 규모에서 온다. 어플리케이션의 규모가 커진다면 하나의 Model이 여러 View를 조작하거나 하나의 View가 여러개의 Model을 조작한다고 가정한다면, 데이터 흐름을 파악하기 어려워진다. 버그라도 발생한다면 흐름을 추적하는데 시간을 다써버릴것이다.
해당 이미지는 MVC 패턴의 단점을 극명하게 보여준다.(양방향 데이터 흐름으로 인한 데이터 복잡성)
기존의 페이스북은 MVC 패턴으로 데이터 흐름을 관리하는데 많은 어려움을 겪고 있었다. 대안으로 Flux라는 새로운 아키텍처 패턴을 개발하게 된다.
페이스북은 서비스가 거대해지면서 많은 양의 뷰와 모델이 필요해졌고 그에 따른 사용자와의 인터렉션이 많아지게 되면서 많은 양의 데이터 흐름을 관리하기 힘들어지게 된다. 버그 또한 많아지면서 총체적 난국상태에 빠지게 되는데..
이것을 해결해줄 방법으로 Flux를 개발한것이다. Flux는 MVC 패턴으로 인한 복잡한 상황을 개선하는것이 목적이었고, 그 방한으로 '단방향 데이터 흐름' 을 적용하였다. View는 데이터를 변경시키지 않고 Action을 일으키고 Action은 반드시 Dispatcher를 통해 데이터 변경을 해야한다. View는 변경된 데이터를 Store를 통해 다시 전달 받게된다. 이러한 단방향 데이터 흐름은 기존의 양방향 데이터 흐름인 MVC 패턴에 비해 데이터 복잡성을 덜어주고 상태의 전이(View 와 Model이 연결된 많은 곳을 따라 변경되는 것) 현상을 없애준다.
Redux = (Red)ucer + Fl(ux)
이런 구조를 기반으로 React + Flux 구조에 'Reducer'를 결합한 'Redux(리덕스)'가 탄생하게 된다.
왜 굳이 Flux를 쓰지 않고 Redux를 사용할까? Redux의 제작자가 말하길..
- 리듀서의 구성
- 서버 랜더링
- 좋은 개발자 경험
- 간결성
라고 한다.. Flux와 Redux의 차이점은 좀더 자세히 알아봐야할것 같다...
React는 기본적으로 '단방향 데이터 흐름'을 가진다. 부모 컴포넌트에서 자식 컴포넌트들로 데이터를 props로 내려보내 준다는 것을 의미합니다.
각 컴포넌트는 서로 독립적이고 고유의 state를 해당 컴포넌트 이외에 접근할 수 없다. 즉 "하향식"으로 데이터를 넘겨줄 수 있지만 "상향식"으로는 데이터가 이동 못한다.
But 자식 컴포넌트에 의해 부모 컴포넌트의 state가 변하는 상황이 있는데, 이런 경우를 해결하기 위해 Lifting State Up 이 존재한다. 상위 컴포넌트의 "상태를 변경하는 함수" 자체를 하위 컴포넌트로 전달하고, 하위 컴포넌트를 실행하면 된다. 이것이 위의 이미지의 'State change initited'에 해당된다.
리덕스를 설명하다가 딴길로 새어버렸지만...
아무튼 핵심은 위의 이미지처럼 state가 업데이트 되고 앱 전체로 퍼지는 방식이 복잡해지는 것이다. 해당 state가 필요없는 컴포넌트까지 들려야 하기 때문에 흐름이 복잡해진다.
이런 복잡한 흐름을 리덕스 구조로 해결해 버린다. state의 변경은 Reducer를 통해서 일어나며 state는 Store에 저장된다. 그리고 데이터가 필요한곳에 뿌려준다. 여전히 부모 컴포넌트에서 자식 컴포넌트로 state를 넘겨줄 수 있지만 이 state의 원천은 항상 Store가 되어야한다.
View에서 일어나는 이벤트는 직접 데이터를 건들지 않고 Action을 통해 요청만 한다. (Reducer 이외는 읽기만 할 수 있다.)
액션에 의해 상태 트리가 어떻게 변화하는 지를 지정하기위해 순수 함수로 Reducer를 작성한다.
state(데이터)가 집중화 되어 있어서 예측이 가능하고 흐름이 단방향이라서 디버깅하기 쉬운 것 같다. 필요에 맞게 구현한다면 리덕스의 장점을 잘 살릴 수 있지 않을까 싶다. 단, 반드시 써야한다! 이건 아니고 데이터의 흐름이 복잡하지 않다면 굳이 쓸 필요는 없을것 같다.