COCO World

[리액트/React] 상태 관리는 왜, 어떻게 하는가? 본문

Front-End/React

[리액트/React] 상태 관리는 왜, 어떻게 하는가?

코코월드주인장 2023. 6. 11. 18:26

🌱 리액트에서의 State(상태)

 

의미

 

  • State는 컴포넌트 내에서 지속적으로 변경이 일어나는 값을 관리하기 위하여 사용한다
  • 개발자가 의도한 동작에 의해 변할 수도 있고 사용자의 입력에 따라 새로운 값으로 변경될 수도 있다
  • State 값이 변경되고 재렌더링이 필요한 경우에 React가 자동으로 계산하여 변경된 부분을 렌더링 한다

State는 컴포넌트에 대한 데이터 또는 정보를 포함하는데 쓰이는 리액트 내장 객체이다.

컴포넌트 상태는 시간이 지남에 따라 변경될 수 있는데 변경될 때마다 컴포넌트는 다시 렌더링해야 사용자에게 변경된 상태값을 보여줄 수 있다. State 변경은 사용자 작업 또는 시스템 생성 이벤트에 대한 응답으로 발생할 수 있으며 이 변경은 컴포넌트의 동작, 렌더링 방법을 결정한다.

 

3가지의 상태 종류

  • 전역상태(Global State) : 특정 컴포넌트 안에서만 관리되는 상태. 다른 컴포넌트들과 데이터를 공유하지 않는다. 예를 들어, input, selectbox 등에서 사용자의 입력값을 받는 경우가 있다. ( 보통 Form 데이터들이 지역상태에 속한다.)
  • 컴포넌트 간 상태(Cross Component State) : 여러가지 컴포넌트에서 관리되는 상태를 말한다. 다수의 컴포넌트에서 쓰이고, 또 영향을 미치는 상태를 뜻하며, 프로젝트 곳곳에서 쓰이는 모달을 예로 들 수 있다. 보통 상위 컴포넌트에서 하위 컴포넌트로 Props을 넘겨  해당 컴포넌트까지 전달되도록 하는 Props Drilling 방식을 필요로 한다.
  • 전역 상태(Local State) : 프로젝트 전체에 영향을 끼치는 상태이다. 이 또한 Prop Drilling 방식을 활용해 부모에서 자식으로 데이터를 전달한다.

 

Props Drilling이란?

더보기

props를 오직 하위 컴포넌트로 전달하는 용도로만 쓰이는 컴포넌트를 거치며 컴포넌트에서 다른 컴포넌트로 데이터를 전달하는 과정이다.

 

상위 컴포넌트 ➠ 중간 컴포넌트 ➠ 중간 컴포넌트 ➠ ... ➠ 타겟 컴포넌트

 

이런 props 전달 과정이 많지 않다면 큰 문제가 없지만, 프로젝트가 방대하고, 많은 중간 컴포넌트 과정을 거치면 유지보수가 힘들고, 코드 추적이 어려워 가독성이 떨어진다.

 

 

여기서 잠깐, Props랑 State의 쓰임새가 뭔가 헷갈리는데..

 

리액트의 State VS React

Props는 컴포넌트간 전달이 되지만 State는 컴포넌트 안에서 관리되고 시간이 지나면서 바뀌는 동적인 데이터이다.

 

Props

  • 부모 컴포넌트에서 자식 컴포넌트로 전달되는 읽기 전용 데이터 (= 불변의 데이터)
  • 함수의 매개변수나 클래스형 컴포넌트의 this.props 객체를 통해 사용할 수 있다
  • props는 변경되지 않으며, 자식 컴포넌트에서 전달받은 데이터를 사용하여 렌더링한다 ( = 부모 요소에서 데이터를 설정)

 

State

  • 상태에 따라 값이 변화한다 (= 가변의 데이터)
  • 상태 값 직접 변경 가능 ( = 구성 요소에 의해 데이터 설정 가능)
  • state값이 변경되면 컴포넌트를 다시 렌더링 해야한다
  • 외부에는 비공개이며, 컴포넌트가 스스로 관리해야 하는 것이다

 

