Published on

Web API - fetch

fetch

fetch 함수는 HTTP 요청 전송 기능을 제공하는 클라이언트 사이드 Web API다. 비교적 최근에 추가된 Web API라서 인터넷 익스플로러를 제외한 대부분의 브라우저에서 제공한다.

// const promise = fetch(url, [, options]);

fetch('https://jsonplaceholder.typicode.com/todos/1')
  .then((response) => console.log(response))
  .catch((err) => console.log(err));
fetch('https://jsonplaceholder.typicode.com/todos/1')
  .then((response) => response.json())
  .then((json) => console.log(json));

fetch 함수는 HTTP 응답을 나타내는 Response 객체를 래핑한 프로미스를 반환하므로 후속 처리 메서드 then을 통해 Response객체를 전달받을 수 있다.

  • 예시
interface Todo {
  userId: number;
  id: number;
  title: string;
  completed: boolean;
}

// 기본적인 GET 요청
async function fetchTodo(): Promise<void> {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');

    // 응답이 성공적으로 받아진 경우
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }

    const data: Todo = await response.json();
    console.log('Todo Title:', data.title);
  } catch (error) {
    // 오류 처리
    console.error('Error:', error);
  }
}

fetchTodo();
  • Async/Await 예시
interface Todo {
  userId: number;
  id: number;
  title: string;
  completed: boolean;
}

// Async/Await를 활용한 더 간결한 코드
async function fetchTodo(): Promise<void> {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');

    // 응답이 성공적으로 받아진 경우
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }

    const data: Todo = await response.json();
    console.log('Todo Title:', data.title);
  } catch (error) {
    // 오류 처리
    console.error('Error:', error);
  }
}

fetchTodo();
// fetch api 커스텀훅 예시
import { useState, useEffect } from 'react';

type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';

interface FetchOptions {
  method: HttpMethod;
  headers?: Record<string, string>;
  body?: string;
}

interface UseFetchResult<T> {
  response: T | null;
  loading: boolean;
  error: Error | null;
  fetchData: (url: string, options: FetchOptions) => void;
  get: (url: string) => void;
  post: <D>(url: string, data: D) => void;
  put: <D>(url: string, data: D) => void;
  patch: <D>(url: string, data: D) => void;
  remove: (url: string) => void;
}

const useFetch = <T>(): UseFetchResult<T> => {
  const [response, setResponse] = useState<T | null>(null);
  const [loading, setLoading] = useState<boolean>(true);
  const [error, setError] = useState<Error | null>(null);

  const fetchData = async (url: string, options: FetchOptions): Promise<void> => {
    try {
      const result = await fetch(url, options);
      const json = await result.json();

      if (!result.ok) {
        throw new Error(json.message || 'Fetch failed');
      }

      setResponse(json);
    } catch (error) {
      setError(error);
    } finally {
      setLoading(false);
    }
  };

  const get = (url: string): void => fetchData(url, { method: 'GET' });
  const post = <D>(url: string, data: D): void =>
    fetchData(url, { method: 'POST', body: JSON.stringify(data) });
  const put = <D>(url: string, data: D): void =>
    fetchData(url, { method: 'PUT', body: JSON.stringify(data) });
  const patch = <D>(url: string, data: D): void =>
    fetchData(url, { method: 'PATCH', body: JSON.stringify(data) });
  const remove = (url: string): void => fetchData(url, { method: 'DELETE' });

  return { response, loading, error, fetchData, get, post, put, patch, remove };
};

export default useFetch;
// useFetch 훅 사용 예시

import React, { useEffect } from 'react';
import useFetch, { FetchOptions } from './useFetch';

// Placeholder API의 Todo 모델에 맞춰서 타입 정의
interface Todo {
  userId: number;
  id: number;
  title: string;
  completed: boolean;
}

const ExampleComponent: React.FC = () => {
  const apiUrl = 'https://jsonplaceholder.typicode.com/todos/1';
  const { response, loading, error, fetchData, get, post, put, patch, remove } = useFetch<Todo>();

  useEffect(() => {
    // GET 요청
    get(apiUrl);

    // POST 요청
    const postData: Todo = { userId: 1, id: 1, title: 'Buy groceries', completed: false };
    post(apiUrl, postData);

    // PUT 요청
    const putData: Todo = { userId: 1, id: 1, title: 'Buy groceries', completed: true };
    put(apiUrl, putData);

    // PATCH 요청
    const patchData: Partial<Todo> = { completed: true };
    patch(apiUrl, patchData);

    // DELETE 요청
    remove(apiUrl);
  }, [apiUrl, get, post, put, patch, remove]);

  if (loading) {
    return <p>Loading...</p>;
  }

  if (error) {
    return <p>Error: {error.message}</p>;
  }

  return (
    <div>
      <h1>Data from Placeholder API</h1>
      <pre>{JSON.stringify(response, null, 2)}</pre>
    </div>
  );
};

export default ExampleComponent;