스프링 MVC - 직접 까보기 2탄! 그리고 새롭게 느낀 것들

최지환·2022년 4월 12일
0

스프링

목록 보기
6/12
post-thumbnail

스프링 MVC - 직접 까보기 2탄

이전 포스팅에 스프링 MVC의 대략적인 구조를 확인 해보기 위해 직접 Dispatcher Servlet을 들어가봐서 코드를 확인해 보았다.

사실 이렇게 까지 프레임워크의 코드를 들어가본것은 처음이라, 인텔리제이를 이용해서 확인해도 인터페이스와 구현체를 직접 하나하나 까보면서 흐름을 따라가는 것이 정말 어려웠다. 무엇보다 이전 포스팅에서는 김영한님의 강의에서 배운 내용을 끼워 맞추는 느낌으로 코드 구조를 이해하려고 했다.

그러다 보니 코드 흐름을 따라가던 중 배우지 않은 내용에 대해 의문점이 들게되었고, 이 의문을 해소 할 수가 없었다.

무엇보다 내 머리속에서 대충 끼워맞춰서 공부한 느낌이라 너무 찜찜했다.. 그래서 다시 공부하고 정리한다.


내가 궁금했던 점

스프링 MVC가 Http 요청을 받았을 때, FrameworkServlet.service( ) 에서 요청 받은 Http메소드가 patch 이거나 null인 경우는 processRequest( ) 으로 처리를 하고, 그렇지 않으면 super.service( ) 로 처리하는 로직에서 의문점이 발생했다.

Http요청 메서드가 patch와 null인 경우는 FrameworkServlet.service() → FrameworkServlet.processRequest () → DispatcherServlet.doService( ) → DispatcherServlet.doDispatch()의 로직으로 처리가 된다.

김영한님의 강의에서는 doDispatch( ) 가 HTTP 요청 처리의 핵심이라고 하셨기에, 난 이런 생각을 했다.

“일반적으로 Get과 Post를 많이 쓴다고 알고 있는데, 얘네들은 어디서 처리를하지?
그리고 다른 다른 메서드들은 모두 어디서 처리하지? ”

라는 생각이 들었다.

생각해보니, 내가 파악한 흐름에서는 Get과 Post는super.service()로 처리를 해야한다.

하지만 인텔리 제이에서 super.service()를 클릭하고, 인터페이스를 따라가보니, Get, Post, Put 등 다른 요청 메서드를 어디서 처리해야하는지 파악을 전혀 못했다.


해결법 - 의문점 해소

그러던 중, 개발자로 일하고 계시는 분들에게 이런 문제를 말씀드리고 조언을 구했다. 그때 한분께서 “그럼 디버그를 찍어보고 요청을 하면 알 수 있지 않나??” 라고 말씀하셨다.

사실 당연한 말씀이었지만, 나는 처음 그 말씀을 들었을 때, 당황했다. “왜 그 생각을 못했지?” 라는 생각을 했다.

솔직히 조금 충격받았다.

생각해보면 프레임워크 혹은 라이브러리 모두 사람이 작성한 코드이다.
나는 왜 스프링 또한 java로 작성된 코드이고 디버깅이 당연히 될텐데 이 생각을 왜 못했을까??

생각해 보면 어느 순간부터, 이런 것(라이브러리 프레임워크)들이 단순 도구로써 느껴졌고, 코드 자체로 인식을 못했다.

그러다 보니, 이런 도구들의 사용법만 익히고 쉽게 사용하는 요령을 익히는 것에 집중 하다보니 자연스럽게, 도구의 원리를 이해하려 하지 않게 되었다.
→ 물론 도구를 사용할 때, 작동 원리를 전부다 알아야하는 것은 아니다. 하지만 “이게 무슨 원리지?”라는 호기심 자체가 안생기는 것이 문제라고 생각한다.

그렇게 나는 코드로 짜여진 도구(스프링)를 도구로만 보고 코드라고 생각을 안했다...

사실 평소에 프레임워크를 직접 까보면 이런 일은 없을 텐데..(이것도 경험이라고 생각하기로 함)


그렇게 알게 된 것들

이런 과정을 통해 조언을 듣고, 집와서 바로 디버깅을 찍어보았다.

우선 GET방식을 확인해 보았다.

GET요청 메서드가 들어오면 FrameworkServlet.service()이 호출 된다. 이때 patch 또는 null이 아니면 super.service()가 호출이 된다. [super는 HttpServlet 이다. ]

HttpServlet에서 메서드의 타입이 GET인지 체크를 하고, 만약 맞다면 doGet ( ) 을 호출 한다.

그렇다면 doGet을 확인해보자.
FrameworkServlet.doGet()을 확인하면 processRequest() 가 호출 됨을 알 수 있다.

이후는 이전에 확인했던 Patch와 동일하게 로직이 작동한다. 따라서 이후로는 FrameworkServlet.doGet( ) →FrameworkServlet.processRequest() → DispatcherServlet.doService() → DispatcherServlet.doDispatch() 의 순으로 호출이 된다.

이 과정은 POST, PUT, DELETE 또한 동일한 것을 확인 했다.

조금 복잡하다. 정리하자면

Http요청 메서드가 patch와 null인 경우

FrameworkServlet.service() → FrameworkServlet.super.service() → DispatcherServlet.doService( ) → DispatcherServlet.doDispatch()의 로직으로 처리

그외 메서드 요청이 들어온 경우

FrameworkServlet.service() → HttpServlet.service() 여기서 요청 방식(GET,POST,PUT 등) 확인 → FrameworkServlet.do해당메서드( ) → FrameworkServlet.processRequest()→
DispatcherServlet.doService( ) → DispatcherServlet.doDispatch()의 로직으로 처리

즉 모든 HTTP 요청은 결국 DispatcherServlet의 doDispatch()로 처리가 된다는 것을 알 수 있었다.

doDispatch()가 핵심임을 확실하게 알았다. doDispatch()는 이전 포스트 말단에서 정리해 두었다.

0개의 댓글