🐯
경민민 IT 핸드북
  • Orientation
    • 전달사항
    • 복습방법
    • 수료한 선배의 한마디
    • 간단 자기소개
    • 스터디
  • 백엔드
    • Java
      • 1장 프로그래밍 기초
      • 2장 자바 메모리구조
        • 1. Stack
        • 2. Heap
      • 6장 객체
      • 8장 상속
      • 9장 다형성
      • 10장 추상클래스와 인터페이스
      • 13장 Generic
      • 14장 Thread
      • 15장 Network
      • 16장 Lamda
        • 1. 내부 클래스 (Inner Class)
          • DTO , VO, Builder Pattern
        • 2. 람다 표현식 (Lambda Expression)
        • 3. 스트림 API (Stream API)
          • Optional
      • 17장 Enum
  • 프론트
    • Node.js
    • Java Script
      • ES6+
        • Node.js로 자바스크립트 실행
        • let , const , var
        • Destructuring문법
          • Rest(...) 문법
        • Arrow Function
        • 모듈
        • ETC
    • Type Script
      • 개요
      • TS설치 및 환경설정
      • 타입스크립트 기본
        • 기본 자료형들과 타입추론
        • Object, Array , Tuple
        • Any, Unknown, Union Type
        • Function Type
          • Type Assertion && Narrowing
          • Never type
        • Type Aliases와 Interface
        • 리터럴 타입
        • 함수 추가 문법
        • Class문법
        • 객체 타입 추가 문법
        • 실습문제 1차
        • 실습문제 2차
        • 실습문제 3차
    • React
      • 개요
      • SPA 와 MPA
        • SEO(작성예정)
      • 리액트 프로젝트 생성(18.3.1.ver)
        • HTML + react 샘플
        • CRA 와 Vite 비교
      • 리액트 개념들
        • Component
          • 클래스 컴포넌트(작성예정)
          • 함수형 컴포넌트(작성예정)
        • JSX
        • React Virtual Dom
          • Reconciliation
        • hook
          • useState
        • 리액트 데이터 전달
          • FLUX
      • 백엔드 서버 연동
        • 비동기요청
        • 웹소켓
        • Promise(작성예정)
      • 실습문제 1
      • 실습문제 2
      • 실습문제3
      • 실습문제4
  • 프레임워크
    • Spring
      • Spring 개발환경 구축
        • 프로젝트 환경설정
        • 프로젝트 생성
          • MVC Project 생성이슈
        • Maven 설정
        • web.xml 설정
        • Spring Bean Configuration.xml 설정
      • Spring Legacy Project
        • Spring 요청 및 응답 흐름
        • Spring 주요 Annotation
          • 의존성 주입방식의 차이점
          • @ModelAttribute와 유효성검사
          • 비동기처리
          • 스프링 예외처리
        • Logging
        • Pagination
        • Spring File 업로드 및 다운로드
        • Spring WebSocket
        • Spring AOP
      • Spring 라이브러리들(작성예정)
        • Lombok
        • Maven
        • MyBatis
      • Spring 구성 모듈(작성예정)
      • 스프링 과제
    • Spring Boot
      • Spring Boot 개발환경 구축
      • 스프링 부트 프로젝트 생성방법들
        • 프로젝트에서 사용하는 의존성들
      • 스프링 프로젝트 구조
        • SpringBootApplication
      • application.properties
      • Cross Origin
        • CORS
      • WebSocket
        • Stomp(작성중)
      • 로그인(작성중)
      • Spring Security(작성중)
      • 실습문제 Select
      • 실습문제 Update
      • 실습문제 Delete
  • 형상관리(Git)
    • GitHub설정
    • SourceTree를 활용한 깃허브 연동
      • 소스트리 설치
      • Clone
      • Branch
        • Branch Protection rules
          • Branch Protection Rules 상세규칙
        • Rebase 와 Squash (작성예정)
      • Team Project 설정
        • 팀장 프로젝트 셋팅
          • Collaborator
          • .gitignore 설정
        • 팀원 프로젝트 셋팅
        • 공통 프로젝트 진행
  • 프로젝트
    • 진행순서
      • 요구사항 분석 단계
        • 유용한 사이트
      • 프로그램 설계 단계
        • 유용한 사이트
      • 프로그램 구현단계
        • SourceTree를 활용한 Team Project설정
      • 테스트 단계
  • 배포
    • AWS-EC2 배포 연습
    • DevOps
      • IT시스템의 변화와 DevOps
      • DevOps 라이프사이클
    • 젠킨스
      • 도커
        • 도커 설치 방법
        • 도커 기본 명령어들
      • 젠킨스 설치
      • 젠킨스 프로젝트 생성
      • 젠킨스 소스코드 통합 - Github
      • 젠킨스 빌드 설정 - Maven
      • 배포 서버 구축하기
      • 파이프라인 구축
      • AWS 서버 생성
        • AWS 인스턴스 생성
        • AWS - Zenkins 연동
        • AWS - 배포서버 연동
        • AWS - Jenkins CI/CD파이프라인 구축
  • 유용한 사이트 모음
  • SQL
    • SQLD
      • 데이터 모델링의 이해 - 스키마
      • 데이터 모델링의 이해 - ERD
      • 데이터 모델링의 이해 - 정규화
      • 데이터 모델링의 이해 - NULL
      • SQL 기본 및 활용 - WINDOW FUNCTION
    • Oracle
      • 1장 개요
      • 2장 SQL
  • LLM 서비스
    • 1장 LLM에 대한 이해
    • 2장 프롬프트 엔지니어링
      • 프롬프트와 프롬프트 엔지니어링
      • GPT PlayGround
      • 프롬프트 작문 유형
      • 기본 프롬프트 엔지니어링 태크닉
      • 고급 프롬프트 엔지니어링 태크닉
        • ReAct Prompting
        • Active-Prompt
        • Reflexion
        • Graph Prompt
      • OpenAI API설정
      • OpenAI를 활용한 프롬프트 엔지니어링 실습
        • 실습 프롬프트
    • 3장 Lang Chain 프레임워크
      • LangSmith 프레임워크
        • LangSmith를 활용한 LangChain 모니터링 설정
      • LangChain 실습 1 - Prompt
        • 실습 코드
      • LangChain 실습 2 - LLM 캐시와 메모리
    • 4장 RAG
      • Document Loader - 문서 로더
      • Text Splitter - 텍스트 분할
      • Embedding - 임베딩
      • Vector Store - 벡터 저장소
      • Retriever - 검색기
      • ReRanker - 재평가자
      • RAG
