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'
이것도 읽어보세요