애드블럭 종료 후 보실 수 있습니다.

ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • HTTP 클라이언트 라이브러리의 변화 Axios에서 Got, Ky로
    Tip 2024. 12. 8. 19:39
    728x90
    반응형

    프런트엔드와 백엔드 개발 모두에서 HTTP 통신은 필수적이다.

    REST API 호출, 마이크로서비스 간 통신, 외부 서비스 연동 등 다양한 시나리오에서 단순한 HTTP 요청/응답을 넘어 훨씬 복잡해진 요구사항이 있다.

    많은 개발자들이 이제 막 웹 생태계에 입문할 때는 fetch나 Node.js의 기본 http 모듈로 시작한다.

    하지만 일정 수준 이상의 프로젝트 규모나 복잡도, 유지보수성을 요구하는 상황이 되면 fetch 단독 사용은 점차 비효율적으로 느껴지며, 보다 강력한 기능을 제공하는 HTTP 클라이언트 라이브러리로 옮겨가게 된다.

    이 글에서는 프런트엔드 생태계에서 흔히 사용되는 Axios, 그리고 최근 들어 각광받고 있는 Got(Node.js 환경)과 Ky(브라우저 환경)에 대해 살펴보고, 왜 단순한 fetch 대신 이들을 쓰는지, 그리고 기존에 Axios를 사용하다가 Got과 Ky로 눈을 돌리게 되는 이유는 무엇인지 깊이 있게 다뤄보겠다.

    1. 기본 fetch의 한계

    기본적으로 브라우저 환경에서 제공되는 fetch는 지난 수년간 Promise 기반의 깔끔한 API로 많은 개발자들에게 사랑받아 왔다.

    Node.js에서도 node-fetch를 활용하면 유사한 환경을 구축할 수 있다.

    그러나 대규모 프로젝트, 그리고 다양한 HTTP 통신 패턴을 처리해야 할 때 fetch는 다음과 같은 한계를 갖는다.

    1. 기본적인 예외 처리 부족: fetch는 네트워크 에러에 대해서만 오류를 던지며, HTTP 4xx/5xx 응답을 "정상적인" Promise resolve로 처리한다. 응답 상태 코드에 따른 예외 처리를 위한 별도의 코드가 필요하다.
    2. 타임아웃 관리의 번거로움: fetch 자체에는 타임아웃 옵션이 제공되지 않는다. 별도의 AbortController를 사용하거나, 사용자 정의 로직을 추가해야 한다.
    3. Request/Response 인터셉터 기능 미흡: API 요청 전후로 토큰을 갱신하거나 로깅, 공통 에러 처리 로직을 넣으려면 매번 fetch 호출부에 공통로직을 추가해야 한다. 대규모 프로젝트에서는 중복 코드가 많아지며 유지보수가 어려워진다.
    4. 환경별 편의 기능 부족: 브라우저와 Node.js 환경을 모두 지원하는 일관된 API가 부족하거나, 폼데이터 처리나 중첩된 JSON 파싱 등 단순 반복적인 과정을 매번 처리해야 한다.

    2. Axios: 프런트엔드 HTTP 클라이언트의 사실상 표준

    Axios는 브라우저뿐 아니라 Node.js 환경에서도 일관된 API를 제공하며, 등장 이후 여러 해 동안 "사실상의 표준" 자리를 차지해 왔다.

    다음과 같은 장점으로 인해 프런트엔드 영역에서 특히 Axios가 두각을 나타냈다.

    1. 일관된 API & 브라우저/Node.js 지원: Axios는 브라우저와 Node.js 환경 모두에서 동일한 형태로 동작한다. 이로 인해 프런트엔드와 백엔드 간 코드 재활용이 유리하다.
    2. 자동 JSON 변환: 응답을 JSON으로 받을 경우 별도의 res.json() 처리가 필요 없고, Axios는 응답 데이터를 자동으로 파싱 해준다.
    3. 인터셉터(Interceptors) 지원: 요청 또는 응답을 가로채 추가 로직을 삽입할 수 있어, 인증 토큰 갱신, 에러 로깅, 공통 헤더 설정, 응답 포맷 정규화 등 많은 패턴을 손쉽게 구현할 수 있다.
    4. 풍부한 설정 옵션: 타임아웃, 요청 취소(취소 토큰), 헤더 기본값, 응답 변형 등 fetch로는 추가 로직 없이 어렵거나 번거로운 과정을 쉽게 처리할 수 있다.
    // fetch 예시
    fetch('https://api.example.com/data')
      .then(response => {
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        return response.json();
      })
      .then(data => console.log(data))
      .catch(err => console.error(err));
    
    // Axios 예시
    import axios from 'axios';
    
    axios.get('https://api.example.com/data')
      .then(response => console.log(response.data))
      .catch(err => console.error(err));

    3.  Axios대신 Got과 Ky로 넘어가야 되는가?

    Axios는 여전히 강력한 선택이지만, 다음과 같은 이유로 Got 또는 Ky가 각광받고 있다.

    1. 성능 및 환경 특화 요구사항: 마이크로서비스 기반 백엔드나 서버사이드 렌더링(SSR) 환경에서는 Node.js에서의 최적화가 중요해진다. Axios가 여전히 훌륭하지만, Node.js 환경에 특화된 Got의 성능과 기능 확장성은 대규모 트래픽 처리나 HTTP/2 지원, 스트리밍 처리가 필요한 서비스에서 큰 차이를 만든다.
    2. 번들 크기 및 DX 개선: 프런트엔드 번들 사이즈 최적화가 핵심인 프로젝트에서는 Axios보다 가벼운 Ky가 매력적이다. 또한 Ky는 fetch의 장점(브라우저 기본 내장, 최신 API 호환)을 살리면서, Axios의 장점 중 하나였던 에러 처리와 인터셉션 로직을 가볍게 가져오는 경향이 있다.
    3. 장기적인 유지보수와 현대적 패러다임 반영: Axios는 오랫동안 유지되어 온 라이브러리이지만, 그만큼 코드베이스가 오래되고, 의존성 관리나 일부 패턴이 구식으로 느껴질 수 있다. 비교적 최신 철학을 반영한 Got과 Ky는 훅 시스템, 미들웨어, 더 투명하고 단순한 설정 방식을 통해 유지보수성과 가독성을 개선한다.

    4. Got: Node.js 환경에 최적화된 강력한 HTTP 클라이언트

    Got은 Node.js용 HTTP 요청 라이브러리로, Axios와 마찬가지로 풍부한 기능을 제공한다.

    하지만 Got은 Node.js 환경에 보다 최적화되어 있으며, 경량성과 모던한 API 스타일로 많은 개발자들의 주목을 받고 있다.

    1. Node.js 전용 최적화: Axios가 브라우저 환경까지 고려한 반면, Got은 Node.js 환경에 초점을 맞추어 성능, 스트리밍 지원, HTTP/2 지원 등 서버 사이드 환경에서 중요한 기능들을 훌륭히 제공한다.
    2. 기본 Promise 기반, 간결한 API: Axios에 비해 설정이 직관적이며, 디폴트 동작이 합리적이다. 예를 들어 Got은 HTTP 에러 코드를 자동으로 예외로 처리해 주어 별도의 체크 로직을 줄일 수 있다.
    3. 심플한 확장성: 훅(Hook) 시스템을 통해 요청 전후나 재시도 시 특정 로직을 쉽게 삽입할 수 있다.
    4. 모듈러 구조: 필요에 따라 기능을 확장하거나 플러그인처럼 원하는 기능을 쉽게 추가할 수 있어 대규모 백엔드 서비스 운영에 유리하다.
    // 스트리밍 지원 예시
    
    // axios
    const fs = require('fs');
    const axios = require('axios');
    
    axios({
      method: 'get',
      url: 'https://example.com/large-file',
      responseType: 'stream'
    })
      .then(response => {
        response.data.pipe(fs.createWriteStream('large-file.zip'));
      });
      
    // got
    const fs = require('fs');
    const got = require('got');
    
    got.stream('https://example.com/large-file')
      .pipe(fs.createWriteStream('large-file.zip'));
    // 재시도 로직 구현
    
    // Axios in Node.js
    const axios = require('axios');
    
    axios.get('https://api.example.com/data')
      .then(res => console.log(res.data))
      .catch(err => {
        // 재시도 로직을 직접 구현해야 한다.
        console.error(err);
        // ... 필요 시 setTimeout 등을 활용해 재시도 코드 추가
      });
      
    // Got in Node.js
    const got = require('got');
    
    got('https://api.example.com/data', {
      retry: { limit: 3, methods: ['GET'] }, // 자동 재시도 설정
      hooks: {
        beforeRequest: [
          options => {
            // 예: 인증 토큰 삽입
            options.headers.Authorization = 'Bearer my-token';
          }
        ],
        afterResponse: [
          (response) => {
            // 응답 후 처리 (로깅, 데이터 변형 등)
            return response;
          }
        ]
      }
    })
      .then(response => console.log(JSON.parse(response.body)))
      .catch(err => console.error(err));

    5. Ky: 모던 브라우저 환경에 특화된 fetch 기반 Wrapper

    Ky는 브라우저 환경을 위한 경량 fetch Wrapper이다.

    "Axios의 대체"로 종종 소개되지만, 사실 Ky는 Axios와 조금 다른 철학을 갖고 있다.

    Ky는 fetch를 근간으로 삼으면서도 다음과 같은 이유로 각광받고 있다.

    1. 경량성: Axios에 비해 훨씬 가벼우며 tree-shaking이 용이하다. SPA를 구성할 때 번들 크기는 점점 중요한 이슈가 되어가고 있는데, Ky는 이를 적극 반영했다.(Axios: 2.13MB vs Ky: 157kB)
    2. 모던 JavaScript: Ky는 최신 JavaScript 기능을 활용하여 작성되었으며, 이는 코드의 가독성과 유지보수성을 향상한다.
    3. 타입스크립트 지원: Ky는 타입스크립트를 기본적으로 지원하여, 타입 안정성을 제공한다.
    4. Middleware 지원: Ky 또한 middleware를 통해 인증 토큰 삽입, 응답 변환, 로깅 등 다양한 공통 로직을 간결히 처리할 수 있다.

    결국 Ky는 브라우저 환경에서 fetch를 그대로 사용하는 것보다 DX(Developer eXperience)를 크게 향상한다.

    그리고 Axios가 너무 무겁다고 느끼는 개발자들에게 경량 대안을 제시한다.

    // 동일한 GET 요청 + 인증 토큰 삽입 (인터셉터 vs middleware)
    
    // Axios with Interceptor
    import axios from 'axios';
    
    const instance = axios.create({
      baseURL: 'https://api.example.com',
    });
    
    instance.interceptors.request.use(config => {
      config.headers.Authorization = 'Bearer my-token';
      return config;
    });
    
    instance.get('/data')
      .then(res => console.log(res.data))
      .catch(err => console.error(err));
    
    // Ky with Middleware
    import ky from 'ky';
    
    const api = ky.create({
      prefixUrl: 'https://api.example.com',
      hooks: {
        beforeRequest: [
          request => {
            request.headers.set('Authorization', 'Bearer my-token');
          }
        ]
      }
    });
    
    api.get('data')
      .json()
      .then(data => console.log(data))
      .catch(err => console.error(err));

     

    Axios는 여전히 강력한 도구이지만, Got과 Ky는 각각의 환경에서 더 특화된 기능과 성능을 제공한다.

    백엔드에서는 Got의 강력한 기능을, 프런트엔드에서는 Ky의 가벼움과 현대성을 활용하는 것을 고려해 보길 바란다.

    반응형

    댓글

Designed by Tistory.