블로그

PHP만으로 커스텀 블록 만들기. 오래된 숏코드여, 안녕 🥳

David Wang
작성자: David Wang ·

WordPress 5.0이 블록 에디터를 도입한 이후로, Gutenberg 블록을 만들려면 React, Node.js, 그리고 빌드 파이프라인이 필요했습니다. PHP를 전문으로 하는 분들 — 저를 포함해 많은 WordPress 개발자들처럼 — 에게 있어, 그 장벽은 거의 10년 동안 참여를 가로막아 왔습니다. WordPress 7.0이 이것을 바꿉니다. PHP 전용 블록을 사용하면 단일 PHP 파일과 autoRegister 플래그만으로 완전히 기능하는 Gutenberg 블록을 등록할 수 있습니다.

PHP를 작성하면 블록을 얻을 수 있습니다. 툴링 불필요. 빌드 불필요. 🥳 이 글에서는 PHP 전용 블록의 작동 방식을 설명하고, 클래식 숏코드를 블록으로 대체하는 실제 예제를 소개합니다.

PHP 전용 블록이란?

지금까지 커스텀 Gutenberg 블록을 만들려면 JavaScript 툴체인 설정이 필요했습니다. npm install, block.json 파일, webpack.config.js@wordpress/scripts 빌드 단계, 그리고 JSX로 작성된 edit.js 컴포넌트가 필요했습니다. 변경 사항이 있을 때마다 에디터에서 확인하기 전에 컴파일 단계가 필요했습니다. 단순한 표시 블록을 등록하고 싶은 PHP 개발자에게 그 오버헤드는 항상 작업에 비해 과도하게 느껴졌습니다.

PHP 전용 블록은 이 모든 것을 해결합니다. 이제 register_block_type()'autoRegister' => true를 전달하기만 하면, WordPress가 ServerSideRender를 사용해 JavaScript 측의 모든 것을 자동으로 처리합니다. 블록은 삽입기에 나타나고, 캔버스에 라이브 미리보기가 렌더링되며, 사이드바에 Inspector Controls가 생성됩니다 — 모두 JavaScript 코드 한 줄 없이.

컨트롤은 속성 타입에 따라 자동으로 생성됩니다:

속성 타입생성되는 Inspector Control
string텍스트 입력
integer / number숫자 입력
boolean토글
string + enum드롭다운 선택

자동 생성 컨트롤은 현재 위의 네 가지 타입만 지원합니다. 이미지 피커, 미디어 업로드, 중첩된 데이터와 같이 더 복잡한 것은 아직 지원되지 않으며 JavaScript로 등록된 블록이 필요합니다. 개발자는 개별 속성에 local 역할을 표시하여 내부 상태로 지정할 수도 있습니다. WordPress는 사이드바 컨트롤을 구성할 때 이를 건너뜁니다.

PHP 전용 블록은 추가 종속성 없이 WordPress 7.0에서 오늘부터 사용할 수 있습니다. Make WordPress Core의 공식 개발자 노트에서 더 자세히 알아보세요.

이것은 누구를 위한 것인가요?

JavaScript에 대한 깊은 전문 지식이 없는 소규모 에이전시와 프리랜서가 이제 빌드 파이프라인을 건드리지 않고도 WordPress 네이티브 기능을 최대한 활용하는 블록 에디터 솔루션을 만들 수 있게 되었습니다. 숏코드에 의존하지 않고 저자 박스, 풀 인용구, 추천사, CTA 배너, 공지사항 등 테마별 커스텀 Gutenberg 블록을 제공하고 싶다면, PHP 전용 블록이 그 장벽을 크게 낮춰줍니다.

인라인 리치 텍스트 편집, 실시간 반응형 UI, 또는 내부 블록 중첩이 필요한 경우에는 JavaScript로 등록된 블록의 대안이 될 수 없습니다 — 하지만 구조화된 표시 블록의 많은 경우에는 최적의 선택이 됩니다.

이전 방식: 숏코드

