본문 바로가기
실습/리눅스 서버 + 스프링 부트

JPA 페이징

by 이민우 2022. 7. 25.
728x90
반응형

게시판에 약 100,000개의 게시글들이 등록되어 있다고 가정한다.

 

이 경우 굳이 사용자에게 100,000개의 게시글들을 전부 제공해야 할까?

만약 그런다면 속도가 느린 것은 당연하고, 한 페이지 내에서 모든 게시글들을 보여주기 어려워 사용자 편의성이 크게 떨어질 수 있다.

 

페이징이란 이러한 경우 사용하는 것으로, 게시판을 페이지 단위로 나누어 사용자게에 제공하는 작업이다.

예시) 네이버 뉴스 페이징

페이징은 원래대로라면 DB 파라미터에 LIMIT 등의 조건을 추가하면 구현할 수 있다.

 

하지만 DB마다 조금씩 그 방식에 차이가 있기 마련인데, ORM인 JPA는 이러한 페이징도 DB의 종류에 관계없이 쉽게 구현할 수 있도록 Pageable이라는 클래스를 제공한다.


즉 JPA는 Pageable이라는 클래스를 파라미터로 주고받으며 위의 페이징 작업을 쉽게 구현할 수 있도록 도와주고 있다.

import org.springframework.data.domain.Pageable;

 

예제는 아래와 같다. 작업 시간을 줄이기 위해 HTML은 작성하지 않았고, Rest로 동작하도록 한다.

 

우선 예제에 앞서 테이블을 생성한다.

간단하게 아이디, 비밀번호, 가입일로 구성된 테이블을 만들 예정이다.

CREATE TABLE test_domain (
	user_id VARCHAR(100) PRIMARY KEY,
	user_pw VARCHAR(100),
	reg_date timestamp
);

 

테스트용으로 사용할 데이터를 넣어준다.

빠른 작업을 위해 프로시져를 생성한다. 참고로 가입일 구분을 위해 1초를 쉬게 생성하였다.

DELIMITER $$
CREATE PROCEDURE insertUntil(m INT)
BEGIN
	DECLARE i INT DEFAULT 1;
	WHILE (i <= m) DO
		INSERT INTO test_domain VALUES (CAST(i AS VARCHAR(100)), CAST(i AS VARCHAR(100)), NOW());
		SET i = i+1;
		SELECT SLEEP(1);
	END WHILE;
END$$
DELIMITER;

그 후 생성된 프로시져를 100 파라미터를 넣고 돌린다.

CALL insertUntil(100);

100초 후 프로시져가 완료되면 아래와 같이 100 개의 더미 데이터들이 테이블에 적재됨을 확인할 수 있다.

 

 

테이블에 데이터 적재를 완료했다면 이제 해당 테이블 명세에 따라 Domain 클래스를 만들어준다.

package com.example.demo.domain;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Data
@Entity
@Table(name="test_domain")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class TestDomain {
	@Id
	@Column(name="user_id", columnDefinition="VARCHAR(100)")
	private String userId;
	@Column(name="user_pw", columnDefinition="VARCHAR(100)")
	private String userPw;
	@Column(name="reg_date", columnDefinition="timestamp")
	private Date regDate;
}

 

다음은 Repository이다. 모든 데이터를 받아 regDate 순서로 내림차순 (최근 가입일 순)으로 가입한 사용자들을 출력한다.

이 때 메소드의 파라미터에는 위에서 언급한 Pageable이 포함되어 있어야 한다.

package com.example.demo.repository;

import java.util.List;

import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import com.example.demo.domain.TestDomain;

@Repository
public interface TestRepository extends CrudRepository<TestDomain, String>{
	public List<TestDomain> findAllByOrderByRegDateDesc(Pageable pageable);
}

 

다음은 서비스이다. 간단하게 컨트롤러에서 Pageable을 전달받아 Repository로 넘긴 후 다시 컨트롤러로 결과를 전달하는 역할만을 수행하게 작성한다.

package com.example.demo.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.example.demo.domain.TestDomain;
import com.example.demo.repository.TestRepository;

@Service
public class TestService {
	@Autowired TestRepository repo;
	
	public List<TestDomain> getPageList(Pageable pageable) {
		return repo.findAllByOrderByRegDateDesc(pageable);
	}
}

 

마지막으로 Controller이다. 사용자는 쿼리 파라미터로 page=?&size=? 와 같이 page와 size를 보내게 될 것이고, Controller의 메소드는 해당 쿼리 파라미터를 Pageable 클래스로 인식하게 된다.

 

이 때 page는 {현재 조회중인 페이지-1}, size는 {페이지 당 보여줘야 할 글의 숫자}이다.

package com.example.demo.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.domain.TestDomain;
import com.example.demo.service.TestService;

@RestController
public class TestController {
	
	@Autowired TestService service;
	
	@GetMapping("/test/data")
	public List<TestDomain> getTestDomainList(Pageable pageable) {
		return service.getPageList(pageable);
	}
}

 

개발이 완료되었다면 간단하게 테스트를 수행한다.

 

예를 들어 10개씩 보여주는 게시판의 1페이지를 보고자 한다면, {IP}:{PORT}/{URI}?page=0&size=10 로 접속하여 데이터가 정상적으로 Return되는지 확인한다.

가장 마지막에 가입된 100 사용자부터 91 사용자까지 정확히 10명이 출력됨을 확인할 수 있다.

728x90
반응형