useErrorHandler.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /************************
  2. * import
  3. ************************/
  4. const useErrorHandler = () => {
  5. const { $log, $toast, $eventBus } = useNuxtApp()
  6. // 공통 에러코드
  7. let errProfiles = [
  8. { code : '9999' , action : 0, desc : '기타오류', proc : {type:'toast',msg:'처리중 오류가 발생되었습니다.<br/> 지속발생시 관리자에게 문의 바랍니다.'}, after : null}
  9. ]
  10. let errObj = { code : '' , action : 0, desc : '', proc : {type:'toast',msg:'처리중 오류가 발생되었습니다.<br/>상세오류코드: '}, after : null}
  11. /**
  12. * 공통 에러 처리 함수
  13. * @param {*} error 에러
  14. */
  15. async function fnSetCommErrorHandle(error){
  16. let code = ''
  17. let msg = ''
  18. if (error.response){
  19. code = error.response.data.resCode
  20. msg = error.response.data.resMsg
  21. }
  22. //$log.error('[ErrorHandle][ERROR]' + JSON.stringify(error.response.data))
  23. if(code === '1005' || code === '1006' || code === '1007' || code === '1008') {
  24. // 1005: 토큰이 없음, 1006: 토큰 만료됨, 1007: 잘못된 토큰 값, 1008: 로그아웃 처리된 토큰 값 => 강제 로그인 페이지로 이동
  25. $eventBus.emit('SESSION_DESTORY')
  26. }
  27. // 에러로 처리
  28. errObj.code = code
  29. if(_isEmpty(errObj.code)){
  30. errObj = _find(errProfiles, {code:'9999'})
  31. code = '9999'
  32. }
  33. if(errObj.proc.type === 'toast'){
  34. let toastMsg = errObj.proc.msg
  35. toastMsg = errObj.proc.msg.concat(msg+'['+code+']')
  36. //$toast.error(toastMsg)
  37. }
  38. return false
  39. }
  40. // 새로운 포괄적 에러 처리 함수들 추가
  41. const handleApiError = (error, context = '') => {
  42. console.error(`API 오류 [${context}]:`, error)
  43. let errorMessage = '서버 오류가 발생했습니다.'
  44. if (error.response) {
  45. const status = error.response.status
  46. const data = error.response.data
  47. switch (status) {
  48. case 400:
  49. errorMessage = data?.message || '잘못된 요청입니다.'
  50. break
  51. case 401:
  52. errorMessage = '인증이 필요합니다. 다시 로그인해주세요.'
  53. $eventBus.emit('SESSION_DESTORY')
  54. break
  55. case 403:
  56. errorMessage = '접근 권한이 없습니다.'
  57. break
  58. case 404:
  59. errorMessage = '요청한 리소스를 찾을 수 없습니다.'
  60. break
  61. case 422:
  62. errorMessage = data?.message || '입력 데이터를 확인해주세요.'
  63. break
  64. case 429:
  65. errorMessage = '요청이 너무 많습니다. 잠시 후 다시 시도해주세요.'
  66. break
  67. case 500:
  68. errorMessage = '서버 내부 오류가 발생했습니다.'
  69. break
  70. default:
  71. errorMessage = data?.message || `서버 오류가 발생했습니다. (${status})`
  72. }
  73. } else if (error.request) {
  74. errorMessage = '네트워크 오류가 발생했습니다. 인터넷 연결을 확인해주세요.'
  75. } else {
  76. errorMessage = error.message || '알 수 없는 오류가 발생했습니다.'
  77. }
  78. $toast.error(errorMessage)
  79. return {
  80. message: errorMessage,
  81. status: error.response?.status,
  82. data: error.response?.data
  83. }
  84. }
  85. const handleValidationError = (errors) => {
  86. if (Array.isArray(errors)) {
  87. errors.forEach(error => {
  88. $toast.error(error)
  89. })
  90. } else if (typeof errors === 'object') {
  91. Object.values(errors).forEach(error => {
  92. if (Array.isArray(error)) {
  93. error.forEach(msg => $toast.error(msg))
  94. } else {
  95. $toast.error(error)
  96. }
  97. })
  98. } else {
  99. $toast.error(errors || '입력 데이터를 확인해주세요.')
  100. }
  101. }
  102. const handleFileError = (error, fileName = '') => {
  103. const prefix = fileName ? `[${fileName}] ` : ''
  104. if (error.name === 'FileSizeError') {
  105. $toast.error(`${prefix}파일 크기가 너무 큽니다. (최대 10MB)`)
  106. } else if (error.name === 'FileTypeError') {
  107. $toast.error(`${prefix}지원하지 않는 파일 형식입니다.`)
  108. } else if (error.name === 'FileReadError') {
  109. $toast.error(`${prefix}파일을 읽는 중 오류가 발생했습니다.`)
  110. } else {
  111. $toast.error(`${prefix}파일 처리 중 오류가 발생했습니다.`)
  112. }
  113. }
  114. const showConfirmDialog = (title, message, onConfirm, onCancel = null) => {
  115. const param = {
  116. id: 'confirmDialog',
  117. title: title,
  118. content: message,
  119. yes: {
  120. text: "확인",
  121. isProc: true,
  122. event: "CONFIRM_DIALOG_YES",
  123. param: null,
  124. },
  125. no: {
  126. text: "취소",
  127. isProc: false,
  128. event: "CONFIRM_DIALOG_NO",
  129. param: null,
  130. },
  131. }
  132. // 이벤트 리스너 정리 후 재등록
  133. $eventBus.off("CONFIRM_DIALOG_YES")
  134. $eventBus.off("CONFIRM_DIALOG_NO")
  135. $eventBus.on("CONFIRM_DIALOG_YES", () => {
  136. if (onConfirm) onConfirm()
  137. $eventBus.off("CONFIRM_DIALOG_YES")
  138. $eventBus.off("CONFIRM_DIALOG_NO")
  139. })
  140. $eventBus.on("CONFIRM_DIALOG_NO", () => {
  141. if (onCancel) onCancel()
  142. $eventBus.off("CONFIRM_DIALOG_YES")
  143. $eventBus.off("CONFIRM_DIALOG_NO")
  144. })
  145. $eventBus.emit("OPEN_CONFIRM_POP_UP", param)
  146. }
  147. return {
  148. fnSetCommErrorHandle,
  149. handleApiError,
  150. handleValidationError,
  151. handleFileError,
  152. showConfirmDialog
  153. }
  154. }
  155. export default useErrorHandler