본문 바로가기
개발/Spring 블로그 만들기

Spring 블로그 만들기 - 9. 페이징(pagination)

by 똘똘이박사 2019. 2. 26.



이 포스팅의 샘플 게시판 개발 환경은 MAC OS, STS, OpenJDK11 입니다.


페이징 처리에 대한 포스팅은 아래와 같은 순서로 진행합니다.

  1. 페이징 테스트를 위한 데이터 만들기

  2. Pagination 클래스 만들기

  3. 게시판 목록 조회 SQL의 수정 및 전체 게시글 수 알아오기

  4. 총 개시글 개수 확인을 위한 BoardDAO, BoardService의 수정(메소드 추가)

  5. BoardController의 수정

  6. 게시글을 읽어 오기 위한 BoardDAO, BoardService의 수정(getBoardList 메소드 수정)

  7. 게시판 목록 화면(index) 수정


블로그 만들기 - 9. 페이징(pagination)


게시물의 글이 많아 지면 그만큼 스크롤도 길어지지만 서버로 부터 읽어와야 하는 데이터의 양도 많아 지게 됩니다.

따라서 페이지 로딩에 걸리는 시간이 늘어나게 되고, 페이지도 한 번에 보기 힘들어 지게 됩니다.

한 페이지에는 사용자들이 보기 적당할 정의 데이터를 출력해 주는 것이 좋습니다.

이럴 경우 게시판 목록에 페이징을 적용하여 필요한 만큼만의 데이터를 보여줍니다.



이번 포스팅에서 우리가 만들어 볼 페이징을 적용한 게시판 입니다.


페이징을 적용하기 전에 우선 해야할 작업이 있습니다.

지난번 예외처리와 트랜잭션 처리를 위해 의도적으로 에러를 만들도록 수정했던 BoardServiceImpl.java를 원상 복구 합니다.


BoardServiceImpl.java - getBoardContent() 메소드 수정(원상복구)

@Transactional

@Override

public BoardVO getBoardContent(int bid) throws Exception{

BoardVO boardVO = new BoardVO();

 

boardDAO.updateViewCnt(bid);

boardVO = boardDAO.getBoardContent(bid);        //주석을 풀어 줍니다.

  //   예외처리 테스트가 끝났으므로 아래 구문은 삭제 하거나 주석 처리 합니다.

//    try {

// boardVO.setBid(bid);

// boardVO.setCate_cd("1111111111111111111111111111111111111");

// boardDAO.updateBoard(boardVO);

// } catch (RuntimeException e) {

// throw new NotFoundException();

// }


return boardVO;

}


두번째 해야할 사전 작업은 페이징을 테스트 할 충분한 데이터를 만들어 내는 것입니다.

페이징을 테스트하기 위해 기존의 데이터는 모두 삭제하고, 새로운 데이터를 대량생산해 보도록 하겠습니다.



페이징 테스트를 위한 데이터 만들기

데이터를 만들기 전에 기존의 데이터들을 삭제하고, 게시판 번호(bid)를 초기화 시킵니다.

데이터베이트 툴을 이용해 아래의 명령을 실행 합니다.


DELETE FROM tbl_board;

ALTER TABLE tbl_board AUTO_INCREMENT = 1;


테스트할 대량의 데이터를 만들기 위해 기존에 만들어 놓았던 DAO 테스트를 이용합니다.

기존에 만든 BoardDAOTest.java 파일을 열어 아래와 같이 수정합니다.

(BoardDAOTest.java 는 '여기' 를 클릭하여 확인 할 수 있습니다.)


기존의 데이터를 모두 지우고 게시판번호(bid)를 초기화 하는 이유는

페이징 이동시 데이터 확인을 좀더 편하게 하기 위해서 입니다.

따라서 데이터 삭제와 게시판 번호(bid) 초기화를 건너 띄어도 상관이 없습니다.


BoardDAOTest.java - testInsertBoard() 수정

@Test @Ignore 

public void testInsertBoard() throws Exception {

BoardVO boardVO = new BoardVO();


boardVO.setCate_cd("1");

// boardVO.setTitle("첫번째 게시물 입니다.");

// boardVO.setContent("첫번째 게시물입니다.");

boardVO.setTag("1");

boardVO.setReg_id("1");


   for( int i = 1; i < 1234 ; i++) {

    boardVO.setTitle(i + " 번째 게시물 입니다.");

    boardVO.setContent(i + " 번째 게시물 입니다.");

    int result = boardDAO.insertBoard(boardVO);


logger.info("\n Insert Board Result " +result);


if(result == 1) {

logger.info("\n 게시물 등록 성공 ");

} else {

logger.info("\n 게시물 등록 실패");

}

  }

}


