TIL - 20260718

juni·2026년 7월 18일

TIL

목록 보기
407/468

0718 프론트엔드 실무 심화 (1/N): 상태 관리와 서버 상태 관리


✅ 1. 프론트엔드 상태란 무엇인가?

  • 상태(State)는 화면이 현재 어떤 값을 기준으로 보여지고 있는지를 결정하는 데이터입니다.
  • 프론트엔드에서는 버튼이 열려 있는지, 모달이 보이는지, 검색어가 무엇인지, API로 받아온 상품 목록이 무엇인지, 로그인한 관리자가 누구인지 같은 값들이 모두 상태입니다.
  • React에서는 상태가 바뀌면 화면이 다시 렌더링됩니다.
상태 변경
  ↓
React 렌더링
  ↓
화면 변경

➕ 1-1. 상태 예시

상담 신청 모달이 열려 있는가?
선택한 상품은 무엇인가?
검색어는 무엇인가?
현재 페이지 번호는 몇 번인가?
API 로딩 중인가?
에러가 발생했는가?
로그인한 관리자 정보는 무엇인가?
상품 목록 데이터는 무엇인가?
  • 프론트엔드 개발에서 상태 관리는 화면 품질과 유지보수성에 직접 영향을 줍니다.
  • 상태를 아무 데나 두면 화면이 복잡해지고 버그가 늘어납니다.

✅ 2. 상태 관리를 잘해야 하는 이유

  • 상태 관리는 단순히 useState를 쓰는 문제가 아닙니다.
  • 어떤 상태를 어디에 둘지, 서버 데이터와 로컬 UI 상태를 어떻게 분리할지 결정하는 설계 문제입니다.

➕ 2-1. 상태 관리가 안 좋을 때 생기는 문제

모달이 의도치 않게 닫힘
검색 조건이 초기화됨
페이지 이동 후 필터가 사라짐
API 데이터를 전역 상태에 넣고 계속 꼬임
로딩/에러 처리가 화면마다 다름
관리자 테이블 새로고침 후 상태가 이상함
같은 데이터를 여러 곳에서 따로 관리함

➕ 2-2. 좋은 상태 관리의 효과

화면 흐름이 예측 가능함
컴포넌트 역할이 명확함
API 데이터 갱신이 쉬움
필터/페이지네이션 유지가 쉬움
버그 추적이 쉬움
AI에게 작업을 맡겨도 결과가 안정적임
  • 특히 관리자 페이지는 검색, 필터, 테이블, 모달, 권한, 엑셀 다운로드가 섞이기 때문에 상태 설계가 중요합니다.

✅ 3. 상태의 종류

  • 프론트엔드 상태는 크게 5가지로 나눠서 보면 이해하기 쉽습니다.
상태 종류의미예시
로컬 UI 상태한 컴포넌트 안에서만 쓰는 상태모달 열림, 탭 선택
전역 클라이언트 상태여러 컴포넌트가 공유하는 상태로그인 사용자, 테마
서버 상태API로 받아온 데이터상품 목록, 상담 목록
URL 상태주소에 남겨야 하는 상태검색어, 페이지, 필터
폼 상태사용자가 입력 중인 값이름, 전화번호, 상품 선택
  • 이 구분이 중요합니다.
  • 모든 상태를 전역 상태로 넣으면 안 되고, 모든 상태를 useState로만 처리해도 안 됩니다.

✅ 4. 로컬 UI 상태

  • 로컬 UI 상태는 특정 컴포넌트 안에서만 필요한 상태입니다.
  • 다른 화면이나 다른 컴포넌트가 알 필요 없는 값입니다.

➕ 4-1. 예시

드롭다운 열림 여부
상담 신청 모달 열림 여부
현재 선택된 탭
토글 ON/OFF
hover 상태
간단한 confirm 모달 상태

➕ 4-2. useState 예시

function ProductDetailPage() {
  const [isConsultModalOpen, setIsConsultModalOpen] = useState(false);

  return (
    <>
      <button onClick={() => setIsConsultModalOpen(true)}>
        상담 신청
      </button>

      {isConsultModalOpen && (
        <ConsultModal onClose={() => setIsConsultModalOpen(false)} />
      )}
    </>
  );
}
  • 이런 상태는 굳이 전역 상태로 올릴 필요가 없습니다.
  • 가까운 곳에 두는 것이 가장 좋습니다.

