maybeCafe -3-

하파타카·2022년 5월 5일
0

할 일

  • 페이징 및 페이지네이션
  • 시큐리티(로그인) 구상하기

페이징

PagingVO라는 entity를 새로 만들어 현재페이지, 시작페이지, 끝페이지, 총 개시글수, 페이지당 글 갯수, 마지막페이지,

페이징 참고

기본적으로 수업시간의 bbs프로젝트에서 사용했던 방법을 끌어올 예정.
검색기능에 대한 부분은 추후 같은방식으로 할지 다르게 해볼지 고민해보기.

PageVO 클래스

- PageVO -

public class PageVO {
	private int pageNum;	// 현재페이지
	private int amount;		// 한 페이지의 게시글 수
	private int skip;		// 스킵할 게시글 수 ((page - 1) * amount)
	
	// 기본생성자 => 기본세팅: pageNum = 1, amount = 10
	public PageVO() {
		this(1, 10);
	}
	
	public PageVO(int pageNum, int amount) {
		this.pageNum = pageNum;
		this.amount = amount;
		this.skip = (pageNum - 1) * amount;
	}
	
	public int getPageNum() {
		return pageNum;
	}
	
	// 새로 페이지 수를 설정했을 때 skip도 계산
	public void setPageNum(int pageNum) {
		this.pageNum = pageNum;
		this.skip = (pageNum - 1) * amount;
	}
	
	public int getAmount() {
		return amount;
	}
	
	// 페이지 당 데이터 갯수를 바꿀때에도 skip을 다시 계산
	public void setAmount(int amount) {
		this.amount = amount;
		this.skip = (pageNum - 1) * amount;
	}
	
	public int getSkip() {
		return skip;
	}
	
	public void setSkip(int skip) {
		this.skip = skip;
	}

	@Override
	public String toString() {
		return "PageVO [pageNum=" + pageNum + ", amount=" + amount + ", skip=" + skip + "]";
	}
}

뛰어넘을 게시글 수 skip은 현재 페이지pageNum과 한 페이지당 게시글 수amount를 기준으로 계산하여 구하는 값이므로 두 멤버변수의 값이 바뀔 때마다 새로 산출해야 함.

생성자의 this(1, 10)은 멤버변수인 pageNum과 amount에 초기값을 설정해준다.
skip은 계산으로 구하는 변수이므로 초기값할당 안함.

=> 생성자는 멤버변수를 초기화하는 역할을 한다. java의 this와 생성자에 대한 용법은 링크 참고.


페이징 쿼리문 작성

- StudyBoardMapper.interface -

public List<StudyBoardVO> getListPaging(PageVO page);	// 페이징을 적용한 전체 게시글 가져오기. pageNum과 amount를 입력받아 객체 page생성. 없으면 기본값(1, 10) 적용.

기존의 전체게시글 조회는 두고 추가로 작성.
기존 메서드는 페이지네이션까지 적용 후 주석or삭제.

- StudyBoardMapper.xml -

<!-- 페이징 적용 게시판 목록 -->
<select id="getListPaging" resultType="StudyBoardVO">
	SELECT * FROM (
		SELECT sno, title, writer, regdate, updatedate, hit, like_no
		FROM studyboard ORDER BY sno DESC) as T1
	LIMIT #{skip}, #{amount}
</select>

JUnit5 테스트

- StudyBoardMapperTest -

@Test
public void testGetListPaging() {
	PageVO page = new PageVO();
	List<StudyBoardVO> list = sBoardMapper.getListPaging(page);
	list.forEach(board -> log.info("" + board));
}

여기서는 new PageVO()에 따로 값을 넣지않아 생성자의 기본값인 (1, 10)으로 페이징이 적용됨.
만약 현재 페이지와 한 페이지당 게시글 수를 변경하고싶다면 new PageVO(2, 5)처럼 생성자에 값을 지정해주면 됨.
new PageVO(pageNum, amount)임을 참고.


가장 마지막 번호의 게시글부터 10개의 게시글이 출력됨을 확인.


service에 페이징 적용

- StudyBoardService.interface -

public List<StudyBoardVO> getListPaging(PageVO page);	// 페이징 적용 게시글목록

- StudyBoardServiceImpl -

@Override
public List<StudyBoardVO> getListPaging(PageVO page) {
	// 페이징 적용 공부게시판 전체 가져오기 
	return sBoardMapper.getListPaging(page);
}

- StudyBoardController -

@GetMapping("/list")
public String studyListGET(PageVO page, Model model) {
	model.addAttribute("studyboard", sBoardService.getListPaging(page));
	return "studyBoard/studyList";
}

앞서 사용하던 studyListGET메서드는 주석처리or삭제 후 페이징이 적용된 버전으로 추가.

테스트

http://localhost:8080/studyboard/list

