반응형
청춘고양이
배움을 기록하는 곳
청춘고양이
전체 방문자
오늘
어제
  • Hello World (119)
    • JQuery (5)
    • In my opinion (4)
    • HTML&CSS (8)
    • JS (9)
    • JAVA (21)
    • Spring Boot (21)
    • Node.js (1)
    • Linux (7)
    • Git (2)
    • Kotlin (4)
    • Fluttor (4)
    • 정보처리기사 (19)
    • AWS (1)
    • Oracle (8)
    • MySQL (3)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 자바db연동
  • 자바
  • 가위바위보js
  • 초보개발
  • 제이쿼리
  • 제이쿼리 비밀번호
  • css
  • js
  • js 비밀번호
  • 제이쿼리 버튼클릭시 색 변경
  • spring 기본설정
  • 스크롤js
  • 청춘고양이
  • js 로또 번호
  • ScrollEffectJs
  • js 패스워드 변경
  • 제이쿼리 패스워드 변경
  • 객체 안의 함수
  • 중복 제거 로또
  • 쉬프트 연산

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
청춘고양이

배움을 기록하는 곳

Spring Boot

효율적인 데이터 로딩: Spring Boot과 MyBatis로 구현하는 페이징 처리

2024. 6. 21. 16:16
반응형

1. 서론

페이징 처리란? 페이징 처리는 많은 양의 데이터를 한 번에 모두 가져오는 대신, 일부만 가져와서 화면에 보여주는 기법입니다. 이를 통해 성능을 개선하고 사용자의 경험을 향상시킬 수 있습니다.

왜 페이징 처리가 필요한가? 대량의 데이터를 한 번에 처리하면 메모리와 성능에 큰 부담을 주게 됩니다. 페이징 처리를 통해 필요한 데이터만 가져와서 처리함으로써 이러한 문제를 해결할 수 있습니다.

2. 페이징 처리의 기본 개념

페이징의 기본 원리

  • 데이터를 일정한 크기로 나누어 각 페이지에 해당하는 부분만 가져오는 방식입니다.
  • 클라이언트에서 요청하는 페이지 번호와 한 페이지당 항목 수를 기준으로 데이터베이스에서 필요한 부분만 쿼리합니다.

주요 용어

  • 페이지(Page): 데이터를 나누는 단위입니다.
  • 오프셋(Offset): 현재 페이지의 시작 지점을 나타냅니다.
  • 한 페이지당 항목 수: 한 페이지에 표시할 데이터의 개수입니다.

3. 페이징 처리 구현 예제

Spring Boot와 MyBatis를 이용한 페이징 처리

4. 코드 예제

Controller

@RestController
@RequestMapping("/api/qna")
public class QnaController {

    private final QnaService qnaService;

    @Autowired
    public QnaController(QnaService qnaService) {
        this.qnaService = qnaService;
    }

    @GetMapping("/")
    public ModelAndView getIndex(
            @RequestParam(value = "tab", required = false, defaultValue = "help") String tab,
            @RequestParam(value = "page", required = false, defaultValue = "1") int page) {
        ModelAndView modelAndView = new ModelAndView("qna/index");

        int totalArticles = qnaService.getArticleTotalCount(tab);
        PagingModel pagingModel = new PagingModel(totalArticles, page);
        
        List<QnaArticleEntity> articles = qnaService.getArticlesByTab(tab, pagingModel);
        
        modelAndView.addObject("articles", articles);
        modelAndView.addObject("pagingModel", pagingModel);
        
        return modelAndView;
    }
}

Model (Model로 PagingModel로 만들어 사용하는 방식이 효율적입니다.)

public class PagingModel {
    // 기본적으로 한 페이지에 표시할 행(row)의 개수
    public static final int DEFAULT_ROW_COUNT_PER_PAGE = 20;

    // 전체 행(row)의 개수 (총 게시글의 개수)
    private final int totalRowCount;
    // 요청된 페이지 번호
    private final int requestPage;
    // 한 페이지에 표시할 행(row)의 개수
    private final int rowCountPerPage;

