axios 요청 시 Date 객체가 다른 시간으로 보내지는 현상

seung·2024년 5월 27일
0
post-thumbnail

문제 상황

상품 등록 페이지 작업 중에 기간을 선택하는 부분이 있었다.

분명히 기간 선택을 했을 때는 Date 객체가 내가 선택한 날짜가 제대로 찍혔는데 API 요청을 보내고 payload 로 확인해봤을 때는 내가 선택한 날짜의 하루 전 날짜가 찍혔다.

✔️ 내가 선택했을 때 찍히는 값

✔️ API 요청할 때 payload 에서 확인한 값


원인 및 해결방법

찾아보니 나와 같은 현상을 갖고 있는 사람들이 있었다.

이런 문제가 생기는 이유는 axios는 기본적으로 Date 객체를 UTC 문자열로 직렬화하기 때문이라고 한다.

개발자가 다른 표준 시간대를 사용하는 경우에도 UTC 시간으로 보내지기 보내지기 때문에 이런 현상이 생기게 되는 것이다.

아래 axios issue 글에서는 moment를 이용하여 Date의 형식을 정해준 뒤 백엔드에 보내라는 답변이었다.

const moment = require('moment')

const startDateStr = moment(startDate).format('YYYY-MM-DD HH:mm:ss')
const endDateStr = moment(endDate).format('YYYY-MM-DD HH:mm:ss')

굳이 moment 를 사용할 필요없이 Date의 형식을 정해준 뒤 보내주었더니 해결되었다.

// yyyymmdd_hhmmss 함수는 "2022-01-20" 형식으로 변환해주는 함수
const param = {
	...,
	startDate: yyyymmdd_hhmmss(data.discount.startDate),
	endDate: yyyymmdd_hhmmss(data.discount.endDate),
}

try {
	await put(`/products/${item.id}`, param)
} catch (e) { ... }

payload 에서도 선택한 값으로 잘 보내지는 것을 확인할 수 있다.


axios config 설정에 Date 변환함수 추가하기

위의 방법처럼 axios를 요청하기 전에 Date 타입인 파라미터를 일일이 format 해주는 방법이 있지만 이 방법은 Date 객체를 모두 format 해주어야 한다는 번거로움이 있다.

그래서 axios config 설정에 Date 타입인 값을 찾아서 변환해주는 함수를 적용시켜주면 번거롭게 일일이 변환하지 않아도 된다.

// Date 객체 변환해주는 함수
const dateTransformer = data => {
  if (data instanceof Date) {
    return yyyymmdd_hhmmss(data)
  }
  if (Array.isArray(data)) {
    return data.map(val => dateTransformer(val))
  }
  if (typeof data === 'object' && data !== null) {
    return Object.fromEntries(Object.entries(data).map(([key, val]) => [key, dateTransformer(val)]))
  }
  return data
}

// axios config 에 적용
axios({
	...,
	transformRequest: [dateTransformer, ...axios.defaults.transformRequest],
})

🚨 추가 사항

이미지 등록 API 가 동작이 안되어서 찾아봤더니 요청 데이터가 FormData 일때는 변환하지 않고 그대로 반환해주어야 정상적으로 파일 업로드 API 가 동작했다.

export const dateTransformer = data => {
  if (data instanceof Date) {
    return yyyymmdd_hhmmss(data)
  }
	// ✨ formData 일때는 그대로 반환해주는 로직 추가
  **if (data instanceof FormData) {
    return data
  }**
  if (Array.isArray(data)) {
    return data.map(dateTransformer)
  }
  if (typeof data === 'object' && data !== null) {
    return Object.fromEntries(Object.entries(data).map(([key, val]) => [key, dateTransformer(val)]))
  }
  return data
}

📌 참고

profile
🌸 좋은 코드를 작성하고 싶은 프론트엔드 개발자 ✨

0개의 댓글