티스토리 뷰
스프링 MVC |
프론트 컨트롤러 패턴 |
스프링으로 웹 개발을 해본사람들은 알겠지만 컨트롤러가 비즈니스 로직이 담긴 서비스 객체에 요청을 전달하면, 로직의 결과물을 리턴받는다. 그렇게 메인 컨트롤러의 실행이 끝나게 되면 return "XXX.jsp"; 문장을 실행시켜서
저 jsp파일을 사용자에게 보여주게끔 한다. 근데, 사실은 좀더 내부를 자세히 보면 메인 컨트롤러는 프론트 컨트롤러인 디스패쳐 서블릿에게 그 뷰의 이름을 리턴하는것이고, 실제로 jsp파일을 찾는것은 프론트 컨트롤러가 하는것이다.
이 프론트 컨트롤러가 있음으로써 보안 작업과 같은 모든 요청에 대한 전처리를 해줄 수 있게 된다.
한번 체로 거르는 듯한 느낌?
step.1
DispatcherServlet의 HTTP 요청 접수
서블릿 컨테이너(톰캣)는 위의 경로로 들어오는 모든 HTTP요청에 대해서 디스패쳐 서블릿에게 요청을 전달한다.
만약에 사용자가 http://www.tistory.com/action.do라고 입력할 경우에 디스패쳐 서블릿에게 전달된다는 뜻이다.
(이것은 web.xml에 정의 되어 있다.)
스프링에서는 컨트롤러를 웹의 요청을 다룬다는 의미에서 핸들러라고도 부른다
step.2
DispatcherServlet에서 컨트롤러로 HTTP 요청 위임
디스패쳐서블릿은 스프링 컨텍스트에 등록되는 빈이 아니라서 DI가 일어나지는 않는다.
하지만 DI가 적용되는 것처럼 서블릿 어플리케이션 컨텍스트의 빈을 가져와서 사용한다.
스프링에서는 어떤 객체의 형식이라도 컨트롤러로 사용할수 있게 끔 해준다. 이것이 가능한 이유는 바로 스프링이 오브젝트 어댑터 패턴을 사용해서, 특정 컨트롤러를 호출할때 중간에 어댑터를 끼워서 중간 매개체로 사용하기 때문이다.
이렇게 되면, 디스패쳐 서블릿은 특정 컨트롤러가 어떤 메소드를 갖고 있고 어떤 인터페이스를 구현한건지 전혀 알필요가 없이, 단순히 클라이언트의 요청을 HttpServletRequest에 담아서 중간 매개체인 어댑터에 전달만 해줄 뿐이다. 또한, 컨트롤러가 응답으로 내어준것을 다시 디스패쳐서블릿에게 전달해주는 역할도 한다.
step.3
컨트롤러의 모델 생성과 정보 등록
MVC패턴의 장점은 데이터를 담은 모델과 출력을 담당하는 뷰가 서로 분리되어 있다는 점이다.
컨트롤러의 역할 4가지
1.사용자의 요청 정보 해석
2.서비스 객체에 작업을 준다.
3.작업의 결과물을 모델에 담는다.
4.어떤 뷰를 사용할것인지 결정한다.
컨트롤러가 위의 4가지 작업을 마치고 나면 어댑터를 통해서 디스패쳐 서블릿에게 모델과 뷰에 대한 정보를 넘기고 디스패쳐 서블릿은 그 JSP파일로 이루어진 뷰를 찾아서 모델과 함께 실행을 시킨다. 그 뷰 에서는 모델에 담긴 데이터를 통해서 사용자에게 다양한 정보를 제공할 수 있게 된다.
모델은 속성과 속성값으로 이루어진 맵의 형태로 존재한다.
step.4
컨트롤러의 결과 리턴: 모델과 뷰
컨트롤러가 뷰의 이름을 리턴해주게 되면 어댑터를 거쳐서 디스패쳐서블릿에게 전달되는데, 디스패쳐 서블릿이 뷰리졸버 라는것을 통해서 뷰를 찾아서 뷰 오브젝트로 생성해준다. 이 뷰 객체는 실질적인 결과물을 생성한다(html문서등..)
그 결과물이 최종적으로 HttpServletResponse에 담기게 된다. 이 HttpServletResponse에 담긴 최종 결과물 html은 서블릿컨테이너인 톰캣에서 최종적으로 HttpResponse로 변해서 클라이언트(브라우저)에 전달되어 화면에 출력되게 된다.
컨트롤러가 하는것중에 가장 중요한 역할 2가지가, 바로 모델과 뷰를 디스패쳐 서블릿에게 리턴해주는것이다.
스프링에는 ModelAndView 라는 객체가 존재하는데 말그대로 모델과 뷰가 담긴 오브젝트이다. 이 2가지를 리턴함으로써 컨트롤러의 역할은 종료된다.
step.5 디스패쳐 서블릿이 컨트롤러로 부터 뷰의 이름과 모델을 넘겨 받고나서, 뷰 리졸버를 통해 실제 뷰를 찾아서 오브젝트로 만들고 그 뷰에 모델을 전달한다고 했었다. 만약에 뷰의 이름이 JSP확장자를 가지게 되면, jstlview라는것이 jsp파일을 참조해서 Html문서를 작성한 다음에 HttpServletResponse라는 객체 안에 담아서 클라이언트에게 리턴하게 된다. jstlview가 모델에 담긴 정보를 토대로 html을 생성할때 다음과 같은 방식으로 모델을 참조한다. <div>이름 : ${name} </div> <div>이름 : Spring </div> 만약에 모델에 name이라는 속성에 Spring이라는 속성값이 들어있었다고 해보자. 그럼 jstlview는 모델에서 name이라는 속성의 속성값을 참조해서 html문서를 생성할때 그 속성값을 끼워 넣는다. 모델에 담긴 정보를 어떤 뷰에서 참조하느냐에 따라서 결과물의 내용은 달라질 수 있다. JSON을 생성해주는 뷰를 사용하게 되면 똑같은 모델이지만, 결과물이 JSON의 형태로 리턴 될 것이고, JSP파일을 참조해서 html문서를 만들어주는 jstlview를 사용하게 되면 똑같은 모델을 참조하더라도, 결과물은 html이 될것이다. 어떤 뷰를 사용하느냐에 따라 결과물이 달라진다. step.7 디스패쳐 서블릿이 모델과 뷰의 이름을 리턴받았으면, 뷰 리졸버를 통해서 그 이름으로 된 파일을 찾아서 뷰 객체로 만들고 그 뷰 객체 안에서 모델에 담긴 값을 참조하여 최종적인 결과물을 만들어서 HttpServletResponse에 담고, 이것이 다시 서블릿 컨테이너인 톰캣에게 전달되서 HttpResponse에 담겨 최종적으로 브라우저에게 전송된다. 종이에 위의 흐름을 그려가면서 꼭 외우도록 하자. 이런 기본 토대가 있어야 나중에 오류가 생겼을 때 어디가 잘못 됬는지 금방 찾을 수 있게 된다. 이런 기반 지식 없이 그냥 코드를 짜게 되면 오히려 그 오류 고치는데 시간이 더걸리고 남는건 없게 될것이다!! 개인적으로 공부하면서 적은 내용이기 때문에 오류가 있을 수 있습니다.DispatcherServlet의 뷰 호출과 모델 참조
HTTP 응답 돌려주기
잘못된 내용을 발견하시면 댓글로 달아주시면 감사하겠습니다.
- Total
- Today
- Yesterday
- javascript
- props
- await
- reducer
- useRef
- mobx
- computed
- Action
- design system
- rendering scope
- react
- storybook
- promise
- server side rendering
- hydrate
- es6
- useEffect
- type alias
- Next.js
- atomic design
- react hooks
- Polyfill
- async
- webpack
- reflow
- return type
- state
- typescript
- Babel
- reactdom
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |