Notice
Recent Posts
Recent Comments
Link
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Archives
Today
Total
관리 메뉴

Everything has an expiration date

[inflearn] 20240114 [스프링-프레임워크] - 19강 필기 본문

[Inflearn]/자바 스프링 프레임워크(renew ver.)

[inflearn] 20240114 [스프링-프레임워크] - 19강 필기

Jelly-fish 2024. 1. 14. 17:37

19강 - Controller 객체 구현 - Ⅱ

컨트롤러의 URL 맵핑과 파라미터 처리 방법에 대해서 학습한다.

19-1 @ModelAttribute
19-2 커맨드 객체 프로퍼티 데이터 타입
19-3 Model & ModelAndView

 

19-1 @ModelAttribute

 

`@ModelAttribute` 를 이용하면 커맨드 객체의 이름을 변경할 수 있고,

이렇게 변경된 이름은 뷰에서 커맨드 객체를 참조할 때 사용된다.

 

 

 

Controller View
public String memJoin(Member member) ID : ${member.memId}
public String memLogin(Member member) ID : ${member.memId}
public String memRemove
(`@ModelAttribute("mem")` Member member)
ID: ${mem.memId}

MemberController.java
@RequestMapping(value="/memJoin", method=RequestMethod.POST)
public String memJoin(@ModelAttribute("mem") Member member)
//                     ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄★
{
    service.memberRegister(member.getMemId(), member.getMemPw(), member.getMemMail()
                         , member.getMemPhone1(), member.getMemPhone2(), member.getMemPhone3());

    return "memJoinOk";
}

 

memJoinOk.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
</head>
<body>
	<h1> memJoinOk </h1>
    <!-- @RequestMapping 어노테이션을 통해 -->
    <!-- 『mem』으로 객체에 접근한 것을 확인! -->
	ID : ${mem.memId}<br />
	PW : ${mem.memPw}<br />
	Mail : ${mem.memMail} <br />
	Phone : ${mem.memPhone1}-${mem.memPhone2}-${mem.memPhone3} <br />
	
	<a href="/lec17/resources/html/memJoin.html"> Go MemberJoin </a>
</body>
</html>

 

출처 - Inflearn [스프링-프레임워크(renew)] - 19강

 

 


 

`@ModelAttribute("serverTime")` 란?

 


`serverTime`
실제로 서버에서 컨트롤러 내부의 특정 메소드가 호출됐을 때서버의 시간을 나타내 주는 기능을 한다.

 

MemberController.java
@ModelAttribute("serverTime")
public String getServerTime(Locale locale)
{
    Date date = new Date();
    DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);

    return dateFormat.format(date);
}

 

memRemoveOk.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
</head>
<body>
	<h1> memRemoveOk </h1>
	
	ID : ${mem.memId}<br />
	
	<P>  The time on the server is ${serverTime}. </P>
    <!--                             ̄ ̄ ̄ ̄ ̄ ̄ ̄★    -->
	
	<a href="/lec19/resources/html/index.html"> Go Main </a>
</body>
</html>

 

<P>  The time on the server is ${serverTime}. </P>

 

위와 같이, View 페이지에서 바로 메소드`String getServerTime()` 가 실행됐던 순간서버 시간을 표시해 줄 수 있다.


★②
`@ModelAttribute()` 어노테이션을 특정 메소드 상단에 작성하게 되면
Controller 내부의 `memJoin()` `memLogin()` `memRemove()` 등의 메소드들 중 어떤 것을 호출하든지 간에
`@ModelAttribute()` 가 적용되어 있는 메소드는 공통적으로 무조건 실행되는 것이다.

 

example ) `ModelAttribute()` 어노테이션 메소드, 다른 메소드와 함께 공통 호출

 

1. 클라이언트 `/memRemove` URL 요청

2. MemberController.java 컨트롤러의 `memRemove()` 메소드 실행
@RequestMapping(value = "/memRemove", method = RequestMethod.POST)
public String memRemove(@ModelAttribute("mem") Member member)
{
    service.memberRemove(member);
    return "memRemoveOk";
}

