태풍, GlobalMemberExceptionHandler error 이슈 해결, Order 개발
오늘은 태풍 때문인지 날씨가 많이 선선하니 좋았으나, 비가 많이오고, 날씨가 많이 흐렸다. 이 때문인지 금방 해결할 것같던 GlobalMemberExceptionHandler error 이슈는 생각보다 해결에 애를 먹었다. 정말 이해가 되지 않는 동작들로 어제 새벽 3시까지 해당 문제를 고민하게 만들었으니 말이다.
그래도 다행히(?) 해당 문제를 해결할 수 있는 방법은 찾았고, 내가 원하는 동작을 하도록 정상적으로 수정되었다. 하지만 여전히 이것이 왜 이렇게 동작하는가에 대해서는 의문이다..
GlobalMemberExceptionHandler error 이슈 해결
GlobalMemberExceptionHandler 의 오류를 개선한다. · Issue #9 · KEEMSY/shoes-ordering-system
설명 기준 버전/ 커밋: c62fb39 // MemberGlobalExceptionHandler 의 일부분 @ResponseBody @ExceptionHandler(value = {MemberDomainException.class}) @ResponseStatus(HttpStatus.BAD_REQUEST) public ErrorDTO handlerExc...
github.com
나는 Controller 에서 발생하는 에러를 @ControllerAdvice 를 통해 관리하고 있다. 이에 대해 간단하게 설명한다면, @ControllerAdvice 어노테이션은 Spring MVC 애플리케이션의 여러 @Controller 클래스에 적용되는 전역 예외 처리를 담당한다 이해하면 편하다.
나는 @ControllerAdvice 를 사용하여, 보다 깔끔한 Controller 클래스를 만들고 싶었다. 에러 처리로 지저분해지는 Controller 코드가 아닌 해당 통신에 대한 코드만 보기쉽게 정리된 코드를 기대하며 @ControllerAdvice 를 사용했다.
그리고 코드 베이스는 기대에 부응했다.@ControllerAdvice 를 사용함으로써, 훨씬 Controller 클래스가 명확해졌기 때문이다.
하지만 이를 사용함에 있어 문제가 존재했다. 그리고 나는 Product 도메인을 개발하면서 인지했었다.
오류: 해당 에러를 처리하는 메서드가 정상적으로 동작하지 않음
나는 각 도메인별, GlobalExceptionHandler 를 개발하여, 해당 도메인에서 발생하는 에러에 따른 올바른 HTTP 에러로 처리하도록 설계하였다. 하지만 정상적으로 동작하지 않았다. 이를 처음 인지한것은 Product 개발 간, Web 테스트를 작성하면서 인지하였고, 이를 해결하는데 있어, 컴포넌트를 인식하지 못하거나, 인식하는데, 부모 클래스를 먼저 스캔하는것으로 판단하여, 순서를 정해줌으로써 ProductGlobalExceptionHandler 의 오류를 개선했다. 그리고 나는 Member 도메인에서도 똑같이 해당 문제가 있는 것을 확인했고 동일한 방법으로 에러를 해결하면 되겠다 생각했다.
하지만 신기하게 순서을 똑같이 지정함으로써 해당 에러는 해결되지 않았다. 정확히는 하나(Member 혹은 Product)는 해결이 되었지만, 다른 하나는 문제가 재발했다.
기본적으로 @ControllerAdvice 로 어노테이션된 클래스의 메서드는 모든 컨트롤러에 전역적으로 적용되고, 여러 @ControllerAdvice 가 존재할 경우, 우선순위를 지정하여 특정 에러를 처리하도록 정하는 것으로 알고 있었다. 하지만 이것은 이번 경험을 통해 잘못된 방법이 아닌가? 하는 생각이 들었다.
부모클래스(GlobalExceptionHandler) 는 기본적으로 가장 낮은 순서(@Order(Ordered.LOWEST_PERCEDENCE))를 갖고있다. 그리고 나는 MemberGlobalExceptionHandler 와 ProductGlobalExceptionHandler 에 모두 가장 높은 순서(@Order(Ordered.HIGHEST_PERCEDENCE))를 부여하였으나, 이 순서대로 동작하지 않았다.
이상했다. 둘다 고장나는것도 아니고, 하나만 고장이 났다. 그리고 분명히 MemberDomainException 을 처리하는 메서드를 MemberGlobalExceptionHandler 에 작성해두었는데.. 이상했다.
너무 이상했다. 나는 우선순위에 문제가 있는듯하여, 부모클래스, 자식클래스 모두 일일히 하나씩 우선순위를 정수로 지정해보았다. 하지만 여전히 에러는 해결되지 않았다. 왜 이렇게 되는건지 이해가 되질 않았다. 이 부분 때문에 나는 진짜 이것저것 다해본다고 새벽3시가 넘도록 계속 책상에 앉아 키보드를 두두렸었다.
하지만 새벽에는 이 문제를 해결하지 못했다. 나는 디버그를 해보고 싶었지만, 경험의 부족과 지식의 부족으로 해당 부분을 어떻게 디버그 해야할지 모르겠었다.. GPT 에게 상황을 설명하고 문제해결을 위한 다양한 시도를 해보았으나 실패했다. 진짜 졸려죽는줄알았는데, 이거하면서 잠이 다달아나서 잠을 제대로 못잤던 것 같다.
오류 해결: 순서와 범위 지정
아침(?)에 일어나 바로 책상에 앉았다. 뭐 때문이었을까... 고민하다 어제 보지 않은 공식문서를 찾아보았다. 그리고 공식문서에서 힌트(?)를 얻고 기존의 메서드를 개선하고, 문제를 해결 할 수 있었다.
ControllerAdvice (Spring Framework 6.0.11 API)
Specialization of @Component for classes that declare @ExceptionHandler, @InitBinder, or @ModelAttribute methods to be shared across multiple @Controller classes. Classes annotated with @ControllerAdvice can be declared explicitly as Spring beans or auto-d
docs.spring.io
In addition, Ordered is not honored for scoped @ControllerAdvice beans — for example if such a bean has been configured as a request-scoped or session-scoped bean.
또한 범위가 지정된 @ControllerAdvice 빈(예: 해당 빈이 요청 범위 또는 세션 범위 빈으로 구성된 경우)에 대해서는 Ordered가 적용되지 않습니다.
해당 부분을 통해 문제 해결의 힌트를 얻었다. 나는 순서만을 생각하고, 범위를 생각하지 못했다. 생각해보면, 해당 도메인에만 적용되는것이 맞는 것인데, 도메인 에러 핸들러가 전역적인 범위를 가질 필요가 없었고 범위를 한정하여 이 문제를 해결 할 수 있었다.
나는 basePackages 설정을 통해 범위를 지정한 하위 패키지에 속한 컨트롤러에만 적용되도록 하였다. 그러나 순서에 대한 부분은 지울 수가 없었다. 순서를 없앨경우, 여전히 문제 해결이 되지 않았다. 이 부분은 정말 왜 이런건지.. 진짜 궁금하다.. 왜지..? 순서가 적용안된다했는데... 내부 동작 순서를 확인해보고 싶은데 디버그를 키고 종단점을 찍어봐도 모르겠다...
드디어 테스트가 정상적인 초록불을 멱등적으로 볼 수 있었다. 그리고 이를 기점으로 해당 이슈를 마무리 지었다.
Order 개발 시작
이번주 월요일부터 개발하겠다던 Order 를 목요일이되서야 개발을 시작했다.. 하...하... 이번 수요일을 토요일과 바꿨기에.. 무려 3일만에 시작하게 되었다.. 문서를 작성하는 것을 시작으로 진정으로 Order 개발을 시작했다.
해당 문서는 아래의 링크에서 확인 가능하다. 하지만 결정사항을 구체적으로 작성해두지 않아서 볼게.. 생각보다 없는듯하다..
신발 주문 시스템 분석 ‐ 도메인 : Order
shoes-ordering-system. Contribute to KEEMSY/shoes-ordering-system development by creating an account on GitHub.
github.com
지난 Member와 Product 개발을 진행하면서, 모델링 경험의 부족과 해당 도메인에 대한 경험의 부족으로 인한 수 많은 변경으로 인해 결정부분을 많이 추상적으로 작성해두었다. 그래도 컨텍스트에 작성한 Order 도메인 분석 부분을 구현하는 것을 핵심으로 개발을 진행할 예정이다.
오늘은 재미나게 Domain 계층을 개발하고 있는데, 시작부터 재밌다. 실제 주문과정을 상상하면서 진행하는데, (부족한) 상상이 실제가 된다고 생각하니 너무 즐겁다. 어서 남은 주말까지 열심히 달려서, 목표한 Order 도메인 개발을 이번주 내로 끝마칠 수 있도록 노력해야겠다.
아 물론 이번주로 끝마친다는 것이 개발 끝! 이 아니라 지금 Member, Product 도메인의 문제점을 식별하거나 개선점을 고민하듯이, 계속해서발전해 나갈 계획이다!
나는 1차적으로라도 프로젝트를 마무리를 하고서, 이력서를 완성하고, 면접을 경험하고 싶다. 요즘에는 정말 다른 개발자들과 이야기를 너무 하고싶은 생각뿐이다. 내 문제를 함께 고민하기도하고, 다른사람들의 고민을 함께 고민하고싶다. 특히 다른사람들의 생각, 코드이 너무 궁금하다.