Plugins, Must Use Plugins, Child Theme, functions.php

워드프레스로 블로그, 웹사이트를 처음 구성할 때나 운영 중에 콘텐츠 표현 변경 또는 특정 기능 추가 및 변경이 필요한데, 확실하지 않거나 조금 애매한 과정이 있어 정보를 찾으면 팁과 함께 다음 안내를 커뮤니티나 블로그 등에서 언제나 볼 수 있습니다.

  • 사용하는 테마의 functions.php 파일에 추가하세요.
  • Child theme 생성하여 구성하세요.
  • 플러그인(또는 Must Use Plugins)으로 정의하여 사용하세요.

팁은 얻었지만, 입문자의 경우 추가하는 방법이 새로운 걸림돌이 되어 외면하거나 불필요한 기능이 더 많이 포함된 설치 플러그인으로 부족한 경험을 위안 삼는 경우가 있습니다. 위의 3가지 항목에 관련한 많은 정보가 웹에 있으며, 코덱스에도 충실한 정보로 안내하고 있습니다. 하지만 입문자가 코덱스 정보 기준으로 이해할 때, 코덱스 정보를 번역한 방식으로 사용자들이 생산한 포스트로 경험할 때 조금 부족할 수도 있습니다.

입문자를 위한 것으로 위의 항목을 사용하는 간단한 실 예제를 통해 알아봅니다. 이어서 나오는 기준 환경에 맞춰서 따라 해보는 것도 좋습니다. 꼭 알아야 하는 것은 아니지만, 꼭 알기 싫다면 꼭 워드프레스를 사용할 필요가 없다 표현할 정도로 기본 중의 기본인 워드프레스 배경지식입니다. 또 글에 나오는 워드프레스 훅이나 일부 PHP 코드는 처음의 전제처럼 검색이나 답변자에게 도움을 얻어 사용한다는 기준이므로 설명하지 않습니다. 글의 취지를 기억하세요.

기준

  • 워드프레스 한글 버전 설치 후 기본 상태
  • 테마 twenty fifteen, 테마 twenty sixteen 설치
  • 기본 활성 테마는 twenty fifteen
  • 크롬 브라우저 사용

따라 할 워드프레스 기본 환경을 구성하기 어렵다면 여기를 클릭하여 준비할 수 있습니다. 이 경우 최신 버전으로 업데이트한 후 테마를 설치하면 됩니다. 또 워드프레스 설치 후 기본 상태의 환경을 맞추지 않고 이미 사용하는 사이트에서 경험해도 되지만, 특정 플러그인이 활성화된 경우 예상치 못한 결과가 나올 수 있습니다.

용어

다음처럼 글에서 표기하는 용어를 미리 정의합니다.

  • 테마 2015 : 테마 twenty fifteen
  • 테마 2016 : 테마 twenty sixteen
  • 하위테마 : Child theme
  • 상위테마 : Parent theme
  • MUP : Must Use Plugins
  • Plugins : 플러그인

(Child theme 경우 ‘자식테마’라는 표현이 주로 사용되지만, 괜히 뭔가 이상하게 어색한 표현이라는 생각을 여전히 가지고 있습니다. 하위테마도 좋은 표현은 아닙니다.)

Plugins

플러그인은 보통 워드프레스 플러그인 저장소에 있는, 사용자가 검색하여 관리페이지에서 선택하여 설치하는 공개된 설치 플러그인을 뜻하는 것이 일반적입니다. 코덱스는 워드프레스에 존재하는 기능을 추가, 확장하는 방법을 플러그인으로 정의하고 있습니다. 따라서 저장소의 플러그인과 함께 사용자가 최소한의 플러그인 구조(정의)에 맞게 생성한 파일이나 코드 자체도 플러그인입니다. 글에서는 최소한의 구조에 맞춰 기능을 정의한 플러그인을 사용합니다.

테마 2015 색상 구조 변경

안내한 기준을 준비했다면 테마 2015가 활성화되어 있고, 사이트는 회색의 배경, 검정 텍스트, 흰 본문 및 사이드 배경색으로 나올 것입니다. 로그인 상태에서 다음 순서로 색상 구조를 변경합니다.

  • 사이트 위 툴바의 ‘사용자 정의하기’ 메뉴 클릭
  • 왼쪽에 나타나는 새로운 영역의 ‘색상’ 클릭
  • 기본 색상 구조 ‘보라’ 선택
  • ‘저장 & 발행’ 버튼 클릭
  • 왼쪽 영역 닫기 (X 버튼 클릭)

사이트 색 구조가 변경된 것을 확인할 수 있는데, 브라우저의 페이지 소스 보기로 소스를 확인합니다. 대략 39번 줄에서 412번 줄에 사이트 전체의 색 관련 CSS 코드가 생성된 것을 볼 수 있습니다.

(실 사이트에서 이런 방법으로 간편하게 색상 구조를 변경할 수 있는데 나중에 꼭 경험하기를 권장합니다. 테마 2016은 더 세부적인 옵션을 제공합니다.)

<link rel='stylesheet' id='twentyfifteen-style-css'  href='http://domain.com/wp-content/themes/twentyfifteen/style.css?ver=4.5.2' type='text/css' media='all' />
<style id='twentyfifteen-style-inline-css' type='text/css'>
    /* Color Scheme */

    ..............

</style>

테마 2015에서 제공하는 색상 구조 정보는 데이터베이스 _options 테이블에 theme_mods_twentyfifteen 필드명으로 3가지 색 정보가 저장됩니다. 이 기본 3가지 색 데이터는 테마의 inc/customizer.php 파일에서 정의한 코드에 사용되고 해석하여 페이지 소스에서 볼 수 있는 CSS 코드로 변환하여 페이지 출력 시 추가합니다.

세부 과정 파악의 목적이 아니며 알 필요는 없습니다. 다만 이런 과정을 줄이면 좋겠다 생각합니다. (생각은 설명을 위한 가정이며, 이후도 마찬가지입니다) 결국 페이지 소스 보기에 나오는 CSS 코드만 확보하면 극미한 데이터베이스 사용이지만 줄일 수 있고, CSS 코드 변환 과정도 생략할 수 있을 것입니다.

이때 확보한 CSS 코드는 테마의 메인 style.css 파일보다 나중에 출력(정의)해야 메인 스타일에서 정의한 색상 구조를 대체할 수 있습니다. 위의 코드에서 첫 줄은 테마의 메인 스타일 파일이며, 그다음부터 추가 정의한 색상 구조 CSS 코드가 나타납니다. 소스 보기를 통해 확인할 수 있습니다.

확보한 CSS 코드를 메인 스타일 파일보다 나중에 출력하는 방법으로 테마 파일에 직접 추가하는 것이 제일 먼저 생각납니다. 또는 테마 메인 스타일 파일을 열어 맨 아래에 추가하는 방법도 있으며, 테마의 functions.php 파일에 훅(wp_head)으로 추가할 수도 있습니다. 하지만 테마 업데이트 후 변경 사항 유지가 어렵다는 단점이 있습니다. 핵심 전제는 다음과 같습니다.

테마 파일을 편집하지 않고 CSS 코드를 추가

플러그인과 MUP 사용은 (모든 경우는 아니지만) 이처럼 테마 파일을 직접 편집하지 않는다는 것과 특정 기능이 테마 변경(동)에 영향을 받지 않아야 한다는 기본 전제를 포함하고 있습니다.

플러그인 만들기

테마 업데이트가 문제라면 플러그인을 생각할 수 있습니다. 플러그인은 플러그인 업데이트라는 문제가 있지만, 플러그인 업데이트는 플러그인 기능의 업데이트로 지금의 CSS 코드 유지 문제를 염려하지 않아도 됩니다. CSS 코드 추가가 목적이므로 CSS와 관련한 플러그인을 검색하여 설치하고 사용할 수 있습니다. 하지만 글의 방향이 아니므로 직접 만들어 봅니다.

플러그인을 정의할 때 다른 모든 것을 제외하고, 가장 기본인 헤더 텍스트(Header Text)와 헤더 텍스트에 정의하는 필수 항목인 플러그인 이름만 정의하여 CSS 코드를 워드프레스 페이지 html 문서 </head> 태그 위에 출력되도록 플러그인을 만들어 봅니다. 다음 코드는 플러그인을 정의하는 헤더 텍스트의 기본입니다. Description 항목은 입력하지 않아도 되지만 간단한 서술을 입력하는 것이 나중에 편리합니다. 플러그인 이름은 혼자 사용한다면 한글로 적어도 됩니다. 의무는 아니나 배포의 목적이라면 영문으로.

<?php
/**
 * Plugin Name: 보라색 워드프레스
 * Description: 워드프레스에 사용하는 보라색 색상 구조
 */

소스 보기에서 확보한 CSS 코드는 긴 세로 나열이므로 편의를 위해 압축한 코드를 사용합니다. 이 글에서는 압축에 관해 염두에 두지 않아도 됩니다. 다음 코드는 압축한 CSS 코드를 추가하고, “ 태그 위에 출력되도록 wp_head 훅을 추가한 것입니다. 그리고 CSS 코드를 함수 블록에 정의합니다.

<?php
/**
 * Plugin Name: 보라색 워드프레스
 * Description: 워드프레스에 사용하는 보라색 색상 구조
 */

