Skip to content

Commit

Permalink
#82 fix: authFetch 기존 fetchApi로 통합
Browse files Browse the repository at this point in the history
  • Loading branch information
hwanheejung committed Aug 14, 2024
1 parent 40525b9 commit c2669fa
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 100 deletions.
2 changes: 2 additions & 0 deletions src/app/(onboarding)/signup/components/NicknameForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import Button from '@/components/Button'
import NicknameInput from '@/components/TextInput/NicknameInput'
import { changeNickname } from '@/lib'
import { useSession } from 'next-auth/react'
import { useRouter } from 'next/navigation'
import SketchIcon from 'public/icons/sketchIcons-1.svg'
Expand All @@ -18,6 +19,7 @@ const NicknameForm = () => {
update({
name: nickname,
})
await changeNickname(nickname)
router.push('/signup/complete')
}

Expand Down
2 changes: 2 additions & 0 deletions src/app/mypage/profileEdit/components/NicknameForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Button from '@/components/Button'
import { useSession } from 'next-auth/react'
import { ReactNode, useState } from 'react'
import NicknameInput from '@/components/TextInput/NicknameInput'
import { changeNickname } from '@/lib'
import Title from './Title'

const NicknameForm = ({ children }: { children: ReactNode }) => {
Expand All @@ -15,6 +16,7 @@ const NicknameForm = ({ children }: { children: ReactNode }) => {
update({
name: newName,
})
await changeNickname(newName)
}

return (
Expand Down
6 changes: 2 additions & 4 deletions src/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import NextAuth from 'next-auth'
import Kakao from 'next-auth/providers/kakao'
import { changeNickname, login, refreshAT } from './lib/api/auth'
import { login, refreshAT } from './lib/api/auth'

/* eslint-disable-next-line @typescript-eslint/naming-convention */
export const { handlers, signIn, signOut, auth, unstable_update } = NextAuth({
Expand Down Expand Up @@ -30,7 +30,6 @@ export const { handlers, signIn, signOut, auth, unstable_update } = NextAuth({
birthDt: '2024-08-11', // TODO: 기획 대기
gender: 'F', // TODO: 기획 대기
})

user.name = nickName
user.newUser = newUser
user.accessToken = accessToken
Expand All @@ -47,8 +46,7 @@ export const { handlers, signIn, signOut, auth, unstable_update } = NextAuth({
async jwt({ token, user, account, trigger, session }) {
if (trigger === 'update' && session?.name) {
const { name } = session
await changeNickname(name, token.accessToken) // server update
token.name = name // client update
token.name = name
}
if (trigger === 'update' && session?.accessToken) {
token.accessToken = session.accessToken
Expand Down
48 changes: 34 additions & 14 deletions src/lib/api/auth.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,53 @@
import { SignInPayload, User } from '@/types'
import { post, put } from './base'

export const login = async (body: SignInPayload): Promise<User> => {
const res = await post('/api/v1/oauth/sign-in', {
body: JSON.stringify(body),
})
const handleResponse = async (res: Response) => {
const text = await res.text()

if (!res.ok) {
throw new Error(
`Request failed: ${res.status} - ${res.statusText} - ${text || 'No error message provided'}`,
)
}

if (!text) {
throw new Error('No response body')
}

return res.data
try {
return JSON.parse(text)
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
} catch (error: any) {
throw new Error(`Failed to parse JSON: ${error.message}`)
}
}

export const changeNickname = async (nickName: string, token: string) => {
return put('/api/v1/user/nickname', {
export const login = async (body: SignInPayload): Promise<User> => {
const res = await fetch(`${process.env.API_HOST}/api/v1/oauth/sign-in`, {
method: 'POST',
body: JSON.stringify(body),
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ nickName }),
})

const data = await handleResponse(res)
return data.data
}

export const refreshAT = async (refreshToken: string) => {
const res = await put('/api/v1/oauth/re-issue', {
const res = await fetch(`${process.env.API_HOST}/api/v1/oauth/re-issue`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${refreshToken}`,
},
})

const data = await handleResponse(res)

return {
accessToken: res.data.accessToken,
refreshToken: res.data.refreshToken,
expiredDate: res.data.expiredDate,
accessToken: data.data.accessToken,
refreshToken: data.data.refreshToken,
expiredDate: data.data.expiredDate,
}
}
76 changes: 53 additions & 23 deletions src/lib/api/base.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
'use server'

import { auth, unstable_update as update, signOut } from '@/auth'
import { RequestInit } from 'next/dist/server/web/spec-extension/request'
import { refreshAT } from './auth'

const ERRORS = {
FETCH_FAILED: '데이터를 불러오는데 실패했습니다.',
SAVE_FAILED: '데이터를 저장하는데 실패했습니다.',
DELETE_FAILED: '데이터를 삭제하는데 실패했습니다.',
}

const getBaseUrl = (useMocked: boolean) =>
useMocked ? 'http://localhost:3001' : process.env.API_HOST
Expand All @@ -9,13 +19,49 @@ const fetchApi = async (
useMocked: boolean,
errorMessage: string,
) => {
const res = await fetch(getBaseUrl(useMocked) + path, options)
const session = await auth()

const fetchOptions = {
...options,
headers: {
'content-type': 'application/json',
...options?.headers,
...(session && { Authorization: `Bearer ${session?.accessToken}` }),
},
}

let res = await fetch(getBaseUrl(useMocked) + path, fetchOptions)

if (res.status === 401 && session) {
const resJson = await res.json()
if (resJson.code === 'JWT002') {
// AT expired
try {
const newToken = await refreshAT(session.refreshToken)

await update({
accessToken: newToken.accessToken,
refreshToken: newToken.refreshToken,
expiredDate: newToken.expiredDate,
})

// retry original request
res = await fetch(getBaseUrl(useMocked) + path, fetchOptions)
} catch (e) {
signOut()
}
} else {
// RT expired or invalid
signOut()
}
}

if (!res.ok) {
throw new Error(errorMessage)
throw new Error(`Error: ${res.status} - ${res.statusText}. ${errorMessage}`)
}

return res.json()
const text = await res.text()
return text ? JSON.parse(text) : null
}

export const get = async (
Expand All @@ -28,13 +74,9 @@ export const get = async (
{
...options,
method: 'GET',
headers: {
'Content-Type': 'application/json',
...options?.headers,
},
},
useMocked,
'데이터를 불러오는데 실패했습니다.',
ERRORS.FETCH_FAILED,
)

export const post = async (
Expand All @@ -47,13 +89,9 @@ export const post = async (
{
...options,
method: 'POST',
headers: {
'Content-Type': 'application/json',
...options?.headers,
},
},
useMocked,
'데이터를 저장하는데 실패했습니다.',
ERRORS.SAVE_FAILED,
)

export const put = async (
Expand All @@ -66,13 +104,9 @@ export const put = async (
{
...options,
method: 'PUT',
headers: {
'Content-Type': 'application/json',
...options?.headers,
},
},
useMocked,
'데이터를 저장하는데 실패했습니다.',
ERRORS.SAVE_FAILED,
)

export const deleteApi = async (
Expand All @@ -85,11 +119,7 @@ export const deleteApi = async (
{
...options,
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
...options?.headers,
},
},
useMocked,
'데이터를 삭제하는데 실패했습니다.',
ERRORS.DELETE_FAILED,
)
6 changes: 2 additions & 4 deletions src/lib/api/board.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Board, CreateBoardPayload } from '@/types'
import { get } from './base'
import { authFetch } from './customFetch/authFetch'
import { get, post } from './base'

export const getBoard = async (id: string): Promise<Board> => {
const res = await get(`/api/v1/boards/${id}`, {
Expand All @@ -15,8 +14,7 @@ export const getBoard = async (id: string): Promise<Board> => {
export const postBoard = async (
payload: CreateBoardPayload,
): Promise<string> => {
const res = await authFetch('/api/v1/boards', {
method: 'POST',
const res = await post('/api/v1/boards', {
body: JSON.stringify(payload),
})

Expand Down
51 changes: 0 additions & 51 deletions src/lib/api/customFetch/authFetch.ts

This file was deleted.

13 changes: 9 additions & 4 deletions src/lib/api/user.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import { WithdrawUserPayload } from '@/types'
import { authFetch } from './customFetch/authFetch'
import { get, put } from './base'

export const withdraw = async (body: WithdrawUserPayload) => {
return authFetch('/api/v1/user/withdraw', {
method: 'PUT',
return put('/api/v1/user/withdraw', {
body: JSON.stringify(body),
})
}

export const changeNickname = async (nickName: string) => {
return put(`/api/v1/user/nickname`, {
body: JSON.stringify({ nickName }),
})
}

export const viewProfile = async () => {
return authFetch('/api/v1/user/profile', {
return get('/api/v1/user/profile', {
next: {
tags: ['profile'],
},
Expand Down

0 comments on commit c2669fa

Please sign in to comment.