본문 바로가기

반응형
검색 > 페이징 > AJax > 파일 업/다운로드

 

Ajax란?

Ajax는 비동기 방식으로 동작하는 웹 애플리케이션의 핵심 기술 중 하나로, JavaScript를 이용하여 웹 페이지가 서버와 비동기적으로 데이터를 교환할 수 있게 합니다. 이를 통해 페이지의 새로고침 없이도 동적으로 데이터를 갱신하고 사용자와 웹 서버 간의 원활한 상호작용을 가능케 합니다.

비동기 방식이란?

비동기 방식은 어떤 작업이 다른 작업의 진행에 영향을 주지 않고 독립적으로 수행되는 방식을 말합니다. Ajax에서 비동기 방식은 데이터를 서버로부터 받아오거나 서버에 전송할 때, 웹 페이지의 다른 부분이나 사용자의 다른 동작을 방해하지 않고 동작할 수 있도록 하는 것을 의미합니다. 이를 통해 사용자는 다른 작업을 할 수 있으면서도 필요한 데이터를 서버로부터 받아올 수 있습니다.

1. listPage.jsp 수정

<form id='delForm'>
	<!-- Ajax 적용시켜줄 영역 설정 -->
	<div id='listZone'>
    	<!-- 
        	기존 table 등의 코드들
		-->
    </div>
</form>

 

2. JQuery 작성

    $(function(){
        // 이전 코드

        // 검색 버튼 Ajax
        $('#searchBtn').on('click', function(event){
            event.preventDefault();

            $.ajax({
                url : 'ajaxList',
                type : 'post',
                data : $("#searchForm").serialize(),

            success : function(data){
            	$("#listZone").html(data);
            },
            error : function(){
            	alert('에러');
            }
            });
        });
    })

검색 버튼에 추가해줬었던 id를 이용해서 버튼으로써 작동하는 submit을 막고 Ajax를 실행 시켜줍니다. serialize()를 이용해서 간편하고 쉽게 data를 넘겨줄 수 있습니다!

3. ajaxList.jsp 작성

<%@ 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"%>

<c:set var="path" value="${ pageContext.request.contextPath }" />

    <button onclick='createBoardBtn(event)'>글쓰기</button>
    <button onclick='deleteBoardBtn(event)'>삭제</button>
    <table>
        <thead>
            <tr>
                <th><input type='checkbox' id='allChk'></th> <!-- 체크박스 -->
                <th>번호</th>
                <th>글쓴이</th>
                <th>제목</th>
                <th>만든 날짜</th>
                <th>수정 날짜</th>
                <th>조회수</th>
            </tr>
        </thead>

        <tbody>
            <c:forEach var="boardList" items="${boardList}">
                <tr>
                    <td><input type="checkbox" name="chkBox" value="${boardList.boardSeq}"></td>
                    <td>${boardList.boardSeq}</td>
                    <td>${boardList.writer}</td>
                    <td><a href="${path}/read/${boardList.boardSeq}">${boardList.title}</a></td> <!-- title -->
                    <td><fmt:formatDate value="${boardList.regDate}" pattern="yyyy-MM-dd" /></td>
                    <td><fmt:formatDate value="${boardList.uptDate}" pattern="yyyy-MM-dd" /></td>
                    <td>${boardList.viewCnt}</td>
                </tr>
            </c:forEach>
        </tbody>

        <tfoot>
            <tr>
                <td colspan="7">
                    <!-- **처음페이지로 이동 : 현재 페이지가 1보다 크면  [처음]하이퍼링크를 화면에 출력-->
                    <c:if test="${pager.curPage > 1}">
                    	<a href="javascript:list('1')">[처음]</a>
                    </c:if>

                    <!-- **이전페이지 블록으로 이동 : 현재 페이지 블럭이 1보다 크면 [이전]하이퍼링크를 화면에 출력 -->
                    <c:if test="${pager.curBlock > 1}">
                    	<a href="javascript:list('${pager.prevPage}')">[이전]</a>
                    </c:if>

                    <!-- **하나의 블럭에서 반복문 수행 시작페이지부터 끝페이지까지 -->
                    <c:forEach var="num" begin="${pager.blockBegin}" end="${pager.blockEnd}">
                        <!-- **현재페이지이면 하이퍼링크 제거 -->
                        <c:choose>
                            <c:when test="${num == pager.curPage}">
                            	<span style="color: red">${num}</span>&nbsp;
                            </c:when>
                            <c:otherwise>
                            	<a href="javascript:list('${num}')">${num}</a>&nbsp;
                            </c:otherwise>
                        </c:choose>
                    </c:forEach>

                    <!-- **다음페이지 블록으로 이동 : 현재 페이지 블럭이 전체 페이지 블럭보다 작거나 같으면 [다음]하이퍼링크를 화면에 출력 -->
                    <c:if test="${pager.curBlock <= pager.totBlock}">
                    	<a href="javascript:list('${pager.nextPage}')">[다음]</a>
                    </c:if>

                    <!-- **끝페이지로 이동 : 현재 페이지가 전체 페이지보다 작거나 같으면 [끝]하이퍼링크를 화면에 출력 -->
                    <c:if test="${pager.curPage < pager.totPage}">
                    	<a href="javascript:list('${pager.totPage}')">[끝]</a>
                    </c:if>
                </td>
            </tr>
        </tfoot>

    </table>

