sql로 페이지네이션 구현 하기

김국민·2025년 3월 26일

task-management API

프로젝트 개요

이 프로젝트는 스프링 MVC를 활용하여 일정 관리 애플리케이션의 API를 구현하는 것을 목표로 합니다. 이 애플리케이션에서는 사용자들의 일정을 관리하고, CRUD(생성, 읽기, 수정, 삭제) 기능을 제공합니다.


API 명세서

1. 요구사항

  • 일정 생성
  • 전체 일정 조회
  • 선택 일정 조회
  • 선택 일정 수정
  • 선택 일정 삭제
  • 전체 일정 조회(페이지)

2. API 엔드포인트

작업 관련 API

작성자 관련 API


ERD (Entity Relationship Diagram)

MySQL

-- 데이터베이스 선택
use task;

-- task 테이블 생성
create table task (
    id BIGINT auto_increment primary key comment "작업 식별자",
    authorEmail varchar(50) not null comment "작성자 이메일 (식별)",
    created_at date not null comment "작성일자",
    updated_at date not null  comment "수정일자",
    taskName varchar(200) not null comment "작업내용"
);

-- author 테이블 생성
create table author (
    id BIGINT auto_increment primary key comment "작성자 식별자",
    email varchar(50) not null unique comment "작성자 이메일 고유값",
    name varchar(50) not null comment "작성자 이름",
    password varchar(50) not null comment "작성자 비밀번호",
    created_at date not null comment "등록일",
    updated_at date not null comment "수정일"
);

-- 외래키 제약조건 추가 (task 테이블에 author 테이블과 관계 설정)
alter table task 
add constraint fk_task_author 
foreign key (authorEmail) references author(email);


💥 Trouble Shooting

과제를 진행하면서 페이지네이션을 구현하라는 항목이 있었다.
단순히 페이지 수와 전송할 데이터의 수만 정하고 서비스레이어에서 계산을하고 응답을 하는 방식으로 구현했다

그런데 이렇게 하면 매번 전체 데이터를 다 가져와서 계산을 하고 응답을 하니 코드도 복잡해지고 성능저하가 발생할 거 같았다.

jpa를 활용하면 간단하게 페이지네이션을 구현할 수 있다고 하는데 나는 아직 jdbc밖에 배우지 못하고 할일이 많아 도전하진 못했다.

그래도 일전에 배워둔 sql을 이용해서 간단하게 페이지네이션 흉내를 낼 수 있었다.


페이지네이션 이란?

페이징은 큰 데이터를 여러개의 페이지로 나누어 표현하는 기술이다

왜 페이지네이션을 사용하나요?

사용자가 상품목록을 조회할 때 데이터베이스에 있는 모든 상품을 다 가져온다면 서버에 과도한 부하가 발생하고 클라이언트에서 데이터를 처리하거나 표시하는 데 시간이 오래 걸릴 수 있다. 또 사용자 경험에 있어서도 좋지 않다.

SQL로 페이지네이션 구현하기

1. LIMIT과 OFFSET을 사용한 페이징

  • LIMIT: 반환할 데이터의 개수를 지정합니다.
  • OFFSET: 데이터를 반환할 시작 위치를 지정합니다.

2. CURSOR를 이용한 페이징

  • 이 방법은 페이지 번호 대신 이전 페이지의 마지막 데이터를 기준으로 데이터를 조회하는 방식
  • CURSOR가 마지막 데이터를 가르킨다

페이지네이션 구현하기

예시 데이터


세개의 컬럼을 가진 테이블
27549의 데이터가 들어있다

조회할 페이지
10000번째 페이지를 조회한다
int page = 10000;

limit 설정
한번에 보여줄 데이터 수는 5로 정한다
int limit = 5;

offset
시작할 인덱스인 offset계산
int offset = (page - 1) * limit;


OffSet을 이용해 페이지네이션 구현하기

1. 서비스레이어에서 처리하기

서비스 레이어 코드

테스트 결과 코드

154정도의 시간이 걸린다
전체 데이터를 가져오고 서비스레이어에서 계산을 하는 과정에서 늦어진다


2. sql 쿼리로 가져오기

레포지토리 레이어 코드

서비스 레이어 코드

테스트 결과 코드

29의 시간이 걸린다 앞에서 했던 결과보다 더 빠르다. 데이터베이스에서 데이터를 필요한 부분만 가져와서 바로 보여준다.


3. Cursor를 이용한 방법

앞에서 했던 방법은 page의 크기가 커지면 매번 앞에서 했던 결과를 또 불러와야 한다는 단점이 있다.
또 페이지를 불러오는 도중에 새로운 데이터가 생성되면 데이터가 중복되는 문제도 생긴다
성능저하, 데이터중복

cursor 기반 방식은 마지막 데이터를 기준으로 limit을 더해서 값을 보내주기 때문에 어떤 페이지를 읽더라도 빠르게 데이터를 보여줄 수 있다

서비스 레이어 코드

레포지토리 레이어 코드

테스트 결과 코드


14의 시간이 걸린다 앞에 두 방법보다 많이 빠르다.
실제 커서를 구현하려면 이전에 값을 저장해야 하기 때문에 쿠키나 세션에 대해서 알아야 한다 (전 아직 알지 못하기 때문에 맛만 봤다)


이번 과제를 진행하면서 ..

이번 과제를 진행하면서 배운것은 내가 구현하고자 하는 것에 대해 틀을 잡아두고 한다면 내가 어떤 기술이 필요한지 알 수 있다는 것이다.

향후 수업을 진행하면서 무조건 개념을 다 습득하고 진행하기 보다는 구현해야 하는 것의 틀을 먼저 잡아두고 그때그때 배운다면 조금 더 성장에 도움이 될 거같다.

profile
개발지망생

0개의 댓글