์ด๋ฒ์ ํ์์ โํ๋ก์ ํธ ์ ๋ฐ์ Fetch API๋ฅผ Axios๋ก ๋ฆฌํฉํฐ๋งํด๋ฌ๋ผโ๋ ์์ฒญ์ ๋ฐ์๋ค.
๋จ์ํ ์์ฒญ ์ฝ๋๋ฅผ ๋ฐ๊พธ๋ ์์ ์ฒ๋ผ ๋ณด์์ง๋ง,
๋ง์ ์งํํด๋ณด๋ HTTP ํต์ ์ ๊ตฌ์กฐ์ RESTful API ์ค๊ณ๊น์ง
ํ ๋ฒ์ ์ดํดํ ์ ์๋ ๊ณ๊ธฐ๊ฐ ๋๋ค.
ํด๋ผ์ด์ธํธ(๋ธ๋ผ์ฐ์ )์ ์๋ฒ๋ HTTP ํ๋กํ ์ฝ์ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ๋๋ค.
์ด๋ ์์ฒญ์ ๋ณดํต ๋ค์ ๋ค ๊ฐ์ง ์์๋ก ๊ตฌ์ฑ๋๋ค ๐
| ์์ | ์ค๋ช | ์์ |
|---|---|---|
| Method | ๋์์ ์ข ๋ฅ (GET, POST, PATCH, DELETE ๋ฑ) | POST /apis/posts |
| URL | ๋ฆฌ์์ค(๋ฐ์ดํฐ)์ ์์น | /apis/posts |
| Header | ์์ฒญ/์๋ต์ ๋ถ๊ฐ ์ ๋ณด | Content-Type: application/json |
| Body | ์ค์ ์ ์ก๋๋ ๋ฐ์ดํฐ | { "content": "์ค๋ ํ๋ฃจ ๋๋ฌด ํ๋ค๋ค" } |
REST(Representational State Transfer) ๋
์๋ฒ ์์(Resource)์ ๋ช ํํ ๊ท์น์ผ๋ก ๋ค๋ฃจ๋ API ๋์์ธ ํจํด์ด๋ค.
| Method | ์๋ฏธ | ์์ |
|---|---|---|
| GET | ์กฐํ | /apis/posts |
| POST | ์์ฑ | /apis/posts |
| PATCH/PUT | ์์ | /apis/posts/:id |
| DELETE | ์ญ์ | /apis/posts/:id |
์ด ๊ท์น์ ๋ฐ๋ผ, Axios๋ก ์์ฒญ์ ๋ณด๋ผ ๋
axios.get, axios.post, axios.delete๊ฐ ์์ฐ์ค๋ฝ๊ฒ REST ๊ตฌ์กฐ๋ฅผ ํํํ๋ค.
Axios๋ Fetch API๋ฅผ ๋ ๋ค๋ฃจ๊ธฐ ์ฝ๊ฒ ๊ฐ์ผ HTTP ํด๋ผ์ด์ธํธ๋ค.
| ํญ๋ชฉ | Fetch | Axios |
|---|---|---|
| JSON ๋ณํ | ์๋(res.json()) | ์๋(res.data) |
| ์๋ฌ ์ฒ๋ฆฌ | if (!res.ok) ํ์ | 200๋ ์ธ์ ์๋ throw |
| ์ฟ ํค ์ ์ง | credentials: 'include' | withCredentials: true |
| ๊ธฐ๋ณธ ํค๋ ์ค์ | ์ง์ ๋งค๋ฒ ์ง์ | ์ธ์คํด์ค์์ ์ ์ญ ์ค์ ๊ฐ๋ฅ |
| ์ธํฐ์ ํฐ | โ | โ ์ง์ |
์๋๋ ์ด๋ฒ ํ๋ก์ ํธ์์ ์ค์ ๋ก ๋ฐ๊พผ ์ฝ๋๋ค์ด๋ค.
(Next.js + React Query + Zustand ๊ธฐ๋ฐ)
Before (Fetch)
await fetch('/apis/auth/logout', { method: 'POST', credentials: 'include' })
logout()
router.push('/login')
After (Axios)
await axios.post('/apis/auth/logout', null, { withCredentials: true })
logout()
router.push('/login')
โ axios.post()๋ body๊ฐ ์์ ๋ null ์ ๋ฌ
โ ์ฟ ํค ์ธ์
์ ์ง ์ withCredentials: true ํ์
Before
const body = new FormData()
body.append('email', email)
body.append('password', password)
const res = await fetch('/apis/auth/login', { method: 'POST', body })
const data = await res.json()
if (res.ok) setUser(data.user)
After
const body = new FormData()
body.append('email', email)
body.append('password', password)
const res = await axios.post('/apis/auth/login', body, { withCredentials: true })
setUser(res.data.user)
โ Axios๋ ์๋์ผ๋ก ์๋ต์ JSON์ผ๋ก ํ์ฑ (res.data)
โ 401, 500 ๋ฑ์ ์ํ ์ฝ๋๋ ์๋์ผ๋ก ์์ธ ์ฒ๋ฆฌ๋จ
Before
await fetch('/apis/posts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ content, tags }),
})
After
await axios.post('/apis/posts', { content, tags }, { withCredentials: true })
โ JSON.stringify ํ์ ์์
โ Content-Type ์๋ ์ง์
Before
const qs = new URLSearchParams({ cursor, limit })
const res = await fetch(`/apis/posts?${qs}`, { cache: 'no-store' })
if (!res.ok) throw new Error(`API ์คํจ: ${res.status}`)
return res.json()
After
const qs = new URLSearchParams({ cursor, limit })
const res = await axios.get(`/apis/posts?${qs}`, { withCredentials: true })
return res.data
โ cache๋ axios์์ ์๋ฏธ ์์ โ ์๋ต
โ 200๋ ์ธ ์ํ์ฝ๋๋ ์๋์ผ๋ก catch๋ก ์ ๋ฌ
Before
const res = await fetch(`/apis/posts/${id}`, { cache: 'no-store' })
if (res.status === 404) throw new Error('NOT_FOUND')
return res.json()
After
try {
const res = await axios.get(`/apis/posts/${id}`, { withCredentials: true })
return res.data
} catch (e) {
if (axios.isAxiosError(e) && e.response?.status === 404) {
throw new Error('NOT_FOUND')
}
throw e
}
โ 404 ์์ธ๋ ๋ช ์์ ์ผ๋ก ์ฒ๋ฆฌ ๊ฐ๋ฅ
Before
await fetch(`/apis/me/posts/${id}`, { method: 'DELETE' })
After
await axios.delete(`/apis/me/posts/${id}`, { withCredentials: true })
โ RESTful ๊ท์น์ ๋ง๋ ๋ฉ์๋ ์ด๋ฆ(delete)
โ ์๋ฌ ๋ฐ์ ์ catch์์ ๊ฐ๋จํ ์ฒ๋ฆฌ
| Method | Body ์ฌ์ฉ ์ฌ๋ถ | ๋ชฉ์ | ์์ |
|---|---|---|---|
| GET | โ ์์ | ๋ฐ์ดํฐ ์กฐํ | /apis/posts |
| POST | โ ์์ | ์ ๋ฐ์ดํฐ ์์ฑ | /apis/posts |
| PATCH/PUT | โ ์์ | ์ผ๋ถ ์์ | /apis/posts/:id |
| DELETE | โ ์์ | ๋ฐ์ดํฐ ์ญ์ | /apis/posts/:id |
๐ก POST๋ง body๋ฅผ ๋ฐ๋์ ํฌํจํด์ผ ํ๊ณ ,
GET์ด๋ DELETE๋ URL๋ก ๋ฆฌ์์ค๋ฅผ ์ง์ ํ๋ ๊ฒ ์์น์ด๋ค.
Axios๋ ๋จ์ํ ๋ฌธ๋ฒ์ ๊ฐ๊ฒฐํ๊ฒ ๋ง๋๋ ๋๊ตฌ๊ฐ ์๋๋ผ,
HTTP ์์ฒญ์ ๊ตฌ์กฐ๋ฅผ ๋ช ํํ๊ฒ ๋๋ฌ๋ด๋ ๋๊ตฌ์๋ค.
axios.post() โ โ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ธ๋คโaxios.get() โ โ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์จ๋คโaxios.delete() โ โ์๋ฒ์ ๋ฆฌ์์ค๋ฅผ ์ ๊ฑฐํ๋คโ
์ด๋ ๊ฒ HTTP์ ์๋ฏธ๊ฐ ์ฝ๋์ ๋ น์๋ ๋ค.
| ํญ๋ชฉ | Fetch | Axios |
|---|---|---|
| ์ฝ๋ ๊ธธ์ด | ๋ฐ๋ณต ๋ง์ | ์งง๊ณ ๊ฐ๊ฒฐ |
| ์๋ฌ ์ฒ๋ฆฌ | if ๋ฌธ ์๋ | catch ์๋ |
| ๊ณตํต ์ค์ | ๋ถ๊ฐ | ์ธ์คํด์ค์์ ๊ฐ๋ฅ |
| ์ ์ง๋ณด์์ฑ | ๋ฎ์ | ๋์ |
| REST ํํ | ์ ํ์ | ์ง๊ด์ (get/post/delete) |
POST์ body๊ฐ ๊ผญ ์์ด์ผ ํ๊ณ ,GET์ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ์ง ์์์ผ ํ๋ค.