이렇게 하면 1233개의 테스트 데이터가 만들어 집니다.

제목과 내용 부분에 몇 번째 게시물인지 표시하여 페이징 테스트를 할때 보기 편하도록 데이터를 입력하였습니다.




Pagination 클래스 만들기

우선 페이징을 할때 화면에 어떻게 보여질지 그려봅니다. 그리고 어떤 값들이 필요한지 살펴 봅니다.



위 그림은 페이징에 필요한 요소들을 정리한 내용입니다.

각 요소의 의미와 변수명 등은 아래 표와 같습니다.


구분

변수명

타입

의미

 현재 페이지

 page 

 int 

 현재 목록의 페이지 번호 

 현재 페이지 범위

 range

 int 

 각 페이지 범위 시작 번호 

 총 게시물의 개수

 listCnt 

 int 

 전체 개시물의 개수 

 총 페이지 범위의 개수

 pageCnt 

 int 

 전체 페이지 범위의 개수 

 한 페이지 목록의 개수

 listSize

 int

 한 페이지당 보여질 리스트의 개수 

 한 페이지 범위의 개수 

 rangeSize 

 int

 한 페이지 범위에 보여질 페이지의 개수 

 시작번호

 startPage 

 int 

 각 페이지 범위 시작 번호 

 끝 번호

 endPage

 int

 각 페이지 범위 끝 번호

 이전 페이지 

 prev

 boolean 

 이전 페이지 여부 

 다음 페이지 

 next 

 boolean 

 다음 페이지 여부 


위 그림을 바탕으로 기본적인 페이징을 할 Pagination 클래스를 만들어 보겠습니다.

Pagination 클래스는 프로젝트 모든 곳에 쓰이는 클래스 이므로 별도의 페키지를 만들어 따로 분리 시키도록 하겠습니다.

아래 그림과 같이 com.freehoon.web.common 이라는 페키지를 생성하고, 그 아래 Pagination.java 라는 클래스 파일을 생성합니다.



Pagination.java 추가

package com.freehoon.common;


public class Pagination {


private int listSize = 10;                //초기값으로 목록개수를 10으로 셋팅

private int rangeSize = 10;            //초기값으로 페이지범위를 10으로 셋팅

private int page;

private int range;

private int listCnt;

private int pageCnt;

private int startPage;

private int startList;

private int endPage;

private boolean prev;

private boolean next;

public int getRangeSize() {

return rangeSize;

}


public int getPage() {

return page;

}


public void setPage(int page) {

this.page = page;

}


public int getRange() {

return range;

}


public void setRange(int range) {

this.range = range;

}


public int getStartPage() {

return startPage;

}


public void setStartPage(int startPage) {

this.startPage = startPage;

}


public int getEndPage() {

return endPage;

}


public void setEndPage(int endPage) {

this.endPage = endPage;

}


public boolean isPrev() {

return prev;

}


public void setPrev(boolean prev) {

this.prev = prev;

}


public boolean isNext() {

return next;

}


public void setNext(boolean next) {

this.next = next;

}


public int getListSize() {

return listSize;

}


public void setListSize(int listSize) {

this.listSize = listSize;

}

public int getListCnt() {

return listCnt;

}


public void setListCnt(int listCnt) {

this.listCnt = listCnt;

}

public int getStartList() {

return startList;

}


public void pageInfo(int page, int range, int listCnt) {

this.page = page;

this.range = range;

this.listCnt = listCnt;

//전체 페이지수 

this.pageCnt = (int) Math.ceil(listCnt/listSize);

//시작 페이지

this.startPage = (range - 1) * rangeSize + 1 ;

//끝 페이지

this.endPage = range * rangeSize;

//게시판 시작번호

this.startList = (page - 1) * listSize;

//이전 버튼 상태

this.prev = range == 1 ? false : true;

//다음 버튼 상태

this.next = endPage > pageCnt ? false : true;

if (this.endPage > this.pageCnt) {

this.endPage = this.pageCnt;

this.next = false;

}

}

}


