Spring Framework에 소소한 기여.
최근에 회사 퇴근 이후 시간과 주말을 활용해 사이드 프로젝트를 진행하고 있다.
회사에선 주로 DevOps Engineering을 하고 있어서 Kotlin, Spring 6로 개발을 하고 싶었고 마음 맞는 지인들과 같이 사이드 프로젝트를 하고 있다.
Spring 6에 추가된 것들 중, ProblemDetail이라는 RFC-7807 을 반영한 클래스가 있다.
이 클래스를 사용하면 API 호출 시 입력 값이 올바르지 않거나, 로직이 잘못된 경우 RFC-7807 문서에 정의된 Error Response를 내려줄 수 있다.
API 개발을 하다보면 Error Response에 대한 포맷을 정의하는 것이 은근히 귀찮고 성가신 일인데, RFC 문서 내용을 바탕으로 Spring에서 클래스를 제공해주고 있어 사이드 프로젝트에서 적극적으로 쓰고 있다.
API 호출 시 입력 값 검증이 실패한 경우, 에러 응답을 내려주는 테스트를 작성하며 Kotlin으로 ProblemDetail 클래스를 생성하던 중 이상한 점을 발견했다.
ProblemDetail 클래스에 설정된 다른 private 필드에는 setter 메서드가 제공되어 apply 함수를 이용한 객체 구성을 할 수 있었는데, Map으로 정의된 properties 필드에 대해서만 setter 메서드가 제공되고 있지 않았다.
아래와 같이 작성을 해서 구현을 완료했지만, 찝찝한 느낌이 가시지 않아 Spring Framework 프로젝트를 열어 이슈를 확인했다.
ProblemDetail.forStatusAndDetail(
HttpStatusCode.valueOf(HttpStatus.BAD_REQUEST.value()),
ErrorMessage.INVALID_INPUT.value,
).apply {
setProperty("validationErrors" , validationErrors)
}
이슈를 확인해보니, ProblemDetail 클래스 객체 구성에 대해 의문을 가지는 사람이 아무도 없었던 것인지? 아니면 커스텀 한 에러 응답 클래스가 있어서 사용할 필요성을 못 느꼈던 건지 모르겠으나 올라온 이슈가 없었다.
그래서 아래 코드처럼 객체 구성을 할 순 없는지에 대해 이슈를 남겼다.
ProblemDetail.forStatusAndDetail(
HttpStatusCode.valueOf(HttpStatus.BAD_REQUEST.value()),
ErrorMessage.INVALID_INPUT.value,
).apply {
properties = mapOf("validationErrors" to validationErrors)
}
이슈를 남긴지 3일 정도 지난 후, Spring Framework Core 개발자 중 한명인
Sébastien Deleuze가 확인하여 코드를 수정한 뒤 6.0.14 마일스톤에 함께 릴리즈 될 수 있도록 반영을 해주었다.
6.0.14 버전이 릴리즈 되고 나면 Kotlin으로 ProblemDetail 클래스를 객체 구성할 때 부자연스러움이 없어질 것 같다.
소소한 기여였지만 Spring처럼 성숙한 프레임워크도 이런 류의 부자연스러움을 남길 수 있구나라는 생각이 들어, 사람 사는 거 다 똑같구나 하는 생각도 들었다.