✅ 5. 전역 상태

  • 전역 상태(Global State)는 여러 컴포넌트에서 공유해야 하는 클라이언트 상태입니다.
  • 예를 들어 로그인한 관리자 정보, 권한, 테마, 사이드바 접힘 여부 같은 값입니다.

➕ 5-1. 전역 상태로 둘 만한 것

로그인한 관리자 정보
관리자 권한
테마 설정
사이드바 접힘 여부
전역 알림 토스트
전역 Confirm 모달

➕ 5-2. 전역 상태로 두면 안 좋은 것

상품 목록 API 결과
상담 목록 API 결과
검색 결과
페이지네이션 결과
서버에서 가져온 대부분의 목록 데이터
  • 서버에서 가져온 데이터는 전역 상태보다 TanStack Query 같은 서버 상태 관리 도구로 관리하는 것이 좋습니다.
  • 전역 상태는 “클라이언트 안에서 유지해야 하는 상태”에 집중해야 합니다.

✅ 6. 서버 상태란 무엇인가?

  • 서버 상태(Server State)는 프론트엔드가 소유한 데이터가 아니라 서버에서 가져오는 데이터입니다.
  • 상품 목록, 상담 목록, 주문 목록, 배너 목록, FAQ, 관리자 목록은 모두 서버 상태입니다.
프론트엔드:
데이터를 보여줌

백엔드:
데이터의 실제 원본을 가짐

즉, 프론트는 서버 데이터를 임시로 캐싱해서 보여주는 것

➕ 6-1. 서버 상태의 특징

비동기로 가져옴
로딩 상태가 있음
에러 상태가 있음
캐싱이 필요함
다른 사용자가 변경할 수 있음
시간이 지나면 stale해질 수 있음
수정 후 다시 갱신해야 함
  • 서버 상태는 일반 useState로 관리하기 까다롭습니다.
  • 그래서 TanStack Query 같은 도구가 필요합니다.

✅ 7. 서버 상태를 전역 상태에 넣으면 생기는 문제

  • 예전에는 Redux 같은 전역 상태에 API 결과를 넣는 방식이 많았습니다.
  • 하지만 서버 상태를 전역 상태로 직접 관리하면 코드가 복잡해집니다.

➕ 7-1. 문제 예시

API 호출 코드가 여러 곳에 흩어짐
로딩/에러 상태를 직접 관리해야 함
캐시 만료 기준이 없음
수정 후 목록 갱신을 직접 처리해야 함
같은 API를 여러 컴포넌트에서 중복 호출함
뒤로가기 시 데이터 유지가 어려움

➕ 7-2. 나쁜 예시

const [products, setProducts] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);

useEffect(() => {
  setIsLoading(true);

  fetch('/api/products')
    .then((res) => res.json())
    .then((data) => setProducts(data.items))
    .catch((err) => setError(err))
    .finally(() => setIsLoading(false));
}, []);
  • 작은 화면에서는 괜찮아 보이지만, 목록/필터/페이지네이션/수정/삭제가 붙으면 금방 복잡해집니다.

✅ 8. TanStack Query란 무엇인가?

  • TanStack Query는 React에서 서버 상태를 관리하기 위한 라이브러리입니다.
  • API 호출, 캐싱, 로딩, 에러, 재요청, 데이터 무효화, 페이지네이션, optimistic update 같은 기능을 도와줍니다.
React Component
  ↓
useQuery / useMutation
  ↓
API 호출
  ↓
캐싱
  ↓
로딩/에러/성공 상태 제공

➕ 8-1. TanStack Query가 해결해주는 것

API 로딩 상태 관리
에러 상태 관리
응답 데이터 캐싱
같은 queryKey 중복 요청 방지
데이터 stale 관리
수정 후 목록 자동 갱신
페이지 이동 후 캐시 재사용
백그라운드 refetch
  • 서버 상태는 TanStack Query에 맡기고, 로컬 UI 상태는 React state로 관리하면 구조가 깔끔해집니다.

✅ 9. queryKey

  • queryKey는 서버 상태 캐시를 구분하는 고유한 키입니다.
  • TanStack Query에서 가장 중요한 개념 중 하나입니다.

➕ 9-1. queryKey 예시

['products']
['product', productId]
['admin', 'consults', { page, status, source }]
['admin', 'orders', { page, keyword }]
  • queryKey가 같으면 같은 캐시를 공유합니다.
  • 검색 조건이나 페이지가 다르면 queryKey도 달라져야 합니다.