Powered by GitBook
On this page
  • Intro
  • 페이징 처리 과정
  • 1) 페이징객체 만들기
  • 미리 값을 준비해야 하는 변수들
  • 계산을 통해 값을 구해야하는 변수
  • 2) 페이지객체를 통한 게시글 조회
  • 3) 페이지객체를 통한 페이징바 구현
  1. 프레임워크
  2. Spring
  3. Spring Legacy Project

Pagination

PreviousLoggingNextSpring File 업로드 및 다운로드

Last updated 11 months ago

Intro

  • Pagination이란 게시판과 같은 웹페이지에서 클라이언트가 게시글정보를 요청할때 데이터베이스상에 존재하는 대량의 게시글정보를 여러 Page로 구분하여 클라이언트가 요청한 특정 Page에 해당하는 정보만 제공하는 방식이다.

  • 위 이미지에서 각 썸네일은 1페이지의 "게시글정보"들이고, 하단 1~10페이지까지 이동할수 있는 버튼들을 "페이징바"라고 부른다.

  • 즉 페이징 작업에는 요청한 페이지에대한 게시글 정보들과, 요청한 페이지에서 보여줄 페이징바에 대한 정보를 함께 클라이언트에게 응답해줘야한다.

페이징 처리 과정

  • 요청한 페이지에 맞는 게시글과 페이징 바를 만들기 위해선 페이지 정보를 가지고 있는 페이징 객체를 우선적으로 만들어 줘야 한다.

1) 페이징객체 만들기

//페이징 객체 멤버변수들
@Data
public class PageInfo {
	private int listCount; // 게시글의 총 갯수
	private int currentPage; // 클라이언트가 요청한 페이지
	private int pageLimit; // 한 페이징바당 보여줄 페이지넘버의 갯수
	private int boardLimit; // 한 페이지당 보여줄게시글의 갯수
	
	private int maxPage; // 최대 페이지
	private int startPage; // 페이징바의 시작 페이지넘버
	private int endPage; // 페이징바의 끝 페이지 넘버
}
  • Pagination객체를 만들기 위해서는 계산을 통해 구해야 할 값과, 미리 준비해둬야 할 변수들이 정해져 있다.

미리 값을 준비해야 하는 변수들

  1. listCount : 게시글의 총 갯수로 DB에서 SELECT문을 통해 조회해온다.

  2. currentPage : 클라이언트가 요청한 페이지로 요청 parameter로부터 얻어온다

  3. pageLimit : 하나의 페이징바에 보여줄 페이지넘버의 갯수로 내부 규칙에 의해 고정된 값이 정해진다

  4. boardLimit : 한 페이지에 보여줄 게시글의 갯수로 값을 고정해두는 경우도 있고, 10개씩보기 20개씩 보기등 보여줄 갯수를 클라이언트에게 추가로 위임하는 경우도 있다.

계산을 통해 값을 구해야하는 변수

  1. maxPage : 최대 페이지넘버로 총 개시글 갯수와 게시글당 보여줄 게시글의 갯수에 영향을 받는다 int maxPage =(int)(Math.ceil(((double)listCount/boardLimit)));

  2. startPage : 페이징바의 시작숫자로 현재 요청페이지와 페이징바당 보여줄 페이지넘버의 갯수에 영향을 받는다. int startPage = (currentPage-1) / pageLimit * pageLimit+1;

  3. endPage : 페이징바의 끝수로 startPage와 pageLimit에 영향을 받으며, maxPage에도 영향을 받는다 int endPage = startPage+pageLimit-1;

    if(endPage>maxPage) {
        endPage=maxPage;
    }

