java, spring

[Spring framework] 스프링 MVC 설정과 Controller, Model 실습 2

isaac.kim 2021. 5. 20. 23:59
728x90
반응형

[Spring framework] 스프링 MVC 설정과 Controller, Model 실습 2

지난 글의 내용이 너무 길어져서 실습 내용을 분할했습니다. 지난 글에 이어서 해당 글을 작성하기 때문에 지난 글을 먼저 읽으시는 것을 추천합니다.

 

지난 글

https://lifere.tistory.com/120

 

[Spring framework] 스프링 MVC 설정과 Controller 실습 1

[Spring framework] 스프링 MVC 설정과 Controller 실습 1 스프링 MVC는 웹 관련 스프링 라이브러리로 최근 웹 개발에서 필수적으로 사용되는 구조입니다. 국내에선 전자정부 표준 프레임워크를 스프링 프

lifere.tistory.com

 

1. Controller 실습 @initBinder

파라미터의 수집을 다른 용어로는 'binding(바인딩)'이라고 합니다. 변환이 가능한 데이터는 자동으로 변환되지만 경우에 따라서는 파라미터를 변환해서 처리해야 하는 경우도 존재합니다. 예를 들어, 화면에서 '2018-01-01'과 같이 문자열로 전달된 데이터를 java.util.Date 타입으로 변환하는 작업이 그러합니다. 스프링 Controller에선 파라미터를 바인딩할 때 자동으로 호출되는 @InitBinder를 이용해서 이러한 변환을 처리할 수 있습니다.

 

com.project.domain 패키지에 TodoDTO 클래스를 작성

사용자가 '2021-01-01'과 같이 들어오는 데이터를 변환하고자 할 때 문제가 발생하게 되는데, 이러한 문제의 간단한 해결책은 @InitBinder를 이용하는 것입니다.

 

지난번 작성한 SmapleController 클래스에 다음 메서드를 추가

      -- 생략 --

      @InitBinder
      public void initBinder(WebDataBinder binder) {
          SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
          binder.registerCustomEditor(java.util.Date.class, new CustomDateEditor(dateFormat, false));
      }
    
      -- 생략 --
    
      @GetMapping("/ex03")
      public String ex03(TodoDTO todo) {
          log.info("todo: " + todo );
          return "ex03";
	}

 

요청 URL

http://localhost:8080/sample/ex03?title=test&dueDate=2021-01-01

 

실행결과

initBinder 메서드의 호출을 확인하기 위해 log를 찍었고, TodoDTO에 값이 들어오기 전에 initBinder를 먼저 호출하고, 타입에 맞춰서 저장된 것을 확인할 수 있습니다.

 

반면 @InitBinder 처리가 되지 않으면 브라우저에선 400 에러가 발생하는 것을 볼 수 있습니다(400 에러는 요청 구문(syntax)이 잘못되었다는 의미입니다.). 날짜가 정상적으로 처리되어도 아직 jsp 페이지는 없으므로 404 에러가 나타나게 됩니다.  

 

2. @DateTimeFormat

@initBinder를 이용해서 날짜를 변환할 수도 있지만, 파라미터로 사용되는 인스턴스 변수에 @DateTimeFormat을 적용해도 변환이 가능합니다. @DateTimeFormat을 사용하는 경우에는 @initBinder는 필요하지 않습니다.

 

TodoDTO 클래스에서 dueDate 변수에 @DateTimeFormat을 설정합니다. 그리고 SampleController 클래스에서 사용했던 @initBinder 어노테이션과 메서드는 주석 처리합니다.

package com.project.domain;

import java.util.Date;

import org.springframework.format.annotation.DateTimeFormat;

import lombok.Data;

@Data
public class TodoDTO {
	private String title;
	
	@DateTimeFormat(pattern= "yyyy/MM/dd")
	private Date dueDate;
}

 

Request URL

http://localhost:8080/sample/ex03?title=aaa&dueDate=2021/05/20

 

Result

해당 요청에 대해 문자열로 'yyyy/MM/dd'의 형식이 맞다면 자동으로 날짜 타입으로 변환됩니다.

 

 

3. Model이라는 데이터 전달자

Controller의 메서드를 작성할 때는 특별하게 Model이라는 타입을 파라미터로 지정할 수 있습니다. Model 객체는 JSP에 컨트롤러에서 생성된 데이터를 담아서 전달하는 역할을 하는 존재입니다. 이를 이용해서 JSP와 같은 뷰(View)로 전달해야 하는 데이터를 담아서 보낼 수 있습니다. 메서드의 파라미터에 Model 타입이 지정된 경우에는 스프링은 특별하게 Model 타입의 객체를 만들어서 메서드에 주입하게 됩니다.

 

Model은 모델 2 방식에서 사용하는 request.setAttribute( )와 유사한 역할을 합니다. Servlet을 이용해 본 적이 있다면 다음과 같은 코드에 익숙할 것입니다.

// Servlet에서 모델 2 방식으로 데이터를 전달하는 방식
	request.setAttribute("serverTime", new Java.util.Date());
    
	RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/jsp/home.jsp");
    
	dispatcher.forward(request, response);

위의 코드를 스프링에서는 Model을 이용해서 다음과 같이 처리하게 됩니다.

// 스프링 MVC에서 Model을 이용한 데이터 전달
public String home(Model model) {
	model.addAttribute("serverTime", new java.util.Date());
    return "home";
}

