본문 바로가기
Spring 프레임워크/이론

Spring MVC 패턴의 구조 파악 2 (Controller 파트)

by Hwanii_ 2023. 8. 3.
728x90

1.

 

 

Spring 에서는,

 

기존의 Action 인터페이스를 의미하는 인터페이스를 Controller 인터페이스로 이름을 사용.

 

또한,

 

기존의 excute() 메서드를 의미하는 메서드는 handleRequest() 메서드로 이름을 사용.

 

기본적으로 Spring 에서는, 어디로 갈지에 대한 경로값을 String 타입으로 해서 반환 한다.

 

FrontController 때 처럼, ActionForward 타입의 actionforward 객체를 반환 하는것 보다,

상대적으로 String 타입의 데이터를 반환 하는게 가볍기 때문이다.

 

암튼, String 타입으로 경로를 반환 하게 되면,

이 페이지의 확장자가 뭔지, 어떻게 갈지, 어디로 갈지 "주체"를 알 수 있다.

 

https://hwanii96.tistory.com/311

 

Spring MVC 패턴의 구조 파악 (Controller 파트)

스프링 에서는 기존 서블릿 파일 이름이였던, FrontController를 DispatcherServlet 로 사용 한다. 1. 기존, controller.jsp의 코드를 FrontController.java 서블릿으로 옮겨 왔다. >> 유지 보수 불리 2. 그래서, XxxAction

hwanii96.tistory.com

 

위의 글에서는 XxxController 에서, handleRequest가 작업을 수행 하고 나서,

return 값으로 경로를 반환 한다는 개념만 다루고,

 

실제로 어떤식으로 반환 하고,

반환값을 받아서 어떤식으로 진행 되는지를,

다루지 않았기에, 아래서 정리 하도록 하겠다.

 

2.

ViewResolver

>>

Controller 류의 객체가 == XxxController

.handleRequest() 의 수행 결과로,

String을 반환 했을 때,

'어떻게 갈지' 와 '어디로 갈지' 를 판단해서 처리 하는 "주체" 이다.

 

[ 참고 ]

Spring 에서는 XxxResolver 들을 많이 구현해 두었다.

>> 특정 역할을 자동으로 수행 해주는 기능을 가진 아이.

 

 

위의 이미지는 DispatcherServlet 이다.

 

 

우선, 위의 코드를 확인 하면, doAction() 메서드 내부에,

 

사용자로부터 요청값 == command를 받으면,

HM이 getController() 메서드를 수행해서,

요청값 == command == key 값에 대해,

value == 값 == XxxController 타입의 객체를 반환 한다.

 

그 객체를 Controller 인터페이스 타입의 ctrl 참조변수에 저장하고,

 

다시 XxxController 타입을 가리키는 변수 ctrl를 주체로 해서,

handleRequest() 메서드를 수행 한다.

 

아래의 코드를 확인해보자.

 

 

 

사용자가 main.do 요청을 보냈기에,

main.do 요청에 대한 MainController 객체를 반환 했고,

MainController 객체가 handleRequest() 메서드를 수행 하는데,

main.jsp 에서 필요한 데이터가,

게시글 전체 목록 이기 때문에,

DB에서, 게시글 전체 목록을 selectAll() 해서,

bdatas 라는 파라미터명으로 set 하는 모습이다.

 

그리고, return 값으로 String 타입의 "main" 만 반환 하는 모습을 볼 수 있다.

 

이게, 이제 DispatcherServlet 에서 받아서,

 

ViewResolver 에 의해서, main.jsp 로 변하게 되는데,

 

이것을 아래에서 확인 해보자.

 

 

ctrl.handleRequest(request, response) 를 해서,

 

반환값으로 "main" 을 return 했는데,

 

그 값을 String 타입의 viewName 변수에 저장 하고,

 

만약  "main" 이라는 문자열이 .do 를 포함 하고 있지 않으면 !

 

viewResolver 을 주체로 해서 getView(viewName) 이라는 메서드를 수행 하게 된다.

 

만약 viewName 문자열이 .do를 포함 하고 있으면 !

(viewName이 .do를 가지고 있다는 말은, View가 아니라, Controller 로 간다는 의미 이다)

 

if문에 걸리지 않기 때문에,

94번째 라인의 sendRedirect 인자로 넣어 마무리 하게 되는 구조 이다.

 

이때, 88번째 라인과 89번째 라인의 코드가 정확히 무엇인지 확인해보자.

 

우선, viewResolver 참조변수가 DispatcherServlet 내부에서 사용 되었기 때문에,

 

DispatcherServlet와 viewResolver 는 서로 의존 관계 이다.

 

그래서, 의존 주입을 해야 한다.

 

handlerMapping과 동일 하게,

 

viewResolver 도, 여러 의존 주입 방법들을 사용 하지 않고,

 

DispatcherServlet 내부에 존재하는 init() 메서드를 사용 해서 의존 주입을 한다.

 

또한, viewResolver 는 의존 주입을 할 때, setter로 주입 하기 때문에,

아래와 같이 setter을 작성 해서 의존 주입을 진행 한다.

 

 

setter에 set된 값들은, 아래에서 정확히 무엇인지 확인해보자.

 

 

위는, ViewResolver 클래스 내부에 작성된 코드 이다.

 

위에서 말했듯이,

 

ViewResolver 는 자신의 멤버변수를 setter를 통해서 받는다.

 

ViewResolver는 setter의 인자로,

 

"경로" 를 받으면, '어떻게 갈지' 와 '어디로 갈지' 를 앞 / 뒤 로 붙혀서 반환 한다.

 

viewName 문자열에 .do가 contains() 되어 있지 않으면 ? 해당 getView 메서드를 호출 !

 

 

 

.do를 포함 하고 있지 않으면,

viewResolver 객체를 주체로 해서 getView() 메서드를 호출 한다.

 

만약 viewName이 "main" 이였다면,

 

 

./ + viewName + .jsp

 

즉,

 

./main.jsp 가 된다.

 

만약, viewName 문자열에 .do가 포함 되어 있었으면 ?

 

 

handleRequest() 메서드가 "main.do" 를 반환 한다면 ?

 

 

viewName은 "main.do" 이고,

 

String path 에 viewName 이 저장되고,

 

if문에 걸리지 않아서 !

 

sendRedirect("main.do"); 가 되어 마무리 된다.

 

참고로, 이렇게 String 타입으로 경로만 보내도 되는 이유는,

 

보내야할 데이터를,

request를 주체로 해서, setAttribute 를 하거나,

session을 주체로 해서, set 하기 때문에,

경로만 보내주게 된다.

반응형