Apollo Server+Nexus+Prism에서 GraphiQL 개발: Relay 2 따르기

이 글은 나의 아버지 5일째 되는 글이다.

Recruit 표시


주식회사 토리토리토리는 엔지니어를 모집 중이다.
관심 있는 사람은 반드시 나의 트위터에 투고하세요!서로 기준치가 생기다.
https://toridori.co.jp/

종지


저번 보도에서는 Nexus에서 Relay의 GUID/노드를 따르는 방법에 대해 설명합니다.
이번 기사에서는 릴레이의 페이지에 대해 해설을 하고자 합니다.
술 많이 마셔서 힘들어요. 오늘은 간단하게...

Relay의 호출


Relay의 페이지 나누기 시스템에는 다음 매개변수가 있습니다.
  • first
  • after
  • last
  • before
  • 여기서 firstafter는 "after에서 지정한 ID의 노드의 다음 노드에서 first 지정된 수량의 노드로 되돌아온다"는 뜻이다.
    또한lastbefore는 "before에서 지정한 ID의 노드 이전 노드에서 반환last된 수량의 노드(앞으로)"를 의미합니다.
    실용적으로lastbefore가 무엇에 쓰이는지 잘 모르겠어요(때로는 앞쪽으로 붙이고 싶어요)관례대로 하는 것 같으니 실현해야 한다.

    prisma-relay-cursor-connection


    세계에prisma-relay-cursor-connection이라는 프로그램 라이브러리가 있습니다. 이 라이브러리는Presma로 Relay를 붙여넣은 것입니다. 이용하세요.npm i @devoxa/prisma-relay-cursor-connection 설치.
    또한relay의 접착을 실현하기 위해 다음과 같은 편집src/schema.ts을 했습니다.
    src/schema.ts
    plugins: {
      connectionPlugin({
        extenedConnection: {
          totalCount: { type: 'Int', requireResolver: false },
        }
      })
    }
    
    여기에 한 열totalCount을 추가했습니다.
    이것은 페이지를 나누는 것을 고려하지 않고 모든 노드의 수를 되돌려 주는 열입니다.

    Query에 prisma-relay-cursor-connection 적용


    앞의 두 글에서 소개한 포스트의Query는prisma-relay-cursor-connection을 적용한다.
    src/query/post.ts
    export const searchPosts = extendType({
      type: 'Query',
      definition(t) {
        t.connectionField('posts', {
          type: 'Post',
          additionalArgs: {
            search: stringArg({ nullable: true }),
          },
          resolve(_root, args, ctx){
            const baseArgs = {
              where: {
                OR: [
                  { title_contains: args.search },
                  { content_contains: args.search },
                ],
              },
            };
            return findManyCursorConnection<Campaign, {databaseId: bigint}>(
              (_args) => ctx.prisma.post.findMany({..._args, ...baseArgs}),
              () => ctx.prisma.post.count(baseArgs),
              { ...args },
              {
                getCursor: (record) => ({ databaseId: record.databaseId }),
                encodeCursor: (cursor) => Buffer.from('Post:' + cursor.databaseId).toString('base64'),
                decodeCursor: (cursor) => ({databaseId: Buffer.from(cursor, 'base64').toString().split(':')[1]}),
              }
            )
          }
        })
      }
    })
    
    복잡하지만 다음과 같은 느낌이 든다.
  • additionalArgs: first, last 등 이외의 매개 변수를 지정합니다.
  • baseArgs:additionalArgs를 통해 where 또는 orderBy.
  • getCursor: 붙여넣을 ID를 지정합니다.데이터베이스 Id면 될 것 같습니다.
  • encodeCursor: 붙여넣을 커서를 지정합니다.우리는 GUID라는 무기가 있으니 이 정도면 되겠지.
  • decodeCursor: 붙여넣은 커서의 디코딩 방법을 지정합니다.GUID에서 데이터베이스 ID를 가져오면 되죠.
  • 주의점


    위에서 말한 바와 같이 붙여넣기는 잘 가능하지만, 실제 발매되는 SQL은 확인해보는 게 좋다.
    특히 orderBy를 index가 아닌 열로 지정하면 속도 면에서 불안할 수 있다.
    앞의 두 문장에서 지정한 SQL을 표준 출력으로 출력합니다:.
    src/context.ts
    prisma.$on('query', (e) => {
      console.log(e)
    })
    

    뭐가 그리 좋으냐


    솔직히 서버 쪽은 잘 모르지만 이걸 따른다면 아폴로 클라이언트와 릴레이가 클라이언트 쪽에서 잘 할 수 있을 거예요.
    질의는 물론, 객체의 Resolver에도 많은 양의 데이터가 반환될 위험이 있는 경우 페이지를 만듭니다.

    끝말


    오늘은 너무 짧아서 죄송합니다. 제가 스티커를 설명해 드렸어요.
    다음에는 발리 데이 등 다른 요소를 설명한다.

    좋은 웹페이지 즐겨찾기