PHP 전용 블록이 등장하기 전, PHP 개발자의 현실적인 접근 방식은 숏코드였습니다. 저자 이름, 회사명, 별점이라는 세 가지 속성과 리뷰 텍스트를 위한 내부 콘텐츠를 가진 간단한 추천사 숏코드의 예입니다:

function testimonial_shortcode( $atts, $content = '' ) {
    $atts = shortcode_atts( [
        'name'    => '',
        'company' => '',
        'stars'   => 5,
    ], $atts );
 
    $stars_count = max( 1, min( 5, intval( $atts['stars'] ) ) );
    $stars_html  = str_repeat( '★', $stars_count )
                 . str_repeat( '☆', 5 - $stars_count );
 
    return sprintf(
        '<blockquote class="testimonial">
            <p class="testimonial__stars">%s</p>
            <p class="testimonial__body">%s</p>
            <footer class="testimonial__attribution">
                <strong>%s</strong>%s
            </footer>
        </blockquote>',
        esc_html( $stars_html ),
        wp_kses_post( $content ),
        esc_html( $atts['name'] ),
        $atts['company'] ? ', ' . esc_html( $atts['company'] ) : ''
    );
}
add_shortcode( 'testimonial', 'testimonial_shortcode' );

사용 예:

[testimonial name="Sarah K." company="Acme Corp" stars="4"]
	Saved us hours every week.
[/testimonial]

작동은 합니다... 하지만 그냥 숏코드일 뿐입니다 🤷🏻‍♂️

숏코드의 문제점 몇 가지를 살펴보면:

  • 에디터에서 보이지 않는다. 저자는 에디터에서 렌더링된 카드가 아닌 [testimonial name="Sarah K." ...]라는 코드만 봅니다. 미리보기가 없습니다.
  • 발견하기 어렵다. 숏코드가 존재한다는 것을 알고 파라미터 이름을 기억해야 합니다. UI에는 아무것도 표시되지 않습니다.
  • 네이티브 스타일 컨트롤이 없다. 색상, 간격, 타이포그래피를 조정하려면 커스텀 CSS나 수동으로 추가된 속성이 필요합니다.
  • 내부 콘텐츠는 리치 텍스트가 아니다. 리뷰 본문은 $content에 일반 문자열로 전달됩니다 — 편집 가능한 리치 텍스트 영역이 아닙니다.

숏코드는 그 시대에 적합한 도구였습니다. 블록 에디터는 더 나은 것을 제공하지만, 활용하기 어려운 상황이었습니다. WordPress 7.0은 PHP 전용 블록의 형태로 지름길을 제공합니다.

명확히 해두자면: Gutenberg 블록을 구축하는 올바른 새로운 방법은 여전히 완전한 edit 컴포넌트를 갖춘 JavaScript로 등록된 블록입니다. PHP 전용 블록은 단순화된 경로입니다 — 캔버스에서 리치 편집이 필요 없는 서버 렌더링 블록에 의도적으로 제한되어 있습니다. JavaScript 블록의 대체가 아니라, 빌드 파이프라인과 React 컴포넌트의 오버헤드가 정당화되지 않는 더 간단한 사용 사례를 위한 새로운 옵션입니다.

더 간단한 선택지: PHP 전용 블록

PHP만으로 동일한 추천사를 WordPress 커스텀 블록으로 만들어 보겠습니다. 레시피: supports'autoRegister' => true를 지정한 register_block_type()render_callback입니다.

블록의 전체 코드는 다음과 같습니다:

