본문 바로가기

카테고리 없음

실전에서 바로쓰는 Next.js | 지역 및 전역 상태 관리

리액트 애플리케이션에서는 상태 관리가 아주 중요한 부분을 차지합니다. 

Next.js도 리액트 프레임워크이므로 마찬가지입니다. 

 

일반적으로 상태라는 것은 동적인 정보의 일종으로, 높은 수준의 상호 작용이 가능한 UI를 구현하거나 사용자 경험을 더 뛰어나게 만들기 위한 필수 요소입니다.

 

UI는 사용자와 인터렉션에 따라서 반응할 수 있는데, 이는 전적으로 개발자가 변경된 상태를 어떻게 다루느냐에 따라 결정됩니다. 

 

상태 관리 -> 애플리케이션에 더 뛰어난 상호작용 등의 기능을 구현할 수 있습니다. 하지만 그만큼 애플리케이션의 복잡도도 증가합니다.

 

리액트에서 데이터의 흐름은 단방향이라서 부모 컴포넌트는 자식에게 props의 형태로 상태를 전달할 수는 있지만 반대로 자식이 부모에게 상태를 전달할 수는 없습니다. 지역 상태는 클래스 컴포넌트나 훅을 사용해서 별다른 어려움 없이 관리할 수 있지만 전역 상태는 단방향 데이터 흐름 때문에 관리하기 어렵습니다. 

 

지역 상태 관리

지역 상태 관리에 있어서 애플리케이션의 상태는 컴포넌트 스코프(scope) 상태를 의미합니다. 

 

import React, { useState } from 'react';

function Counter({ initialCount = 0 }) {
	const [count, setCount] = useState(initialCount);
    
    return (
    	<div>
            <b>Count is: {count}</b><br />
            <button onClick={() => setCount(Count + 1)}>
                Increment + 	
            </button>
            <button onClick={() => setCount(Count - 1)}>
                Decrement -	
            </button>
        </div>
    )

}

export default Counter

 

애플리케이션에서는 지역 상태만 관리하는 경우가 많습니다. 이때는 리액트의 useState 훅만으로도 필요한 모든 것을 구현할 수 있습니다.(ex: 아톰 컴포넌트)

 

문제는 전체 컴포넌트를 아우르는 전역 애플리케이션 상태 관리에 있습니다. 예를 들어 온라인 상거래 사이트의 경우 장바구니에 물건을 추가하면 이 정보는 화면의 내비게이션 바에 항상 표시됩니다.

전역 상태 관리

애플리케이션의 전역 상태 관리는 여러 컴포넌트들이 공유하는 상태를 의미합니다. 어떤 컴포넌트라도 접근 및 수정이 가능한 상태인 것입니다. 리액트 컴포넌트는 단방향으로 밖에 데이터를 전달할 수 없습니다. 이는 에러가 발생할 가능성을 줄이고 디버깅하기 쉬우며 효율적이지만 애플리케이션 개발이 복잡해진다는 단점이 있습니다.

 

 

위와 같은 쇼핑 카트 앱이 있다고 했을 때 물건을 Add to cart를 누르면 Number of items가 증가해야하는데, 가장 큰 문제는 이 두사이에 어떠한 연결점도 없다는 것입니다. 사용자가 담기 버튼을 클릭했을 때 아이템 숫자를 업데이트할 명백한 방법도 없습니다. 페이지를 이동한 경우에는 어떻게 될까요? 컴포넌트가 가지고 있는 데이터들은 언마운트되는 즉시 지역 상태를 잃게 됩니다.

 

최근 애플리케이션에서는 다양한 라이브러리를 사용해서 이런 상태 관리를 구현합니다. Redux, Recoil, MobX가 대표적이며 그 외에도 다양한 라이브러리가 있습니다. 사실 리액트에서는 외부 라이브러리를 사용할 필요없이 Context API를 사용해서 애플리케이션의 전역 상태를 관리할 수 있습니다.

 

Apollo 클라이언트와 메모리 캐시를 이용한 전역 상태 관리 방식도 존재합니다. Apollo 클라이언트를 사용하면 애플리케이션의 전역 데이터를 정형화된 질의 언어(query language)로 다룬다는 새로운 관점을 얻을 수 있습니다.

Context API

2018년 공개된 리액트 버전 16.3 부터는 Context API를 공식적으로 사용할 수 있습니다.  이 API는 특정 콘텍스트 내의 모든 컴포넌트 간에 데이터를 공유할 수 있는 매우 직관적인 방법을 제공합니다. 명시적으로 다른 컴포넌트에 속성값 형태로 데이터를 전달할 필요도 없고 심지어 자식 컴포넌트가 부모 컴포넌트에게 데이터를 공유할 수도 있습니다

 

Redux

리액트가 공개된지 2년이 흐른 2015년 무렵에는 오늘날처럼 큰 규모의 애플리케이션 상태를 관리할 수 있는 프레임워크나 라이브러리가 많지 않았습니다. 특히 Redux는 리액트 커뮤니티에서 큰 화제를 모았으며 리액트로 일정 규모 이상의 애플리케이션을 만들 때 쓰는 사실상 표준 상태 관리자가 되었습니다. 

 

리액트 Context API와 미들웨어 없는 순수한 Redux는 큰 차이가 없습니다. 하지만 Redux를 사용하면 수많은 플러그인, 미들웨어, 디버깅 툴을 사용할 수 있으며 별다른 노력 없이도 웹 애플리케이션의 복잡한 비즈니스 로직을 쉽게 만들고 확장할 수 있다는 장점이 있습니다.

 

정리

이 장에서는 리액트 내장 Context API 및 훅을 이용한 상태 관리, Redux를 사용한 상태관리 방법을 살펴보았습니다.

이 외에도 Mobx, Recoil, XState, Unistore와 같이 수없이 많은 라이브러리나 도구를 사용해서 애플리케이션의 전역 상태를 관리할 수 있습니다. Redux를 사용할 때와 같은 방법으로 Next.js에서 이런 라이브러리를 클라이언트나 서버에서 사용할 수 있습니다.  그리고 Apollo의 GraphQL 클라이언트와 인메모리 캐시를 사용해서 애플리케이션의 상태를 관리하고, 정형화된 질의 언어를 사용해서 전역 상태 데이터를 질의하고 수정할 수도 있습니다.