스프링 MVC란

 

 

스프링 MVC는 애플리케이션을 Model-View-Controller 형식으로 관심사를 분리하여 각 계층을 모듈화 한 것을 말합니다.

스프링 mvc는 이런 mvc를 프레임워크 형태로 제공하고 있습니다.

 

1 View
  • 역할: 최종 사용자에게 보여지는 화면을 구성합니다.
  • 내용: 모델로부터 전달받은 데이터를 바탕으로 사용자에게 화면을 렌더링합니다. HTML, JSP, Thymeleaf와 같은 템플릿 엔진을 사용해 뷰를 작성할 수 있습니다.
  • 예시: 웹 페이지의 HTML 코드, 데이터 출력 등.
2 Controller   역할: 사용자의 요청을 처리하고 적절한 모델 데이터를 생성한 후, 이를 뷰에 전달하는 역할을 합니다.

요청을 받고, 그에 대한 비즈니스 로직을 실행한 후, 결과 데이터를 담아 뷰로 넘겨줍니다. 주로 @Controller 또는 @RestController로 정의되며, URL 매핑을 통해 특정 요청을 처리합니다.


● 예시: 사용자가 특정 페이지를 요청하면 그에 맞는 데이터를 불러와 뷰에 전달하는 작업.
3 Model ● 애플리케이션의 데이터와 비즈니스 로직을 담당, 
● 데이터베이스나 다른 외부 리소스에서 가져온 데이터를 표현하며, 사용자의 요청에 따라 데이터를 처리하거나 조작합니다.
● 데이터 객체(POJO), DAO (Data Access Object) 클래스 등이 속할 수 있습니다.

 

 

스프링 MVC 동작 원리

  1. 클라이언트 요청
    • 사용자가 웹 브라우저에서 URL을 입력하거나 버튼을 클릭하면, HTTP 요청이 발생합니다.
  2. DispatcherServlet (프론트 컨트롤러)
    • DispatcherServlet은 모든 요청을 가장 먼저 받는 프론트 컨트롤러 역할을 합니다.
    • 클라이언트의 요청을 적절한 컨트롤러로 전달하고, 컨트롤러의 처리 결과를 다시 받아 클라이언트에게 반환하는 흐름을 제어합니다.
  3. 핸들러 매핑 (Handler Mapping)
    • DispatcherServlet은 요청 URL을 분석하여, 해당 요청을 처리할 컨트롤러를 찾습니다.
    • HandlerMapping이 이 작업을 담당하며, URL과 컨트롤러 메서드 사이의 매핑을 관리합니다.
  4. 컨트롤러 (Controller)
    • 매핑된 컨트롤러가 요청을 받아 비즈니스 로직을 처리합니다.
    • 필요한 데이터를 가져오거나 조작한 후, 모델에 데이터를 담고, 이름을 반환합니다.
  5. 모델 (Model)
    • 모델은 컨트롤러가 처리한 데이터(예: 데이터베이스에서 조회한 값)를 저장하는 역할을 합니다.
    • 이 데이터는 로 전달되어 화면에 출력될 수 있도록 합니다.
  6. 뷰 리졸버 (View Resolver)
    • 컨트롤러가 반환한 뷰 이름을 기반으로, 어떤 화면을 렌더링할지 결정합니다.
    • ViewResolver는 뷰 이름을 실제 뷰(JSP, HTML, Thymeleaf 등)로 변환하는 역할을 합니다.
  7. 뷰 (View)
    • ViewResolver가 선택한 가 모델 데이터를 받아 HTML과 같은 사용자 인터페이스로 렌더링합니다.
    • 이 뷰는 최종적으로 사용자에게 응답으로 전송됩니다.
  8. 클라이언트에게 응답
    • 최종적으로 DispatcherServlet은 생성된 를 클라이언트에게 응답으로 반환합니다

 

주요 구성 요소

  1. DispatcherServlet: 프론트 컨트롤러로 모든 요청을 중앙에서 처리.
  2. Handler Mapping: URL 요청을 적절한 컨트롤러와 매핑하는 역할.
  3. Controller: 요청을 받아 비즈니스 로직을 처리하고 결과를 반환.
  4. Model: 컨트롤러에서 처리된 데이터가 저장되는 공간.
  5. ViewResolver: 뷰 이름을 물리적인 뷰 파일로 변환하는 역할.
  6. View: 클라이언트에게 데이터를 보여주기 위한 UI 부분.

 

스프링 MVC 라이브러리 프로젝트에서 web.xml에 다음과 같은 설정을 해준다.

<servlet>
	<servlet-name>dispather</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispathcerSerlvet</servlet-class>
</servlet>


//사용자가 요청을 할 수 있게 매핑 설정
//모든 요청이 여기로 들어올 것 
<servlet-mapping>
	<url-pattern>/</url-pattern>
</servlet-mapping>

 

여기서 url-mapping하는 부분을 따로 dispather-servlet.xml 파일을 생성하여 여기서 따로 관리를 하겠습니다.

