fetch를 할 때 매번 똑같은 코드를 치는 것이 비효율적이라 여겨져서 만든 fetcher 함수다.
fetcher 함수를 이용하면 아무래도 fetch를 반복하여 소스 코드에 적을 필요가 없어지니 궁극적으로는 코드 가독성 향상 + 유지보수성 증대를 꾀할 수 있다.
fetcher 함수는 객체를 파라미터로 가지며, 파라미터 객체는 { url, options, useToken } 을 프로퍼티로 가진다.
url은 fetch에 사용될 주소값이 담겨있으며, options에는 request시 초기화가 필요한 fetch의 기본 옵션들이, useToken은 헤더의 Authorization에 토큰을 담을지 말지 여부를 결정하는 플래그가 담겨있다.
type FetcherPropsType = {
url: string
options: RequestInit
useToken?: boolean
}
export const fetcher = async <T extends unknown>({
url,
options,
useToken = false
}: FetcherPropsType): Promise<ResponseWrapper<T>> => {
if (useToken) {
const accessToken = // ... accessToken를 가져온다.
options.headers = {
...options.headers,
Authorization: `Bearer ${accessToken}`
}
}
try {
const response = await fetch(url, options)
if (!response.ok) {
throw new Error('통신에 실패했습니다.')
}
const data = await response.json()
return data
} catch (error) {
throw new Error('통신에 실패했습니다.')
}
}
호출은 아래와 같이 하면 된다.
'use server'
export const uploadSomething = async (
FormData: FormData
): Promise<ResponseWrapper<string>> => {
try {
const response = await fetcher<string>({
url: `https://test.server.api.com/upload`,
options: {
method: 'POST',
body: FormData
},
useToken: true
})
return response
} catch (error) {
throw new Error('업로드에 실패했습니다.')
}
}
내 경우에는 fetcher 함수를 호출한 코드의 상단에 'use server'를 명시해주어 fetch가 서버 액션으로 동작하게 만들어주었다.
서버 액션을 쓰는 것이 반드시 옳지만은 않다. 나의 경우에는 토큰을 쿠키에 보관하고 있어 서버 사이드에서도 액세스 토큰에 충분히 접근 가능하다는 점 및 .env 파일에서 관리되고 있는 서버 URL 환경변수 앞에 NEXT_PUBLIC이라는 접두사를 붙이는게 꺼려진다는 이유(클라이언트에 공개되기 때문. 사실 공개되어도 문제가 없다면 상관없다.)로 fetch를 서버 액션으로 만들어 사용하였다. 서버 액션이 편하면 서버 액션을 사용하면 되고, 클라이언트에서 사용하는 것이 편하면 클라이언트 액션으로 사용하면 되겠다.
위의 코드의 단점으로는 에러 메세지 처리가 어려울 수 있다는 것이다. 에러 메세지를 일일히 프론트에서 관리하자니 상당히 귀찮고 생산성 없는 작업이 될 수도 있다. 에러 메세지 처리를 잘 하고 싶다면 백엔드에서 결정해주는 에러 메세지를 그대로 화면단에 띄울 수 있도록 설계하는 것도 방법일 듯 싶다.
'개발 일지' 카테고리의 다른 글
블로그 이관합니다! (1) | 2024.10.03 |
---|---|
연구) server action 함수를 자식 client-side 컴포넌트로 전달 (1) | 2024.07.14 |
React Hook) hover시 state를 변경하는 Hook (useHover) (0) | 2024.07.09 |
React, Typescript) Debounce-Input 컴포넌트 구현 (0) | 2024.06.27 |
gitlab) runner has never contacted this instance (1) | 2024.05.27 |