Pagination 클래스에서 가장 눈여겨 살펴보아야 할 부분은 pageInfo 메소드 입니다.

pageInfo메소드는 는 3개의 파라미터를 받습니다.


pageInfo(int page, int range, int listCnt)


첫번째 인자 page 는 현재 페이지 정보 입니다.

두번째 인자 range 는 현재 페이지 범위 정보 입니다.

세번째 인자 listCnt는 게시물의 총 개수입니다.


우선 전달 받은 인자들을 프로퍼티에 셋팅을 합니다.


전달 받은 전체 게시물 개수(listCnt)와 기본값으로 설정한 한 페이지당 목록 개수(listSize)를 이용해 전체 페이지 개수(pageCnt)를 구합니다.

//전체 페이지수 

this.pageCnt = (int) Math.ceil(listCnt/listSize);



각 페이지 범위의 시작 번호를 구하는 방법입니다.

//시작 페이지

this.startPage = (range - 1) * rangeSize + 1 ;



각 페이지 범위의 마지막 번호를 구하는 방법입니다. 마지막 페이지의 번호를 구하는 이유는 다음에 나올 [다음] 버튼의 활성화 여부를 판단하기 위해서 입니다.

//끝 페이지

this.endPage = range * rangeSize;



게시판의 시작번호를 따로 구하는 이유는 현재 MySQL을 이용해 원하는 목록을 가져 오기 위해서 입니다.

이 부분에 대해서는 SQL 수정 부분에서 상세히 다루도록 하겠습니다.

//게시판 시작번호

this.startList = (page - 1) * listSize;



이전 버튼과 상세 버튼의 활성화 여부를 판단하는 구문입니다.

첫번째 페이지 범위 에서는 [이전] 버튼이 필요 없습니다. 따라서 페이지범위가 1일 때는 fales를 설정하고, 1이 아닐때 ture를 설정합니다. [다음] 버튼은 현재 페이지의 마지막 페이지 번호가 전체 페이지 개수 보다 크다면 활성화 하게 만듭니다.


그런데 마지막 페이지 번호를 작업할때 한가지 유의 사항이 있습니다.

위에서 마지막 번호를 구하는 공식은 시작 번호에 매칭시켜 무조건 페이지를 10개씩 만들어 냅니다. (pageSize가 10이므로)

따라서 시작 번호가 121인 페이지 범위의 마지막 번호가 아래 그림과 같이 130이 됩니다.



하지만 게시물의 갯수가 현재 1233 이므로 123 이 마지막 번호가 되어야 합니다.

마지막에 있는 if 구문은 마지막 번호화 페이지의 총 갯수를 비교하여 마지막 번호가 총갯수 보다 크다면 마지막 번호로 셋팅 되도록 한 구문입니다. 또한 다음 페이지에 대한 이동도 할 수 없으므로 [다음]버튼 상태를 비활성화 하도록 만듭니다.

//이전 버튼 상태

this.prev = range == 1 ? false : true;


//다음 버튼 상태

this.next = endPage > pageCnt ? false : true;

if (this.endPage > this.pageCnt) {

this.endPage = this.pageCnt;

this.next = false;

}



게시판 목록 조회 SQL 수정 및 전체 게시글 수 알아오기

게시판에 페이징을 적용하기 위해 기존에 작성했던 getBoardList 쿼리 문장에 한 줄을 추가해야 합니다.

MySQL에서는 페이징을 하기 쉽게 Limit 라는 명령어를 지원 합니다.


LIMIT 첫번째 ROW 위치, 읽어올 갯수


따라서 첫번째 글부터 총 10개의 게시글을 읽어 오고 싶다면 아래와 같이 작성할 수 있습니다.


LIMIT 0, 10


이때 주위 해야 할 점이 조회할 첫번째 글은 '1'이 아닌 '0' 입니다.

이 규칙을 정리하면 아래 그림과 같습니다.




간단히 정리 하면 ROW는 글번호에서 1을 뺀것과 같습니다.

따라서 각 페이지의 시작 번호는 0, 10, 20 과 같습니다.

즉 현재 '(페이지 번호 - 1) x 페이지 사이즈' 가 됩니다.

위 Pagination 클래스에서 각 페이지의 게시판 시작 번호(startList) 를 구하던 식은

이런 공식을 적용하여 만든 것 입니다.