function my_plugin_register_testimonial_block() {
    register_block_type(
        'my-plugin/testimonial', // Block name: namespace/slug
        array(
            'title'      => 'Testimonial', // Shown in the block inserter
            'attributes' => array(
                // string attributes generate a text input in the sidebar
                'name'    => array(
                    'type'    => 'string',
                    'default' => '',
                ),
                'company' => array(
                    'type'    => 'string',
                    'default' => '',
                ),
                // integer attributes generate a number input
                'stars'   => array(
                    'type'    => 'integer',
                    'default' => 5,
                ),
                'body'    => array(
                    'type'    => 'string',
                    'default' => '',
                ),
            ),
            // render_callback is the PHP function that outputs the block's HTML
            'render_callback' => function ( $attributes ) {
                $stars_count = max( 1, min( 5, intval( $attributes['stars'] ) ) );
                $stars_html  = str_repeat( '★', $stars_count )
                             . str_repeat( '☆', 5 - $stars_count );
 
                // Translatable string for screen readers — standard WordPress i18n, nothing extra needed
                /* translators: %d: star rating out of 5 */
                $stars_label = sprintf( __( '%d out of 5 stars', 'my-plugin' ), $stars_count );
 
                return sprintf(
                    '<blockquote %s>
                        <p class="testimonial__stars" aria-label="%s">%s</p>
                        <p class="testimonial__body">%s</p>
                        <cite class="testimonial__attribution">
                            <strong>%s</strong>%s
                        </cite>
                    </blockquote>',
                    // Merges your class with editor-added colour, spacing, and typography styles
                    get_block_wrapper_attributes( array( 'class' => 'testimonial wp-block-quote' ) ),
                    esc_attr( $stars_label ),
                    esc_html( $stars_html ),
                    wp_kses_post( $attributes['body'] ),
                    esc_html( $attributes['name'] ),
                    $attributes['company'] ? ', ' . esc_html( $attributes['company'] ) : ''
                );
            },
            'supports' => array(
                // The key flag — tells WordPress to handle JS registration automatically
                'autoRegister' => true, 
                // The rest unlock native colour, typography, and spacing panels in the sidebar
                'color'      => array(
                    'background' => true,
                    'text'       => true,
                ),
                'typography' => array(
                    'fontSize' => true,
                ),
                'spacing'    => array(
                    'padding' => true,
                    'margin'  => true,
                ),
            ),
        )
    );
}
add_action( 'init', 'my_plugin_register_testimonial_block' );

결과:

PHP만으로 만들어진 WordPress 커스텀 블록의 예
자동 생성된 컨트롤과 에디터 캔버스의 라이브 미리보기를 갖춘 PHP 전용 추천사 블록과 숏코드 버전의 비교.

몇 가지 주목할 점이 있습니다. 첫째, 숏코드의 내부 콘텐츠는 PHP 전용 블록에서 직접적으로 대응하는 것이 없습니다. 리뷰 본문은 사이드바 Inspector Controls에서 편집할 수 있는 string 속성이 됩니다 — 캔버스 내 편집 가능한 리치 텍스트 영역이 아닌 단일 행 텍스트 필드입니다. 짧은 추천사 인용문이라면 이것으로 충분합니다. 더 긴 본문 텍스트에는 RichText 컴포넌트를 가진 JavaScript로 등록된 블록이 필요합니다.

둘째, get_block_wrapper_attributes()는 여러분의 클래스와 에디터가 색상, 타이포그래피, 간격을 위해 추가하는 것을 병합합니다 — 따라서 추가 CSS 없이 네이티브 스타일 패널이 작동합니다. render_callback은 사용자가 설정한 값만 포함하는 $attributes 배열을 받습니다. 내부 콘텐츠가 지원되지 않으므로 $content 파라미터는 없습니다.

숏코드 버전과 비교해 얻는 것:

  • 에디터 캔버스의 라이브 미리보기. 더 이상 원시 숏코드 구문은 없습니다 — 저자는 편집하면서 렌더링된 추천사 카드를 볼 수 있습니다.
  • 자동 생성된 컨트롤. 이름, 회사명, 본문(텍스트 입력)과 별점(숫자 입력)이 사이드바 Inspector Controls에 자동으로 나타납니다.
  • 네이티브 색상, 폰트, 간격 패널. supports에서 제공됩니다 — 커스텀 CSS 불필요.
  • 발견하기 쉽다. 블록은 삽입기에 이름과 아이콘으로 표시됩니다.

처음부터 번역 준비 완료

PHP 전용 블록을 사용할 때 두 가지 별개의 번역 관련 사항이 있으며, 어느 것이 어느 것인지 명확히 해두는 것이 좋습니다.