src/main/webapp/WEB-INF 경로에 해당 파일을 생성해줍니다.

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
      https://www.springframework.org/shcema/beans/spring-beans.xsd">
      
      //id: controller의 요청 URL,   class : controller의 class파일 경로
      <bean id="/index" class="패키지명.IndexController" />
      
</beans>

 

IndexController도 생성해줍니다.

public class IndexController implements Controll {  //Controll 인터페이스 구현
	
    
    //요청에 대한 핸들러 메서드를 구현
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
    
    	//dispatcher에게 담아서 줄 ModelAndView 객체 생성
    	ModelAndView mv = new ModelAndView();
        mv.addObject("data", "Hello"); // "data"라는 이름으로 "Hello"라는 문자열데이터 값을 보냄
        mv.setViewName("index.jsp"); //view페이지의 이름
        return mv;
    }
}

 

사용자의 서버로의 요청은 Controller가 받게 해야한다. 바로 view페이지로의 요청은 차단되어야 한다.

원래는 서비스로직과 view페이지가 하나로 합쳐진 것을 기능과 관심사별로 계층을 분리했지만 일련의 하나의 동작으로 구성되어야 한다.

 

index.jsp를 직접 요청할 수 없게 보통은 WEB-INF파일에 jsp파일들을 위치시킨다.

WEB-INF아래에 있는 파일들은 사용자가 직접 요청 할 수 없기때문에이다. 서버에서는 요청해서 반환시켜 줄 수 있다.

 

그래서 Controller에서 view를 반환하는 부분을 

mv.setViewName("/WEB-INF/index.jsp"); //view페이지의 이름  , 맨앞에 / 를 추가했으므로 루트경로의 절대경로를 통해 찾는다.

이렇게 수정한다.  이렇게 해서 view는 컨트롤러를 통해서만 요청 할 수 있게 된다.

 

 

ViewResolver 사용하기

mv.setViewName("/WEB-INF/index.jsp");  이런식으로 모든 경로와 파일확장자까지 쓰는건 귀찮고 내용이 길어지기 때문에 생략을 해야합니다.

 

/WEB-INF 와 .jsp 반복되는 형태이기 때문에 이것들은 따로 설정을 하고 재사용성을 높히게 할 수 있습니다.

 

dispatcher-servlet.xml에 다음 내용을 추가합니다.

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/WEB-INF/view/"></property>
    <property name="suffix" value=".jsp"></property>
</bean>

 

이 내용을 추가하면 

이제 view를 반환할때 mv.setViewName("index"); 로 변환해서 사용할 수 있게 되었습니다.

 

 

데이터 서비스 클래스 준비하기 (Service)

이제는 어떠한 service클래스를 만들어서 (service클래스 소스는 생략) 이것또한 bean으로 관리 할 수 있게 되어야 합니다.

그래야 컨트롤러 계층에서 전역적으로 사용을 할 수 있고 관리가 쉬어집니다. service클래스를 만들었다는 가정하에

dispatcher-servlet.xml 파일에 다음과 같은 내용을 추가합니다.

 

<bean id="indexService" class="패키지명.IndexService">  이 내용 또한 빈즈 태그안에 포함하고 그 후 IndexController에 주입을 해야 하기 때문에 

<bean id="/index" class="패키지명.IndexController" /> 또한 변경합니다 

 

<bean id="/index" class="패키지명.IndexController" />

       <property name=" indexService " ref="indexService" />  //해당 서비스의 빈 id를 ref에 넣어주면된다.

</bean>

 

그 후 IndexController는 아래와 같이 수정될것입니다. (서비스 계층을 컨트롤러에 주입)

public class IndexController implements Controll {  //Controll 인터페이스 구현
	
    private IndexService indexservice;
    
    public void setIndexService(IndexService indexService){ //indexService는 설정에서 서비스클래스의 빈의 아이디
    	this.indexservice = indexService;
    }
    
    //요청에 대한 핸들러 메서드를 구현
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
    
    	//dispatcher에게 담아서 줄 ModelAndView 객체 생성
    	ModelAndView mv = new ModelAndView();
        mv.addObject("data", "Hello"); // "data"라는 이름으로 "Hello"라는 문자열데이터 값을 보냄
        mv.setViewName("index.jsp"); //view페이지의 이름
        return mv;
    }
}

 

이렇게 이제 컨트롤러에서 해당 서비스클래스를 이용가능하고 의존성이 주입되었습니다.

 

서비스 객체 분리하기

이렇게 컨트롤러와 서비스 객체 사이에 추상화된 인터페이스를 사이에 두고 주입이 된다면 추후에 구현체(Service객체)

의 교체가 원할해진다.  (Controller에 대한 수정이 필요없다. --> 결합력이 약해진다.)

 

'Spring' 카테고리의 다른 글

[Spring] IOC , DI  (0) 2025.04.02
Spring Security  (0) 2025.02.24
Component  (0) 2024.10.15
스프링 어노테이션을 활용한 DI  (3) 2024.10.12
Spring framework 설정  (0) 2024.10.09

+ Recent posts