들어가며

  • 약 8개 포스트에 걸쳐서 기존의 각 서블릿이 공통 로직을 각각 구현했어야 했고, View 이름이 중복되었으며 모델이 서블릿의 request에 의존하던 코드들을 깔끔하게 구조화시켰다.
  • 이번 포스트는 전체적인 구조를 정리하고 요청에 대해 어떻게 처리가 이루어지는지를 정리해본다.

 

 

 

MVC 프레임워크 전체 구조

  • 프론트 컨트롤러를 도입만 했던 버전 1부터 시작해 확장성을 적용시킨 버전 5까지 코드의 개선을 보아왔다.
  • 확장성을 적용시킨 프레임워크의 전체적인 구조는 다음과 같다.

  • 꽤 많이 복잡해졌다. 각 컴포넌트들에 대해 간략하게 정리하고 넘어가자.
  • Handler Mapping Store는 모든 핸들러(컨트롤러)에 대한 매핑 정보를 가지고 있다. 핸들러가 처리 가능한 URL을 key로 가지고 핸들러 객체를 value로 가진다.
  • Handler Adapter List는 Handler Mapping Store에서 반환받은 핸들러를 처리할 수 있는 어댑터들을 모아놓은 어댑터의 집합이다.
  • HandlerAdapter는 핸들러(컨트롤러)를 호출하고, 그 결과를 ModelView의 형식으로 반환하는 책임을 가진 인터페이스의 구현체들이다.
  • ViewResolver는 논리적 View 경로를 받아 실제 View가 존재하는 물리적 경로로 바꾸고 이 물리적 경로를 가진 View 객체를 반환하는 책임을 가진다.
  • MyView는 View로 사용자에게 화면을 뿌려주는 책임을 가진다.
  • Front Controller는 각 핸들러에 공통으로 처리되야 하는 로직이 존재할 경우 처리하는 책임을 가지며 요청을 받고 해당 요청을 처리할 수 있는 핸들러와 이 핸들러를 처리할 수 있는 HandlerAdapter를 찾아 요청을 위임하고, 그 결과를 최종적으로 클라이언트에게 내보내는 책임을 가진다.
    • 보면 이 Front Controller가 여러 객체들과 협력하는 것을 알 수 있을 것이다.

 

 

 

MVC 프레임워크의 요청 처리 과정

  • 클라이언트가 어떤 요청을 서버로 보내었다고 생각해보자. 어떤 일이 일어날까
  • 가장 먼저 Front Controller가 해당 요청을 받는다. 이후 해당 요청을 처리할 수 있는 핸들러가 존재하는지를 handler Mapping Store에서 찾은 뒤, 처리할 수 있는 핸들러를 가져온다.
  • 이후 해당 핸들러를 처리할 수 있는 어댑터를 찾는다. 이를 Handler Adapter List에서 찾는데 내부적으로 supports()메서드를 통해 처리 가능한 핸들러인지를 판단하도록 하는 방식으로 찾는다. 이후 처리 가능한 HandlerAdapter 구현체를 가져온다.
  • 이후 해당 HandlerAdapter 구현체에 핸들러를 호출하도록 요청한다. HandlerAdapter 구현체는 해당 요청 메시지를 받고, 핸들러를 호출하여 그 결과를 받아 ModelView로 Front Controller에게 반환한다.
  • Front Controller는 ModelView를 받아 ViewResolver에 View의 논리적 이름을 통해 MyView 객체를 반환하도록 요청한다. ViewResolver는 물리적 경로로 경로를 바꾼 MyView 객체를 반환하는 책임을 수행한다.
  • 이후 최종적으로 해당 MyView 객체에 ModelView로 받아온 Model을 넣고, View를 랜더링하여 클라이언트에게 반환하도록 함으로서 전체적인 처리가 완료된다.

 

 

 

마무리

  • 지금까지 우리가 새로운 프레임워크를 만들어 그 구조까지 모두 확인해 보았다.
  • 공교롭게도 스프링의 MVC 프레임워크 또한 거의 동일한 구조를 가지고 있는데 이는 스프링 MVC 프레임워크가 어디선가 혁신적인 아이디어를 통해 갑자기 나타난 것이 아닌 어떠한 문제와 기능, 그리고 편리성을 해결하기 위하여 생긴 수많은 논의와 생각들을 통해 나온 것임을 증명한다.
  • 다음 포스트부터는 스프링 MVC 프레임워크의 구조에 대해 알아보고 스프링 MVC 프레임워크에서 각 컴포넌트들이 어떻게 되어 있는지에 대해 알아본다.
복사했습니다!