위와 같이 이전 JSP(listPage.jsp)에서 <div id='listZone'></div> 내에 있는 모든 코드들을 복사 붙여넣기를 했습니다. 이번에 제가 택한 방식은 따로 다른 JSP에 Ajax가 적용될 부분들의 코드를 옮겨오는 것입니다.
이 방식의 장점은 기존에는 JavaScript에서 다 적어줘야 했던 단점이 없다는 점입니다. 단축키 복사,붙여넣기 두 개면 끝나는 간단한 방식이죠. 단점으로는 유연성이 감소한다는 점입니다. 똑같은 코드가 양 쪽에 모두 적혀있다는 것은 수정을 할 때, 다른 한 쪽도 똑같이 수정해야 한다는 것을 의미합니다. 이는 유지보수성을 감소시킨다는 것을 의미하기도 합니다.

4. Controller 작성

    // 이전 코드
    @RequestMapping(value = "ajaxList")
    public String ajaxList(Model model, @RequestParam Map<String, Object> param) {
        BoardPager pager1 = new BoardPager();

        int totalCount = boardSer.boardsNum(param); // 총 게시글 수
        pager1.setTotPage(totalCount); // 총 페이지 수 setter
        int totalPage = pager1.getTotPage(); // 총 페이지 수 getter
        int pageNum = 0;
        // Default 페이지 설정
        if (param.get("pageNum") == null || Integer.parseInt(param.get("pageNum").toString()) == 1) {
        	pageNum = 1;
        } else {
        	pageNum = Integer.parseInt(param.get("pageNum").toString());
        }

        if (pageNum > totalPage)
        	pageNum = totalPage;
        if (pageNum < 1)
        	pageNum = 1;

        BoardPager pager2 = new BoardPager(totalCount, pageNum);
        int startRow = pager2.getPageBegin();
        int endRow = pager2.getPageEnd();

        param.put("startRow", startRow);
        param.put("endRow", endRow);

        List<Map<String, Object>> boardList = boardSer.getList(param);

        model.addAttribute("pager", pager2);
        model.addAttribute("boardList", boardList);

        return "ajaxList";
    }

적용 시켜줄 부분이 게시글 리스트에 해당하는 것이니 그에 관한 코드들을 함께 적어줍니다. (List 출력, 페이징 적용)
참고로 이 때엔 @RequestBody 어노테이션을 쓰지 않습니다!

5. 결과

Ajax 결과물

후기

이번 Ajax는 기존의 CRUD 코딩보다는 오래 걸리고 실수도 많을 것이라고 생각했는데 수정할 것도 크게 없었고, 대부분이 복사, 붙여넣기라서 크게 어려울 것은 없었습니다.
어노테이션 @RequestBody 사용 여부가 헷갈려서 잠시 헤맸으나, 다시 찾아보고 언제 사용하고 언제 사용 안 하는지 확실히 알게 됐습니다.

컨트롤러에서 기존 리스트 화면을 보여주는 메소드와 이번 Ajax 메소드가 많은 부분이 일치해서 마음이 불편하군요.. 그래서 아래에 제가 따로 코딩을 해봤습니다! 선배님들은 어떻게 생각하시는지 모르겠습니다... 괜찮나요??

다음엔 파일 업로드로 찾아뵙겠습니다. 빠잇~!

 

 

더보기

 

// 공통 메소드
private BoardPager setupPager(Map<String, Object> param) {
    BoardPager pager = new BoardPager();

    int totalCount = boardSer.boardsNum(param);
    pager.setTotPage(totalCount);
    int totalPage = pager.getTotPage();
    
    int pageNum = param.get("pageNum") == null ? 1 : Integer.parseInt(param.get("pageNum").toString());

    pageNum = Math.min(Math.max(1, pageNum), totalPage);

    pager = new BoardPager(totalCount, pageNum);
    int startRow = pager.getPageBegin();
    int endRow = pager.getPageEnd();

    param.put("startRow", startRow);
    param.put("endRow", endRow);

    return pager;
}

// 기존 리스트 페이지 컨트롤러
@RequestMapping(value = "/list", method = RequestMethod.GET)
public String list(Model model, @RequestParam Map<String, Object> param) {
    BoardPager pager = setupPager(param);
    
    List<Map<String, Object>> boardList = boardSer.getList(param);
    
    model.addAttribute("pager", pager);
    model.addAttribute("boardList", boardList);

    return "listPage";
}

// Ajax 컨트롤러
@RequestMapping(value = "ajaxList")
public String ajaxList(Model model, @RequestParam Map<String, Object> param) {
    BoardPager pager = setupPager(param);

    List<Map<String, Object>> boardList = boardSer.getList(param);

    model.addAttribute("pager", pager);
    model.addAttribute("boardList", boardList);

    return "ajaxList";
}
반응형

'Spring > CRUD Project' 카테고리의 다른 글

[CRUD] 파일 업로드 및 조회 2 : 수정 및 출력  (1) 2023.12.05
[CRUD] 파일 업로드 및 조회  (1) 2023.12.04
[CRUD] 페이징  (0) 2023.11.29
[CRUD] 검색  (1) 2023.11.28
[CRUD] Delete : 글 삭제하기  (1) 2023.11.27
댓글