22P by lemonmint 4일전 | ★ favorite | 댓글 5개

HTTP API를 개발할 때 에러 처리는 종종 번거로운 부분입니다. API 수가 많아지고 내부 로직이 복잡해질수록 세 가지 측면에서 어려움이 발생합니다.

  • 적절한 에러 코드 반환: 경험이 부족한 개발자의 경우 복잡한 로직에서 일관된 HTTP 상태 코드를 사용하기 어렵습니다.
  • 많은 양의 결과 로그 작성: 에러 발생 시 예상되는 모든 종료 지점에 로그를 기록하는 것은 코드 양을 늘리고 관리를 복잡하게 합니다.
  • 명확한 에러 메시지 전송: 클라이언트에게 단순히 에러 메시지를 전달하는 것만으로는 에러를 명확하게 이해하고 처리하기 어렵습니다.

적절한 에러 코드 반환 개선

에러 코드 사용의 일관성 문제를 해결하기 위해 StatusCodeMessage를 포함하는 HttpError 인터페이스 또는 구조체를 구현하는 방법을 제안합니다.

  • 해결책:
    • HttpError 타입 정의: HTTP 상태 코드와 메시지를 캡슐화.
    • 헬퍼 함수 제공: httperror.BadRequest("wrong format")와 같이 특정 에러 코드를 반환하는 헬퍼 함수를 사용하여 에러 객체를 쉽게 생성.
  • 장점:
    • IDE의 자동 완성 기능을 활용하여 편리하고 안정적으로 에러 코드와 메시지 입력.
    • 수동으로 숫자 코드를 입력하는 것보다 오류 발생 가능성 감소.
    • 사전에 준비된 설계 문서를 일일이 확인하는 번거로움 감소.

로그 작성 중앙화

반복적인 로그 작성을 줄이고 에러 처리 로직을 한 곳에서 관리하기 위해 HTTP 핸들러를 래핑하는 방법을 제시합니다.

  • 해결책:
    • 커스텀 라우터(chiwrap.Router) 구현: chi.Router와 같은 기존 라우터를 내부에 포함하고 에러 처리 로직을 추가합니다.
    • 핸들러 래핑: 커스텀 라우터의 Get 등의 메서드는 HandlerFunc를 받아서 내부적으로 실행하고, 에러가 발생하면 중앙 처리 로직으로 전달합니다.
    • 에러 콜백 함수: NewRouter 생성 시 errCallback 함수를 받아 에러 발생 시 해당 콜백을 호출하여 중앙에서 로그를 기록하거나 추가적인 처리를 수행합니다.
  • 장점:
    • API 로직에서 에러 발생 시 자동으로 적절한 에러 코드와 메시지가 응답으로 반환.
    • 서비스별로 적절한 로그를 기록하도록 콜백 함수를 등록하여 로그 관리가 용이.
    • 코드 중복을 줄이고 유지보수성 향상.

명확한 에러 메시지 전송 (RFC7807 활용)

클라이언트가 에러를 더 명확하게 이해하고 처리할 수 있도록 RFC7807 표준을 활용한 구조화된 에러 메시지 전송 방안을 제안합니다.

  • RFC7807 주요 요소:
    • type: 에러 유형을 식별하는 URI (예: https://example.com/errors/validation).
    • title: 에러에 대한 짧은 한 줄 설명.
    • status: HTTP 상태 코드와 동일.
    • detail: 사람이 읽을 수 있는 상세 에러 설명.
    • instance: 에러가 발생한 특정 URI (예: /api/users/abc).
    • extensions: 추가 정보를 담는 JSON 객체 (예: invalid_field, expected_format).
  • 구현:
    • RFC7807Error 구조체 생성 및 주요 요소 포함.

    • 메서드 체이닝 패턴(WithType(), WithInstance(), WithExtension())을 통해 쉽게 구조화된 에러 객체 생성.

    • ToHttpError() 메서드를 통해 RFC7807ErrorHttpError로 변환하여 중앙화된 라우터와 연동 가능.

    • 클라이언트가 에러의 종류, 원인, 발생 위치 등을 명확하게 파악 가능.

    • API 응답의 일관성과 유용성을 높여 클라이언트 개발 효율성 증대.

좋은 글 감사합니다

좋은 글 감사합니다!
참고로 스프링에서는 spirng-web 라이브러리 > org.springframework.http.ProblemDetail에 구현체가 존재합니다!

좋은 소개 감사합니다!
찾아보니 RFC 9457로 대체됐네요.

https://datatracker.ietf.org/doc/html/rfc9457
(기존 7807 문서: https://datatracker.ietf.org/doc/html/rfc7807)

RFC 7807과 RFC 9457의 주요 차이점

  • 문제 유형 관리: 7807은 커스텀 URI만 사용 가능, 9457은 IANA 공유 레지스트리 도입
  • 다중 오류 처리: 7807은 HTTP 207 상태 코드 사용 권장, 9457은 단일 문제 유형 내에서 errors 배열을 사용해 관련 오류를 그룹화
  • 확장 필드: 7807은 임의 필드 추가 가능, 9457은 문제 유형별 예상 필드 명시적 연관
  • 보안 권고: 7807은 미포함, 9457은 보안 취약점 방지를 위한 명시적 지침 추가
  • JSON 포인터: 7807은 미지원, 9457은 pointer 필드 공식 지원

2023년 7월 이후 신규 프로젝트에서는 RFC 9457을 적용하는 것을 권장

type 필드는 역참조 가능한 URI로 설정하는 것이 권장되는 것으로 보여요.

내부 서비스에서는 Swagger-ui 문서 링크로 대체해도 무방할 것 같습니다.