🌱 리액트에서의 상태 관리에 대해 알아보자.

 

초기의 리액트의 상태관리는 MVC(Model-View-Controller) 방식인 '양방향 데이터 흐름'으로 UI를 관리하였다.

그러나 시간이 흘러 모델 하나에 의존되는 뷰가 많아지면, 컨트롤러의 복잡도가 올라가고, 데이터 흐름을 이해하기 어려운 상황이 발생하여 유지보수와 에러 대처에도 곤란한 상황이 발생한다. 이러한 복잡성을 해결하기 위해 단방향 데이터 흐름을 가지는 리액트가 등장하게 되었다.

 

MVC 패턴이란?

더보기

Model 상태가 바뀌면 View 상태도 바뀌며, View 에서 다시 변경이 일어난다면 다시 Model 상태도 바뀌는데 이를 Cotroller가 조작하는 원리이다. 한쪽에서 상태가 바뀌면 다른 한쪽도 상태가 바뀌는 상호작용 형태를 나타내 '양방향'을 의미한다.

 

🌱 상태 관리 라이브러리

그렇다면 상태 관리는 어떻게 해야할까? 

개념적으로는 props를 상속하여 넘겨주지만 우리는 보통 라이브러리를 사용하여 상태관리를 해주기 때문에 이에 대해 알아볼 필요가 있다.

각각의 차이가 있어 적재적소에 사용하는 것이 좋고, 보편적으로 모두 경험해보는 것이 좋을 것 같다. 여기선 좋은 상태관리에 대한 포스팅이므로 라이브러리에 관해서는 관련 게시물에서 자세히 서술할 예정이다.

 

  • Redux : 가장 대중적이며 활성화되어있는 커뮤니티로 많이 쓰이는 라이브러리이다. 많은 Tool과 미들웨어가 존재하지만 복잡한 사용법으로 인해 초기의 학습이 필요하고, 대중적인만큼 무분별하게 사용되는 감이 있다.
  • Context API : 리액트 Hook이 나오면서 비대한 Redux 대신 사용되는 라이브러리이다.Context는 수단일 뿐 사실상 상태관리 자체는 리액트 컴포넌트의 useState와 useReducer로 하게 된다. 프로젝트가 방대해질수록 중첩에 따른 영향으로 성능 이슈를 유발할 수 있다.
  • Recoil : Redux, MobX와 같은 타 라이브러리와 다르게 오직 리액트만을 위해 태어난 라이브러리이다. 리액트 상태를 깊게 직접 다룰 수 있고, 장기적으로 동시성 모드나 Suspense같은 리액트의 실험적 기능까지 확대 목적으로 갭라 되고 있지만 아직까지 사용빈도는 Redux에 밀린다.
  • SWR : Stable-While-Rebalidate, 데이터를 검증하는 동안 stable(cache) 데이터를 사용하는 것으로 cache된 데이터를 보여주고 데이터 요청을 보낸 후 새롭게 받은 데이터를 보여준다. useSWR을 import해서 사용한다.
  • MobX : 사용률은 Redux보다 떨어지며, 리덕스보다는 다루기 쉽다. Store가 여러 개로 존재할 수 있어 상태 변경 시 여러 Store가 영향을 받을 수 있다.

 

🌱리액트에서 좋은 상태 관리란?

  • State는 관련 컴포넌트들과 최대한 가까이 배치 되는게 좋다
  • State가 관련 컴포넌트와 멀어질수록 상태와 컴포넌트 사이에 관련 없는 컴포넌트의 리렌더까지 일으킬 위험이 있다
  • State들은 기능에 따라 잘 불리가 되어야 이후 유지 보수시에 사이드 이펙트를 최소화할 수 있다
  • 서로 관련 없는 컴포넌트들의 State가 한번에 관리되면 결합도가 높아지고 후에 어플리케이션이 비대화 될수록 의도치 않은 영향을 줄 수 있으며, 격리되어 있지 않은 탓에 코드의 재사용성도 떨어진다