3. `@ModelAttribute("serverTime")` 어노테이션으로 인해
`getServerTime()` 메소드도 `memRemove()` 메소드와 함께 실행
@ModelAttribute("serverTime")
public String getServerTime(Locale locale)
{
    Date date = new Date();
    DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);

    return dateFormat.format(date);
}

 

출처 - Inflearn [스프링-프레임워크(renew)] - 19강

 

 


※ [총정리] : `@ModelAttribute()` 어노테이션의 기능

 

▶ Ⅰ. View 페이지에서 특정한 닉네임으로 접근 가능

`ModelAttribute("mem") Member member` 특정 닉네임을 정해서, View 페이지에서 (`${mem.memId}`) 사용할 수 있다.

 

▶ Ⅱ. 공통 호출

`ModelAttribute()` 가 적용되어 있는 메소드는, 컨트롤러의 어떤 메소드가 호출되던 간에 공통적으로 같이 호출된다.

 


19-2 커맨드 객체 프로퍼티 데이터 타입

데이터가 기초데이터 타입인 경우

 

memberJoin.html
ID : <input type="text" name="memId">
PW : <input type="password" name="memPw">
MAIL : <input type="text" name="memMail">
AGE : <input type="text" name="memAge" size="4" value="0">

Member.java (회원 DTO : Data Transfer Object)
private String memId;
private String memPw;
private String memMail;
private int memAge;

★데이터가 중첩 커맨드 객체를 이용한 List 구조인 경우

 

memberJoin.html
PHONE1 : <input type="text" name="memPhones[0].memPhone1" size="5"> -
         <input type="text" name="memPhones[0].memPhone2" size="5"> -
         <input type="text" name="memPhones[0].memPhone3" size="5"><br />
PHONE2 : <input type="text" name="memPhones[1].memPhone1" size="5"> -
         <input type="text" name="memPhones[1].memPhone2" size="5"> -
         <input type="text" name="memPhones[1].memPhone3" size="5"><br />

Member.java (회원 DTO : Data Transfer Object)
private List<MemPhone> memPhones;

 


 

회원의 전화번호 `memPhone` 같은 경우,

전화번호를 총 3개의 입력 창으로 분리하여 처리

 

memJoin.html

 

사용자로부터 하나의 전화번호를 입력받을 때,

`PHONE1 : [  ①  ] - [  ②  ] - [  ③  ]`

위와같이 입력을 받도록 처리한다.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>Member Join</h1>
	<form action="/lec19/member/memJoin" method="post">
    <!-- * Phone 입력 객체를 제외한 다른 Element 생략. -->
		PHONE1 : <input type="text" name="memPhones[0].memPhone1" size="5"> -
				 <input type="text" name="memPhones[0].memPhone2" size="5"> -
				 <input type="text" name="memPhones[0].memPhone3" size="5"><br />
		PHONE2 : <input type="text" name="memPhones[1].memPhone1" size="5"> -
				 <input type="text" name="memPhones[1].memPhone2" size="5"> -
				 <input type="text" name="memPhones[1].memPhone3" size="5"><br />
    <!-- ... -->

 

MemPhone.java (전화번호 DTO)

 

`PHONE1 : [  ①  ] - [  ②  ] - [  ③  ]`

으로 입력된 값들은 MemPhone.java DTO 에 setter를 통해 입력 값이 저장되게 된다.

 

→ ① (010) : `Memphone.memPhone1` 값

→ ② (1234) : `Memphone.memPhone2` 값

→ ③ (5678) : `Memphone.memPhone3` 값

 

package com.bs.lec19.member;

public class MemPhone {
	
	private String memPhone1;
	private String memPhone2;
	private String memPhone3;
	
	public String getMemPhone1() {
		return memPhone1;
	}
	public void setMemPhone1(String memPhone1) {
		this.memPhone1 = memPhone1;
	}
	public String getMemPhone2() {
		return memPhone2;
	}
	public void setMemPhone2(String memPhone2) {
		this.memPhone2 = memPhone2;
	}
	public String getMemPhone3() {
		return memPhone3;
	}
	public void setMemPhone3(String memPhone3) {
		this.memPhone3 = memPhone3;
	}
	
}

 

