2019년 12월 25일 수요일

@ModelAttribute 어노테이션을 이용한 Controller에서 View로의 데이터 전달

@ModelAttribute가 Controller 메소드의 매개변수로 선언된 Command 객체의 긴 이름을 짦은 이름으로 변경할때도 사용되지만(해당 포스트는 여기를 클릭),
Controller 클래스에 있는 특정 데이터를 View(.jsp 페이지)에서 사용할수 있도록 View로 넘기는 용도로도 사용되는 별스런 역할도 할수 있다.
일단 개념부터 정리를 해 보면...

어떤 컨트롤러 클래스 안에있는 특정 메소드에 @ModelAttribute 어노테이션이 붙어 있으면 해당 컨트롤러 클래스의 모든 @RequestMapping 어노테이션이 붙은 메소드가 호출될 때마다 그 메소드 호출 전에 @ModelAttribute가 붙은 메소드가 일단 먼저 호출되고 그 이후 @RequestMapping이 붙은 메소드가 호출되는데 이때 @ModelAttribute 메소드 실행 결과로 리턴되는 객체(데이터)는 자동으로 @RequestMapping 어노테이션이 붙은 메소드의 Model에 저장이되고 그 이후에 .jsp(View)에서 @ModelAttribute 메소드가 반환한 데이터를 사용할수 있다.
놀라운 @ModelAttribute의 능력이랄까?

일단 코드에서 확인해 보자. 아래와 같은 컨트롤러 클래스가 있다.

@Controller
public class BoardController {
... 전 략 ...

//글 수정
@RequestMapping("/updateBoard.do")
public String updateBoard(BoardVO vo, BoardDAO bdDao) throws Exception {
System.out.println("UpdateBoardController 글 수정 처리~");

bdDao.updateBoard(vo);
return "getBoardList.do";
}

//글 상세 조회
@RequestMapping("/getBoard.do")
public String getBoard(BoardVO vo, BoardDAO bdDao, Model model) throws Exception {
System.out.println("GetBoardController 글 상세 조회 처리~");

model.addAttribute("boardModel", bdDao.getBoard(vo));
return "getBoard.jsp";
}

//글 목록 검색
@RequestMapping("/getBoardList.do")
public String getBoardList(
        @RequestParam(value="searchCondition", defaultValue="TITLE", required=true) String condition,
@RequestParam(value="searchKeyword", defaultValue="", required=false) String keyWord,
BoardVO vo,
BoardDAO bdDao,
Model model) throws Exception {
System.out.println("$$$$$$$ GetBoardListController 글 목록 검색 처리~");

model.addAttribute("boardListModel", bdDao.getBoardList(vo));
return "getBoardList.jsp";
}

@ModelAttribute("myModelAttribute")
public Map<String, String> joe() {
System.out.println("▶▶▶▶▶▶▶ 여기는 joe()~~~ ▶▶▶▶▶▶▶");

Map<String, String> infoMap = new HashMap<String, String>();

infoMap.put("joe", "Web Developer");
infoMap.put("kim", "Designer");
infoMap.put("nana", "CEO of M&P");

return infoMap;
}
}

위의 BoardController 클래스안에는 @RequestMapping 어노테이션이 붙은 메소드가 3개가 있는데
-. public String updateBoard()
-. public String getBoard()
-. public String getBoardList()

이들 메소드가 호출될때마다 @ModelAttribute("myModelAttribute") 어노테이션이 붙은 아래 메소드가 먼저 호출된다.
public Map<String, String> joe()
그리고 joe() 메소드에서 반환하는 데이터(infoMap)가 클라이언트 요청으로 실행될 @RequestMapping이 붙은 메소드의 Model 객체에 자동으로 저장이 된다. 이렇게 저장된 데이터는 .jsp 페이지에서 사용할수 있게 되는데 이때 @ModelAttribute("myModelAttribute") 안에 지정한 문자열인 myModelAttribute가 객체 이름이 된다. 
역시 .jsp에서 어떻게 데이터에 접근하는지 코드에서 확인해 보자.

예를들어 http://xxx.xxx.xx/getBoard.do로 요청이 들어오면 먼저  
public Map<String, String> joe()가 먼저 호출이 되고 그 이후 
public String getBoard(BoardVO vo, BoardDAO bdDao, Model model)가 호출이 되는데 이때 joe() 메소드에서 생성된 infoMap 데이터가 getBoard()의 model 객체에 자동으로 저장이 되고 getBoard.jsp에서는 다음과 같이 데이테어 접근할수 있게 된다. 

... 전 략 ...
<h1>글 상세보기</h1>
<a href="logout.do">로그아웃</a>
<hr>

구성원1 : ${ myModelAttribute.joe }<br/>
구성원2 : ${ myModelAttribute.nana }<br/>
<hr/>
... 후 략 ...

위 .jsp 페이지의 출력 결과는 다음과 같이 될 것이다.

구성원1 : Web Devloper
구성원2 : CEO of  M&P

혹은 다음과 같이도 할수 있다.

<c:forEach items="${ myModelAttribute }" var="item">
item.key : ${item.key }<br/>
item.value : ${item.value }<br/><br/>
</c:forEach>
<hr/>

그러면 다음과 같은 결과가 나올 것이다.

item.key : joe
item.value : Web Developer

item.key : nana
item.value : CEO of M&P

item.key : kim
item.value : Designer

@ModelAttribute 어노테이션이 이런 용도로도 사용될수 있다는 점이다.
그런데 @ModelAttribute는 이것 외에 또 있으니 @SessionAttribute와 연결되면 또 요술을 부린다.

댓글 없음:

댓글 쓰기