첫 번째는 PHP 템플릿에 내장된 정적 문자열 — 레이블, 버튼 텍스트, UI 카피입니다. 이것들은 일반적인 WordPress PHP 파일에서처럼 __()_e()로 처리됩니다. 위의 블록에서 별 레이블이 그 예입니다:

/* translators: %d: star rating out of 5 */
$stars_label = sprintf( __( '%d out of 5 stars', 'my-plugin' ), $stars_count );

표준 WordPress 도구가 이것들을 자동으로 감지합니다. 추가 설정은 불필요합니다.

두 번째 관심사는 블록 속성으로 저장된 사용자 입력 콘텐츠 — 추천사 본문, 리뷰어의 이름, 회사명입니다. 이것은 에디터가 실제로 블록에 입력하는 콘텐츠이며, __()는 그것을 건드리지 않습니다. 다국어 사이트에서는 이러한 속성 값을 각 언어로 개별적으로 번역해야 하며, 이것은 WordPress가 단독으로 처리하는 것이 아닙니다.

Gato AI Translations for Polylang은 PHP 전용 블록을 즉시 지원합니다, Gutenberg, Bricks, Elementor 및 기타 페이지 빌더를 지원하는 것과 동일한 방식으로. 추가 설정이 필요하지 않습니다.

모든 string 속성은 번역을 위해 자동으로 등록됩니다. 특정 필드를 번역하지 않아야 하는 경우 — 내부 참조, URL, 문자열로 저장된 숫자 코드 — 필터를 사용하여 제외할 수 있습니다.

이 글의 추천사 블록에서 리뷰어 이름, 회사명, 본문 텍스트는 모두 플러그인을 설치하는 것만으로 자동으로 번역됩니다.

PHP 전용 블록으로 할 수 없는 것 (현재)

PHP 전용 블록의 현재 제한 사항:

  • 내부 블록이나 중첩 불가. PHP 전용 블록 내부에 다른 블록을 배치할 수 없습니다.
  • 캔버스 내 리치 텍스트 편집 불가. RichText 컴포넌트에는 JavaScript가 필요합니다. 텍스트 컨트롤은 사이드바 텍스트 필드로만 렌더링됩니다.
  • 사이드바 문자열 필드는 한 줄만. string 속성은 TextareaControl이 아닌 TextControl이 됩니다 — 긴 텍스트에는 적합하지 않습니다.
  • 이미지나 미디어 피커 속성 없음. 이미지/파일 업로드 지원은 Block Fields API를 통해 이후 릴리스에서 계획되어 있습니다.
  • 에디터 미리보기에 왕복 지연이 있음. 속성 변경 시 서버에서 다시 렌더링하기 위해 REST API 요청이 트리거되므로 미리보기가 즉시 업데이트되지 않습니다.

단순한 구조화 블록 — 추천사, CTA, 공지사항, 저자 약력, 비즈니스 목록 — 에는 PHP 전용 블록이 최적의 선택입니다. 캔버스 내 리치 편집이 필요한 것에는 JavaScript 등록이 여전히 올바른 도구입니다.

다음 단계

WordPress 7.0의 PHP 전용 블록으로 블록 개발이 모든 PHP 개발자의 손에 닿는 곳에 왔습니다. PHP 파일 하나, register_block_type() 호출 하나로 사이드바 컨트롤, 라이브 캔버스 미리보기, 네이티브 스타일 지원을 갖춘 완전히 기능하는 Gutenberg 블록을 얻을 수 있습니다. PHP를 작성하면 블록을 얻습니다. 툴링 불필요. 빌드 불필요. JavaScript도 불필요.

다국어 사이트를 구축하고 있다면, Gato AI Translations는 PHP 전용 블록과 원활하게 연동됩니다 — 콘텐츠는 첫날부터 번역 가능합니다.

더 나아갈 준비가 되셨나요?


다음에 무엇이 나오는지 알아보세요

뉴스레터를 구독하세요: 새 버전을 출시하거나, 새 플러그인을 선보이거나, 공유할 소식이 있을 때 알려드립니다.