서버 상태 vs 클라이언트 상태, 나눠서 관리해야 하는 이유
웹 애플리케이션을 개발하다 보면 화면에 보여줄 수많은 데이터를 관리해야 하는 순간을 맞이합니다. 다크 모드 설정부터 사용자 로그인 정보, 게시글 목록에 이르기까지 모든 것이 상태에 해당합니다. 하지만 모든 데이터를 하나의 전역 상태 저장소에 마구 섞어 관리하면 코드의 복잡성이 급격히 증가하고 예상치 못한 오류가 발생하기 쉽습니다.
상태(State)란 무엇이며 왜 나눌까?
상태는 쉽게 말해 웹 페이지에서 시간이 지남에 따라 변하는 모든 데이터를 의미합니다. 과거에는 Redux나 Context API 같은 하나의 도구로 프론트엔드의 모든 상태를 관리하는 것이 보편적이었습니다. 하지만 앱의 규모가 커지면서 서버에서 받아오는 데이터와 브라우저 내부에서만 쓰이는 데이터의 성격이 완전히 다르다는 점이 명확해졌습니다.
서버 상태 클라이언트 상태를 명확히 분리하지 않으면 비동기 데이터의 로딩 상태나 에러 처리, 캐싱 로직이 UI 상태와 복잡하게 얽히게 됩니다. 마치 서류함에 중요한 계약서와 개인 메모를 구별 없이 섞어 두어 필요한 문서를 제때 찾지 못하는 것과 같습니다. 따라서 각 데이터의 출처와 소유권에 따라 관리를 분리하는 것이 현대 프론트엔드 아키텍처의 핵심 원칙이 되었습니다.
화면 겉모습을 결정하는 '클라이언트 상태'
클라이언트 상태는 브라우저 내부에서 생성되고 소유되는 동적 데이터입니다. 사용자가 다크 모드 토글 스위치를 누르거나, 모달 창을 열고 닫거나, 드롭다운 메뉴를 선택하는 행동이 이에 해당합니다. 이 데이터들은 서버와의 통신 없이 사용자의 기기 안에서 즉각적으로 변경되고 사라집니다.
클라이언트 상태는 동기적으로 작동하며 항상 최신 데이터임이 보장됩니다. 네트워크 지연을 걱정할 필요가 없기 때문에 비교적 단순한 전역 상태 라이브러리나 컴포넌트 자체의 로컬 상태로 충분히 관리할 수 있습니다. UI의 시각적 형태를 제어하는 것이 주목적이므로 외부 시스템의 영향을 받지 않는 독립성을 가집니다.
원격 데이터를 담는 '서버 상태'의 특징
반면 서버 상태는 말 그대로 원격 서버에 저장되어 있으며 API 요청을 통해 받아오는 데이터입니다. 사용자 프로필 정보, 상품 목록, 결제 내역 등이 대표적인 예시입니다. 이 데이터의 진짜 소유권은 클라이언트가 아닌 서버에 있으며, 우리가 브라우저에서 보는 데이터는 일종의 스냅샷에 불과합니다.
따라서 서버 상태는 비동기적이며 항상 불안정 요소를 안고 있습니다. 내가 화면을 보고 있는 순간에도 다른 사용자가 데이터를 수정할 수 있어 언제든 오래된 데이터가 될 수 있습니다. 이 때문에 단순한 값의 저장을 넘어 데이터 요청, 캐싱, 주기적인 재요청, 에러 처리 등 까다로운 관리가 필요합니다.
React Query를 활용한 전역 상태 분리의 이점
이처럼 성격이 판이하게 다른 두 상태를 분리하기 위해 최근에는 React Query와 같은 전역 상태 분리 전용 도구가 널리 쓰입니다. React Query는 서버 상태의 캐싱과 동기화를 전담하여 처리해 주며, 개발자가 복잡한 네트워크 로직을 직접 구현하지 않도록 돕습니다.
이렇게 서버 상태 관리를 전용 라이브러리에 위임하면 클라이언트 상태 저장소는 본래의 목적인 UI 상태만 가볍게 유지할 수 있습니다. 코드의 가독성이 크게 향상되고, 데이터가 어디서 오고 어디서 관리되는지 직관적으로 파악할 수 있게 됩니다. 결국 서버 상태 클라이언트 상태 분리는 불필요한 리렌더링을 줄이고 앱의 전반적인 성능과 유지보수성을 극대화하는 결과를 가져옵니다.
결론: 깔끔한 상태 관리가 만드는 더 나은 개발 경험
결국 두 상태를 나눠서 관리하는 이유는 복잡성을 낮추고 각 데이터의 특성에 맞는 최적의 관리 방식을 적용하기 위해서입니다. UI 제어는 가벼운 클라이언트 상태 도구로, 원격 데이터 동기화는 전문적인 서버 상태 라이브러리로 분리할 때 애플리케이션은 훨씬 안정적으로 동작합니다. 올바른 상태 분리 전략을 고민하고 적용하는 것만으로도 더 쾌적한 개발 환경과 뛰어난 사용자 경험을 동시에 제공할 수 있습니다.