게시판에 페이징을 추가해보자

HiroPark·2022년 9월 23일
0

Spring

목록 보기
8/11

PostsRepository

  • 먼저 Repository의 기존에 List인터페이스 형을반환하던 findAllDesc 기능이
    Page인터페이스를 구현한 객체를 리턴하게 하고, Pageable을 파라미터로 제공합니다.

  • Page인터페이스는 객체의 리스트의 서브리스트에 대한 인터페이스입니다. Page객체를 통하여 전체 리스트에서의 위치를 파악할 수 있습니다.

  • Page는 Slice 인터페이스를 확장했는데요, Slice인터페이스는 이전, 이후 슬라이스의 존재에 대해 알 수 있는 기능을 구현해야하기에, Pageable이 슬라이스의 전후에 대해 요청을 할 수 있습니다.

  • Pageable은 페이징 정보를 담고있는 인터페이스입니다.

public interface PostsRepository extends JpaRepository<Posts,Long> { 

    @Query("SELECT p FROM Posts p ORDER BY p.id DESC")
    Page<Posts> findAllDesc(Pageable pageable);
}

PostsService

@RequiredArgsConstructor
@Service
public class PostsService {
    private final PostsRepository postsRepository;
    private final UserRepository userRepository;

    private final UserDetailService userDetailService;
   .
   .
   .
   .
    /* 페이징 1 */
    @Transactional(readOnly = true) //트랜젝션 범위는 유지하나, 조회 기능만 남겨서 조회 속도를 개선함
    public Page<Posts> findAllDesc(Pageable pageable) {
        return postsRepository.findAllDesc(pageable);
    }
}
  • Pageable을 파라미터로 받아 앞서봤던 PostsRepository에 넘깁니다.

IndexController

@RequiredArgsConstructor
@Controller
public class IndexController {

    private final PostsService postsService;
    private final HttpSession httpSession;

    /* 페이징 1 */
    @GetMapping("/")
    public String index(Model model, @PageableDefault(size = 3)Pageable pageable) {
        Page<Posts> list = postsService.findAllDesc(pageable);

        model.addAttribute("posts", list);
        model.addAttribute("prev", pageable.previousOrFirst().getPageNumber());
        model.addAttribute("next", pageable.next().getPageNumber());
        model.addAttribute("hasNext", list.hasNext());
        model.addAttribute("hasPrev", list.hasPrevious());

        SessionUser user = (SessionUser) httpSession.getAttribute("user");
        if (user != null) {
            model.addAttribute("userName", user.getName());
        }

        return "index"; // 머스태치 스타터가 앞의 경로 src/main/resources/templates로, 뒤의 확장자 .mustache 로 자동 지정
    }
    .
    .
    .
 }
  • 앞서서 Pageable이 페이징에 대한 정보를 담고 있는 인터페이스라고 했죠, 이 정보를 @PageableDefault를 통해 전달하고 있습니다.
    - 컨트롤러에 Pageable을 주입할 때 해당 애노테이션을 활용합니다.

    • size(페이징 크기) , sort(정렬기준), direction(정렬방향) 등을 정할 수 있습니다.
    • Repository에 정렬에 대한 쿼리가 정해져있기에 페이징 크기만 정해주었습니다.
  • prev : 이전 페이지의 페이지번호

  • next : 다음 페이지의 페이지번호
    이들을 모델에 넘겨서 화면에서 이를 통해 페이지를 이동합니다.

  • hasNext와 hasPrev는 더이상 보여줄 페이지가 없음에도 페이지가 계속 넘어가는 것을 막기 위한 boolean입니다.

Index.mustache

{{>layout/header}}
    <h1>스프링 부트 테스트</h1>
    <div class="col-md-12">
        <!-- 로그인 기능 영역 -->
        <div class="row">
            <div class="col-md-6">
                <a href="/posts/save" role="button" class="btn btn-primary">글 등록</a>
                {{#userName}} <!-- userName이 있다면 이를 노출 -->
                Logged in as : <span id="user"> {{userName}}</span>
                <a href = "/logout" class="btn btn-info active" role = "button">Logout</a>
                {{/userName}}
                {{^userName}} <!--userName이 존재하지 않는 경우 로그인버튼 -->
                    <a href ="/oauth2/authorization/google"
                       class = "btn btn-success active" role="button">Google Login</a>
                {{/userName}}
            </div>
        </div>
        <br>
        <!-- 목록 출력 영역 -->
        <table class="table table-horizontal table-bordered">
            <thead class="thead-strong">
            <tr>
                <th>게시글번호</th>
                <th>제목</th>
                <th>작성자</th>
                <th>최종수정일</th>
            </tr>
            </thead>
            <tbody id="tbody">
            {{#posts}} <!-- 리스트를 순회, 변수 는 여기서 뽑아낸 객체의 필드, 컨트롤러에서 model 객체를 통해 넘겨줌-->
                <tr>
                    <td>{{id}}</td>
                    <td><a href="/posts/{{id}}">{{title}}</a></td>
                    <td>{{userName}}</td>
                    <td>{{modifiedDate}}</td>
                </tr>
            {{/posts}}
            </tbody>
        </table>

        <ul class="pagination justify-content-center">
            {{#hasPrev}}
                <a class="page-link" href="?page={{prev}}">Previous</a>
            {{/hasPrev}}
            {{#hasNext}}
                <a class="page-link" href="?page={{ next }}">Next</a>
            {{/hasNext}}
        </ul>

    </div>
{{>layout/footer}}
  • 모델로 넘겨받은 prev와 next를 통해 페이지를 이동하는 버튼을 만들어줍니다.

  • 만약 이전, 다음 페이지가 없다면 버튼을 보여주지 않음으로써 페이지가 무제한으로 넘어가는 것을 방지합니다,

profile
https://de-vlog.tistory.com/ 이사중입니다

0개의 댓글