    /**
     * 생성자: 전체 행(row)의 개수와 요청된 페이지 번호를 받아서 PagingModel 객체를 생성한다.
     * 
     * @param totalRowCount 전체 행(row)의 개수
     * @param requestPage   요청된 페이지 번호
     */
    public PagingModel(int totalRowCount, int requestPage) {
        // 전체 행(row)의 개수를 설정
        this.totalRowCount = totalRowCount;
        // 요청된 페이지 번호가 1보다 작으면 1로 설정
        this.requestPage = requestPage < 1 ? 1 : requestPage;
        // 기본 행(row) 개수를 설정
        this.rowCountPerPage = DEFAULT_ROW_COUNT_PER_PAGE;
    }

    /**
     * @return 현재 페이지에서의 시작 인덱스 (0부터 시작)
     */
    public int getStartIndex() {
        return (requestPage - 1) * rowCountPerPage;
    }

    /**
     * @return 한 페이지에 표시할 행(row)의 개수
     */
    public int getRowCountPerPage() {
        return rowCountPerPage;
    }
}

Service

@Service
public class QnaService {

    private final QnaMapper qnaMapper;

    @Autowired
    public QnaService(QnaMapper qnaMapper) {
        this.qnaMapper = qnaMapper;
    }

    public int getArticleTotalCount(String tab) {
        return qnaMapper.countArticlesByTab(tab);
    }

    public List<QnaArticleEntity> getArticlesByTab(String tab, PagingModel pagingModel) {
        return qnaMapper.selectArticlesByTab(tab, pagingModel.getStartIndex(), pagingModel.getRowCountPerPage());
    }
}

Mapper

@Mapper
public interface QnaMapper {

    @Select("SELECT COUNT(*) FROM qna_articles WHERE category = #{tab}")
    int countArticlesByTab(@Param("tab") String tab);

    @Select("SELECT * FROM qna_articles WHERE category = #{tab} LIMIT #{count} OFFSET #{offset}")
    List<QnaArticleEntity> selectArticlesByTab(@Param("tab") String tab, @Param("offset") int offset, @Param("count") int count);
}

SQL 쿼리

SELECT COUNT(*) FROM qna_articles WHERE category = #{tab};
SELECT * FROM qna_articles WHERE category = #{tab} LIMIT #{count} OFFSET #{offset};

5. 결론

페이징 처리의 이점

  • 성능 향상: 필요한 데이터만 가져와서 처리하기 때문에 성능이 크게 향상됩니다.
  • 사용자 경험 개선: 빠른 응답 시간과 필요한 정보만 보여줌으로써 사용자 경험이 향상됩니다.

페이징 처리 시 주의사항

  • 페이지 번호와 같은 입력 값은 항상 유효성을 검사해야 합니다.
  • 페이지를 이동할 때마다 동일한 쿼리를 반복적으로 실행하지 않도록 캐싱 등을 고려할 수 있습니다.
반응형
저작자표시 변경금지 (새창열림)

'Spring Boot' 카테고리의 다른 글

메서드 체이닝과 빌더 패턴을 활용한 엔티티 클래스 구현  (0) 2024.06.24
댓글 시스템 데이터베이스(MySQL) 설계 및 MyBatis를 이용한 댓글 수 조회  (0) 2024.06.24
스프링 부트에서 @Transactional을 활용한 트랜잭션 관리  (0) 2024.06.21
미디어 관련 공부#3  (0) 2022.09.12
미디어 관련 공부#2  (0) 2022.08.30
    'Spring Boot' 카테고리의 다른 글
    • 메서드 체이닝과 빌더 패턴을 활용한 엔티티 클래스 구현
    • 댓글 시스템 데이터베이스(MySQL) 설계 및 MyBatis를 이용한 댓글 수 조회
    • 스프링 부트에서 @Transactional을 활용한 트랜잭션 관리
    • 미디어 관련 공부#3
    청춘고양이
    청춘고양이
    신입개발자

    티스토리툴바