๐Ÿ’ป PROJECT/[์Šคํ”„๋ง ๋ถ€ํŠธ] ๊ฒŒ์‹œํŒ

[์Šคํ”„๋ง ๋ถ€ํŠธ] 9. ๊ฒŒ์‹œํŒ ๋งŒ๋“ค๊ธฐ ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ

devCloud 2023. 10. 27. 15:53
728x90

ํŽ˜์ด์ง•์ด๋ž€?

์šด์˜์ฒด์ œ ๊ด€์ ์—์„œ, ์ปดํ“จํ„ฐ๊ฐ€ ๋ฉ”์ธ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด 2์ฐจ ๊ธฐ์–ต ์žฅ์น˜๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ฒ€์ƒ‰ํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ๊ธฐ๋ฒ•์ด๋‹ค.

 

์˜ˆ๋ฅผ ๋“ค์–ด, 100๊ฐœ์˜ ๊ฒŒ์‹œ๋ฌผ์ด ์žˆ์œผ๋ฉด ํ•œ ํŽ˜์ด์ง€์— 100๊ฐœ๋ฅผ ๋ชจ๋‘ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์ด ์•„๋‹Œ 10๊ฐœ์”ฉ ๋‚˜๋ˆ ์„œ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์„ ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ๋ผ๊ณ  ํ•œ๋‹ค. 

ํŽ˜์ด์ง• ์˜ˆ์‹œ

 

01. ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ

JPA์—์„œ ์ œ๊ณตํ•˜๋Š” Pageable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ๋ฅผ ํ•œ๋‹ค.

01-1. BoardController์˜ boardList ๋ฉ”์†Œ๋“œ ์ˆ˜์ •

๋ฉ”์†Œ๋“œ ์ธ์ž์— Pageable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. Pageable ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋งŽ์€๋ฐ ๊ทธ ์ค‘์— org.springframework.data.domain ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ import ํ•ด์ค€๋‹ค. 

boardController์˜ boardList ๋ฉ”์†Œ๋“œ

 

• Pageable

  • ์š”์ฒญํ•œ ํŽ˜์ด์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • JPA์—์„œ ์ œ๊ณตํ•ด์ฃผ๋Š” ๊ฐ์ฒด์ด๋‹ค.

 

โ€ป Pag๋งŒ ์ณ๋„ ๊ด€๋ จ ํด๋ž˜์Šค๊ณผ ์ธํ„ฐํŽ˜์ด์Šค๋“ค์ด ๊ฒ€์ƒ‰๋œ๋‹ค. Tab์œผ๋กœ ์„ ํƒํ•˜๋ฉด ๋œ๋‹ค.

 

boardController์˜ boardList ๋ฉ”์†Œ๋“œ

@PageableDefault

  • Pageable ๊ฐ์ฒด ์•ž์— @PageableDefault ์• ๋…ธํ…Œ์ด์…˜์„ ๋ถ™์ด๋ฉด ๊ธฐ๋ณธ๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • PageableHandlerMethodArgumentResolverSupport ์— ์ •์˜๋œ getDefaultFromAnnotationOrFallback() ๋ฉ”์†Œ๋“œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
  • @PageDefault๋กœ ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์–ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋Š” fallbackPageable์ด ์•„๋‹Œ, @PageDefault์–ด๋…ธํ…Œ์ด์…˜์— ์„ค์ •ํ•œ๋Œ€๋กœ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด๋‚ด์ค€๋‹ค.
  • page : default ํŽ˜์ด์ง€(ํŽ˜์ด์ง€ ์ธ๋ฑ์Šค๊ฐ€ 1์ด ์•„๋‹Œ 0๋ถ€ํ„ฐ ์‹œ์ž‘)
  • size : ํ•œ ํŽ˜์ด์ง€์— ๋‚˜ํƒ€๋‚ผ ๊ฒŒ์‹œ๊ธ€ (์—ฌ๊ธฐ์„œ๋Š” 10๊ฐœ๋กœ ์„ค์ •)
  • sort : ์ •๋ ฌ ๊ธฐ์ค€ ์ปฌ๋Ÿผ (์—ฌ๊ธฐ์„œ๋Š” id๊ฐ’์œผ๋กœ ์ •๋ ฌ)
  • direction : ์ •๋ ฌ ์ˆœ์„œ
    • DESC : ์—ญ์ˆœ์œผ๋กœ ์ •๋ ฌ(๋‚ด๋ฆผ์ฐจ์ˆœ์ด๋ž€ ๋œป์œผ๋กœ ํฐ ๊ฐ’์ด ์ œ์ผ ๋จผ์ € ์˜ค๋„๋ก ์ฆ‰, ์ตœ์‹  ํŽ˜์ด์ง€๊ฐ€ ์ƒ์œ„์— ์˜ค๋„๋ก ์ฒ˜๋ฆฌ)
    • ASC : DESC์™€ ๋ฐ˜๋Œ€๋กœ ์˜ค๋ฆ„์ฐจ์ˆœ์ด๋ผ๋Š” ๋œป์ด๋‹ค. ๋””ํดํŠธ ๊ฐ’์ด๋ฏ€๋กœ ์ƒ๋žต์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

 

์ธ์ˆ˜๋กœ ๋ฐ›์€ pageable์„ boardList์— ๋„˜๊ฒจ์ค„๊ฑด๋ฐ ํ˜„์žฌ ์˜ค๋ฅ˜๊ฐ€ ๋‚œ๋‹ค. ์ด๋Š” ์„œ๋น„์Šค์—์„œ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ฃผ์ง€ ์•Š์•„์„œ ์ƒ๊ธด ๋ฌธ์ œ์ด๋‹ค. ์˜ค๋ฅ˜๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Service์—์„œ List ๋ฉ”์†Œ๋“œ๋ฅผ ์ˆ˜์ •ํ•œ๋‹ค.

 

โžค Pageable์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์„ค๋ช… โžœ https://tecoble.techcourse.co.kr/post/2021-08-15-pageable/

01-2. BoardService์˜ boardList ๋ฉ”์†Œ๋“œ ์ˆ˜์ •

boardService์˜ boardList ๋ฉ”์†Œ๋“œ

pageable ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋„ฃ์–ด์ฃผ๋‹ˆ ์˜ค๋ฅ˜๊ฐ€ ๋‚œ๋‹ค. List์ž๋ฆฌ์— Page๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ์‚ฌ๋ผ์ง„๋‹ค.

boardService์˜ boardList ๋ฉ”์†Œ๋“œ

Controller๋„ ๋‹ค์‹œ ํ™•์ธํ•˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ์‚ฌ๋ผ์ง„ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

boardController์˜ boardList ๋ฉ”์†Œ๋“œ

์‹คํ–‰ํ•˜๊ธฐ(http://localhost:8080/board/list)

์ขŒ - ๊ธฐ์กด ๋ฆฌ์ŠคํŠธ, ์šฐ - ํ˜„์žฌ ๋ฆฌ์ŠคํŠธ

๊ธฐ์กด์—๋Š” ๋ชจ๋“  ๊ฒŒ์‹œ๊ธ€์ด ํ•œ ํŽ˜์ด์ง€์— ๋‹ค ๋ณด์˜€์ง€๋งŒ, PageableDefault๋ฅผ ํ†ตํ•ด ํŽ˜์ด์ง• ์ฒ˜๋ฆฌํ•œ ๊ฒฐ๊ณผ ์ตœ์‹  ๊ธ€์ด ๋งจ ์œ„๋กœ ์˜ฌ๋ผ์˜จ ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๊ณ , ํ•œ ํŽ˜์ด์ง€์— 10๊ฐœ์˜ ๊ฒŒ์‹œ๊ธ€๋งŒ ๋ณด์ด๋Š” ๊ฑธ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ํ˜„์žฌ๋Š” 0ํŽ˜์ด์ง€(์ฒซ ๋ฒˆ์งธ ํŽ˜์ด์ง€)๋งŒ ๋ณด์ด์ง€๋งŒ, url์„ ์ˆ˜์ •ํ•ด ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋ฅผ ํ™•์ธํ•ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 0์ž๋ฆฌ์— 1์„ ๋„ฃ์œผ๋ฉด ๋‘ ๋ฒˆ์งธ ํŽ˜์ด์ง€๋กœ ๋„˜์–ด๊ฐ„๋‹ค.

์ขŒ - ์ฒซ ๋ฒˆ์งธ page, ์šฐ - ๋‘ ๋ฒˆ์งธ ํŽ˜์ด์ง€

 

ํ•œ ํŽ˜์ด์ง€์— ๋ณด์—ฌ์ค„ ๊ฒŒ์‹œ๊ธ€์˜ ์ˆ˜๋„ ์ง€์ •ํ•ด ์ค„ ์ˆ˜ ์žˆ๋‹ค. url์— size๋„ ๋„˜๊ฒจ์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

size = 20 ์ฆ‰, ์ฒซ ๋ฒˆ์งธ ๊ฒŒ์‹œ๋ฌผ์— 20๊ฐœ์˜ ๊ฒŒ์‹œ๋ฌผ์„ ๋ณด๊ฒ ๋‹ค๋Š” ๋ง์ด๋‹ค.

 

์ •๋ฆฌํ•˜๋ฉด, ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ ์‹œ์— ์ฟผ๋ฆฌ๋ฌธ ์ž‘์„ฑ๊ณผ ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ๋ฅผ ํ•  ํด๋ž˜์Šค๋„ ์ƒ์„ฑํ•ด์ค˜์•ผ ํ•˜๋Š”๋ฐ ์ด๋•Œ, jpa๋ฅผ ์ด์šฉํ•œ๋‹ค. jpa์˜ findAll ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ pageable ํด๋ž˜์Šค๋ฅผ ๋„˜๊ฒจ์ฃผ๋ฉด ์–ด๋ ค์šด ์ฒ˜๋ฆฌ๋ฅผ ์ด๋ ‡๊ฒŒ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

02. ํŽ˜์ด์ง€ ๋ธ”๋Ÿญ ์ถœ๋ ฅ

์ด์ œ ํ”„๋ก ํŠธ ์ฆ‰, ๋ฆฌ์ŠคํŠธ ํŽ˜์ด์ง€์— ๋‹ค์Œ ํŽ˜์ด์ง€๋กœ ํด๋ฆญ์œผ๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ณด์—ฌ์ค€๋‹ค.

 

02-1. boardlist.html์— thymeleaf ์ถ”๊ฐ€

<!DOCTYPE html>
<html lang="en" xmlns:th="http://thymeleaf.org">
                            .
                            .
<body>
  <div class="layout">
    <table border="1" align="center"> <!-- ๋ฆฌ์ŠคํŠธ ์ค‘๊ฐ„ ์ •๋ ฌ ์ถ”๊ฐ€ -->
                        .
                        .
    </table>
    
     <!-- ํŽ˜์ด์ง• ๋ธ”๋Ÿญ ์ฒ˜๋ฆฌ thymeleaf ์ถ”๊ฐ€ -->
     <nav style="text-align: center;"> <!-- ํŽ˜์ด์ง• ๋ธ”๋Ÿญ๋„ ์ค‘๊ฐ„ ์ •๋ ฌ ์ถ”๊ฐ€ -->
        <th:block th:each="page : ${#numbers.sequence(startPage, endPage)}">
            <a th:if="${page != nowPage}" th:href="@{/board/list(page = ${page - 1})}" th:text="${page}"></a>
            <strong th:if="${page == nowPage}" th:text="${page}" style="color : red"></strong>
        </th:block>
     </nav>

  </div>
</body></html>

• thymeleaf ๋ฌธ๋ฒ•

  • th:text - ํƒœ๊ทธ ์•ˆ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ถœ๋ ฅ
    • Thymeleaf์˜ th:text ์†์„ฑ์€ ์š”์†Œ ์˜ ํ…์ŠคํŠธ ๋‚ด์šฉ์„ ์„ค์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.
    • ๋˜ํ•œ ์ด๋Š” ํ‘œ์ค€ HTML ํ…์ŠคํŠธ ์†์„ฑ์„ ๋Œ€์ฒดํ•œ๋‹ค.
    • ๋”ฐ๋ผ์„œ ์ œ๋ชฉ, ๋‹จ๋ฝ, ๋ ˆ์ด๋ธ” ๋“ฑ๊ณผ ๊ฐ™์€ ํ…์ŠคํŠธ ์ฝ˜ํ…์ธ ๋ฅผ ์ง€์›ํ•˜๋Š” ๋ชจ๋“  HTML ์š”์†Œ ๋‚ด์— ์ด๋ฅผ ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค.
    • ๋˜ํ•œ ์ด ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์›น ํŽ˜์ด์ง€์˜ ์ œ๋ชฉ๊ณผ ๊ฐ™์€ ๋™์  ํ…์ŠคํŠธ ์ฝ˜ํ…์ธ ๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋‹ค.
  • th:each - ๋ฐ˜๋ณต๋ฌธ, ๋ฐ˜๋ณต ์ถœ๋ ฅ
    • th:each = "board : ${boardList}" - ๊ธฐ๋ณธ ๋ฌธ๋ฒ•์œผ๋กœ, ํ’€์ดํ•˜๋ฉด boardList์˜ ๊ฐ’๋“ค์„ board๊ฐ€ ํ•˜๋‚˜ํ•˜๋‚˜ ์ฐธ์กฐํ•œ๋‹ค.
  • "${number : #number(์‹œ์ž‘ ๋ฒˆํ˜ธ, ๋๋ฒˆํ˜ธ)}" - ์‹œ์ž‘ ๋ฒˆํ˜ธ์—์„œ ๋๋ฒˆํ˜ธ๊นŒ์ง€ ๋ฐ˜๋ณต

 

02-2. BoardController์˜ boardList ๋ฉ”์†Œ๋“œ ์ˆ˜์ •

1. "List"์— ๋„˜๊ฒจ์ค„ ํŽ˜์ด์ง€๋ฅผ ์ง์ ‘ ๋„˜๊ฒจ์ฃผ์ง€ ์•Š๊ณ  ๋”ฐ๋กœ ๊ตฌํ˜„ํ•œ๋‹ค. ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ๋‹ค๋ฅธ ๊ณณ์—๋„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ์ฒด๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด์„œ ๋ถˆํ•„์š”ํ•œ ๋ฐ˜๋ณต์„ ์ค„์ด๊ณ  ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•œ ๊ฒƒ์ด๋‹ค. 

//์ถ”๊ฐ€
Page<Board> list = boardService.boardList(pageable);

 

2. ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์—ˆ์œผ๋‹ˆ list๋ฅผ ๋‹ด์•„์ค€๋‹ค. ๊ธฐ์กด์—๋Š” list ์ž๋ฆฌ์— 'boardService.boardList(pageable));'๊ฐ€ ์žˆ์—ˆ๋‹ค.

  //์ˆ˜์ •
model.addAttribute("List", list);

 

3. ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ ๋‹ค.

int nowPage = list.getPageable().getPageNumber() + 1; //ํ˜„์žฌ ํŽ˜์ด์ง€
int startPage = nowPage / pageable.getPageSize() * pageable.getPageSize() + 1; //๋ธ”๋Ÿญ์—์„œ ๋ณด์—ฌ์ค„ ์‹œ์ž‘ ํŽ˜์ด์ง€
int endPage = startPage + pageable.getPageSize() - 1; //๋ธ”๋Ÿญ์—์„œ ๋ณด์ด๋Š” ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ง€
  • nowPage
    • ํ˜„์žฌ ํŽ˜์ด์ง€๋ฅผ ์˜๋ฏธํ•˜๊ณ , ํ˜„์žฌ ํŽ˜์ด์ง€๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค.
    • nowPage์— pageable.getPageNumber()๋งŒ ๋„˜๊ฒจ์ค˜๋„ ๋˜์ง€๋งŒ ํ†ต์ผ์„ฑ์„ ์œ„ํ•ด ์œ„์™€ ๊ฐ™์ด ์ž‘์„ฑํ•œ๋‹ค.
  • startPage
    • ๋ธ”๋Ÿญ์—์„œ ๋ณด์—ฌ์ค„ ์‹œ์ž‘ ํŽ˜์ด์ง€๋ฅผ ์˜๋ฏธํ•œ๋‹ค.
    • ํ˜„์žฌํŽ˜์ด์ง€/ํŽ˜์ด์ง• ๊ฐœ์ˆ˜*ํŽ˜์ด์ง• ๊ฐœ์ˆ˜ + 1
  • endPage
    • ๋ธ”๋Ÿญ์—์„œ ๋ณด์ด๋Š” ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ง€๋ฅผ ์˜๋ฏธํ•œ๋‹ค.
    • ์‹œ์ž‘ํŽ˜์ด์ง€ + ํŽ˜์ด์ง• ๊ฐœ์ˆ˜ - 1

 

4. ๋ณ€์ˆ˜ ์„ค์ •์ด ๋๋‚ฌ์œผ๋ฉด ๊ฐ’์„ ๋„˜๊ฒจ์ค€๋‹ค.

//์ถ”๊ฐ€
model.addAttribute("nowPage", nowPage);
model.addAttribute("startPage", startPage);
model.addAttribute("endPage", endPage);

 

์‹คํ–‰ํ•˜๊ธฐ(localhost:8080/board/list)

์œ„์™€ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ์ถœ๋ ฅ๋˜๋Š” ๊ฒƒ์€ ์ปจํŠธ๋กค๋Ÿฌ์˜ boardList์—์„œ 10๊ฐœ ๋‹จ์œ„๋กœ ๋‚˜์˜ค๋„๋ก ์„ค์ •ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

728x90