-
Notifications
You must be signed in to change notification settings - Fork 2
fetch API 사용하기
정재희 edited this page Nov 1, 2023
·
2 revisions
Fetch api를 커스텀하고 서버사이드에서의 사용과 클라이언트의 사용이 분리됨에 따라 적절한 가이드를 제공하고자 함.
NextJS에서 axios 등의 서드파티 라이브러리를 사용하면 캐싱 정책 등을 따로 적용해야 하는 수고가 있다.
때문에 NextJS 공식 문서에서도 이를 권장하지 않고, 기존 fetch를 확장한 형태를 사용하기 때문에 fetch를 사용하는 것이 좋다.
class FetchAPI {
private baseURL: string
private headers: { [key: string]: string }
private static instance: FetchAPI
private constructor() {
this.baseURL = ''
this.headers = {
'Content-Type': 'application/json',
}
}
public static getInstance(): FetchAPI {
if (!FetchAPI.instance) {
FetchAPI.instance = new FetchAPI()
}
return FetchAPI.instance
}
public setBaseURL(url: string): void {
this.baseURL = url
}
public setDefaultHeader(key: string, value: string): void {
this.headers[key] = value
}
public async get(
endpoint: string,
nextInit: RequestInit = {},
customHeaders: { [key: string]: string } = {},
): Promise<any> {
const response = await fetch(`${this.baseURL}${endpoint}`, {
method: 'GET',
headers: { ...this.headers, ...customHeaders },
...nextInit,
})
return response
}
public async post(
endpoint: string,
body: any,
nextInit: RequestInit = {},
customHeaders: { [key: string]: string } = {},
): Promise<any> {
const response = await fetch(`${this.baseURL}${endpoint}`, {
method: 'POST',
headers: { ...this.headers, ...customHeaders },
body: JSON.stringify(body),
...nextInit,
})
return response
}
public async put(
endpoint: string,
body: any,
nextInit: RequestInit = {},
customHeaders: { [key: string]: string } = {},
): Promise<any> {
const response = await fetch(`${this.baseURL}${endpoint}`, {
method: 'PUT',
headers: { ...this.headers, ...customHeaders },
body: JSON.stringify(body),
...nextInit,
})
return response
}
public async delete(
endpoint: string,
nextInit: RequestInit = {},
customHeaders: { [key: string]: string } = {},
): Promise<any> {
const response = await fetch(`${this.baseURL}${endpoint}`, {
method: 'DELETE',
headers: { ...this.headers, ...customHeaders },
...nextInit,
})
return response
}
}
export default FetchAPI
해당 클래스를 전역에서 관리하기 위해 Context를 전역에 wrapper로 감싸 제공한다.
singleton 클래스의 인스턴스를 불러오는 것으로 충분하기 때문에 삭제되었습니다.
해당 모듈에서 불러와 사용하면 된다.
// apiClient.ts
import { Environment } from '@/config/environment'
import FetchAPI from '@/lib/fetchAPI'
const apiClient = FetchAPI.getInstance()
apiClient.setDefaultHeader('Content-Type', 'application/json')
apiClient.setBaseURL(Environment.apiAddress() ?? '')
export default apiClient
각 요청에 대한 함수를 사전에 정의한다. 필요시 직접 fetch를 사용해도 무관.
각 내용을 src/services/
이하에 만들어 사용한다.
// 예시 test.ts
import ApiEndPoint from '@/config/apiEndPoint'
import apiClient from '../apiClient'
const getTest = async () => {
const response = await apiClient.get(
ApiEndPoint.test(),
{next: {revalidate:10}},
{ Authorization: 'Bearer ' },
)
return response
}
export { getTest }
- 클라이언트 사이드
'use client'
import React, { useEffect } from 'react'
import { getTest } from '@/services/test/test'
export default function TestBlock() {
useEffect(() => {
async function fetchData() {
const data = await getTest()
console.log(await data.json())
}
fetchData()
}, [])
return <div>{'index '}</div>
}
- 서버 사이드
import React from 'react'
import { getTest } from '@/services/test/test'
async function getTestValue() {
const res = await getTest()
const data = await res.json()
return data
}
export default async function TestBlock() {
const data = await getTestValue()
console.log(data.message)
return <div>{'index '}</div>
}