Skip to content

Instantly share code, notes, and snippets.

@g6ling
Created January 13, 2017 05:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save g6ling/0ab204f8942b70094b64ec4e26fe68af to your computer and use it in GitHub Desktop.
Save g6ling/0ab204f8942b70094b64ec4e26fe68af to your computer and use it in GitHub Desktop.

Realm과 Redux을 같이 쓰는데 엄청난 문제가 발생했다.

현재는

  1. ActionCreator 가 Relam을 변경
  2. 변경된 Realm 객체 을 payload로 하여 Action을 생성
  3. 만들어진 Action으로 reducer 을 변경
  4. 변경된 reducer 로 View 을 변경

이러한 흐름으로 된다.

하지만 Accessing object of type "X" which has been deleted 이러한 에러가 발생하는 경우가 생겼다.

이미 지워진 Object 에 대해 접근을 했다는 것이다.

이유는 View 가 직접 Realm Object 을 참조하는 것이 문제이다.

일반적인 redux 라면 이런식으로 만들어 질것이다. New Store 가 만들어지기 전까지는 View 가 Old Store Object 을 참조하다가, Reducer 에 의해서 New Store Object로 store 가 변경 된다면, View 는 New Store Object을 참조하도록 바뀌고 (이때 render 실행), Old Store Object는 View 가 참조하지 않기 때문에 gc에 의해서 자동으로 사라지게 된다.

하지만 Realm 을 사용하는 경우에는 View는 항상 Realm Object을 참조하게 된다. 만약 ActionCreator 가 Realm 을 변경하게 된다면 (예를 들어 item 삭제), Reducer 에 의해서 새로운 Realm Object을 받기 전까지는 View 는 없는 주소값을 참조하게 되고, 이것이 에러를 만든다.

즉 문제점은, New Store Object 가 만들어지기 전에, Old Store Object 가 변경, 또는 삭제 되는 문제다.

어떻게 해결하면 될까?

가장 쉬운 방법은 Realm Object을 항상 복사하고 그걸 Reducer 에서 넘겨주면 됩니다.이때 복사는 deep copy을 해야하죠. 복사할 량이 조금밖에 없다면 나쁘지는 않겟지만 비효율적이고 Realm 의 query을 사용하지 못한다는 점은 너무나도 큰 단점입니다.

또 다른 해결방법은 delete 을 하기전에 미리 연결을 끊어 주면 됩니다. 예를 들어서 id가 3인 아이템을 지운다고 생각을 해보죠.

    const Items = realm.objects('Item');
    const deleteItem = Items.filtered('id == 3');
    realm.write(() => {
      realm.delete(deleteItem);
    });
    dispatch({ type: 'UPDATE_ITEM', payload: Items });

일반적이라면 이렇게 할 것 입니다. 하지만 이 경우에는 아직 View 가 realm과의 연결이 있는 상태에서 realm을 지우기 때문에 에러가 날것입니다.

    const Items = realm.objects('Item');
    const newItems = Items.filtered('id != 3');
    dispatch({ type: 'UPDATE_ITEM', payload: newItems });
    const deleteItem = Items.filtered('id == 3');
    realm.write(() => {
      realm.delete(deleteItem);
    });

이걸 이렇게 바꾼다면 미리 View 을 업데이트 그 뒤에 delete 을 하기 때문에 에러가 생기지 않을 것 입니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment