▸Spring MVC/기본 문법

스프링 MVC - 데이터 전달 객체들

코데방 2020. 3. 11.
728x90
- Develop OS : Windows10 Ent, 64bit
- WEB/WAS Server : Tomcat v9.0
- DBMS : MySQL 5.7.29 for Linux (Docker)
- Language : JAVA 1.8 (JDK 1.8)
- Framwork : Spring 3.1.1 Release
- Build Tool : Maven 3.6.3
- ORM : Mybatis 3.2.8

 

기본 서블릿에서는 사용자 요청을 받을 때 서블릿 컨테이너가 request, response 객체 두 개를 전달해주는 방식이 고정적이어서 컨트롤러를 작성할 때 크게 고민되는 부분이 없었던 것 같습니다.

 

하지만 스프링에서는 컨트롤러에 정해진 형식이 없고, 온갖 어노테이션과 파라미터들을 활용해 컨테이너로부터 파라미터 객체를 얻어올 수 있어 사용이 편리한만큼 머리가 복잡해집니다. 이번 글에서는 가장 기본적인 부분들에 대해 정리한 뒤, 점차 추가해나가도록 하겠습니다.

 

 


 

 

 

[ 클라이언트 → 처리기 메소드 (요청 객체) ]

 

클라이언트로부터 넘어온 요청 데이터는 DispatcherServlet과 스프링 컨테이너가 매핑된 컨트롤러와 요청 처리기 메소드를 호출하면서 넘겨줍니다. 이 때 어떤 객체 타입으로 메소드의 파라미터를 받을지가 가장 첫 번째 이슈입니다. 파라미터를 지정하면 요청 데이터를 핸들러 어댑터가 자동으로 해당 객체로 만든 뒤 전달해줍니다. 가장 기본적인 객체들만 살펴보겠습니다.

 

 

1. HttpServletRequest

서블릿 API이므로 기존 서블릿에서의 사용법과 동일합니다.

 

2. WebRequest

별도의 스프링 API로, 기존 서블릿 Request와 거의 동일합니다. 원래 다른 용도로 나온 API라 많이 사용되진 않는다고 합니다. 

 

3. MultipartRequest

파일 업로드에 대한 요청을 받을 수 있는 스프링 API 입니다. 

 

4. @RequestParam

HttpServletRequest 객체를 사용하는 방식과 동일한데, 어노테이션을 이용해 개별 파라미터를 바로 전달받는 방식입니다. 아래 예시와 같이 사용할 수 있습니다. 요청 객체의 파라미터를 찾아서 변수에 넣어주겠다는 의미입니다.  코드의 가시성을 생각하면 파라미터가 많은 경우 그리 보기 좋을 것 같진 않습니다. 어노테이션을 생략할 수 있지만 유지보수를 위해 명시해주는게 좋습니다.

 

package com.hsweb.springweb;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
@RequestMapping(value = "/board")
public class HomeController {

	// "/list" URI에 대한 요청 처리
	@RequestMapping(value = "/list")
	public String home2(@RequestParam("id") String id,
			@RequestParam("pw") String pw) {

		System.out.println(id);
		System.out.println(pw);

		return "/board/list";
	}
}

 

 