➕ 9-2. 관리자 상담 목록 queryKey

const queryKey = [
  'admin',
  'consults',
  {
    page,
    limit,
    status,
    source,
    keyword,
    startDate,
    endDate,
  },
];
  • 필터 조건이 queryKey에 들어가야 조건이 바뀔 때 새 데이터를 가져옵니다.
  • queryKey 설계가 엉성하면 다른 조건의 데이터가 섞일 수 있습니다.

✅ 10. useQuery 기본 사용

➕ 10-1. 상품 목록 조회 예시

function ProductListPage() {
  const { data, isLoading, isError, error } = useQuery({
    queryKey: ['products'],
    queryFn: () => productApi.getProducts(),
  });

  if (isLoading) {
    return <ProductListSkeleton />;
  }

  if (isError) {
    return <ErrorMessage message="상품 목록을 불러오지 못했습니다." />;
  }

  return <ProductList products={data.items} />;
}

➕ 10-2. 장점

  • isLoading, isError, data를 바로 사용할 수 있습니다.
  • 같은 queryKey를 쓰는 다른 컴포넌트가 있으면 캐시를 재사용할 수 있습니다.
  • API 호출 상태를 직접 useState로 관리하지 않아도 됩니다.

✅ 11. staleTime과 gcTime

  • TanStack Query에서는 데이터가 언제 오래된 것으로 볼지, 캐시를 언제 지울지 정할 수 있습니다.
옵션의미
staleTime데이터가 fresh로 간주되는 시간
gcTime사용되지 않는 캐시를 메모리에서 제거하기까지 시간

➕ 11-1. 예시

useQuery({
  queryKey: ['products'],
  queryFn: () => productApi.getProducts(),
  staleTime: 1000 * 60,
  gcTime: 1000 * 60 * 5,
});
  • staleTime: 1분이면 1분 동안은 같은 데이터를 fresh로 봅니다.
  • 상품 카테고리, FAQ, 배너처럼 자주 안 바뀌는 데이터는 staleTime을 길게 줄 수 있습니다.

➕ 11-2. 기준 예시

상품 카테고리:
5분 ~ 30분

배너 목록:
1분 ~ 10분

관리자 상담 목록:
짧게 또는 조건 변경 시 refetch

관리자 통계:
1분 ~ 5분

로그인 사용자 정보:
상황에 따라 길게 유지
  • 무조건 짧게 잡으면 API 호출이 많아지고, 너무 길게 잡으면 오래된 데이터가 보일 수 있습니다.

✅ 12. useMutation

  • useMutation은 서버 데이터를 생성, 수정, 삭제할 때 사용합니다.
  • 상담 신청, 상품 수정, 상태 변경, 배너 삭제, 엑셀 Export 요청 같은 작업에 적합합니다.

➕ 12-1. 상담 신청 mutation 예시

const createConsultMutation = useMutation({
  mutationFn: (payload: CreateConsultPayload) => {
    return consultApi.createConsult(payload);
  },
  onSuccess: () => {
    alert('상담 신청이 완료되었습니다.');
    closeModal();
  },
  onError: (error) => {
    showToast('상담 신청 중 문제가 발생했습니다.');
  },
});

➕ 12-2. 사용 예시

function handleSubmit(values: CreateConsultFormValues) {
  createConsultMutation.mutate({
    name: values.name,
    phone: values.phone,
    productId: values.productId,
  });
}
  • isPending을 사용하면 버튼 중복 클릭을 막을 수 있습니다.
<button
  type="submit"
  disabled={createConsultMutation.isPending}
>
  {createConsultMutation.isPending ? '신청 중...' : '상담 신청'}
</button>

✅ 13. invalidateQueries

  • 데이터를 수정한 뒤에는 관련 목록을 다시 가져와야 합니다.
  • TanStack Query에서는 invalidateQueries로 특정 queryKey를 무효화할 수 있습니다.

➕ 13-1. 상담 상태 변경 후 목록 갱신

const queryClient = useQueryClient();

const updateStatusMutation = useMutation({
  mutationFn: adminConsultApi.updateStatus,
  onSuccess: () => {
    queryClient.invalidateQueries({
      queryKey: ['admin', 'consults'],
    });
  },
});
  • 상담 상태를 변경한 뒤 관리자 상담 목록을 다시 가져오게 할 수 있습니다.
  • queryKey prefix를 잘 설계하면 관련 목록을 한 번에 무효화할 수 있습니다.

