- 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;