메서드의 파라미터를 Model 타입으로 선언하게 되면 자동으로 스프링 MVC에서 Model 타입의 객체를 만들어 주기 때문에 개발자의 입장에서는 필요한 데이터를 담아 주는 작업만으로 모든 작업이 완료됩니다. Model을 사용해야 하는 경우는 주로 Controller에 전달된 데이터를 이용해서 추가적인 데이터를 가져와야 하는 상황입니다. 

 

예를 들어, 다음과 같은 경우들을 생각해 볼 수 있습니다.

- 리스트 페이지 번호를 파라미터로 전달받고, 실제 데이터를 View로 전달해야 하는 경우

- 파라미터들에 대한 처리 후 결과를 전달해야 하는 경우

 

 

4. @ModelAttribute 어노테이션

웹페이지의 구조는 Request에 전달된 데이터를 가지고 필요하다면 추가적인 데이터를 생성해서 화면으로 전달하는 방식으로 동작합니다. Model의 경우는 파라미터로 전달된 데이터는 존재하지 않지만 화면에서 필요한 데이터를 전달하기 위해서 사용합니다. 예를 들어 페이지 번호는 파라미터로 전달되지만, 결과 데이터를 전달하려면 Model에 담아서 전달합니다.

 

스프링 MVC의 Controller는 기본적으로 Java Beans 규칙에 맞는 객체는 다시 화면으로 객체를 전달합니다. 좁은 의미에서 Java Beans의 규칙은 단순히 생성자가 없거나 빈 생성자를 가져야 하며, getter/setter를 가진 클래스의 객체들을 의미합니다. 앞의 예제에서 파라미터로 사용된 SampleDTO의 경우는 Java Bean의 규칙에 맞기 때문에 자동으로 다시 화면까지 전달됩니다. 전달될 때에는 클래스명의 앞글자는 소문자로 처리됩니다.

 

반면에 기본 자료형의 경우는 파라미터로 선언하더라도 기본적으로 화면까지 전달되지는 않습니다.

 

SampleController에 추가

	@GetMapping("/ex04")
	public String ex04(SampleDTO dto, int page) {
		log.info("dto : " + dto);
		log.info("page : " + page);
		
		return "/sample/ex04";
	}

ex04( )는 SampleDTO 타입과 int 타입의 데이터를 파라미터로 사용합니다. 결과를 확인하기 위해 '/WEB-INF/views' 폴더 아래 sample 폴더를 생성하고 리턴값에서 사용한 'ex04'에 해당하는 ex04.jsp를 작성합니다.

ex04.jsp 작성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<h2>SampleDTO ${sampleDTO }</h2>
<h2>Page ${page }</h2>

</body>
</html>

서버를 실행하고 브라우저를 통해 'http://localhost:8080/sample/ex04?name=aaa&age=11&page=9' 와 같이 호출하면 화면에 SampleDTO만이 전달된 것을 확인할 수 있습니다. int 타입으로 선언된 page는 전달되지 않습니다.

 

URL 요청 결과

 

@ModelAttribute는 강제로 전달받은 파라미터를 Model에 담아서 전달하도록 할 때 필요한 어노테이션입니다. @ModelAttribute가 걸린 파라미터는 타입에 관계없이 무조건 Model에 담아서 전달되므로, 파라미터로 전달된 데이터를 다시 화면에서 사용해야 할 경우에 유용하게 사용됩니다.

 

기존의 코드에서 int 타입의 데이터가 화면까지 전달되지 않았으므로 @ModelAttribute를 추가하면 다음과 같은 형태가 됩니다.

	@GetMapping("/ex04")
	public String ex04(SampleDTO dto, @ModelAttribute("page") int page) {
		log.info("dto : " + dto);
		log.info("page : " + page);
		
		return "/sample/ex04";
	}

@ModelAttribute가 붙은 파라미터는 화면까지 전달되므로 브라우저를 통해 호출하면, ex04.jsp 에 작성한 ${page} 변수에 값이 넘어와 출력되는 것을 확인할 수 있습니다(기본 자료형에 @ModelAttribute를 적용할 경우에는 반드시 @ModelAttribute("page")와 같이 값(value)을 지정하도록 합니다.).

 

5. RedirectAttributes

Model 타입과 더불어 스프링 MVC가 자동으로 전달해 주는 타입 중에는 RedirectAttributes 타입이 있습니다. RedirectAttributes는 일회성으로 데이터를 전달하는 용도로 사용됩니다. RedirectAttributes는 기존에 Servlet에서는 response.sendRedirect( )를 사용할 때와 동일한 용도로 사용됩니다.

 

Servlet에서 redirect 방식

	response.sendRedirect("/home?name=aaa&age=10");

 

스프링 MVC를 이용하는 경우에는 다음과 같이 변경됩니다.

 

스프링 MVC를 이용하는 redirect 처리

rttr.addFlashAttribute("name", "AAA");
rttr.addFlashAttribute("age", 10);

return "redirect:/";

 

RedirectAttributes는 Model과 같이 파라미터로 선언해서 사용하고, addFlashAttribute(이름, 값) 메서드를 이용해서 화면에 한 번만 사용하고 다음에는 사용되지 않는 데이터를 전달하기 위해서 사용합니다.

 

 

SampleController에 추가

ex04.jsp

요청 URL : http://localhost:8080/sample/ex04r

 

결과


오늘은 스프링 MVC에서 Controller, Model에 대해 알아보았는데요. 컨트롤러로 들어오는 데이터의 자동 타입 변환, 요청받은 데이터를 다음 화면까지 전달하는 Model 그리고 @ModelAttribute 어노테이션, 일회성 데이터를 전달하는 목적의 RedirectAttributes 등에 대해 실습했습니다.

 

다음은 Controller의 리턴 타입에 대해 알아보도록 하겠습니다.

 

728x90
반응형