이번 5주차는 상태를 나누는 기준 , 즉 각각의 상태를 어디에 둘 것인가를 주제로 과제를 하였다.
1번 url의 상태
2번 서버에서 호출하는 데이터
3번 클라이언트에서 필요한 상태
이렇게 3가지를 생각해 볼 수 있다.
input 필터 값들을 예로 들을 수 있다. '검색어', '페이지 번호' , '카테고리' 등등 이런 것들은 url에서만 관리를 하고 따로 중복되는 내부 상태 선언은 하지 않는다. 오직 url 쿼리파람 자체에서 데이터 정보를 가져오고 셋팅을 한다.
url 쿼리파람 핸들링은 nuqs 라이브러리를 통해 관리하는 법을 배웠다.
프론트엔드 개발자라면 모를 수 없는 라이브러리 Tanstack Query를 통해 관리하는 법을 배웠다.
서버에서 호출해와 보관하는 데이터는 리액트 쿼리를 적극 활용한다. 캐싱 정책을 사용하여 api 호출 최적화도 가능하다.
나는 리액트 쿼리의 query에서 캐시키만 팩토리 패턴으로 관리를 했었는데 밑에처럼 쿼리 옵션들 자체를 팩토리 패턴으로 관리하는 방법을 배워 실무에서도 적용해 볼 수 있겠다 생각을 하였다.

클라이언트 상태 관리는 모두 잘 알다시피, 내부 로컬 상태로 관리하면 된다.
물론 렌더링 중 계산할 수 있는 파생값은 별도 state로 들고 있지 않는 편이 좋다.
한 컴포넌트나 한 화면 안에서만 필요한 상태라면 React의 useState로 충분하다.
예를 들어 모달 열림 여부, 입력 중인 draft 값, 드롭다운 open 상태처럼 컴포넌트 수명 안에서만 의미가 있는 값은 로컬 상태
로 두는 게 자연스럽다.
반대로 여러 화면이나 서로 떨어진 컴포넌트에서 함께 써야 하는 클라이언트 상태라면 전역 상태를 고려할 수 있다.
이때는 Context로 관리할 수도 있고, Zustand 같은 상태 관리 라이브러리를 사용할 수도 있다.
이번 과제에서는 비로그인 사용자의 장바구니와 위시리스트를 Zustand로 관리했다.
이 상태들은 서버에서 내려온 상품 목록 데이터와는 성격이 다르다. 상품 데이터의 원본은 서버지만, 비로그인 사용자의 장바
구니와 위시리스트는 현재 브라우저 안에서 사용자가 직접 만든 상태이기 때문이다.
다만 Next.js에서 Zustand persist를 사용할 때는 hydration을 조심해야 했다.
서버에서는 localStorage를 읽을 수 없지만, 클라이언트에서는 저장된 장바구니와 위시리스트를 복원할 수 있다.
이때 서버가 렌더링한 초기 UI와 클라이언트가 처음 렌더링한 UI가 달라지면 hydration mismatch가 발생할 수 있다.
그래서 이번 구현에서는 skipHydration: true로 Zustand persist의 자동 복원을 막고, 클라이언트 마운트 이후
rehydrate()를 명시적으로 호출했다.
복원이 끝나기 전에는 헤더의 장바구니/위시리스트 개수를 -로 보여주고, 상품 카드의 담기/찜 버튼은 비활성화했다.
클라이언트 상태라고 해서 무조건 전역 store에 넣는 것이 아니라, 먼저 상태의 수명과 공유 범위를 봐야 했다.
이번 과제를 하면서 전역 상태 관리의 핵심은 “어떤 라이브러리를 쓰느냐”보다 “이 상태의 원본이 어디에 있느냐”를 먼저 정하는 것이라는 점을 배웠다.