✅ 14. URL 상태

  • URL 상태는 주소에 남겨야 하는 상태입니다.
  • 검색어, 필터, 페이지 번호, 정렬 조건처럼 새로고침하거나 링크를 공유해도 유지되어야 하는 값입니다.

➕ 14-1. URL 상태로 두면 좋은 것

검색어
페이지 번호
페이지 사이즈
상태 필터
유입경로 필터
날짜 범위
정렬 조건
탭 선택

➕ 14-2. 관리자 상담 목록 예시

/admin/consults?page=2&status=PENDING&source=NAVER&keyword=아이폰
  • 이렇게 URL에 남기면 새로고침해도 같은 조건을 유지할 수 있습니다.
  • 운영자가 특정 검색 결과를 공유하기도 쉽습니다.

✅ 15. URL 상태와 서버 상태 연결

  • 관리자 목록 화면에서는 URL 상태와 TanStack Query를 같이 쓰는 구조가 좋습니다.
URL query string
  ↓
page/status/source/keyword 파싱
  ↓
queryKey에 포함
  ↓
API 요청
  ↓
테이블 렌더링

➕ 15-1. 예시 흐름

const searchParams = useSearchParams();

const page = Number(searchParams.get('page') ?? 1);
const status = searchParams.get('status') ?? undefined;
const keyword = searchParams.get('keyword') ?? undefined;

const consultsQuery = useQuery({
  queryKey: ['admin', 'consults', { page, status, keyword }],
  queryFn: () =>
    adminConsultApi.getConsults({
      page,
      status,
      keyword,
    }),
});
  • URL 상태가 바뀌면 queryKey가 바뀌고, queryKey가 바뀌면 새 API 요청이 나갑니다.
  • 관리자 테이블에서는 이 패턴이 매우 중요합니다.

✅ 16. 폼 상태

  • 폼 상태는 사용자가 입력 중인 값입니다.
  • 상담 신청, 사전예약 신청, 관리자 상품 등록/수정, 배너 등록, 검색 폼에서 사용됩니다.

➕ 16-1. 폼 상태의 특징

입력 중 값이 계속 바뀜
유효성 검증이 필요함
에러 메시지가 필요함
submit 시 서버로 전송됨
초기값이 필요할 수 있음
수정 폼은 서버 데이터와 연결됨
  • 간단한 폼은 useState로도 충분합니다.
  • 복잡한 폼은 react-hook-form과 zod를 사용하는 것이 좋습니다.

➕ 16-2. 상담 신청 폼 예시

const form = useForm<CreateConsultFormValues>({
  defaultValues: {
    name: '',
    phone: '',
    productId: product.id,
  },
});
  • 폼 상태는 서버 상태와 분리해서 봐야 합니다.
  • 서버에서 가져온 상품 정보는 서버 상태이고, 사용자가 입력 중인 이름/전화번호는 폼 상태입니다.

✅ 17. 상태를 어디에 둘지 결정하는 기준

➕ 17-1. 판단 질문

이 상태는 한 컴포넌트에서만 쓰는가?
여러 컴포넌트가 공유해야 하는가?
서버에서 가져온 데이터인가?
URL에 남아야 하는가?
사용자가 입력 중인 값인가?
새로고침 후에도 유지되어야 하는가?
다른 사용자가 변경할 수 있는 데이터인가?

➕ 17-2. 기준표

상태추천 위치
모달 열림로컬 useState
드롭다운 열림로컬 useState
로그인 관리자 정보전역 상태 또는 query
상품 목록TanStack Query
상담 목록TanStack Query
검색어/페이지URL query
상담 신청 입력값form state
테마전역 상태
토스트 메시지전역 UI store
  • 상태의 종류를 구분하면 구조가 훨씬 깔끔해집니다.

✅ 18. Zustand 사용 기준

  • Zustand는 가볍고 사용하기 쉬운 전역 상태 관리 라이브러리입니다.
  • Redux보다 설정이 적고, 전역 UI 상태나 로그인 사용자 상태 관리에 적합합니다.

➕ 18-1. Zustand에 넣기 좋은 것

사이드바 접힘 여부
전역 토스트
전역 confirm modal
관리자 UI 설정
테마
간단한 클라이언트 상태

➕ 18-2. Zustand에 넣지 않는 것이 좋은 것

상품 목록 API 결과
상담 목록 API 결과
주문 목록 API 결과
검색 결과
서버에서 가져온 대부분의 데이터

