Skip to content

[개발 위키] 검색 쿼리 pagination cursor 방식 명세

kimhji edited this page Feb 3, 2025 · 1 revision

원리

cursor 데이터를 활용한 where 문을 통해, 불필요한 행에 대한 연산을 제외하여 page 데이터의 load 속도 개선

기존의 skip은 건너 뛰어야 할 행이 많을 수록 더 느려짐. 이는 sql에 skip이 효율적으로 되는 방식이 없고 행을 읽어와서 스캔하는 과정이 선행되어야 하기 때문.

이를 방지하기 위해 최신순 정렬 후 skip이 아닌 where문을 통해 order_id를 기준으로 불필요한 행을 아예 가져오지 않도록 하기 위함.

  • 유의 사항
    • 현재 페이지 기준으로 이동하기 때문에 현재 페이지와 먼 페이지로 이동 시, 성능이 저하될 수 있음
      • 해당 서비스에서는 검색 페이지 이동이 최대 2페이지 최소 1페이지까지만 좌우로 이동 가능하기 때문에 이는 현재로써 크게 문제되지 않음.

** 참고자료

https://stackoverflow.com/questions/54820978/why-skip-and-take-is-taking-longer-time-when-the-record-being-fetched-is-get

데이터 흐름

커서 정보 내용 : 현재 페이지 정보

→ 검색어, 현재 page, 현재 페이지 첫 feed의 order_id, 현재 페이지 마지막 feed의 order_id

  • client가 검색: cursor 데이터 없이 기존 api 그대로 보내면 됨.

  • server가 응답: 기존에 주던 페이지 데이터와 함께 추가로 cursor 데이터를 줌.

  • client가 페이지 이동: 검색 시 server가 줬던 cursor 정보와 함께 기존 api 보내기.

  • server가 응답: 기존에 주던 페이지 데이터와 함께 추가로 cursor 데이터를 줌.

검색 api

기존

image (2)

  • 200 OK

    {
      "message": "검색 결과 조회 완료",
      "data": {
        "totalCount": 1,
        "result": [
          {
            "id": 1,
            "blogName": "블로그 이름",
            "title": "데나무",
            "path": "https://test.com/1",
            "createdAt": "2024-10-27T02:08:55.000Z"
          }
        ],
        "totalPages": 3,
        "limit": 1
      }
    }

변경 후

  • 요청

    GET /api/feed/search

    Param

    • find: [string]

    • type: [string]

    • page: [number]

    • limit: [number]

    • cursor?: [json]

      { curPage : [number], preIndex: { feedId: [number],

            createAt: [string]
        },
        nextIndex: {
            feedId: [number],
      
            createAt: [string]
        }
      

      }

  • 응답

    {
      "message": "검색 결과 조회 완료",
      "data": {
        "totalCount": 1,
        "result": [
          {
            "id": 1,
            "blogName": "블로그 이름",
            "title": "데나무",
            "path": "https://test.com/1",
            "createdAt": "2024-10-27T02:08:55.000Z"
          }
        ],
        "totalPages": 3,
        "limit": 1,
        "cursor":{
          "curPage" : 1,{
          "preIndex": {
            "feedId": 2323,
            "createAt": "2024-10-27T02:08:55.000Z"
          },
          "nextIndex": {
            "feedId": 2323,
            "createAt": "2024-10-27T02:08:55.000Z"
          },
        }
      }
    }
    • 위 응답의 cursor 정보를 client가 저장하고 이후에 page 변동 시 해당 cursor 데이터를 함께 보내주면 됨.
    • client가 가지고 있는 cursor 정보는 1개 뿐이며, 현재 page의 cursor 정보만 가지고 있으면 됨. page 변동 시 그 cursor 데이터를 함께 보내주어야 함.

🎋DENANNU

👮🏻 팀 규칙

*️⃣ 기술로그

공통

프로젝트 문서

트러블슈팅

김현지

프로젝트 문서

트러블슈팅

양현호

프로젝트 문서

트러블슈팅

정지혜

프로젝트 문서

트러블슈팅

한영준

프로젝트 문서

트러블슈팅

🗓️ 주간 스프린트 기록

📚 회의록

🍵 주간회고

Clone this wiki locally