프론트엔드 기본개념 복습/Redux

[Redux] 리덕스의 세 가지 원칙

콘요맘떼 2022. 1. 30. 03:15

지금 진행하고 있는 Todo 어플리케이션의 상태관리 코드를 짜다가 non-serializable type에 대한 경고를 받았다. 해당 부분을 조사하다가 관련된 리덕스의 세 가지 원칙에 대해서 간략하게 기록을 남기려고 한다.

 

1. 시스템의 모든 상태는 하나의 저장소 안에 하나의 객체 트리 구조로 저장된다.

리덕스는 store의 일관성 유지, 복원, 시간여행 디버깅 등이 방해되는 것을 방지하기 위해서 Non-serializable 타입을 저장하는 것을 추천하지 않는다. 우선 serialize(직렬화)는 객체에 저장된 값을 연속적인(serial) 데이터로 변환하는 것을 말한다. 그 반대 개념이 역직렬화(deserialize)이다. 직렬화는 다양한 환경에서 데이터의 사용이 보존되기 위한 목적에서 필요하다. 예를 들어서 Object는 asyncstorage나 localstorage에는 저장될 수 없다. 그렇기 때문에 해당 환경들 사이를 값이 원활히 이동할 수 있도록 직렬화 혹은 역직렬화의 과정이 필요한 것이다. javascript에서 직렬화는 JSON.stringify를, 역직렬화는 JSON.parse를 통해 구현할 수 있다. 물론 Non-serializable type을 사용하지 않는다고 값이 저장되는 것은 아니지만 데이터가 직렬화 과정에서 손실될 수 있다는 문제점을 가진다. 따라서 리덕스를 사용할 때에는 기본적으로 Non-serializable 타입을 사용하지 않는 것에 대한 습관이 필요할 것으로 보이며 redux-persist를 사용하는 경우에는 상태값이 asyncstorage 혹은 localstorage로 넘어가는 현상이 발생할 수 밖에 없기 때문에 해당 부분에 대한 주의가 더더욱 필요할 것으로 보인다.

 

※ Non-serializable Type의 예

Promise, Symbol, Map, Set, Function, Class Instance ...

 

 

2. 상태는 읽기 전용이다.

상태는 직접적으로 수정이 불가능하며 상태의 변화를 표현해주는 액션 객체를 통해서만 바뀔 수 있다.

 

3. 상태의 변화는 순수 함수로 작성되어야 한다.

리듀서는 이전의 상태와 액션을 받아서 변화 이후의 상태를 반환한다. 정확히는 이전의 상태를 바꿔주는 것이 아니라 액션을 통해 그려내고자 하는 상태가 표현된 새로운 상태 객체를 반환한다. 리듀서는 일관성을 위해서 순수 함수로 작성되어야 하는데 이는 동일한 인자값이 주어졌을 때 매번 동일한 결과가 반환되어야 한다는 뜻이다. 그렇기 때문에 순수 함수는 함수 내 변수를 제외한 외부값을 참조하거나 변환하는 등의 작업이 포함되어서는 안된다. 예를 들어서 배열 형태의 상태가 존재할 때 새로운 원소를 추가하려면 push 메소드를 통해 상태에 직접 원소를 추가하는 것이 아니라 concat 등의 메소드를 통해 새로운 배열을 생성 후 리턴해줘야 한다.