➕ 18-3. 예시

type SidebarStore = {
  isCollapsed: boolean;
  toggle: () => void;
};

export const useSidebarStore = create<SidebarStore>((set) => ({
  isCollapsed: false,
  toggle: () =>
    set((state) => ({
      isCollapsed: !state.isCollapsed,
    })),
}));
  • Zustand는 클라이언트 상태에 집중시키고, 서버 데이터는 TanStack Query에 맡기는 조합이 좋습니다.

✅ 19. 관리자 페이지 상태 설계 예시

➕ 19-1. 상담 관리 화면

URL 상태:
page, limit, status, source, keyword, startDate, endDate

서버 상태:
상담 목록, 상담 상세, 상태 변경 이력

로컬 UI 상태:
상세 모달 열림, 상태 변경 모달 열림

폼 상태:
상태 변경 사유, 상담 메모 입력값

전역 상태:
로그인 관리자 정보, 권한, 토스트

➕ 19-2. 상품 관리 화면

URL 상태:
page, category, keyword, isVisible

서버 상태:
상품 목록, 상품 상세, 카테고리 목록

로컬 UI 상태:
상품 등록 모달, 이미지 미리보기

폼 상태:
상품명, 출고가, 지원금, 요금제, 노출 여부

전역 상태:
관리자 권한, 토스트, confirm modal
  • 화면별로 상태를 구분해두면 컴포넌트 구조를 잡기 쉬워집니다.

✅ 20. 상태 관리에서 자주 하는 실수

➕ 20-1. 모든 것을 전역 상태로 올림

문제:
작은 모달 상태까지 전역으로 관리

결과:
상태 추적 어려움
불필요한 렌더링
컴포넌트 재사용 어려움
  • 가까운 곳에서 끝나는 상태는 가까운 곳에 두는 것이 좋습니다.

➕ 20-2. 서버 상태를 useState로 직접 관리

문제:
API 데이터, loading, error, refetch를 직접 구현

결과:
화면마다 코드 반복
캐싱 없음
수정 후 갱신 누락
  • 서버 상태는 TanStack Query로 관리하는 것이 좋습니다.

➕ 20-3. 검색 조건을 URL에 안 남김

문제:
관리자 상담 목록 필터를 local state로만 관리

결과:
새로고침하면 조건 사라짐
뒤로가기 동작 이상
운영자가 검색 결과 공유 불가
  • 관리자 목록의 검색/필터/페이지는 URL 상태로 두는 것이 좋습니다.

➕ 20-4. queryKey에 필터 조건을 빼먹음

useQuery({
  queryKey: ['admin', 'consults'],
  queryFn: () => adminConsultApi.getConsults({ status }),
});
  • status가 바뀌어도 queryKey가 같으면 캐시가 꼬일 수 있습니다.

좋은 방식:

useQuery({
  queryKey: ['admin', 'consults', { status }],
  queryFn: () => adminConsultApi.getConsults({ status }),
});

✅ 21. 실무 체크리스트

➕ 21-1. 상태 분리 체크리스트

  1. 로컬 UI 상태와 서버 상태를 구분했는가?
  2. 서버 데이터는 TanStack Query로 관리하는가?
  3. 검색/필터/페이지네이션은 URL 상태로 관리하는가?
  4. 폼 입력값은 form state로 관리하는가?
  5. 전역 상태에는 정말 공유가 필요한 값만 넣는가?
  6. 모달 열림 같은 단순 상태를 과하게 전역화하지 않았는가?
  7. 로그인 관리자 정보와 권한은 일관된 위치에서 관리되는가?
  8. 같은 서버 데이터를 여러 곳에서 중복 관리하지 않는가?

➕ 21-2. TanStack Query 체크리스트

  1. queryKey에 모든 검색 조건이 포함되어 있는가?
  2. queryFn이 API 호출만 담당하는가?
  3. staleTime 기준이 데이터 성격에 맞는가?
  4. mutation 성공 후 필요한 query를 invalidate하는가?
  5. 로딩/에러/빈 상태 UI가 있는가?
  6. 같은 API를 중복 호출하지 않는가?
  7. 수정/삭제 후 목록 갱신이 누락되지 않는가?
  8. 관리자 목록에서 페이지/필터 변경이 정상 동작하는가?

