API로 코딩하기
API로 코딩하기서버(PHP)와 클라이언트(JS) 양쪽의 블록 렌더링에 DRY 코드 사용하기

서버(PHP)와 클라이언트(JS) 양쪽의 블록 렌더링에 DRY 코드 사용하기

동적(Gutenberg) 블록은 프론트엔드에서 블록이 렌더링될 때 구조와 콘텐츠를 동적으로 구성하는 블록입니다.

동적 블록을 프론트엔드(WordPress 에디터에 표시하기 위해)와 서버 측(블로그 게시물의 HTML을 생성하기 위해)에서 렌더링할 때, 일반적으로 두 가지 서로 다른 방식으로 데이터를 가져옵니다.

  • 클라이언트 측(JavaScript)에서 API에 연결
  • 서버 측(PHP)에서 WordPress 함수 호출

Gato GraphQL과 확장 기능을 사용하면 이 로직을 DRY하게 만들어, 클라이언트 측과 서버 측 모두에서 데이터를 가져오는 단일 진실 공급원을 가질 수 있습니다. 그 방법을 살펴보겠습니다.

GraphQL 쿼리를 .gql 파일에 저장하기

클라이언트에서 GraphQL 서버에 연결하려면, 일반적으로 JavaScript 코드 내에 GraphQL 쿼리를 직접 삽입하여 실행합니다. 예를 들면 다음과 같습니다.

const response = await fetch(endpoint, {
  body: JSON.stringify({
    query: `
      query {
        posts {
          id
          title
          author {
            id
            name
          }
        }
      }
    `
  )
} );

대신 GraphQL 쿼리를 .gql(또는 .graphql) 파일에 저장하고, Webpack의 raw-loader를 사용해 그 내용을 가져올 수도 있습니다.

// File webpack.config.js
const config = require( '@wordpress/scripts/config/webpack.config' );
 
config.module.rules.push(
  {
    test: /\.(gql|graphql)$/i,
    use: 'raw-loader',
  },
);
 
module.exports = config;

(이 코드는 Webpack v4용입니다. v5에서는 대신 Asset Modules를 사용해야 합니다.)

다음으로, GraphQL 쿼리를 .gql 파일에 작성합니다.

# File graphql-documents/fetch-posts-with-author.gql
query {
  posts {
    id
    title
    author {
      id
      name
    }
  }
}

마지막으로, 블록 코드 내에서 파일을 가져와 그 내용을 fetch에 전달합니다.

import graphQLQuery from './graphql-documents/fetch-posts-with-author.gql';
 
// ...
 
const response = await fetch(endpoint, {
  body: JSON.stringify({
    query: graphQLQuery
  )
} );

서버 측에서 .gql 파일 처리하기

위에서 생성한 GraphQL 파일이 블록의 데이터 가져오기를 위한 단일 진실 공급원이 됩니다. 클라이언트 측은 이미 해결되었으므로, 이제 서버 측에서 어떻게 처리하는지 알아보겠습니다.

Internal GraphQL Server 확장 기능은 PHP 코드를 사용하여 애플리케이션 내에서 호출할 수 있는 서버를 설치합니다.

Internal GraphQL Server는 GraphQLServer 클래스를 통해 다음과 같은 정적 메서드를 제공합니다.

  • executeQuery: GraphQL 쿼리 실행
  • executeQueryInFile: (.gql) 파일에 포함된 GraphQL 쿼리 실행
  • executePersistedQuery: 영속화된 GraphQL 쿼리 실행(ID를 int로, 또는 슬러그를 string으로 제공) (Persisted Queries 확장 기능 필요)

executeQueryInFile의 시그니처는 다음과 같습니다.

namespace GatoGraphQL\InternalGraphQLServer;
 
class GraphQLServer {
  /**
   * Execute a GraphQL query contained in a (`.gql`) file
   */
  public static function executeQueryInFile(
      string $file,
      array $variables = [],
      ?string $operationName = null
  ): Response {
    // ...
  }
}

앞서 생성한 .gql 파일을 전달하여 executeQueryInFile을 호출하면, 동적 블록을 렌더링할 때 데이터를 가져올 수 있습니다.

use GatoGraphQL\InternalGraphQLServer\GraphQLServer;
 
$block = [
  'render_callback' => function(array $attributes, string $content): string {
    // Provide the GraphQL query file
    $file = __DIR__ . '/blocks/my-block/graphql-documents/fetch-posts-with-author.gql';
 
    // Execute the query against the internal server
    $response = GraphQLServer::executeQueryInFile($file);
 
    // Get the content and decode it
    $responseContent = json_decode($response->getContent(), true);
 
    // Access the data and errors from the response
    $data = $responseContent["data"] ?? [];
    $errors = $responseContent["errors"] ?? [];
 
    // Do something with the data
    // $content = $this->useGraphQLData($content, $data, $errors);
    // ...
 
    return $content;
  },
];
register_block_type("namespace/my-block", $block);

이처럼 단일 .gql 파일로 클라이언트 측과 서버 측 모두에서 블록에 데이터를 제공할 수 있습니다.