2번째 필수강의 ch4. 6강 요약
/write로 가는 버튼을 게시글 목록 화면에 새로 만들고, 버튼을 누르면 /write로 GET 요청을 보내게 만든다. 게시글 조회에 사용했던 board.jsp를 그대로 사용하되, 글을 쓸 때는 옵션으로 readonly를 주지 않는다. 두 가지를 구분하기 위해 mode를 생성하고, mode값이 new면 readonly를 해제하도록 코드를 작성한다.
// BoardController
---
@GetMapping("/write")
public String write(Model m){
m.addAttribute("mode", "new");
return "board";
}
// Board.jsp
---
...
<h2>게시물 ${mode=="new"?"쓰기":"읽기"}</h2>
<form action="" id="form">
<input type="hidden" name="bno" value="${boardDto.bno}" ${mode=="new"?'':'readonly="readonly"'}>
<input type="text" name="title" value="${boardDto.title}" ${mode=="new"?'':'readonly="readonly"'}>
<textarea name="content" id="" cols="30" rows="10" ${mode=="new"?'':'readonly="readonly"'}>${boardDto.content}</textarea>
...
읽기와 쓰기 페이지를 따로 만들면 코드를 쓸 때는 편하지만, 유지보수 면에서는 수정사항이 있으면 두 곳을 고쳐야 하기 때문에 같은 화면을 쓴다.
게시글 내용을 입력하고 등록 버튼을 누르면, /write로 POST 요청을 보내도록 한다.
$('#writeBtn').on("click", function(){
let form = $('#form');
form.attr("action","<c:url value='/board/write'/>");
form.attr("method","post");
form.submit();
});
요청으로 넘어온 게시글을 DB에 저장한 후에는 다시 게시글 목록 첫 페이지로 redirect하도록 작성한다. 예외처리도 추가하여, 실행 결과가 1이 아니면 예외를 던지도록 처리하였다. 예외가 발생하면 다시 작성 화면으로 돌아가는데, 작성한 내용이 사라지지 않도록 model에 저장해준다.
@PostMapping("/write")
public String writePost(BoardDto boardDto, HttpSession session, Model m, RedirectAttributes rattr){
String writer = (String) session.getAttribute("id");
boardDto.setWriter(writer);
try{
int count = boardService.write(boardDto);
rattr.addFlashAttribute("msg", "write_ok");
if (count!=1) throw new Exception("글 작성 실패");
return "redirect:/board/list";
} catch (Exception e){
e.printStackTrace();
m.addAttribute("boardDto", boardDto);
rattr.addFlashAttribute("msg", "write_err");
return "board";
}
}
게시글 삭제처럼 게시글 등록도 등록에 성공하면 게시글 목록 화면에서 alert를 띄우도록 한다. 마찬가지로 새로고침했을 때 반복적으로 나오지 않도록 RedirectAttribute의 addFlashAttribute를 활용한다.
게시글 작성에 실패했을 경우 작성 화면에 그대로 머물러있기 때문에 board.jsp에 스크립트를 추가해준다.
<script>
let msg = "${msg}"
if(msg=="del_ok") alert("성공적으로 삭제되었습니다.");
if(msg=="del_err") alert("삭제에 실패했습니다.");
if(msg=="write_ok") alert("성공적으로 작성하였습니다.");
</script>
테스트해보면 잘 작동하는 것을 확인할 수 있다. 예외가 발생했을 때도 제대로 돌아가는지 보려면 DAO에서 예외를 던지도록 잠시 주석처리한 후 테스트해보면 된다.
다음으로 게시글 수정 기능을 구현해본다. 게시글 조회 화면에서 수정 버튼을 클릭하면 readonly 상태가 해제되게 만든다. jQuery를 활용하여 수정 버튼이 등록 버튼으로 바꾸고, 등록 버튼을 누르면 글 작성 화면과 똑같이 동작하도록 한다.
$('#modifyBtn').on("click", function(){
let form = $('form');
let isReadOnly=$("input[name=title]").attr('readonly');
if(isReadOnly=='readonly'){
$("input[name=title]").attr('readonly',false);
$("textarea").attr('readonly',false);
$("#modifyBtn").html("등록");
$("h2").html("게시물 수정");
return;
}
form.attr("action","<c:url value='/board/modify'/>");
form.attr("method","post");
form.submit();
});
다만 이 때는 /modify로 POST 요청이 날아가고, insert가 아니라 update가 일어난다.
@PostMapping("/modify")
public String modify(BoardDto boardDto, HttpSession session, Model m, RedirectAttributes rattr) {
String writer = (String) session.getAttribute("id");
boardDto.setWriter(writer);
try {
int count = boardService.modify(boardDto);
rattr.addFlashAttribute("msg", "modify_ok");
if (count != 1) throw new Exception("글 수정 실패");
return "redirect:/board/list";
} catch (Exception e) {
e.printStackTrace();
m.addAttribute("boardDto", boardDto);
rattr.addFlashAttribute("msg", "modify_err");
return "board";
}
}
추가로, 게시글을 수정하고 난 후에는 게시글 목록 첫 페이지가 아닌 해당하는 게시글 페이지로 돌아갈 수 있도록 수정해볼 필요가 있다.