왜 이 기능이 나왔을까?

WordPress에 블록 에디터(Gutenberg)가 등장한 지 7년 반. 그동안 커스텀 블록을 만들려면 React를 배우고, NPM 패키지를 관리하고, 빌드 파이프라인을 세팅해야 했어요. "블록 하나 만들자고 이걸 다 배워야 하나?" 싶은 순간이 많았죠.

WordPress 7.0은 이 진입 장벽을 PHP 한 줄로 낮춥니다. supports에 autoRegister => true 플래그만 넣으면, WordPress가 클라이언트 사이드 등록과 에디터 프리뷰에 필요한 JavaScript를 자동 생성해줘요.

이 글은 WordPress 7.0의 PHP 전용 블록 등록 기능을 다룹니다. 근거자료는 CSS-Tricks의 PHP Block Registration 아티클을 참고했어요.

핵심은 **"새 블록을 만들 때 쓰는 도구가 아니라, 레거시 PHP 코드를 블록 테마로 옮기는 다리"**라는 점이에요. 이 관점을 놓치면 실무에서 삽질합니다.

Developer writing PHP code to register WordPress block without JavaScript Software Concept Art

기본 사용법: PHP만으로 블록 등록하기

가장 단순한 Hello World 블록부터 볼게요. render_callback과 supports.autoRegister만 있으면 끝입니다.

function css_tricks_hello_world_block() {
    register_block_type(
        'css-tricks/hello-world',
        [
            'title' => 'Hello World',
            'render_callback' => function () {
                return sprintf(
                    '<div %s>Hello World!</div>',
                    get_block_wrapper_attributes()
                );
            },
            'supports' => [
                'autoRegister' => true, // JS 자동 생성 트리거
            ],
        ]
    );
}
add_action('init', 'css_tricks_hello_world_block');

속성(Attributes) 추가하기

기존에는 속성 정의 + 에디터 컨트롤 UI를 JavaScript로 직접 만들어야 했지만, PHP 전용 등록에서는 attributes 배열만 정의하면 WordPress가 사이드바에 자동으로 입력 컨트롤을 생성해줍니다.

'attributes' => [
    'greeting' => [
        'type' => 'string',
        'default' => 'Hello World!',
    ],
],

지원 타입은 string, number, boolean 세 가지뿐이고, 매핑되는 UI는 텍스트 인풋, 숫자 인풋, 체크박스, 드롭다운 4종입니다. 이미지 업로드나 리치 텍스트 편집기는 아직 없어요.

에디터 렌더 vs 프론트 렌더 구분하기

is_admin()은 REST 엔드포인트에서 true를 반환하지 않기 때문에 쓸 수 없어요. 대신 wp_is_rest_endpoint()와 rest_route를 조합합니다.

if ( wp_is_rest_endpoint()
    && str_contains($GLOBALS['wp']->query_vars['rest_route'] ?? '', 'v2/block-renderer/')
) {
    $frontend = false; // 에디터 프리뷰
} else {
    $frontend = true;  // 프론트엔드
}

현재 포스트 ID 접근하기 (워크어라운드)

REST API는 stateless라서 get_the_ID()가 에디터 프리뷰에서 동작하지 않습니다. init 훅 시점에 $_GET['post']를 읽어서 role => 'local' 속성으로 넘기는 우회법을 씁니다.

'attributes' => [
    'postId' => [
        'type' => 'integer',
        'default' => isset($_GET['post']) ? absint($_GET['post']) : 0,
        'role' => 'local', // 사이드바 UI 생성 방지
    ],
],

단, 신규 포스트 생성 시에는 URL에 ID가 없어서 저장 후 새로고침 전까지는 동작하지 않아요. Core에서 정식 지원이 나오기 전까지의 임시방편입니다.

Server-side rendering of WordPress block via REST API endpoint IT Technology Image

반드시 알아야 할 한계

한계영향실무 대응
블록 콘텐츠 내 상호작용 불가에디터 프리뷰에서 인라인 편집 불가, 사이드바 컨트롤만 사용정적 렌더 블록에만 사용
프리뷰 마크업에 JS 이벤트 연결 불가슬라이더/캐러셀 같은 DOM 조작 라이브러리 사용 불가프론트엔드에서만 JS 사용 (view_script)
프레시 데이터 접근 불가에디터에서 제목 변경해도 블록은 DB 값 표시제목/본문/발췌/특성 이미지 표시 블록에 부적합
포스트 컨텍스트 없음the_title(), get_post_meta() 등 템플릿 태그 사용 불가위 워크어라운드 또는 정적 블록만
속성 타입 제한 (string/number/boolean)이미지 업로드, 날짜 피커, 리치 텍스트 불가복잡한 UI는 JavaScript 블록으로
드롭다운 keyed array 미지원라벨≠저장값 매핑 불가 (카테고리 slug 저장 → 이름 변경 시 깨짐)안정적 식별자가 필요하면 JS 블록으로

