computer_study

[Spring] 11. MVC1 : 요청 매핑, 커맨드 객체, 리다이렉트, 폼 태그, 모델 본문

스터디/스프링5 프로그래밍 입문

[Spring] 11. MVC1 : 요청 매핑, 커맨드 객체, 리다이렉트, 폼 태그, 모델

knowable 2022. 5. 9. 01:48

1. 프로젝트 준비

2. 요청 매핑 애노테이션을 이용한 경로 매핑

컨트롤러 클래스의 요청 매핑 애노테이션

  • 메서드가 처리할 요청 경로를 지정한다
  • @RequestMapping
  • @GetMapping
  • @PostMapping

관련 요청 경로를 한 개의 컨트롤러 클래스에서 처리하는 것이 좋다.

(ex. 약관 동의, 회원정보 입력, 가입 처리 결과 경로를 하나의 클래스에)

@Controller
@RequestMapping("/register")
public class RegistController{
    @RequestMapping("/step1")
    public String HandleStep1(){
        return "register/step1";
    }
    
    @RequestMapping("/step2")
    public String HandleStep2(){
        ...
    }
    ...
}

 

3. GET 과 POST 구분: @GetMapping, @PostMapping

스프링MVC는 별도 설정이 없다면 GET과 POST방식에 상관없이 @RequestMapping에 지정한 경로와 일치하는 요청을 처리한다.

 

요청 방식을 제한하기 위해선 @GetMapping, @PostMapping 방식을 사용한다.

같은 경로에 대해 GET과 POST방식을 각가 다른 메서드가 처리하도록 설정할 수도 있다.

@Controller
public class LoginController{
    @GetMapping("/member/login")
    public String form(){
        ...
    }
    
    @PostMapping("/member/login")
    public String login(){
        ...
    }
}

 

4. 요청 파라미터 접근

HttpServletRequest 이용

  • 컨트롤러 처리 메서드의 파라미터로 HttpServletRequest타입, HttpServletRequest의 getParameter()메서드를 이용해서 파라미터 값을 구할 수 있다
@PostMapping("register/step2")
public String HandleStep2(HttpServletRequest request){
    String agreeParam = request.getParameter("agree");
    ...
}

@RequestParam애노테이션 사용

  • 요청 파라미터 개수가 몇 개 안될 때 사용
@PostMapping("register/step2")
public String HandleStep2(
      @RequestParam(value="agree", defaultValue="false") Boolean agree){
    ...
}

 

5. 리다이렉트 처리

잘못된 전송방식으로 요청이 왔을 때 에러 화면 대신 알맞은 경로로 리다이렉트 하는 것이 좋은 경우 사용.

// GET방식 요청이 들어왔을 때 redirect시킨다면
@GetMapping("/register/step2")
public String handleStep2Get(){
    return "redirect:/register/step1";
}

// 위와같이 return시 웹 어플리케이션 경로가 기준이 된다.
// return "redirect:step1" 식으로 return 시 현재 경로가 기준이 된다.
// ex. http://localhost:8080/main/register/step2에서 호출했다면
//     http://localhost:8080/main/register/step1으로 redirect
// 완전한 url을 작성하면 해당 url로 redirect

 

6. 커맨드 객체를이용해서 요청 파라미터 사용하기

파라미터가 많아지는 경우를 대비해 스프링은 파라미터 값을 커맨드 객체에 담아주는 기능을 제공한다.

요청 파라미터의 값을 전달받을 수 있는 세터 메서드를 객체를 커맨드 객체로 사용하면 된다.

@PostMapping("/register/step3")
public String HandleStep3(RegisterRequest regReq){
    ....
}

RegisterRequest클래스에 포함된 메서드

  • setEmail()
  • setName()
  • setPassword()
  • setConfirmPassword()

 

7. 뷰 JSP 코드에서 커맨드 객체 사용하기

스프링 MVC는 커맨드 객체의 첫 글자를 소문자로 바꾼 클래스 이름과 동일한 속성 이름을 사용해서 커맨드 객체를 뷰에 전달한다.

