SPRING

SPRING 페이징 처리 (pagination)

Adev 2022. 11. 30. 16:45
  • 목표

: 빠르게, 필요한 양만큼만 데이터를 가져온다.

 

  • 페이징 처리 방법 2가지 

1) 번호 이용

2) 계속 보기(무한스크롤, 더보기)

 

  • 실행계획 

: SQL을 DB에서 어떤 순서와 방식으로 처리할 것인가?
: SQL 파싱(parsing) -> SQL 최적화 -> SQL 실행
  SQL을 실행하면 트리구조로 처리결과를 보여준다. 안쪽에서 바깥쪽, 위에서 아래로 확인한다.

 

 

1. 오라클 db 페이징 처리

1.1. index를 이용한 정렬

: 색인. 데이터베이스의 테이블의 데이터를 찾거나 정렬하기 위한(scan) 도구이다.
: 테이블 생성 시 PK를 지정하면 인덱스가 만들어 진다.
: 정렬이 되어 있는 상태이다. (SORT 과정 생략 가능)

+ order by를 사용해 정렬하면 데이터가 많은 경우 엄청난 시간과 리소스를 소모하게 되는 단점이 있기 때문에, 일반적으로 index를 사용하는 게 효율적이다.


1) PK (primary key)


: 식별자. 인덱스.


ex) 

alter table tbl_board add constraint pk_board primary key (bmo);

-- : 테이블 제약 조건으로 pk 지정하고 이름을 'pk_board'라고 정한다. 
-- : bno 칼럼을 기준으로 인덱스를 생성한다.

 


2) ROWID

: 데이터베이스 내 (고유한) 주소.인덱스와 실제 테이블을 연결하는 역할을 한다.

 


3) 오라클 힌트

: select문 처리 방식을 명시한다.

 에러 발생 시 무시하며 SQL실행에 영향을 미치지 않는다.

 

ex) 

select /*+INDEX_DESC (tbl_board pk_board) */ * from tbl_board;
-- : tbl_board 테이블에 pk_board 인덱스를 역순으로 이용할 것

 

     - FULL : 테이블 전체 스캔

     - INDEX_ASC, INDEX_DESC : 인덱스를 순서대로/역순으로 이용 (주로 ORDER BY)

 

 

 

1.2. ROWNUM과 인라인뷰

1) ROWNUM

: SQL 실행 결과에 순번을 붙인다.

 테이블에 존재하는 실제 데이터가 아닌, 변수이다

 SQL 작성 시 ROWNUM 조건에 1이 포함돼야 한다.  (1을 포함하지 않는 결과가 필요하다면 구한 데이터를 하나의 테이블로 간주하고 추출한 순번을 칼럼으로 이용해 인라인뷰 처리를 한다.)

+ ORDER BY로 데이터에 접근 시에는 빨리 찾은 데이터부터 먼저 순번이 붙고 이후 정렬한다. 반면 인덱스로 접근 시에는 이미 정렬이 된 상태이기 때문에 정렬된 순서대로 ROWNUM이 붙게 된다.

 

 

2) In-ling View 처리

: select문 from구문 안에 select문을 작성한다.
 

 


2. MyBatis와 스프링 페이징 처리

: 인라인뷰를 이용하는 SQL문을 작성하고, 페이지번호와 한 페이지당 보여줄 데이터수를 지정한다.
(페이지 번호와 페이지당 보여줄 개수의 값을 묶어서 전달하는 클래스를 만들어서 사용할 수 있다.)

 

 

 

3. 페이징 화면 처리

3.1. 필요 정보 

현재 페이지

이전, 다음 링크 표시 여부

화면에 보여지는 페이지 시작 번호, 끝번호

 

1) 끝번호 계산

this.endPage = (int)(Math.ceil(페이지번호 / 10.0)) * 10;
//10페이지씩 보일 때
//Math.ceil : 소수점 올림
realEnd = (int)(Math.ceil((total * 1.0) / amount));

if(realEnd < this.endPage) {
this.endPage = realEnd;
}
//전체 데이터 수가 10페이지 총 데이터 수보다 적을 때..
//진짜 끝페이지가 구해둔 끝 번호보다 작을 때
//total을 통한 endPage계산

 

 

2) 시작 번호 계산

this.startPage = this.endPage - 9;
//10페이지씩 보일 때

 

 

3) 이전과 다음 존재 여부

this.prev = this.startPage > 1;
//이전

this.next = this.endPage < realEnd;
//다음