Member.java (회원 DTO)

 

`MemPhone.java` (전화번호 DTO) DTO 객체는

하나의 전화번호에 해당하는 값을 갖고 있고,

 

`Member.java` (회원 DTO) 에서는 본인의 전화번호비상 전화번호(보호자 전화번호),

총 두 개의 전화번호를 저장할 수 있도록 설정해 두었다.

 

즉, `Member.java` (회원 DTO) 객체에는 전화번호 '들' (`MemberPhone.java`)을 저장해야 하므로

이를 `List<MemberPhone>` 자료구조 형식으로 선언하여 총 두 개의 전화번호 객체를 저장할 수 있도록 한 것이다.

 

package com.bs.lec19.member;

import java.util.List;

public class Member
{
    // * memPhone 프로퍼티를 제외한 다른 프로퍼티 생략.

    private List<MemPhone> memPhones;

    public List<MemPhone> getMemPhones()
    {
        return memPhones;
    }
    
    public void setMemPhones(List<MemPhone> memPhones)
    {
        this.memPhones = memPhones;
    }

}

memJoinOk.jsp (회원가입 완료 창)

 

회원 객체인 `Member.java`에 저장된 전화번호 `memPhones` 프로퍼티의 타입은 `List<MemPhone>` 이다.

private List<MemPhone> memPhones;

 

★ 즉, `memPhones[0]` 과 같이 인덱스로 하나의 요소를 선택했을 때의 타입은 `MemberPhone` (전화번호 DTO)이므로

`${member.memPhone[0].memPhone1}` → 본인 전화번호의 첫 번째 자리인 `010` 을 표시하게 되는 것이다.

 

① `${member.memPhone[0].memPhone1}` : 010

② `${member.memPhone[0].memPhone2}` : 1234

③ `${member.memPhone[0].memPhone3}` : 5678

 

 

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
</head>
<body>
	<h1> memJoinOk </h1>
    <!-- * Phone 에 해당하는 EL을 제외한 다른 EL 구문 생략. -->	
	PHONE1 : ${member.memPhones[0].memPhone1} - ${member.memPhones[0].memPhone2} - ${member.memPhones[0].memPhone3} <br />
	PHONE2 : ${member.memPhones[1].memPhone1} - ${member.memPhones[1].memPhone2} - ${member.memPhones[1].memPhone3} <br />
    <!-- ... -->

 


19-3 Model & ModelAndView

컨트롤러에서 뷰에 데이터를 전달하기 위해 사용되는 객체로 Model과 ModelAndView 가 있다.

두 객체의 차이점은

 

◎ `Model` 은 뷰에 데이터만을 전달하기 위한 객체이고,

◎ `ModelAndView` 는 데이터뷰의 이름을 함께 전달하는 객체이다.

 

ⓐ return : `String` 일 때 - [`Model` 만 사용]

 

MemberController.java 
@RequestMapping(value = "/memModify", method = RequestMethod.POST)
public String memModify(Model model, Member member)
{
	Member[] members = service.memberModify(member);
    
    // ① 데이터 전달
    model.addAttribute("memBef", members[0]);	//-- 수정 전 멤버 객체
    model.addAttribute("memAft", members[1]);	//-- 수정 후 멤버 객체
    
    // ② 뷰의 이름 전달
    return "memModifyOk";
}

 

memModifyOk.jsp
ID : ${memBef.memId}
ID : ${memAft.memId}

ⓑ return : `ModelAndView` 일 때

 

MemberController.java
@RequestMapping(value = "/memModify", method = RequestMethod.POST)
public ModelAndView memModify(Model model, Member member)
{
	Member[] members = service.memberModify(member);
    
	ModelAndView mav = new ModelAndView();
    
    // ① 모델(model) 객체에 데이터 저장(추가)
    mav.addObject("memBef", members[0]);
    mav.addObject("memAft", members[1]);
    
    // ② 뷰(view) 페이지 이름 전달(추가).
    mav.setViewName("memModifyOk");
    
    return mav;
}