[워드프레스] 22. 숏코드 : 숏코드로 동적 콘텐츠 넣는 법

워드프레스 해부 22편 - 숏코드로 동적 콘텐츠 넣는 법

작성자

카테고리:

* 이 게시물은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

(워드프레스 해부 ㉒) 숏코드

글 본문에 [프로필] 한 줄 넣으면 프로필 카드가 뜨고, [최근글] 넣으면 목록이 나온다. 이런 걸 숏코드(shortcode)라 한다. 정적인 글 안에 동적인 조각을 심는 장치다.

만드는 법은 add_shortcode('이름', 콜백). 핵심 규칙 하나 — 콜백은 결과를 echo가 아니라 return 해야 한다. echo하면 출력 위치가 어긋난다.

직접 해보기

add_shortcode( 'greeting', function( $atts ) {
    $a = shortcode_atts( array( 'name' => '방문자' ), $atts );  // 속성 기본값
    return '<strong>안녕하세요, ' . esc_html( $a['name'] ) . '님!</strong>';
} );
// 글에서 사용:  [greeting name="코즈모"]

shortcode_atts()로 속성의 기본값을 정하고, 출력할 땐 19편에서 배운 esc_html()로 이스케이프하는 걸 잊지 말자.

✅ 확인 — 글에 [greeting name="코즈모"]를 넣고 발행하면, 그 자리에 “안녕하세요, 코즈모님!”이 렌더되면 성공. 대괄호가 그대로 보이면 숏코드가 등록 안 된 것이다.

흔히 막히는 지점 — 숏코드 콜백에서 echo로 출력하면 결과가 글 맨 위로 튀어 올라간다. 숏코드는 반환값(return)이 그 자리에 삽입되는 구조다. 문자열을 만들어 return하고, HTML이 길면 ob_start()로 버퍼링해 반환하자.

속성을 제대로 다루기

실전 숏코드는 속성이 여러 개다. shortcode_atts()로 기본값을 정의하면, 사용자가 실제로 넘긴 값만 그 위에 덮인다. 하나 알아둘 것 — 속성 이름은 전부 소문자로 정규화된다. [button URL="..."]처럼 대문자로 써도 콜백엔 url로 들어온다.

add_shortcode( 'button', function( $atts ) {
    $a = shortcode_atts( array(
        'text'  => '자세히',
        'url'   => '#',
        'color' => '#0d6efd',
    ), $atts, 'button' );

    return sprintf(
        '<a href="%s" style="background:%s" class="cz-btn">%s</a>',
        esc_url( $a['url'] ),        // URL 자리 → esc_url
        esc_attr( $a['color'] ),     // 태그 속성 자리 → esc_attr
        esc_html( $a['text'] )       // 화면 텍스트 자리 → esc_html
    );
} );
// 사용: [button text="구매하기" url="https://cozlab.app" color="#ff8000"]

이스케이프 함수가 자리마다 다른 게 핵심이다. URL은 esc_url, 태그 속성 안은 esc_attr, 사람이 읽는 텍스트는 esc_html. 같은 값이라도 어디에 출력되느냐에 따라 방어법이 달라진다.

긴 HTML은 출력 버퍼로 반환한다

return 규칙 때문에 출력할 HTML이 길어지면 문자열을 .로 잇는 코드가 금세 지저분해진다. 이럴 땐 ob_start()로 출력을 버퍼에 모았다가 ob_get_clean()으로 한 번에 문자열로 받아 반환하면 깔끔하다.

add_shortcode( 'recent_posts', function( $atts ) {
    $a = shortcode_atts( array( 'count' => 5 ), $atts );
    $q = new WP_Query( array(
        'posts_per_page' => (int) $a['count'],
        'no_found_rows'  => true,   // 페이지네이션 불필요 → 쿼리 절약
    ) );

    ob_start();                      // 여기서부터 출력을 버퍼에 모은다
    echo '<ul class="cz-recent">';
    while ( $q->have_posts() ) { $q->the_post();
        printf( '<li><a href="%s">%s</a></li>',
            esc_url( get_permalink() ), esc_html( get_the_title() ) );
    }
    echo '</ul>';
    wp_reset_postdata();             // 전역 $post 원복
    return ob_get_clean();           // 버퍼 내용을 문자열로 반환
} );
// 사용: [recent_posts count="3"]

