JBEE.io icon indicating copy to clipboard operation
JBEE.io copied to clipboard

react/react-redux-normalize/

Open utterances-bot opened this issue 5 years ago • 6 comments

Redux에서 Normalize 다루기 | JBEE.io

웹이 복잡해질수록 프런트엔드(자바스크립트 환경)에서 다뤄야 하는 상태가 많아진다. 그 종류도 점점 다양해지면서 UI의 상태와 도메인 데이터에 대한 값들도 함께 다뤄야 한다. UI도 중요하지만 React Application의 상태를 ‘잘’ 설계(Design)해야 한다.자연스럽게 상태 관리를 위한 라이브러리가 많이 등장했다. 를 시작으로 , 등 여러 라이브러리가 존재한다. 이번 포스팅에서는 redux 라이브러리와 normalizr 라이브러리를 중심으로 상태 설계에 대한 내용을 다룬다.Table…

https://jbee.io/react/react-redux-normalize/

utterances-bot avatar Feb 27 '20 02:02 utterances-bot

이 경우에 가비지 컬렉팅(?)이나 cache invalidation 문제에 대해서 잘 대처하려면 어떤 방식으로 설계하는게 좋을까요? 관련 메타데이터를 엔티티에 같이 저장하나요?

ellemedit avatar Feb 27 '20 02:02 ellemedit

@Beingbook 깊게 생각해보지 않았던 부분인데, 흥미롭네요! 구체적으로 어느 부분에 대한 GC를 고려해야 할까요? cache는 어느 부분에서 적용되어 언제 invalid 될까요? 고민하기 나름일 것 같습니다 :)

jbee37142 avatar Feb 27 '20 03:02 jbee37142

  1. 가비지 컬렉팅은 사고실험에서 기인한 것인데요. 유저가 애플리케이션을 종료하지 않고 극단적으로 오래 사용하는 사례를 생각해보면 거대한 상태가 JS의 GC 수행시간이 길어질 것으로 예상됩니다. (제가 정확히 측정해보진 않았지만 GC원리상 10만개 이상의 엔티티가 쌓이면 느려지지 않을까? 하는 킹리적 갓심입니다) 위 경우 유저의 선택지는 애플리케이션을 재시작하거나 필요 없다고 판단된 엔티티는 자연스럽게 참조가 '해제' 되어야 할 것 같습니다. 그런데 정규화된 데이터를 수동 GC 하려면(다른 GC 어프로치가 존재하는지는 모르겠습니다.) 어떤 엔티티가 '얼마나' 참조되고 있는지 알아야 하는데 이런 구현은 비용이 너무 비싼 것 같아서 혹시 좀 더 좋은 방법이 있는지 질문드렸습니다. :) (물론 이건 제 상상속에만 존재하는 익스트림 케이스 일 수 있겠네요.)

  2. Cache Invalidation은 말씀주신대로 다양한 방법이 있을 것 같네요. 굳이 정규화 레이어에서 할 필요가 없을 것 같습니다.

그런데 한가지 더 고민되는 포인트가 생겨서 같이 질문 남겨봅니다. ㅎㅎ;

  1. 비슷하지만 다른 엔티티일때

형태가 비슷하지만 엔티티의 모양새가 다른 경우가 있습니다. 아래처럼요:

User {
  id: string;
  name: string;
  followers: Follower[];
  posts: Post[];
  viewerRelation: { followMe: boolean; }
  // ...
}
Post {
  title: string;
  author: Author;
  // ...
}
Follower {
  id: string;
  name: string;
  viewerRelation: { followMe: boolean; }
}
Author {
  id: string;
  name: string;
  posts: Post[];
  viewerRelation: { followMe: boolean; }
}

User, Follower, Author 3개의 엔티티는 비슷해보이지만 조금씩 다른데요. 이 경우는 실제로 각 화면이나 엔티티 관계에 따라 필요한 정보가 달라지고 불필요한 정보를 필터할 수도 있기 때문에 실제로 발생할 수 있는 케이스 같습니다.

선택지는

  1. User, Follower, Author 개별 엔티티를 분리해서 관리
  2. User, Follower, Author 엔티티를 User 하나로 하고 유니온타입으로 추론

중 택일 같은데 1번의 경우 팔로우를 했을 때 엔티티가 다 분리되어 있기 때문에 정보일관성이 보장되지 않는다는 문제가 있고

2번은 코드를 user.followers && user.followers.map(...) 혹은 user.followers?.map(...) 등 타입세이프하기 위해 노력해야 하는 코드가 많아질 것 같습니다.

일단 제 생각엔 2번쪽이 데이터 일관성을 좀더 보장하기 때문에 올바른 방법인 것 같은데 혹시 이와 관련해서도 고민해보신적 있으시다면 공유해주실 수 있나요?

ellemedit avatar Feb 27 '20 04:02 ellemedit

@Beingbook 와 😮 좋은 고민인 것 같습니다.

  1. GC의 경우, 정규화 처리를 하지 않는다 하더라도 10만개 이상의 데이터 배열을 다룰 때도 마찬가지 고민이 필요할 것 같아요. 10만개를 올려두지 않는 방향으로 설계를 해야하지 않을까? 생각해봅니다.

  2. 말씀해주신 상황을 제가 잘 이해했는지 모르겠지만 개별 엔티티로 분리하거나, 유니온 타입으로 추론하기 전에 구조를 다시 잡아보면 어떨까 생각됩니다. Author, Follower가 필요한지 먼저 생각해보면 RDBMS에서도 user table 하나로 관리할 것으로 생각됩니다. 따라서 User를 다음과 같이 변경하게 되면 Follower, Author를 별도로 정의하지 않아도 될 것 같습니다.

User {
  id: string;
  name: string;
  followers: User[];
  posts: Post[];
}

정규화가 만능은 아닌지라 ㅎㅎ 의도하셨던 부분에 대한 고민이 있을 수 있겠지만 말씀하신 정보일관성을 어느 정도 유지할 것인가에 따라서 달라질 것 같습니다 :)

jbee37142 avatar Feb 27 '20 05:02 jbee37142

1번은 말씀 주신 것 처럼 그런 케이스 자체를 막아버리는 게 필요하죠. 생각해보니 정규화 상태를 LRU 캐시로 저장만해도 대부분 문제는 없겠네요.

2번은 제가 설명을 잘못한것 같습니다. 2번 케이스의 문제는 각각 UI마다 필요한 데이터가 다르다는 것에서 기인해요. 예를 들어 follower랑 post를 모두 로드하는건 옵티멀한 상황이 아니게 되어버리죠. (특히 팔로워가 팔로워를 또 로드하면 어떤 성능좋은 DB를 쓰더라도 끔찍해질겁니다. 잘못하면 서큘러 디펜던시가 있을 수도 있겠죠.) DBMS스키마 정의와는 별개로 각각 옵티멀한 엔티티 상태는 분리되어야 하는 케이스가 필연적일 것 같아요.

ellemedit avatar Feb 27 '20 06:02 ellemedit

약간 저만 가지고 있는 뜬구름 잡는 생각인가 싶었는데 답변해주셔서 감사합니다 ㅋㅋ

ellemedit avatar Feb 27 '20 06:02 ellemedit