[Notion Cloning] 회고 02 - State에 대한 고찰을 바탕으로

devBuzz142·2022년 4월 22일
0

VanillaJS_Component

목록 보기
2/2

개요

바닐라JS로 TodoApp을 만드는 것을 지나, 이번 Notion 클로닝 프로젝트를 하면서, 단순히 기능을 구현하는 것보단 구조에 대한 고민을 하였다. 당장에 구현하기 위해 억지로 얼기설기 덧붙인 코드가 아니라, 명확한 원칙을 갖고, 다소 부족한 점이 있더라도 원칙에 따른 코드를 작성해보고 싶었다.

우선 컴포넌트에 대한 고민을 하였다. 우리는 Component라고 불리는 단위로 기능을 구현하고 있다. 객체지향 프로그래밍의 Object와 비슷한 개념이라는 생각이 들었다. 상태state와 행동behavior을 가져, 현재 컴포넌트의 상태를 사용자가 볼 수 있게 UI로 렌더링한다.

컴포넌트가 렌더링하기 위하여, 컴포넌트의 현재 시점 (또는 어떤 시점)에서의 status에 대한 정보를 담는 data로 state를 사용한다. (React와 같은 프레임워크에선 state를 특별한 객체로 활용한다.) 물론 state를 사용하지 않고, 리터럴한 raw data를 represent하는 컴포넌트를 작성할 수도 있을 것이다. 그러나 그럴 경우 data의 변화를 반영하기 힘들고, 사용자와의 interaction을 기대할 수 없다. state는,

  • 시간이 지남에 따라, 유저와의 interaction에 따라 값이 변할 수 있는 data
  • 컴포넌터의 status에 대한 한 시점의 data를 담고 있다.
  • state의 값이 변하면, 컴포넌트는 이를 반영하여 새로이 렌더링한다.
  • state는 컴포넌트의 현재 status와 직결되고 이는 사용자가 보고있는 View와 직결되기 때문에, 무결해야한다.
    - 같은 state를 공유하는 서로 다른 컴포넌트가, 해당 state에 대하여. 다른 값을 가지고 있을 수 없다.
  • setState를 통해 state의 불병성을 유지한다.

어플리케이션 구조와 Data Flow

App

  • usernaem : 소유 여부를 기반으로 LoginPage / DocsRootPage 를 호출한다.

DocsRootPage

  • docs : root docs 목록 상태
  • editorId : 선택된 doc의 Id, 존재할 경우 해당 Editor 호출
  • isRich : T/F에 따라 Rich/Plain Editor 결정

DocsEditor

  • ...editingdoc(id, title, updatedAt, content, etc...) : 현재 호출된 editor의 doc content등 정보를 저장한다.
  • focustInfo : content의 어느 위치에 foucsing 중이었는지

State vs. Props(Data)

일전에 학교에서 리액트로 프로젝트를 하였을 때의 일이다. useState 함수를 배우고 나서, 컴포넌트 안의 거의 모든 변수를 useState를 사용하여 선언하였다. state의 정의에 대하여 별다른 생각을 하지 않고 마구잡이로 사용한 것이었다.

이번 프로젝트를 하면서, 컴포넌트 안에 있는 data 중에서 어떤 것을 state라는 개념으로 특별하게 다룰지에 대해서 고민하였다. 이 과정에서 React제공하는 state에 대한 문서들을 참고하였다.

이를 토대로, 적어도 이번 바닐라JS로 구현하는 Notion 클로닝 프로젝트에선 다음과 같은 방식으로 정의하기로 하였다.

state

  • 어떤 컴포넌트에 대한 현재 시점에서의 status로 해당 컴포넌트가 고유하게 소유한다.

  • 초기화된 이후론 setState 메서드를 통해서만 그 값이 변할 수 있다.

  • props로 전달 받았다면 state가 아니다.

  • 변하거나 intreactive하지 않는, 단순 raw data라면 state가 아니다.

  • 다른 state나 props를 가지고 계산 가능한가? state가 아니다.

  • props : 상위 컴포넌트로부터 전달 받은 data. 상위 컴포넌트로 부터 이벤트 핸들러, 단순 data, 상위 컴포넌트가 소유한 state의 value 등 다양한 종류의 props를 받을 수 있고, 이를 렌더링하는데 활요할 수 있다.

기존의 경우, DocsRootPage에서도 docs를 상태로 저장하고, 이를 props로 Sidebar에 전달한다음, Sidebar에서도 state로 저장하였다. 이 경우 Sidebar에서 해당 staet에 대한 조작을 한다면, Sidebar에서 setState를 하고 DocsRootPage에서도 setState를 하거나, DocsRootPage에서만 setState를 한다면, Sidebar에서 굳이 state로 소유할 필요가 없는 상황이 발생하였다.

정립한 원칙에 따라, 상위 컴포넌트인 DocsRootPage에서 저장한 docs는, Sidebar로 prosp에 담겨 전달되지만, Sidebar의 상태로 저장되지 않는다. (저장하지 않기로 하였다.) Sidebar에선 해당 data를 조작하고 렌더링할 수 있다. 그러나 Sidebar에서는 단순히 data로 사용할 뿐이기에, 원래 상태의 무결성을 해치지 않기 위해 state로 저장하지 않았다.

profile
가보자구

0개의 댓글