➕ 21-3. 관리자 페이지 체크리스트

  1. 필터 조건이 새로고침 후에도 유지되는가?
  2. 뒤로가기/앞으로가기 동작이 자연스러운가?
  3. 특정 검색 결과 URL을 공유할 수 있는가?
  4. 상태 변경 후 목록이 갱신되는가?
  5. 상세 모달과 목록 데이터가 충돌하지 않는가?
  6. 권한 없는 버튼은 숨기되, API 권한도 백엔드에서 막는가?
  7. 에러 발생 시 운영자가 이해할 수 있는 메시지가 나오는가?
  8. 로딩 중 중복 클릭이 막히는가?

✅ 22. AI를 활용해 상태 관리를 설계할 때 질문법

  • AI에게 프론트 상태 관리를 물어볼 때는 화면의 역할, API 데이터, 필터, 모달, 폼, 권한 조건을 같이 알려줘야 합니다.
  • 단순히 “상태 관리 어떻게 해?”라고 하면 너무 일반적인 답변이 나옵니다.

➕ 22-1. 좋은 질문 예시

React + TanStack Query + Zustand로 관리자 상담 관리 화면의 상태 구조를 설계하고 싶어.

상황:
1. 상담 목록은 API로 조회함
2. 검색 조건은 page, limit, status, source, keyword, startDate, endDate가 있음
3. 검색 조건은 새로고침해도 유지되어야 함
4. 상담 상세는 모달로 보여줌
5. 상담 상태 변경도 모달에서 처리함
6. 상태 변경 성공 후 상담 목록과 상세 데이터가 갱신되어야 함
7. 로그인한 관리자 권한에 따라 버튼 노출이 달라짐
8. VIEWER는 상태 변경 버튼을 볼 수 없음
9. 로딩/에러/빈 상태 UI도 필요함

요청:
- 로컬 상태, URL 상태, 서버 상태, 전역 상태 분리
- queryKey 설계
- useQuery/useMutation 구조
- invalidateQueries 기준
- Zustand에 넣을 상태와 넣지 말아야 할 상태
- 컴포넌트 구조
- 자주 생기는 버그와 방지법
을 실무 기준으로 정리해줘.

➕ 22-2. AI 답변 검증 기준

  1. 서버 상태를 Zustand/Redux에 모두 넣으라고 하지 않는가?
  2. 검색 조건을 URL 상태로 관리하라고 하는가?
  3. queryKey에 필터 조건을 포함하는가?
  4. mutation 후 invalidateQueries를 설명하는가?
  5. 로컬 UI 상태와 폼 상태를 구분하는가?
  6. 권한 버튼 숨김과 백엔드 권한 검사를 구분하는가?
  7. 로딩/에러/빈 상태 UI를 포함하는가?
  8. 현재 서비스 규모에 비해 과하게 복잡하지 않은가?

📌 요약

  • 상태(State)는 화면이 현재 어떤 값을 기준으로 보여지는지를 결정하는 데이터입니다.
  • 프론트엔드 상태는 로컬 UI 상태, 전역 클라이언트 상태, 서버 상태, URL 상태, 폼 상태로 나눠서 생각하면 구조가 명확해집니다.
  • 모달 열림, 드롭다운 열림 같은 단순 UI 상태는 가까운 컴포넌트 안에서 useState로 관리하는 것이 좋습니다.
  • 로그인 관리자 정보, 전역 토스트, 사이드바 접힘 여부 같은 값은 Zustand 같은 전역 상태로 관리할 수 있습니다.
  • 상품 목록, 상담 목록, 주문 목록, 배너 목록처럼 서버에서 가져오는 데이터는 TanStack Query로 관리하는 것이 좋습니다.
  • 검색어, 페이지, 상태 필터, 날짜 범위처럼 새로고침 후에도 유지되어야 하는 값은 URL query string으로 관리하는 것이 좋습니다.
  • TanStack Query의 queryKey에는 API 결과를 구분하는 모든 조건이 포함되어야 합니다.
  • 데이터를 생성/수정/삭제하는 작업은 useMutation으로 처리하고, 성공 후 관련 query를 invalidate해야 화면 데이터가 갱신됩니다.
  • 관리자 페이지는 URL 상태, 서버 상태, 로컬 모달 상태, 폼 상태, 전역 권한 상태를 명확히 나누면 유지보수가 쉬워집니다.
  • 상태를 무조건 전역화하거나, 서버 상태를 직접 useState로 관리하거나, queryKey에 필터 조건을 빼먹는 실수를 조심해야 합니다.

0개의 댓글