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_restrest_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_resttrue 대신 [ 'schema' => [ … ] ] 형태로 항목 스키마를 함께 줍니다. 스키마 없이 복합 타입을 노출하려 하면 등록 단계에서 거부됩니다 — 검증할 방법이 없는 값을 API 에 싣지 않겠다는 뜻이고, 옳은 기본값입니다.

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

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

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

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

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

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

다음 회차

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

이 주제의 다른 글

노하우 목록으로

개발 워크플로우 실무

워드프레스를 GitHub 에 올릴 때의 .gitignore

워드프레스 저장소에서 커밋해야 할 것과 절대 커밋하면 안 되는 것의 경계는 명확합니다. wp-config.php 한 파일이 저장소에 들어가는 순간 DB 비밀번호와 인증 솔트가 통째로 유출됩니다.

개발자 · 운영 · 관리자 5분 읽기

개발 워크플로우 실무

취향 논쟁을 규칙 확인으로 바꾸는 디자인 리뷰

"좀 답답해 보인다" 는 반박할 수 없고 고칠 수도 없습니다. 간격 척도 밖의 값, 팔레트 밖의 색, 기준 미달 대비, 빠진 상태 — 네 항목만 규칙으로 바꿔도 리뷰의…

디자이너 4분 읽기

₩270,000 · 신청하기