⚠️ 주의사항: 이 한계들은 아키텍처에서 기인한 것이라 가까운 미래에 바뀌지 않습니다. "나중에 좋아지겠지" 하고 신규 블록을 PHP 전용으로 만들면 안 돼요.

그럼 어디에 쓰나? — 레거시 마이그레이션

이 기능의 킬러 유즈케이스는 클래식 테마의 PHP 코드를 블록 테마로 옮기는 것입니다.

  • 레거시 위젯 → 블록 (사이드바 설정 UI로 재현 가능)
  • 숏코드 → 블록 (블록 템플릿에서 숏코드는 다루기 번거로움)
  • 템플릿 파트/커스텀 템플릿 태그 → 블록 (헤더, 푸터, 작성자 소개, 관련 글)
  • 프론트엔드에서만 동작하는 커스텀 기능

에디터 프리뷰가 완벽하지 않아도 됩니다. 프론트엔드에서 정확히 렌더링되면 충분해요. 실제로 헤더를 PHP 블록으로 감싸서 테마 마이그레이션을 며칠 → 몇 시간으로 단축한 사례가 있습니다.

실무 팁 모음

  • CSS 등록: wp_register_style() → 'style' (프론트+에디터) 또는 'editor_style' (에디터 전용 오버라이드)
  • JS 등록: view_script로 등록하면 해당 블록이 있는 페이지에서만 로드됨 (프론트 전용)
  • 클래스 네이밍: WordPress가 자동 생성하는 .wp-block-{namespace}-{name}을 루트 클래스로 사용. BEM 방식 권장
  • iframe 에디터: Block API Version 3 이상이면 iframe 모드. WordPress 7.1에서 강제되므로 미리 v3로 맞춰두세요
  • 유용한 supports: inserter => false (인서터 숨김), multiple => false (단일 인스턴스), align => true (정렬 옵션)

한국 개발 생태계에서의 적용 맥락

국내 SI/에이전시 환경에서는 유지보수 계약이 걸린 레거시 WordPress 사이트가 많아요. 클라이언트가 "블록 테마로 바꾸고 싶다"고 해도, 기존 커스텀 PHP 위젯과 숏코드가 발목을 잡는 경우가 흔합니다. 이 기능은 그런 프로젝트에서 **"전면 재개발 없이 블록 테마로 전환"**이라는 명분을 만들어줍니다. 다만 에디터 UX 기대치가 높은 클라이언트(예: 콘텐츠 팀이 직접 편집하는 사이트)라면 사이드바 컨트롤만으로는 부족할 수 있으니, 인터랙티브 블록은 JavaScript로 병행 개발하는 하이브리드 전략을 추천해요.

WordPress admin editor showing PHP-only registered block with sidebar settings Technical Structure Concept

결론: 7년 반 기다린 보람이 있을까?

신규 기능성 블록을 만들 거라면 → No. WordPress 사용자가 기대하는 네이티브한 편집 경험은 JavaScript 없이는 불가능합니다. PHP 전용 등록은 JavaScript 블록을 대체하지도, 대체해서도 안 됩니다.

레거시 PHP 코드 때문에 클래식 테마에 묶인 사이트를 옮길 거라면 → Yes. 숏코드, 위젯, 템플릿 파트를 이미 가진 PHP 스킬만으로 블록 에디터로 이관할 수 있습니다. JavaScript도, 빌드 파이프라인도, 코드 중복도 없이요.

이 기능이 진짜 의미하는 바는 **"WordPress Core가 드디어 개발자 경험(DX)을 우선순위에 두기 시작했다"**는 신호입니다. JavaScript 블록 개발에도 보일러플레이트가 너무 많고, block.json–PHP–JS 간 조율 비용이 크니까요.

다음 단계 학습 방향

  1. Block API Version 3 마이그레이션 — WordPress 7.1 iframe 강제 대비
  2. block.json 메타데이터 구조 이해 — PHP 전용에서 JavaScript 블록으로 자연스럽게 확장하는 다리
  3. @wordpress/scripts 빌드 환경 — 인터랙티브 블록이 필요해지는 순간 반드시 필요
  4. Block Supports API 전체 스펙 — 테마 theme.json과의 상호작용 이해

함께 보면 좋은 글

본 콘텐츠는 신뢰할 수 있는 출처를 바탕으로 AI 도구를 활용하여 초안이 작성되었으며, 편집자의 검토를 거쳐 발행되었습니다. 전문가의 조언을 대체하지 않습니다.