A non-serializable value was detected in an action, in the path: register. ...
파이어베이스에서 반환된 유저 데이터를 Redux에서 받아왔는데, 위와 같은 에러가 발생하였다.
구글링 결과 Redux에는 직렬화할 수 있는 일반 객체만을 저장할 수 있다는 사실을 알게되었다. 파이어베이스에서 반환되는 유저 객체는 중첩 객체 형태인데 이로 인해서 직렬화가 불가능했고 Redux Store에서 처리할 수가 없다는 에러가 나는 것으로 보인다.
각각의 환경에 따라서 받아들일 수 있는 데이터의 구조는 조금씩 다를 수 있다. 웹 스토리지를 예시로 들자면 배열이나 객체 데이터를 그대로 웹 스토리지에 저장하면 내부의 데이터가 저장되는 것이 아니라 배열이나 객체 그 자체가 저장되어버린다. 웹 스토리지에는 문자열 형식의 데이터만을 저장해야하는데, 그렇다면 어떻게 해야하는가?
JSON.stringify() 를 사용하면 된다. JSON.stringify()는 배열 혹은 객체를 문자열로 바꾸어주는데, 이때 배열 혹은 객체 구조의 데이터들은 일렬로 '직렬화'되게 된다.
{
a: {
b: 1
}
}
이런 형태의 객체 데이터가..
{a: {b: 1}}
이런 직선 형태로 재구성되는 것이다.
그런데 이렇게 직렬화된 문자열 데이터를 나중에 어떻게 꺼내와야 하는가? 바로 JSON.parse()를 사용해준다. JSON.parse()는 JSON.stringify와 반대로 문자열 데이터를 객체 형태로 재구성시켜준다. 이런 재구성이 간단하게 이루어지는 까닭은 데이터 자체가 JSON 표준 형식을 따르고 있기 때문이다. 기본 구조가 동일하기 때문에 객체와 문자열의 전환이 자유롭게 이루어지는 것.
Promises, Symbols, Maps/Sets, 함수들 또는 클래스 인스턴스 등은 직렬화가 불가능하다고 한다. 따라서 이런 데이터들은 Redux Store에서 다루어서는 안된다. 경우에 따라서 직렬화가 불가능한 데이터를 Redux Store에서 다루어도 에러가 발생되지 않을 수도 있지만 이는 Redux가 공식적으로 지양하라는 방법이고, 프로그램 안정성에 문제가 발생할 수 있다고 한다. 직렬화가 불가능한 데이터는 기능과 렌더링에 예상하지 못한 문제를 발생시킨다고 하니 주의해야겠다.
-> 그래서 미들웨어라는 개념이 등장했다. Redux-Thunk 혹은 Redux-Saga가 Redux에서 Promises 객체를 다룰 수 있게 해준다.
원인은 하나지만 해결 방법은 다양하다. 직렬화되지 않은 데이터는 Redux Store를 거치지 않고 props로 관리하거나, 직렬화가 가능한 데이터를 사용하는 등의 방법이 여기에 해당한다.
나의 경우 유저 데이터에서 필요한 부분은 일부분이었고, 여기는 직렬화가 가능한 범위 내에 위치하여 점 표기법으로 특정 데이터만 받아와 Redux Store에 넘기는 방식으로 문제를 해결하였다.