프론트엔드 개발자의 경우,
가끔 백엔드의 API Response 값이 snake_case일 경우 어떻게 관리할 지에 대해 고민에 빠지게 됩니다.
저도 오늘 같은 상황을 겪게 되었는데,
이번엔 네이밍 컨벤션을 맞춰주기로 했습니다.
컨벤션을 맞추는 데에는 여러가지 방법이 있겠지만,
고민 끝에 저는 axios의 interceptor를 통해 해결을 해보았습니다.
전체적인 프로세스는 두 가지입니다.
하나는 공용으로 사용하는 instance에 interceptor를 붙이는 것,
하나는 넘겨받은 object의 key들을 CamelCase로 변경하는 함수를 작성하는 것이 되겠습니다.
먼저 interceptor를 붙여봅시다.
import axios from 'axios'
const client = axios.create({
withCredentials: true,
})
client.interceptors.response.use((response) => {
response.dataOriginal = JSON.parse(JSON.stringify(response.data))
return response
})
export default client
혹시 모를 경우를 위해 오리지널 데이터를 따로 복제해둡시다.
이번엔 object의 key들을 CamelCase로 변경하는 함수를 작성해보겠습니다.
export const objectKeysToCamelCase = (ob = {}, isDeep = true) => {
return Object.entries(ob).reduce((acc, [key, value]) => {
const keyComputed = key.replace(/(_.?)/g, (matches) => matches[1].toUpperCase())
let result
if (isDeep === false || !value || typeof value !== 'object') {
result = value
} else if (Array.isArray(value)) {
result = value.map((item) => objectKeysToCamelCase(item, isDeep))
} else {
result = objectKeysToCamelCase(value, isDeep)
}
acc[keyComputed] = result
return acc
}, {})
}
저는 유틸리티성 함수들을 따로 모아 관리하고 있어서 export가 포함되어있는데,
만약 하나의 파일에서 진행하신다면, 굳이 넣지 않으셔도 됩니다.
함수를 조금 설명하자면, API Response 값의 경우 대부분 여러 depth가 존재할 텐데, 이를 위해 재귀함수로 구성하였습니다.
만약 2번째 파라미터인 isDeep이 참이라면,
depth 1 뿐만 아니라 하위 depth까지 object가 존재하는지 탐색하고 key의 컨벤션들을 CamelCase로 변환시켜줍니다.
반대로 거짓일 경우엔 depth 1의 key 값들만 변환시켜주겠지요 ?
이렇게 네이밍컨벤션을 변환해주는 함수를 만들었다면, 아래와 같이 적용시켜줍시다.
import axios from 'axios'
import { objectKeysToCamelCase } from '../util'
const client = axios.create({
withCredentials: true,
})
client.interceptors.response.use((response) => {
response.dataOriginal = JSON.parse(JSON.stringify(response.data))
response.data = objectKeysToCamelCase(response.data)
return response
})
export default client
그 후 확인해보면,

적용이 잘 된 것을 확인해볼 수 있습니다.
하지만 여기서 뭔가 찜찜한 기분이 드는데,
퍼포먼스에 대한 이슈입니다.
아무래도 모든 요소의 key와 value를 탐색하고, 비교 한 뒤 새로운 객체를 생성하는데, 걱정이 안 될 수가 없습니다.
그래서 한번 ... 테스트를 시도해보았습니다.
import axios from 'axios'
import { objectKeysToCamelCase } from '../util'
const client = axios.create({
withCredentials: true,
})
client.interceptors.response.use((response) => {
console.time()
response.dataOriginal = JSON.parse(JSON.stringify(response.data))
response.data = objectKeysToCamelCase(response.data)
console.timeEnd()
return response
})
export default client
단순히 response가 도착한 후 interceptor가 받아 들일 때부터 넘겨줄 때까지의 시간을 재어봤는데요.

다행히도 이 과정에 0.017초 가량 소요된 것을 알 수 있었습니다.