React 앱에서 서버와 통신할 때 fetch
나 axios
를 자주 사용해.
TypeScript를 활용하면 API 응답 타입, 에러, 로딩 상태까지 정교하게 관리할 수 있어.
type User = {
id: number;
name: string;
};
const getUser = async (): Promise<User> => {
const res = await fetch('/api/user');
if (!res.ok) throw new Error('서버 오류');
const data: User = await res.json();
return data;
};
✅ Promise<User>를 명시하면, 호출한 쪽에서 반환값 타입이 자동 추론돼.
fetch
는 오류를 직접 처리해야 하므로 반드시res.ok
체크 필요.
import axios from 'axios';
type Todo = {
id: number;
title: string;
completed: boolean;
};
const getTodos = async () => {
const res = await axios.get<Todo[]>('/api/todos');
return res.data; // ✅ Todo[] 타입으로 추론됨
};
✅ axios.get<T>()처럼 제네릭으로 응답 타입을 지정하면, res.data가 자동으로 그 타입으로 인식돼.
const fetchPost = async (id: number): Promise<string> => {
const res = await fetch(`/api/post/${id}`);
const data = await res.json();
return data.content as string;
};
✅ 비동기 함수의 리턴 타입은 Promise<T> 형식으로 명시.
명확한 반환 타입은 컴포넌트에서 사용할 때 큰 도움이 돼.
type ApiError = {
message: string;
statusCode?: number;
};
const getData = async (): Promise<string> => {
try {
const res = await fetch('/api/data');
if (!res.ok) throw new Error('요청 실패');
const json = await res.json();
return json.result;
} catch (err) {
const error: ApiError = {
message: err instanceof Error ? err.message : '알 수 없는 오류',
};
console.error(error.message);
throw error;
}
};
✅ catch 블록에선 Error 타입을 명시적으로 판별해야 해.
err instanceof Error
패턴은 타입 안전한 방식으로 널리 쓰여.