Skip to content

Axios 기능 만들기

Axios

Axios: Promise based HTTP client for the browser and node.js)

CRUD 기능

Fetch API를 기반으로 Axios의 기능을 만들어 본다.

fetch-wrapper.js

설정
js
const DOMAIN = 'http://localhost:3000'
const DEFAULT_HEADER = {
  'Content-Type': 'application/json'
}
코어
js
const HTTP_METHOD = {
  GET: 'GET',
  POST: 'POST',
  PUT: 'PUT',
  DELETE: 'DELETE'
}

const fetchGetData = (url, queryObj) => {
  return fetchData({
    url: `${url}${queryToString(queryObj)}`,
    method: HTTP_METHOD.GET
  })
}

const fetchPostData = (url, body) => {
  return fetchData({
    url,
    body,
    method: HTTP_METHOD.POST,
  })
}

const fetchPutData = (url, body) => {
  return fetchData({
    url,
    body,
    method: HTTP_METHOD.PUT,
  })
}

const fetchDeleteData = (url, body) => {
  return fetchData({
    url,
    body,
    method: HTTP_METHOD.DELETE,
  })
}

const fetchData = ({url, method, body, headers}) => {
  return fetch(`${DOMAIN}${url}`, {
    method,
    body: toHttpBody(body),
    headers: toHttpHeader({body, headers})
  })
    .then(async response => {
      const {status, statusText} = response
      const body = await extractHttpBody(response)
      return {status, statusText, body}
    })
}
헬퍼
js
const toHttpBody = body => {
  return isFormData(body) ? body : JSON.stringify(body)
}

const toHttpHeader = ({body, headers}) => {
  return isFormData(body) ? undefined : Object.assign(DEFAULT_HEADER, headers)
}

const extractHttpBody = response => {
  const contentType = response.headers.get('Content-Type')

  switch (true) {
    case contentType.startsWith('application/json'):
      return response.json()
    case contentType.startsWith('image'):
      return response.blob()
  }
  return response.text()
}

const isFormData = data => data instanceof FormData

const queryToString = obj => {
  if (!obj) {
    return ''
  }

  const query = Object
    .entries(obj)
    .map(item => item.join('='))
    .join('&')
  return `?${query}`
}

사용 예

GET Basic
js
fetchGetData('/get/json', { value: 10 })
  .then(response => console.log(response))
fetchGetData('/get/text')
  .then(response => console.log(response))
GET Image
js
fetchGetData('/static/code.png')
  .then(response => {
    getElem('get-image-tag').src = URL.createObjectURL(response.body)
  })
POST Basic
js
fetchPostData('/post/json', {data: 'json'})
  .then(response => console.log(response))
POST File Upload
js
const file = getElem('post-file-input').files[0]
const formData = new FormData()
formData.append('uploadFile', file, file.name)

fetchPostData('/post/file', formData)
  .then(response => console.log(response))
PUT Basic
js
fetchPutData('/put/json', {data: 'json'})
  .then(response => console.log(response))
PUT File Upload
js
const file = getElem('put-file-input').files[0]
const formData = new FormData()
formData.append('uploadFile', file, file.name)

fetchPutData('/put/file', formData)
  .then(response => console.log(response))
DELETE Basic
js
fetchDeleteData('/delete/json', {data: 'json'})
  .then(response => console.log(response))

Credentials 설정

인증된 계정임을 식별하기 위해 Cookie를 사용하기도 한다. 해당 케이스에서 Credentials 설정이 필요하다. Fetch API에서 Credentials를 사용하기 위해서는 다음과 같이 하면된다.

js
const fetchData = ({
                     url,
                     method,
                     body,
                     headers,
                     isCredentials = true
                   }) => {
  return fetch(`${DOMAIN}${url}`, {
    method,
    body: toHttpBody(body),
    headers: toHttpHeader({body, headers}),
    credentials: isCredentials ? 'include' : 'same-origin'
  })
    .then(async response => {
      const {status, statusText} = response
      const body = await extractHttpBody(response)
      return {status, statusText, body}
    })
}