add_action( 'wp_head', 'default_theme_style', 77 );
function default_theme_style() {
?>
<style id='twentyfifteen-style-inline-css' type='text/css'>
body{background-color:#674970}.site-header,body:before{background-color:#2e2256}.comments-area,.hentry,.page-content,.page-header,.pagination,.post-navigation,.secondary,.site-footer,.widecolumn{background-color:#fff}.page-links a,.page-links a:focus,.page-links a:hover,.pagination .next,.pagination .prev,.sticky-post,.widget_calendar tbody a,.widget_calendar tbody a:focus,.widget_calendar tbody a:hover,button,input[type=button],input[type=reset],input[type=submit]{color:#fff}.page-links a,.pagination .next,.pagination .prev,.sticky-post,.widget_calendar tbody a,button,input[type=button],input[type=reset],input[type=submit]{background-color:#2e2256}.comment-list .reply a:focus,.comment-list .reply a:hover,.comment-metadata a:focus,.comment-metadata a:hover,.comment-navigation a:focus,.comment-navigation a:hover,.dropdown-toggle:after,.entry-footer a:focus,.entry-footer a:hover,.image-navigation a:focus,.image-navigation a:hover,.pingback .edit-link a:focus,.pingback .edit-link a:hover,.site-info a:focus,.site-info a:hover,.widget-title,a,blockquote cite,blockquote small,body{color:#2e2256}.author-description a,.comment-content a,.comment-list .reply a:hover,.comment-metadata a:hover,.entry-content a,.entry-footer a:hover,.entry-summary a,.page-content a,.pingback .comment-body>a,.pingback .edit-link a:hover,.site-info a:hover,.taxonomy-description a,.textwidget a{border-color:#2e2256}.page-links a:focus,.page-links a:hover,.pagination .next:focus,.pagination .next:hover,.pagination .prev:focus,.pagination .prev:hover,.widget_calendar tbody a:focus,.widget_calendar tbody a:hover,button:focus,button:hover,input[type=button]:focus,input[type=button]:hover,input[type=reset]:focus,input[type=reset]:hover,input[type=submit]:focus,input[type=submit]:hover{background-color:#2e2256;background-color:rgba(46,34,86,.7)}.author-heading,.comment-author,.comment-awaiting-moderation,.comment-form label,.comment-list .reply a,.comment-metadata,.comment-metadata a,.comment-navigation,.comment-navigation a,.comment-notes,.entry-caption,.entry-footer,.entry-footer a,.form-allowed-tags,.gallery-caption,.image-navigation,.image-navigation a,.logged-in-as,.main-navigation .menu-item-description,.no-comments,.page-links>.page-links-title,.pingback .edit-link,.pingback .edit-link a,.post-navigation .meta-nav,.post-navigation a:focus .post-title,.post-navigation a:hover .post-title,.post-password-form label,.site-info,.site-info a,.taxonomy-description,.widecolumn .mu_register label,.widecolumn label,.widget,.wp-caption-text,a:focus,a:hover,blockquote{color:#2e2256;color:rgba(46,34,86,.7)}.comment-author a:hover,.logged-in-as a:hover,blockquote{border-color:#2e2256;border-color:rgba(46,34,86,.7)}.dropdown-toggle:focus,.dropdown-toggle:hover,hr{background-color:#2e2256;background-color:rgba(46,34,86,.1)}.author-info,.comment-list .pingback,.comment-list .reply a,.comment-list .trackback,.comment-list article,.comment-list+.comment-respond,.comment-navigation,.comments-area,.entry-content .page-links a,.hentry+.hentry,.main-navigation li,.main-navigation ul,.no-comments,.page-header,.page-links>span,.pagination,.post-navigation,.post-navigation div+div,.site-footer,.site-header,.widget li,.widget_categories .children,.widget_nav_menu .sub-menu,.widget_pages .children,abbr[title],input,pre,table,td,textarea,th{border-color:#2e2256;border-color:rgba(46,34,86,.1)}a:focus,button:focus,input:focus{outline-color:#2e2256;outline-color:rgba(46,34,86,.3)}input:focus,textarea:focus{border-color:#2e2256;border-color:rgba(46,34,86,.3)}.secondary-toggle:before,.site-description,.site-title a{color:#fff}.site-title a:focus,.site-title a:hover{color:rgba(255,255,255,.7)}.secondary-toggle{border-color:#fff;border-color:rgba(255,255,255,.1)}.secondary-toggle:focus,.secondary-toggle:hover{border-color:#fff;border-color:rgba(255,255,255,.3)}.site-title a{outline-color:#fff;outline-color:rgba(255,255,255,.3)}.entry-footer{background-color:#f1f1f1}@media screen and (min-width:38.75em){.page-header{border-color:#2e2256}}@media screen and (min-width:59.6875em){.secondary,.site-header{background-color:transparent}.widget button,.widget input[type=button],.widget input[type=reset],.widget input[type=submit],.widget_calendar tbody a,.widget_calendar tbody a:focus,.widget_calendar tbody a:hover{color:#2e2256}.dropdown-toggle:after,.secondary a,.widget blockquote cite,.widget blockquote small,.widget-title{color:#fff}.widget button,.widget input[type=button],.widget input[type=reset],.widget input[type=submit],.widget_calendar tbody a{background-color:#fff}.textwidget a{border-color:#fff}.main-navigation .menu-item-description,.secondary a:focus,.secondary a:hover,.widget,.widget .gallery-caption,.widget .wp-caption-text,.widget blockquote{color:rgba(255,255,255,.7)}.widget button:focus,.widget button:hover,.widget input[type=button]:focus,.widget input[type=button]:hover,.widget input[type=reset]:focus,.widget input[type=reset]:hover,.widget input[type=submit]:focus,.widget input[type=submit]:hover,.widget_calendar tbody a:focus,.widget_calendar tbody a:hover{background-color:rgba(255,255,255,.7)}.widget blockquote{border-color:rgba(255,255,255,.7)}.main-navigation li,.main-navigation ul,.widget abbr[title],.widget input,.widget li,.widget pre,.widget table,.widget td,.widget textarea,.widget th,.widget_categories .children,.widget_nav_menu .sub-menu,.widget_pages .children{border-color:rgba(255,255,255,.1)}.dropdown-toggle:focus,.dropdown-toggle:hover,.widget hr{background-color:rgba(255,255,255,.1)}.widget input:focus,.widget textarea:focus{border-color:rgba(255,255,255,.3)}.dropdown-toggle:focus,.sidebar a:focus{outline-color:rgba(255,255,255,.3)}} 
</style>
<?php
}

이제는 위의 코드를 플러그인으로 사용하기 위해 파일로 만들고, 플러그인 디렉터리에 넣습니다. 다음 순서로 처리합니다.

(파일은 UTF-8 인코딩으로 생성해야 합니다. 이후에 나오는 파일도 마찬가지입니다.)

  • 사이트 위 툴바의 ‘사용자 정의하기’ 메뉴 클릭
  • 왼쪽에 나타나는 새로운 영역의 ‘색상’ 클릭
  • 기본 색상 구조 ‘기본’ 선택
  • ‘저장 & 발행’ 버튼 클릭
  • 왼쪽 영역 닫기 (X 버튼 클릭)
  • 위의 코드를 복사하여 default-theme-style.php 이름의 파일 생성
  • 워드프레스 설치 경로의 wp-content > plugins 디렉터리에 넣기 (올리기)
  • 관리페이지 플러그인 메뉴 클릭
  • 플러그인 목록에서 ‘보라색 워드프레스’ 활성화
  • 사이트에서 결과 확인
  • 소스 보기로 </head> 태그 위 CSS 코드 확인

파일 이름은 원하는 것으로 지정해도 무관하며, 파일을 새로운 디렉터리를 만들어 추가해도 됩니다.

지금까지 과정의 핵심을 요약하면, 앞에서 이야기했지만 ‘테마 파일을 편집하지 않고 원하는 CSS 코드를 특정 위치에 출력할 때 플러그인으로 정의할 수 있다는 것입니다. 플러그인을 복잡한 코드로 방대한 기능을 가진 뭔가 거창한 것으로 해석하지 않기를 바랍니다. 플러그인은 존재하는 파일(의 집합)과 함께 사용 방법의 뜻도 포함한 넓은 의미로 이해하는 것이 좋습니다. 또 워드프레스에서만 사용하는 정의가 아님을 알아야 합니다.

만약 특정 스타일을 추가로 정의하고 싶을 때, 예를 들어 사이트 제목의 크기를 변경하고 싶을 때 관련 CSS 코드를 </style> 태그 앞에 추가하면 됩니다. 또 다른 추가의 경우도 마찬가지입니다. 색상 구조 CSS 코드 추가는 예시이므로 실제 변경이 필요한 코드를 추가하면 됩니다.

Must Use Plugins

MUP, 말 그대로 이해하면 쉽습니다. 대신 ‘꼭 써야 하는’ 보다 ‘강제로 적용되는’ 또는 ‘관리페이지에서 활성, 비활성 상태 변경을 제어할 수 없는’의 뜻으로 생각하면 됩니다. (물론 MUP 제어 플러그인도 있습니다) 코덱스 안내는 시간 여유 있을 때 찾아볼 것을 권장하며, 이어지는 내용으로 먼저 이해하세요.

앞에서 테마 파일을 편집하지 않고 특정 기능을 처리하기 위해 플러그인 방식을 사용했는데, MUP 방식으로도 같은 결과를 얻을 수 있습니다. 이번에는 지금 예제로 진행하는 사이트가 테마 2015와 테마 2016을 심심할 때마다 번갈아 사용하는 사이트라고 가정합니다. 또 플러그인처럼 활성, 비활성화 과정 없이 무조건 적용되면 어떨까 하는 생각이 든다고 역시 가정합니다.

플러그인을 MUP 방식으로

플러그인과 MUP 방식은 현재 같은 결과를 얻을 수 있다고 했으므로 앞에서 만든 플러그인을 MUP 방식으로 변경해 봅니다. 간단하므로 아래 순서를 확인하세요.

  • 관리페이지 플러그인 메뉴 클릭
  • 플러그인 목록에서 ‘보라색 워드프레스’ 비활성화
  • 사이트에서 기본 색상 구조로 출력되는지 확인
  • 소스 보기로 </head> 태그 위 CSS 코드가 나오지 않는지 확인
  • wp-content 디렉터리에 mu-plugins 디렉터리 만들기
  • wp-content > plugins 디렉터리의 default-theme-style.php 파일을 mu-plugins 디렉터리로 이동
  • 사이트에서 결과 확인
  • 소스 보기로 </head> 태그 위 CSS 코드가 나오는지 확인
  • 관리페이지에서 테마를 2016으로 변경해두기
  • 관리페이지 플러그인 메뉴 클릭

사이트 결과는 보라색 색상 구조를 변함이 없이 출력할 것이며, 관리페이지 플러그인 목록에는 ‘보라색 워드프레스’ 플러그인이 나타나지 않을 것입니다. 대신 ‘Must-Use’ 탭 메뉴가 생긴 것을 볼 수 있는데 클릭하면 플러그인 ‘보라색 워드프레스’가 나타날 것입니다.

Must Use Plugins
‘보라색 워드프레스’ Must Use Plugins

이전의 플러그인처럼 활성화 과정이 필요가 없고, 헤더 텍스트를 추가하지 않아도 기능이 적용되며, 플러그인 이름이 없으면 목록에서 파일명이 플러그인 이름에 나타납니다.

테마 2016 색상 CSS 코드 추가

바로 앞의 과정에서 테마 2016으로 변경했습니다. 아직 변경하지 않았다면 변경하세요. 그리고 사이트를 보면 일부 배경색이 보라색 계열로 나타나는 것을 확인할 수 있을 것입니다. MUP에 정의한 CSS 클래스 등이 2015 테마와 같아 나오는 현상입니다. 테마 2016의 색상 구조 변경을 위한 CSS 코드 확보는 2015 테마와 같은 방식으로 진행하면 되는데, 구분을 위해 ‘어두움’으로 정하여 확보한 CSS 코드를 MUP(default-theme-style.php 파일)에 추가하고, 사용 중인(활성화한) 테마를 확인하여 해당 CSS 코드가 자동으로 적용되도록 정의합니다. 번거로울 수 있어 완성한 코드를 아래 나열합니다.

<?php
/**
 * Plugin Name: 보라색과 어두움의 워드프레스
 * Description: 워드프레스 기본 2015, 2016 테마의 색상 구조 CSS 코드
 */

add_action( 'wp_head', 'default_theme_style', 77 );
function default_theme_style() {
    $current_theme = wp_get_theme();
    if ( 'twentyfifteen' == $current_theme->get( 'TextDomain' ) ) {
?>
<style id='twentyfifteen-style-inline-css' type='text/css'>
body{background-color:#674970}.site-header,body:before{background-color:#2e2256}.comments-area,.hentry,.page-content,.page-header,.pagination,.post-navigation,.secondary,.site-footer,.widecolumn{background-color:#fff}.page-links a,.page-links a:focus,.page-links a:hover,.pagination .next,.pagination .prev,.sticky-post,.widget_calendar tbody a,.widget_calendar tbody a:focus,.widget_calendar tbody a:hover,button,input[type=button],input[type=reset],input[type=submit]{color:#fff}.page-links a,.pagination .next,.pagination .prev,.sticky-post,.widget_calendar tbody a,button,input[type=button],input[type=reset],input[type=submit]{background-color:#2e2256}.comment-list .reply a:focus,.comment-list .reply a:hover,.comment-metadata a:focus,.comment-metadata a:hover,.comment-navigation a:focus,.comment-navigation a:hover,.dropdown-toggle:after,.entry-footer a:focus,.entry-footer a:hover,.image-navigation a:focus,.image-navigation a:hover,.pingback .edit-link a:focus,.pingback .edit-link a:hover,.site-info a:focus,.site-info a:hover,.widget-title,a,blockquote cite,blockquote small,body{color:#2e2256}.author-description a,.comment-content a,.comment-list .reply a:hover,.comment-metadata a:hover,.entry-content a,.entry-footer a:hover,.entry-summary a,.page-content a,.pingback .comment-body>a,.pingback .edit-link a:hover,.site-info a:hover,.taxonomy-description a,.textwidget a{border-color:#2e2256}.page-links a:focus,.page-links a:hover,.pagination .next:focus,.pagination .next:hover,.pagination .prev:focus,.pagination .prev:hover,.widget_calendar tbody a:focus,.widget_calendar tbody a:hover,button:focus,button:hover,input[type=button]:focus,input[type=button]:hover,input[type=reset]:focus,input[type=reset]:hover,input[type=submit]:focus,input[type=submit]:hover{background-color:#2e2256;background-color:rgba(46,34,86,.7)}.author-heading,.comment-author,.comment-awaiting-moderation,.comment-form label,.comment-list .reply a,.comment-metadata,.comment-metadata a,.comment-navigation,.comment-navigation a,.comment-notes,.entry-caption,.entry-footer,.entry-footer a,.form-allowed-tags,.gallery-caption,.image-navigation,.image-navigation a,.logged-in-as,.main-navigation .menu-item-description,.no-comments,.page-links>.page-links-title,.pingback .edit-link,.pingback .edit-link a,.post-navigation .meta-nav,.post-navigation a:focus .post-title,.post-navigation a:hover .post-title,.post-password-form label,.site-info,.site-info a,.taxonomy-description,.widecolumn .mu_register label,.widecolumn label,.widget,.wp-caption-text,a:focus,a:hover,blockquote{color:#2e2256;color:rgba(46,34,86,.7)}.comment-author a:hover,.logged-in-as a:hover,blockquote{border-color:#2e2256;border-color:rgba(46,34,86,.7)}.dropdown-toggle:focus,.dropdown-toggle:hover,hr{background-color:#2e2256;background-color:rgba(46,34,86,.1)}.author-info,.comment-list .pingback,.comment-list .reply a,.comment-list .trackback,.comment-list article,.comment-list+.comment-respond,.comment-navigation,.comments-area,.entry-content .page-links a,.hentry+.hentry,.main-navigation li,.main-navigation ul,.no-comments,.page-header,.page-links>span,.pagination,.post-navigation,.post-navigation div+div,.site-footer,.site-header,.widget li,.widget_categories .children,.widget_nav_menu .sub-menu,.widget_pages .children,abbr[title],input,pre,table,td,textarea,th{border-color:#2e2256;border-color:rgba(46,34,86,.1)}a:focus,button:focus,input:focus{outline-color:#2e2256;outline-color:rgba(46,34,86,.3)}input:focus,textarea:focus{border-color:#2e2256;border-color:rgba(46,34,86,.3)}.secondary-toggle:before,.site-description,.site-title a{color:#fff}.site-title a:focus,.site-title a:hover{color:rgba(255,255,255,.7)}.secondary-toggle{border-color:#fff;border-color:rgba(255,255,255,.1)}.secondary-toggle:focus,.secondary-toggle:hover{border-color:#fff;border-color:rgba(255,255,255,.3)}.site-title a{outline-color:#fff;outline-color:rgba(255,255,255,.3)}.entry-footer{background-color:#f1f1f1}@media screen and (min-width:38.75em){.page-header{border-color:#2e2256}}@media screen and (min-width:59.6875em){.secondary,.site-header{background-color:transparent}.widget button,.widget input[type=button],.widget input[type=reset],.widget input[type=submit],.widget_calendar tbody a,.widget_calendar tbody a:focus,.widget_calendar tbody a:hover{color:#2e2256}.dropdown-toggle:after,.secondary a,.widget blockquote cite,.widget blockquote small,.widget-title{color:#fff}.widget button,.widget input[type=button],.widget input[type=reset],.widget input[type=submit],.widget_calendar tbody a{background-color:#fff}.textwidget a{border-color:#fff}.main-navigation .menu-item-description,.secondary a:focus,.secondary a:hover,.widget,.widget .gallery-caption,.widget .wp-caption-text,.widget blockquote{color:rgba(255,255,255,.7)}.widget button:focus,.widget button:hover,.widget input[type=button]:focus,.widget input[type=button]:hover,.widget input[type=reset]:focus,.widget input[type=reset]:hover,.widget input[type=submit]:focus,.widget input[type=submit]:hover,.widget_calendar tbody a:focus,.widget_calendar tbody a:hover{background-color:rgba(255,255,255,.7)}.widget blockquote{border-color:rgba(255,255,255,.7)}.main-navigation li,.main-navigation ul,.widget abbr[title],.widget input,.widget li,.widget pre,.widget table,.widget td,.widget textarea,.widget th,.widget_categories .children,.widget_nav_menu .sub-menu,.widget_pages .children{border-color:rgba(255,255,255,.1)}.dropdown-toggle:focus,.dropdown-toggle:hover,.widget hr{background-color:rgba(255,255,255,.1)}.widget input:focus,.widget textarea:focus{border-color:rgba(255,255,255,.3)}.dropdown-toggle:focus,.sidebar a:focus{outline-color:rgba(255,255,255,.3)}} 
</style>
<?php
    }
    if ( 'twentysixteen' == $current_theme->get( 'TextDomain' ) ) {
?>
<style id='twentysixteen-style-inline-css' type='text/css'>
body{background-color:#262626}.site{background-color:#1a1a1a}.menu-toggle.toggled-on,.menu-toggle.toggled-on:focus,.menu-toggle.toggled-on:hover,.page-links a,.page-links a:focus,.page-links a:hover,.pagination .nav-links:after,.pagination .nav-links:before,.pagination .next,.pagination .next:focus,.pagination .next:hover,.pagination .prev,.pagination .prev:focus,.pagination .prev:hover,.widget_calendar tbody a,.widget_calendar tbody a:focus,.widget_calendar tbody a:hover,button,button[disabled]:focus,button[disabled]:hover,input[type=button],input[type=button][disabled]:focus,input[type=button][disabled]:hover,input[type=reset],input[type=reset][disabled]:focus,input[type=reset][disabled]:hover,input[type=submit],input[type=submit][disabled]:focus,input[type=submit][disabled]:hover,ins,mark{color:#1a1a1a}.comment-metadata a:focus,.comment-metadata a:hover,.comment-reply-link,.comment-reply-link:focus,.comment-reply-link:hover,.dropdown-toggle:focus,.dropdown-toggle:hover,.entry-footer a:focus,.entry-footer a:hover,.entry-title a:focus,.entry-title a:hover,.main-navigation a:focus,.main-navigation a:hover,.menu-toggle:focus,.menu-toggle:hover,.pingback .comment-edit-link:focus,.pingback .comment-edit-link:hover,.post-navigation a:focus .post-title,.post-navigation a:hover .post-title,.required,.site-branding .site-title a:focus,.site-branding .site-title a:hover,.site-info a:focus,.site-info a:hover,.social-navigation a:focus:before,.social-navigation a:hover:before,.tagcloud a:focus,.tagcloud a:hover,a{color:#9adffd}.page-links a:focus,.page-links a:hover,.pagination .next:focus,.pagination .next:hover,.pagination .prev:focus,.pagination .prev:hover,.widget_calendar tbody a,button:focus,button:hover,input[type=button]:focus,input[type=button]:hover,input[type=reset]:focus,input[type=reset]:hover,input[type=submit]:focus,input[type=submit]:hover,ins,mark{background-color:#9adffd}.menu-toggle:focus,.menu-toggle:hover,.tagcloud a:focus,.tagcloud a:hover,input[type=text]:focus,input[type=email]:focus,input[type=url]:focus,input[type=password]:focus,input[type=search]:focus,textarea:focus{border-color:#9adffd}.comment-author,.comment-reply-title small a:focus,.comment-reply-title small a:hover,.dropdown-toggle,.entry-title a,.main-navigation a,.menu-toggle,.page-links>.page-links-title,.pagination a:focus,.pagination a:hover,.post-navigation a,.site-branding .site-title a,.social-navigation a,.widget-title a,blockquote cite,blockquote small,body{color:#e5e5e5}.comment-reply-title,.comments-title,.menu-toggle.toggled-on,.menu-toggle.toggled-on:focus,.menu-toggle.toggled-on:hover,.page-header,.page-links a,.pagination,.post-navigation,.post-navigation div+div,.widget,blockquote{border-color:#e5e5e5}.menu-toggle.toggled-on,.menu-toggle.toggled-on:focus,.menu-toggle.toggled-on:hover,.page-links a,.pagination .next,.pagination .prev,.pagination:after,.pagination:before,button,button[disabled]:focus,button[disabled]:hover,input[type=button],input[type=button][disabled]:focus,input[type=button][disabled]:hover,input[type=reset],input[type=reset][disabled]:focus,input[type=reset][disabled]:hover,input[type=submit],input[type=submit][disabled]:focus,input[type=submit][disabled]:hover{background-color:#e5e5e5}.author-bio,.comment-awaiting-moderation,.comment-form label,.comment-metadata,.comment-metadata a,.comment-navigation,.comment-notes,.entry-caption,.entry-footer,.entry-footer a,.form-allowed-tags,.gallery-caption,.image-navigation,.logged-in-as,.pingback .comment-edit-link,.pingback .edit-link,.post-navigation .meta-nav,.post-password-form label,.site-description,.site-info,.site-info a,.sticky-post,.taxonomy-description,.widecolumn .mu_register label,.widecolumn label,.widget_recent_entries .post-date,.widget_rss .rss-date,.widget_rss cite,.wp-caption .wp-caption-text,a:active,a:focus,a:hover,blockquote,body:not(.search-results) .entry-summary{color:#c1c1c1}.widget_calendar tbody a:focus,.widget_calendar tbody a:hover{background-color:#c1c1c1}.comment-list .pingback,.comment-list .trackback,.comment-list article,.comment-navigation,.comment-reply-link,.dropdown-toggle:after,.entry-content,.entry-summary,.image-navigation,.main-navigation .primary-menu,.main-navigation li,.menu-toggle,.no-comments,.page-links a,.page-links>span,.social-navigation a,.tagcloud a,.widecolumn .mu_register .mu_alert,abbr,acronym,fieldset,input[type=text],input[type=email],input[type=url],input[type=password],input[type=search],pre,table,td,textarea,th{border-color:#e5e5e5;border-color:rgba(229,229,229,.2)}code,hr{background-color:#e5e5e5;background-color:rgba(229,229,229,.2)}@media screen and (min-width:56.875em){.main-navigation li.focus>a,.main-navigation li:hover>a{color:#9adffd}.main-navigation ul ul,.main-navigation ul ul li{border-color:rgba(229,229,229,.2)}.main-navigation ul ul:before{border-top-color:rgba(229,229,229,.2);border-bottom-color:rgba(229,229,229,.2)}.main-navigation ul ul li{background-color:#1a1a1a}.main-navigation ul ul:after{border-top-color:#1a1a1a;border-bottom-color:#1a1a1a}}
</style>
<?php
    }
}

다음 순서를 확인하세요.

  • 위의 코드 전체를 복사하여 default-theme-style.php 파일 만들기
  • 현재 mu-plugins 디렉터리에 존재하는 파일과 대체
  • 사이트에서 결과 확인 (어두움 색상 구조)
  • 관리페이지에서 2015 테마로 변경
  • 사이트에서 결과 확인 (보라색 색상 구조)

테마 변경에 따라 보라색과 어두움의 색상 구조로 사이트가 변경되는 것을 확인할 수 있습니다. MUP로 테마에 따라 자동으로 지정한 CSS 코드가 적용되도록 처리한 것 역시 플러그인으로 만들어도 같은 결과라는 것을 이제는 짐작했을 것입니다.

CSS 코드 예시는 MUP 사용 필요성을 명확하게 이해하는 데 부족할 수 있지만, 글에서 소개한 MUP 사용 방법 하나와 간략한 특징을 얻는 것이면 충분합니다. 나머지 모든 경우는 필요할 때 연관 정보를 더 찾아 직접 검토하는 것이 좋습니다. 그래도 MUP 방법을 알았으니 워드프레스 기본 기능과 테마의 기능을 변경하거나 추가하는 몇 가지 간단한 팁을 적용해 봅니다. 코드를 이해할 필요는 없으며, 이 역시 테마 파일을 직접 편집하지 않는다는 전제가 있음을 잊지 마세요.

워드프레스 기본 기능 편집

웹에서 워드프레스 보안 관련 정보를 찾다 보면 페이지 소스에 출력되는 몇 가지 정보를 제거하는 것이 좋다는 내용이 있습니다. 정말 좋은지는 알 수 없습니다. 취약점 대비를 잘했다는 유명 사이트는 적용하지 않은 것도 볼 수 있으니까요. 어쨌든 다음 코드는 워드프레스 페이지 소스에 기본으로 출력되는 몇 가지를 제거하는 것입니다.

add_action('init', 'default_some_head_cleanup');
function default_some_head_cleanup() {
    remove_action( 'wp_head', 'rsd_link' );
    remove_action( 'wp_head', 'wlwmanifest_link' );
    remove_action( 'wp_head', 'wp_generator' );
    remove_action( 'wp_head', 'wp_shortlink_wp_head' );
}

‘이모티콘’과 비슷한 ‘Emoji’는 유니코드 체계의 그림 문자 정도로 해석할 수 있는데 현재는 대중화라는 말이 무색할 정도로 일상이 된 것입니다. 워드프레스도 기본으로 제공하는 기능입니다. 그런데 글쓴이는 잘 사용하지 않습니다.

add_action( 'init', 'disable_emojis' );
function disable_emojis() {
    remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
    remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
    remove_action( 'wp_print_styles', 'print_emoji_styles' );
    remove_action( 'admin_print_styles', 'print_emoji_styles' );
    remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
    remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
    remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
    add_filter( 'tiny_mce_plugins', 'disable_emojis_tinymce' );
}

function disable_emojis_tinymce( $plugins ) {
    if ( is_array( $plugins ) ) {
        return array_diff( $plugins, array( 'wpemoji' ) );
    } else {
        return array();
    }
}

역시 일반화된 내용으로 볼 수 있는 구글의 통계 스크립트(추적 코드) 추가입니다. 아래 코드는 페이지 </body> 태그 위에 통계 스크립트를 삽입하는데, UA-XXXXXXX-1 추적 ID는 자신의 것으로 대체하면 됩니다. 나중에 실제 사용한다면.

add_action( 'wp_footer', 'my_footer_script' );
function my_footer_script() {
?>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXXXX-1', 'auto');
ga('send', 'pageview');
</script>
<?php
}

아래는 지난 에 나온 워드프레스 메일 발신 관련 코드로 Gmail SMTP를 사용할 경우입니다.

add_action( 'phpmailer_init', 'my_phpmailer' );
function my_phpmailer( $phpmailer ) {
    $phpmailer->isSMTP();
    $phpmailer->Host = 'smtp.gmail.com';
    $phpmailer->SMTPAuth = true;
    $phpmailer->Port = 587;
    $phpmailer->Username = 'your_account@gmail.com';
    $phpmailer->Password = 'password';
    $phpmailer->SMTPSecure = "tls";
    $phpmailer->From = "your_account@gmail.com";
    $phpmailer->FromName = get_option( 'blogname' );
}

소개한 4가지 코드 스니핏은 모두 테마와 관계가 없고, 테마 변경과도 관련이 없어야 하며, 테마 파일을 편집하지 않는 전제가 있으므로 MUP 방식의 사용이 적절하다 생각합니다. 플러그인으로 만들어 사용해도 됩니다.

테마의 기능 제거, 편집

다음 그림은 테마 2015에서 정의한 twentyfifteen_nav_description 함수에 의해 사이트에 출력되는 메뉴 아이템 하나의 설명입니다. 메뉴 설명은 관리페이지 메뉴 설정에서 (기본으로 나오지 않으므로) ‘화면 옵션’을 펼쳐 ‘설명’ 항목을 선택해야 입력할 수 있습니다.

테마 2015 ‘twentyfifteen_nav_description’ 함수에 의한 결과
테마 2015 ‘twentyfifteen_nav_description’ 함수에 의한 결과

아래 코드를 사용하면 테마 2015의 twentyfifteen_nav_description 함수를 사용하지 않는 것과 같습니다.

add_action( 'init', 'disable_2015_nav_desc_function' );
function disable_2015_nav_desc_function() {
    remove_filter( 'walker_nav_menu_start_el', 'twentyfifteen_nav_description' );
}

다음 그림은 테마 2015에서 포스트 작성 시 ‘특성 이미지’를 추가할 경우 나타나는 사이트 화면입니다.

테마 2015 포스트 작성 시 특성 이미지를 추가한 경우
테마 2015 포스트 작성 시 특성 이미지를 추가한 경우

아래 코드를 사용하면 테마 2015의 twentyfifteen_post_thumbnail 함수를 사용하지 않는 것과 같아 특성 이미지를 추가해도 사이트에 나타나지 않습니다. 이미지가 출력되지 않아 간격이 어색할 수 있습니다. 스타일 추가로 간단하게 조절할 수 있지만 생략합니다.

(특성 이미지는 사이트에 출력하지 않더라도 페이지의 메타 정보에 등록할 여지를 남겨두기 위해 등록할 필요는 있습니다.)

if ( ! function_exists( 'twentyfifteen_post_thumbnail' ) ) {
  function twentyfifteen_post_thumbnail() {
    // 
  }
}

다음은 위에서 안내한 6가지 코드를 MUP로 사용하기 위해 합친 것입니다.

<?php
/**
 * Plugin Name: Default Functions
 * Description: 워드프레스 기본 기능과 테마 2015 일부 기능 편집
 */

/* 사이트 소스 <head> 태그 블록 요소 제거 */
add_action('init', 'default_some_head_cleanup');
function default_some_head_cleanup() {
    remove_action( 'wp_head', 'rsd_link' );
    remove_action( 'wp_head', 'wlwmanifest_link' );
    remove_action( 'wp_head', 'wp_generator' );
    remove_action( 'wp_head', 'wp_shortlink_wp_head' );
}

/* Emoji 비활성 */
add_action( 'init', 'disable_emojis' );
function disable_emojis() {
    remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
    remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
    remove_action( 'wp_print_styles', 'print_emoji_styles' );
    remove_action( 'admin_print_styles', 'print_emoji_styles' );
    remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
    remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
    remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
    add_filter( 'tiny_mce_plugins', 'disable_emojis_tinymce' );
}

function disable_emojis_tinymce( $plugins ) {
    if ( is_array( $plugins ) ) {
        return array_diff( $plugins, array( 'wpemoji' ) );
    } else {
        return array();
    }
}

/* 구글 통계 스크립트(추적 코드) */
add_action( 'wp_footer', 'my_footer_script' );
function my_footer_script() {
?>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXXXX-1', 'auto');
ga('send', 'pageview');
</script>
<?php
}

/* Gmail SMTP */
add_action( 'phpmailer_init', 'my_phpmailer' );
function my_phpmailer( $phpmailer ) {
    $phpmailer->isSMTP();
    $phpmailer->Host = 'smtp.gmail.com';
    $phpmailer->SMTPAuth = true;
    $phpmailer->Port = 587;
    $phpmailer->Username = 'your_account@gmail.com';
    $phpmailer->Password = 'password';
    $phpmailer->SMTPSecure = "tls";
    $phpmailer->From = "your_account@gmail.com";
    $phpmailer->FromName = get_option( 'blogname' );
}

/* 테마 2015 몇 가지 기능 제거 */
add_action( 'init', 'disable_2015_nav_desc_function' );
function disable_2015_nav_desc_function() {
    remove_filter( 'walker_nav_menu_start_el', 'twentyfifteen_nav_description' );
}

if ( ! function_exists( 'twentyfifteen_post_thumbnail' ) ) {
  function twentyfifteen_post_thumbnail() {
    // 
  }
}

혹시 계속 따라 했다면 사이트는 2015 테마 활성화 상태일 것입니다. 다음 순서를 확인합니다.

  • 직전의 그림 2개를 보고 메뉴와 메뉴 설명, 포스트 섬네일이 나타나도록 관리페이지에서 처리하기 (메뉴 이름, 설명, 이미지는 같지 않아도 됩니다)
  • 사이트에서 결과 확인
  • 사이트 소스 보기 후 wpemoji, generator 단어 검색 후 확인
  • 바로 위의 합친 코드를 복사하여 default-mup.php 파일로 생성
  • 워드프레스 설치 경로의 wp-content > mu-plugins 디렉터리에 넣기 (올리기)
  • 사이트에서 메뉴 설명, 섬네일 출력 여부 확인
  • 사이트 소스 보기 후 wpemoji, generator 단어를 검색하여 출력 여부 확인
  • GoogleAnalyticsObject 단어 검색으로 통계 스크립트 추가 확인

MUP는 워드프레스 멀티사이트에서 사용하면 개별 사이트 전체에 적용됩니다. 개별 사이트 운영자가 특정 플러그인을 제어할 수 없어야 할 때 최고 관리자가 플러그인을 네트워크 활성화(Network Activate)하는 것과 같은 목적으로 보면 됩니다. 커스텀 포스트 타입 정의처럼 다른 로드 요소보다 먼저 로드되는 것이 적절할 때 사용하는 것이 좋다는 코덱스의 의견도 있습니다. 그렇다고 반드시 따를 필요는 없고 판단과 상황에 따라 결정하면 됩니다.

직전에 살펴본 6가지 코드 스니핏 중에 메뉴 아이템 설명, 포스트 섬네일의 테마 기능 제어 2가지는 해당 테마를 사용하지 않는다면 불필요합니다. 해당 테마를 사용하지 않는데 코드가 존재해도 심각한 오류가 발생하는 것은 아니지만, 없어도 되는 코드임은 확실합니다. 나머지 4가지는 테마와 관련이 없는 것이므로 MUP 또는 플러그인 방식으로 유지하는 것은 문제가 없습니다.

다시 2가지 테마 기능 제어는 (계속 반복하는 것으로) 테마 파일을 직접 편집하지 않는다는 전제로 시작한 것이지만, 실제 앞의 과정처럼 테마 파일을 직접 편집할 필요가 없는 특징이 있습니다.

Child theme

하위테마는 상위테마가 존재할 때 성립합니다. 상위테마가 없다면 하위테마는 정의할 수 없고, 하위테마가 없다는 것은 그냥 하나의 테마를 사용한다는 뜻과 같습니다. 하위테마에 대한 긴 이해는 중요하지 않습니다. 규칙에 맞춰 만들어 사용하면 그만입니다.

코덱스에서 안내하는 하위테마 사용 필요성을 그대로 가져오면 다음과 같습니다.

  • If you modify a theme directly and it is updated, then your modifications may be lost. By using a child theme you will ensure that your modifications are preserved.
  • Using a child theme can speed up development time.
  • Using a child theme is a great way to learn about WordPress theme development.

하위테마 방식을 사용하지 않고 테마나 플러그인을 수정하면 업데이트 후 수정 사항 유지가 어렵고, 개발 시간을 단축할 수 있으며, 워드프레스를 배우는 가장 훌륭한 방법이라는 내용입니다. 마지막 항목을 ‘테마 개발을 위한’ 것으로 좁게 해석할 필요는 없습니다.

하위테마가 정말 필요한 경우

하위테마를 생성하여 사용하세요.

위는 워드프레스 입문자에게 조금 먼저 경험한 사용자가 늘 하는 말인데, (입문자를 상대적으로 배경지식이 적은 하나의 그룹으로 가정할 때) 사실 입문자 입장 또는 상황에서 하위테마를 사용할, 사용해야 하는 경우는 거의 없습니다.

글에서 지금까지 안내한 코드 스니핏 추가를 통한 일부 요소의 제어는 글의 과정처럼 하위테마를 사용하지 않아도 가능했으며, 입문자 그룹에 속한 사용자의 비슷한 점은 내 사이트의 스타일 변경특정 기능 추가입니다. 이 두 가지는 글에서 예시로 든 것과 일치합니다.

입문자가 하위테마를 꼭 사용해야 하는 경우는 테마의 템플릿 파일을 변경해야 할 때 또는 템플릿 파일을 추가할 때로 볼 수 있습니다. (꼭 템플릿 파일 추가나 변경의 경우만이 아닌 예는 당연히 있지만 생략) 이것은 입문자만이 아니라 어떤 사용자도 마찬가지입니다. ‘테마의 템플릿 파일’은 테마에서 .txt, .js, .css 등의 확장자 파일과 functions.php 등의 워드프레스 테마 템플릿 계층(Template Hierarchy)과 관계가 없는 파일을 제외한 모든 파일을 말합니다.

(테마의 템플릿 파일을 변경해야 할 때도 플러그인, MUP 방식을 사용하여 처리할 수 있습니다. 그렇게 프로그래밍할 수 있다면. 하지만, 역효과나 비효율적 방식으로 생각합니다.)

테마의 템플릿 파일을 변경한다는 것은 쉬운 예로, 테마 2015의 single.php 파일 소스의 html 마크업을 완전히 변경하는 경우로 생각할 수 있습니다. 테마의 템플릿 파일을 추가하는 경우는 2015 테마를 예로 author.php 파일을 추가하여 archive.php 파일을 통하지 않고 글쓴이 페이지를 새롭게 구성하고 싶을 때로 볼 수 있습니다. 또 book이라는 커스텀 포스트 타입을 생성했을 때 single.php 파일에서 표현하는 book 타입의 싱글 콘텐츠를 single-book.php 파일을 사용하여 새롭게 구성하고 싶을 때입니다. 다른 많은 경우가 있습니다.

하위테마 만들기

하위테마를 구성하는 것도 플러그인이나 MUP와 비슷합니다. 헤더 텍스트에 필수 항목을 정의하는 것을 시작으로 간단하게 처리할 수 있습니다. 코덱스의 하위테마 안내는 주기가 아주 길지만 업데이트되므로 하위테마가 필요할 때 먼저 확인하는 것이 좋습니다. 기준은 언제나 (영문) 코덱스로 정하세요.

이전에는 하위테마에 style.css 파일 하나만 필수 파일이었지만, 지금은 functions.php 파일이 추가되었습니다. 추가되었다는 것은 style.css 파일처럼 없어서 안 된다는 것이 아니라 상위테마의 style.css 파일을 포함하는 방식을 하위테마의 style.css 파일 소스에서 처리(@import)하지 않고, 하위테마의 functions.php 파일에 워드프레스 스크립트 추가 방식(wp_enqueue_style, wp_enqueue_scripts)으로 변경(개선)되었다는 뜻입니다. 강제는 아니며 권장사항이지만 다른 생각할 필요가 없이 그대로 따르면 됩니다.

글의 예제 과정을 계속 따라 했다면 2015 테마가 활성화 상태이므로 2015 테마의 하위테마를 생성합니다. 그리고 앞에서 진행한 MUP 파일이 사용 중이라는 점을 기억하며, 다음 순서를 확인합니다.

  • 사이트를 잠깐 확인
  • PC에서 twentyfifteen-child 이름의 디렉터리 생성
  • style.css 파일을 twentyfifteen-child 디렉터리에 생성
  • functions.php 파일을 twentyfifteen-child 디렉터리에 생성

디렉터리 이름은 원하는 것으로 정해도 되며, 먼저 생성한 style.css 파일을 열어 아래 헤더 텍스트를 추가합니다.

/*
 Theme Name: Twenty Fifteen Child
 Template: twentyfifteen
 Version: 1.5
 Text Domain: twenty-fifteen-child
*/

Theme Name은 원하는 것으로 사용해도 되지만 어떤 상위테마의 하위테마인지 쉽게 알 수 있도록 정하는 것이 좋고, Text Domain은 필수 항목은 아니지만, 정의하면 특정 기능 추가만을 위해서가 아니라 지난 과정에서 테마에 따라 다른 CSS 코드를 적용할 때 사용한 것처럼 조건으로 사용할 수 있으므로 입력하는 것을 기본으로 생각하세요. Template는 상위테마의 이름(Text Domain)을 입력해야 합니다. 이름은 상위테마의 style.css 파일을 열어 Text Domain 항목에 있는 것을 하위테마의 Template에 입력해야 합니다. 또 Version 정보를 추가하는 것이 좋은데 상위테마의 버전 정보를 그대로 가져와서 입력하면 됩니다. 상위테마 업데이트 후 변경사항을 비교하는 데 도움이 될 수 있습니다. 따라서 하위테마를 만들 때는 상위테마의 style.css 파일을 열어서 참고하는 것이 좋습니다. 다른 나머지 항목은 선택사항입니다.

하위테마를 사용자가 직접 구성했다면 상위테마 업데이트 후 하위테마 업데이트를 고려할 필요가 있습니다. 대표적인 경우는 상위테마의 보안 업데이트입니다. 이때 style.css 파일의 버전 정보가 도움됩니다. 상위테마 템플릿 파일 변경이나 하위테마에 새롭게 추가할 때도 상위테마의 소스(테마 템플릿 파일에 대부분 존재하는 파일 헤더 텍스트 포함)를 그대로 복사한 후 원하는 방향으로 부분 수정하는 것이 좋습니다. 이와 같은 방법으로 하위테마를 구성한다면 Child Theme Check 플러그인과 같은 관련 플러그인의 도움을 얻을 때 유리합니다. 글에서는 이 정도의 내용으로 정리합니다. 아래 순서를 확인하세요.

  • 워드프레스 설치 경로에서 wp-content > themes 디렉터리에 style.css 파일을 포함한 twentyfifteen-child 디렉터리를 올리기
  • 관리페이지에서 Twenty Fifteen Child 하위테마 활성화
  • 사이트 확인

사이트를 보면 스타일이 적용되지 않은 페이지를 볼 수 있습니다. 당연한 결과입니다. 하위테마의 style.css 파일 헤더 텍스트(Template)에 2015 테마의 하위테마라고 선언했지만, 그 선언으로 상위테마의 스타일(style.css 파일)을 자동으로 가져오지는 않습니다.

꼭 상위테마의 스타일을 가져올 필요는 없습니다. 원한다면 하위테마의 style.css 파일에 처음부터 하나씩 원하는 CSS 코드로 스타일을 정의하면 됩니다. 그러나 그런 방법을 사용한다면 하위테마를 만들 필요가 없습니다. 테마를 직접 개발하거나 2015 테마에서 Text Domain twentyfifteen 등의 유사 키워드만 다른 것으로 일괄 변경하여 새로운 테마로 사용하는 것이 더 유리합니다. 따라서 하위테마를 만들 때 상위테마의 스타일을 기본으로 포함하는 것을 기준으로 정하세요. 앞에서 잠깐 말했지만 @import 방식을 지양하고 워드프레스 스크립트 추가 방식을 사용하기 위해 아래 코드를 기본으로 추가한 하위테마의 functions.php을 만듭니다.

<?php
add_action( 'wp_enqueue_scripts', 'child_theme_enqueue_styles' );
function child_theme_enqueue_styles() {
    wp_enqueue_style( 'twenty-fifteen-style', get_template_directory_uri() . '/style.css' );
}

다음 순서를 확인하세요.

  • `twentyfifteen-child` 디렉터리의 `functions.php`을 열어 위 코드 추가
  • 워드프레스 설치 경로에서 wp-content > themes > twentyfifteen-child 디렉터리에 `functions.php` 파일 올리기
  • 사이트 확인
  • 사이트 소스 보기를 통해 상위테마의 `style.css` 파일이 하위테마의 `style.css` 파일 위에 위치하는지 확인

여기까지 진행한 하위테마 생성과 활성화의 기본은 다음과 같습니다.

  • 원하는 이름의 디렉터리 만들기
  • 만든 디렉터리에 최소 기준의 헤더 텍스트를 포함한 `style.css` 파일 만들기
  • 만든 디렉터리에 상위테마의 `style.css` 파일을 포함하는 코드를 추가한 `functions.php` 파일 만들기
  • wp-content > themes 디렉터리에 `style.css`, `functions.php` 파일을 포함한 디렉터리 올리기
  • 하위테마 활성화

사이트를 보면 아래 그림처럼 흰 배경의 페이지로 나타나는데 글의 과정에서 정상 결과입니다.

하위테마 활성화 후
하위테마 활성화 후

앞에서 테마별 색상 구조를 추가한 CSS 코드가 있는 MUP에 다음의 조건이 있습니다. 모두 생략하고 필요한 부분만 나열합니다.

if ( 'twentyfifteen' == $current_theme->get( 'TextDomain' ) ) {
if ( 'twentysixteen' == $current_theme->get( 'TextDomain' ) ) {

twentyfifteen, twentysixteen Text Domain 외에는 정의한 것이 없으므로 색상 구조가 적용되지 않는 것은 당연한 결과이며, 현재 테마 2015 하위테마를 활성화한 상태이며, 이 하위테마의 Text Domain은 twenty-fifteen-child입니다. 위 코드의 첫 번째만 아래처럼 변경하면 색상이 적용된 사이트를 볼 수 있습니다.

//
if ( 'twentyfifteen' || 'twenty-fifteen-child' == $current_theme->get( 'TextDomain' ) ) {

이 과정은 하지 않아도 됩니다.

functions.php

‘사용하는 테마의 functions.php 파일에 추가하세요.’는 지금처럼 하위테마를 사용(활성화)하고 있을 때 ‘하위테마의 functions.php 파일에 추가하세요.’의 뜻으로 해석하면 됩니다. 하위테마를 사용하지 않는다면 앞에서 나온 플러그인 또는 MUP 방식을 생각하세요.

functions.php 파일은 파일 이름이 시스템적이며, 시스템적의 뜻은 워드프레스가 자동으로 인식한다는 뜻입니다. 따라서 파일 이름이 정확해야 하며, 상위든 하위든 테마의 style.css 파일도 마찬가지입니다. 그 외에 워드프레스 테마 템플릿 계층 구조 규칙에 의한 파일 이름 모두 같은 특성을 가지고 있습니다.

하위테마와 MUP (또는 플러그인) 방식의 적절한 사용

하위테마를 만들었고, 하위테마에는 CSS 코드를 추가 정의할 수 있는 style.css 파일과 functions.php이 있습니다. MUP에는 특정 테마를 위한 CSS 코드 정의와 워드프레스 기본 기능 및 테마의 기능을 제어하는 2개의 MUP가 있습니다.

테마 2015 하위테마를 사용하므로 CSS 코드가 있는 MUP에서 2015 테마를 위한 CSS 코드를 잘라내어 하위테마의 style.css 파일에 넣고, 2015 테마를 위한 기능 제어 코드만 해당 MUP에서 잘라 하위테마의 functions.php 파일에 추가하여 정리합니다.

먼저 default-theme-style.php 파일에서 테마 2015를 위한 색상 구조 CSS 코드만 복사하여 하위테마의 style.css 파일에 추가하면 다음 코드로 정리할 수 있습니다.

/*
 Theme Name: Twenty Fifteen Child
 Template: twentyfifteen
 Version: 1.5
 Text Domain: twenty-fifteen-child
*/

body{background-color:#674970}.site-header,body:before{background-color:#2e2256}.comments-area,.hentry,.page-content,.page-header,.pagination,.post-navigation,.secondary,.site-footer,.widecolumn{background-color:#fff}.page-links a,.page-links a:focus,.page-links a:hover,.pagination .next,.pagination .prev,.sticky-post,.widget_calendar tbody a,.widget_calendar tbody a:focus,.widget_calendar tbody a:hover,button,input[type=button],input[type=reset],input[type=submit]{color:#fff}.page-links a,.pagination .next,.pagination .prev,.sticky-post,.widget_calendar tbody a,button,input[type=button],input[type=reset],input[type=submit]{background-color:#2e2256}.comment-list .reply a:focus,.comment-list .reply a:hover,.comment-metadata a:focus,.comment-metadata a:hover,.comment-navigation a:focus,.comment-navigation a:hover,.dropdown-toggle:after,.entry-footer a:focus,.entry-footer a:hover,.image-navigation a:focus,.image-navigation a:hover,.pingback .edit-link a:focus,.pingback .edit-link a:hover,.site-info a:focus,.site-info a:hover,.widget-title,a,blockquote cite,blockquote small,body{color:#2e2256}.author-description a,.comment-content a,.comment-list .reply a:hover,.comment-metadata a:hover,.entry-content a,.entry-footer a:hover,.entry-summary a,.page-content a,.pingback .comment-body>a,.pingback .edit-link a:hover,.site-info a:hover,.taxonomy-description a,.textwidget a{border-color:#2e2256}.page-links a:focus,.page-links a:hover,.pagination .next:focus,.pagination .next:hover,.pagination .prev:focus,.pagination .prev:hover,.widget_calendar tbody a:focus,.widget_calendar tbody a:hover,button:focus,button:hover,input[type=button]:focus,input[type=button]:hover,input[type=reset]:focus,input[type=reset]:hover,input[type=submit]:focus,input[type=submit]:hover{background-color:#2e2256;background-color:rgba(46,34,86,.7)}.author-heading,.comment-author,.comment-awaiting-moderation,.comment-form label,.comment-list .reply a,.comment-metadata,.comment-metadata a,.comment-navigation,.comment-navigation a,.comment-notes,.entry-caption,.entry-footer,.entry-footer a,.form-allowed-tags,.gallery-caption,.image-navigation,.image-navigation a,.logged-in-as,.main-navigation .menu-item-description,.no-comments,.page-links>.page-links-title,.pingback .edit-link,.pingback .edit-link a,.post-navigation .meta-nav,.post-navigation a:focus .post-title,.post-navigation a:hover .post-title,.post-password-form label,.site-info,.site-info a,.taxonomy-description,.widecolumn .mu_register label,.widecolumn label,.widget,.wp-caption-text,a:focus,a:hover,blockquote{color:#2e2256;color:rgba(46,34,86,.7)}.comment-author a:hover,.logged-in-as a:hover,blockquote{border-color:#2e2256;border-color:rgba(46,34,86,.7)}.dropdown-toggle:focus,.dropdown-toggle:hover,hr{background-color:#2e2256;background-color:rgba(46,34,86,.1)}.author-info,.comment-list .pingback,.comment-list .reply a,.comment-list .trackback,.comment-list article,.comment-list+.comment-respond,.comment-navigation,.comments-area,.entry-content .page-links a,.hentry+.hentry,.main-navigation li,.main-navigation ul,.no-comments,.page-header,.page-links>span,.pagination,.post-navigation,.post-navigation div+div,.site-footer,.site-header,.widget li,.widget_categories .children,.widget_nav_menu .sub-menu,.widget_pages .children,abbr[title],input,pre,table,td,textarea,th{border-color:#2e2256;border-color:rgba(46,34,86,.1)}a:focus,button:focus,input:focus{outline-color:#2e2256;outline-color:rgba(46,34,86,.3)}input:focus,textarea:focus{border-color:#2e2256;border-color:rgba(46,34,86,.3)}.secondary-toggle:before,.site-description,.site-title a{color:#fff}.site-title a:focus,.site-title a:hover{color:rgba(255,255,255,.7)}.secondary-toggle{border-color:#fff;border-color:rgba(255,255,255,.1)}.secondary-toggle:focus,.secondary-toggle:hover{border-color:#fff;border-color:rgba(255,255,255,.3)}.site-title a{outline-color:#fff;outline-color:rgba(255,255,255,.3)}.entry-footer{background-color:#f1f1f1}@media screen and (min-width:38.75em){.page-header{border-color:#2e2256}}@media screen and (min-width:59.6875em){.secondary,.site-header{background-color:transparent}.widget button,.widget input[type=button],.widget input[type=reset],.widget input[type=submit],.widget_calendar tbody a,.widget_calendar tbody a:focus,.widget_calendar tbody a:hover{color:#2e2256}.dropdown-toggle:after,.secondary a,.widget blockquote cite,.widget blockquote small,.widget-title{color:#fff}.widget button,.widget input[type=button],.widget input[type=reset],.widget input[type=submit],.widget_calendar tbody a{background-color:#fff}.textwidget a{border-color:#fff}.main-navigation .menu-item-description,.secondary a:focus,.secondary a:hover,.widget,.widget .gallery-caption,.widget .wp-caption-text,.widget blockquote{color:rgba(255,255,255,.7)}.widget button:focus,.widget button:hover,.widget input[type=button]:focus,.widget input[type=button]:hover,.widget input[type=reset]:focus,.widget input[type=reset]:hover,.widget input[type=submit]:focus,.widget input[type=submit]:hover,.widget_calendar tbody a:focus,.widget_calendar tbody a:hover{background-color:rgba(255,255,255,.7)}.widget blockquote{border-color:rgba(255,255,255,.7)}.main-navigation li,.main-navigation ul,.widget abbr[title],.widget input,.widget li,.widget pre,.widget table,.widget td,.widget textarea,.widget th,.widget_categories .children,.widget_nav_menu .sub-menu,.widget_pages .children{border-color:rgba(255,255,255,.1)}.dropdown-toggle:focus,.dropdown-toggle:hover,.widget hr{background-color:rgba(255,255,255,.1)}.widget input:focus,.widget textarea:focus{border-color:rgba(255,255,255,.3)}.dropdown-toggle:focus,.sidebar a:focus{outline-color:rgba(255,255,255,.3)}}

다음 순서를 확인하세요.

  • 위의 코드를 복사하여 style.css 파일로 만들기
  • 워드프레스 설치 경로에서 wp-content > themes > twentyfifteen-child 디렉터리에 파일 올리기 (덮어쓰기)
  • 사이트에서 색상 변화 확인
  • 워드프레스 설치 경로에서 wp-content > mu-plugins 디렉터리의 default-theme-style.php 파일 삭제

사이트를 확인하면 보라색 색상 구조를 볼 수 있습니다. default-theme-style.php 파일에는 테마 2016의 CSS 코드가 남아 있지만 그냥 지웁니다. 시간 여유가 있다면 테마 2016의 하위테마를 만드는 데 사용하세요.

이번에는 default-mup.php 파일에서 테마 2015의 기능 제어에 해당하는 코드만 가져와서 하위테마의 functions.php 파일에 추가하면 다음 코드와 같습니다.

<?php
add_action( 'wp_enqueue_scripts', 'child_theme_enqueue_styles' );
function child_theme_enqueue_styles() {
    wp_enqueue_style( 'twenty-fifteen-style', get_template_directory_uri() . '/style.css' );
}

/* 테마 2015 몇 가지 기능 제거 */
add_action( 'init', 'disable_2015_nav_desc_function' );
function disable_2015_nav_desc_function() {
    remove_filter( 'walker_nav_menu_start_el', 'twentyfifteen_nav_description' );
}

if ( ! function_exists( 'twentyfifteen_post_thumbnail' ) ) {
  function twentyfifteen_post_thumbnail() {
    // 
  }
}

다음 순서를 확인하세요.

  • 위의 코드를 복사하여 `functions.php` 파일로 만들기
  • 워드프레스 설치 경로에서 wp-content > themes > twentyfifteen-child 디렉터리에 파일 올리기 (덮어쓰기)
  • 사이트를 확인하여 섬네일과 메뉴 설명 노출 여부 확인 (나오지 않아야 함)

default-mup.php 파일에서 위에서 진행한 테마 2015 관련 코드를 제외하면 다음과 같습니다. 혹시 어려운 분을 위해 남기며, 중요한 것은 아니나 설명(Description)을 변경할 필요는 있습니다.

<?php
/**
 * Plugin Name: Default Functions
 * Description: 워드프레스 기본 기능 제어
 */

/* 사이트 소스 <head> 태그 블록 요소 제거 */
add_action('init', 'default_some_head_cleanup');
function default_some_head_cleanup() {
    remove_action( 'wp_head', 'rsd_link' );
    remove_action( 'wp_head', 'wlwmanifest_link' );
    remove_action( 'wp_head', 'wp_generator' );
    remove_action( 'wp_head', 'wp_shortlink_wp_head' );
}

/* Emoji 비활성 */
add_action( 'init', 'disable_emojis' );
function disable_emojis() {
    remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
    remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
    remove_action( 'wp_print_styles', 'print_emoji_styles' );
    remove_action( 'admin_print_styles', 'print_emoji_styles' );
    remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
    remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
    remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
    add_filter( 'tiny_mce_plugins', 'disable_emojis_tinymce' );
}

function disable_emojis_tinymce( $plugins ) {
    if ( is_array( $plugins ) ) {
        return array_diff( $plugins, array( 'wpemoji' ) );
    } else {
        return array();
    }
}

/* 구글 통계 스크립트(추적 코드) */
add_action( 'wp_footer', 'my_footer_script' );
function my_footer_script() {
?>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXXXX-1', 'auto');
ga('send', 'pageview');
</script>
<?php
}

/* Gmail SMTP */
add_action( 'phpmailer_init', 'my_phpmailer' );
function my_phpmailer( $phpmailer ) {
    $phpmailer->isSMTP();
    $phpmailer->Host = 'smtp.gmail.com';
    $phpmailer->SMTPAuth = true;
    $phpmailer->Port = 587;
    $phpmailer->Username = 'your_account@gmail.com';
    $phpmailer->Password = 'password';
    $phpmailer->SMTPSecure = "tls";
    $phpmailer->From = "your_account@gmail.com";
    $phpmailer->FromName = get_option( 'blogname' );
}

원격에서 직접 편집이 어려운 분을 위해 아래 순서로 안내합니다.

  • 위의 코드를 복사하여 `default-mup.php` 파일 만들기
  • 워드프레스 설치 경로에서 wp-content > mu-plugins 디렉터리에 올리기 (덮어쓰기)

테마 변경에 영향을 받지 않도록 MUP 방식으로 워드프레스 기본 기능에 관한 정의를. 하위테마에는 테마와 관련한 코드만 추가하여 다른 테마를 사용할 때 필요하지 않은 표현과 기능만 추가한 것으로 정리할 수 있습니다.

이후부터는 테마와 관련한 CSS 코드 추가나 기능 제어를 위한 코드 스니핏을 추가해야 한다면 하위테마의 style.css 파일과 functions.php 파일에 이어서 추가하면 됩니다. 테마에 영향을 받지 않아야 하는 정의가 필요하다면 존재하는 MUP 파일에 이어서 추가하거나 새로운 MUP를 만들어 구분하는 것도 좋습니다.

하위테마에 템플릿 파일 추가

테마의 템플릿 파일을 변경 또는 추가할 필요가 없다면 하위테마를 꼭 사용할 필요가 없다고 했는데, 상위테마에 존재하는 특정 템플릿 파일을 변경하기 위해서는 상위테마의 해당 파일을 그대로 복사해서 하위테마에 가져온 후 원하는 작업을 진행하면 됩니다. 소스의 내용을 변경하지 않아도 같은 이름의 파일이 있다면 하위테마의 파일을 사용합니다.

현재 테마 2015는 single.php 파일이 워드프레스 기본 포스트 타입 post의 상세 내용을 보여주는 템플릿 파일입니다. 상세 내용 페이지를 ‘싱글 페이지’라고 보통 부릅니다. 조금 극단적인 가정으로 싱글 페이지를 흰색으로 표현하고 싶다면 다음 코드로 마크업할 수 있습니다.

<?php
/**
 * The template for displaying all single posts and attachments
 *
 */

다음 순서를 확인하세요.

  • 위 코드를 복사하여 `single.php` 파일로 만들기
  • 워드프레스 설치 경로에서 wp-content > themes > twentyfifteen-child 디렉터리에 파일 올리기
  • 브라우저 URL 필드에 도메인/?p=1 입력 후 결과 확인

상위테마가 아닌 하위테마의 single.php 파일을 워드프레스가 사용한다는 것을 간단하게 확인할 수 있습니다.

테마 2015는 archive.php 파일이 워드프레스 기본 분류(taxonomy)의 하나인 category 아카이브(목록) 페이지를 출력하는 역할을 맡고 있습니다. 다른 아카이브(date, author 등) 페이지 출력도 모두 담당하고 있습니다. category 아카이브 페이지는 흰색으로 표현한다는 가정으로 상위테마에 없는 category.php 파일을 하위테마에 만들어 봅니다.

(category.php 파일은 템플릿 계층 구조에 속하는 파일이므로 워드프레스가 자동으로 인식합니다.)

<?php
/**
 * The template for displaying category archive pages
 */

다음 순서를 확인하세요.

  • 위 코드를 복사하여 `category.php` 파일로 만들기
  • 워드프레스 설치 경로에서 wp-content > themes > twentyfifteen-child 디렉터리에 파일 올리기
  • 브라우저 URL 필드에 도메인/?cat=1 입력 후 결과 확인
  • 다른 아카이브 페이지가 상위테마의 `archive.php` 파일에 의해 출력되는지 확인하기 위해 브라우저 URL 필드에 도메인/?author=1 입력 후 확인

상위테마에 없는 템플릿 계층 구조의 파일을 하위테마에 추가하여 사용할 수 있음을 간단하게 확인할 수 있습니다.

정리

글에서 안내하지 못한 내용이 꽤 있지만, 테마의 템플릿 파일을 편집 또는 추가하지 않는다면 반드시 하위테마를 사용할 필요가 없으며, CSS 코드를 통한 사이트의 스타일 변경이나 워드프레스 기본 기능 및 테마의 특정 기능을 제어하는 것은 플러그인 또는 MUP 방식의 전개로 충분하며 오히려 효율적일 수 있다는 것이 이 글의 한 줄 요약입니다.

혹 이 포스트의 모든 과정을 빠짐없이 따라 했다면 정말 훌륭한 분입니다.

댓글 4

  1. 저는 “하위테마” 가 자식테마/새끼테마 보다는 어감이 훨씬 더 좋은데요?

    앞으로 child theme 은 “하위테마” 라고 표현하고 싶은데 왜 좋은 표현이 아닌지 궁금합니다.

    1. 반갑습니다. 특별한 이유는 없어요. 일상에서 사용하는 하위, 상위 같은 단어가 테마와 함께 사용되는 게 왠지 부자연스러운 그냥 느낌입니다.

      hackya님을 왜 스패머로 판정했을까요?

  2. “혹 이 포스트의 모든 과정을 빠짐없이 따라 했다면 정말 훌륭한 분입니다.”

    => 훌륭한 분이 되기 위해, 다시 한번 정독하고 공부 했습니다. ㅋㅋ

    잘 지내시죠? 새로운 책은 계획중이신가요? 혹시 소식 있으면 꼭 알려주세요. ^^*