스크랩

왜 우리는 아직도 상태관리로 고생할까? 프론트엔드가 숨기고 있던 네 가지 난제

왜 우리는 아직도 상태관리로 고생할까? 프론트엔드가 숨기고 있던 네 가지 난제

핵심 요약

React를 비롯한 프론트엔드 생태계에는 Redux, Zustand, Jotai, Recoil 등 수많은 상태관리 도구가 있지만, 정작 근본적인 난제 몇 가지는 아직 제대로 조명받지 못했습니다. 이 글에서는 그 네 가지 문제를 짚어보고, 사실 이들이 별개의 문제가 아니라 하나로 얽힌 문제라는 점을 소개합니다.

1. 상태의 공유 범위를 바꾸기 어렵다

우리는 보통 상태를 "지역 상태"와 "전역 상태" 두 가지로만 나눠서 이야기합니다. 하지만 실제 애플리케이션을 만들다 보면 이 두 개념만으로는 설명이 안 되는 상태들이 등장합니다. 특정 컴포넌트 트리 안에서만 공유되는 "공유 상태" 같은 것들이죠.

문제는 이 공유 범위가 개발 과정에서 계속 변한다는 점입니다. 처음엔 한 컴포넌트에서만 쓰던 상태가 어느 순간 형제 컴포넌트와 공유해야 하고, 나중엔 페이지 전체로 확장되기도 합니다. 그런데 기존 상태관리 도구들은 이런 "범위의 변화"를 매끄럽게 다룰 방법을 제공하지 않습니다.

2. 공유 상태의 수명을 표현하기 어렵다

범위 문제를 해결하겠다고 지역 상태를 덜컥 전역 상태로 바꿔버리면 새로운 골칫거리가 생깁니다. 상태가 실제로 필요한 기간보다 훨씬 오래 살아남아 버리는 것이죠.

지역 상태였을 때는 컴포넌트가 사라지면 자동으로 정리됐지만, 전역 상태로 옮기는 순간부터는 개발자가 직접 reset, clean 같은 로직을 챙겨야 합니다. 즉, 원래는 신경 쓸 필요조차 없던 "상태의 생애주기 관리"라는 새로운 책임이 생겨버립니다.

3. 파생 상태를 효율적으로 공유하기 어렵다

hook은 로직을 재사용하기엔 좋지만, 같은 파생 상태에 대한 계산을 재사용하는 방법은 제공하지 않습니다. 여러 컴포넌트에서 같은 원본 데이터로부터 같은 계산을 해야 할 때, hook만으로는 계산이 중복 실행됩니다.

useMemo나 useContext로 이 문제를 우회하려는 시도도 있지만, 이 도구들은애초에 이 문제를 풀기 위해 설계된 게 아닙니다. 순수한 계산이라면 중복 계산의 비효율 정도만 감수하면 되지만, 부수효과(side effect)가 얽힌 계산이라면 기존 도구로는 제대로 해결이 안 됩니다.

4. 상태를 기능 단위로 응집시키기 어렵다

이상적으로는 하나의 기능에 필요한 코드가 한 파일 안에, 못해도 서로 가까운 파일들 안에 모여 있어야 합니다. hook으로 추상화하면 겉보기엔 하나의 훅이 하나의 기능을 담당하는 것처럼 보입니다.

하지만 실제 계산 모델에서는 여러 곳에서 같은 훅을 호출해도 같은 인스턴스로 동작하지 않습니다. 그래서 부수효과가 필요한 로직에서는 이 방식을 쓸 수가 없죠. 결국 useContext, useEffect 등을 동원하게 되고, 이 과정에서 같은 기능과 관련된 코드가 서로 멀리 떨어진 여러 파일로 흩어지고 맙니다.

사실은 하나의 문제였다

흥미로운 점은 이 네 가지가 각각 독립된 문제가 아니라는 것입니다. 하나의 근본 문제가 여러 얼굴로 드러난 것에 가깝습니다.

공유 범위가 바뀌면 표현 방법도 바뀌어야 하고, 공유 상태에는 자연스러운 수명이 없으며, 파생 상태의 유일성을 보장하기 어렵다. 그리고 그 결과로 상태를 기능 단위로 응집시키는 것도 어려워진다.

즉, 범위·수명·파생·응집이라는 네 가지 증상은 모두 같은 뿌리에서 뻗어 나온 가지들인 셈입니다.

마치며

이 글은 문제 제기에 집중했고, 실제 해결책은 후속 글에서 다룰 예정이라고 합니다. 상태관리 라이브러리를 고를 때마다 "이걸 쓰면 되는 걸까?" 고민해본 적 있다면, 도구 선택 이전에 이 네 가지 구조적 난제를 먼저 이해해두는 것이 좋은 출발점이 될 것 같습니다.


원문: https://news.hada.io/topic?id=32794