파라미터명과 저장할 변수명이 같은 경우 아래와 같이 ("id")부분을 생략할 수 있습니다.

	public String home2(@RequestParam String id,
			@RequestParam String pw) {

 

 

만약 해당 파라미터가 없다면 예외가 발생합니다. 예외를 피하고 싶다면 required 값을 false로 줍니다. 이 때 디폴트 값을 사용하고 싶다면 defaultValue를 지정할 수도 있습니다.

package com.hsweb.springweb;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
@RequestMapping(value = "/board")
public class HomeController {

	// "/list" URI에 대한 요청 처리
	@RequestMapping(value = "/list")
	public String home2
	(@RequestParam(value="id", required=false, defaultValue="coco") String id) {
		
		System.out.println(id);
		
		return "/board/list";
	}
}

 

 

 

5. @PathVariable

기존 GET 방식의 파라미터에서는 물음표 뒤에 데이터를 붙여서 전달받았습니다. 하지만 이 어노테이션을 쓰게 되면 URL과 동일한 구조로 GET 방식의 파라미터 데이터를 받을 수 있습니다. 지금 보시고 있는 티스토리의 페이지 주소도 URL 같이 생겼지만 아마 가장 뒤는 페이지 번호를 나타내는 파라미터 값인 것 같습니다. 

 

아래와 같이 @RequestMapping 어노테이션에는 받을 파라미터를 변수{ }로 지정해주고, 메소드의 파라미터에서는 @PathVariable 어노테이션을 이용해 받아주면 됩니다.

 

 

package com.hsweb.springweb;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping(value = "/board")
public class HomeController {

	// "/list" URI에 대한 요청 처리
	@RequestMapping(value = "/list/{page1}/{page2}")
	public String home2(@PathVariable int page1, @PathVariable int page2) {
		
		System.out.println(page1);
		System.out.println(page2);
		
		return "/board/list";
	}
}

 

 

6. @ModelAttribute (Command 객체 사용)

요청 객체의 파라미터가 많을 경우 매우 편리한 방법입니다. 파라미터명과 같은 필드명을 가진 클래스를 만들어 메소드의 파라미터로 넣어주면 자동으로 해당 클래스 객체에 요청 데이터를 담아줍니다. 이 때 커맨드 클래스는 getter, setter가 존재해야 합니다. 어노테이션은 생략할 수 있지만 붙여주는게 유지보수를 위해 좋습니다. 

 

package com.hsweb.springweb;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping(value = "/board")
public class HomeController {

	// "/list" URI에 대한 요청 처리
	@RequestMapping(value = "/list")
	public String home2(@ModelAttribute Test test) {
		
		System.out.println(test.getId());
		System.out.println(test.getPw());
		
		return "/board/list";
	}
}
package com.hsweb.springweb;

public class Test {

	private String id;
	private String pw;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getPw() {
		return pw;
	}
	public void setPw(String pw) {
		this.pw = pw;
	}
}

 

 


 

 

 

[ 스프링 → 처리기 메소드 ]

 

클라이언트에게서 받는 요청 데이터가 아닌, 스프링에서 받을 수 있는 객체입니다. 핸들러가 만들어서 전달해줍니다. 너무 많아서 기본적인 부분만 다뤘습니다.

 

 

1. HttpSession

request 객체에서 얻을 수 있지만 세션 객체만 필요한 경우라면 파라미터로 바로 받을 수 있습니다. 

 

2. Locale

java.util.Locale 클래스의 객체입니다. 지리적, 국가적, 문화적 지역을 다루는 클래스로 지역적 분류에 따라 여러 가지 처리를 자동으로 해줍니다. 대표적으로 시간 표현 등이 있습니다.

 

3. Model

스프링에서 제공해주는 데이터 공유 객체입니다. 스프링 이전에 사용하던 방식대로 request, session 등의 객체를 사용해도 되지만 Model 객체를 더 많이 사용하는 것 같습니다. 사용법은 거의 비슷하고, request와 같이 하나의 요청 처리에 국한된 생명주기를 가집니다. 이것저것 찾아보면서 느낀점인데 스프링은 기존 서블릿 기술들에 의존하는 것을 별로 좋아하지 않는 것 같습니다..

 

4. ModelMap

Model 객체는 인터페이스이기 때문에, 실제 기능을 구현한 클래스가 ModelMap 객체입니다. 핸들러에서 자동으로 생성해서 전달해주는 Model 객체도 사실 ModelMap 객체를 생성해 오버라이딩 시킨 객체입니다. Model 객체와 차이는 거의 없으니 취향대로 쓰면 됩니다. 

 

5. ModelAndView

스프링 2.0 이전에 사용하던 객체입니다. 물론 지금도 쓸 수 있습니다. 지금은 Model 객체에 오브젝트를 담기만 하고 처리기 메소드에서는 뷰 페이지 정보를 리턴하는 방식이 가능합니다. Model 객체는 내부적으로 알아서 뷰에서 사용할 수 있도록 공유해줍니다.

 

하지만 예전에는 ModelAndView 객체에 원하는 오브젝트와 뷰 페이지에 대한 정보를 모두 담아 리턴시켰다고 합니다. 최신 버전의 스프링에서는 사용할 일이 많지는 않을 것 같습니다. 이 객체를 사용할 때는 처리기 메소드에서 String 타입이 아닌 ModelAndView 타입의 객체를 리턴해야 합니다. 

 

 

 


 

 

 

[ 어플리케이션 → 클라이언트 (응답 객체) ]

 

- HttpServletResponse

 

최종적으로 클라이언트에게 전달되는 객체입니다. 클라이언트와의 통신은 여전히 서블릿 컨테이너가 맡고 있기 때문에 response 객체가 담당하게 됩니다. 쿠키 추가 등에 사용할 수 있습니다.

 

다만 기존에 자주 썼던 sendRedirect() 메소드는 사용할 일이 별로 없어졌습니다. 처리기 메소드에서 뷰 페이지 리턴 시 "redirect:"를 앞에 붙여주면 서블릿이 알아서 리다이렉트로 처리해줍니다. 그냥 뷰 페이지만 리턴할 경우 포워딩 방식으로 뷰로 제어 흐름을 넘겨 처리하게 됩니다.

728x90

댓글

💲 추천 글