api 요청 시 header에서 필수로 받아야하는 값이 db로 정리되어있어 service를 di받아야하기 때문에
guard를 이용해 validation을 해주려고 했습니다.
하지만 guard에서 사용자 정의 에러를 던지니 interceptor를 들리지않고 바로 예외 filter로 넘어가게 되었고 멘붕이 왔어요~
마음 다잡고 이제 왜 그렇게 되었는지 설명하면서 nest의 요청 수명 주기에 대해 알아보도록 하겠습니다.
nest 공식페이지를 보면 이렇게 적혀 있는 것을 볼 수 있습니다
요청 -> 미들웨어 -> 가드 -> 요청 인터셉터 -> 파이프 -> 응답 -> 응답 인터셉터 -> 예외 필터 -> 응답
이것만 보면 당연히 인터셉터도 들리는게 맞다! 라고 생각할 수 있습니다.
왜냐? catchError로 error를 잡으니까!!
물론 저도 그랬습니다ㅠㅠㅠㅠㅠ
그래서 guard와 interceptor, filter에 로그를 찍어봤습니다
그 결과..
인터셉터만 쏙 빼두고 응답을 주고 있는것을 볼 수 있습니다ㅠ
물론 guard도 middleware의 한 종류니까 middleware 자체도 안되겠죠? (해본건 안비밀..)
왜 그런걸까요?
냅다 스택 오버 플로우를 들어가봤습니다
위 글에서는.. '안돼 돌아가! 잡을 수 없어' 였습니다
그럼 다시 생각해봅시다 왜 인터셉터만 쏙 빼두고 갈 수 있을까요?
제가 생각한 이유는 이렇습니다
interceptor에서 사용하는 rxjs의 catchError자체가 응답 후의 error를 잡게 되는 것이고
middleware와 guard는 controller에 들어오기 전에 실행되기 떄문에 interceptor에서는 catch 할 수 없다!
이것을 증명하기 위해 이번에는 정상적으로 controller에 들어온 후 에러를 터트리고 로그를 찍어보았습니다.
정상적으로 interceptor에 들리고 에러를 잡아 로직을 처리하는 것을 보았습니다.
그리고 다음 nestjs의 issues를 보면
https://github.com/nestjs/nest/issues/3065
guard가 interceptor보다 먼저 실행되기 때문에 guard의 error는 잡을 수 없다라고 설명하고 있습니다.
어떻게든 돌아가야합니다..
error & log 처리를 interceptor가 아니라 filter를 이용한다던지
db의 값이나 다른 service를 이용해 확인을 해야한다면 service단에서 해결하거나
아니면 guard에서 모든 것을 해결하는 방법 등 여러가지 방법이 있을 것 같습니다.
이 이슈는 나중에도 또 발목을 잡게 될 것 같은데 저같은 이슈가 있으신분들에게 조금이라도 도움이 됐음 합니다ㅎㅎ
여담으로 저는 interceptor에서 사용량과 성공 여부를 체크하는 로직이라서
guard에서 error가 나면 어떤 사람이 사용한지 몰라 interceptor에서 할 일이 없어 그대로 두었습니다
가드 & 미들웨어에서 사용자 정의 에러를 던지면 interceptor를 들리지 않는다!
저도 Interceptor 로 Logging Interceptor 를 만들던 중에 "라이프 사이클에 따르면 Guard 에서 에러가 발생했을 떄, Interceptor 로 가지 않지 않을까?" 라는 의구심이 들어서 찾아보던 중에 딱 맞게 오게되었습니다.
이런 부분들을 대신 연구해주셔서 큰 도움이 되었습니다. 감사합니다.