웹 개발에서 외부 리소스와의 상호 작용을 하기 위한 다양한 HTTP 클라이언트가 존재합니다.
이 글에서는 가장 널리 사용되는 Fetch, Axios, 그리고 Ky를 비교하고, 각 라이브러리의 특징, 장단점, 그리고 적합한 사용 사례를 정리해보았습니다.
1. Fetch
Fetch는 브라우저에 기본 내장된 API로, 별도의 라이브러리 설치 없이 바로 사용할 수 있다는 가장 큰 장점을 가지고 있습니다. Promise 기반으로 작동하며, 간결한 문법으로 비동기 통신을 처리할 수 있습니다.
장점:
- 설치 불필요: 브라우저 내장 API이므로 추가적인 패키지 설치가 필요 없어 번들 크기를 줄이는 데 효과적입니다.
- 표준 API: 웹 표준을 따르므로 브라우저 환경에서 높은 호환성을 보장합니다.
- React Query, SWR 연동: 서버 상태 관리 라이브러리와 함께 사용하기에 적합합니다.
단점:
- 수동 에러 처리: HTTP 에러 상태(404, 500 등)를 자동으로 감지하지 않아 res.ok 속성을 통해 수동으로 에러를 처리해야 합니다.
- JSON 파싱: 응답 데이터를 사용하기 위해 .json() 메서드를 명시적으로 호출해야 합니다.
- 기능 부족: 타임아웃, 요청 취소 등의 기능을 직접 구현해야 하는 번거로움이 있습니다.
- 구형 브라우저 미지원: Node.js 환경에서는 node-fetch와 같은 추가 모듈이 필요합니다.
2. Axios
Axios는 브라우저와 Node.js 환경 모두에서 사용할 수 있는 널리 사용되는 HTTP 클라이언트 라이브러리입니다. Fetch보다 풍부한 기능을 제공하며, 실무에서 많은 개발자들에게 사랑받고 있습니다.
장점:
- 자동 JSON 변환: 응답 데이터를 자동으로 JSON으로 파싱해주어 코드가 간결해집니다.
- 직관적인 에러 처리: HTTP 에러 상태 발생 시 자동으로 예외를 던져 catch 블록에서 쉽게 처리할 수 있습니다.
- 인터셉터 : 요청 및 응답을 가로채어 공통 로직(예: 토큰 추가, 에러 로깅)을 처리할 수 있어 유지보수성이 뛰어납니다.
- 다양한 기능: 요청 취소, 타임아웃 설정, 업로드 진행률 표시 등 고급 기능을 기본적으로 제공합니다.
- 브라우저 호환성: 구형 브라우저를 포함하여 다양한 환경을 지원합니다.
단점:
- 별도 설치 필요: 외부 라이브러리이므로 설치가 필요하며, 프로젝트 번들 크기가 증가할 수 있습니다.
- 복잡성: Fetch에 비해 설정이 복잡하고 초기 학습 곡선이 존재할 수 있습니다.
코드 예시
src/shared/api/api-client.ts
인스턴스를 생성하고 에러 로깅을 위한 인터셉터를 설정
export const apiClient = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
headers: { 'Content-Type': 'application/json' },
withCredentials: true, // CORS 요청 시 쿠키 포함
});
apiClient.interceptors.response.use(
(response) => response,
(error: AxiosError<BaseResponse<unknown>>) => {
// 에러 로깅 처리
if (import.meta.env.DEV) {
/* ... console.error(method, url, status) ... */
}
return Promise.reject(error);
}
);
src/shared/api/request.ts
request 헬퍼 함수입니다. apiClient를 호출하고, 성공 시 data만 추출하여 반환합니다.
export const request = async <T>(config: RequestConfig): Promise<T> => {
const { method, url, query, body, headers } = config;
try {
const response = await apiClient.request<BaseResponse<T>>({
method, url, params: query, data: body, headers,
});
// 성공하면 실제 data만 반환
return response.data.data;
} catch (error: unknown) {
if (!isAxiosError(error)) throw error;
// 실패하면 서버 메시지 > 프론트 메시지 > 기본 메시지 순으로 매핑
const status = error.response?.status;
const message =
error.response?.data?.message ??
(status ? RESPONSE_MESSAGE[status] : undefined) ??
'알 수 없는 오류가 발생했습니다.';
if (import.meta.env.DEV) {
/* ... console.error(url, message) ... */
}
throw error;
}
};
src/shared/api/response.ts
HTTP 상태 코드와 그에 따른 기본 메시지를 상수로 관리하여, 매직 넘버 사용을 줄이고 메시지를 통일했습니다.
export const HTTP_STATUS = {
OK: 200,
CREATED: 201,
BAD_REQUEST: 400,
// ...
SERVER_ERROR: 500,
} as const;
// 상태별 기본 메시지
export const RESPONSE_MESSAGE: Record<number, string> = {
[HTTP_STATUS.OK]: '요청이 성공했습니다.',
[HTTP_STATUS.BAD_REQUEST]: '입력값이 올바르지 않습니다.',
// ...
};
3. Ky
kysms 경량 HTTP 클라이언트 라이브러리로, fetch와 ESM을 기반으로 동작하며 사용성을 개선한 것이 특징이다. 기본적으로 JSON 변환, 타임아웃 처리, 간결한 API 인터페이스를 제공하여 번거로운 설정 없이도 효율적인 네트워크 요청을 수행할 수 있다. ⇒ axios보다 훨씬 가볍다.
https://www.npmjs.com/package/ky
장점:
- 가벼운 용량: Fetch를 래핑하여 만들었기 때문에 매우 가볍고 번들 크기에 부담이 적습니다.
- 간결한 문법: Fetch보다 직관적인 API를 제공하며 체이닝 방식을 지원합니다.
- 편의 기능 제공: 타임아웃, 재시도(Retry), 훅(Hooks) 등의 유용한 기능을 내장하고 있습니다.
- TypeScript 지원: TypeScript를 완벽하게 지원하여 타입 안정성을 보장합니다.
- 자동 JSON 파싱 및 에러 처리: Axios처럼 JSON 자동 파싱과 HTTP 에러 처리를 지원합니다.
단점:
- 인지도 부족: Axios에 비해 상대적으로 인지도가 낮아 커뮤니티 지원이나 자료가 부족할 수 있습니다.
- Node.js 설정 필요: 기본적으로 브라우저 환경에 최적화되어 있어 Node.js 환경에서는 추가 설정이 필요할 수 있습니다.
ky 사용법
ky를 설치하려면 다음 명령어를 실행해야한다.
npm install ky
ky는 요청 인터셉터, 재시도(retry) 기능, 헤더 설정 등을 지원하며, 필요에 따라 확장하여 사용할 수 있다.
아래는 코드 예시이다.
1) ky.create()
// src/shared/api/api-client.ts
import ky from 'ky';
export const api = ky.create({
prefixUrl: import.meta.env.VITE_API_BASE_URL,
credentials: 'include', // 쿠키 포함 요청
timeout: 10_000, // fetch에는 없는 timeout 내장
retry: { limit: 2 }, // fetch에는 없는 retry 내장
hooks: {
// Axios interceptor처럼 요청 직전 공통 처리 가능
beforeRequest: [
(request) => {
const token = localStorage.getItem('token');
if (token) request.headers.set('Authorization', `Bearer ${token}`);
},
],
// 응답 직후 공통 처리 가능
afterResponse: [
(_request, _options, response) => {
if (response.status === 401) window.location.href = '/login';
return response;
},
],
},
});
2) GET/POST
// GET
type User = { id: number; name: string };
const users = await api.get('users', {
searchParams: { page: 1, limit: 10 }, // => ?page=1&limit=10 자동
}).json<User[]>();
// POST
const created = await api.post('posts', {
json: { title: 'foo', body: 'bar' }, // body + 헤더 처리 자동
}).json<{ id: number }>();
- searchParams로 쿼리 스트링을 직접 조립하지 않아도 되고, json 옵션 하나로 JSON 전송을 자동 처리한다.
- 응답은 .json<T>() 체이닝으로 바로 파싱하며, TypeScript 제네릭으로 타입까지 함께 가져갈 수 있다
3) HTTPError로 에러 처리
import { HTTPError } from 'ky';
try {
await api.get('me').json();
} catch (e) {
if (e instanceof HTTPError) {
const status = e.response.status;
// 서버가 에러 바디를 주면 읽어서 로깅 가능
const payload = await e.response.clone().json().catch(() => null);
console.error('HTTPError:', status, payload?.message);
}
throw e;
}
- Ky는 기본적으로 4xx/5xx 응답을 HTTPError로 던져서(fetch의 res.ok 체크처럼) 수동 에러 분기 코드를 줄일 수 있다.
- 에러 객체에서 response.status와 서버 에러 바디(JSON)를 읽어 공통 로깅/메시지 매핑을 쉽게 구성할 수 있다.
라이브러리 비교
| 특징 | Fetch | Axios | Ky |
| 기반 | 브라우저 내장 API | XMLHttpRequest (브라우저) / http (Node.js) | Fetch API |
| 설치 | 불필요 | 필요 (npm install axios) | 필요 (npm install ky) |
| JSON 파싱 | 수동 (.json()) | 자동 | 자동 (.json()) |
| 에러 처리 | 수동 (res.ok 확인) | 자동 (HTTP 상태 코드 기반) | 자동 (HTTP 상태 코드 기반) |
| 인터셉터 | 없음 (직접 구현 필요) | 지원 | 지원 (Hooks) |
| 타임아웃/취소 | 직접 구현 필요 | 지원 | 지원 |
| 번들 크기 | 없음 (내장) | 상대적으로 큼 | 작음 |
| 주요 사용 환경 | 간단한 프로젝트, 최신 브라우저 | 대규모 프로젝트, 구형 브라우저 지원 필요 | 현대적인 프로젝트, 경량화 중요 |
어떤 라이브러리를 선택해야 할까?
- Fetch: 외부 라이브러리 설치 없이 가볍게 시작하고 싶거나, 최신 브라우저 환경만 지원하면 되는 경우. React Query나 SWR 같은 상태 관리 라이브러리와 함께 사용할 때.
- Axios: 구형 브라우저 지원이 필수적이거나, 복잡한 요청 처리, 인터셉터 등 다양한 기능이 필요한 대규모 프로젝트의 경우.
- Ky: Fetch의 가벼움과 Axios의 편의성을 동시에 원하며, 최신 브라우저 환경을 타겟으로 하는 경우.
'FE' 카테고리의 다른 글
| biome , left-hook 설정 (0) | 2026.03.29 |
|---|---|
| 의료 서비스 - 보안 강화 방법 (0) | 2026.01.03 |
| React Suspense + Error Boundary로 안정적인 로딩/에러 핸들링 (1) | 2026.01.03 |
| 건강검진 결과 시각화 : 차트 라이브러리 선정 및 구현 전략 (0) | 2026.01.01 |
| PDF 업로드가 느린 이유와 런칭을 위한 성능 최적화 (0) | 2025.12.30 |