<!-- 바로 위 예시처럼 커맨드 객체의 클래스 이름이 RegisterRequest인 경우 -->
<p>${registerRequest.name}</p>

 

8. @ModelAttribute 애노테이션으로 커맨드 객체 속성 이름 변경

커맨드 객체에 접근할 때 사용할 속성 이름을 변경하고 싶은 경우, 커맨드 객체로 사용할 파라미터에 @ModelAttribute 애노테이션 적용

@PostMapping("/register/step3")
public String handleStep3(@ModelAttribute("formData") RegisterRequest regReq){
    ...
}
// 위처럼 설정 시 뷰 코드에서 formData라는 이름으로 커맨드 객체에 접근이 가능하다.

 

9. 커맨드 객체와 스프링 폼 연동

폼을 다시 보여줄 때, 입력했던 값이 비어있으면 다시 적기 불편하기에 이전 폼을 채워서 보여주도록 할 수 있다.

<input type="text" name="email" id="email" value="${registerRequest.email}">
<input type="text" name="name" id="name" value="${registerRequest.name}">

스프링 MVC의 커스텀 태그를 사용하면 아래와 같이 출력할 수 있다.

<%@ taglib prefix-"form" url "http://www.springframework.org/tags/form"%>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <!-- modelAttribute: 커맨드 객체의 속성 이름, 커맨드 객체가 존재해야 사용가능   -->
    <form:form action="step3" modelzAttribute="registerRequest">
    <p>
        <label>이메일:<br>
        <form:input path="email" />
        </label>
    </p>
    <p>
        <label>이름:<br>
        <form:input path="name" />
        </label>
    </p>
    ...
    </form:form>
</body>
</html>

커맨드 객체가 존재해야 사용가능하기에 form태그 정상동작을 위해 다음처럼 추가할 수 있다

import org.springframework.ui.Model;

@PostMapping("register/step2")
public String HandleStep2(
      @RequestParam(value="agree", defaultValue="false") Boolean agree,
      Model model){
      
    model.addAttribute("registerRequest", new RegisterRequest());
    ...
}

 

10. 컨트롤러 구현 없는 경로 매핑

단순 연결을 위해 컨트롤러 클래스를 만드는 것은 성가시기에 해당 기능을 사용

WebMvcConfigurer 인터페이스의 addViewControllers()메서드를 사용할 수 있다.

@Override
public void addViewControllers(ViewControllerRegistry registry){
    registry.addViewController("/main").setViewName("main");
}

main경로에 대한 컨트롤러 구현 없이 main뷰에 해당하는 JSP를 실행할 수 있게된다.

 

11. 주요 에러 발생 상황

요청 매핑 애노테이션과 관련된 주요 익셉션

  • 404에러(Not Found)
    • WebMvcConfigurer를 이용한 설정이 없다면 발생
    • 확인해야 될 사항
      • 요청 경로가 올바른지
      • 컨트롤러에 설정한 경로가 올바른지
      • 컨트롤러 클래스를 빈으로 등록했는지
      • 컨트롤러 클래스에 @Controller 애노테이션을 적용했는지
      • 뷰 이름에 해당하는 JSP파일이 존재하는지 (존재하지 않는 파일 경로가 출력된다)
  • 405 에러(Method Not Allowed)
    • 지원하지 않는 전송 방식을 사용한 경우 (ex. POST만 처리하는 요청에 GET요청한 경우)

 

@RequestParam이나 커맨드 객체와 관련된 주요 익셉션

  • 400에러(Bad Request)
    • 필수 파라미터가 존재하지 않는 경우 (Message에 무엇이 필요하다고 알려준다)
    • 요청 파라미터 값을 @RequestParma이 적용된 파라미터의 타입으로 변환할 수 없는 경우
    • 요청 파라미터 값을 커맨드 객체에 복사하는 과정에서 타입 변환이 불가능 할 경우

 

12. 커맨드 객체: 중첩,콜렉션 프로퍼티

스프링 MVC는 커맨드 객체가 리스트 타입의 프로퍼티를 가졌거나 중첩 프로퍼티를 가진 경우에도 요청 파라미터의 값을 알맞게 커맨드 객체에 설정해준다.

 

