반응형
소프트워에 개발 과정에서 예외처리는 필수적인 요소이다. 예외가 발생했을 때 이를 적절히 처리하지 않으면 프로그램이 비정상적으로 종료되거나 예상치 못한 동작들을 할 수 있다. 기본적인 예외처리는 간단한 방식으로 구현되지만, 프로젝트가 복잡해질수록 더 정교하고 유연한 예외처리 전략이 필요하다.
앞서 내가 진행했던 커스텀 예외처리에 관한 글인데, 당시에는 부족한 부분도 많고 재대로 이해하지 못한 부분도 있었고 아래 글 처럼 진행하였더니 여러 불편한 상황들이 많아서 더 안정적이고 유지보수, 가독성이 많이 발전된 코드를 작성하게 되어서 이 글을 작성하게 되었다.
[Custom] DRF Custom exception fomat (exception_handler)
Response에 이어서 exception_handler를 이용하여 기본 예외 포맷이나 응답 구조를 사용자화 하려고한다. 들어가기에 앞서 exception_handler란 무엇인가?'exception_handler'는 DRF의 예외처리 기능으로 API에서
jongseoung.tistory.com
응답 구조
우선 예외처리가 발생하면 리턴되는 응답 구조는 아래와 같이 설정하였다.
{
"code": "USER-NOT-FOUND",
"message": "유저를 찾을 수 없습니다."
}
APIException 오버라이딩
# core/exceptions/__init__.py
import json
from copy import deepcopy
from rest_framework.exceptions import APIException
from rest_framework import status
from enum import Enum
class Contexts(Enum):
code = 0
message = 1
@classmethod
def get_members(cls):
return cls.__members__.keys()
@classmethod
def get_context(cls, context):
return cls.__getitem__(context).value
class CustomAPIException(APIException):
status_code = status.HTTP_400_BAD_REQUEST
_msg = []
_map = dict(
code="UNKNOWN ERROR CODE",
message="UNKNOWN MESSAGE DESCRIPTION",
)
def __init__(self, **kwargs):
_detail_msg = deepcopy(self._msg) if self._msg else list()
_detail_map = deepcopy(self._map)
if kwargs:
_detail_msg = self.get_updated_msg(items=kwargs.items(), msg=_detail_msg)
for i, k in enumerate(_detail_map.keys()):
_detail_map[k] = _detail_msg[i]
self.detail = _detail_map
def get_updated_msg(self, items, msg):
for k, v in items:
if k in Contexts.get_members():
msg[self._get_context_value(k)] = v
return msg
@staticmethod
def _get_context_value(context):
return Contexts.get_context(context)
def get_error_messages(self):
return json.dumps(self._msg, ensure_ascii=False)
- 객체가 생성되면 __init__ 메서드 호출
- _msg와 _map을 복사하여 _detail_msg와 _detail_map으로 설정
- kwargs로 전달된 값으로 _detail_msg 업데이트
- _detail_map에 앞서 업데이트 시킨 _detail_msg 값을 부여
- self.detail에 최종적으로 서부 정보 설정
- 필요시, get_error_messages 메서드로 에러 메시지를 JSON형식으로 변환
굳이 map과 msg를 나눈 이유는 딕셔너리보다 리스트형으로 정의하고 호출하는게 조금 더 가독성이 좋고 작성하는데 편리하기 때문이다.
# 딕셔너리로 작성
_map = dict(
code="UNKNOWN ERROR CODE",
message="UNKNOWN MESSAGE DESCRIPTION",
)
# 리스트로 작성
_msg = ["UNKNOWN ERROR CODE", "UNKNOWN MESSAGE DESCRIPTION"]
호출 및 예외 클래스 생성
# core/exceptions/service_exceptions.py
from rest_framework import status
from . import CustomAPIException
class UnknownException(CustomAPIException):
status_code = status.HTTP_412_PRECONDITION_FAILED
_msg = ["UNKNOWN-EXCEPTION", "서버에서 알 수 없는 에러가 발생하였습니다."]
# 예외처리가 필요한 부분에서 호출
from core.exceptions.service_exceptions import *
try:
...
except:
raise UnknownException
참고
`황금별`.blog
황금별의 기술블로그 ……໒(⊙ᴗ⊙)७✎▤
www.0x00.kr
반응형
'BackEnd > Django, DRF' 카테고리의 다른 글
[Custom] Custom Logging Mixin With CRUD Mixin (0) | 2024.05.23 |
---|---|
[Custom] Django와 CustomJWT로 안전한 인증 시스템 구축하기 (0) | 2024.05.23 |
[TEST] 테스트 DB 없이 Django에서 유닛 테스트 수행하기 (0) | 2024.05.14 |
[CORS] DRF에서 CORS 문제 해결 및 테스트 방법 (0) | 2024.05.14 |
[Custom] DRF Custom exception fomat (exception_handler) (0) | 2024.05.02 |