페이징이 적용되어 10개의 게시글만 출력됨.

http://localhost:8080/studyboard/list?pageNum=2&amount=12

pageNum과 amount의 값을 주소창에 직접 기입해 값을 변경하는것도 가능.


페이지네이션

PageMakerDTO클래스 생성

- PageMakerDTO -

@Data
public class PageMakerDTO {
	private int startPage;		// 시작 페이지
	private int endPage;		// 끝 페이지
	private boolean prev, next;	// 이전, 다음페이지 존재유무
	private int total;			// 전체 게시글 수
	private PageVO pageVo;		// 현재 페이지, 페이지당 게시글 표시 수 정보
	
	public PageMakerDTO(int total, PageVO page) {
		this.total = total;
		this.pageVo = page;
		
		// 마지막 페이지(현제 페이지네이션바의 마지막 숫자): 10 단위로 표시 1~10, 11~20
		// Math.ceil은 올림함수
		this.endPage = (int)(Math.ceil(pageVo.getPageNum() / 10.0)) * 10;
		
		// 시작 페이지
		this.startPage = this.endPage - 9;
		
		// 실제 마지막 페이지 (총 마지막 페이지)
		int realEnd = (int)(Math.ceil(total * 1.0 / pageVo.getAmount()));
		
		// 전체 마지막 페이지(realEnd)가 화면에 보이는 마지막 페이지(endPage)보다 작은 경우
		if (realEnd < this.endPage) {
			this.endPage = realEnd;		// 화면에 보일 마지막 페이지를 전체 마지막 페이지로 변경
		}
		
		// < 이전페이지 참? 시작 페이지(startPage)값이 1보다 큰 경우 true
		this.prev = this.startPage > 1;
		
		// < 다음페이지 참? 마지막 페이지(endPage)값이 1보다 큰 경우 true
		this.next = this.endPage < realEnd;
	}
}

페이지 계산을 위한 클래스.
페이지네이션바에 나타날 시작페이지startPage, 페이지네이션바에 나타날 끝페이지endPage를 계산.

전체 첫페이지는 1부터로 고정일 수 밖에 없으며, 전체 마지막페이지는 페이지네이션과는 관계없으므로(이 부분은 페이징에서 처리) 여기서 시작페이지와 끝페이지는 페이지네이션바에 노출될 페이지수를 칭함.

총 게시글 수 구하기

- StudyBoardMapper.interface -

public int getTotal();		// 게시글 총 갯수

- StudyBoardMapper.xml -

<!-- 게시글 총 갯수 -->
<select id="getTotal" resultType="int">
	SELECT count(*) FROM studyboard 
</select>

studyboard테이블에 저장된 데이터의 총 갯수를 구함.

JUnit5 테스트

- StudyBoardMapperTest -

@Test	// 총 게시글 구하기
public void testGetTotal() {
	int result = sBoardMapper.getTotal();
	log.info("총 게시글 수: " + result);
}


총 게시글 수를 구하는 테스트.

service에 페이지네이션 적용

- StudyBoardService.interface -

public int getTotal();		// 게시글 총 갯수

- StudyBoardServiceImpl -

@Override
public int getTotal() {
	// 전체 게시글 수
	return sBoardMapper.getTotal();
}

Controller

- StudyBoardController -

@GetMapping("/list")
public String studyListGET(PageVO page, Model model) {
	model.addAttribute("studyboard", sBoardService.getListPaging(page));
	
	int total = sBoardService.getTotal();
	PageMakerDTO pmk = new PageMakerDTO(total, page);
	
	model.addAttribute("pmk", pmk);
	return "studyBoard/studyList";
}

view

- studyList.html -

<nav th:if="${pmk.endPage > 0}">
  <ul>
    <li>
      <a href="javascript:;">
        <span>이전</span>
      </a>
    </li>

    <li class="page-item" th:each="number : ${#numbers.sequence(1,pmk.endPage)}">
      <a class="page-link" href="javascript:;" th:text="${number}"></a>
    </li>

    <li>
      <a href="javascript:;">
        <span>다음</span>
      </a>
    </li>
  </ul>
</nav>

number는 컨트롤러에서 넘어온 pmk.endPage의 값을 이용해 얻은 임시적인 변수.
Thymeleaf의 문법 numbers.sequence을 사용하여 얻은 수.
참고

number의 값은 forEach문을 통해 얻었으므로 반복문 내에서만 사용할 수 있는 지역변수이다.

=> 1부터 endPage의 값까지 forEach문으로 반복시

테스트

http://localhost:8080/studyboard/list

현재 총 게시글 수가 34개이므로 한 페이지당 10개의 게시글을 보여준다고 했을때 총 4페이지가 나오는게 맞음.

profile
천 리 길도 가나다라부터

0개의 댓글