2) 페이지객체를 통한 게시글 조회

  • Controller에서는 PageInfo 객체를 생성한후 Service에게 전달하고, Service는 다시한번 Dao에게 전달한다.

  • Dao는 전달받은 PageInfo객체를 통해 요청페이지에 맞는 게시글 정보를 조회한다.

방법1) ROWNUM을 활용한 데이터 조회

  • ORACLE의 ROWNUM은 조회된 순서대로 겹치지 않는 고유한 번호를 매겨주는 가상칼럼으로 INLINE VIEW와 결합하여 올바른 데이터를 조회한다

  • EX) 클라이언트가 요청한 페이지가 1페이지이고, 한페이지당 보여줘야할 게시글의 갯수가 10개인경우? 조회할 데이터는 1번행부터 10개 즉, 1~10번행까지의 데이터를 조회하면 될것이다. 마찬가지로2페이지라면 RNUM은 11 ~ 20까지의 데이터를 조회할수 있도록 꾸미면 된다

SELECT * 
FROM (
       SELECT B.* , ROWNUM RNUM
       FROM 
       (
               SELECT * FROM BOARD
       ) B
      ) C
WHERE RNUM >= 1 AND RNUM <=10;

// 위 코드를 마이바티스 구문으로 바꾸면 아래와 같다.
WHERE RNUM >= 1 AND RNUM <=10 ==> WHERE RNUM >= #{startRow} AND RNUM <=  #{endRow}

// 각 변수에 들어갈 값값
startRow = (currentPage -1) * boardLimit +1
endRow = startRow + boardLimit - 1; 
  • 특징 : 조회할 칼럼이 많아지거나, join문이 많이 들어가면 가독성이 굉장히 나빠질수 있으며 유지보수성또한 떨어질 수 있다. 만약 방법2번과 쿼리수행비용(cost)이 비슷하게 산출이 된다면 가독성이 확보되는 방법2번을 사용하는게 좋을 것 이다.

방법2) RowBounds클래스를 활용한 데이터 조회

  • RowBounds는 위 ROWNUM과는 다른방식으로 응답 페이지에 들어갈 데이터를 조회한다.

  • ROWNUM방식은 데이터를 조회할때 내가 요청한 페이지의 게시글정보만큼만 조회해 왔다면 , RowBounds는 우선 모든 게시글정보를 조회한 후 조회된 행의 offset 위치에서부터 limit만큼 반복을 진행하여 데이터를 조회해온다.

int offset = (pi.getCurrentPage() -1 ) * pi.getBoardLimit(); // 데이터를 조회할 시작행
int limit = pi.getBoardLimit(); // 조회할 갯수
		
RowBounds rowBounds = new RowBounds(offset, limit); // 매개변수로 초기화

return sqlSession.selectList("boardMapper.selectList" , paramMap ,rowBounds);

// sql문쪽 코드
SELECT * FROM BOARD

  • 특징 : 복잡한 조건식이나 중첩 인라인 뷰를 사용할 필요가 없어 읽기에 좋고 유지보수성도 올라간다. 단, DB의 모든 데이터를 조회한후 JAVA-SERVER로 전달하여 데이터 필터링 작업을 수행하게 되는데 이떄 너무 많은 데이터가 JAVA서버로 전달된다면 많은 리소스가 이를 위해 소비될 것이다.

  • 결론 : 데이터를 조회할때 자원의 소비와 가독성 및 유지보수성의 비교를 수행하여 편한 방법으로 코드를 짜면 된다.

3) 페이지객체를 통한 페이징바 구현

  • 서버에서 계산한 PageInfo객체를 클라이언트의 requestSopce에 담아서 전달해주면 클라이언트는 전달받은 페이징 객체를 통해 페이징바를 만들면 된다.

// 페이징바 구현 소스코드
<div id="pagingArea">
<ul class="pagination">
	<c:if test="${pi.currentPage eq 1 }">
		<li class="page-item">
        		<a class="page-link">Previous</a>
        	</li>
	</c:if>
	<c:if test="${pi.currentPage ne 1 }">
       		<li class="page-item">
        		<a class="page-link" href="${url}${pi.currentPage -1}${sUrl}">Previous</a>
        	</li>        		
	</c:if>
	<c:forEach var="i" begin="${pi.startPage }" end="${pi.endPage }">
        	<li class="page-item">
        		<a class="page-link" href="${url}${i}${sUrl}">${i}</a>
        	</li>	
	</c:forEach>      
			  		
	<c:if test="${pi.currentPage eq pi.maxPage }">
		<li class="page-item">
        		<a class="page-link">Next</a>
        	</li>
	</c:if>
	<c:if test="${pi.currentPage ne pi.maxPage }">
       		<li class="page-item">
        		<a class="page-link" href="${url}${pi.currentPage +1}${sUrl}">Next</a>
        	</li>        		
	</c:if>
</ul>
</div>

게시글과 페이징바