IT/development

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

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

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

 

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

 

[jQuery] jQuery.ajax() 사용법 예시(feat. 댓글 페이지네이션) - undefined - jQuery .ajax() 😄
반응형

댓글