표준화 예외 포멧
에러 응답을 모두 제각각 만들지 말고, 공통된 표준 포맷으로 내려주자는 취지로, RFC 9457 Problem Details for HTTP APIs를 참고할 수 있다.
해당 문서를 기반으로 Spring Framework6 부터는 대표 필드 5가지를 표현하는 ProblemDetail 이라는 클래스가 추가되었다. 해당 예외 응답 포멧으로 공통화하는 방법도 인지하고 넘어가자.
// 위치
org.springframework.http.ProblemDetail;
// 대표 필드
private URI type = BLANK_TYPE;
@Nullable
private String title;
private int status;
@Nullable
private String detail;
@Nullable
private URI instance;
@Nullable
private Map<String, Object> properties;
예시
1. Type: 에러의 종류를 식별하는 URI
"type": "https://example.com/errors/invalid-input"
- 어떤 유형의 문제인지, 어떤 문서 및 정책과 연결되는지 표현한다. URI 형태를 권장하며, 브라우저로 접근 시에 에러 설명 문서를 제공할 수 있다.
2. Title: 사람이 읽기 쉬운 짧은 에러 요약
"title": "Invalid Request"
- 에러 타입별로 거의 고정이며 detail보다 훨씬 일반적인 표현을 사용한다.
3. status: HTTP 상태 코드
"status": 400
- 실제 HTTP 상태 코드와 동일해야하며, 중복으로 설정하는 이유는 로그 저장시나, 중간 프록시가 상태코드를 바꾼 경우나, Http 정보 없이 body만 남은 경우에 대비하기 위함이다.
4. detail: 현재 발생한 문제에 대한 구체적인 설명
"detail": "Your current balance is 30, but that costs 50."
- 요청마다 달라질 수 있으며 문제에 대한 구체적인 설명이라 케이스마다 자유도가 높다. 사용자 요청의 수정 방향을 알려주는 용도로 활용한다.
5. instance: 현재 발생한 에러 사례의 식별자
"instance": "/errors/abc123"
- 이번에 발생한 에러를 식별하는 id로 쉽게 말해 이번 에러 사건 id를 의미한다. 추후 로그 추적이나 고객 문의, 장애 분석시에 사용할 수 있다.
전체 포멧 예시
{
"type": "...",
"title": "...",
"status": 400,
"detail": "...",
"errors": [
{
"field": "email",
"reason": "must not be blank"
}
]
}
- RFC 9457의 추가 필드(extension field)를 포함한 본문 전문 예시는 다음과 같다.