리덕스(Redux)란 무엇일까?
redux, redux-saga, … 리덕스와 관련한 용어는 많이 들어봤는데, 본격적으로 공부를 한 적이 없었습니다.
하지만 redux
는 대표적인 상태 관리 JavaScript 라이브러리
로 아직까지는 사용되는 곳이 많다 보니 이 현실을 피할 수 없었습니다.
오늘부터는 리덕스가 무엇이고, 왜 사용하게 되었는가? 그리고 그 흐름에 대해 정리하면서 제 생각과 함께 적어보려고 합니다.
어떤 오픈소스나 라이브러리든 getting started
를 먼저 들어가서 보기 시작합니다. Redux 또한 이 페이지에서 친절하게 설명해 주고 있으니 다음 링크를 참고하는 것을 추천드립니다.
리덕스(Redux)는 무엇이고, 왜 사용하게 되었을까?
리덕스는 위에서 언급한 대로, 대표적인 상태 관리 JavaScript 라이브러리
입니다. 그러면 상태
가 대체 무엇이길래 이렇게 별도로 관리하는 것들이 생겨났을까요?
상태(state)란?
상태(state)
란 간단하게 말하자면 데이터
입니다. 덧붙이자면 상태
는 컴포넌트
내부에서 사용하는 데이터
라고 할 수 있습니다.
요즘은 웹 사이트를 구성할 때, 사용자에게 보여지는 UI들을 하나의 파일로 몽땅 구현하지 않고, 요소들을 컴포넌트
단위로 구성하여 조합하는 식으로 만듭니다.
리액트에서 상태(state)를 활용하는 예시를 간단하게 보여 드리겠습니다. 여기서는 상태가 무엇인지만 간략하게 파악하면 될 것 같습니다.
1
const [check, setCheck] = useState(true);
위 코드에서는 리액트 훅(hook) 중 하나인 useState
를 사용하여, check
라는 상태값을 선언하고 있습니다. (useState hook에 관해서는 해당 링크를 참고해 주세요)
1
2
3
4
5
6
<input
type="checkbox"
className="checkbox"
onChange="{handleClick}"
checked="{check}"
/>
check값에 따라 UI를 보여주거나, 가리는 기능을 포함한 컴포넌트에서 위와 같이 input 태그를 사용하고 있다고 가정해 보겠습니다. 위 코드에서는 checked
속성에 check
상태값을 활용하고 있습니다.
이처럼 하나의 컴포넌트가 사용하게 되는 데이터
역할을 상태(state)라고 생각하면 됩니다.
상태 관리 라이브러리와 요즘의 동향
하지만 프로젝트 규모가 커질수록 컴포넌트 갯수도 많아질 것이고, 그에 따라 관리해야 하는 state
들은 자연스레 많아질 수 밖에 없습니다. 기능이 확장되면서 연관되는 컴포넌트들이 많아지고, 그 안에서 사용되는 상태값들도 복잡해지기 마련입니다. 그래서 개발자들은 상태 관리 라이브러리를 사용하게 되고, 그 중의 하나가 Redux
인 것입니다.
물론 요즘은 react hooks가 생겨남에 따라, 굳이 Redux가 필요한가? 에 대해서 많은 의견들이 오가고 있습니다. Redux가 오히려 복잡성을 높인다는 의견도 적지 않은 편이죠. 그리고 Redux를 대체할 수 있는, 새롭게 생겨나는 라이브러리들에 더 많은 관심이 생겨나고 있는 것이 요즘 추세이기도 합니다.
아래 링크에서 자바스크립트 관련 라이브러리들에 대한 동향을 살펴볼 수 있습니다.
https://2020.stateofjs.com/ko-KR/technologies/datalayer/
그렇지만 라이브러리는 개발 목적에 맞게 잘 선택해서 사용하는 것이 궁극적인 목표일 것이므로, 어느 것이든 잘 선택해서 목적에 맞게 사용하는 것이 중요할 것입니다.
무엇보다 아직까지는 redux를 사용한 코드들을 많이 접하게 되다 보니, 이해를 하기 위한 차원에서 개인적으로 공부를 할 필요가 있었습니다. (개인적으로는 최근에 생긴 Apollo Client + GraphQL
에 관심이 많아서 별도로 공부하고 싶은 생각을 가지고 있습니다.)
Redux의 상태 관리 흐름
그렇다면 리덕스는 어떻게 state
를 다루고 관리하는지, 전체적인 흐름을 간략하게 그림으로 나타내었습니다.
- 액션은 액션 type과 전송할 데이터(payload)로 이루어진 객체 형태입니다.
- Action Creator는 액션을 반환하는(만드는) 함수입니다. 이를 통해 액션을 dispatch 합니다.
- dispatch는 액션값을 매개변수로, Reducer를 호출하는 것입니다.
- 리듀서는 현재(이전)의 state와 받은 action에 따라 그 state를 변화시킨 다음 새로운 state를 반환합니다.
- 리듀서에서는 상태를 변화시킬 때 반드시 이전 객체와는 다른 새로운 state 객체를 반환해야 합니다. 이렇게 되면 데이터(상태)가 변화하기 이전과 이후의 객체는 서로 다른 객체가 됩니다.
- 따라서 이전 상태 객체는 유지하였으므로
불변성
을 지킨 것이며, 리덕스는 데이터가 변경되었다는 사실을shallow equality checking
을 통해 상태가 변화했음을 알 수 있습니다.
Redux는 Shallow equality 검사로 상태의 변화를 감지한다.
- 서로 다른 객체(a, b)인 경우 단순히
a === b
인지만 체크해도 다른지 알 수 있고 이것을shallow equality
검사라고 합니다. - 반대로
deep equality
검사는, 두 객체(a, b) 내부 프로퍼티까지 모두 같은지 일일이 체크를 하는 것을 말합니다. - 따라서 두 가지 방식 중 성능적으로 당연히
shallow equality
가 우위일 수 밖에 없습니다. - 그러므로 리듀서에서는 상태를 변화시킬 때 이전 상태 객체의 값을 변경시키는 것이 아니라, 아예 새로운 객체를 반환하는 것입니다. 그리고 여기서 이전 상태 객체는 변경하지 않았으므로
불변성
을 지켰다고 하는 것입니다.
리덕스에서 shallow equalitiy checking을 하는 이유 : https://redux.js.org/faq/immutable-data#how-do-shallow-and-deep-equality-checking-differ
액션(Action), 액션 생산자(Action Creator), 디스패치(dispatch), 리듀서(reducer), 스토어(store) 등 관련 용어는 다음 포스팅에서 더 자세히 작성하도록 하겠습니다.
참고한 자료