//게시판 시작 번호

this.startList = (page - 1) * listSize;


이제 getBoardList 쿼리를 수정해 봅니다.


boardMapper.xml - getBoardList 수정(추가)

<select id="getBoardList" resultType="com.freehoon.web.board.model.BoardVO">

SELECT

BID, CATE_CD, TITLE, CONTENT, TAG, VIEW_CNT, REG_ID, REG_DT, EDIT_DT

FROM

TBL_BOARD

LIMIT #{startList}, #{listSize}

</select>


그리고 또 한 가지 쿼리를 추가 합니다.

전체 글의 개수를 읽어와 전체 페이지의 수를 개산해야 합니다.

따라서 전채 글의 개수를 읽어 오는 SQL문을 추가 합니다.


boardMapper.xml - getBoardListCnt 추가

<select id="getBoardListCnt" resultType="int">

SELECT

count(*) as listCnt

FROM

TBL_BOARD

</select>


글(row)을 얻어올 때는 count() 라는 함수를 사용합니다.



BoardDAO, BoardService의 수정

BoardDAO와 BoardService에 수정된 내용을 반영해야 합니다.

우선 각 단계에 게시글의 총 개수를 구해오는 클래스를 추가 합니다.


BoardDAO.java(interface) 추가

//총 게시글 개수 확인

public int getBoardListCnt() throws Exception;


BoardDAOImpl.java 추가

//총 게시글 개수 확인

@Override

public int getBoardListCnt() throws Exception {

return sqlSession.selectOne("com.freehoon.web.board.boardMapper.getBoardListCnt");

}


BoardService.java(interface) 추가

//총 게시글 개수 확인

public int getBoardListCnt() throws Exception;


BoardServiceImpl.java 추가

//총 게시글 개수 확인

@Override

public int getBoardListCnt() throws Exception {

return boardDAO.getBoardListCnt();

}




BoardController 수정

페이징 계산을 위해 Pagination 클래스에 보내야 할 파라미터에는 '현재 페이지'와 '현재 페이지 범위', 그리고 '게시물의 총 개수'가 있습니다. 

'현재 페이지'와 '현재 페이지 범위'는 화면에서 Get 방식으로 넘겨 받습니다. 하지만 처음 접속 할때는 현재 페이지의 번호나 페이지 범위 등이 없기 때문에 디폴트 값으로 받을 수 있도록 합니다. 

게시글의 총 개수는 위에서 만든 메소드를 호출하여 얻어올 수 있습니다.

이 세 가지 파라미터를 가지고 Pagination 객채를 생성하면 페이지의 시작 번호와 페이지의 총 개수 등도 알 수 있습니다.

생성된 Pagination에는 원하는 페이지의 첫번째 게시물의 Row을 담고 있으므로 getBoardList가 Pagination을 파라미터로 사용 할 수 있도록 기존 메소드를 수정 합니다.


BoardController.java 수정 (getBoardList() 메소드 수정)

@RequestMapping(value = "/getBoardList", method = RequestMethod.GET)

public String getBoardList(Model model

, @RequestParam(required = false, defaultValue = "1") int page

, @RequestParam(required = false, defaultValue = "1") int range

) throws Exception {

//전체 게시글 개수

int listCnt = boardService.getBoardListCnt();

    //Pagination 객체생성

Pagination pagination = new Pagination();

   pagination.pageInfo(page, range, listCnt);

model.addAttribute("pagination", pagination);

model.addAttribute("boardList", boardService.getBoardList(pagination));

return "board/index";

}



getBoardList메소드에 기존에 보지 못했던 새로운 파라미터를 사용하였습니다.

앞에서 언급 했던 '현재 페이지 번호' 와 '현재 페이지 범위' 를 get방식으로 받기 위해 사용하였습니다.

파라미터에 사용된 @RequestParam 어노테이션은 특정 파라미터를 View에서 전달 받을 수 있습니다. 또한 전달 받을 때 몇 가지 설정을 할 수 있는데 전달 받은 특정 파라미터가 필수값인지 여부와 데이터가 없을 경우 초기값을 셋팅 할 수 있습니다. 특정값을 지정 할 수 있는데 지정하지 않을 경우 뒤에 따라오는 파라미터 명과 일치 하는 값을 받습니다.

따라서 위의 구문을 해석해 보면