규칙

  • HTTP 요청 파라미터 이름이 "프로퍼티이름[인덱스]" 형식이면 List타입 프로퍼티의 값 목록으로 처리
  • HTTP 요청 파라미터 이름이 "프로퍼티이름.프로퍼티이름" 형식이면 중첩 프로퍼티의 값을 처리

 

13. Model을 통해 컨트롤러에서 뷰에 데이터 전달하기

뷰가 응답화면을 구성할 때 필요한 데이터를 전달할 때 Model을 사용

 

ModelAndView를 통한 뷰 선택과 모델 전달

  • ModelAndView를 사용하면 1. Model을 이용해서 뷰에 전달할 데이터 설정 2. 결과를 보여줄 뷰 이름 리턴 을 한번에 할 수 있다.
import org.springframework.web.servlet.ModelAndView;

@GetMapping
public ModelAndView form(){
    List<Question> questions = createQuestions();
    
    ModelAndView mav = new ModelAndView();
    mav.addObject("questions", questions); // 뷰에 전달할 모델 데이터 추가
    mav.setViewName("survey/surveyForm"); // 뷰 이름은 해당 메서드를 이용
    
    return mav
}

 

GET방식과 POST 방식에 동일 이름 커맨드 객체 사용하기

ex) "/login"요청 경로일 때 GET방식이면 로그인 폼을 POST방식이면 로그인을 처리하도록 컨트롤러를 작성해야될 때

@ModelAttribute 애노테이션을 붙인 커맨드 객체를 파라미터로 추가하면 된다.

@GetMapping
public String form(@ModelAttribute("login") LoginCommand loginCommand){
    return "login/loginForm";
}

@PostMapping
public String form(@ModelAttribute("login") LoginCommand loginCommand){
    ...
}

 

 

14. 주요 폼 태그 설명

필요할 때 찾아보는 식으로

 

<form>태그를 위한 커스텀 태그: <form:form>

<form>태그를 생성할 때 사용

 

<input> 관련 커스텀 태그

  • <form:input>
    • text 타입의 <input> 태그
  • <form:password>
    • password 타입의 <input> 태그
  • <form:hidden>
    • hidden 타입의 <input> 태그

 

<select> 관련 커스텀 태그

  • <form:select>
    • <select>태그 생성. <option> 태그를 생성할 때 필요한 콜렉션을 전달받을 수도 있다.
  • <form:options>
    • 지정한 콜렉션 객체를 이용하여 <option>태그를 생성한다.
  • <form:option>
    • <option>태그 한 개를 생성한다.

 

체크박스 관련 커스텀 태그

  • <form:checkboxes>
    • 커맨드 객체의 특정 프로퍼티와 관련된 checkbox 타입의 <Input> 태그 목록을 생성한다.
  • <form:checkbox>
    • 커맨드 객체의 특정 프로퍼티와 관련된 한 개의 checkbox 타입 <Input> 태그를 생성한다.

 

라디오버튼 관련 커스텀 태그

  • <form:radiobuttions>
    • 커맨드 객체의 특정 프로퍼티와 관련된 radio 타입의 <input> 태그 목록을 생성한다.
  • <form:radiobutton>
    • 커맨드 객체의 특정 프로퍼티와 관련된 한 개의 radio 타입 <input> 태그를 생성한다.

 

<textarea> 태그를 위한 커스텀 태그

  • <form:textarea>
    • 게시글 내용과 같이 여러 줄을 입력받아야 하는 경우 사용

 

CSS및 HTML 태그와 관련된 공통 속성

  • CSS관련 속성
    • cssClass
      • HTML의 class 속성 값
    • cssErrorClass
      • 폼 검증 에러가 발생했을 때 사용할 HTML의 clas 속성 값
    • cssStyle
      • HTML의 style속성 값
  • HTML 태그 속성
    • id, title, dir
    • disabled, tabindex
    • onfocus, onblur, onchange
    • onclick, ondblclick
    • onkeydown, onkeypress, onkeyup
    • onmousedown, onmojusemove, onmouseup
    • onmouseout, onmouseover
Comments