[커서기반페이징] 3.커서기반페이징 API Request/Response의 BestPractice를 찾아서
뭐든지 잘 만드는게 중요하니까 리서치해보는 Best Practice 시간.
시리즈
3.커서기반페이징 API Request/Response의 BestPractice를 찾아서
서론(+잡담)
뭐든 이론을 살피고 난 후 POC(개념실증)을 만들었다고 끝나는것이 아니라고 생각한다.
나만 이해갔다고 해서 출시를 해버리면
시간이 흐른 뒤, 다른 개발자들이 살펴볼때
‘얘는 왜 이렇게 했지..?’라는 의문을 가져버린다면..
참 여러모로 골치아파진다. (부끄럽기도하고..)
따라서 이론 구현의 모범사례나 관례가 있다면 따르는것이 좋다는 개인적인 의견에서 비롯한!
커서기반페이징 API에서 사용되는 요청/응답 데이터 형식의 모범사례 찾기 시간을 가져볼까 한다.
1.현황
일단 현황부터 정리해보자.
1.1.Request
- cursor( “idx” + “,” + “time” 형식을 base64 인코딩 한)
- limit
1.2.Response
- data (cursor와 limit 범위에 해당하는 데이터리스트)
- cursor( “idx” + “,” + “time” 형식을 base64 인코딩 한)
2.주요개념
- 커서는 데이터리스트에서 특정 항목을 표시하는 임의의 문자열을 가르킨다
- 커서는 항상 그 항목을 가르키지만, 항목이 삭제되면 무효화된다.
- 따라서 커서가 계속 유효할것이라고 가정하지 말아야 한다.
3.커서 응답데이터 포멧
Facebook API를 벤치마크했습니다.
"paging": {
"cursors": {
"after": "MTAxNTExOTQ1MjAwNzI5NDE=",
"before": "NDMyNzQyODI3OTQw"
},
"previous": "https://graph.facebook.com/{your-user-id}/albums?limit=25&before=NDMyNzQyODI3OTQw"
"next": "https://graph.facebook.com/{your-user-id}/albums?limit=25&after=MTAxNTExOTQ1MjAwNzI5NDE="
}
-
before
- 반환된 데이터 페이지의 시작을 가르키는 커서
-
after
- 반환된 데이터 페이지의 끝을 가르키는 커서
-
limit
- 반환될 수 있는 최대 개체 수
-
next
- 데이터의 다음 페이지를 반환하는 엔드포인트
- 이 데이터가 포함되어있지 않으면, 현재 페이지가 마지막 페이지임을 나타냄
-
previous
- 데이터의 이전 페이지를 반환하는 엔드포인트
- 이 데이터가 포함되어있지 않으면, 현재 페이지가 첫번째 페이지임을 나타냄
4.인사이트
- Cursor을 반환하지만, 이것도 결국 Paging기법 중 하나이므로 Paging으로 감싼다.
- Cursor에는 After과 Before을 추가하여, 데이터의 시작과 끝 정보를 제공한다.
- 이것으로 현재페이지가 첫페이지인지, 마지막페이지인지의 정보를 제공할 수 있다.
- Next와 Previous를 제공하여 클라이언트의 API사용 편의성을 높인다.
5.적용
5.1.Before
"cursor": "Mzg4MTQ0MywyMDIyLTAzLTE3IDEzOjA1OjQw"
5.2.After
배경설정
- 총 8개의 데이터가 존재한다고 했을 때
- [1,2,3,4,5,6,7,8]
- 3개씩 호출한다고 했을 때
5.2.3.최초 조회 시, 페이징 결과 값 (이전데이터 없음)
"paging": {
"cursor": {
"after": "MTk2MTQ3NzAsMjAyMy0wOC0wNyAyMjo0MDowNw=="
},
"next": "endpoint/limit=3&after=MTk2MTQ3NzAsMjAyMy0wOC0wNyAyMjo0MDowNw=="
}
- [1,2,3]반환
5.2.4.다음 조회 시, 페이징 결과 값 (이전/이후 데이터 있음)
"paging": {
"cursor": {
"before": "MTk2MTQ3NzAsMjAyMy0wOC0wNyAyMjo0MDowNw==",
"after": "MTk1ODcyMDEsMjAyMy0wNS0wMiAxMDozMToxMg=="
},
"previous": "endpoint/limit=3&before=MTk2MTQ3NzAsMjAyMy0wOC0wNyAyMjo0MDowNw==",
"next": "endpoint/limit=3&after=MTk1ODcyMDEsMjAyMy0wNS0wMiAxMDozMToxMg=="
}
- [4,5,6]반환
5.2.5.다음 조회 시, 페이징 결과 값 (이후 데이터 없음)
"paging": {
"cursor": {
"before": "MTk1ODcyMDEsMjAyMy0wNS0wMiAxMDozMToxMg=="
},
"previous": "https://api.imtest.me/v2/external-review-service/members?limit=3&before=MTk1ODcyMDEsMjAyMy0wNS0wMiAxMDozMToxMg=="
}
- [7,8]반환
5.3.문제점
5.3.1.after와 before을 제외하는 경우를 어떻게 판단 할 수 있을까?
5.3.1.1.after를 제외하는 경우
마지막 데이터를 의미한다.
limit보다 적은 데이터가 반환될 때 를 기준으로 할 경우
- 3개씩 조회하는데 총 9개의 데이터가 있을 경우에는 limit보다 적은 데이터가 반환 될 수 없다
어떻게 처리할 수 있을까?
5.3.1.2.before를 제외하는 경우
첫번째 데이터를 의미한다.
after로 조회할 때 를 기준으로할 경우
- after나 before 파라미터를 주지않는 최초조회의 경우 체크 불가능
- before로 조회할 때 에도 이전 데이터가 있을 수 있다.
어떻게 처리할 수 있을까?
5.3.2. 해결
N+1개의 데이터를 조회하는 방식으로 해결할 수 있다.
사용자가 3개를 요청했을 때, 3개가 아니라 4개를 요청하는것이다.
상세히 정리해보자.
-
after
- after로 조회한다면 반환값-before는 무조건 존재한다
- N+1개의 데이터를 전부 가져올 수 있다면 반환값-after는 존재한다
- 가져올 수 없다면 반환값-after는 존재하지 못한다.
-
before
- before로 조회한다면 반환값-after는 무조건 존재한다
- 커서없이 조회한다면(최초조회) 반환값-before는 존재하지못하여 반환값-after는 존재한다.
- N+1개의 데이터를 전부 가져올 수 있다면 반환값-before는 존재한다.
- 가져올 수 없다면 반환값-before는 존재하지 못한다.