← 전체 글로 돌아가기

웹 개발

로딩 스피너보다 진행 상황을 설명하는 문구가 나을 때

사용자에게 진행 중 상태를 알릴 때, 단순한 로딩 스피너보다 문맥 있는 텍스트가 더 효과적인 경우를 정리했다.

사용자가 기다리는 동안 단순히 스피너만 보여주면 답답해 보인다. 특히 작업이 몇 초 이상 걸리면, 현재 무슨 일이 진행 중인지 알려주는 게 좋다.

예를 들어 "Saving..."보다는 "파일을 저장하는 중입니다" 같은 구체적인 문구가 사용자를 안심시킨다.

스피너만으로는 부족한 이유

  1. 진행도를 알 수 없다: 사용자는 얼마나 더 기다려야 할지 모른다
  2. 에러인지 진행 중인지 구분이 안 된다: 화면이 응답 없어 보인다
  3. 무엇을 하고 있는지 알 수 없다: 무관한 작업처럼 보일 수 있다

좋은 로딩 상태 메시지

// 나쁜 예
<div>
  <Spinner />
</div>

// 좋은 예
<div>
  <Spinner />
  <p>데이터베이스에 저장하는 중입니다...</p>
</div>

// 더 좋은 예 - 진행도 표시
<div>
  <ProgressBar value={45} />
  <p>이메일 발송 중... (45/100)</p>
</div>

상황별 메시지 예시

파일 업로드:

"파일을 업로드하는 중입니다... (2.3MB / 5MB)"

API 호출:

"서버에서 데이터를 가져오는 중입니다..."

대량 처리:

"50개 항목 중 12개를 처리했습니다..."

생성/변환 작업:

"이미지를 최적화하는 중입니다..."

진행도 표시

특히 오래 걸리는 작업은 진행 상황을 수치로 보여주는 게 효과적이다.

const [progress, setProgress] = useState(0);

return (
  <div>
    <ProgressBar value={progress} max={100} />
    <p>{progress}% 완료</p>
  </div>
);

타임아웃 처리

만약 작업이 예상보다 오래 걸리면, 사용자에게 알려야 한다.

const [elapsedTime, setElapsedTime] = useState(0);

effect(() => {
  const timer = setInterval(() => setElapsedTime(t => t + 1), 1000);
  return () => clearInterval(timer);
}, []);

return (
  <div>
    <Spinner />
    <p>작업이 진행 중입니다...</p>
    {elapsedTime > 5 && (
      <p style={{color: 'orange'}}>
        작업이 예상보다 오래 걸리고 있습니다. 계속 기다려주세요.
      </p>
    )}
  </div>
);

실수하기 쉬운 부분

  1. 너무 자세한 기술 용어 사용

    • "async task queue를 flush하는 중..." → "처리 중입니다..." (간단히)
  2. 메시지를 자주 바꾸지 않기

    • 메시지가 깜빡거리면 산만해 보인다
  3. 진행도가 멈춘 것처럼 보이기

    • 진행도가 100%에 도달했는데 아직 작업 중이면 혼란스럽다
    • 마지막 10%를 천천히 채우거나, "마무리하는 중입니다" 메시지 추가

테스트하기

# 속도를 의도적으로 느리게 해서 테스트
const [data, setData] = useState(null);

useEffect(() => {
  // 실제 API 호출 대신 의도적 지연
  const timer = setTimeout(() => setData({...}), 3000);
  return () => clearTimeout(timer);
}, []);

느린 네트워크에서도 로딩 상태가 명확한지 확인한다.

결론

로딩 상태는 사용자 경험의 중요한 부분이다. 스피너만으로 충분하지 않으니, 구체적인 문구와 진행도를 함께 보여주자.