Blog

  • 커스텀 포스트 관리 UI 관련 옵션 집중 분석

    이 포스트는 커스텀 포스트의 관리 UI(admin UI)와 관련된 옵션을 다룬다. 목록은 아래와 같다.

    • public
    • show_ui
    • show_in_nav_menus
    • show_in_menu
    • show_in_admin_bar
    • menu_position
    • menu_icon
    • supports
    • register_meta_box_cb

    public 옵션은 관리 UI 관련 옵션에도 관여하지만 가시성 관련 옵션에도 관계가 있다. 해당 포스트에서 확인할 수 있다. 전체 옵션은 이 포스트에서 확인할 수 있다.

    public이 true이면 show_in_hav_menus, show_ui 옵션이 true. 반대로 false이면 모두 false로 설정된다.

    show_ui

    포스트 타입을 관리하는 기본 UI를 제공할지를 결정한다. 기본적인 포스트의 목록 확인, 생성, 편집 UI를 재활용할 수 있다. 이 UI는 다음과 같은 URL 패턴을 따라 제공된다.

    <site_url>/wp-admin/edit.php?post_type=<post_type>      // 목록
    <site_url>/wp-admin/edit.php?post=<post_id>&action=edit // 편집
    <site_url>/wp-admin/post-new.php?post_type=<post_type>  // 추가
    custom_post_admin_ui_002
    커스텀 포스트 목록 UI
    custom_post_admin_ui_003
    커스텀 포스트 편집 UI

    이 패턴 대로 URL을 입력하는 경우 위 그림처럼 익숙한 UI를 만날 수 있다. 만일 show_ui가 false이면 아래 그림처럼 권한이 없다는 메시지를 만날 수 있다.

    custom_post_admin_ui_001
    관리 UI에 접근 권한 없음

    show_in_nav_menus

    이 옵션은 기본값으로 public 옵션 값을 따라 간다. 이 값이 true이면 외모(appearance) > 메뉴(menus) 항목에서 커스텀 포스트 항목을 메뉴로 선택할 수 있게 된다.

    custom_post_admin_ui_004

    show_in_menu

    관리자 화면에 포스트 타입에 관한 메뉴를 출력할지 결정한다. show_ui는 반드시 true여야 한다.

    이 옵션은 true/false, 혹은 문자열을 가질 수 있다.

    true이면 관리자 화면에서 메뉴를 출력한다. 반대로 false면 관리자 화면에 메뉴는 출력하지 않지만 목록, 삽입, 편집의 URL을 알면 UI에 접근은 가능하다.

    문자열은 이미 워드프레스에 등록된 메뉴 슬러그를 대상으로 한다. 예를 들어 ‘글’ 메뉴는 post.php이다. 워드프레스의 기본 메뉴 슬러그의 예를 들면:

    • 글 (posts): edit.php
    • 미디어 (media): upload.php
    • 페이지 (pages): edit.php?post_type=page
    • 댓글 (comments): edit-comments.php
    • 외모 (appearance): themes.php
    • 플러그인 (plugins): plugins.php
    • 사용자 (users): users.php
    • 도구 (tools): tools.php
    • 설정 (settings): options-general.php

    이렇게 메뉴 슬러그를 입력하면 그 메뉴의 하위 메뉴에 해당 개체의 관리 UI 항목이 삽입된다. 아래 그림은 플러그인 메뉴에 HackPosts 관리 메뉴를 삽입한 예이다.

    custom_post_admin_ui_005

    show_in_admin_bar

    어드민 바는 워드프레스에 로그인하면 생기는 화면 상단의 관리용 UI이다. 전단부(frontend) 및 관리자 화면 양측에 둘다 나오므로 보다 편리하게 관리 명령을 사용할 수 있다.

    custom_post_admin_ui_006

    여기에 “+ 새로 추가 (+ New)” 버튼을 누르면 글, 페이지, 사용자를 쉽게 추가할 수 있다. 이 옵션이 true일 경우 해당 개체를 새로 추가할 수 있는 메뉴를 여기에 등록해 준다.

    custom_post_admin_ui_007

    기본값은 show_ui 옵션값을 따라 간다.

    menu_position

    메뉴의 위치를 설정한다. 정수로 입력하는데, 기본값인 null로 입력하면 댓글 아래에 메뉴가 삽입된다. PHP는 타입 저글링이 일어나 이 값을 문자열 형태로 입력해도 될 것 같지만, 실제로 해 보면 진짜 “정수형”만 가능하다는 점에 유의한다. 정수형이 아니면 기본값과 같게 동작하게 된다.

    $args = array(
        ....
        'menu_position'    => 65,    // ok
        // 'menu_position' => "65",  // wrong
        ....
    );
    
    register_post_type( 'wphack', $args );

    코덱스에서 수치에 대한 가이드라인을 참고할 수 있다.

    menu_icon

    메뉴 아이콘을 지정할 수 있다. 아이콘의 URL이나 dashicon id를 입력해 주면 된다. Dashicon 페이지에 들어가면 아래처럼 화면이 나온다. custom_post_admin_ui_008

    여기서 사용하고 싶은 아이콘을 클릭한다. 예를 들어 ‘Admin menu’의 가장 처음 보이는 아이콘을 클릭하면 그림처럼 아이콘이 크게 보인다. 붉은색 사각형으로 하이라이트한 문자열을 여기에 적으면 원하는 아이콘을 메뉴 아이콘으로 지정할 수 있다.

    custom_post_admin_ui_009

    $args = array(
        ....
        'menu_icon' => 'dashicons-menu',
        ....
    );
    
    register_post_type( 'wphack', $args );

    custom_post_admin_ui_010

    supports

    개체의 작성, 편집 화면에서 어떤 개체 작성 도구를 기본으로 지원할지 선택할 수 있다. 값으로 false나 배열을 입력할 수 있다.

    false를 입력한 경우 어떤 작성 도구도 선택하지 않을 때 쓴다. 단, 기본 메타 박스인 ‘Publish’는 사라지지 않는다. 배열의 경우 아래의 항목을 입력 가능하다.

    custom_post_admin_ui_011
    publish 메타박스는 사라지지 않는다.

    title

    제목(post_title)을 편집할 수 있는 UI를 제공한다.

    custom_post_admin_ui_014
    제목을 입력하는 입력 상자

    editor

    본문 편집기를 그대로 재활용할 수 있다.

    custom_post_admin_ui_015
    워드프레스 위지윅 편집기는 재활용 가치가 높다

    author

    작성자를 변경할 수 있다.

    custom_post_admin_ui_016

    thumbnail

    특성 이미지(featured image)를 선택할 수 있다. 테마에서 지원해야 한다.

    custom_post_admin_ui_017

    excerpt

    요약글을 작성할 수 있다.

    custom_post_admin_ui_018

    custom-fields

    사용자 정의 필드(커스텀 필드 또는 메타 필드)를 직접 수정할 수 있다. 키와 값이 그대로 출력되는 형태라 편집하기 직관적인 형태는 아니다. 주의할 점은, 직렬화된(serialized) 값은 이 목록에 포함되지 않는다. 예를 들어 아래 코드처럼 array를 serialize 시킨 것이라면 목록으로 출력되지 않는다. 개발하면서 가끔 착각할 수도 있으니 참고하도록 하자.

    custom_post_admin_ui_012
    키로 hack_key_01, hack_key_02를 입력하고 값에는 일반 문자열과 직렬화된 PHP 배열을 주었다.
    custom_post_admin_ui_013
    hack_key_01은 문자열이라 UI에 표시된다. 그러나 직렬화된 값을 가진 hack_key_02는 키의 존재만 감지될 뿐 UI로 출력되지 않는다.

    comments

    custom_post_admin_ui_019
    토론(discussion)메타박스 새 개체 추가 및 편집 화면에서 나온다.

    토론(discussion)관련 메타 박스를 출력하거나, 편집 화면에서 댓글(comments) 메타 박스를 출력해 댓글 관리를 할 수 있게 한다.

    custom_post_admin_ui_020
    댓글(comments) 메타 박스. 편집 화면에서 나온다.

    revisions

    개정판(revisions) 목록을 조회할 수 있는 메타박스를 보여 준다. 개정판 목록은 함부로 수정할 수 없다. 혹시 너무 많은 개정판이 문제라면 별도의 워드프레스 최적화 플러그인을 설치해서 이를 제거해 주거나 wp-config.php 파일을 수정해 주어야 한다.

    custom_post_admin_ui_021

    page-attributes

    페이지의 속성을 지정해 주는 메타 박스를 출력한다.

    custom_post_admin_ui_022

    상위(Parent) 항목은 커스텀 포스트의 다른 옵션인 ‘hierarchical’이 true인 경우에 출력된다. Order의 경우 테이블의 menu_order 값과 연결되는데, 이 값은 개체 목록 출력시 별도의 정렬 순서를 지정해 줄 수 있다. 예를 들어 다음과 같이 menu_order 값을 지정해 주었다.

    custom_post_admin_ui_023

    포스트 목록의 기본 순서가 그대로 정렬되어 나온다. 전단부에서 아카이브 페이지로 접근해도 이 순서는 동일하다.

    custom_post_admin_ui_024

    post-formats

    custom_post_admin_ui_025

    포스트 포맷은 워드프레스 3.1에서부터 지원하는 테마 기능이다. 코덱스에서는 대략적인 가이드라인을 줄 뿐, 각 포맷을 처리하는 방식은 전면적으로 테마에게 달려 있다. 아래에 항목에 대한 간략한 설명을 추가했다.

    • 추가정보 (aside): 올바른 번역인지는 잘 모르겠다. 페이스북과 같은 제목이 없이 콘텐츠만 나열하는 스타일로 사용된다.
    • 이미지 (image): 이미지를 위한 포스트 스타일. 첫번째 img 태그의 이미지가 해당 이미지로 간주된다. 포스트 본문에 URL 하나만 있을 수도 있는데, 그러면 그 이미지를 사용하며 이미지의 title 태그는 포스트 제목으로부터 온다.
    • 비디오 (video):비디오 혹은 비디오 재생 목록 스타일. 첫번째 video 태그나 object/embed 태그를 해당 비디오로 생락한다. 비디오와 마찬가지로 URL 하나만 있을 수도 있다.
    • 인용 (quote): 인용에 관한 콘텐츠를 설정하는 경우이다. 이 때 제목은 인용의 출처나 인용구의 저자 정보를 담을 수 있다.
    • 링크 (link): 다른 사이트로의 링크를 기록하는 스타일이다. 처음 <a href=”” 태그가 외부로의 링크를 의미한다. 이미지와 마찬가지로 포스트 본문에 URL 하나만 놓을 수 있는데 이 때 포스트 제목을 이 링크의 제목으로 설정한다.
    • 갤러리 (gallery): 이미지의 모음 스타일. 포스트의 내용으로 갤러리 쇼트코드를 가지고 있고 이미지 첨부 파일을 가지고 있을 수 있다.
    • 상태 (status): 트위터 스타일로 짧은 글을 작성하는 스타일이다.
    • 오디오 (audio): 팟캐스트 같은 오디오 파일 및 재생 목록 스타일이다.
    • 채팅 (chat): 채팅 목록 스타일.

    예를 들어, twentysixteen 테마에서 포스트 포맷을 걸어 보면 이렇게 나온다.

    표준 포맷

    custom_post_admin_ui_026
    standard 포스트 포맷. 커서가 지나는 중 캡쳐하여 글자색이 다른 건 무시하자.

    추가정보(aside) 포맷

    custom_post_admin_ui_027
    aside 포스트 포맷. 제목이 작게 나오고 ‘Aside’ 포스트 포맷이라는 표시가 나온다. 표준 포맷에 대해 제목이 좀 더 작게 나온다.

    상태 (status) 포맷

    custom_post_admin_ui_028
    status 포스트 포맷. 제목 자체를 필요로 하지 않는다. 또 제목링크가 완전히 사라져 단일 포스트만 화면의 접근이 차단된다.

    register_meta_box_cb

    개체에 대한 세부적인 인터페이스를 위해 메타 박스를 추가할 수 있다. 포스트 타입을 설정하면서 메타 박스를 디자인하기 위한 콜백 함수를 값으로 입력하면 된다.

    $args = array(
        ....
       'register_meta_box_cb' => 'wphack_meta_boxes',
        ....
    );
    
    register_post_type( 'wphack', $args );
    
    function wphack_meta_boxes() {
        ....
    }
    

    위 코드 예제처럼 콜백 함수를 등록하면 된다. wphack_meta_boxes() 함수 내에서 remove_meta_box()add_meta_box()를 불러 메타 박스를 편집하면 된다.

    예를 들어 기본적으로 삽입되는 슬러그(slug) 메타 박스를 삭제하고 싶다면 아래 코드를 삽입하면 된다.

    remove_meta_box( 'slugdiv', $post_type, 'normal' );

    한편 워드프레스에서는 해당 개체에 대해 읽기만을 허용하고 싶을 때에는 공개하기(Publish) 메타박스가 오히려 껄끄러울 것이다. 아래 코드처럼 사용해서 이를 삭제할 수 있다.

    remove_meta_box( 'submitdiv', $post_type, 'side' );

    이렇게 하면 슬러그와 발행하기 메타 박스는 화면에서 사라진다.

    마치며

    관리 UI 옵션은 커스텀 포스트의 여러 요소 중 관리자 화면에서 나타낼 유저 인터페이스와 관련 깊은 옵션들만 따로 모아 내가 임의로 그룹화한 것이다. 관리 화면 UI 관련 옵션인 만큼 워드프레스 관리자와 가장 밀접한 부분일 것이라 생각한다. 사용하는 목적에 따라 적절한 파라미터 값을 찾아 사용하기를 바란다.

     

  • 커스텀 포스트 집중 분석

    언젠가는 한 번 잡아서 해 볼 포스팅이었는데, 시간이 없다는 핑계로 엄청나게 미루고 있었다. 그치만 다시 여유가 넘치는 생활로 돌아오니, 이제는 다루고 넘어가야겠다는 생각이 든다.

    커스텀 포스트는 워드프레스를 자신의 취향에 맞게 활용하기 위한 핵심적인 기능 중 하나라고 할 수 있다. 이 지루한 포스팅을 더 지루하게 만들고 싶지는 않다. 커스텀 포스트가 왜 필요한지, 그것이 무엇인지에 대해서는 설명을 아끼도록 하겠다. 아무래도 개발적인 이야기만 늘어 놓을 작정이니, 이것에 대한 필요성은 이 포스팅일 읽는 거의 모든 이가 잘 이해하고 있으리라 생각한다.

    늘 그렇듯 내가 커버하고자 하는 모든 내용은 register_post_type() 함수에 대한 코덱스에서 서술되어 있다. 또 커스텀 포스트는 pods 같은 플러그인에서도 손쉽게 확장할 수 있도록 되어 있다. 그렇지만 제아무리 뛰어난 플러그인이라 할지라도 아마 register_post_type에서 사용하는 수많은 옵션 값들을 생략한 채로 내놓는 플러그인은 없을 것이다.

    그런데 이 내용이 워낙 많고 복잡하다보니 나도 잊을 때가 많기도 한데다 기능이 새로 추가되는 일도 있으니 그러한 기능을 공부하고자 하는 목적이 우선이다. 포스팅을 하면서 스크린샷도 많이 달 생각이고, 워드프레스 소스도 많이 달아 두려고 한다. 소스는 현재 사용 중인 4.5.2 기준이다.

    포스트 타입 이름

    포스트 타입 이름은 20자 내여야한다. 영대문자와 공백은 포함하면 안 된다. 또한 몇몇 이름은 이미 점유되어 있기 때문에 그 이름은 사용해서는 안 되며, 이미 사용중인 커스텀 포스트 타입 이름이 있을 수도 있으니 prefixing을 권장한다. register_post_type 함수의 첫번째 인자로 사용된다.

    사실 코어는 모든 포스트 타입을 posts 테이블에 저장한다. 커스텀 포스트로 새로운 타입을 만들든, 아니면 내부의 기본 타입의 포스트를 사용하게 되든 포스트라면 모두 예외없이 posts 테이블에 저장된다.

    한편 posts 테이블에는 post_type 이란 최대 길이 20자의 varchar 필드가 존재한다. 바로 이 필드가 모든 포스트 타입을 구분하는 데 사용된다. 포스트를 작성하면 그 레코드의 post_type 필드 값은 ‘post’일 것이고 커스텀 포스트를 저장했다면 그 커스텀 포스트의 타입 이름이 저장될 것이다.

    코덱스에도 언급되어 있지만, 아래 포스트 이름은 포스트 타입 이름으로 쓸 수 없다.

    • post: 기본 포스트 타입으로 선점되어 있다.
    • page: 기본 페이지 타입으로 선점되어 있다.
    • attachment: 첨부 파일을 위한 포스트 타입으로 이미 사용된다.
    • revision: 글을 수정하고 저장하면 ‘개정판’의 개념으로 이전 작성글이 보관된다. 이전 개정판본의 저장 내역을 위한 포스트 타입으로 사용된다.
    • nav_menu_item: 네비게이션 메뉴 항목도 일종의 포스트로 저장된다.

    다음은 내부에서 파라미터 등으로 곳곳에서 사용되기 때문에 사용해서는 안 되는 단어들이다.

    • action
    • author
    • order
    • theme

    아마 내부 로직에서 해당 문자열이 곳곳에 사용되므로 잘못하면 오작동을 일으킬 우려가 있지 않을까 생각해 본다. order는 순서라는 뜻 말고 ‘주문’이라는 뜻도 있다. 우커머스 같은 상거래 플러그인과 직결되는데, 우커머스의 주문 포스트 타입도 그리하여 shop_order로 사용한다.

    인자 목록

    인자 목록은 PHP의 연관배열(associative array)로 구성되어 있다. 키의 구조는 워드프레스의 버전에 따라 추가 혹은 삭제될 수 있다. 이 인자의 수는 포스트 타입에 대한 섬세한 제어가 가능한 만큼, 그 수가 많고 또 몇몇 파라미터는 까다로워서 코덱스에서조차 제대로 설명되지 않은 것도 있다.

    이렇게 많은 내용을 한 포스트에 담아 내는 것은 적절하다고 판단하지 않아, 몇 개의 카테고리로 나누어 별도의 포스트로 분할하여 작성해 보았다. 아래는 각 파라미터 마다 적절히 그룹을 짓고 각 하위 포스트를 링크한 것이다.

    레이블

    • label
    • labels

    커스텀 포스트 레이블 집중 분석 포스트에서 이를 다룬다.

    가시성

    • public
    • exclude_from_search
    • publicly_queryable
    • has_archive
    • query_var

    이 포스트에서 확인할 수 있다.

    관리 UI

    • show_ui
    • show_in_nav_menus
    • show_in_menu
    • show_in_admin_bar
    • menu_position
    • menu_icon
    • supports
    • register_meta_box_cb

    이 포스트에서 확인할 수 있다.

    역할과 권한

    • capability_type
    • capabilities
    • map_meta_cap

    이 포스트에서 볼 수 있다.

    말단지점(endpoint)과 다시 쓰기(rewrite)

    • permalink_epmask
    • rewrite

    이 포스트에서 볼 수 있다.

    REST

    • rest_base
    • rest_controller_class
    • show_in_rest

    분류(taxonomy) 및 기타

    • can_export
    • description
    • hierarchical
    • taxonomies

    이 포스트에서 다룬다.

    참고 자료

    워드프레스 3.X 기반의 커스텀 포스트이지만, Justin Tadlock이라는 블로거가 쓴 Custom post types in WordPress는 여전히 가치가 높다. 이 블로거는 Members 플러그인 외 여러 플러그인의 제작자이기도 하다.

  • 커스텀 포스트 가시성 관련 옵션 집중 분석

    이 포스트에서는 커스텀 포스트의 가시성과 관련된 옵션을 다룬다. 목록은 아래와 같다.

    • public
    • exclude_from_search
    • publicly_queryable
    • query_var
    • has_archive

    전체 옵션은 이 포스트에서 확인할 수 있다.

    이 옵션션들은 개체를 워드프레스 전단부(frontend, 일반 사용자가 만나게 되는 사이트 외부 화면)에 노출시키는 방법과 관련이 있다.

    참고로 아래 글들은 모두 고유 주소(permalink)를 기본(plain)으로 세팅하였을 때로 상정하고 작성하였다.

    public

    프리셋 같은 옵션이다. 이것 하나만 true/false로 정해줘도 관련된 다른 옵션은 일일이 지정하지 않아도 그 의미에 따라 자동으로 true/false로 지정된다.

    true일 때 다음처럼 동작한다.

    • exclude_from_search: false
    • publicly_queryable: true

    false일 때 다음처엄 동작한다.

    • exclude_from_search: true
    • publicly_queryable: false

    이 옵션은 관리 UI에도 관여한다.

    exclude_from_search

    외부 화면에서 글을 검색할 때 키워드에 해당 포스트는 제외하도록 지정한다. 옵션 이름이 exclude이므로 포함의 반대.

    검색 파라미터는 URL상에 /?s=<term> 식으로 입력된다. 다시 말해 파라미터 ‘s’가 커스텀 포스트도 포함하여 데이터베이스를 검색할지 말지를 결정하는 옵션이다.

    publicly_queryable

    이 포스트를 쿼리할 수 있는지 결정한다. false라면 전단부에서는 글을 조회할 수가 없다. 워드프레스는 아래 방식으로 전단부의 글을 쿼리한다.

    • ?post_type={타입}: 개체 목록 쿼리
    • ?{포스트타입_쿼리변수}={포스트_슬러그}: 단일 개체 쿼리

    만일 wphack이라는 커스텀 포스트를 등록했으면 아래 예제와 같다.

    • ?post_type=wphack
    • ?wphack=wphack-6

    query_var

    쿼리 변수를 별도로 지정할 수 있다. true로 지정하면 $post_type으로 지정하고, false면 쿼리 변수를 쓰지 않는다. 또 문자열로 입력 가능한데, 이러면 별도의 쿼리 변수를 사용한다.

    예를 들어 query_var 옵션의 값을 hp로 지정한 경우, 이제 단일 개체 목록을 부르기 위해 사용한 URL ?wphack=wphack-6은 이제 사용이 불가하고 이제는 URL을 이렇게 고쳐야 한다: ?hp=wphack-6

    has_archive

    이 옵션이 true/false이든 관계없이 개체 목록을 불러오는 URL은 post_type=wphack처럼 사용한다.

    custom_post_visibility_001

    위 그림 좌측이 has_archives가 false, 우측이 has_archives 옵션이 true인 경우이다. “그래서 ‘Archives: ‘ 라는 텍스트가 추가된 것 말고는 도대체 뭐가 변한 건가?”라고 의문을 가질 수 있다.

    사실 가장 중요한 변경점이 나타난 것이다. 바로 has_archives가 true로 설정되면서 테마의 템플릿이 변경된 것이다.

    예로 쓰고 있는 워드프레스의 템플릿은 기본으로 설치되는 twentysixteen인데,  포스트의 기본 템플릿은 twentysixteen/index.php 파일을 이용한다. 아카이브의 기본 템플릿은 twentysixteen/archive.php을 이용하게 된다. 워드프레스 템플릿의 기본 룰이다.

    만일 아카이브를 가지지 않는다(false)고 하면, 일반 블로그의 글 목록을 쓸 때 쓰는 가장 기본인 index.php를 템플릿으로 사용한다.  반면 아카이브를 가진다(true)고 하는 경우는 이제 archive.php를 템플릿으로 사용하는 것이다.

    다만 index.php와 archive.php 파일을 직접 보면 구조가 거의 같다. 템플릿이 코드가 거의 동일해서 결과가 동일하게 눈에 보이는 것일 뿐, 사실 수면 아래에서는 전혀 다른 프로세스가 일어났던 것이다.

    템플릿 룰 중에 또 이런 것이 있다. 특정 포스트 타입을 위한 아카이브 템플릿 파일을 별도로 지정하는 방법이 있다. ‘archive-{포스트 타입}.php’와 같이 이름을 짓는 방법이다. 예제로 드는 wphack 포스트 타입이라면 ‘archive-wphack.php’라고 이름짓고 별도의 템플릿을 디자인하면 이제는 이 포스트 타입만을 위한 아카이브 페이지가 출력될 것이다. 만일 특정 포스트 타입이 별도의 목록 페이지 스타일을 가지게 만드려면 이 옵션을 반드시 true로 설정해야 할 것이다.

    한편 아카이브를 가지게 되면 커스텀 포스트의 목록을 메뉴에 삽입할 수 있다. 관리자 메뉴 외모(appearance) > 메뉴(menus)로 접근해 보자. 커스텀 포스트를 위한 만들 때 단일 개체 뿐 아니라 개체 목록 전부를 출력하는 링크를 선택해 메뉴에 삽입할 수 있다.

    custom_post_visibility_002

    아래 그림처럼 메뉴로 나온다. 만약 이렇게 메뉴를 삽입하고 난 다음에 has_archives 옵션을 true에서 false로 변경해버리면 링크가 동작하지 않는다.

    custom_post_visibility_003

    정리: 옵션 조합

    그러니까 어떤 옵션을 쓰면 어떤 상황에서는 개체가 나올 수도, 반대로 나오지 않을 수도 있다. 매우 세부적으로 나눠져 있어 오히려 혼란스럽기도 하다.

    사실 전면 화면에서의 가시성은 public 옵션을 쓰는 것이 이상적이고 편하기도 하다. 그렇지만 만일 이런저런 세부 옵션을 조합하면 어떤 결과가 나올까? public을 true/false로 정했을 때 지정되는 방법 이외의 케이스를 한 번 따져 보자.

    1. exclude_from_search: true, publicly_queryable: true
      검색에서 제외되지만 쿼리는 가능한 경우이다. 글 목록은 전면에서 조회하지만, 내용을 검색할 수 없어 어색해진다.
    2. exclude_from_search: false, publicly_queryable: false
      검색은 되지만 전면에서 글을 볼 수가 없다. 검색은 되지만 본문을 보려 해도 접근이 안 된다. 이 역시 어색하다.

    또 publicly_queryable이 false면 query_var는 아무 의미가 없다. 한편 query_var는 true, false, 그리고 어떤 문자열도 가능하다. publicly_queryable이 true로 고정되었다고 하면, query_var의 조합에 따라 다음과 같은 결과가 나올 수 있다.

    query_var를 true로 설정하는 것은 가장 자연스러운 옵션이다. ?{query_var}={post_slug} 과 같은 URL로 접근된다. 또 query_var를 어떤 문자열로 쓰는 것도 자명한 결과이다.

    그런데 query_var를 false로 쓰는 것은 어떤 결과를 불러 올까? 우선 URL post_type=wphack으로 개체 목록을 접근할 수 있지만, wphack=post_slug으로는 접근 불가능하다.

    그렇지만 이것이 각 개체에 대한 접근을 제어하는 것은 아니다. 파라미터의 조합에 따라 query_var 없이도 얼마든지 개체에 접근할 방법이 있기 때문이다. 단지 ?wphack=hackpost-6 처럼 각개 개체에 대한 단일 화면에 슬러그(포스트 이름, post_name)를 이용해 접근하는 것이 불가능해 질 뿐임을 의미하는 것이다. 워드프레스는 query_var가 false가 되면 각기 단일 개체 접근하는 URL을 ‘p’ 파라미터를 이용해 구성한다. p는 포스트의 고유 ID를 받을 수 있다.

    예를 들어 ‘HackPost #5’라는 제목을 가진 wphack 개체가 있다고 보자. 이 개체의 슬러그는 ‘hackpost-5’이고 ID는 10이라고 한다. 그러면 query_var에 관계 없이 다음 URL로 접근 가능하다.

    • site_url/?post_type=wphack&p=10 (단일 개체)
    • site_url/?post_type=wphack (개체 목록)
    • site_url/?p=10 (단일 개체)

    이것은 고유주소(permalinks) 옵션을 기본(plain)에서 다른 옵션으로 변경한다 하더라도 지장이 없다. 단지 웹브라우저에서 예쁜 URL로 표시되는 것일 뿐, 서버에서는 이 예쁜 URL을 규칙에 따라 분석해서 index.php?post_type=…&p=…&s=… 와 같이 내부적으로 변경하기 때문에 URL을 어떤 스타일로 넣든 결과는 사실상 동일하다.

  • 커스텀 포스트 레이블 집중분석

    커스텀 포스트 레이블은 꽤 많은 경우 사소한 문제로 넘어가게 된다. 보통 커스텀 포스트를 워드프레스 기본 포스트 타입인 ‘포스트’와 유사하게 별도의 작성자가 꾸준히 어떤 콘텐츠를 작성(주로 수동으로)해 발행하기 위한 용도로는 잘 사용해 본 적이 없기 때문이다.

    그러다 보니 레이블에 대한 인식은 많이 낮았다. 또 레이블에 별로 신경 쓰지 않아도 코어가 ‘post’나 ‘page’ 타입에 의거해 기본적인 레이블을 만들어 주니 신경 쓸 것이 거의 없었기도 했고.

    register_post_type 레퍼런스를 보면 꽤나 많은 입력 인자가 있는데, 이 중에서도 상당수를 차지하는 것이 레이블이다. 사소하기는 하나 이 레이블들이 어디에서 어떻게 쓰이고 있는지 꼭 한번은 체크해 보고 싶었다. 물론 이것은 로직과는 별개로 그저 ‘텍스트’의 취향일 뿐이라고 할 수도 있다. 그리고 대략의 문서를 보면 어떤 텍스트를 넣어야 하는 건지도 바로 이해할 수도 있다.

    그러나, 궁금했다. 이렇게 열심히 세부 옵션을 넣어 텍스트를 지정해 주면 도대체 UI 어디에서 이 레이블을 활용하고 있는 건지, 이 레이블이 실제로 어디서 어떻게 쓰이는지 조목조목 따져 보고 싶었다. 그렇게 알게 되면 각 레이블에 대한 이해도도 높아지지 않을까?

    원래 커스텀 포스트에 대해 포스팅을 하면서 한꺼번에 처리하려고 했지만, 의외로 레이블의 세부 옵션이 많아서 이것만 따로 포스팅하는 것이 낫겠다 싶어 별도로 작성한다.

    자, 그럼 지루하기는 하지만 커스텀 포스트의 레이블이 어떤 식으로 사용되나 보도록 하자.

    레이블과 관련된 옵션

    여기서 레이블(label)이란 것은 UI 상에 표시되는 텍스트를 말한다. 다들 알다시피 워드프레스는 다국어 설정이 가능하다. 그러므로 각 언어 설정에 따라 표시되는 텍스트는 달라질 수 있다. 그래서 어떤 UI 상에 어떤 텍스트를 표시하려면 두 가지 조건이 필요하다. 바로 언어 도메인과 문맥이다. 언어 도메인은 워드프레스가 어떤 언어로 표시될 지를 지시하고 문맥은 어떤 상황의 텍스트를 출력해야 하는지를 지시한다.

    레이블과 관련된 커스텀 포스트의 옵션은 크게 두 가지가 있다. label과, labels이다. 사실 두 옵션을 다 사용할 필요는 없고, 커스텀 포스트를 만들 때 둘 중 하나만 써도 된다. label은 아주 심플하게 레이블을 만들고 싶을 때 (다시 말해 레이블에 그다지 신경을 쓰지 않아도 좋을 때), 반면 labels는 각 레이블에 대해 세부적인 문맥에 맞춰 텍스트를 지정해 줄 수 있다.

    label 옵션

    가장 기본으로 사용할 수 있는 것이 label 옵션이다. 아주 간단한 용도의 커스텀 포스트라면 이 옵션만 사용해도 큰 문제는 없다. 나머지 세세한 레이블 텍스트는 기본 타입인 ‘post’를 기준으로 적절히 메꿔지기 때문이다. 왠만큼 까다로운 사람이 아니라면 이 것 때문에 불편을 호소할 일은 거의 없을 것이다.

    custom_post_label_001

    이 옵션만을 주고 ‘wphack’ 타입의 커스텀 포스트를 만들었다. 레이블 이름은 ‘HackPosts’로 정했다. 보통 복수로 레이블 이름을 주는 것이 관례이다. 메뉴는 ‘post’ 타입에 준해 적절히 보간되고 번역되었다.

    코드 내부에서 labels를 발견하지 못하고 label만 있다면 label에 의거해 모든 labels 세부 텍스트 항목을 만들어 내서 커스텀 포스트를 등록한다. 그러니까 커스텀 포스트를 만들면서 label과 labels를 동시에 쓸 필요는 없다.

    labels 옵션

    커스텀 포스트의 각 레이블을 보다 세심하게 신경 써 주어야 할 경우도 있을 수 있을 것이다. 이 경우를 위해 워드프레스는 labels라는 옵션을 추가로 제공한다. 이 옵션에서는 커스텀 포스트를 생성하면 생각할 수 있는 모든 경우에 대해 상세하게 텍스트를 지정해 줄 수 있다. 사실 본 포스팅의 주 목적.

    우선 세부 옵션부터 나열해 보자.

    • name
    • singular_name
    • add_new
    • add_new_item
    • edit_item
    • new_item
    • view_item
    • search_items
    • not_found
    • not_found_in_trash
    • parent_item_colon
    • all_items
    • archives
    • insert_into_item
    • uploaded_to_this_item
    • featured_image
    • set_featured_image
    • remove_featured_image
    • use_featured_image
    • menu_name
    • filter_items_list
    • items_list_navigation
    • items_list
    • name_admin_bar

    각 세부 옵션의 이름으로 이 텍스트가 무엇인지 추측을 할 수 있다. 그래서 적절하게 번역 텍스트를 주면 어차피 텍스트니 프로그램이 돌아가는 데는 큰 지장은 없다. 그렇지만 나는 확실히 이 텍스트가 어디서 어떻게 나오는지를 알아보고 싶었다.

    name 레이블 옵션

    포스트 타입에 대한 일반적 이름이다. 워드프레스 UI 전반에서 이 포스트 타입 단위를 지칭할 때 쓰인다. 위 설명된 label 옵션과 동일하게 복수형으로 지으면 된다. label 옵션을 쓰는 것과 labels 옵션에서 이 세부 옵션 하나만 쓰는 것은 사실 같다고 볼 수 있다.

    singular_name 레이블 옵션

    이 포스트 타입 하나의 개체를 지칭할 때 쓰이는 이름이다. 사실 UI 상에서는 이 텍스트가 보이는 일은 그리 흔치 않다. 하나 예를 들자면 아래 그림처럼 어드민 바에서 새로운 개체를 작성할 때의 레이블로 사용된다. (정확히 설명하자면 name_admin_bar 세부 옵션의 기본값이 singular_name 옵션값이기 때문이다)

    만일 name만 있다면 singular_name은 name을 따라 간다. 복수, 단수 구분 없이 무조건. 그리고 name 마저도 없다면 이보다 한 단계 위의 label 옵션에서 name을 가져 온다. 그럼 label 옵션 마저 없다면? label의 기본값은 Posts, 혹은 Pages이다. 구조적인 타입이라면 Pages고 비구조적이라면 Posts로 이름이 만들어질 것이다.

    custom_post_label_002

    한국어에서는 단수/복수 개념이 뚜렷하지 않긴 하지만, 어쨌든 옵션 이름이 의미하는 것처럼 단수로 지정해 주어야 한다.

    참고로 Piklist라는 빠른 개발용 플러그인이 있다. 여기서 별도의 훅을 지정해 커스텀 포스트를 생성할 수 있도록 하는 기능을 제공한다. register_post_type 함수를 래핑하여 보다 편하게 쓸 수 있게 만든 것인데, 여기서는 name 인자를 하나만 넣어 줘도 영어 단수/복수 규칙을 추측해 singular_name, plural name을 지정하는 기능을 갖추고 있다. 왠지 영어권 사용자에게는 나름 유용해 보인다.

    add_new 레이블 옵션

    메뉴에 나오는 ‘Add New’ 텍스트를 변경할 수 있다. 이 텍스트는 명백하게 두 곳에서 사용되고 있다.

    custom_post_label_003

    어드민 메뉴의 메뉴 항목과 페이지 h1 문단 제목 우측의 버튼의 텍스트로 사용된다.

    add_new_item, edit_item 레이블 옵션

    add_new_item은 새 개체 작성 페이지의 h1 문단 제목으로 사용된다. ‘_item’ 접미의 item은 해당 단수 개체 이름이라고 생각하면 된다. 마찬가지로 edit_item은 개체 편집 페이지의 h1 문단 제목으로 사용된다. 아래 그림은 이 옵션을 지정하지 않은 것과 한 것을 비교한 것이다.

    custom_post_label_004

    new_item 레이블 옵션

    UI 전반에서 사용되는 레이블은 아닌 것으로 보인다. 코드의 완전성을 위해 넣은 듯하다.

    view_item 레이블 옵션

    개체 편집 화면의 어드민 바에는 프론트 화면에서 작성된 개체가 어떻게 보이는지 바로 확인하는 메뉴가 삽입된다. 이 옵션으로 그 텍스트를 변경할 수 있다.

    custom_post_label_005

    또 참고로 이 레이블 텍스트는 댓글(Comments) 목록 화면의 ‘댓글이 달린 글(In Response To)’ 칼럼에서 사용된다. ‘글 보기(View Post)’ 링크 텍스트가 바로 그것이다. 물론 이것은 기본인 ‘post’ 타입에만 해당되겠지만.

    custom_post_label_006

    search_items 레이블 옵션

    개체 목록을 검색하기 위한 검색 버튼의 텍스트를 변경할 수 있다.

    custom_post_label_007

    not_found, not_found_in_trash 레이블 옵션

    not_found 레이블 옵션은 개체 검색 결과가 없는 경우에 이를 알리기 위한 텍스트를 위해 주어진다. 마찬가지로  not_found_trash 레이블 옵션은 휴지통에서 검색한 경우의 텍스트이다.

    custom_post_label_008

    parent_item_colon 레이블 옵션

    포스트 타입을 계층적(hierarchical)으로 설정한 경우 개체의 부모 개체를 설정해 줄 수 있다.

    사실 이 레이블은 UI 상에서 찾아 보기가 어렵다. 이 텍스트가 명시적으로 보이는 한 예는 이렇다. 포스트 목록에서 부모 포스트가 삭제되거나 휴지통으로 이동하여 부모-자식 위계에 영향을 주는 사안이 발생한 경우 자식 포스트에서 부모 포스트가 어떤 것인지 표시해 줄 때 사용된다.

    아래 그림처럼 부모 – 자식 관계가 있는 페이지 목록이 있다고 보자.

    custom_post_label_009

    그리고 부모 페이지인 ‘Parent Page’를 휴지통으로 보내고 난 다음 목록을 다시 불러오면 아래처럼 화면이 변경된다.

    custom_post_label_010

    텍스트 구조는 이렇다: | parent_item_colon <부모 개체의 이름>

    한편 포스트 타입 구조가 아닌 카테고리에 해당하는 케이스지만 비슷한 사례라 기록을 남겨 본다. 아래 그림은 ‘post’ 편집 화면에서 카테고리 설정을 위한 메타박스 UI이다.

    워드프레스에는 시각적으로 표시되지는 않는 여러 텍스트들이 HTML 코드 상에 존재한다. 시각장애인을 위해 존재하는 들리는 텍스트들이다. 그림의 붉은 상자로 표시된 쪽의 입력 상자를 위한 들리는 레이블이 존재한다. 이 레이블의 텍스트로 카테고리의 parent_item_colon 속성이 사용된다.

    custom_post_label_011

    HTML 보면 아래 코드와 같이 출력된다.

    <label class="screen-reader-text" for="newcategory">Add New Category</label>
    <input type="text" name="newcategory" id="newcategory" class="form-required form-input-tip" value="New Category Name" aria-required="true"/>
    <label class="screen-reader-text" for="newcategory_parent">
      Parent Category:
    </label>

    label for=”newcategory_parent” 태그를 보면 Parent Catecory: 라는 텍스트를 확인할 수 있다. 포스트 레이블이 아닌 카테고리 레이블의 용례이지만, 둘 다 엇비슷하므로 같이 남겨 본다.

    all_items 레이블 옵션

    ‘모든 개체들’의 의미를 지닌 텍스트를 출력하기 위해 지정할 수 있다.

    커스텀 포스트를 생성하면 나오는 하위 메뉴로 ‘모든 글’, ‘모든 페이지’ 같은 ‘모든 개체’ 항목이 자동으로 생성된다. 이 때 이 레이블이 사용된다.

    한편 커스텀 포스트의 ‘show_in_menu’ 옵션은 불리언 혹은 문자열을 넣을 수 있다. 불리언의 경우는 메뉴에 보일 것인지 숨길 것인지 정하기 위해 사용한다. 그런데 인수로 문자열로도 입력할 수도 있는데, 이렇게 되면 해당 메뉴의 하위 메뉴에 커스텀 포스트 UI가 삽입된다.

    예를 들어 ‘show_in_menu’의 값으로 ‘tools.php’ 문자열을 입력하면 HackPosts UI는 도구(Tools) 메뉴의 하위 메뉴로 이동하게 된다. 이 때에도 레이블의 텍스트로 all_items 레이블 옵션이 사용된다.

    custom_post_label_012

    다른 예로 두 유저간에 개체 편집 충돌이 일어나는 경우에 출력된다. 가령 사용자 A가 편집 중인 개체를 사용자 B도 편집하기 위해 해당 URL로 접근한다고 생각해 보자. 그러면 사용자 B는 다음과 같은 메시지를 받음으로써 사용자 A가 편집 과정에 있음을 통지받는다.

    custom_post_label_013

    이 때 사용자 B가 Take Over 단추를 눌려 편집권을 이양받게 되면, 편집 중이었던 사용자 A는 이런 메시지를 실시간으로 전달받게 된다. 이 때 all_items 레이블이 사용된다. (설명은 장황한데, 정말 너무 사소한 부분이다…)custom_post_label_014

    archives 레이블 옵션

    메뉴 편집 화면에서 해당 타입의 아카이브를 위한 레이블이다. 아래 그림을 보자.

    custom_post_label_015

    ‘All HackPosts Items’라고 나온 것은 archives 레이블 옵션이 정해지지 않았을 때이다. 이 값이 없다면 all_items레이블 옵션에서 가져오기 때문에 all_items 레이블이 출력된다.

    custom_post_label_016

    archives 레이블을 적절히 조절하면 위 그림처럼 별도의 레이블을 가지게 된다.

    insert_into_item 레이블 옵션

    custom_post_label_017

    미디어 삽입 화면에서 개체에 미디어를 삽입시키는 버튼 텍스트로 사용된다.

    uploaded_to_this_item 레이블 옵션

    ‘미디어 추가(Add Media)’ 버튼을 클릭하면 나오는 미디어 관리 창에 속한 미디어 필터의 한 레이블 텍스트. 아래 그림과 같은 위치에 있다.

    custom_post_label_018

    이 아이템으로 업로드된 미디어란 의미는 로 연결되었다는 의미이다. 현재 편집 중인 화면에서 미디어 추가를 눌러 파일을 업로드하면, 해당 업로드 파일은 편집 중인 개체에 특정지어 업로드 되었다고 간주된다. DB에서는 attachment 포스트의 post_parent 필드가 현재 편집 중인 post ID로 대입된다는 의미로 볼 수 있다.

    featured_image, set_featured_image, remove_featured_image 레이블 옵션

    support 옵션에 ‘thumbnail’을 추가하면 커스텀 포스트도 특성 이미지를 지정할 수 있다. 특성 이미지라는 이름을 다른 것으로 변경하기 위해 featured_image를 사용한다. 이름으로 추측 가능하다. 다들 특성 이미지 관련 UI에서 레이블로 사용된다.

    custom_post_label_019

    use_featured_image 레이블 옵션

    이 레이블이 직접적으로 사용된 UI를 찾기가 쉽지 않다. 왜냐하면 이 레이블이 코어에서 직접적으로 쓰이는 곳은 단 한 곳, wp-admin/includes/media.php 파일의 get_media_item() 이라는 함수 뿐이다.

    get_media_item 함수는 이미지 첨부 메타데이터를 수정할 수 있는 HTML 폼을 출력하는데, 워드프레스 관리 UI 상에서 일반적인 방법으로는 이 주소가 명시적으로 나타난 곳이 없다. 최근 버전의 워드프레스는 미디어 파일의 조회와 수정은 post.php에서 모두 처리하도록 되어 있다.

    그렇지만 이 화면을 완전히 볼 수 없는 것은 아니다. 직접 주소를 쳐서 들어가면 된다. 다음과 같은 경로로 접근하면 된다.

    <site_url>/wp-admin/media.php?action=edit&attachment_id=<attachment_id>&post_id=<post_id>

    action, attachment_id 두 파라미터는 정상적으로 화면이 출력되기 위해 필수적으로 있어야 하며, 특성 이미지 속성까지 출력시키려면 post_id 파라미터가 별도로 필요하다. 이 때 attachment_id는 attachement 포스트의 ID, post_id는 특성 이미지를 집어 넣고 싶은 포스트의 ID이다. 올바르게 입력하면 아래 그림과 같은 화면이 출력된다. 목록 마지막에 use_featured_image 레이블 옵션이 나오는 것을 확인할 수 있다.

    custom_post_label_020

    menu_name 레이블 옵션

    기본값이 name 옵션과 같은 이것은 관리자 메뉴의 레이블을 별도로 지정하고 싶을 때 사용된다.

    custom_post_label_021

    filter_items_list, items_list_navigation, items_list 레이블 옵션

    이 레이블들은 숨겨져 있고 스크린 리더를 위한 텍스트로 입력된다. 개체 목록 UI 화면에서 <h2 class=’screen-reader-text’>를 검색하면 해당 레이블 값이 나오는 것을 확인할 수 있다.

    filter_items_list는 필터 버튼을 위한 스크린 리더 텍스트이다.

    <h1>HackPosts
        <a href="http://wphack.vagrant:8080/wp-admin/post-new.php?post_type=wphack" class="page-title-action">
            Add New HackPost
        </a>
    </h1>
    <h2 class='screen-reader-text'>
        Filter HackPosts List
    </h2>
    <ul class='subsubsub'>
    ...

    items_list_navigation은 개체의 수가 많아 몇 개의 페이지로 나뉘어 질 때 페이지네이션을 위한 스크린 리더 텍스트로 사용된다.

    <h2 class='screen-reader-text'>
        HackPosts List Navigation
    </h2>
    <div class='tablenav-pages'>
        <span class="displaying-num">6 items</span>
        <span class='pagination-links'>
        ...

    items_list는 테이블 목록 바로 위에 있다.

    <h2 class='screen-reader-text'>HackPosts List</h2>
    <table class="wp-list-table widefat fixed striped pages">

    name_admin_bar 레이블 옵션

    어드민 바의 ‘+ 새로 추가 (+ New)’ 메뉴에 새 개체를 삽입하는 명령을 추가할 수 있다. 이 때의 레이블 옵션을 별도로 지정할 수 있다. 이 옵션이 없다면 singular_name 레이블 옵션을 가져와 사용한다.

    custom_post_label_022

    마치며

    어떤 레이블이 UI 어디에서 어떻게 쓰이는지에 대해 굉장히 궁금했었다. 물론 코덱스에 있는 대로 적당히 뉘앙스나 문맥만 파악한 후 개체에 맞게 말을 고쳐 주면 그만일 수도 있지만, 그 레이블이 나오는 정확한 문맥을 알 수 없었기에 과연 올바른 의미를 가진 레이블로 제공되는지 확실히 알 수가 없었다. 이번 기회로 각 레이블이 어떤 상황에서 어떻게 쓰이는지 명확히 파악해 보았다. 이젠 보다 자신있게 커스텀 포스트의 레이블을 다룰 수 있으리라 생각한다.

  • 내가 어쩌다?

    내가 어쩌다 이렇게 워드프레스 개발에 깊숙히 들어오게 된 걸까?

  • 우커머스 결제/배송 정보 관련 의문점

    의문점.

    결제 관련 정보(Billing details)에서는 결제자의 이메일과 전화번호를 적는 란이 있다. 그런데 배송 정보(Shipping details)에는 그렇지 않다. 조금 전 생짜 워드프레스에 우커머스만 올려 놓고 테스트를 해 배송 정보에는 이메일과 전화번호 필드가 포함되지 않음을 확인했다.

    간혹 우커머스의 결제와 배송이 서로 다른 경우에는 어떻게 하란 말인가? 한국에서는 배송을 할 때 배송 상자에 받는 사람의 전화번호도 같이 적게 되어 있다. 그리고 택배 기사님들이 보통 수신인이 부재중일 경우 이 전화로 전화를 걸기도 하고. 결국 한국 상황에 맞춰 일괄적으로 기능 확장을 하는 수 밖에 없지 않은가?