Notion Clone 내맘대로 상태관리론

Alang·2021년 9월 11일
0

처음의 시행착오

처음에는 각자의 컴포넌트가 필요한 상태만을 보유하는 방식이 메모리적으로 효율적이라고 생각해 각각의 Component에서 상태관리 및 필요한 정보를 api로부터 fetch하도록 코드를 진행했다.

하지만 이렇게되면 각각의 컴포넌트가 어떤 특정한 상태를 공유하고 있다면, 한 컴포넌트에서 상태변화가 이루어졌을때 해당 변화를 다른 컴포넌트에게 전달하기위해서 새로운 루트를 만들어줘야했고, 새로운 기능을 추가할때마다 이 작업을 반복해야하고 (본인은 이것을 물길을 낸다..라고 표현했다) , 또 복잡해지는 문제가 발생하였고 결국 수많은 버그가 생겨났다.

상태관리는 나무다...!

위와 같은 시행착오를 겪으며 도달했던 생각은 상태관리를 나무처럼 생각하자..! 였다. 나무의 가지는 필요한 물을 스스로 생산하지 못한다. 나무의 모든 가지는 뿌리로부터 물을 받는다.가 핵심이였다.

이 물을 데이터, 즉 상태라고 생각했을때, 하위 컴포넌트는 본인의 상태를 변화하기 위해서는(특히나 다른 컴포넌트와 상태를 공유한다면..!) 상위 컴포넌트에서의 setState를 통해서만 이루어지도록 하는것이다. 자기 자신만이 상태변화하는 것을 최소화 시킴으로서 다른 컴포넌트들과 동일한 데이터를 공유하도록하여, 누구는 최신화된, 누구는 최신화되지 않은 그러한 상황들을 별도로 물길을 파주지 않아도 방지할 수 있다.

효율적인 앱을 위해 줄여야할것

일단, 내가 생각했던 반드시 지켜야할것이라 생각했던 부분이 있다.

1. 통신의 최소화

서버와의 통신은 돈이다. 통신이 많으면 많을수록, 서버에서 부담하게 되는 비용은 커지게 된다. 앱을 상품이라 생각하고, 우리는 상품의 제작자라고 생각했을때, 불필요한 생산비용을 최소화시키는것은 필수적인 요소라 생각했다. 이부분을 고려했을때, 각각의 컴포넌트에서 fetch 수행을 하기보단 한곳의 컴포넌트(App)에서 fetch를 진행하는 로직을 통틀어 담당하는것이 통신 최소화를 위한 설계를 하는데 있어서 조금 더 편하다라는 생각을 했다.

다만 아직 고민이되는점은, 낙관적 업데이트 후, 꼭 다시 서버로부터 데이터를 받아와 렌더링을 할필요가 있을까..? 라는 점이다. 물론 실제 데이터가 서버까지 반영되었는지 명확한 확인을 위해서는 필요한 부분이라고 생각하지만, 다른 유저와 공유하는 데이터가 아닌 한 유저만을 위한 데이터라면 매 post,put 과 같은 요청이 아니라면, get 요청은 조금 더 최소화를 시켜도 되지 않을까.. 라는 생각을하게된다.

2. 렌더링의 최소화

상태가 변화했어도, 렌더링에 변화가 없다면, 이는 불필요한 렌더링이된다. 그리고 이러한 불필요한 렌더링은 화면의 깜빡임을 유발할수 있고, 유저입장에서 다소 친화적이지 않다( 이쁜 앱이 아니다). 내가 설계한 방식의 전역상태관리는 치명적인 단점이 있었다. 바로 상태변화가 이루어질때마다, 하위의 모든 컴포넌트가 다시 렌더링 될수 있다는 문제점이였다.

이를 개선하고자 생각한 방식은, '선택적 상태전송'이다.(물론 내가 지어낸말)

선택적 상태전송

각각의 컴포넌트에서 상위 컴포넌트로 상태변경 요청을 할때, sendState라는 boolean값의 인자를 함께 전달한다. 상위 컴포넌트는 해당인자를 받아, 변화된 상태를 아래에 전송할지, 말지를 정한다.

해당 방식을 사용하면, 하나의 요청이 다양한 상태변화를 일으킬때 효과적으로 작용했다.



예를 들어, 새로운 문서 작성을하면,

API에 새로운 문서를 생성한다는 POST 요청을하고,
만약 기존 문서의 하위로 Document를 생성한다면 기존의 문서를 Toggle하고 (ListPage 상태변경),
생성된 문서를 DocumentList에 반영하기위해 GET 요청을 해 List Page 상태를 변경하고,
생성된 문서의 id주소로 url을 변경하여 해당 id문서를 get하여 Content Page의 상태를 변경한다
과 같은 작업을 수행한다.

만약에 저 하나하나의 로직이 이미 함수로 구현되어있고, 해당 함수에서 setState수행을 한다면, 한번의 문서생성으로 적어도 3번의 렌더링을 진행하게 된다.

이와 같은 렌더링 횟수를 줄이기 위해, 2 , 3 의 해당되는 상태변화는 전역에서만 변화를 간직하고, 아래로 상태변화를 주지않은뒤, 마지막 4의 경우만 상태변화를 주게된다면, 모아두었던 상태를 한번에 하위 컴포넌트에게 반영해줄수 있다.

문제점

그렇다고해서 불필요한 렌더링이 모두 사라지지는 않았다. 이를 해결하기위해서, 전달자의 역할이 되는 List Page와 Content Page에서 아래로 전송하는 상태값이 실제로 변화되었는지를 확인하는 Validation 로직을 추가할 필요가 있다.

profile
안녕하세요. 개발자 지망생입니다.

0개의 댓글