귀여운 눈높이에서 작성된, 🐰

하루 한 걸음씩, 성장 하는 중 입니다 🫶🏻

Studying/React

리액트 공부하기 - 로딩 관련

creamymood 2025. 5. 22. 14:35

프로젝트를 하면서 비동기로 데이터를 받아오는 작업을 많이 했는데, 그 때 활용하면 좋을 로딩 관련


그러니까, 로그인 관련한 로딩 

              패치 받는 것에 관련한 로딩 

 

 

우선 영화 페이지에서는 크게 이렇게 있을 것 같은데

(이 두가지는 분야가 아예 다르기 때문에, 전역 상태도 따로 관리하면 좋을 것 같다.)

 

 

비슷한 부류끼리 공통 로딩 컴포넌트 만들거나,

                                   그 때 그 때 만들어주면 좋을 것 같다.

 

 

 

 

챗 지피티가 설명해준 그 외에 추가로 로딩 로직 넣으면 좋을 곳 ↓

더보기

로그인, 데이터 패치 외에 로딩 스피너나 로딩 상태 표시를 적용하면 좋은 곳 몇 가지 추천해드릴게요.


1. 로그인 관련 로딩

  • 로그인 요청 중일 때: 서버에 로그인 요청 보내는 동안 버튼 비활성화 + 로딩 표시
  • 로그인 후 사용자 정보 받아오는 중: 토큰 검증, 프로필 데이터 로딩 시 로딩 UI

2. 데이터 패치 관련 로딩

  • 영화 목록 불러올 때: 영화 리스트를 서버에서 불러오는 동안 로딩 표시
  • 영화 상세 정보 요청 중: 특정 영화 상세 페이지 들어갔을 때 상세 정보 불러오는 중 표시
  • 댓글이나 평점 불러오는 중: 댓글, 리뷰 데이터 요청 시 로딩 UI

3. 추가로 로딩 표시하면 좋은 곳

  • 검색 결과 로딩 중: 영화 검색 기능에서 결과가 나올 때까지 로딩 표시
  • 필터링/정렬 변경 시: 필터나 정렬 버튼 클릭 후 결과가 바뀔 때 로딩 표시
  • 영화 예매/구매 요청 처리 중: 예매 버튼 클릭 후 서버 처리 중 로딩 표시
  • 사용자 프로필 업데이트 중: 사용자 정보 수정 후 저장하는 중 로딩 표시
  • 페이지 전환 시: 큰 페이지 이동(예: 영화 목록 → 상세 페이지) 중 데이터 로딩 시간 길다면 로딩 표시
  • 이미지(포스터 등) 로딩 중: 영화 포스터 이미지가 늦게 뜰 때 기본 이미지 + 로딩 UI

부가 팁

  • 로딩 상태는 꼭 사용자 행동에 따른 비동기 처리 구간에 넣는 게 중요해요.
  • 로딩 표시 없이 화면이 갑자기 깜빡이거나 멈추면 UX가 나빠지니까요.
  • 스켈레톤 UI(skeleton screen)도 고려해보세요. 빈 화면 대신 기본 틀 UI 보여주면 더 자연스럽습니다.

 

 

그러니까 결국, 이런 곳에 비슷한 부류끼리 공통 로딩 컴포넌트 만들거나, 그 때 그 때 만들어주면 좋을 것 같다. 

로딩관련해서 스켈레톤이나, Intersection Observer이 부분 공부해봐야겠다.


그 중, 

1. 예를 들어 회원 정보를 받아오는 과정에서, 그 과정은 비동기니까,

좀 늦을 것이나 그런걸 대비해서 로딩 관련 로직을 만들어주는 것도 좋은데 

 

한가지 예시는 다음과 같다.

더보기

일반적인 useUser 훅 내부 구조 예시

import { useEffect, useState } from "react";

function useUser() {
  const [user, setUser] = useState(null); // 사용자 정보
  const [loading, setLoading] = useState(true); // 로딩 상태

  useEffect(() => {
    const fetchUser = async () => {
      try {
        const res = await fetch("/api/check-token"); // 예: 토큰 유효성 검사
        if (res.ok) {
          const userData = await res.json();
          setUser(userData); // 로그인된 사용자 정보
        } else {
          setUser(null); // 로그인 안 됨
        }
      } catch (err) {
        console.error(err);
        setUser(null); // 오류 발생 시 로그인 안 된 것으로 처리
      } finally {
        setLoading(false); // 무조건 로딩 종료
      }
    };

    fetchUser();
  }, []);

  return { loggedIn: !!user, loading };
}

여기서 로딩은 사용자 정보랑 관련된 전역에서 같이 관리했다. 그 이유는 로그인 상태에 따라서 로딩을 보여줄지 말지 결정하는 것 이기 때문.

핵심 흐름 정리

  1. 컴포넌트가 처음 렌더링되면 loading은 true.
  2. fetchUser()가 비동기로 사용자 정보를 받아옴.
  3. 응답에 따라 user 상태가 업데이트됨.
  4. 마지막에 setLoading(false)로 로딩 상태 종료.

이걸, 컴포넌트에서 사용하는 방식

const { loggedIn, loading } = useUser();

if (loading) {
  return <Spinner />; // 로딩 중 UI
}

return loggedIn ? <Dashboard /> : <LoginPage />;

 

즉, loading은 단순히 "값이 왔는지 여부"가 아니라, "비동기 처리 중인 상태" 자체를 의미하는 명시적인 상태 변수야.
그리고 useUser 훅 안에서 setLoading(true) → 비동기 처리 → setLoading(false) 구조로 직접 제어하는 게 일반적이야.


위 코드 중 setLoading(false); // 무조건 로딩 종료 이게 무슨 말이지

 

좋은 질문이야, Jane!
여기서 **"무조건 로딩 종료"**라는 말은 비동기 작업이 성공하든 실패하든, 마지막에는 loading 상태를 false로 바꾼다는 의미야.


try {
  // 비동기 작업: 예를 들면 로그인 여부 확인 API 호출
} catch (err) {
  // 에러 처리
} finally {
  setLoading(false); // ✅ 여기
}

 

 finally 블록이란?

JavaScript에서 try...catch...finally 구문에서 finally는:

  • try에서 성공하든
  • catch에서 에러가 나든

무조건 실행되는 블록이야.

왜 필요해?

예를 들어 서버에 로그인 여부 확인 요청을 보냈을 때:

  • 성공해서 사용자 정보를 받아오면 → setUser(...) 하고 setLoading(false)
  • 실패해서 에러가 나도 → setUser(null) 하고 setLoading(false)

이렇게 하면 언제든지 로딩 상태가 끝났다는 걸 확실하게 표시할 수 있어.


요약

setLoading(false); // 무조건 로딩 종료

→ 이건 비동기 작업이 끝났다는 신호를 컴포넌트에 주는 것이고,
→ 로딩 스피너를 멈추게 하는 조건이기도 해.