3. 등록 입력 페이지와 등록 처리
게시물의 등록 작업은 POST 방식으로 처리하지만, 화면에서 입력을 받아야 하므로 GET 방식으로 입력 페이지를 볼 수 있도록 BoardController에 메서드를 추가한다.
@GetMapping("/register")
public void register() {
}
register()는 입력 페이지를 보여주는 역할만을 하기 때문에 별도의 처리가 필요하지 않다. views 폴더에는 includes를 적용한 입력 페이지를 작성한다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@include file="../includes/header.jsp" %>
<div class="row">
<div class="col-lg-12">
<h1 class = "page-header">Board Register</h1>
</div>
<!-- /.col-lg-12 -->
</div>
<!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class ="panel panel-default">
<div class="panel-heading">Board Register</div>
<!-- /.panel-heading -->
<div class="panel-body">
<form role="form" action="/board/register" method="post">
<div class="form-group">
<label>Title</label> <input class="form-control" name='title'>
</div>
<div class ="form-group">
<label>Text area</label>
<textarea class = "form-control" rows="3" name ='content'></textarea>
</div>
<div class = "form-group">
<label>Writer</label> <input class = "form-control" name='writer'>
</div>
<button type="submit" class = "btn btn-default">Submit Button</button>
<button type="reset" class = "btn btn-default">Reset Button</button>
</form>
</div>
<!-- end panel-body -->
</div>
<!-- end panel-body -->
</div>
<!-- end panel -->
</div>
<!-- /.row -->
<%@include file="../includes/footer.jsp"%>
register 페이지에서는 <form> 태그를 이용해서 필요한 데이터를 전송한다. <input>이나 <textarea> 태그의 name 속성은 BoardVO 클래스의 변수와 일치시켜 준다.
브라우저를 통해 'board/register' 화면이 제대로 출력되는지 확인한다.
화면이 정상적으로 보인다면 입력 항목을 넣어서 새로운 게시물이 등록되는지를 확인한다. BoardController의 POST 방식으로 동작하는 register()는 redirect 시키는 방식을 이용하므로, 게시물의 등록 후에는 다시 '/board/list' 로 이동하게 된다.
게시물의 등록은 정상적으로 이루어지지만 한글이 깨지는 문제가 발생한다.
3-1. 한글 문제와 UTF-8 필터 처리
새로운 게시물을 등록했을 때 만일 한글 입력에 문제가 있다는 것을 발견했다면
1) 브라우저에서 한글이 깨져서 전송되는지 확인
2) 문제가 없다면, 스프링 MVC 쪽에서 한글을 처리하는 필터를 등록
브라우저에서 전송되는 데이터는 개발자 도구를 이용해서 확인할 수 있다. 개발자 도구에서 'Network'탭을 열어둔 상태에서 데이터를 보내면 해당 내용을 볼 수 있으므로 이때 POST 방식으로 제대로 전송되었는지, 한글이 깨진 상태로 전송된 것인지를 확인할 수 있다.
위의 화면을 보면 브라우저가 한글을 문제없이 보냈음을 알 수 있는데, 문제는 Controller 혹은 데이터베이스 쪽이라는 것을 알 수 있다.
BoardController 와 BoardServiceImpl을 개발할 때는 이미 Lombok의 로그를 이용해서 필요한 기능들을 기록해 두었으므로, 이를 확인해야 한다.
로그를 살펴보면 BoardController 에 전달될 때 이미 한글이 깨진 상태로 처리된 것을 볼 수 있다.
이 문제를 해결하기 위해 web.xml에 아래와 같이 필터를 추가한다.
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<servlet-name>appServlet</servlet-name>
</filter-mapping>
한글에 대한 처리가 끝난 후 다시 게시물을 작성해 보면 한글에 문제가 없이 입력되는 것을 확인할 수 있다.
3-2. 재전송 처리
등록 과정에서 POST 방식으로 데이터가 처리되는 과정을 그림으로 표현하면 다음과 같다.
BoardController 에서 register() 메서드는 'redirect:/board/list'를 전송하는데 브라우저는 이를 통보받은 후 '/board/list'로 이동하게 된다. 만일 위와 같이 재전송을 하지 않는다면 사용자는 브라우저의 '새로고침'을 통해서 동일한 내용을 계속 서버에 등록할 수 있기 때문에 (흔히 도배라고 표현하는) 문제가 발생하게 된다. 브라우저에서는 이런 경우 경고창을 보여주기는 하지만 근본적으로 차단하지는 않는다.
따라서 등록,수정,삭제 작업은 처리가 완료된 후 다시 동일한 내용을 전송할 수 없도록 아예 브라우저의 URL을 이동하는 방식을 이용한다. 이러한 과정에서 하나 더 신경써야 하는 것은 브라우저에 등록, 수정, 삭제의 결과를 바로 알 수 있게 피드백을 줘야 한다는 점이다. 경고창이나 <div>를 이용하는 모달창을 이용해서 이러한 작업을 처리한다.
BoardController에서 redirect 처리를 할 때 RedirectAttributes라는 특별한 타입의 객체를 이용했다. addFlashAttribute()의 경우 이러한 처리에 적합한데, 그 이유는 일회성으로만 데이터를 전달하기 때문이다. addFlashAttribute()로 보관된 데이터는 단 한 번만 사용할 수 있게 보관된다. (내부적으로는 HttpSession 을 이용해서 처리)
list.jsp 페이지의 아래쪽에 <script>태그를 이용해서 상황에 따른 메시지를 확인할 수 있다.
<script type="text/javascript">
$(document).ready(function(){
var result = '<c:out vlaue="${result}"/>';
});
</script>
새로운 게시물의 번호는 addFlashAttribute()로 저장되었기 때문에 한 번도 사용된 적이 없다면 값을 만들어 내지만 사용자가 '/board/list'를 호출하거나, '새로고침'을 통해서 호출하는 경우는 아무런 내용이 없게 된다.
addFlashAttribute()를 이용해서 일회성으로만 데이터를 사용할 수 있으므로 이를 이용해서 경고창이나 모달창 등을 보여주는 방식으로 처리할 수 있다.
3-3. 모달창 보여주기
최근에는 브라우저에서 경고창을 띄우는 방식보다 모달창을 보여주는 방식을 많이 사용합니다. BootStrap은 모달창을 간단하게 사용할 수 있으므로 목록 화면에서 필요한 메시지를 보여주는 방법을 사용해 보자.
모달창은 기본적으로 <div>를 화면에 특정 위치에 보여주고, 배경이 되는 <div>에 배경색을 입혀서 처리한다. 모달창은 활성화된 <div>를 선택하지 않고는 다시 원래의 화면을 볼 수 없도록 막기 때문에 메시지를 보여주는데 효과적인 방식이다. 모달창에 대한 코드는 다운로드한 SBAdmin2의 폴더 내 notifications.html 파일을 참고하면 된다.
모달창을 처리하기 위해서는 우선 <div>를 이용해서 페이지의 코드에 추가해야 한다. list.jsp 내에 <table> 태그의 아래쪽에 모달창의 <div>를 추가한다.
<!-- Modal 추가 -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog"
aria-labelledby="myModalLabel" aria-hidden="true">
<div class = "modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class = "close" data-dismiss="modal"
aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<div class = "modal-body">처리가 완료되었습니다.</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /.modal -->
모달창을 보여주는 작업은 jQuery를 이용해서 처리할 수 있다.
<script type="text/javascript">
$(document).ready(function(){
var result = '<c:out value="${result}"/>';
})
checkModal(result);
function checkModal(result){
if(result === ''{
return;
}
if (parseInt(result) >0){
$(".modal-body").html("게시글" + parseInt(result) + " 번이 등록되었습니다.");
}
$("#myModal").modal("show");
}
});
</script>
checkModal() 함수는 파라미터에 따라서 모달창을 보여주거나 내용을 수정한 뒤 보이도록 작성한다. checkModal()에서는 새로운 게시글이 작성되는 경우 RedirectAttributes로 게시물의 번호가 전송되므로 이를 이용해서 모달창의 내용을 수정한다. $("#modal").modal('show')를 호출하면 모달창이 보이게 된다.
이제 'board/register'를 이용해서 새로운 게시물을 작성하고 나면 자동으로 'board/list'로 이동하며 모달창이 보이게 된다.
띠용..
해결! (-> 방법은 error 보고서 카테고리에!)
3-4. 목록에서 버튼으로 이동하기
게시물의 작성과 목록 페이지로 이동이 정상적으로 동작했다면, 마지막으로 목록 페이지 상단에 버튼을 추가해서 등록 작업을 시작할 수 있게 처리하는 것이다.
우선은 list.jsp 의 HTML 구조를 아래와 같이 수정한다.
(panel-heading의 div 태그를 닫기전 버튼을 추가!)
list.jsp 하단의 jQeury를 이용하는 부분에서 해당 버튼을 클릭했을 때의 동작을 정의한다.
<script type="text/javascript">
$(document).ready(function(){
var result = '<c:out value="${result}"/>';
checkModal(result);
function checkModal(result){
if(result === ''){
return;
}
if (parseInt(result) >0){
console.log("들어옴?");
$(".modal-body").html("게시글" + parseInt(result) + " 번이 등록되었습니다.");
}
$("#myModal").modal("show");
}
$("#regBtn").on("click", function(){
self.location = "/board/register";
});
});
</script>
화면에서 'Register New Board' 버튼을 클릭하면 게시물의 등록 페이지로 이동할 수 있다.
(그런데 나는 왜 버튼이 진하게 표시되지않지???..)
4. 조회 페이지와 이동
게시물의 등록과 리스트 처리가 끝났다면 가장 중요한 틀은 완성되었다고 볼 수 있다. 다음으로는 목록 페이지에서 링크를 통해서 GET 방식으로 특정한 번호의 게시물을 조회할 수 있는 기능을 작성한다.
4-1. 조회 페이지 작성
조회 페이지는 입력 페이지와 거의 유사하지만 게시물 번호가 출력된다는 점과 모든 데이터가 읽기 전용으로 처리된다는 점이 가장 큰 차이다.
게시물의 조회는 BoardController에서 get() 메서드로 구성되어 있다.
@GetMapping("/get")
public void get(@RequestParam("bno") Long bno, Model model) {
log.info("/get");
model.addAttribute("board", service.get(bno));
}
views/board 폴더 내 get.jsp를 register.jsp로 복사해서 작성한다.
get.jsp는 게시물 번호를 보여줄 수 있는 필드를 추가하고, 모든 데이터는 readonly를 지정해서 작성한다. register.jsp에 있던 <form> 태그는 조회 페이지에서는 그다지 필요하지 않으므로 제거하는 대신 마지막에는 수정/삭제 페이지로 이동하거나 원래의 목록 페이지로 이동할 수 있는 버튼을 추가한다.
브라우저에서는 '/board/get?bno=1' 과 같이 게시물의 번호를 반드시 파라미터로 전달해야 한다. 파라미터로 전달하는 bno 값이 존재한다면 아래와 같은 페이지를 보게된다.
화면 하단의 버튼은 '/board/list'와 '/board/modify?bno=xx'와 같이 이동하는 링크를 추가한다.
<button data-oper='modiyfy'
class="btn btn-default"
onclick="location.href='/board/modify?bno=<c:out value="${board.bno }"/>'">
Modify
</button>
<button data-oper='list'
class="btn btn-info"
onclick="location.href='/board/list'">
List
</button>
'Spring > Spring' 카테고리의 다른 글
[SpringDataJPA] @Modifying 과 @Query 의 관계와 동작방식 (@Query 없이 @Modifying 만 사용한다면 어떻게 될까?) (1) | 2023.12.28 |
---|---|
[SpringCache] 쪼금의 개념 설명과 Caffeine maximumSize 옵션 테스트 (1) | 2023.11.01 |
[14] 기본적인 웹 게시물 관리 - 화면 처리 (0) | 2019.12.19 |
[13] 기본적인 웹 게시물 관리 - 프레젠테이션 계층의 CRUD 구현 (0) | 2019.12.19 |
[12] 기본적인 웹 게시물 관리 - 비즈니스 계층 (0) | 2019.12.19 |