<form method="post" class="example-form"> <fieldset>Book</fieldset> <label>책 제목</label> <input type="text" name="title" placeholder = "책 제목을 입력해주세요."/> <label>작가 이름</label> <input type="text" name="author" placeholder = "작가 이름을 넣어주세요."/> <label>추가 설명</label> <input type="text" name="comment" placeholder = "추가 설명을 넣어주세요."/> <br/> <button type="submit" class="btn">추가</button>
</form>
@RequestMapping(value = "/book/add01", method = RequestMethod.POST) public String add(String title, String author, String comment) { Book book = new Book(); book.setTitle(title); book.setComment(comment); book.setAuthor(author); bookService.add(book); return "redirect:add01"; }
@RequestMapping(value = "/book/add01", method = RequestMethod.POST) public String add(@RequestParam(value = "title") String title, @RequestParam(value = "author") String author, @RequestParam(value = "comment") String comment) { Book book = new Book(); book.setTitle(title); book.setComment(comment); book.setAuthor(author); bookService.add(book); return "redirect:add01"; }
@RequestMapping(value = "/book/add02", method = RequestMethod.POST) public String add02(Book book) { bookService.add(book); return "redirect:add01"; }
//BookController @RequestMapping(value = "/book/add02", method = RequestMethod.POST) public String add02(Book book, final RedirectAttributes redirectAttribute) { bookService.add(book); redirectAttribute.addFlashAttribute("book", book); return "redirect:add01"; } //BookControllerTest @Test public void add02() throws Exception { String bookTitle = "Book Title"; String bookAuthor = "Book Author"; String bookComment = "Book Comment"; MvcResult mvcResult = mvc.perform(post("/book/add02") .param("title", bookTitle) .param("author", bookAuthor) .param("comment", bookComment)) .andExpect(status().isFound()) .andExpect(flash().attributeExists("book")) .andDo(print()) .andReturn(); Book book = (Book) mvcResult.getFlashMap().get("book"); assertThat(book.getTitle(), is(bookTitle)); assertThat(book.getComment(), is(bookComment)); assertThat(book.getAuthor(), is(bookAuthor)); System.out.println(mvcResult); }
@RequestMapping(value = "/book/add02", method = RequestMethod.GET) public String add02(Model model) { Book book = new Book(); model.addAttribute("book", book); return "book/add02"; } @RequestMapping(value = "/book/add02", method = RequestMethod.POST) public String add02(@ModelAttribute Book book, final RedirectAttributes redirectAttribute) { bookService.add(book); redirectAttribute.addFlashAttribute("book", book); return "redirect:add01"; }
이전의 동기 통신에서는 웹 애플리케이션이 서버와의 인터랙션을 필요로 할 때에 매번 브라우저가 사용자와의 인터랙션을 멈추고, 서버로부터의 응답이 올때까지 기다려야 했습니다. 서버로부터의 응답이 오기 전까지 사용자는 아무것도 할 수 없었죠.
하지만 비동기 통신에서는 서버로부터의 응답을 기다릴 필요 없이 사용자는 계속해서 애플리케이션에서 원하는 작업을 할 수 있습니다.
Ajax를 이용하는 예로는 구글맵, 검색사이트 검색창에서의 검색어 제시, 네이버 실시간 검색 순위 등이 있습니다.
Ajax의 장점
Ajax의 주요 장점은 아래와 같습니다.
1) 페이지 이동없이 고속으로 화면 전환
: Ajax는 페이지의 이전 없이 필요한 부분의 데이터 송수신만을 자유롭게 행할 수 있으므로, 효율적이고 빠르게 페이지를 전환할 수 있습니다.
2) 서버의 처리를 기다리지 않고 비동기 요청이 가능
: 서버와의 통신시 사용자는 서버로부터의 응답을 기다리지 않고 계속해서 다음 작업을 이어갈 수 있습니다.
3) 서버에서 처리하는 부분을 클라이언트에서 분담 가능
: Ajax로는 최소의 데이터만을 브라우저에 전달하기 위해 서버에서 하는 작업 중 JavaScript에서 수행 가능한 일을
클라이언트에서 분담하는 것이 가능합니다.
4) 수신하는 데이터의 양을 줄일 수 있음
: 기존의 브라우저가 수신하는 데이터는 HTML이나 XHTML과 같은 마크업 언어로 받는 것이 일반적인데 반해, Ajax로는 수신하는 데이터가 HTML이나 XML에 한정되지 않고 최소한의 텍스트 데이터로도 수신이 가능하기 때문에 수신 데이터이 양을 줄일 수 있습니다.
5) 실시간 인터렉티브 성능이 증가
: (1) ~ (4) 까지의 장점을 이용해 Ajax에서는 데스크탑 애플리케이션과 유사한 실시간 인터랙티브 성능을 보여줄 수 있습니다.
Ajax의 단점
Ajax의 단점은 아래와 같습니다.
1) 크로스 브라우저화의 노하우가 필요
: Ajax는 JavaScript 이므로 브라우저에 따른 크로스 브라우저 처리가 필요합니다.
2) Ajax를 지원하지 않는 브라우저에 대한 대책 필요
: Ajax를 지원하지 않는 브라우저에서는 사용이 불가능하므로 이에 대한 대책이 필요합니다. (하지만 현재 Ajax를 지원하지 않는 브라우저는 거의 없다고 볼 수 있습니다.)
3) 보안에 대한 주의가 불가피
: 페이지 이동 없이 서버와 통신하기 때문에 전보다 더욱 신중한 보안상의 주의가 요구됩니다.
4) 현재의 처리 상황에 대한 정보가 필요
: 페이지 전환 없이 처리가 진행되므로 사용자가 처리가 완료되었는데도 이를 모를 수 있습니다. 따라서 처리 중을 나타내는 프로그레시브 바등을 사용하는 것이 요구됩니다.
5) 요청을 남발하면 역으로 서버 부하가 늘 수 있음
: Ajax의 장점은 서버 부하의 감소에 있지만 그 의도와 반대로 요청이 너무 빈번하게 일어나 서버의 부하를 늘려버릴 수 있습니다. 따라서 데이터 전송량, 요청 회수, 서버 부하 등에 대한 종합적인 판단과 튜닝이 필요합니다.
6) Socket open / close의 부하 시간 증가
: 브라우저에서 가장 큰 부하를 주는 http call을 open을 자주 시키게 됩니다. URL이동으로 인하여 한번에 모든 데이터를 들고오는 방식을 ajax로 여러번을 나눠서 받는 경우, socket의 open/close 시간이 http call 횟수만큼 증가하게 됩니다. 적정한 ajax call이 필요합니다.
7) 개발의 어려움
: 1)항목과 연관이 있는 이야기입니다. javascript는 브라우져에 따라 동작이 다르게 움직여집니다. javascript를 테스트하기 위해서는 지금 상태로는 browser를 반드시 실행시켜서 그 결과를 확인해야지 됩니다. 상당한 수작업이 들어가기 때문에 ajax를 통해서 일을 진행을 해야지 된다면, 그에 대한 pattern등을 명확히 지정해야지 됩니다. 필요없이 모든 것을 다 ajax로 하게 되면 개발 시간뿐 아니라 부하역시 무시할 수 없기 때문입니다.
<script> $(function() { $('#add-button').on('click', function() { var title = $('form input[name=title]').val(); var author = $('form input[name=author]').val(); var comment = $('form input[name=comment]').val(); addBook(title, author, comment); }); }); function addBook(title, comment, author) { $.post("add03", { "title" : title, "author" : author, "comment" : comment }, function(jsonResult){ alert(jsonResult); }, 'json') .done(function(jsonResult) { console.log(jsonResult); }) .fail(function(jsonResult) { console.log(jsonResult); }); } </script> <form method="post" class="example-form"> <fieldset>Book</fieldset> <label>책 제목</label> <input type="text" name="title" placeholder = "책 제목을 입력해주세요."/> <label>작가 이름</label> <input type="text" name="author" placeholder = "작가 이름을 넣어주세요."/> <label>추가 설명</label> <input type="text" name="comment" placeholder = "추가 설명을 넣어주세요."/> <br/> <button id="add-button" type="button" class="btn">추가</button>
</form>
@RequestMapping(value = "/book/add03", method = RequestMethod.GET) public String add03(Model model) { Book book = new Book(); model.addAttribute("book", book); return "book/add03"; } @RequestMapping(value = "/book/add03", method = RequestMethod.POST) @ResponseBody public Map<String, String> add03(@ModelAttribute Book book) { bookService.add(book); Map<String, String> bookDto = new HashMap<>(); bookDto.put("title", book.getTitle()); bookDto.put("author", book.getAuthor()); bookDto.put("comment", book.getComment()); return bookDto; }
@RequestMapping(value = "book/list/index") public String getBookListIndex() { return "book/list/index"; } @RequestMapping(value = "book/list/jsonpage", method = RequestMethod.POST) @ResponseBody public List<Book> getBookJsonList(@RequestParam(value = "pageIndex") int pageIndex, @RequestParam(value = "pageSize") int pageSize) { List<Book> books = bookService.listup(pageIndex, pageSize); return books; }
<script type ="text/javascript"> $(function() { $('#btn-getbookList').on( 'click', function () { var pageIndex = parseInt($('input[name=pageIndex]' ).val()); var pageSize = parseInt($('input[name=pageSize]' ).val()); getBookList(pageIndex, pageSize); }); }); function getBookList(pageIndex, pageSize) { $.post("jsonpage", { pageIndex : pageIndex, pageSize : pageSize }, function(jsonResult) { var html = '<table class="table table-striped table-bordered table-hover">'; for(var i = 0 ; i < jsonResult.length ; i++) { html += '<tr>'; html += '<td>' + jsonResult[i].title + '</td>' ; html += '<td>' + jsonResult[i].author + '</td>' ; html += '<td>' + jsonResult[i].comment + '</td>' ; html += '</tr>'; } html += '</table>'; $( '#bookPage').html(html); }, 'json'); } </script> <label>Page Index</label> <input name ="pageIndex" type="number" /> <br/> <label>Page Size</label> <input name ="pageSize" type="number" value="3"/> <br/> <input type ="button" id="btn-getbookList" value="GetBookList"/> <fieldset> <legend>Book List page </legend> <div id="bookPage" ></div> </fieldset> |
@RequestMapping( value = "book/list/index2" ) public String getBookListIndex2() { return "book/list/index2" ; } @RequestMapping( value = "book/list/html" , method = RequestMethod.POST ) public String getBookHtmlList( @RequestParam(value = "pageIndex") int pageIndex, @RequestParam(value = "pageSize") int pageSize , Model model ) { List<Book > books = bookService. listup(pageIndex , pageSize); model.addAttribute ("books", books); return "book/list/html" ; } |
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %> <%@ page language= "java" contentType ="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <table class ="table table-striped table-bordered table-hover"> <c:forEach var="book" items="${books } "> <tr> <td>${book.title }</td> <td>${book.author }</td> <td>${book.comment }</td> </tr> </c:forEach> </table> |
<script type="text/javascript"> $(function() { $('#btn-getbookList').on( 'click', function () { var pageIndex = parseInt($('input[name=pageIndex]' ).val()); var pageSize = parseInt($('input[name=pageSize]' ).val()); getBookList(pageIndex, pageSize); }); }); function getBookList(pageIndex, pageSize) { $.post("html", { pageIndex : pageIndex, pageSize : pageSize }, function(htmlResult) { $( '#bookPage').html(htmlResult); }); } </script > <label>Page Index</label> <input name ="pageIndex" type="number" /> <br/> <label>Page Size</label> <input name ="pageSize" type="number" value="3"/> <br/> <input type ="button" id="btn-getbookList" value="GetBookList"/> <fieldset> <legend>Book List page </legend> <div id="bookPage" ></div> </fieldset> |
방법 | 장점 | 단점 |
Ajax + JSON | 1. 데이터 전송량이 작다 2. client에서 html을 처리하기 때문에 server의 부하가 작다 | 1. javascript로 html을 만들어줘야지 되기 때문에 코드 작성에 어려움이 있다. |
Ajax + HTML | 1. HTML + Server 코드이기 때문에 코드 작성이 간편하다 | 1. 데이터 전송량이 많다. 2. 서버에서 html rendering이 되기 때문에 server의 부하가 발생한다. |