Stored Procedure 를 이용해 Pagination 구현하기

본 글에서는 레거시 환경에서 SQL Server Stored Procedure를 사용하여 페이지네이션을 구현한 경험과 함께 Single Responsibility Principle을 지키기 위한 노력을 소개합니다.

좋지 않은 패턴이지만, Sql Server 의 Stored Procedure 를 이용해 게시판의 Pagination 기능을 구현할 일이 있었다. DB 에서 이러한 스크립트를 작성하여 사용하는 것이 어색했지만, 당장 마이그레이션 할 수 없는 Legacy 서비스여서, Stored Procedure 작성법을 공부해 가며 유틸 함수 기능을 하는 스크립트를 작성하였다. Stored Procedure 는 SQL 을 사용하므로 자료구조에도 제한이 있고, 객체지향 및 함수형 프로그래밍에도 제한이 있다. 이러한 특성 때문에 더 레거시 코드가 양산되기 쉬운 환경이라고 느꼈다. 그래서 더더욱 스크립트의 역할을 하나로 분리하여 Single Responsibility Principle 을 지키고자 노력하였다. 빠르게 마이그레이션 계획을 잡아봐야 겠다.

-- =============================================
-- Author: Heejae Kim
-- Created Date: 2020-09-23
-- Modified Date: 
-- Description: Make Pagination
-- Example: EXEC [dbo].[util_v1_02_PageNavigator] 100, 3
-- =============================================
ALTER PROCEDURE [dbo].[util_v1_01_PageNavigator]
(
  @p_TotalCount INT = 0,
  @p_DisplayRow INT = 5,
  @p_CurrentPage INT = 1,
  @p_DisplayPage INT = 5,
  @p_RangeSize INT = 5
)
AS
SET NOCOUNT ON

  DECLARE @in_DataName NVARCHAR(50)
  DECLARE @in_Range INT 
  DECLARE @in_TotalPage INT
  DECLARE @in_BeginPage INT 
  DECLARE @in_EndPage INT 
  DECLARE @in_StartRowNum INT 
  DECLARE @in_EndRowNum INT 
  DECLARE @in_HasPrev VARCHAR(10)
  DECLARE @in_HasNext VARCHAR(10)

  SET @in_DataName = 'Pagination'

  SET @in_Range = CEILING(CAST(@p_CurrentPage AS FLOAT) / CAST(@p_DisplayRow AS FLOAT))
  SET @in_TotalPage = CEILING(CAST(@p_TotalCount AS FLOAT) / CAST(@p_DisplayRow AS FLOAT))
  SET @in_BeginPage = (@in_Range - 1) \* @p_RangeSize + 1
  IF(CEILING(CAST((@p_TotalCount / @p_DisplayRow) AS FLOAT)) > @in_Range \* @p_RangeSize)
  BEGIN 
    SET @in_EndPage = @in_Range \* @p_RangeSize
    END 
    ELSE 
    BEGIN 
    SET @in_EndPage = CEILING(CAST((@p_TotalCount / @p_DisplayRow) AS FLOAT))
    END 

    SET @in_StartRowNum = (@p_CurrentPage-1) \* @p_DisplayRow + 1 
    SET @in_EndRowNum = @p_CurrentPage \* @p_DisplayRow

    IF(@in_Range=1)
    BEGIN 
      SET @in_HasPrev = 'false'
    END
    ELSE 
    BEGIN 
      SET @in_HasPrev = 'true'
    END 

    IF(@in_EndPage >= @in_TotalPage)
    BEGIN 
      SET @in_HasNext = 'false'
    END 
    ELSE 
    BEGIN 
      SET @in_HasNext = 'true'
    END 

    IF(@in_EndPage > @in_TotalPage)
    BEGIN 
      SET @in_EndPage = @in_TotalPage
    SET @in_BeginPage = @in_EndPage - @p_DisplayPage + 1
    SET @in_HasNext = 'false'
 END 

 IF(@in_BeginPage < 0)
 BEGIN 
   SET @in_BeginPage = 1
   SET @in_EndPage = @in_BeginPage + @p_DisplayRow - 1 
   SET @in_HasPrev = 'false'
 END 

SELECT @p_TotalCount AS 'TotalCount', 
  @p_CurrentPage AS 'CurrentPage', 
  @p_DisplayPage AS 'DisplayPage', 
  @p_DisplayRow AS 'DisplayRow', 
  @in_Range AS 'Range',
  @p_RangeSize AS 'RangeSize',
  @in_StartRowNum AS 'StartRowNum',
  @in_EndRowNum AS 'EndRowNum',
  @in_TotalPage AS 'TotalPage',
  @in_BeginPage AS 'BeginPage',
  @in_EndPage AS 'EndPage',
  @in_HasPrev AS 'HasPrev',
  @in_HasNext AS 'HasNext'

 


이것도 읽어보세요