Redux 공식문서 해체하기 ( 공부용 ) : Structuring Reducer_Normalizing State Shape

오범준·2021년 2월 26일
0

link : https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape

많은 application들이 nested된 data 를 다룬다

🧡 Nested data ?
for example ) reference type value in reference type value
ex) object in object

const blogPosts = [
  {
    id: 'post1',
    author: { username: 'user1', name: 'User 1' },
    body: '......',
    comments: [
      {
        id: 'comment1',
        author: { username: 'user2', name: 'User 2' },
        comment: '.....'
      },
      {
        id: 'comment2',
        author: { username: 'user3', name: 'User 3' },
        comment: '.....'
      }
    ]
  },
  {
    id: 'post2',
    author: { username: 'user2', name: 'User 2' },
    body: '......',
    comments: [
      {
        id: 'comment3',
        author: { username: 'user3', name: 'User 3' },
        comment: '.....'
      },
      {
        id: 'comment4',
        author: { username: 'user1', name: 'User 1' },
        comment: '.....'
      },
      {
        id: 'comment5',
        author: { username: 'user3', name: 'User 3' },
        comment: '.....'
      }
    ]
  }
  // and repeat many times
]

위와 같은 구조의 data는 크게 3가지 문제점을 지닌다

❤ 1. 같은 구조의 코드가 중복된다

❤ 2. Nested 된, 중첩된 구조의 data가 너무 많다. 즉, 이전상태를 받아서, 다음 상태를 반환하는 , 즉, 순수함수여야 하는 reducer 함수의 입장에서는, 위의 data를 관리하기 위해, 그만큼 더 nested 된, 중첩된 구조로 reducer함수도 짜여져야 한다는 점이다

❤ 3. 설령 reducer함수를 중첩해서 잘 짜서, 위의 data를 immutable 하게 update한다고 하더라도, 비효율적이다.
왜냐하면, post2의 comment 내용만을 update 하고 post2의 다른 내용은 그대로 있게끔 update 할때에도 , post2 라는 전체 state 자체를 copy, update하는 과정을 거쳐야 하는 것이다. 즉, unrelated 된 다른 요소들도 update 시켜야 하고, 그렇게 unrelated된 다른 요소들이 update되면서, 또 그와 연결된 UI component들도 re-render을 일으킬 수 있다.
❤ 즉 ! 딱 필요한 애만 update 되고, 관련없는 애들은 update 안되게 끔 구조를 다시 잡아야 한다

Designing a Normalized State

모든 개체가 ID를 키로 가지고, ID를 통해 다른 개체나 목록을 참조하도록 하세요 !!

❤ 기본적인 원리는 다음과 같다

1) 각 데이터 타입이 / 고유의 'table'을 갖게 한다.

예를 들어, 하나의 post 안에도,
post, authour, comment등 다양한 data type이 존재한다

위와 같이 하나의 post 정보 안에, 서로 다른 data type을 때려박아 놓는 것이 아니라

post는 post 대로, comment는 comment 대로,
따로 분리해서 data 구조를 짠다는 것이다
post는 post관련 table, comment는 comment 관련 table을 마련하는 것이다

2) 각 데이터 타입의 table 안에는 / 데이터 하나하나가 object 형식으로 들어가는데 / 해당 하나의 object 로 접근하기 위한 ID 를 key로 설정해주고 , 해당 데이터 자체는 value로 설정해준다

"post1" : {
             id : "post1",
             author : "user1",
             body : "......",
             comments : ["comment1", "comment2"]
         },

3) 각 데이터에 대한 참조는, 해당 데이터의 id를 저장하는 것으로 이루어져야 한다

4) ID, 즉, 해당 데이터. 라는 value에 접근하기 위한 id를 담는 배열을 id가 순서대로 들어가 있게끔 , 따로 마련해둔다.
ex) allIds : [ 'post1', 'post2']

 posts : {
        byId : {
            "post1" : {
                id : "post1",
                author : "user1",
                body : "......",
                comments : ["comment1", "comment2"]
            },
            "post2" : {
                id : "post2",
                author : "user2",
                body : "......",
                comments : ["comment3", "comment4", "comment5"]
            }
        },
        allIds : ["post1", "post2"]
    },

그렇다면 위와 같이 정리되었을 때 장점은 ?

  1. 각 아이템은, 고유의 id 와 함께 한 장소에만 저장되어 있다. 아까와 같이 post2의 comment2를 바꾸기 위해 post2 전체를 바꾸는 것이 아니라, comment2만 바꾸면 된다
  1. 1) 과 같이, update 과정이 단순하기 때문에 / 당연히 reducer 함수의 logic도 중첩,nested될 필요 없이 단순해질 수 있다
  1. 이전에 비해 데이터 얻기(retrieving), 데이터 변경(updating) 이 더 쉬워졌다. 해당 특정 데이터의 id만 있으면 되기 때문이다.

Organizing Normalized Data in State

사실 relational data, non-relational data 를 합쳐놓는 것이다.
정답으로 여겨지는 방식은 없을 수도 있지만

일반적인 방식 중 하나는
relational 'table'
즉, 공통 유형의 데이터들을 하나의 table 에 넣고
그 table을 가리키는 parent key를 id로 설정해두는 것이다.

다른 말로 하면
parent key를 두고, 그 parent key 아래에 table 영역을 두고
그 table에는 공통 유형의 데이터들을 두면서

여러개의 parent key, 여러개의 table을 두는 원리이다

{
    simpleDomainData1: {....},
    simpleDomainData2: {....},
    entities : {
        entityType1 : {....},
        entityType2 : {....}
    },
    ui : {
        uiSection1 : {....},
        uiSection2 : {....}
    }
}

최종본

{
    posts : {
        byId : {
            "post1" : {
                id : "post1",
                author : "user1",
                body : "......",
                comments : ["comment1", "comment2"]
            },
            "post2" : {
                id : "post2",
                author : "user2",
                body : "......",
                comments : ["comment3", "comment4", "comment5"]
            }
        },
        allIds : ["post1", "post2"]
    },
    comments : {
        byId : {
            "comment1" : {
                id : "comment1",
                author : "user2",
                comment : ".....",
            },
            "comment2" : {
                id : "comment2",
                author : "user3",
                comment : ".....",
            },
            "comment3" : {
                id : "comment3",
                author : "user3",
                comment : ".....",
            },
            "comment4" : {
                id : "comment4",
                author : "user1",
                comment : ".....",
            },
            "comment5" : {
                id : "comment5",
                author : "user3",
                comment : ".....",
            },
        },
        allIds : ["comment1", "comment2", "comment3", "comment4", "comment5"]
    },
    users : {
        byId : {
            "user1" : {
                username : "user1",
                name : "User 1",
            },
            "user2" : {
                username : "user2",
                name : "User 2",
            },
            "user3" : {
                username : "user3",
                name : "User 3",
            }
        },
        allIds : ["user1", "user2", "user3"]
    }
}
profile
Dream of being "물빵개" ( Go abroad for Dance and Programming)

0개의 댓글