lifecarelog
프론트엔드

debounce 자동저장, 화면을 떠날 때 마지막 입력이 사라진다면

화면 전환이나 탭 종료 순간 debounce 타이머가 취소돼 마지막 입력이 저장되지 않는 문제를 flush와 sendBeacon으로 막는 방법을 정리했어요.

5분 읽기

debounce 자동저장, 화면을 떠날 때 마지막 입력이 사라진다면

입력할 때마다 서버로 저장하면 요청이 너무 잦아요. 그래서 debounce로 "타이핑을 멈춘 뒤 잠깐 있다가" 저장하게 만들죠. 그런데 직접 붙여 보니 묘한 버그가 생겼어요. 마지막에 친 한두 글자가 저장이 안 된 채로 사라지는 거예요. 혹시 겪어본 적 있나요?

왜 마지막 입력만 사라질까

debounce는 마지막 호출로부터 일정 시간이 지나야 실제 저장을 실행해요. 간격을 800ms로 잡았다면, 타이핑을 멈추고 0.8초가 지나기 전에 화면을 벗어나면 예약된 저장이 아직 대기 중인 상태예요.

여기서 갈리는 지점이 두 가지예요. 직접 재현해 보니 마지막 1~2글자가 열 번 중 서너 번은 빠졌는데, 원인이 상황마다 달랐어요.

  • 화면 전환(컴포넌트 언마운트): 타이머 자체는 살아 있을 수 있어요. 문제는 정리(cleanup) 코드에서 습관적으로 cancel()을 부를 때예요. 언마운트 경고를 없애려고 넣은 그 한 줄이 대기 중이던 저장을 조용히 버려요.
  • 탭 닫기·새로고침(페이지 언로드): 이땐 타이머가 아예 안 돌고, 진행 중이던 fetch도 중단될 수 있어요.
입력debounce 대기(800ms)이탈 순간 flush저장 완료

언마운트에서는 cancel 대신 flush

가장 흔한 실수부터 고쳐요. 정리 코드에서 cancel() 말고 flush()를 부르면 돼요. 대부분의 debounce 구현(lodash 포함)은 대기 중인 호출을 지금 즉시 실행하는 flush()를 제공해요.

const save = useMemo(() => debounce(saveToServer, 800), []);
 
useEffect(() => {
  // cancel()이면 마지막 저장이 버려져요. flush()로 지금 실행.
  return () => save.flush();
}, [save]);

한 가지 더. debounce 함수를 한 번만 만들면 오래된 값을 저장할 수 있어요. 최신 입력을 ref에 담아두고 저장 함수가 그 ref를 읽게 하면 이 문제가 사라져요. 적용해 봤더니 마지막 값이 안정적으로 붙었어요.

탭을 닫거나 사이트를 벗어날 때

하드 언로드는 flush로도 못 잡아요. 진행 중이던 요청이 취소되니까요. 이땐 navigator.sendBeacon이 답이에요. 언로드 순간에도 살아남는 fire-and-forget 전송이에요.

useEffect(() => {
  const onHide = () => {
    if (document.visibilityState === "hidden") {
      navigator.sendBeacon("/api/autosave", JSON.stringify(draftRef.current));
    }
  };
  document.addEventListener("visibilitychange", onHide);
  return () => document.removeEventListener("visibilitychange", onHide);
}, []);

beforeunload보다 visibilitychangehidden 시점을 쓰는 걸 권해요. 모바일 브라우저에서 beforeunload는 잘 안 불리거든요. 돌려 보니 확실히 이쪽이 덜 놓쳤어요.

  • cleanup은 flush
  • 최신값은 ref
  • 하드 언로드는 sendBeacon

정리

세 가지만 챙기면 마지막 입력을 지킬 수 있어요. 언마운트에선 flush, 값은 ref로 최신 유지, 페이지 이탈은 sendBeacon. 플랜비(plan-b) 전술보드처럼 손이 자주 가는 화면일수록 이 처리가 티가 나요. 자동저장은 "저장됐다"는 안심을 주는 기능이라, 마지막 한 글자를 놓치면 그 신뢰가 먼저 무너지거든요. 작은 도구를 만들 때도 이탈 시점 처리를 먼저 챙겨두면 나중에 덜 고생해요.

#debounce#자동저장#React

라이프케어로그 서비스가 궁금하신가요?

AI 기반 건강·일정·재활 관리 앱을 직접 써보세요.

서비스 살펴보기

관련 글

댓글

아직 댓글이 없어요. 첫 댓글을 남겨주세요.