Spring & SpringBoot

스프링부트 엔드포인트 무한루프 오류 (NoHandlerFoundException)

땅콩콩 2024. 6. 27. 13:38

스프링부트로 프로젝트를 만들다가 완전 무섭게 생긴 오류를 만났다.....

 

아놔 완전 무시무시하다.. !ㅁ! 

무엇보다 무한루프에 컴퓨터가 뻗어서 제대로 된 로그 확인이 어려웠고, 디버깅을 했더니 코드가 타고타고 저기 심해 바닥까지 내려가서 디버깅으로는 원인을 제대로 파악할 수 없었다...

그래서 일단 이것저것 시도해봤다.

 

1. JPA 양방향 연관관계에서 순환참조가 발생해서 생긴 문제일까?

 

1-1 양방향 관계를 가지는 엔티티에서 toString 메서드를 사용하면 무한 루프가 발생할 수 있다!

> 롬복 사용없이 toString메서드 오버라이딩해서 순환참조를 피해보았으나 실패

 

1-2 잭슨 라이브러리를 사용하는 해결 방법이 있다고 한다.

> @JsonManagedReference와 @JsonBackReference를 사용해보았으나 실패

> @JsonIgnore 사용해도 실패

> @JsonView 사용해도 실패

 

2. 엔드포인트가 반복되는걸보니 뭔가 핸들러와 관련된 문제같다... -> 정답!!!

 

정답은 GlobalExceptionHandler의 @ControllerAdvice와 응답 형식의 문제!!

즉, 내가 설정해둔 애노테이션과 리턴 타입의 불일치에 있었다..

 

우선 나는 restController를 사용중인데, restControllerAdvice가 아니라 controllerAdvice를 사용한 것에서 문제가 시작됐다.

controllerAdvice를 사용했더라도 ResponseEntity를 사용했으면 스프링부트가 아 이건 뷰로 가는게 아니라 rest api응답으로 나가는구나 하고 알았을텐데, ResponseEntity를 쓰지도 않고, restControllerAdvice를 쓰지도 않았으니 스프링부트는 뷰가 있구나..! 그 뷰에 모델을 전달해야겠다고 생각한것이다.

문제가 있던 코드... ErrorResult 객체를 그대로 반환하고 있다.

 

그래서 스프링부트는 아마도...

 

일반 controllerAdvice... 근데 반환되는게 객체네.. 이놈은 분명 모델이로구나..

뷰는 어딨을까..  요청 path에서 뗄거떼고 찾았는데 뷰가 없다..

엥 뭐야 나 어디로가요 

 

이렇게 된 것 같다고 추측한다..

그래서 해결방법은 두가지다!!!

 

첫번째 방법은 ControllerAdvice를 사용하는 대신 모든 메소드를 ResponseEntity로 응답을 보내는 것이다.

이렇게하면 뷰를 사용하는게 아니라고 응답형식을 명확히 지정해줄 수 있게 된다.

모든 예외 응답을 ResponseEntity로 보내게 처리했다.

 

근데 사실 더 간단한 방법은 그냥 애초에 RestControllerAdvice를 쓰면 된다.

그럼 굳이 귀찮게 하나하나 알려줄 필요가 없다. Controller와 RestController의 차이라고 보면 된다.

이렇게 GlobalExceptionHandler에서 발생하는 모든 예외상황에 ResponseEntity를 통해 HTTP 응답을 반환하거나, 또는 RestControllerAdvice를 사용하도록 수정해서 해결했다.

아니근데 애초에 왜 여기에다가만 일반 ControllerAdvice를 쓴거냐 과거의 나야^^..... 덕분에 고생했다 고맙다!!!