WordPress에서 PHP만 사용하여 블록 등록하기
요약
워드프레스 7.0부터는 복잡한 JavaScript나 빌드 파이프라인 없이 오직 PHP만으로 커스텀 워드프레스 블록을 등록할 수 있게 되었습니다. `autoRegister` 플래그를 사용하면 필요한 JS가 자동으로 생성되어 개발 경험이 크게 간소화됩니다. 또한, 속성 정의도 PHP 코드만으로 처리 가능해져 편리합니다.
핵심 포인트
- PHP 전용 등록 방식으로 복잡한 빌드 과정 생략
- autoRegister 플래그로 JS 자동 생성 및 에디터 지원
- 속성(Attributes) 정의가 PHP 코드로 간소화됨
커스텀 워드프레스(WordPress) 블록을 만들고 싶지만, React를 배우거나 빌드 파이프라인을 관리하거나 NPM 패키지 같은 복잡한 과정을 처리하고 싶지는 않을 때가 있습니다.
블록 기능이 코어에 도입된 지 7년 반이라는 시간이 흘렀지만, 워드프레스는 이 모든 과정 없이 블록을 만들 수 있는 방법을 소개합니다. 필요한 것은 오직 PHP뿐입니다.
하지만 오랜 기다림은 그만한 가치가 있었을까요?
근본적으로 간소화된 블록 빌딩 경험
전통적인 워드프레스 블록은 두 번 등록되어야 했습니다. 한 번은 PHP에서, 그리고 한 번은 JavaScript에서 말이죠.
하지만 워드프레스 7.0에서는 새로운 간소화된 접근 방식을 도입하여, 오직 PHP만을 사용하여 블록을 등록할 수 있게 되었습니다.
PHP만으로 블록 등록하기
이 기능을 활용하여 Hello World 블록을 만들어 보겠습니다:
function css_tricks_hello_world_block() {
register_block_type('
'css-tricks/hello-world',
...
이 블록은 블록 에디터에서 완전히 작동하며, 다른 모든 블록들과 자연스럽게 어우러집니다:

핵심 추가 사항은 supports 섹션의 'autoRegister' => true 플래그입니다. 이 플래그를 설정하면 워드프레스가 PHP 등록을 기반으로 필요한 JavaScript를 자동으로 생성합니다. 여기에는 클라이언트 측 등록과 에디터 미리보기가 포함됩니다.
PHP 전용으로 등록된 블록에 속성 추가하기
속성(Attributes)은 사용자가 블록의 모양과 동작을 커스터마이징할 수 있게 해줍니다. 전통적인 블록 개발에서는 속성을 정의하는 것뿐만 아니라, 에디터 인터페이스에서 해당되는 컨트롤도 직접 구현해야 했습니다.
PHP 전용 등록 방식을 사용하면, 블록 등록 시 attributes 정의만 해주면 됩니다:
function css_tricks_hello_world_block()
{
register_block_type(
...
이 코드는 기본값을 가진 문자열 형태의 greeting 속성을 등록합니다. 워드프레스는 블록의 설정 사이드바에 해당되는 입력 컨트롤을 자동으로 생성합니다.

언뜻 보기에는 PHP 전용으로 등록된 블록들이 정말 많은 장점을 가지고 있는 것 같습니다. 모든 워드프레스 개발자에게는 프로그래밍이 더 단순했던 옛 시절의 느낌을 되살려주는 듯합니다.
PHP 전용으로 등록된 블록의 한계점
JavaScript 블록 개발 학습을 무기한으로 미루고 싶을 수도 있습니다. 하지만 PHP 전용 접근 방식에는 이해할 가치가 있는 중요한 한계점들이 존재합니다.
블록 콘텐츠와의 상호작용 불가
편집기는 블록의 render_callback PHP 함수가 반환하는 HTML을 표시합니다. 블록이 처음 표시되거나 사용자가 해당 컨트롤 중 하나와 상호 작용할 때, 편집기 컴포넌트는 REST API 엔드포인트에서 새로운 PHP 렌더링을 요청합니다.
이렇게 렌더링된 블록은 편집기에 원활하게 통합되지만, 전체 편집 경험을 구동하는 단일 페이지 JavaScript 애플리케이션의 일부는 아닙니다.
이는 두 가지 주요 한계점을 만듭니다:
첫째, 블록 미리보기 내에 어떤 컨트롤도 추가할 수 없습니다. 이는 설정 사이드바에서 자동 생성된 컨트롤로 제한된다는 것을 의미합니다.
블록의 기본 상호작용 방식은 블록 미리보기 자체입니다. 예를 들어, 추천사(testimonial) 블록이 필요하다고 가정해 봅시다. JavaScript로 렌더링된 블록을 사용하면 추천사 디자인을 구축하고 제자리에서 편집할 수 있도록 할 수 있습니다.
하지만 PHP로 렌더링된 블록의 경우 사이드바만 사용할 수 있습니다. 게다가 여기에서도 제한적입니다. 현재 이미지 업로드나 여러 줄 텍스트에 대한 지원이 없기 때문입니다.
JavaScript를 사용하면 사이드바뿐만 아니라 블록 자체 내에서도 편집을 허용할 수 있습니다. 또한 WordPress Core가 사용하는 모든 컨트롤에 접근할 수 있으며, 심지어 자신만의 컨트롤도 구현할 수 있습니다.
하지만 JavaScript 없이는 PHP 전용 블록의 등록된 속성(attributes)을 기반으로 워드프레스가 제공하는 옵션에 항상 제한될 것입니다.
둘째, 블록 미리보기 내 마크업에 JavaScript를 연결할 수 없습니다. 관련 게시물 5개를 가져와 슬라이더로 표시하는 블록을 개발하고 싶다고 가정해 봅시다. 이 경우 마크업을 출력한 다음, DOM 노드를 JavaScript 라이브러리에 전달하여 원시 마크업을 원하는 슬라이더 인터페이스로 변환해야 합니다.
DOM 요소를 찾고 조작하는 것에 의존하는 것은 전통적인 JavaScript 개발의 전형적인 방식입니다. 하지만 블록 편집기에서 PHP만으로 등록된 블록을 사용하면, 마크업이 비동기적으로 가져와지며 리렌더링될 때마다 교체됩니다. 이로 인해 블록 미리보기의 DOM과 상호 작용하는 것이 신뢰할 수 없거나 불가능해집니다.
프론트엔드 렌더링은 JavaScript 라이브러리를 사용하면 잘 작동하지만, 편집기 작성 경험(authoring experience)은 올바르게 작동하지 않을 것입니다. 첫 로딩 시에 아무 이벤트 리스너를 연결하더라도, 미리보기가 리렌더링되는 순간 연결이 끊어집니다.
이러한 제한 사항들은 이 기능의 아키텍처 때문에 발생하며, 앞으로도 변경되지 않을 것입니다.
최신 데이터 접근 불가
블록 편집기가 처음 로드될 때, WordPress는 포스트 데이터를 데이터베이스에서 가져와 JavaScript가 관리하는 클라이언트 측 저장소에 로드합니다. 사용자가 편집기에서 어떤 변경을 하더라도 이 데이터 저장소가 클라이언트 측에서 업데이트됩니다. 하지만 게시물을 저장하기 전까지는 데이터베이스 자체가 업데이트되지 않습니다.
PHP만으로 등록된 블록은 이 클라이언트 측 저장소를 우회합니다. 블록이 렌더링될 때마다 데이터베이스에 직접 쿼리합니다. 그러나 데이터베이스에는 현재 편집기에 있는 내용과 비교하여 오래된(stale) 데이터가 포함되어 있을 수 있습니다. 설상가상으로, PHP로 렌더링된 블록은 클라이언트 측 데이터의 변경 사항을 통보받지 못하므로, 데이터가 변경되어도 새로 고칠 수 없습니다.
실용적인 예를 들어보겠습니다. 포스트 제목과 같은 헤더 요소를 표시하는 블록을 만든다고 가정해 봅시다. 사용자가 편집기에서 제목을 변경해도, 귀하의 블록은 여전히 데이터베이스의 값을 표시할 것입니다. 변경된 제목이 PHP만으로 구성된 블록에 나타나게 하려면 게시물을 저장하고 편집기를 다시 로드해야 합니다.
이로 인해 PHP만으로 구성된 블록은 제목, 내용(content), 발췌문(excerpt), 기능 이미지 또는 첨부 약관 등 사용자가 편집기에서 변경할 수 있는 데이터를 표시하는 모든 블록에 부적합합니다.
현재 포스트 컨텍스트 접근 불가
PHP만으로 등록된 블록은 REST API 엔드포인트를 통해 렌더링됩니다. 따라서 동일한 코드가 에디터 미리보기와 프런트엔드 모두에 적용됩니다. 하지만 중요한 차이점이 있습니다. 바로 전역 상태(global state)입니다.
프런트엔드에서 블록은 The Loop 내에서 렌더링되며, 이 과정에서 $post와 같은 핵심 전역 변수들이 설정됩니다. the_title()나 the_content() 같은 템플릿 태그들은 어떤 포스트가 표시되는지 알기 위해 이러한 전역 변수에 의존합니다.
하지만 REST API는 상태 비저장(stateless)이며, 전역 상태에 의존하지 않습니다. 블록 에디터 미리보기를 렌더링하는 엔드포인트는 포스트 ID 매개변수를 받지만, 에디터 컴포넌트가 이를 전달하지 않습니다. 이는 여러분의 렌더 콜백이 어떤 포스트가 편집되고 있는지 알 방법이 없다는 것을 의미합니다.
이는 블록 에디터 미리보기에서 사용할 수 있는 함수를 제한합니다. get_post_meta()와 같은 템플릿 태그나 함수는 포스트 컨텍스트에 대한 지식이 필요하기 때문입니다.
이는 WordPress 7.0 기준으로 상당한 아키텍처적 한계점입니다. 포스트 ID를 엔드포인트로 전달하여 해결할 수 있겠지만, 현재 작성 시점에서는 이를 변경하겠다는 구체적인 계획은 없습니다.
제한된 속성 유형 및 편집 인터페이스
WordPress 7.0은 세 가지 속성 유형(attribute types)만 지원합니다: 문자열(strings), 숫자(numbers), 그리고 부울(booleans). 이들은 네 가지 기본 에디터 컨트롤로 매핑됩니다: 텍스트 입력(text inputs), 숫자 입력(number inputs), 체크박스(checkboxes), 그리고 드롭다운(dropdown).
이 스크린샷은 사용 가능한 모든 사용자 인터페이스 요소를 사용하는 블록을 보여줍니다:

드롭다운 요소는 유일하게 고급 컨트롤이지만, 상당한 제한점이 있습니다. 바로 키가 지정된 배열(keyed arrays)을 지원하지 않는다는 것입니다. 이 때문에 저장된 값과 다른 레이블을 가진 것을 구현하는 것이 불가능합니다.
관련 포스트를 선택할 수 있는 블록의 예를 들어보겠습니다. 사용자는 드롭다운에서 카테고리 이름을 보고 싶지만, 실제로는 카테고리 ID를 저장해야 합니다. 이는 불가능합니다.
대신, 이름 또는 슬러그 중 하나를 선택하여 표시하고, 이 값을 사용자 편집이 가능하도록 저장해야 합니다:
'attributes' => [
'selected_category' => [
'label' => '카테고리를 선택하세요',
...
이렇게 하면 슬러그가 블록 마크업에 저장됩니다:
이렇게 하면 슬러그가 블록 마크업에 저장됩니다:
<!-- wp:css-tricks/related-posts {"selected_category":"news"} -->
슬러그를 사용하면 인터페이스에서 보기 좋지 않을 뿐만 아니라, 카테고리 이름을 변경할 때 이 구현이 깨질 수도 있습니다. 이전 슬러그를 참조하는 모든 기존 블록은 관련 게시물을 가져올 수 없게 됩니다. ID는 더 안정적이며, 카테고리가 삭제될 때만 무효화됩니다.
드롭다운 메뉴 외에도 이미지 업로드, 리치 텍스트 에디터 또는 날짜 선택기 같은 필수 컨트롤이 없습니다. 이는 향후 릴리스에서 변경될 수도 있지만, 현재로서는 계획이 없습니다.
핵심 사용 사례: 레거시 PHP 코드 마이그레이션
이러한 제한 사항들을 보면 쉽게 낙담할 수 있습니다. PHP 전용으로 등록된 블록은 처음부터 새로운 블록을 구축하는 데는 적합하지 않다는 것이 사실입니다.
하지만 저는 여전히 매우 가치 있다고 생각합니다. 왜냐하면 이러한 제한 사항들이 중요하지 않은 사용 사례가 하나 있기 때문입니다: 레거시 PHP 코드를 블록 테마로 마이그레이션하는 것입니다. 이 WordPress 7.0 기능은 개발자들이 채택하고 있는 블록 테마와 관련하여 진정한 게임 체인저이며, 이는 여전히 많은 테마 작성자들에게 일종의 장벽으로 남아 있습니다.
블록 테마 도입 문제
제 경험상, 블록 테마는 레거시 테마보다 성능이 뛰어나고 유지 관리가 쉬우며 구축 속도가 빠릅니다. 그럼에도 불구하고 많은 개발자들이 여전히 클래식 테마에 의존하고 있습니다. 그리고 이는 선택의 문제가 아니라 기존 PHP 기반 기능들 때문입니다.
지금까지 이러한 기능을 마이그레이션하는 것은 거의 극복할 수 없는 장벽에 부딪혔습니다. 첫째, JavaScript 블록 개발을 학습해야 하고 종속성 관리 및 빌드 파이프라인과 함께 완전히 새로운 개발 워크플로우를 설정해야 하는 필요성이었습니다. 둘째, 이 모든 코드를 JavaScript로 다시 작성하는 데 필요한 시간이었습니다.
PHP 전용으로 등록된 블록은 이러한 두 가지 장애물을 모두 제거합니다.
실제 마이그레이션 예시
2022년에 저는 클래식 테마를 블록 테마로 마이그레이션하고 싶었습니다.

콘텐츠 영역과 푸터는 블록으로 재구축하기가 간단했습니다. 하지만 헤더는 더 복잡했는데, 특히 당시의 제한적인 블록 빌딩 기능 때문이었습니다.
그래서 헤더를 재구축하는 데 시간을 쏟기보다는, 기존 PHP 헤더 코드를 가져와 서버 측에서 렌더링되는 블록으로 감쌌습니다.

물론 현실적으로 생각해야 합니다. 이 헤더 블록은 결코 완벽하지 않았습니다. 블록 미리보기는 반응형이 아니었고, 드롭다운 메뉴가 에디터에서 작동하지 않았으며, 아무것도 편집할 수 없었습니다.
그게 중요했을까요? 전혀 그렇지 않았습니다. 블록은 프런트엔드에서는 완벽하게 렌더링되었고, 에디터 미리보기만 충분했습니다. 그리고 이 접근 방식 덕분에 저는 테마를 며칠이 아닌 몇 시간 만에 마이그레이션할 수 있었습니다.
PHP 전용 등록 이전에도 이러한 블록을 구축하려면 견실한 JavaScript 숙련도와 빌드 도구가 필요했습니다. 하지만 이제는 기존 기술만 가진 모든 PHP 개발자가 이 마이그레이션 경로를 사용할 수 있습니다.
마이그레이션할 수 있는 것들
PHP 전용으로 등록된 블록은 다음을 변환하는 데 이상적입니다:
레거시 위젯: 블록 에디터의 설정 사이드바는 레거시 위젯의 설정을 재현하는 데 완벽합니다.**쇼트코드(Shortcodes):**블록 템플릿에서 쇼트코드를 사용할 수는 있지만, 이것을 다루는 것은 기껏해야 어색할 뿐입니다. 워드프레스 7.0으로 쇼트코드를 블록으로 마이그레이션하는 것이 이제 간단해졌습니다.**템플릿 부분 및 사용자 정의 템플릿 태그:**헤더, 푸터, 작성자 소개, 관련 게시물 등이 있습니다.**사용자 정의 기능(Custom functionality):**에디터에서 상호 작용할 필요 없이 프런트엔드에서 작동하는 모든 것입니다.
생성된 블록이 에디터에서 완벽할 필요는 없습니다. 중요한 것은 프런트엔드에서 올바르게 렌더링되는 것입니다. 기존 PHP 코드를 사용함으로써, 블록 테마에 대한 적응은 최소화됩니다.
PHP 전용으로 등록된 블록 구축을 위한 실질적인 팁
AI 자동 생성 콘텐츠
본 콘텐츠는 CSS-Tricks의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기