Technote

개발 워크플로우 입문

연재 REST API 와 헤드리스 8부 중 2부

CPT 와 메타 노출하기 — show_in_rest 가 하는 일

포스트 타입은 한 줄로 열립니다. 메타는 다릅니다 — 타입을 등록해야 하고, auth_callback 이 쓰기를 가르며, 읽기는 그것과 무관하게 열려 버립니다.

커스텀 포스트 타입을 만들었는데 /wp-json/wp/v2/ 목록에 보이지 않는다면 이유는 하나입니다. show_in_rest 를 켜지 않은 것입니다. 이 한 줄은 REST 라우트만 만드는 것이 아니라 블록 에디터를 켜는 스위치이기도 합니다 — 에디터가 REST 위에서 돌기 때문에, 이 값이 false 면 편집 화면이 옛 클래식 에디터로 떨어집니다.

포스트 타입 — 한 줄과, 같이 정해야 할 것

register_post_type(
	'wper_tool',
	[
		'public'       => true,
		'show_in_rest' => true,   // 라우트 생성 + 블록 에디터
		'rest_base'    => 'tools', // 없으면 라우트 이름이 포스트 타입 키 그대로다
		'supports'     => [ 'title', 'editor', 'custom-fields' ],
	]
);

rest_base 를 지정하지 않으면 주소가 /wp-json/wp/v2/wper_tool 이 됩니다. 동작에는 문제가 없지만 내부 접두사를 공개 API 주소에 그대로 노출하는 셈이라, 접두사를 바꾸는 날 클라이언트가 함께 깨집니다. 공개 주소는 처음부터 따로 정합니다.

택소노미도 같은 방식입니다. register_taxonomy() 에 show_in_rest 와 rest_base 를 주면 텀 라우트가 생기고, 글 응답에도 그 택소노미 필드가 붙습니다.

위 예제의 마지막 줄에 custom-fields 가 있는 것이 중요합니다. 포스트 타입이 custom-fields 를 지원하지 않으면 응답 스키마에 meta 속성 자체가 만들어지지 않습니다. 메타를 아무리 정성껏 등록해도 나오지 않고, 원인이 메타 등록 쪽에 없기 때문에 한참 헤매게 됩니다.

메타는 한 줄로 끝나지 않습니다

메타를 REST 에 실으려면 register_post_meta() 로 등록해야 합니다. 등록되지 않은 메타 키는 아무리 값이 들어 있어도 REST 에 나타나지 않습니다. 그리고 등록에는 type 이 필요합니다 — REST 는 스키마를 먼저 만들고 값을 그 스키마에 맞춰 검증하기 때문에, 타입이 없으면 실을 자리가 없습니다.

register_post_meta(
	'wper_tool',
	'github_url',
	[
		'type'          => 'string',
		'single'        => true,     // 빠뜨리면 REST 에 배열로 나간다
		'show_in_rest'  => true,
		'auth_callback' => function ( $allowed, $meta_key, $post_id ) {
			return current_user_can( 'edit_post', $post_id );
		},
	]
);

single 을 빠뜨리는 실수가 가장 흔합니다. 기본값이 false 라 "github_url": ["https://…"] 처럼 값이 배열로 나가고, 클라이언트는 문자열을 기대하다가 조용히 빈 화면을 그립니다.

배열이나 객체를 실으려면 show_in_rest 에 true 대신 [ 'schema' => [ … ] ] 형태로 항목 스키마를 함께 줍니다. 스키마 없이 복합 타입을 노출하려 하면 등록 단계에서 거부됩니다 — 검증할 방법이 없는 값을 API 에 싣지 않겠다는 뜻이고, 옳은 기본값입니다.

읽기와 쓰기는 서로 다른 문을 씁니다

여기가 사고가 나는 지점입니다. auth_callback 은 쓰기를 가르는 관문입니다. 읽기는 그것과 무관하게, 그 글을 읽을 수 있는 사람이면 누구나 메타를 함께 받습니다.

메타 노출의 규칙 — 읽기와 쓰기가 다른 판정을 쓴다

밑줄로 시작하는 보호 메타(_wper_amount 같은)는 auth_callback 을 주지 않으면 기본값이 쓰기 거부로 잡힙니다. 그래서 “값은 저장되는데 에디터에서 못 고친다” 는 증상이 나옵니다. 반대로 show_in_rest 를 켠 순간 그 값의 읽기는 공개되므로, 내부용 값을 편집 화면에서 다루고 싶다는 이유만으로 REST 에 올리면 안 됩니다.

판단 기준은 간단합니다 — 이 값이 페이지 소스에 그대로 적혀 있어도 괜찮은가. 아니라면 REST 가 아니라 메타박스와 admin_post 로 다룹니다. 실제로 결제 자격증명이나 접속 정보 같은 값은 이 원칙 때문에 API 근처에 두지 않습니다.

구조화 필드를 어떤 기준으로 설계하는지는 테마 · 플러그인 아카이브에서 더 다루고, 이렇게 만든 데이터 계층을 실제 사이트에 적용할 때의 절차는 작업 과정에 있습니다.

다음 회차

코어가 주는 라우트로 부족해지는 순간이 옵니다. 다음 회차는 자체 엔드포인트 — 네임스페이스를 어떻게 정하고, 왜 permission_callback 이 필수 인자이며, 스키마를 주면 검증 코드를 왜 손으로 안 써도 되는지입니다.

이 주제의 다른 글

노하우 목록으로

개발 워크플로우 실무

캠페인 주소 관리 — 색인과 리포트가 함께 쪼개집니다

캠페인 파라미터가 붙은 주소는 검색엔진에게 별개의 주소입니다. 색인되면 같은 페이지가 여러 벌로 잡히고, 표기가 흔들리면 리포트가 쪼개집니다. 원인이 하나라 해법도 하나입니다.

마케터 5분 읽기

개발 워크플로우 심화

배포 전 디자인 QA 체크리스트

배포 후에 발견하는 디자인 문제의 대부분은 배포 전에 순서대로 확인하면 잡힙니다. 규칙 · 상태 · 실기기의 세 단계로 정리했습니다.

디자이너 3분 읽기

개발 워크플로우 심화

되돌릴 계획 없이 배포하지 않습니다

롤백은 버튼 하나가 아니라 코드와 데이터베이스 두 갈래이고, 되돌리는 순서가 있습니다. 그 순서를 배포 전에 적어 두는 것까지가 준비입니다.

디자이너 5분 읽기

₩270,000 · 신청하기