@RequestParam(required = false, defaultValue = "1") int page


라는 구문은 화면에서 보내온 데이터 중에 page를 받습니다. 

동시에 반드시 화면에서 넘어올 필요는 없으며(required = false) 

데이터가 없을 경우 기본값으로 "1"을 셋팅(defaultValue="1") 합니다.

'현재 페이지 범위' 값 역시 마찬가지 원리가 적용됩니다.


메소드는 이미 설명한 바와 같이 가장 먼저 '게시글의 총 개수'를 얻어와 listCnt 라는 변수에 저장을 합니다.


//전체 게시글 개수

int listCnt = boardService.getBoardListCnt();


그리고 View에서 전달받은 파라미터(현재 페이지, 현재 페이지 범위) 와 '전체 게시글 개수'를 가지고 페이지 정보를 생성합니다.


    //Pagination 객체생성 및 페이징 정보 셋팅

Pagination pagination = new Pagination();

    pagination.pageInfo(page, range, listCnt);


Pagination 객체는 View에서 화면 하단에 페이징을 할때 필요 하므로 model.addAttribute를 사용해 화면으로 보냅니다.

그리고 게시판 리스트는 원하는 페이지의 데이터를 읽어 올 수 있도록 페이징 정보(Pagination 객체)를 파라미터로 보낼 수 있게 수정을 합니다. 따라서 BoardService 와 BoardDAO의 getBoardList() 메소드가 Pagination 객체를 사용 할 수 있도록 모두 수정을 해야 합니다.


model.addAttribute("pagination", pagination);

model.addAttribute("boardList", boardService.getBoardList(pagination));




게시글을 읽어 오기 위한 BoardDAO, BoardService의 수정(getBoardList 메소드 수정)

원하는 페이지의 리스트를 읽어 올 수 있도록 게시판의 페이지 정보를 가지고 있는 Pagination 객체를 받을 수 있도록 BoardDAO와 BoardService를 모두 수정합니다.


BoardDAO.java(interface) 수정

public List<BoardVO> getBoardList(Pagination pagination) throws Exception;


BoardDAOImpl.java 수정

@Override

public List<BoardVO> getBoardList(Pagination pagination) throws Exception {

return sqlSession.selectList("com.freehoon.web.board.boardMapper.getBoardList", pagination);

}


BoardService.java(interface) 수정

public List<BoardVO> getBoardList(Pagination pagination) throws Exception;


BoardServiceImpl.java 수정

@Override

public List<BoardVO> getBoardList(Pagination pagination) throws Exception {

return boardDAO.getBoardList(pagination);

}




게시판 목록 화면(index) 수정

게시판 목록 화면의 하단에 페이지를 보여 줄 수 있도록 아래와 같이 페이징 처리 구문을 추가 합니다.


index.jsp(수정)

<script>

//이전 버튼 이벤트

function fn_prev(page, range, rangeSize) {

var page = ((range - 2) * rangeSize) + 1;

var range = range - 1;

var url = "${pageContext.request.contextPath}/board/getBoardList";

url = url + "?page=" + page;

url = url + "&range=" + range;

location.href = url;

}


  //페이지 번호 클릭

function fn_pagination(page, range, rangeSize, searchType, keyword) {

var url = "${pageContext.request.contextPath}/board/getBoardList";

url = url + "?page=" + page;

url = url + "&range=" + range;


location.href = url;

}


//다음 버튼 이벤트

function fn_next(page, range, rangeSize) {

var page = parseInt((range * rangeSize)) + 1;

var range = parseInt(range) + 1;

var url = "${pageContext.request.contextPath}/board/getBoardList";

url = url + "?page=" + page;

url = url + "&range=" + range;

location.href = url;

}

</script>

  // 생략

<div>

<button type="button" class="btn btn-sm btn-primary" id="btnWriteForm">글쓰기</button>

</div>


<!-- pagination{s} -->

<div id="paginationBox">

<ul class="pagination">

<c:if test="${pagination.prev}">

<li class="page-item"><a class="page-link" href="#" onClick="fn_prev('${pagination.page}', '${pagination.range}', '${pagination.rangeSize}')">Previous</a></li>

</c:if>

<c:forEach begin="${pagination.startPage}" end="${pagination.endPage}" var="idx">

