1. 테마 디자인 관리 개요
DXCMS 관리자 패널의 [테마 디자인 관리] 메뉴는 사이트 프론트엔드에 적용할 디자인 테마를 선택•활성화하고, 테마별 개별 옵션을 설정하며, 자신이 제작한 테마를 DesignOneX 마켓에 공유하는 도구입니다. 테마는 /themes/ 디렉터리에 설치되며, 관리자 화면에서 클릭 한 번으로 즉시 전환됩니다.📌 접근 경로: 관리자 대시보드 → 테마 디자인 관리 (URL: /admin/themes) 테마 디렉터리: /themes/{테마폴더명}/
1.1 테마 시스템 개념
| 구성 요소 | 설명 |
| 테마 (Theme) | /themes/{폴더명}/ 디렉터리에 설치된 디자인 패키지. theme.json 메타데이터 파일과 레이아웃·스킨·에셋 파일로 구성. |
| 활성 테마 | settings 테이블의 setting_key='theme' 값. 단 하나의 테마만 활성화 가능. 기본값: default. |
| 테마 옵션 | 테마 개발자가 theme.json의 options에 정의한 커스터마이징 항목. 색상·폰트·레이아웃 등을 관리자가 설정. |
| 오버라이딩 | 테마 파일이 없는 경우 자동으로 default 테마의 코드를 불러옵니다. 필요한 부분만 오버라이딩하여 효율적 개발 가능. |
| DxTheme 클래스 | 테마 목록 조회·메타 읽기·리셋 담당 PHP 싱글톤 클래스. |
1.2 화면 구성
| 영역 | 설명 |
| 페이지 헤더 | "테마 디자인 관리" 제목과 부제목. |
| 메시지 배너 | 활성화·저장·공유 결과 메시지(초록=성공 / 빨강=오류). |
| 테마 그리드 | /themes/ 디렉터리의 모든 테마를 카드 형태로 표시. 1~4열 반응형 그리드. |
| 테마 프레임워크 가이드 | 어두운 배경의 개발자 참고 패널. 디렉터리 구조·전역 헬퍼 함수 코드 표시. |
| 테마 옵션 설정 패널 | 활성화된 테마의 [테마 옵션 설정] 클릭 시 URL이 /admin/themes/{폴더명}으로 변경되며 옵션 폼이 아래 표시. |
| 마켓 공유 모달 | [마켓에 테마 공유] 버튼 클릭 시 팝업 형태로 표시. |
2. 테마 그리드 — 테마 목록
설치된 모든 테마가 카드 형태로 격자 배열됩니다. 화면 너비에 따라 1~4열로 자동 반응형 배치됩니다.
2.1 테마 카드 구성 요소
| 요소 | 설명 |
| 미리보기 이미지 | h-44(176px) 영역. theme.json의 preview 경로에 이미지가 있으면 object-cover로 표시. 없으면 🎨 이모지 대체. 마우스 호버 시 scale-110 확대 효과. |
| Active 배지 | 현재 활성화된 테마의 미리보기 우측 상단에 하늘색 "Active" 배지가 표시됩니다(animate-bounce-in). |
| 테마명·버전 | theme.json의 name + 버전(V1.0.0). 버전은 회색 모노스페이스. |
| 설명 | theme.json의 description. 최대 2줄(line-clamp-2) 이탤릭체. |
| 제작자 | theme.json의 author. 미설정 시 "알 수 없음". |
| [지금 활성화하기] 버튼 | 비활성 테마에만 표시. 검정 버튼. 클릭 시 해당 테마가 즉시 활성화됩니다. |
| [테마 옵션 설정] 버튼 | 활성 테마에만 표시. 하늘색 버튼. 클릭 시 /admin/themes/{폴더명}으로 이동하여 옵션 폼 표시. |
| [마켓에 테마 공유] 버튼 | 마켓 미공유 테마에 표시. 보라색 버튼. 클릭 시 공유 모달 팝업. |
| "공유중" 상태 | 마켓 공유 중인 테마에 초록 "공유중 (UID앞4자)" 배지 + 빨간 [×] 공유 중단 버튼. |
2.2 활성 테마 카드 시각 구분
활성 테마 카드는 비활성 테마와 다음과 같이 시각적으로 구분됩니다.| 카드 테두리 | border-sky-500(2px 하늘색 테두리) + ring-sky-500/10(4px 글로우 링). |
| 미리보기 배지 | 우측 상단에 "✓ Active" 하늘색 배지. |
| 아이콘 색상 | 카드 안 아이콘이 emerald(초록) 색상으로 표시. |
| 버튼 변경 | [지금 활성화하기] 대신 [테마 옵션 설정] 버튼이 표시됨. |
3. 테마 활성화
테마 카드의 [지금 활성화하기] 버튼을 클릭하면 해당 테마가 즉시 사이트 프론트엔드에 적용됩니다.
3.1 활성화 처리 흐름
- CSRF 토큰 검증
- POST된 theme 값에서 영문소문자•숫자•_•- 외 문자 제거 (XSS•경로 조작 방지)
- DX_THEMES/{폴더명} 디렉터리 실제 존재 여부 확인
- settings 테이블에 setting_key='theme', setting_value={폴더명} UPSERT
- DxCache::delete('dx_settings') — 설정 캐시 초기화
- dx_config_set('theme', {폴더명}) — 현재 요청의 설정 즉시 갱신
- DxTheme::reset() — 테마 클래스 인스턴스 리셋
- "테마 [{폴더명}]가 활성화되었습니다." 성공 메시지 표시
💡 테마 전환은 DB 업데이트 즉시 반영됩니다. 사이트 방문자도 페이지를 새로고침하면 새 테마가 적용됩니다. 캐시 환경에서는 DxCache 초기화로 즉시 반영됩니다.
3.2 활성화 절차
- 관리자 대시보드 → [테마 디자인 관리] 메뉴 클릭
- 테마 그리드에서 적용할 테마 카드 확인 (미리보기 이미지•이름•설명 참고)
- 원하는 테마 카드의 [지금 활성화하기] 버튼 클릭
- "테마 [...] 가 활성화되었습니다." 초록 메시지 확인
- 해당 테마 카드에 "Active" 배지가 표시됨 확인
- 사이트 프론트엔드를 새 탭에서 열어 테마 적용 확인
- 필요하면 [테마 옵션 설정] 버튼으로 옵션 커스터마이징
4. 테마 옵션 설정
활성화된 테마가 theme.json에 options를 정의한 경우, [테마 옵션 설정] 버튼 클릭 시 URL이 /admin/themes/{폴더명}으로 변경되며 화면 하단에 옵션 설정 폼이 표시됩니다.
4.1 옵션 입력 필드 유형
| 옵션 타입 | HTML 입력 요소 | 사용 사례 및 특징 |
| text (기본) | <input type="text"> | 일반 텍스트 입력. 사이트명·태그라인·폰트명 등에 사용. |
| color | <input type="color"> + 읽기 전용 텍스트 | 색상 피커(w-12 h-12 둥근 사각형) + HEX 값 읽기 전용 텍스트 쌍. 포인트 색상·배경색 등. |
| checkbox | <input type="checkbox" value="1"> | "기능 활성화" 레이블과 함께 표시. 다크 모드·상단 배너·애니메이션 ON/OFF 등. |
| textarea | <textarea rows=3> | 여러 줄 텍스트. 커스텀 CSS 코드·긴 설명·임베드 스크립트 등. |
4.2 옵션 저장 처리
- CSRF 토큰 검증
- POST된 theme 폴더명 정제
- DxTheme::getInstance()->meta($themeDir)로 해당 테마의 options 정의 로드
- 각 옵션 키(optKey)별로 POST 값 읽기: opt_{optKey} 이름의 필드
- settings 테이블에 UPSERT: setting_key='theme_{폴더명}_{optKey}', setting_group='theme'
- DxCache::delete('dx_settings') 캐시 초기화
- "테마 옵션이 저장되었습니다." 성공 메시지
💡 옵션 저장 후 사이트 새로고침 즉시 적용됩니다. 테마 파일에서는 dx_theme_option('optKey') 헬퍼 함수로 저장된 옵션값을 읽어 사용합니다.
4.3 옵션 설정 DB 저장 키 형식
테마 옵션은 settings 테이블에 다음 형식으로 저장됩니다.| DB 저장 키(setting_key) | 예시 |
| theme_{폴더명}_{옵션키} | theme_my-theme_primary_color → 폴더: my-theme, 옵션: primary_color |
| theme_default_logo_url | 폴더: default, 옵션: logo_url |
💡 PHP 테마 파일에서 읽을 때: dx_theme_option('primary_color'). 또는 dx_config('theme_{폴더명}_{옵션키}')로 직접 읽을 수 있습니다.
4.4 옵션 설정 절차
- [테마 디자인 관리] 접속
- 활성화된 테마 카드의 [⚙ 테마 옵션 설정] 버튼 클릭
- URL이 /admin/themes/{폴더명}으로 변경되고 화면 하단에 옵션 폼 표시 확인
- 각 옵션 필드 값 입력•변경 (색상 피커•텍스트•체크박스•텍스트에어리어)
- [💾 옵션 저장하기] 버튼 클릭
- "테마 옵션이 저장되었습니다." 성공 메시지 확인
- 사이트 프론트엔드 새로고침으로 변경 확인
- 취소 시 [목록으로 취소] 링크 클릭 → /admin/themes로 이동
5. DesignOneX 마켓에 테마 공유
자신이 제작한 테마를 DesignOneX 마켓에 공유하거나 유료 판매할 수 있습니다. [마켓에 테마 공유] 버튼 클릭 시 공유 모달이 팝업으로 열립니다.
⚠️ 마켓 공유 전 [관리자 → DesignOneX 마켓] 메뉴에서 사이트 마켓 등록이 완료되어 있어야 합니다. 미등록 시 "먼저 관리자 > DesignOneX 마켓에서 사이트를 등록하세요." 오류가 발생합니다.
5.1 마켓 공유 모달 입력 필드
| 필드 | 필수 여부 | 설명 |
| 공개 방식 | 필수 | 🆓 FREE(무료 공유) 또는 💰 PAID(유료 판매). PAID 선택 시 가격·구매 URL 필드 추가 표시. |
| 판매 가격 (KRW) | 유료 시 필수 | PAID 선택 시 표시. 숫자 입력. 단위: KRW. 예: 29000. |
| 구매 페이지 URL | 유료 시 필수 | PAID 선택 시 표시. 구매·결제가 이루어지는 외부 페이지 URL. |
| 미리보기 이미지 URL | 선택 | 마켓에 표시될 미리보기 이미지 외부 URL. 비워두면 theme.json의 preview 파일 사용. |
| 카테고리 | 선택 | 블로그형·쇼핑몰형·포트폴리오·커뮤니티형 중 선택. |
| 태그 | 선택 | 쉼표로 구분한 키워드. 예: 반응형, 미니멀. |
| 공개용 설명글 | 선택 | 마켓에서 다른 사용자에게 표시되는 테마 소개 텍스트. |
5.2 공유 처리 흐름
- 모달의 [마켓 공유 승인 요청] 버튼 클릭
- CSRF 토큰 검증
- DxMarket::getInstance()->isRegistered() 확인 → 미등록 시 오류
- DxMarket::shareTheme($folder, $opts) 실행 → 마켓 API 호출
- 성공 시: settings 테이블에 market_theme_shared_{폴더명}=1, market_theme_uid_{폴더명}={UID} 저장
- "테마 [{폴더명}]가 마켓에 공유되었습니다." 성공 메시지
- 카드에 초록 "공유중" 배지 + 빨간 [×] 공유 중단 버튼 표시
5.3 공유 중단
공유 중인 테마 카드의 빨간 [×] 버튼 클릭 시 공유가 중단됩니다.| 처리 내용 | DxMarket::unshareTheme($folder) 실행. settings 테이블의 market_theme_shared_{폴더명}=0으로 변경. |
| 마켓 반영 | 마켓 API에 공유 해제 요청이 전송됩니다. |
| 결과 메시지 | "테마 [{폴더명}] 공유가 비활성화되었습니다." 성공 메시지 표시. |
| 복구 | 공유 중단 후 다시 [마켓에 테마 공유] 버튼으로 재공유 가능합니다. |
6. 테마 프레임워크 가이드 (개발자)
관리자 화면 하단의 어두운 배경 패널에 테마 제작을 위한 기본 가이드가 제공됩니다. 테마를 직접 제작하거나 수정하려는 개발자를 위한 참고 자료입니다.
6.1 테마 표준 디렉터리 구조
| 파일/폴더 | 역할 및 설명 |
| theme.json (필수 권장) | 테마 메타 정보 JSON. name/version/description/author/preview/options 키 포함. 이 파일이 없으면 폴더명이 이름으로 사용됩니다. |
| layout/main.php | 전체 기본 레이아웃. 헤더·메인·푸터를 포함하는 HTML 뼈대. |
| board/list.php | 게시판 목록 스킨. 게시글 목록 UI. |
| board/view.php | 게시글 본문 스킨. 게시글 상세 내용 UI. |
| page/ | 커스텀 페이지 보관 디렉터리. 특수 목적 페이지 PHP 파일. |
| assets/ | CSS·JavaScript·이미지 등 정적 파일. dx_theme_asset()으로 경로 생성. |
6.2 theme.json 구조
theme.json은 테마의 메타데이터와 옵션을 정의하는 핵심 파일입니다.| 키 | 필수 여부 | 설명 및 예시 |
| name | 권장 | 테마 표시 이름. 예: "My Beautiful Theme". |
| version | 권장 | 버전 문자열. 예: "2.0.0". |
| description | 권장 | 테마 짧은 설명. 관리자 카드에 2줄 표시. |
| author | 선택 | 제작자 이름 또는 회사명. |
| preview | 권장 | 미리보기 이미지 상대 경로. 예: "preview.jpg" (테마 폴더 기준). |
| options | 선택 | 관리자가 설정 가능한 옵션 정의 객체. {optKey: {label, type, default}} 구조. |
6.3 theme.json options 정의 예시
options 객체에 옵션 키를 정의합니다. 각 옵션은 label•type•default 속성을 가집니다.| 텍스트 옵션 (text) | {"label": "사이트 태그라인", "type": "text", "default": "더 나은 내일을 위해"} |
| 색상 옵션 (color) | {"label": "포인트 색상", "type": "color", "default": "#6366f1"} |
| 체크박스 옵션 (checkbox) | {"label": "다크 모드 지원", "type": "checkbox", "default": ""} |
| 텍스트에어리어 (textarea) | {"label": "헤더 추가 CSS", "type": "textarea", "default": ""} |
6.4 전역 헬퍼 함수
테마 PHP 파일에서 즉시 사용 가능한 DXCMS 내장 전역 헬퍼 함수입니다.| 함수 | 역할 및 사용 예 |
| dx_theme_asset($path) | 테마 에셋의 절대 URL 반환. 예: dx_theme_asset('css/main.css') → https://site.com/themes/my-theme/css/main.css |
| dx_theme_option($key) | theme.json에 정의하고 저장된 옵션값 반환. 예: dx_theme_option('primary_color') → #6366f1 |
| dx_include_part($name) | 테마의 parts/ 디렉터리에 있는 공통 모듈(Partial) 포함. 예: dx_include_part('header') |
| dx_menu_group($group) | 지정한 메뉴 그룹의 메뉴 데이터 배열 반환. 예: dx_menu_group('main') |
| dx_run_hook($pos) | 플러그인 훅 포인트 실행. 예: dx_run_hook('dx_header_end') — 활성 플러그인의 해당 훅 출력. |
6.5 오버라이딩 원칙
- DXCMS 테마 시스템은 오버라이딩 방식으로 동작합니다.
- 테마 파일이 없으면 자동으로 default 테마의 동일 파일로 폴백됩니다.
- 새 테마에서 변경하고 싶은 파일만 작성하면 됩니다. 나머지는 default가 처리합니다.
- 예: board/list.php만 있는 테마라도, 다른 페이지는 default/layout/main.php 등으로 자동 처리됩니다.
💡 완전히 새로운 디자인을 원한다면 모든 파일을 작성하세요. 부분적인 변경만 필요하다면 바꿀 파일만 작성하여 효율적으로 개발할 수 있습니다.
7. 새 테마 설치 및 제거
7.1 외부 테마 설치 방법
- 다운로드한 테마 파일을 서버의 /themes/{테마폴더명}/ 디렉터리에 업로드 (FTP 또는 파일 관리자)
- 폴더 안에 theme.json 또는 최소한 PHP 파일이 있는지 확인
- 관리자 → [테마 디자인 관리] 메뉴 새로고침
- 테마 그리드에 새 테마 카드가 표시됨 확인
- [지금 활성화하기] 버튼으로 테마 적용
- 필요하면 [테마 옵션 설정]에서 커스터마이징
7.2 테마 완전 제거
- 사용 중인 테마를 제거하기 전 다른 테마로 먼저 전환 (default 테마 활성화)
- FTP 또는 파일 관리자로 /themes/{제거할 테마 폴더명}/ 디렉터리 삭제
- 관리자 → [테마 디자인 관리] 새로고침 시 해당 테마 카드가 사라짐 확인
⚠️ 현재 활성화된 테마 폴더를 삭제하면 사이트가 default 테마(또는 오류 화면)로 표시됩니다. 반드시 다른 테마로 전환 후 삭제하세요.
8. 전체 사용 절차 요약
8.1 처음 테마 설정하기
- 관리자 대시보드 → [테마 디자인 관리] 메뉴 클릭
- 테마 그리드에서 원하는 테마의 미리보기 이미지•이름•설명 확인
- [지금 활성화하기] 버튼 클릭 → "테마 [...] 가 활성화되었습니다." 확인
- 사이트 프론트엔드 새로고침으로 테마 적용 확인
- 활성 테마의 [⚙ 테마 옵션 설정] 버튼 클릭
- 색상•폰트•레이아웃 등 원하는 옵션값 설정
- [💾 옵션 저장하기] 버튼 클릭
- 사이트에서 옵션 변경 결과 확인
8.2 테마 전환
- [테마 디자인 관리] 접속
- 다른 테마 카드의 [지금 활성화하기] 클릭
- 성공 메시지 확인 및 사이트에서 새 테마 확인
- 필요하면 새 테마 옵션 설정
9. 자주 묻는 질문 (FAQ)
Q1. 새로 설치한 테마가 목록에 표시되지 않습니다.
A. /themes/{폴더명}/ 디렉터리에 파일이 올바르게 업로드되었는지 확인하세요. 폴더 자체는 있어야 하며, 관리자 페이지를 새로고침하면 자동으로 감지됩니다. 폴더명에 대문자•공백•특수문자(영문 소문자•숫자•_•-만 허용)가 포함되어 있으면 보안 처리에 의해 제외될 수 있습니다.
Q2. 테마를 활성화했는데 사이트 디자인이 변경되지 않습니다.
A. DxCache가 활성화된 환경에서는 DxCache::delete('dx_settings')가 자동 실행되어 즉시 반영됩니다. 브라우저 캐시 문제라면 Ctrl+Shift+R(강력 새로고침)을 시도하세요. 테마 폴더에 layout/main.php 또는 필요한 파일이 없으면 default 테마로 폴백됩니다.
Q3. 테마 옵션 설정 버튼이 표시되지 않습니다.
A. 활성화된 테마(Active 배지가 표시된 테마)에만 [테마 옵션 설정] 버튼이 표시됩니다. 또한 해당 테마의 theme.json에 options 키가 정의되어 있어야 합니다. options가 없으면 버튼이 없습니다.
Q4. 마켓 공유 시 오류가 발생합니다.
A. ① [관리자 → DesignOneX 마켓] 메뉴에서 사이트 등록이 완료되어 있는지 확인하세요. ② 마켓 API 서버(designonex.com)와의 네트워크 연결이 가능한지 확인하세요. ③ PAID 방식 선택 시 가격과 구매 URL을 올바르게 입력했는지 확인하세요.
Q5. default 테마로 돌아가고 싶습니다.
A. 테마 그리드에서 "default" 테마 카드의 [지금 활성화하기] 버튼을 클릭하면 됩니다. default 테마가 없으면 /themes/default/ 디렉터리를 생성하거나 다른 테마를 사용하세요.
Q6. 테마 옵션 색상 피커가 반응하지 않습니다.
A. 브라우저가 <input type="color">를 지원해야 합니다. 구형 IE 브라우저는 지원하지 않습니다. 최신 Chrome•Firefox•Edge•Safari를 사용하세요.
Q7. 활성화된 테마의 CSS를 빠르게 변경하고 싶습니다.
A. theme.json에 type: textarea 옵션을 정의하면 관리자에서 직접 CSS를 입력할 수 있습니다. 테마 파일의 레이아웃에서 dx_theme_option('custom_css')로 읽어 <style> 태그 안에 출력하는 방식을 사용하세요.
10. 용어 정리
| 용어 | 설명 |
| DxTheme | 테마 목록 조회·메타 읽기·리셋을 담당하는 PHP 싱글톤 클래스. |
| DxTheme::reset() | 테마 클래스 인스턴스를 초기화하여 새 테마 설정을 즉시 반영. |
| allThemes() | DxTheme의 /themes/ 디렉터리 스캔 후 모든 테마 메타 배열 반환 메서드. |
| meta($dir) | 특정 테마의 theme.json을 읽어 메타데이터 배열 반환 메서드. |
| theme.json | 테마 메타데이터 정의 파일. name/version/description/author/preview/options 키. |
| options (theme.json) | 관리자가 설정 가능한 커스터마이징 옵션 정의 객체. 색상·텍스트·체크박스·텍스트에어리어 지원. |
| preview (theme.json) | 테마 폴더 기준 미리보기 이미지 상대 경로. 예: "preview.jpg". |
| setting_key = "theme" | 현재 활성화된 테마 폴더명을 저장하는 settings 테이블의 키. |
| theme_{폴더명}_{옵션키} | 테마 옵션값 저장 키 형식. 예: theme_my-theme_primary_color. |
| setting_group = "theme" | 테마 관련 설정을 그룹핑하는 settings 테이블의 group 값. |
| dx_theme_asset($path) | 테마 에셋 절대 URL 생성 헬퍼. 예: dx_theme_asset("css/main.css"). |
| dx_theme_option($key) | theme.json에 정의한 옵션의 저장된 값 반환 헬퍼. |
| dx_include_part($name) | 테마의 공통 모듈(Partial) 포함 헬퍼. |
| dx_menu_group($group) | 메뉴 그룹 데이터 반환 헬퍼. 테마 내비게이션 렌더링에 활용. |
| dx_run_hook($pos) | 플러그인 훅 포인트 실행 함수. 테마 레이아웃에 삽입하여 플러그인 출력. |
| 오버라이딩 | 테마 파일이 없을 때 default 테마로 자동 폴백되는 동작 원리. |
| DxMarket::shareTheme() | 테마를 마켓에 공유하는 메서드. 마켓 API 호출 + 설정 저장. |
| DxMarket::unshareTheme() | 테마 마켓 공유를 해제하는 메서드. |
| market_theme_shared_{폴더명} | 테마 마켓 공유 여부를 저장하는 settings 키. 값: "1" 또는 "0". |
| market_theme_uid_{폴더명} | 마켓 공유 후 부여된 테마 고유 식별자(UID)를 저장하는 settings 키. |
| DxCache::delete("dx_settings") | 테마 변경 시 설정 캐시를 즉시 초기화하는 호출. |