React로 HTTP 요청 보내기

학습 목표

  • 데이터베이스와 React는 어떻게 상호작용할까?
  • Http 요청을 보내고 응답을 사용해보자
  • 에러를 처리하고 로딩 State에 대해서 배우자

HTTP 요청 보내기 (ex: 데이터베이스 연결)

데이터베이스에 직접 연결하면 안되는 이유

브라우저측 앱은 데이터베이스에 직접 연결하면 안된다. 브라우저에서는 코드를 모두 볼 수 있기 때문에 보안 이슈가 생긴다. 백엔드 앱은 다른 서버에서 구동되기 때문에 데이터베이스에 연결할 수 있다. 그래서 우리는 백엔드 서버와 통신해 데이터베이스에 안전하게 접근할 수 있다.

SWAPI 소개

SWAPI

이 사이트는 스타워즈 더미 데이터를 제공하는 백엔드 서버이다. 이는 다시 말하지만 데이터베이스가 아닌 API다. API란 Application Programming Interface이다.

Get 요청 보내기

두 가지 방법을 사용할 수 있다. 하나는 axios 패키지를 사용하는 방법, 다른 하나는 내부 메서드인 fetch()를 사용하는 방법이 있다. 그 중 우리는 패키지보단 내부 메서드를 사용해보겠다. 사용법은 JS 문법이므로 새롭진 않다.

개인적으로 이런식으로 오류 처리 하는 걸 선호한다.

// Get
fetch("url")
  .then((response) => {
    if (!response.ok) throw new Error(response.statusText);
    return response.json();
  })
  .then((data) => console.log(data))
  .catch((err) => console.log(err));

프로미스의 후속 처리 메서드인 then을 사용할 수 있지만 async/await를 사용하면 좀 더 코드가 간결해지는 장점이 있다. 둘이 똑같이 비동기 처리를 한다.

async function fetchData() {
  try {
    const response = await fetch("url");
    if (!response.ok) throw new Error(response.statusText);
    return response.json();
    const data = await response.json();

    console.log(data);
  } catch (err) {
    console.log(err);
  }
}

사용자에게 데이터 현재 상태 알려주기

불러오긴 하지만 아무것도 뜨지 않아 사용자는 불러오는 건지 화면이 멈춘것인지 알 수 없다. 그렇기에 이럴 땐 로딩중이라던가 아니면 로딩은 완료했지만 데이터가 없는 경우인지를 알려줄 수 있다. 바로 State를 사용하면 간단하게 가능하다.

const [isLoading, setIsLoading] = useState(false);
const [data, setData] = useState(false);

async function fetchData() {
  // loading State
  setIsLoading(true);
  const response = await fetch("url");
  const data = await response.json();

  setData(data);
  setIsLoading(false);
}

return (
  <section>
    {!isLoading && data.length > 0 && <DataList />}
    {!isLoading && data.length === 0 && <p>Found no data.</p>}
    {isLoading && <p>Loading...</p>}
  </section>
);

HTTP 오류 처리하기

4XX 오류는 서버는 잘 되는데 코드 문제일 가능성이 크고 5XX 오류는 서버가 안되는 것이다. 만약 여러가지 이유로 오류가 발생한다면 사용자에게 알려줘야 한다. 왜냐하면 오류가 생겼는데 계속 로딩중이면 안되기 때문이다.

간단하게 State를 이용해 에러를 설정해주면 된다.

참고로 axios는 모든 HTTP 에러를 reject하는 프로미스를 반환하기에 에러를 모두 catch에서 처리할 수 있어 편리하다.

const [error, setError] = useState(null);

async function fetchData() {
  setError(null);
  try {
    // ... 생략
    if (!response.ok) throw new Error("Something went wrong!");
    // ... 생략
  } catch (error) {
    setError(error.message);
  }
}

깔끔하게 조건부 렌더링 작성해보기

사용자에게 알려줄 때 JSX코드에 Error State까지 적으면 길어질 것이다. 그래서 이런 방법도 있다. else 안 넣어도 된다.

// 기본값
let content = <p>Found no data.</p>;

if (data.length > 0) {
  content = <DataList />;
}

if (error) {
  content = <p>{error}</p>;
}

if (isLoading) {
  content = <p>Loading...</p>;
}

useEffect를 이용하여 요청하기

처음에 렌더링될 때 요청하고 싶은 경우가 있을 것이다. 전에 배웠듯이 그냥 함수를 호출하면 무한루프에 빠진다. 함수를 호출해주고 함수가 변할 때마다 재호출 해주기 위해 의존성 항목에 함수를 넣어준다.

useEffect(() => {
  fetchMoviesHandler();
}, [fetchMoviesHandler]);

물론 함수가 재생성되어 무한루프되는 걸 막기 위해 useCallback을 사용해야 하는 것을 잊으면 안된다. 그리고 의존성 배열도 추가해준다.

const fetchMoviesHandler = useCallback(async () => {
  // ... 생략
}, []);

Post 요청 보내기

Firebase

일단 앞서 실행한 더미 API로는 읽기만 가능할 뿐 보내지는 못한다. 그래서 구글에서 서비스 중인 Firebase를 이용할 것이다. 데이터베이스인 줄 알았으나 API였다. 즉, 백엔드 앱이다. Firebase가 제공하는 서비스들 중 데이터베이스를 사용할 수 있는 서비스가 두 개 있는데 그 중 사용하기 쉬운 realtime 데이터베이스를 사용하겠다. 프로젝트를 만든 후 링크에서 뒤에 json파일 형식으로 붙여주면 새로운 노드가 생성되어 사용할 수 있다.

fetch("https://~.firebaseio.com/data.json");

두 번째 인자에 넣어주기만 하면 끝이다.

// 프로미스의 후속 처리 메서드
fetch("url", {
  method: "POST",
  headers: { "content-Type": "application/json" },
  body: JSON.stringify(payload),
})
  .then((response) => {
    if (!response.ok) throw new Error(response.statusText);
    return response.json();
  })
  .then((data) => console.log(data))
  .catch((err) => console.log(err));
// async/await
async function fetchData() {
  try {
    const response = await fetch("url", {
      method: "POST",
      headers: { "content-Type": "application/json" },
      body: JSON.stringify(payload),
    });
    if (!response.ok) throw new Error(response.statusText);
    return response.json();
    const data = await response.json();

    console.log(data);
  } catch (err) {
    console.log(err);
  }
}

강의명

  • Udemy : React 완벽 가이드

카테고리:

업데이트:

댓글남기기