STAGE 12 · Lv.59
커스텀 포스트 타입과 필드
register_post_type(), ACF/Meta Box 활용, 커스텀 필드와 필드 그룹, 관계 필드, 옵션 페이지를 배웁니다.
커스텀 포스트 타입(CPT)이란?
WordPress를 진정한 CMS로 확장하기
WordPress의 기본 포스트 타입은 "글(post)"과 "페이지(page)"입니다. 하지만 실제 프로젝트에서는 이 두 가지만으로는 다양한 콘텐츠를 체계적으로 관리할 수 없습니다. 커스텀 포스트 타입(Custom Post Type, CPT)을 사용하면 "포트폴리오", "상품", "이벤트", "팀원", "FAQ", "매물" 등 어떤 종류의 콘텐츠든 독립적인 콘텐츠 타입으로 관리할 수 있습니다.
CPT는 WordPress를 단순한 블로그 플랫폼에서 강력한 CMS(Content Management System)로 변환시키는 핵심 기능입니다. 부동산 사이트, 채용 사이트, 레스토랑 메뉴, 온라인 강좌, 디렉토리 사이트 등 거의 모든 종류의 웹 애플리케이션을 WordPress로 구현할 수 있게 해줍니다.
CPT가 필요한 실전 시나리오:
- 부동산 사이트 - 매물(Property) CPT + 가격, 면적, 방 수, 주소 커스텀 필드
- 레스토랑 - 메뉴 아이템(Menu Item) CPT + 가격, 재료, 알레르기 정보 필드
- 학원/교육 - 강좌(Course) CPT + 강사, 일정, 수강료, 난이도 필드
- 기업 사이트 - 팀원(Team) CPT, 서비스(Service) CPT, 사례연구(Case Study) CPT
- 영화/도서 리뷰 - 영화(Movie) CPT + 감독, 장르, 개봉일, 평점 필드
- 이벤트 사이트 - 이벤트(Event) CPT + 날짜, 장소, 가격, 참석자 수 필드
- 포트폴리오 - 작업물(Portfolio) CPT + 클라이언트, 기술 스택, 갤러리 필드
- 채용 사이트 - 채용공고(Job) CPT + 직무, 경력, 급여, 위치 필드
20+
WordPress 내장 포스트 타입 수
무한
생성 가능한 CPT 수
ACF
가장 인기 있는 커스텀 필드 플러그인
REST API
CPT 데이터 외부 접근
데이터 구조
설계
설계
→
CPT 등록
register_post_type
register_post_type
→
커스텀 필드
ACF/Meta Box
ACF/Meta Box
→
템플릿
아카이브/싱글
아카이브/싱글
→
WP_Query
데이터 조회
데이터 조회
register_post_type() 모든 인자 상세
<?php
/**
* ===== 커스텀 포스트 타입 등록 - 모든 인자 상세 해설 =====
* functions.php 또는 커스텀 플러그인에 추가합니다.
* 플러그인에서 등록하는 것을 강력히 권장합니다 (테마 변경 시 데이터 유지).
*/
add_action('init', 'register_property_post_type');
function register_property_post_type() {
// ===== 라벨(Labels) 설정 =====
// 관리자 화면에 표시되는 모든 텍스트를 지정합니다.
$labels = array(
'name' => '매물', // 일반 이름 (복수)
'singular_name' => '매물', // 단수 이름
'menu_name' => '매물 관리', // 관리자 메뉴에 표시
'name_admin_bar' => '매물', // 관리자 바의 "새로 추가"
'add_new' => '새 매물 등록', // 추가 버튼 텍스트
'add_new_item' => '새 매물 등록', // 추가 페이지 제목
'new_item' => '새 매물', // 새 항목
'edit_item' => '매물 편집', // 편집 페이지 제목
'view_item' => '매물 보기', // 보기 링크
'view_items' => '매물 목록 보기', // 목록 보기 링크
'all_items' => '모든 매물', // 하위 메뉴 "모든 항목"
'search_items' => '매물 검색', // 검색 버튼
'parent_item_colon' => '상위 매물:', // 계층형일 때 상위 항목
'not_found' => '등록된 매물이 없습니다', // 검색 결과 없음
'not_found_in_trash' => '휴지통에 매물이 없습니다', // 휴지통 비었음
'featured_image' => '매물 대표 이미지', // 대표 이미지 레이블
'set_featured_image' => '대표 이미지 설정',
'remove_featured_image' => '대표 이미지 제거',
'use_featured_image' => '대표 이미지로 사용',
'archives' => '매물 아카이브', // 아카이브 레이블
'insert_into_item' => '매물에 삽입',
'uploaded_to_this_item' => '이 매물에 업로드됨',
'filter_items_list' => '매물 목록 필터',
'items_list_navigation' => '매물 목록 네비게이션',
'items_list' => '매물 목록',
);
// ===== 포스트 타입 인수(Arguments) 설정 =====
$args = array(
'labels' => $labels,
// --- 공개 및 접근 설정 ---
'public' => true, // 프론트엔드와 관리자 모두에서 접근 가능
'publicly_queryable' => true, // URL로 조회 가능 (?post_type=property 또는 /property/slug)
'show_ui' => true, // 관리자 UI(편집 화면) 표시
'show_in_menu' => true, // 관리자 좌측 메뉴에 표시 (true/false/문자열)
'show_in_nav_menus' => true, // 외모 → 메뉴에서 선택 가능
'show_in_admin_bar' => true, // 관리자 바의 "새로 추가"에 표시
'show_in_rest' => true, // REST API 노출 (Gutenberg 블록 에디터 필수!)
'rest_base' => 'properties', // REST API 엔드포인트 이름 (/wp-json/wp/v2/properties)
'rest_namespace' => 'wp/v2', // REST API 네임스페이스
// --- URL 설정 ---
'query_var' => true, // URL 쿼리 변수 사용 (?property=slug)
'rewrite' => array(
'slug' => 'property', // URL 슬러그 (example.com/property/매물이름)
'with_front' => false, // 퍼머링크 앞부분(/blog/) 포함 여부
'pages' => true, // 페이지네이션 지원 (/property/page/2/)
'feeds' => true, // RSS 피드 지원 (/property/feed/)
),
// 'rewrite' => false, // URL 접근 비활성화 (비공개 CPT)
// --- 기능 설정 ---
'capability_type' => 'post', // 권한 유형 ('post', 'page', 또는 커스텀)
// 'capability_type' => array('property', 'properties'), // 커스텀 권한
// 'map_meta_cap' => true, // 메타 권한 매핑 (커스텀 권한 사용 시)
'has_archive' => true, // 아카이브 페이지 활성 (example.com/property/)
// 'has_archive' => 'properties', // 커스텀 아카이브 슬러그
'hierarchical' => false, // false = 글처럼 (평면), true = 페이지처럼 (계층)
'exclude_from_search' => false, // 검색 결과에서 제외 여부
'can_export' => true, // 내보내기 도구에 포함 여부
'delete_with_user' => false, // 사용자 삭제 시 콘텐츠도 삭제할지
// --- 관리자 메뉴 설정 ---
'menu_position' => 5, // 메뉴 위치 (5=글 아래, 20=페이지 아래, 25=댓글 아래)
'menu_icon' => 'dashicons-building', // 메뉴 아이콘 (dashicons 또는 SVG base64)
// 'menu_icon' => 'data:image/svg+xml;base64,...', // 커스텀 SVG 아이콘
// --- 지원 기능(Supports) ---
'supports' => array(
'title', // 제목 필드
'editor', // 본문 에디터 (Gutenberg 또는 Classic)
'thumbnail', // 대표 이미지
'excerpt', // 요약(발췌)
'custom-fields', // 기본 커스텀 필드 (메타 박스)
'revisions', // 수정 내역 (되돌리기)
'author', // 작성자 선택
'page-attributes', // 페이지 속성 (순서, 부모 - hierarchical일 때)
// 'comments', // 댓글 (필요한 경우만)
// 'trackbacks', // 트랙백 (거의 사용 안 함)
// 'post-formats', // 포스트 형식 (비디오, 갤러리 등)
),
// --- 분류체계(Taxonomy) 연결 ---
'taxonomies' => array('property_type', 'property_location'),
// --- 템플릿 ---
'template' => array(), // 기본 블록 에디터 템플릿
'template_lock' => false, // 템플릿 잠금 (false, 'all', 'insert')
);
register_post_type('property', $args);
}
?>
CPT 이름 규칙
register_post_type()의 첫 번째 인자(포스트 타입 이름)는 최대 20자, 소문자, 밑줄(_)만 사용하세요. 하이픈(-)은 사용하지 마세요. WordPress 내장 포스트 타입(post, page, attachment, revision, nav_menu_item)과 중복되지 않아야 합니다. 접두사를 붙여 충돌을 방지하는 것이 좋습니다(예: mysite_property). show_in_rest를 true로 설정해야 Gutenberg 블록 에디터가 작동합니다.
🔒
여기까지는 미리보기입니다
커스텀 포스트 타입과 필드
무료 가입하면 이어서 볼 수 있고, 강의를 완료할 때마다 XP와 레벨이 쌓입니다.
Google로 3초 만에 시작 →🧵 Threads로 시작무료 공개 강의 둘러보기 (Lv.1~3)무료 가입하면 이어서 볼 수 있고, 강의를 완료할 때마다 XP와 레벨이 쌓입니다.