<li class="page-item <c:out value="${pagination.page == idx ? 'active' : ''}"/> "><a class="page-link" href="#" onClick="fn_pagination('${idx}', '${pagination.range}', '${pagination.rangeSize}')"> ${idx} </a></li>

</c:forEach>

<c:if test="${pagination.next}">

<li class="page-item"><a class="page-link" href="#onClick="fn_next('${pagination.range}', 

'${pagination.range}', '${pagination.rangeSize}')" >Next</a></li>

</c:if>

</ul>

</div>

<!-- pagination{e} -->


</div>

</article>


Bootstrap을 이용해 페이징에 간단히 디자인을 적용하였습니다

아래 구문은 Bootstrap에서 사용되는 페이징에 대한 스타일 시트 기본 사용법 입니다.


<ul class="pagination">

<li class="page-item">...</li class="page-item">

</ul>


중간에 <c:forEach> 문을 이용해 페이지를 반복해서 출력해 줍니다. 

리스트에서 사용했던 <c:forEach> 와는 다르게 반복 시작 번호(begin)와 끝 번호(end)를 지정하여 반복을 할 수 있습니다.


<c:forEach begin="시작번호" end="끝번호" var="idx"></c:forEach>


[이전], [다음] 버튼의 경우는 약간의 계산식이 필요 합니다.

페이지 번호 클릭 할때와 같이 href 안에 주소와 계산식을 포함한 인자값들을 모두 처리 할 수 있지만

소스를 복잡해 지게되어 관리가 어렵습니다.

따라서 [이전][다음] 버튼의 클릭 이벤트와 페이지 번호를 클릭 하였을 경우 발생하는 클릭 이벤트를 별도의 스크립트로 분리 시켜 관리 하도록 하는 것이 좋습니다.

fn_prev는 [이전] 버튼에 대한 이벤트이고, fn_next는 [다음] 버튼에 대한 이벤트 입니다. fn_pagination 은 페이지 번호를 클릭하였을 경우 발생하는 이벤트 입니다.


[이전] 버튼과 [다음] 버튼의 활성화 여부는 Pagination 객체의 prev와 next 를 확인하여 처리 합니다.

[이전] 버튼의 경우 무조건 이전 페이지 범위의 가장 앞 페이지로 이동하게 하기 위해 아래와 같이 처리 합니다.


var page = ((range - 2) * rangeSize) + 1;


[다음] 페이지도 마찬가지로 다음 페이지 범위의 가장 앞 페이지로 이동 하도록 아래와 같이 처리 합니다.


var page = parseInt((range * rangeSize)) + 1;


이제 결과를 확인해 봅니다.


게시판에 처음 접속 했을때


두번째 페이지


세번째 페이지


[다음] 버튼 클릭


계속 [다음] 버튼을 클릭하여 마지막 페이지로 이동 하였을때




추가 : <c:url> 사용하기

웹페이지에서 다른 페이지나 자원을 참조할때 URL 주소를 사용하게 됩니다.

그런데 가만히 보면 중복되는 데이터가 상당히 많습니다.

위 게시판 리스트의 경우 아래와 같은 URL 이 계속 중복이 됩니다.


var url = "${pageContext.request.contextPath}/board/getBoardList";


따라서 위 주소를 공통 변수와 같이 선언해 필요한 곳에 가져다 쓰게 하는 것이 관리 면에서 여러가지 편리합니다.

이러한 방법에는 여러 가지가 있습니다.

<c:url>을 사용하는 방법입니다. <c:url>의 사용법은 아래와 같습니다.


<c:url var="getBoardListURL" value="/board/getBoardList">

</c:url>


위에서 문자열로 주소를 지정할 때 사용했던 Context Path 부분이 보이지 않습니다. <c:url> 에서는 이 부분을 자동으로 처리해 줍니다. 또한 같이 넘어가야할 파라미터들도 생성하여 보낼 수 있습니다. 


<c:url var="getBoardList" value="/board/getBoardList">

<c:param name="page" value="${pagination.page}"/>

<c:param name="range" value="${pagination.range}"/>

</c:url>


이와 같이 <c:url>을 페이지 상단에 선언해 두면 스크립트 부분의 URL 변수 선언쪽을 아래와 같이 간단하게 수정할 수 있습니다.


var url = "${getBoardList}";









※ 포스팅에 오타나 잘못된 부분, 추가적으로 더 알고 싶은 부분이 있으면 댓글 주세요~


반응형