Info

  • BE API ํ†ต์‹  ์‹œ, responseCode์— ๋”ฐ๋ผ ๋ถ„๋ฅ˜๋˜๋Š” ์—๋Ÿฌ ์ผ€์ด์Šค.
  • ์—๋Ÿฌ ์ผ€์ด์Šค์— ๋”ฐ๋ผ ํ™”๋ฉด์—์„œ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์‰ฝ๋„๋ก enumํ™” ํ•˜์—ฌ ์‚ฌ์šฉ.
  • ํ˜„์žฌ API์—์„œ ๋ฐœ์ƒํ•œ ์—๋Ÿฌ๋ฅผ ํ™”๋ฉด๊นŒ์ง€ ํšจ์œจ์ ์œผ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ๋งˆ๋•…ํ•˜์ง€ ์•Š์•„ ๊ณ ๋ฏผ์ค‘.

Structure

  • Error ๋ฐœ์ƒ ์‹œ, responseCode์™€ ๊ธฐ์กด Error ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ApiError ์ƒ์„ฑ
ApiError.ts
import { ApiCode } from '@utils/error/constant/ApiCode'  
  
class ApiError extends Error {  
  public apiCode: ApiCode  
  public originalError?: Error  
  
  constructor(code: ApiCode, originalError?: Error) {  
    super(code)  
    this.name = `${this.constructor.name}.${code}`  
    this.apiCode = code  
    this.originalError = originalError  
  }  
  
  toString() {  
    return `code: ${this.apiCode}\noriginalError: ${this.originalError?.name}\n${this.originalError?.message}`  
  }  
}  
  
export default ApiError

Usage

  • repository์—์„œ API ํ†ต์‹ ์„ ํ†ตํ•ด ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ๊ฒฝ์šฐ, ์‹คํŒจ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•˜์—ฌ ApiError๋ฅผ throw
AuthRepository.login()
login: async (username: string, password: string) => {  
  const apiResponse: ApiResponse<Token> = new ApiResponse<Token>().parseData(  
    await api().post('login', {  
      username: username,  
      password: password  
    })  
  )  
  
  if (apiResponse.isFailure) throw new ApiError(apiResponse.code)  
  
  tokenRepository.setToken(apiResponse.body!)  
  
  return apiResponse.body!  
}
  • ํ•ด๋‹น function์„ ์‚ฌ์šฉํ•˜๋Š” ViewModel์—์„œ try/catch๋ฅผ ํ†ตํ•ด ApiError๋ฅผ catch โ†’ ์—๋Ÿฌ์— ๋Œ€ํ•œ ๋Œ€์‘
    • ์ด๋•Œ, catch์˜ ์ธ์ž์ธ e์˜ ํƒ€์ž…์„ ์œ ์ถ”ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ํƒ€์ž…์„ ์ •ํ•˜๋Š” ๋กœ์ง์ด ๋งค์šฐ ๊ธธ์–ด์ง.
    • ํ•ด๋‹น function ์ž์ฒด๋„ try/catch๋ฅผ ํ†ตํ•ด Error๋ฅผ ๊ฐ์ง€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋กœ์ง ์ž์ฒด๊ฐ€ ์˜๋ฏธ๋ณด๋‹ค ๊ธธ๊ฒŒ ๋Š˜์–ด์ง„ ํ˜•ํƒœ๊ฐ€ ๋œ๋‹ค.
useLoginViewModel.login()
const login = async () => {  
  if (!validate()) return  
  setLoading(true)  
  try {  
    const token: Token = await authRepository.login(username.value, password.value)  
  
    if (token.accessToken && token.refreshToken) {  
      setAuthorization({ isAuthorized: true, userInfo: await authRepository.getUserInfo() })  
      navigate('/', { replace: true })  
    }  
  } catch (e) {  
    handleLoginError(e)  
  } finally {  
    setLoading(false)  
  }  
}