ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Acorn은 플러그인도 테마도 아니다 — 워드프레스 안에 라라벨을 심는 물건의 정체와 2026년 현황
    IT 2026. 9. 21. 22:00

    ▶ 동영상 개요 — Acorn은 플러그인도 테마도 아니다 — 워드프레스 안에 라라벨을 심는 물건의 정체와 2026년 현황

    8분 0초 — Acorn은 플러그인도 테마도 아니라 composer.json에 한 줄로 앉아 있는 라이브러리 묶음이다 — 워드프레스 템플릿 파일 하나가 데이터 조회와 HTML… — NotebookLM 동영상 개요로 생성

    🎧 오디오 개요 — Acorn은 플러그인도 테마도 아니다 — 워드프레스 안에 라라벨을 심는 물건의 정체와 2026년 현황

    21분 35초 — Acorn은 플러그인도 테마도 아니라 composer.json에 한 줄로 앉아 있는 라이브러리 묶음이다 — 워드프레스 템플릿 파일 하나가 데이터 조회와 HTML…. 화면은 이 글의 인포그래픽 한 장 고정 — NotebookLM 오디오 개요로 생성

    워드프레스로 개인 사이트를 굴리면서 정적 문서를 올려 두고 있다. 어느 날 프로젝트의 composer.json을 들여다보다 roots/acorn이라는 한 줄에서 멈췄다. 관리자 화면의 플러그인 목록에도 없고 테마 목록에도 없다. 그런데 이걸 빼면 사이트가 안 뜬다. 몇 달을 쓰면서 정작 그게 무엇인지 몰랐다.

    찾아보니 Acorn은 플러그인도 테마도 아니었다. 워드프레스 프로젝트 안에서 라라벨(Laravel — PHP로 웹 애플리케이션을 만드는 가장 널리 쓰이는 프레임워크)의 부품을 그대로 꺼내 쓰게 해 주는 라이브러리 묶음이다. MIT 라이선스 오픈소스이고, 만든 곳은 Roots라는 독립 조직이다. 숫자 하나가 Acorn의 성격을 잘 보여준다 — PHP 패키지 저장소 Packagist 기준 누적 253만 6,081회 내려받혔고 지금도 월 9만 2,651회가 나가는데, 깃허브 별은 1,000개뿐이다. 사람들이 이름을 보고 고르는 물건이 아니라, 다른 걸 깔면 바닥에 딸려 오는 물건이라는 뜻이다. 내 composer.json에 이름 모를 한 줄로 앉아 있던 이유가 그거였다.

    Acorn이 하는 일 — 라라벨의 부품 21개를 워드프레스로 옮긴다

    Acorn의 composer.json을 열면 정체가 한눈에 드러난다. 의존성 34개 중 21개가 illuminate/*다. illuminate는 라라벨 프레임워크를 기능별로 쪼개 놓은 공식 패키지들의 이름표다 — illuminate/view는 화면 그리기, illuminate/database는 DB 조회, illuminate/queue는 작업 미루기, 이런 식이다. Acorn은 이 부품들을 가져와 워드프레스가 뜰 때 함께 시동을 걸어 준다.

    diagram

    다이어그램 설명. Acorn이 워드프레스 어디에 끼어드는지를 한 장으로 줄이면 이 모양이다. "워드프레스 요청"이 들어올 때 그 앞이나 뒤를 가로채는 게 아니라, 요청을 처리하는 도중에 쓸 수 있는 부품 창고를 하나 열어 두는 것에 가깝다. "Acorn Application"은 서비스 컨테이너(service container — 어떤 부품이 필요하다고 이름만 대면 알아서 만들어 건네주는 저장소)라 부르는 물건인데, 라라벨의 심장에 해당한다. "Blade — 화면 그리기"부터 "Artisan — wp acorn 명령 만들기"까지가 전부 그 상자에서 꺼내 쓰는 부품이다. 여기서 놓치기 쉬운 게 하나 있다 — Acorn은 워드프레스를 대체하지 않는다. 글 목록을 가져오고 URL을 해석하고 플러그인을 부르는 일은 여전히 워드프레스가 한다. Acorn은 그 위에 개발자용 도구층 하나를 얹을 뿐이라, 워드프레스 관리자 화면은 평소와 똑같이 작동하고 다른 플러그인도 그대로 돈다.

    설치는 플러그인 업로드가 아니라 명령 한 줄이다. composer require roots/acorn. Composer(PHP 세계의 패키지 관리자 — Node.js의 npm에 해당한다)로 받아서 테마나 플러그인 안에 부품으로 넣는다. 그래서 관리자 화면 어느 목록에도 안 보인다.

    왜 이런 게 나올 수밖에 없었나 — 워드프레스 템플릿의 구조

    워드프레스는 2026년 8월 29일 W3Techs 집계로 전체 웹사이트의 40.7%, CMS를 쓰는 사이트만 놓고 보면 58.9%를 차지한다. 압도적 1위다. 그런데 이 물건의 테마 시스템은 2003년의 설계를 크게 바꾸지 않은 채 여기까지 왔다.

    워드프레스는 템플릿 계층(template hierarchy)이라는 규칙으로 화면을 그린다. 글 하나를 보여줄 땐 single.php, 페이지는 page.php, 검색 결과는 search.php… 주소를 보고 정해진 이름의 PHP 파일을 찾아 실행하는 방식이다. 단순하고 배우기 쉽다. 문제는 그 파일 하나가 전부를 떠안는다는 것이다.

    diagram

    다이어그램 설명. 전통적인 워드프레스 템플릿 파일 하나가 실제로 담고 있는 것들이다. "글 데이터 조회"와 "HTML 마크업"이 같은 층에 나란히 있다는 게 핵심이다 — 데이터를 가져오는 코드와 화면을 그리는 코드가 물리적으로 같은 파일에 섞여 있다. 왜 이렇게 됐나 하면, 이 설계가 나온 시점에는 그게 장점이었기 때문이다. 파일 하나만 열면 그 화면의 모든 것이 보이니 디자이너도 고칠 수 있었고, 워드프레스가 폭발적으로 퍼진 이유 중 하나가 바로 이 낮은 진입 장벽이다. 대가는 나중에 왔다. 화면이 복잡해질수록 그 파일 하나가 수백 줄이 되고, 제목을 정하는 규칙 같은 걸 다른 화면에서도 쓰려면 복사·붙여넣기 말고는 방법이 없다.

    코드로 보면 더 분명하다.

    <?php
    // 전통적인 워드프레스 템플릿 — single.php
    
    get_header();                                   // 1단: 헤더 파일을 통째로 끌어온다
    
    if (have_posts()) :                             // 2단: 전역 상태에 담긴 글 목록을 확인
        while (have_posts()) : the_post();          //      전역 포인터를 한 칸 옮긴다
    
            // 3단: 제목을 정하는 "규칙"이 마크업 한가운데 끼어든다
            $title = is_archive()
                ? get_the_archive_title()
                : get_the_title();
            ?>
            <article>
              <h1><?php echo esc_html($title); ?></h1>
              <?php the_content(); ?>
            </article>
            <?php
        endwhile;
    endif;
    
    get_footer();                                   // 4단: 푸터 파일을 통째로 끌어온다
    

    코드 설명. 스무 줄 남짓한 이 파일에 네 가지 일이 겹쳐 있다. 여기서 진짜 문제는 길이가 아니라 3단의 $title 계산이다. 이건 화면이 아니라 판단인데, 마크업 사이에 끼어 있어서 다른 템플릿에서 재사용할 방법이 없다. 그리고 have_posts()·the_post()는 인자를 받지 않는다 — 어떤 글을 다루는지가 전역 상태(global state — 프로그램 어디서나 접근 가능한 공용 변수)에 들어 있고 함수들이 그걸 몰래 읽고 고치기 때문이다. 그래서 이 코드는 테스트를 붙이기가 대단히 어렵다. 무엇을 넣으면 무엇이 나오는지가 함수 시그니처에 안 적혀 있으니, 검증하려면 워드프레스를 통째로 띄워 놓고 전역 상태를 흉내 내야 한다.

    Acorn을 얹으면 같은 화면이 이렇게 갈라진다.

    {{-- resources/views/single.blade.php — 화면만 남는다 --}}
    @extends('layouts.app')
    
    @section('content')
      @while(have_posts()) @php(the_post())
        @include('partials.content-single')
      @endwhile
    @endsection
    

    코드 설명. Blade(라라벨의 템플릿 엔진 — @extends·@include 같은 짧은 지시어로 화면을 조각내 조립한다)로 쓴 같은 템플릿이다. @extends('layouts.app')는 "공통 레이아웃 안에 이 내용을 끼워 넣어라"는 뜻이라, 앞 예제의 get_header()·get_footer() 짝이 사라진다. 헤더와 푸터를 양쪽에서 각각 끌어오는 방식과 레이아웃 안에 내용을 넣는 방식의 차이인데, 후자는 닫는 것을 깜빡할 수 없다는 게 실질적인 이득이다. 그리고 이 파일에는 판단이 하나도 없다. 제목을 정하던 규칙은 어디로 갔나 하면, 별도 클래스로 빠진다.

    // app/View/Composers/Post.php — 제목을 정하는 "규칙"만 모아 둔 클래스
    class Post extends Composer
    {
        // 이 규칙을 어떤 화면들에 공급할지 선언한다
        protected static $views = ['partials.content', 'partials.page-header'];
    
        public function title(): string
        {
            if (is_archive()) {
                return get_the_archive_title();
            }
    
            if (is_search()) {
                return sprintf(__('Search Results for %s', 'sage'), get_search_query());
            }
    
            return get_the_title();
        }
    }
    

    코드 설명. Sage 테마에 실제로 들어 있는 파일을 줄인 것이다. 이게 뷰 컴포저(view composer — 화면에 넘길 데이터를 준비하는 전담 클래스)인데, 핵심은 $views 선언이다. "이 규칙은 partials.contentpartials.page-header 화면에 쓴다"고 한 번 적어 두면, 그 화면들이 그려질 때 title()의 결과가 자동으로 배달된다. 템플릿 쪽에서 매번 불러오는 코드를 쓸 필요가 없다. 앞 예제와 비교하면 무엇이 달라졌는지가 분명하다 — 판단은 클래스로, 화면은 템플릿으로 갈렸다. 이제 제목 규칙은 한 군데만 고치면 되고, 클래스라서 테스트도 붙일 수 있다. 다만 공짜는 아니다. 파일 하나 열면 끝나던 것이 이제 두 곳을 오가야 하고, 워드프레스만 알던 사람에게는 배울 것이 하나 더 늘어난다. Acorn이 파는 것은 편의가 아니라 이 맞바꿈이다.

    15년짜리 배경 — Sage 안에서 자라 밖으로 나온 물건

    Acorn은 어느 날 갑자기 기획된 물건이 아니다. Roots가 만드는 워드프레스 스타터 테마 Sage 안에서 자라다가 떨어져 나왔다. 저장소 기록을 따라가면 그 과정이 그대로 보인다.

    diagram

    다이어그램 설명. Acorn이 어떻게 생겨났는지를 시간순으로 늘어놓은 것이다. 눈여겨볼 곳은 "2018년 2월 — Sage 9 정식 출시"와 "2018년 8월 — Acorn 저장소 개설" 사이의 여섯 달이다. Sage 9는 Blade를 처음 들여왔지만, 정작 화면에 데이터를 넘기는 일은 soberwp/controller라는 외부 커뮤니티 패키지에 맡기고 있었다(당시 README에 의존성으로 명시돼 있다). 즉 라라벨의 템플릿 엔진 하나만 떼어 오고 나머지는 임시로 이어 붙인 상태였다. 그 이음매를 제대로 만들려고 시작한 것이 Acorn이고, 그래서 Acorn은 기획된 제품이 아니라 테마 안의 접착제가 독립한 결과다. 이 순서를 알면 왜 Acorn이 "워드프레스용 라라벨"처럼 거창한 이름 대신 부품 창고에 가까운 모양을 하고 있는지 납득이 된다. 처음부터 프레임워크를 만들려던 게 아니라, 이미 쓰고 있던 것을 정리한 물건이다.

    Sage 10이 나온 2022년 3월에 방향이 완전히 뒤집힌다. 그전까지 Acorn은 Sage의 부품이었는데, 이때부터 Sage가 Acorn 위에 서는 구조가 됐다. 지금 Sage 저장소는 깃허브 별 13,265개로 Acorn(1,000개)의 열세 배지만, 다운로드 수는 반대다 — Sage가 누적 34만 5,191회인 데 비해 Acorn은 253만 6,081회다. 사람들이 아는 이름은 Sage인데 실제로 더 많이 설치되는 건 Acorn이다. 테마를 새로 만들 때 한 번 받는 Sage와, 테마·플러그인·배포마다 매번 따라 들어가는 Acorn의 차이다.

    어디에 쓰이고 있나

    Acorn을 쓰는 경로는 크게 셋이다.

    첫째, Sage 테마를 통해서. 가장 흔한 경로이고, 대부분의 사용자가 Acorn을 직접 고르지 않고 여기서 만난다. 현재 버전은 Sage v11.2.1이고 Vite(개발 중 코드를 고치면 새로고침 없이 화면에 반영해 주는 빌드 도구)와 Tailwind CSS v4가 함께 들어온다. Roots가 자사 사이트에 내건 Sage 사용 사례에는 Ars Technica, Gizmodo, PopSci, NASA 같은 이름이 있다.

    둘째, 직접 composer require해서. Sage를 쓰지 않는 자체 테마나 플러그인에도 넣을 수 있다. 이때는 functions.php나 플러그인 진입 파일에 시동 코드를 몇 줄 넣고 wp acorn acorn:install을 실행한다. Roots의 또 다른 프로젝트인 Radicle을 쓰면 이 과정이 미리 되어 있다.

    셋째, Acorn을 전제로 만든 패키지들을 통해서. Roots가 직접 관리하는 공식 패키지만 여섯 개다.

    diagram

    다이어그램 설명. Acorn 위에 올라가는 공식 패키지 목록이다. 여섯 개가 전부 같은 층위에 병렬로 붙어 있고 서로 연결되지 않는다는 게 요점이다 — 필요한 것만 골라 넣는 구조이지, 한 묶음으로 딸려 오는 세트가 아니다. 이 목록이 말해 주는 게 하나 더 있다. "acorn-user-roles — 사용자 권한을 설정 파일로"나 "acorn-post-types — 커스텀 글 유형 선언"은 워드프레스에서 원래 관리자 화면을 클릭하거나 functions.php에 함수를 호출해 하던 일이다. 그걸 굳이 설정 파일로 옮기는 이유는, 그래야 깃 저장소에 기록으로 남고 배포로 옮겨 갈 수 있기 때문이다. Acorn 생태계가 실제로 파는 가치가 여기 드러난다 — 새 기능이 아니라, 이미 있던 것을 버전 관리되는 코드로 끌어내리는 것이다.

    블록 편집기와도 붙는다. 워드프레스 블록은 화면을 그릴 때 render_callback이라는 PHP 함수를 부르는데, 그 자리에 Blade 템플릿을 꽂을 수 있다.

    register_block_type('vendor/example', [
        // 원래는 여기서 문자열로 HTML을 조립해 반환해야 한다
        'render_callback' => function ($attributes, $content) {
            return view('blocks/example', compact('attributes', 'content'));
        },
    ]);
    

    코드 설명. 세 줄짜리지만 이 글의 주제를 압축하고 있다. 워드프레스 블록의 원래 방식은 PHP 함수 안에서 문자열을 이어 붙여 HTML을 만들어 반환하는 것이다 — 조금만 복잡해져도 따옴표와 이스케이프가 엉킨다. view() 한 줄로 바꾸면 마크업은 별도의 Blade 파일로 나가고 이 함수에는 무엇을 넘길지만 남는다. 앞에서 본 템플릿 분리와 정확히 같은 발상이 블록 단위로 반복되는 셈이다.

    2026년 현황 — 활발한 개발과 넘지 못한 벽

    먼저 좋은 쪽부터 보자. Acorn은 죽은 프로젝트가 아니다. 2026년 3월 25일 v6.0.0이 나와 라라벨 13 기반으로 올라갔고, 6월 1일 v6.2.0, 마지막 코드 반영은 8월 24일이다. 릴리스 간격도 규칙적이다 — v4는 2024년 1월, v5는 2025년 3월, v6는 2026년 3월에 나왔다. 라라벨이 메이저 버전을 낼 때마다 대략 따라붙는 리듬이다. 2026년 2월 25일에는 Acorn AI가 발표됐는데, 라라벨의 laravel/ai 패키지와 워드프레스의 Abilities API를 이어 붙여 OpenAI·Anthropic·Gemini 같은 모델을 워드프레스 안에서 쓰게 하는 물건이다. 이 시점에 나온 것치고 늦지 않다.

    그런데 두 개의 벽이 있고, 둘 다 Acorn이 혼자 힘으로는 못 넘는 종류다.

    첫째, PHP 버전. Acorn v6는 PHP 8.3 이상을 요구한다. 워드프레스 본체가 요구하는 최소 버전은 여전히 PHP 7.4다. 이 간극이 실제로 어느 정도인지는 워드프레스가 공개하는 설치 통계로 확인할 수 있다.

    • PHP 8.3 — 24.97%
    • PHP 8.4 — 8.43%
    • PHP 8.5 이상 — 2.75%
    • PHP 8.2 — 24.81% (Acorn v6 불가)
    • PHP 7.4 — 17.32% (2022년 지원 종료된 버전)

    합치면 전체 워드프레스 설치의 36.1%만 Acorn v6를 돌릴 수 있다. 나머지 64%는 서버의 PHP를 올리기 전까지는 설치 자체가 안 된다. 남의 서버에 배포하는 테마를 만드는 입장이라면 이건 취향 문제가 아니라 고객의 3분의 2를 포기하느냐의 문제다. 개인 서버를 직접 관리한다면 상관없는 이야기지만, 이 숫자가 Acorn의 다운로드 곡선에 천장을 씌우고 있다.

    둘째, 의존성 충돌. 이쪽이 더 구조적이다.

    diagram

    다이어그램 설명. Acorn이 겪는 가장 흔한 실무 장애를 그린 것이다. "워드프레스 PHP 프로세스 하나"라는 표현이 전부인데 — 워드프레스는 활성화된 모든 플러그인을 같은 PHP 프로세스에 함께 올린다. 플러그인마다 자기 방을 주는 격리 장치가 없다. 그래서 결제 플러그인이 자기 안에 구버전 로그 라이브러리를 넣어 배포하고 Acorn이 최신 버전을 요구하면, 이름이 같은 클래스 둘이 한 공간에서 만난다. PHP는 이럴 때 병합하거나 경고하지 않는다 — 먼저 로드된 것이 자리를 차지하고, 나중에 온 쪽은 자기가 기대한 것과 다른 코드를 쓰게 된다. 그 결과가 원인 파악이 어려운 치명적 오류다. Acorn 공식 문서가 호환성 문제 페이지를 따로 두고 Google for WooCommerce, Gravity Forms, 여러 WooCommerce 배송 확장 같은 실명을 나열하고 있는 이유가 이것이다. 여기서 중요한 건 누구의 잘못인가다 — Acorn의 버그가 아니고 그 플러그인들의 버그도 아니다. 워드프레스가 의존성 격리를 제공하지 않는다는 사실 자체가 원인이라, Acorn 쪽에서 고칠 방법이 없다. 문서가 내놓는 답도 "플러그인 개발자들이 자기 의존성에 고유 이름표를 붙여 배포해 달라"는 부탁이거나, 사용자가 직접 패치를 덧대라는 우회로다.

    비교 대상 하나를 놓으면 위치가 더 잘 잡힌다. 워드프레스에 현대적 템플릿을 들여오는 다른 선택지로 Timber(Blade 대신 Twig라는 템플릿 엔진을 쓴다)가 있는데, 누적 다운로드 384만 회로 Acorn(254만 회)보다 많다. 다만 월간으로 보면 Timber 8만 4,844회, Acorn 9만 2,651회로 Acorn이 앞선다. 오래 쌓인 쪽은 Timber, 지금 더 빨리 늘어나는 쪽은 Acorn이라는 그림이다. 둘의 성격 차이도 분명하다 — Timber는 템플릿 엔진 하나를 깔끔하게 바꿔 주는 물건이고, Acorn은 프레임워크 하나를 통째로 들고 들어온다. 앞의 PHP 버전 벽과 의존성 충돌은 많이 들고 들어온 쪽이 치르는 비용이다.

    정리 — 이름 모를 의존성 한 줄의 정체

    composer.json에서 마주친 roots/acorn 한 줄의 정체는 이거였다. 워드프레스가 20년 넘게 유지해 온 "파일 하나가 데이터와 화면을 함께 떠안는" 템플릿 구조를, 라라벨의 부품 21개를 빌려와 갈라놓는 물건이다. 플러그인 목록에 안 보이는 이유는 그게 기능이 아니라 바닥 공사이기 때문이다.

    그래서 이 물건은 얹을지 말지가 취향이 아니라 조건의 문제다. PHP 8.3 이상을 내 마음대로 올릴 수 있는 서버인가, 함께 쓰는 플러그인들이 자기 의존성을 격리해 배포하는가? 개인 서버에 정적 문서를 올리는 정도의 규모라면 두 조건 다 내 손 안에 있으니 부담이 거의 없다. 반대로 남의 서버에 나갈 테마라면 사용자의 3분의 2가 설치조차 못 한다는 숫자를 먼저 봐야 한다.

    남는 교훈은 조금 더 일반적이다 — 내 프로젝트에 이름 모를 의존성이 앉아 있다면, 그건 대개 누군가 오래 참다가 만든 물건이다. Acorn은 Sage가 Blade를 들여오고도 여섯 달 동안 임시 접착제로 버티다 떨어져 나온 결과였고, 그 출생 순서를 알고 나니 composer.json의 한 줄이 다르게 읽혔다. 모르는 의존성을 발견했을 때 지울지 남길지 정하기 전에, 그게 무엇을 참다가 생겼는지부터 찾아보는 게 빠른 길이다.


    참고한 공개 자료:


    이 글은 생성형 AI의 도움을 받아 작성되었습니다. 원본 자료를 기반으로 AI가 초안을 생성하고, 작성자가 검토·편집하였습니다.

Designed by Tistory.