🌈컨트롤러에서 폼 데이터를 받는 방법
📑 목차
1️⃣ HttpServletRequest & Model
⭐ 배열 출력할때 컴마 마지막에 항목엔 안찍고 넘기는 법
- 화면을 띄울 때 : @GetMapping("/form") ==> http://localhost:9292/form
- 폼 제출 처리용 :@PostMapping("/input1")
✅ HTML파일에 최상단에 작성 (result와 form 최상단에 기입)
// Thymeleaf 문법(th:text, th:each, th:action 등)을 사용
<html lang="en" xmlns:th="http://www.thymeleaf.org">
Controller 예제 (전체코드)
package com.example.Ex02;
import com.example.Ex02.dto.MusicBean;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class HomeController {
// http://localhost:9292/form
//@RequestMapping(value="/form",method=RequestMethod.GET)
@GetMapping(value="/form")
public String form(){
return "form";
}
// 1. HttpServletRequest & Model 사용
//@RequestMapping(value="/input", method=RequestMethod.POST)
@PostMapping(value="/input1")
public String input1(HttpServletRequest request, Model model){
String title = request.getParameter("title");
String singer = request.getParameter("singer");
String price = request.getParameter("price");
System.out.println(title+"/"+singer+"/"+price);
request.setAttribute("rtitle",title);
model.addAttribute("mtitle",title);
request.setAttribute("rsinger",singer);
model.addAttribute("msinger",singer);
request.setAttribute("rprice",price);
model.addAttribute("mprice",price);
return "music/result1"; // view
}
// 2. @RequestParam + VO/DTO 사용
@PostMapping("/input2")
public String input2(@RequestParam("title") String title,
@RequestParam("singer") String singer,
@RequestParam("price") int price,Model model) {
//String title = request.getParameter("title");
System.out.println(title+"/"+singer+"/"+price);
MusicBean music = new MusicBean();
music.setTitle(title);
music.setSinger(singer);
music.setPrice(price);
model.addAttribute("music",music);
return "music/result2";
}
// 3. ModelAndView 사용
@PostMapping("/input3")
public ModelAndView input3(HttpServletRequest request) {
String title = request.getParameter("title");
String singer = request.getParameter("singer");
String price = request.getParameter("price");
ModelAndView mav = new ModelAndView();
mav.addObject("title",title);
mav.addObject("singer",singer);
mav.addObject("price",price);
mav.addObject("addr","서울");
MusicBean music = new MusicBean();
music.setTitle(title);
music.setSinger(singer);
music.setPrice(Integer.parseInt(price));
mav.addObject("mavMusic",music);
mav.setViewName("music/result3");
return mav;
}
// 4. 커맨드 객체 (VO/DTO 자동 바인딩)
@PostMapping("/input4")
public String input4(MusicBean mb) {
//MusicBean mb : command 객체
/* String title = request.getParameter("title");
String singer = request.getParameter("singer");
String price = request.getParameter("price");
MusicBean music = new MusicBean();
music.setTitle(title);
music.setSinger(singer);
music.setPrice(Integer.parseInt(price));
model.addObject("bean",music);*/
System.out.println(mb.getTitle());
System.out.println(mb.getSinger());
System.out.println(mb.getPrice());
return "music/result4";
}
// 5. @ModelAttribute 사용 (4번의 커맨드 객체를 별칭으로 만듬)
@PostMapping("/input5")
public String input5(@ModelAttribute("bean") MusicBean mb) {
//model.addObject("musicBean",music);
return "music/result5";
}
}
📄 form.html 예제
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Form 입력</title>
</head>
<body>
<form th:action="@{/input1}" method="post">
제목 : <input type="text" name="title"><br>
가수 : <input type="text" name="singer"><br>
가격 : <input type="number" name="price"><br>
<button type="submit">전송</button>
</form>
</body>
</html>
👉 th:action="@{/input1}" 부분만 @{/input2}, @{/input3} … 로 바꿔가며 테스트
📄 MusicBean 예제
package com.example.Ex02.dto;
import java.util.List;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class MusicBean {
private String title;
private String singer;
private int price;
//private List<String> hobby; // 배열<체크박스>
}
1️⃣ HttpServletRequest & Model
// 2. @RequestParam + VO/DTO 사용
@PostMapping("/input2")
public String input2(@RequestParam("title") String title,
@RequestParam("singer") String singer,
@RequestParam("price") int price,Model model) {
//String title = request.getParameter("title");
System.out.println(title+"/"+singer+"/"+price);
MusicBean music = new MusicBean();
music.setTitle(title);
music.setSinger(singer);
music.setPrice(price);
model.addAttribute("music",music);
return "music/result2";
}
result1.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Result1</title>
</head>
<body>
<h2>입력값 출력 비교</h2>
<!-- 1. param : request.getParameter()와 동일 -->
<p>param.title : <span th:text="${param.title}"></span></p>
<p>param.singer : <span th:text="${param.singer}"></span></p>
<p>param.price : <span th:text="${param.price}"></span></p>
<hr>
<!-- 2. request.setAttribute() 로 저장한 값 -->
<p>rtitle (request) : <span th:text="${rtitle}"></span></p>
<p>rsinger (request) : <span th:text="${rsinger}"></span></p>
<p>rprice (request) : <span th:text="${rprice}"></span></p>
<hr>
<!-- 3. model.addAttribute() 로 저장한 값 -->
<p>mtitle (model) : <span th:text="${mtitle}"></span></p>
<p>msinger (model) : <span th:text="${msinger}"></span></p>
<p>mprice (model) : <span th:text="${mprice}"></span></p>
</body>
</html>
- ${param.xxx} 는 폼 input name 그대로 접근하는 방식,
- ${rtitle} 는 request에 직접 저장한 값,
- ${mtitle} 는 model에 추가한 값
2️⃣ @RequestParam + VO/DTO
// 2. @RequestParam + VO/DTO 사용
@PostMapping("/input2")
public String input2(@RequestParam("title") String title,
@RequestParam("singer") String singer,
@RequestParam("price") int price,Model model) {
//String title = request.getParameter("title");
System.out.println(title+"/"+singer+"/"+price);
MusicBean music = new MusicBean();
music.setTitle(title);
music.setSinger(singer);
music.setPrice(price);
model.addAttribute("music",music); // 👉 Model에 저장
// model.addAttribute("music", new MusicBean(title, singer, price))
return "music/result2"; // 👉 뷰 이름 문자열 반환
}
✅ @RequestParam 의 역할
- request.getParameter() + 타입 변환(int, double 등) 과정을 자동으로 대신 해주는 축약 문법
✅일반 클래스 객체 생성 다른점
일반 클래스 객체 생성:
// 일반 클래스 객체 생성: 단순히 메모리에 객체 생성 (컨트롤러 내부에서만 사용 가능).
MusicBean mb = new MusicBean(title, singer, price);
→ 이 상태로는 뷰(JSP/Thymeleaf)에서 접근 불가.
Model에 담은 경우:
model.addAttribute("music", mb);
→ request scope에 "music" 이름으로 객체 저장 → 뷰에서 ${music.title} 로 접근 가능.
result2.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
music/result2.html <br>
제목1 : <span th:text="${param.title}"></span><br> // 출력❌
제목2 : <span th:text="${music.title}"></span><br>
가수1 : <span th:text="${music.singer}"></span><br>
가격1 : <span th:text="${music.price}"></span><br>
</body>
</html>
3️⃣ ModelAndView (단일값 전달, 객체 전달) 2가지
- Model + View를 하나의 객체(ModelAndView)에 담아서 반환.
- 데이터(addObject)와 뷰 이름(setViewName)을 한 번에 처리.
3-1) 단일 값 전달 방식
// 3-1. ModelAndView (단일 값 전달)
@PostMapping("/input3")
public ModelAndView input3(HttpServletRequest request) {
String title = request.getParameter("title");
String singer = request.getParameter("singer");
String price = request.getParameter("price");
ModelAndView mav = new ModelAndView();
// 단일 값 추가
mav.addObject("title", title);
mav.addObject("singer", singer);
mav.addObject("price", price);
mav.addObject("addr", "서울");
mav.setViewName("music/result3"); // 뷰 이름 지정
return mav;
}
- addr → 그냥 "서울" 이라는 문자열을 모델에 직접 담음. (VO와 무관)
- mavMusic → MusicBean 객체 (title, singer, price 필드만 존재)
3-2) VO/DTO 객체 전달 방식
// 3-2. ModelAndView (VO/DTO 전달)
@PostMapping("/input3")
public ModelAndView input3(HttpServletRequest request) {
String title = request.getParameter("title");
String singer = request.getParameter("singer");
String price = request.getParameter("price");
// VO/DTO 객체 생성 후 값 설정
MusicBean music = new MusicBean();
music.setTitle(title);
music.setSinger(singer);
music.setPrice(Integer.parseInt(price));
ModelAndView mav = new ModelAndView();
mav.addObject("mavMusic", music);
mav.setViewName("music/result3"); // 뷰 이름 지정
return mav;
}
reulst3.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
music/result3.html<br>
// 단일 값 전달
title : <span th:text="${title}"></span><br>
singer : <span th:text="${singer}"></span><br>
price : <span th:text="${price}"></span><br>
addr : <span th:text="${addr}"></span><br>
<hr>
// 객체전달
제목: <span th:text="${mavMusic.title}"></span><br>
가수: <span th:text="${mavMusic.singer}"></span><br>
가격: <span th:text="${mavMusic.price}"></span><br>
//addr은 컨트롤러에서 단일 값으로만 모델에 담았기 때문에 ${mavMusic.addr} 로는 출력할 수 없음
</body>
</html>
✅ 핵심 정리
- ${mavMusic.xxx} → MusicBean 안에 있는 필드여야만 출력 가능.
- addr은 VO에 없는 값이라 ${mavMusic.addr}은 불가능.
- VO에 추가하거나, 단일 값 그대로 ${addr}로 출력해야 함.
4️⃣ 커맨드 객체
규칙
- 클래스 이름 그대로 가져옴 → MusicBean
- 첫 글자를 소문자로 바꿈 → musicBean
👉 그래서 뷰에서 접근할 땐 ${musicBean.title}, ${musicBean.singer}, ${musicBean.price}
// 4. 커맨드 객체 (VO/DTO 자동 바인딩)
@PostMapping("/input4")
public String input4(MusicBean mb) {
//MusicBean mb : command 객체
return "music/result4";
}
더보기
✅커맨드객체를 넣으면 자동으로 스프링이 모델에 담아줌
실제론 아래 작업이 이루어짐
String title = request.getParameter("title");
String singer = request.getParameter("singer");
String price = request.getParameter("price");
MusicBean music = new MusicBean();
music.setTitle(title);
music.setSinger(singer);
music.setPrice(Integer.parseInt(price));
model.addObject("bean",music);
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
music/result4.html<br>
제목: <span th:text="${musicBean.title}"></span><br>
가수: <span th:text="${musicBean.singer}"></span><br>
가격: <span th:text="${musicBean.price}"></span><br>
</body>
</html>
기본 이름 = 클래스명에서 첫 글자만 소문자로 바꾼 것.
소문자로 출력!
5️⃣ @ModelAttribute
- 4번의 커맨드객체에 별칭만 추가한 것
@PostMapping("/input5")
public String input5(@ModelAttribute("bean") MusicBean mb) {
return "music/result5";
}
@ModelAttribute("bean")
- 커맨드 객체 MusicBean mb가 자동으로 모델에 등록될 때,
- 기본 이름(musicBean) 대신 "bean" 이라는 이름으로 저장됨.
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
music/result5.html<br>
제목:<span th:text="${bean.title}"></span><br><hr>
가수:<span th:text="${bean.singer}"></span><br><hr>
가격:<span th:text="${bean.price}"></span><br><hr>
</body>
</html>
- 접근할때 별칭으로 접근해야함
Controller 의 매핑과 form 태그 연결
Controller의 @Post
@GetMapping("/input1")
@PostMapping("/input1")
@RequestMapping(value="/input2", method=RequestMethod.Get)
@RequestMapping(value="/input2", method=RequestMethod.POST)
@RequestMapping(value="/input2")
Spring Controller 매핑
<form th:action="@{/input1}" method="post">
제목 : <input type="text" name="title"><br>
가수 : <input type="text" name="singer"><br>
가격 : <input type="number" name="price"><br>
<button type="submit">전송</button>
</form>
⭐ 배열(체크박스) 처리
📌 5가지 방식에서 배열 처리 비교
1️⃣ HttpServletRequest & Model
@PostMapping("/input1")
public String input1(HttpServletRequest request, Model model) {
String[] hobby = request.getParameterValues("hobby");
request.setAttribute("rhobby", hobby);
model.addAttribute("mhobby", hobby);
return "result1";
}
뷰(result1.html):
취미(request) :
<span th:each="h : ${rhobby}" th:text="${h} + ' '"></span>
취미(model) :
<span th:each="h : ${mhobby}" th:text="${h} + ' '"></span>
2️⃣ @RequestParam + VO/DTO
@PostMapping("/input2")
public String input2(@RequestParam("hobby") String[] hobby, Model model) {
model.addAttribute("mhobby", hobby);
return "result2";
}
뷰(result2.html):
취미 :
<span th:each="h : ${mhobby}" th:text="${h}"></span>
3️⃣ ModelAndView
@PostMapping("/input3")
public ModelAndView input3(HttpServletRequest request) {
String[] hobby = request.getParameterValues("hobby");
ModelAndView mav = new ModelAndView();
mav.addObject("hobbyArr", hobby);
mav.setViewName("result3");
return mav;
}
뷰(result3.html):
취미 :
<span th:each="h : ${hobbyArr}" th:text="${h}"></span>
4️⃣ Command 객체 (VO/DTO 자동 바인딩)
VO 클래스:
public class Member {
private String name;
private String age;
private String[] hobby; // ✅ 배열 필드
// getter, setter
}
컨트롤러:
@PostMapping("/input4")
public String input4(Member member) {
return "result4";
}
뷰(result4.html):
취미 :
<span th:each="h : ${member.hobby}" th:text="${h}"></span>
5️⃣ @ModelAttribute
@PostMapping("/input5")
public String input5(@ModelAttribute("bean") Member member) {
return "result5";
}
뷰(result5.html):
취미 :
<span th:each="h : ${bean.hobby}" th:text="${h}"></span>
⭐ 배열 출력 마지막에 , 안 붙이는 방법 3가지
// 1) th:if 조건문과 조합
취미 :
<span th:each ="rh, stat : ${rhobby}">
<span th:text="${rh}"></span>
<span th:if="${not stat.last}">, </span>
</span>
// 2-1) 삼항연산자 not 사용 ==> h가 마지막이 아니면 ' , '
취미 :
<span th:each="h, stat : ${mhobby}">
<span th:text="${h + (not stat.last ? ', ' : '')}"></span>
</span>
// 2-2) 삼항연산자 사용 ==> h가 마지막이면 ' '
취미 :
<span th:each ="h, stat : ${member.hobby}"
th:text="${h + (stat.last ? '':', ')}"></span>
// 3. 컨트롤러에서 반복문 돌려서 출력
@PostMapping(value="/input1")
public String input1(HttpServletRequest request, Model model){
String name = request.getParameter("name");
String age = request.getParameter("age");
String[] hobby = request.getParameterValues("hobby"); // 요리, 게임
String temp="";
for(String hb : hobby){
temp += hb+" ";
request.setAttribute("rhobby",temp);
model.addAttribute("mhobby",temp);
}
✅ 정리
- 체크박스 같은 다중 선택 값은 배열(String[])로 바인딩된다.
- 배열 그대로 넘기면 뷰에서
th:each반복문으로 출력해야 한다. - 한 줄로 합쳐서 출력하려면 컨트롤러에서
String.join(", ", hobby)으로 문자열 변환해서 넘기면 된다.
✅ 차이 핵심 표정리
| 구분 | 2️⃣@RequestParam + VO/DTO | 3️⃣ModelAndView |
| 파라미터 추출 | @RequestParam 자동 바인딩 | request.getParameter() 직접 호출 |
| VO 처리 | VO를 수동으로 만들어 model에 담음 | VO를 만들어 addObject()로 담음 |
| 뷰 이름 | String으로 반환 | ModelAndView.setViewName() |
| 구분 | 3️⃣ModelAndView | 4️⃣커맨드 객체 |
| 파라미터 추출 | request.getParameter() 수동 | 스프링이 자동 바인딩 |
| 모델 추가 | mav.addObject("키", 값) 수동 | 자동으로 모델에 들어감 |
| 뷰 이름 | mav.setViewName("...") | 메서드에서 return "뷰이름" |
| 사용 빈도 | 예전 방식, 지금은 거의 안 씀 | 실무 표준 👍 |
📌 MVC란?
Model – View – Controller 의 약자.
애플리케이션을 세 가지 역할로 분리해서 유지보수성과 확장성을 높이려는 구조
1️⃣ Model (모델)
- 데이터와 비즈니스 로직 담당
- DB, DAO, VO/DTO, Service 같은 계층이 여기 속해요.
- ex) MusicBean, User, BoardDao 등
2️⃣ View (뷰)
- 사용자에게 보여지는 화면
- HTML, JSP, Thymeleaf, React 같은 UI 부분
- 데이터는 직접 처리하지 않고, 컨트롤러가 전달해 준 것만 표시
3️⃣ Controller (컨트롤러)
- 사용자의 요청(Request)을 받아 Model을 호출하고, 결과를 View로 전달
- 흐름 제어 역할
- Spring에서는 @Controller 클래스, @RequestMapping, @GetMapping, @PostMapping 등이 이에 해당
'기초 및 언어 > ▶ Spring' 카테고리의 다른 글
| 06. Spring_마이바티스(MyBatis) (2) | 2025.09.23 |
|---|---|
| 05. Spring_유효성검사 (0) | 2025.09.21 |
| 03. Spring_Lombok 라이브러리 어노테이션(@Setter, @Getter) (0) | 2025.09.19 |
| 02. Spring_import가 안될때 (0) | 2025.09.19 |
| 01. Spring_기초, 출력하기 (1) | 2025.09.18 |