axios를 이용한 통신은 주로 아래와 같은 방식으로 이루어 진다.
const res : MovieDTO = await axios.get('/api/movies', { headers: { Authorization: "Bearer token" } });
return res.data;
이때 서버에서 도착하는 JSON 응답의 형태는 아래와 같다.
{
"id": 1,
"title": "인터스텔라",
"release_date": "2025-06-27T00:00:00.000Z"
}
해당 본문의 응답 자체는 text 형태로 들어오며, 이를 axios가 아래와같이 자동 파싱을 진행한다.
JSON.parse(responseText);
이때 모든 값은 기본 Javascript 타입으로 바뀌게 되는데,
DTO에서 release_date의 타입을 Date로 적용했을지라도, 그냥 string으로 변하게된다.
JSON은 primitive 타입만 직렬화/복원하며, Date는 참조형이기 때문이다.
즉, 서버측에서 Date 타입으로 전송했을지라도, 클라이언트에서는string 타입으로 인식하게된다.
const res : MovieDTO = await axios.get('/api/movies', { headers: { Authorization: "Bearer token" } });
console.log(typeof res.data); // string
아래 방법으로 직접 파싱을 진행 할 수 있다.
if(res.data?.release_date){
res.data.release_date = new Date(res.data.release_date)
}
응답을 가로채서 변환후 반환하는 방법도 가능하다.
api.interceptors.response.use((response) => {
if (response.data?.release_date) {
response.data.release_date = new Date(response.data.release_date);
}
return response;
});
하지만 이 방법은, 응답 형태가 배열 및 중첩 오브젝트일 경우 사용할 수 없다.
또한 필드명이 release_date나 deletated_at, created_at일 경우에도 마찬가지이다.
필드를 하나하나 재귀적으로 탐색하며, 아래 조건이 충족하면 Date 타입으로 변환을 시도한다.
1. Key 이름이 다음 중 하나를 만족:
- date로 시작(/^date/i)
- at, date, At, Date 등으로 끝남(/(at|date)$/i)
2. Value가 ISO 8601 문자열 형태(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/)
function isLikelyDateKey(key: string): boolean {
return /^date/i.test(key) || /(at|date)$/i.test(key);
}
function isISODateString(value: any): boolean {
return typeof value === 'string' && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(value);
}
function reviveDates(obj: any): any {
if (Array.isArray(obj)) {
return obj.map(reviveDates);
}
if (obj !== null && typeof obj === 'object') {
const newObj: any = {};
for (const [key, value] of Object.entries(obj)) {
if (isLikelyDateKey(key) && isISODateString(value)) {
newObj[key] = new Date(value);
} else {
newObj[key] = reviveDates(value); // 재귀
}
}
return newObj;
}
return obj;
}
가령 매일의 경기 결과를 보관하는 필드의 이름이 date_result이며,
득점-실점-최종점수 의 형식으로 보관하기 위해 2-1-4 같은 양식을 쓴다면
위 알고리즘은 해당 타입을 자동으로 Date로 인식하게 된다.
이렇듯 프로그래밍에서 추론식으로 문제를 해결하는 방식은 매우 위험하다.
현업에서는 절대 추측하지 않는다.
서버에서는 날짜를 반드시 ISO 형식으로 명시적으로 반환한다.
(예 : "2025-06-27T14:34:00.000Z" ← ISO 8601 형식 )
프론트 개발자는 YYYY-MM-DDTHH:mm:ss.sssZ 형식인지 점검하고, Date 변환 가능 여부를 판별한다.
Typescript를 쓰더라도, Javascript에서 겪던 타입 혼동 문제에서 완전히 자유로울 순 없다.
특히 Dto 명세의 작성을 class가 아닌 interface로 할 경우엔, 런타임중 타입 비교조차 힘들어진다.
Node.js기반 환경에서는 런타임중 생성되는 데이터의 타입을 항상 의심해야 하며,
이와중에 생산성을 챙기기 위한 설계역량을 꾸준히 키워나가야한다.