Comet5 블로그
개발·운영

프론트엔드 상태 설계: 입력값·서버 데이터·파생값 구분

Comet5 · 최초 발행 · 수정 · 약 3분

검색 화면 예제로 상태의 소유자와 요청 경합을 정리하고 전역 상태 범위를 줄입니다.

이 글의 목차

검색 화면에서 입력값, 검색 결과, 로딩 여부, 선택 항목을 모두 전역 저장소에 넣으면 누가 값을 바꾸는지 찾기 어려워질 수 있습니다. 먼저 상태의 원본이 어디에 있는지와 얼마나 오래 유지해야 하는지 구분합니다.

검색 화면의 상태 분류

값 원본·수명 시작할 위치
입력 중인 검색어 현재 입력 폼 해당 화면의 로컬 상태
제출한 검색 조건 공유·뒤로 가기가 필요할 수 있음 URL 또는 화면 상태
서버 검색 결과 서버가 원본 요청·캐시 계층
결과 개수 결과에서 계산 가능 파생값
로그인한 사용자 여러 화면이 공유 인증 상태 경계

결과 배열과 결과 개수를 별도 상태로 저장하면 한쪽만 갱신될 수 있습니다. 계산할 수 있는 값은 원본에서 유도하는 편이 불일치 지점을 줄입니다. 반대로 서버가 전체 건수를 따로 반환한다면 현재 페이지의 배열 길이와는 다른 값입니다.

늦게 도착한 응답 처리

‘ca’를 검색한 요청보다 ‘cache’를 검색한 요청이 먼저 끝날 수 있습니다. 오래된 결과가 최신 화면을 덮어쓰지 않도록 요청 식별자나 취소를 사용합니다. 아래는 개념을 보여 주는 JavaScript 예제이며 render와 showError는 화면에 맞게 구현해야 합니다.

let latest = 0;
async function search(query) {
  const current = ++latest;
  try {
    const response = await fetch('/api/search?q=' + encodeURIComponent(query));
    if (!response.ok) throw new Error('search failed');
    const data = await response.json();
    if (current === latest) render(data);
  } catch (error) {
    if (current === latest) showError(error);
  }
}

이 코드는 오래된 응답의 표시를 막지만 요청 자체를 취소하지는 않습니다. 실제 화면에서는 로딩 상태, 화면 해제 후 처리, 입력 지연과 요청 취소도 요구사항에 맞춰 추가합니다.

전역으로 옮길 근거

여러 화면에서 공유하고 이동 후에도 유지해야 하는 값인지 확인합니다. 단지 여러 컴포넌트가 필요하다는 이유만으로 앱 전체 저장소까지 올릴 필요는 없습니다. 가까운 공통 소유자나 프레임워크의 데이터 흐름을 먼저 검토합니다.

서버 캐시는 만료와 재조회 규칙이 필요하고, UI 상태는 초기화와 뒤로 가기 규칙이 필요합니다. 같은 도구를 쓰더라도 두 수명을 섞지 않는 것이 중요합니다.

검증할 사용자 흐름

빠르게 검색어 변경, 요청 실패 후 재시도, 뒤로 가기, 필터 변경, 로그아웃 후 재접속을 검사합니다. 로그아웃했는데 이전 사용자의 데이터가 화면에 남는다면 캐시 범위와 초기화가 맞지 않는 것입니다. 데이터 소유권을 정리한 뒤 필요한 도구를 선택하세요.

참고 자료