IT/development

[jQuery] jQuery.ajax() 사용법 예시(feat. 댓글 페이지네이션)

알 수 없는 사용자 2022. 11. 21. 06:58
반응형

목차

     

    jQuery .ajax() 😄

    미래의 내가 보기 위해 남겨둠

    jQuery의 ajax 사용법만 간단히 남기려고 했으나 예시 코드에 있는 코드들도 같이 적는게 좋을 듯 싶어서 같이 남김

    // 예시
    $.ajax({
    	// 호출 url
        url: '/reply/insert',
        // 전달방식
        type: 'post',
        // dataType: "json"	// 데이터타입 json으로 할 경우
        // 전달할 데이터
        data: {'boardId': boardId, 'replyContent': replyContent, 'replyWriter': replyWriter},
        // 성공 시 콜백 함수, 밑에 실패 시 콜백도 만들어도 좋다.
        success: function (data) {
        getRelyList();
        }
    
    // 댓글 조회 예시
    function getRelyList(){
        let boardId = $("#boardId").val();
        $.ajax({
        url:'/reply/list',
        type:'get',
        // 게시글에 대한 댓글 목록이므로 boardId를 넘김 
        // 이렇게 조회해야 되서(SELECT * FROM reply WHERE board_id = #{boardId})
        data:{'boardId':boardId},
        success:function(data){
        // 댓글 페이지네이션 처리를 위한 변수(이전, 다음 존재여부, 시작~끝값)
        let prev = data.pageMaker.prev;
        let next = data.pageMaker.next;
        let startPage = data.pageMaker.startPage;
        parseInt(startPage);
        let isPrev = startPage - 1;
        let endPage = data.pageMaker.endPage;
        parseInt(endPage);
        let isNext = endPage + 1;
    
        // console.log('prev : ' + prev + '\n' + 'next : ' + next + '\n' + 'startPage : ' + startPage + '\n' + 'endPage : ' + endPage);
        // 서버에서 가져온 댓글 데이터를 $.each로 루프 돌려서 <div id="replyList">여기에 넣음</div>
        let replyHtml = "";
        $.each(data.replyList,function(key,value){
        replyHtml += '<div>';
        replyHtml += '<div>' + '댓글번호:'+ value.replyId+ ' / 작성자:' + value.replyWriter + ' / 작성일: ' + value.regDate;
        // click 이벤트안에 parameter 넣을 때 ""안에 ''를 붙여줘야 함(이게 처음 할 땐 은근히 스트레스)
        replyHtml += '<button onclick="replyUpdateForm('+ value.replyId +',\'' + value.replyContent + '\');">수정</button>';
        replyHtml += '<button onclick="replyDelete(' + value.replyId + ');">삭제</button></div>';
        replyHtml += '<div id="replyContentArea"><p>내용:'+value.replyContent+'</p>';
        replyHtml += '</div>';
    });
        $("#replyList").html(replyHtml);
        // 페이지네이션 표시
        viewPagination(boardId, prev, next, startPage, endPage, isPrev, isNext);
    }});
    }
    
    // 페이지네이션 처리(어떤 식으로 하는 원리만 알기 위한 예제라서 간단하게 함)
    function viewPagination(boardId, prev, next, startPage, endPage, isPrev, isNext) {
        // console.log('prev: ' + prev + '\n' + 'next: ' + next + '\n' + 'startPage: ' + startPage + '\n' + 'endPage: ' + endPage + '\n' + 'isPrev: ' + isPrev + '\n' + 'isNext: ' + isNext);
        // 페이지네이션 영역
        let replyPagination = "";
    	// 이전 페이지
        if (prev == true) {
            replyPagination += '<li>';
            replyPagination += '<a href="/reply/list?boardId=' + boardId + '&pageNum=' + isPrev +'">' + "Prev" + '</a>';
            replyPagination += '</li>';
        }
        for (let num = startPage; num <= endPage; num++) {
            replyPagination += '<li>';
            replyPagination += '<a href="/reply/list?boardId=' + boardId + '&pageNum=' + num +'">' + num + '</a>';
            replyPagination += '</li>';
        }
        // 다음 페이지
        if (next == true && endPage > 0) {
            replyPagination += '<li>';
            replyPagination += '<a href="/reply/list?boardId=' + boardId + '&pageNum=' + isNext +'">' + "Next" + '</a>';
            replyPagination += '</li>';
        }
        // 페이지네이션 영역을 div에 붙임
        $("#reply-pagination").html(replyPagination);
    }
    
    
    // 댓글 리스트 영역
    <div class="container">
    <div id="replyList"></div>
    </div>
    
    // 댓글 페이지네이션 영역
    <div>
    <ul id="reply-pagination" class="pagination pagination-sm no-margin pull-right"></ul>
    </div>

     

    controller

    // boardId와 Criteria를 받아서 댓글 목록 반환
    @GetMapping("/reply/list")
    @ResponseBody
        public Map<String, Object> replyListPaging(@RequestParam("boardId") Long boardId, Criteria cri) {
            Map<String, Object> map = new HashMap<>();
            List<ReplyVO> replyList = replyService.findReplyListPaging(boardId, cri);
            int replyCount = replyService.findCount(boardId);
            // 댓글 목록
            map.put("replyList", replyList);
            // 페이지네이션 화면 처리 데이터
            map.put("pageMaker", new PageMaker(replyCount, cri));
            return map;
        }

     

    service

    package paging.study.service;
    
    import lombok.RequiredArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    import paging.study.domain.Criteria;
    import paging.study.domain.vo.ReplyVO;
    import paging.study.mapper.ReplyMapper;
    
    import java.util.List;
    
    @Service
    @RequiredArgsConstructor
    @Slf4j
    @Transactional(readOnly = true)
    public class ReplyService {
    
        private final ReplyMapper replyMapper;
    
    
        public List<ReplyVO> findReplyListPaging(Long boardId, Criteria cri) {
            return replyMapper.findReplyListPaging(boardId, cri);
        }
    
        public int findCount(Long replyId) {
            return replyMapper.findCount(replyId);
        }
    }

     

    mapper

    package paging.study.mapper;
    
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Param;
    import paging.study.domain.Criteria;
    import paging.study.domain.vo.ReplyVO;
    
    import java.util.List;
    
    @Mapper
    public interface ReplyMapper {
    
        List<ReplyVO> findReplyListPaging(@Param("boardId") Long boardId, @Param("cri") Criteria cri);
        int findCount(Long boardId);
    }

     

    mapper xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="paging.study.mapper.ReplyMapper">
        <resultMap id="replydMap" type="paging.study.domain.vo.ReplyVO">
            <id column="reply_id" property="replyId"/>
            <result column="board_id" property="boardId"/>
            <result column="reply_content" property="replyContent"/>
            <result column="reply_writer" property="replyWriter"/>
            <result column="reg_date" property="regDate"/>
            <result column="update_date" property="updateDate"/>
        </resultMap>
    
        <select id="findReplyListPaging" parameterType="map" resultMap="replydMap">
            SELECT * FROM t_reply
            WHERE board_id = #{boardId}
            ORDER BY reg_date DESC
            limit #{cri.limitStart}, #{cri.amount}
        </select>
    
        <select id="findCount" parameterType="Long" resultType="int">
            SELECT COUNT(*) FROM t_reply
            WHERE board_id = #{boardId}
        </select>
    </mapper>

     

    ReplyVO

    package paging.study.domain.vo;
    
    
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;
    import lombok.ToString;
    
    import java.time.LocalDateTime;
    
    // 댓글 용도
    @Getter @Setter
    @ToString
    @NoArgsConstructor
    public class ReplyVO {
    
        private Long replyId;
        private Long boardId;
        private String replyContent;
        private String replyWriter;
        private LocalDateTime regDate;
        private LocalDateTime updateDate;
    
        public ReplyVO(Long boardId, String replyContent, String replyWriter) {
            this.boardId = boardId;
            this.replyContent = replyContent;
            this.replyWriter = replyWriter;
        }
    }

     

    Criteria

    package paging.study.domain;
    
    import lombok.Getter;
    import lombok.Setter;
    import lombok.ToString;
    
    @Getter @Setter
    @ToString
    public class Criteria {
    
        // for paging
        private int pageNum;        // 페이지 번호(현재 페이지가 몇 페이지인지)
        private int amount;         // 한 화면에 출력한 페이지 개수
        private int limitStart;             // 쿼리에서 (pageNum -1) * amount 사용하기 위한 변수
    
        // for search
        private String title;
        private String name;
        
    	// 기본 생성자에서 강제로 페이지 번호와 출력 페이지 수 세팅(페이지네이션 정책에 따라 변경하면 됨)
        public Criteria() {
            this(1,10);
        }
    
        public Criteria(int pageNum, int amount) {
            this.pageNum = pageNum;
            this.amount = amount;
        }
        
         // 쿼리에서 limit 1번 째 parameter로 쓸 값(mybatis에서 이 getter 이용해서 값을 )
        public int getLimitStart() {
            return this.limitStart = (pageNum - 1) * this.amount;
        }
    }

     

    PageMaker

    package paging.study.domain.paging;
    
    import lombok.Getter;
    import lombok.ToString;
    import paging.study.domain.Criteria;
    
    @Getter @ToString
    // 실제 페이지네이션 화면 처리 계산 담당(공통 모듈)
    public class PageMaker {
        private int startPage;  //페이징 화면 하단의 시작 번호(5페이지라고 하면 [1][2][3][4][5] 여기서 제일 첫 번 째 시작번호인 [1])
        private int endPage;    //페이징 화면 하단의 끝 번호(5페이지라고 하면 [1][2][3][4][5] 여기서 제일 끝 번호인 [5])
        private boolean prev, next;     // 이전, 다음 존재 여부
    
        private int totalCount;         // 전체 게시글 수
        private Criteria cri;      // 프론트에서 전달하는 pageNum(현재 페이지), amount(출력 페이지) 전달 역할
    
        public PageMaker(int totalCount, Criteria cri) {
            this.totalCount = totalCount;
            this.cri = cri;
    		
            this.endPage = (int)(Math.ceil(cri.getPageNum() / 10.0) * 10);
            this.startPage = this.endPage - 9;
            // 실제 끝 번호
            int realEnd = (int)(Math.ceil(totalCount * 1.0) / cri.getAmount());
    
            if (realEnd < this.endPage) {
                this.endPage = realEnd;
            }
    
            this.prev = this.startPage > 1;
            this.next = this.endPage < realEnd;
        }
    }

     

    댓글 table

    -- 댓글
    CREATE TABLE t_reply(
                            reply_id bigint auto_increment,
                            board_id bigint,
                            reply_content varchar (30),
                            reply_writer varchar (30),
                            reg_date timestamp,
                            update_date timestamp,
                            primary key(reply_id)
    );

    jQeury에서 ajax를 어떤 식으로 쓰는지 알기 위한 간단한 예제임

    to 미래의 너 그대로 가져다 쓰진 말고 수정해서 쓰는걸 권장함(유지보수나 확장성 등을 고려하고 짠 소스가 아님)

     

    반응형