콜백 안에서 echo를 써도 되는 건 ob_start()가 그 출력을 가로채 버퍼에 담기 때문이다. 결국 밖으로 나가는 건 return한 문자열 하나뿐이라 규칙을 지킨다. 커스텀 쿼리를 돌렸으면 14편의 wp_reset_postdata()를 꼭 호출해 전역 상태를 되돌리자.

내용을 감싸는 숏코드 — [box]…[/box]

여는 태그만 있는 숏코드 말고, [box]내용[/box]처럼 감싸는(enclosing) 형태도 만들 수 있다. 이때 콜백의 두 번째 인자 $content로 사이에 낀 내용이 들어온다.

add_shortcode( 'box', function( $atts, $content = '' ) {
    $a = shortcode_atts( array( 'type' => 'info' ), $atts );
    // 안에 또 다른 숏코드가 있을 수 있으니 do_shortcode로 한 번 더 처리
    $inner = do_shortcode( $content );
    return '<div class="cz-box cz-' . esc_attr( $a['type'] ) . '">' . $inner . '</div>';
} );
// 사용: [box type="tip"]여기에 [greeting name="코즈모"] 도 중첩 가능[/box]

do_shortcode($content)를 거치면 안쪽에 낀 다른 숏코드까지 재귀적으로 처리된다. 이 $content 인자가 있느냐 없느냐가 여는형과 감싸는형을 가른다.

숏코드가 실행되지 않을 때 — 체크리스트

본문에선 잘 되던 숏코드가 다른 곳에선 대괄호 그대로 보이는 경우가 많다. 원인은 대개 정해져 있다.

  • 위젯·템플릿 파일에서는 자동 실행 안 됨 — the_content를 거치지 않기 때문. 직접 echo do_shortcode('[greeting]')로 호출해야 한다.
  • 발췌(excerpt)·대표 영역에선 숏코드가 실행되지 않고 태그만 남거나 제거된다.
  • 대괄호가 그대로 보임 — add_shortcode 등록이 안 됐거나, 로딩 순서상 init 전에 호출된 경우.
  • 줄바꿈이 깨짐 — wpautop이 반환 HTML을 <p>로 감싸며 생기는 문제. 반환 문자열을 trim()하면 대개 해결된다.
  • 페이지 캐시 — 고쳤는데 반영이 안 되면 캐시를 비운다(18편).

숏코드 vs 블록 — 언제 무엇을

구텐베르크 시대에도 숏코드는 사라지지 않았다. 둘은 용도가 다르다.

기준숏코드블록
편집 경험텍스트 [태그] 입력시각적 UI
쓸 수 있는 곳본문·위젯·이메일·다른 CMS주로 에디터 안
만드는 법함수 하나(add_shortcode)block.json + JS(edit/save)
성격레거시·범용현대 워드프레스
추천기존 유지·범용 삽입새로 만들면 이쪽

정리하면 새로 만든다면 블록이 방향이다. 다만 이메일 본문, 위젯, 다른 시스템과의 호환처럼 “어디에나 텍스트로 꽂아야 하는” 상황에선 숏코드가 여전히 가장 간단하다. 그래서 실무에선 둘을 상황에 맞게 섞어 쓴다.

고전적인 숏코드를 봤으니, 다음은 현대 워드프레스의 핵심 — 구텐베르크 블록의 구조다.

자주 묻는 질문 (FAQ)

숏코드가 뭔가요?

[shortcode] 형태로 글 안에 동적 콘텐츠를 넣는 기능입니다. add_shortcode로 이름과 처리 함수를 등록합니다.

블록 에디터에서도 숏코드가 되나요?

네, 숏코드 블록을 쓰거나 문단에 직접 넣으면 됩니다. 다만 새로 만든다면 블록으로 만드는 걸 권하기도 합니다.

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다