회원가입 | 고객센터 |
DESIGNONEX DXCMS BOARD
로그인
DESIGNONEX
디자인원엑스
About DXMB └ 메뉴얼 └ 이용약관 └ MB키 발급 └ 업데이트 DXCMS └ 메뉴얼 └ 다운로드 └ Themes └ Plugin └ Skin └ 사용후기 └ 마켓개발자 키 발급 DXB └ DXB Documentation └ InterfaceGallery └ Download └ 사용후기 └ 디자인소스 Service Q&A PR리그 자유게시판 갤러리 포인트게임 공지사항
로그인 회원가입
고객센터
미니 프레임워크 (Engine)

DxCMS 미니 프레임워크 기술 문서

A Administrator
2026.04.10 15:51(수정됨) 13 0

1. 시스템 개요

DxCMS Board는 DesignOneX에서 만든 PHP 기반 경량 CMS(Content Management System)입니다. 단일 진입점(index.php) 구조, 파일 기반 라우팅, 플러그인•훅•extend 세 가지 확장 방법을 제공하며, PHP 5.6부터 8.x까지 단일 코드베이스로 동작합니다.


핵심 설계 철학

  • 단일 진입점 — 모든 HTTP 요청은 index.php 한 곳으로 집결
  • 직접 수정 최소화 — core/ 폴더 수정 없이 extend, 훅, 플러그인으로 기능 추가
  • 저가형 호스팅 호환 — APCuRedis 없어도 파일 캐시로 동작
  • PHP 5.6 하위 호환 — anonymous fn, ??, return type hint 미사용
  • 보안 단일화 — core/Secure.php 한 파일에 모든 보안 코드 집중

지원 환경
항목 지원 범위
PHP 버전 5.6 • 7.0 • 7.1 • 7.2 • 7.3 • 7.4 • 8.0 • 8.1 • 8.2 • 8.3 • 8.4
데이터베이스 MySQL 5.6+, MariaDB 10.1+ (PDO)
웹서버 Apache 2.2+, Nginx, IIS 7+, 저가형 공유호스팅
OS Windows, Linux
캐시 Redis (1순위) → APCu (2순위) → 파일 캐시 (기본)
에디터 CKEditor 4 (내장), Jodit, TinyMCE (플러그인)
 

2. 전체 폴더 구조

DxCMS의 최상위 폴더 구조입니다. 각 폴더의 역할과 직접 수정 가능 여부를 정리합니다.
dxcms-board/
├── index.php          ← 단일 진입점 (모든 HTTP 요청)
├── .htaccess          ← Apache URL Rewrite
├── web.config         ← IIS URL Rewrite
├── nginx.conf.example ← Nginx 설정 예시
├── core/              ← CMS 엔진 (직접 수정 비권장)
├── admin/             ← 관리자 페이지
├── boards/            ← 게시판 핸들러 + 스킨
├── themes/            ← 프론트엔드 테마
├── plugins/           ← 플러그인
├── assets/            ← 정적 에셋 (CKEditor 등)
├── extend/            ← 코드 삽입 슬롯
├── data/              ← DB설정•업로드•캐시 (웹 비공개)
├── install/           ← 설치 마법사
├── pages/             ← 기본 페이지 파일
├── routes/            ← 라우트 정의 파일
├── controllers/       ← 컨트롤러 클래스
└── docs/              ← 내부 문서
 
폴더 역할 직접 수정
core/ CMS 핵심 엔진 (DB, 라우터, 보안, 테마, 캐시 등) 비권장 (보안 패치 시 Secure.php만)
admin/ 관리자 전용 페이지 (게시판/회원/설정 등 관리) 가능 (관리자 커스텀 시)
boards/ 게시판 요청 처리 핸들러 + 게시판 전용 스킨  가능 (스킨 추가 시)
themes/ 프론트엔드 HTML/CSS 레이아웃 및 게시판 뷰 권장 (커스텀 테마 추가)
plugins/ 에디터•결제•소켓 등 확장 플러그인 권장 (플러그인 개발)
extend/ 훅 없이 코드 삽입(점검모드•IP차단•방문 로그) 권장 (운영 커스텀)
data/ DB 접속 정보•업로드 파일•캐시 저장 자동 생성, 서버 비공개
assets/ CKEditor 로컬 파일, 공통 JS 가능 (에셋 추가)
install/ 설치 마법사 및 마이그레이션 파일 설치 후 삭제 권장
 

3. 폴더별 상세 설명


3-1. core/ — CMS 엔진 핵심

CMS의 두뇌입니다. 데이터베이스, 라우팅, 보안, 캐시, 테마, 플러그인 등 모든 핵심 기능이 여기 있습니다. 직접 수정은 최소화하고, 보안 패치가 필요하면 Secure.php 한 파일만 교체합니다.
core/
├── Secure.php          ← ★ 보안 전담 (CSRF•XSS•Rate Limit•WAF)
├── functions.php       ← 공통 헬퍼 함수 60여 개 (dx_* 접두어)
├── DxCache.php         ← Redis/APCu/파일 캐시 통합
├── DxSeo.php           ← SEO 메타 자동 생성
├── DxCategory.php      ← 카테고리 DB 조회•렌더링
├── DxSanitizer.php     ← HTML 입력 정제 (화이트리스트)
├── DxTheme.php         ← 테마 파일 해석 + 폴백 체인
├── DxSite.php          ← 멀티사이트 (도메인별 설정)
├── DxExtend.php        ← extend/ 폴더 자동 실행
├── DxPoint.php         ← 포인트/경험치/레벨
├── DxBoardSkin.php     ← 게시판 스킨 폴백 체인
├── DxRouter.php        ← 라라벨 스타일 라우터 (선택적)
├── DxMarket.php        ← 마켓 클라이언트 (플러그인 설치)
├── DxNotification.php  ← 실시간 알림 (DB + 소켓)
├── DxFriend.php        ← 스크랩/친구/차단
├── DxShop.php          ← 포인트샵
├── DxPopup.php         ← 팝업 관리
├── DxThumb.php         ← GD 썸네일 생성
├── DxContainer.php     ← 서비스 컨테이너 (DI)
├── DxCss.php           ← Tailwind 호환 CSS SSR
├── DxMemberMonitor.php ← 회원 접속 모니터링
├── DxMigration.php     ← 마이그레이션 감지
├── DxSocialAuth.php    ← 소셜 로그인 (카카오/네이버/구글/GitHub)
├── PluginRegistry.php  ← 플러그인 타입 등록
├── db/
│   ├── Database.php    ← PDO 래퍼 싱글턴
│   └── QueryBuilder.php← 빌더 패턴 쿼리 작성
├── router/
│   ├── Router.php      ← URL → 라우트 타입 결정
│   └── Dispatcher.php  ← 라우트 → 핸들러 실행
├── hook/
│   └── HookManager.php ← 액션/필터 훅 시스템
├── auth/
│   ├── Auth.php        ← 세션 기반 인증
│   ├── login.php       ← 로그인 페이지
│   ├── register.php    ← 회원가입
│   ├── mypage.php      ← 마이페이지
│   └── DxSocialAuth.php(소셜 OAuth2 처리)
└── api/
    ├── upload.php      ← 파일 업로드
    ├── comment.php     ← 댓글 CRUD
    ├── like.php        ← 좋아요
    ├── sitemap.php     ← 동적 사이트맵
    └── ...             ← 기타 AJAX 엔드포인트


3-2. admin/ — 관리자 페이지

모든 관리자 기능이 여기에 있습니다. 각 서브폴더가 하나의 관리 메뉴에 대응합니다. admin/index.php가 사이드바•헤더 레이아웃을 제공하고, 각 서브폴더의 index.php가 내용을 담습니다.
경로 기능
admin/index.php 관리자 레이아웃 (헤더•사이드바•공통 CSS)
admin/dashboard/ 방문자 통계, 최근 게시글, 회원 현황 대시보드
admin/boards/ 게시판 생성•수정•삭제, 에디터 선택, 카테고리 스킨 지정
admin/board_groups/ 게시판 그룹 관리
admin/categories/ 게시판 카테고리 (표시 위치•배지색•스킨)
admin/members/ 회원 목록•수정•포인트•레벨 관리
admin/menus/ 메뉴 관리 (게시판•페이지 빠른 선택 UI)
admin/pages/ 정적 페이지 관리 (홈 설정 포함)
admin/themes/ 테마 목록•활성화
admin/plugins/ 플러그인 목록•활성화•설정
admin/settings/ 사이트 기본 설정 (SEO•Analytics•캐시)
admin/statistics/ 방문자 통계•인기 검색어
admin/socket/ 실시간 소켓 접속자 모니터
admin/popup/ 팝업 관리
admin/shop/ 포인트샵 상품 관리
admin/market/ 마켓 플러그인/테마 설치
admin/social/ 소셜 로그인 설정
admin/points/ 포인트 내역 관리
admin/downloads/ 다운로드 통계
admin/sites/ 멀티사이트 도메인 관리


3-3. boards/ — 게시판 핸들러 및 스킨

게시판의 모든 요청(목록•보기•쓰기•수정•삭제•댓글)은 boards/handler.php 한 파일에서 처리됩니다. 렌더링은 스킨 파일에 위임하여 로직과 표현을 분리합니다.
 
boards/
├── handler.php               ← 모든 게시판 요청 처리 (약 79KB)
├── skins/
│   ├── gallery/              ← 갤러리형 스킨
│   │   ├── list.php          ← 목록 뷰
│   │   ├── view.php          ← 상세 뷰
│   │   ├── write.php         ← 작성/수정 뷰
│   │   └── skin.json         ← 스킨 메타 (이름•버전•옵션)
│   ├── erp/                  ← ERP형 스킨 (재고관리 액션 포함)
│   │   ├── actions/
│   │   │   └── inventory.php ← 커스텀 액션
│   │   └── skin.json
│   └── shop/                 ← 쇼핑몰형 스킨
│       └── actions/cart.php  ← 장바구니 액션
└── category/
    └── skins/
        ├── default/          ← 라운드 탭 카테고리
        │   ├── list.php
        │   └── view.php
        └── pill/             ← 언더라인 탭 카테고리

✅ boards/skins/SKIN_GUIDE.md 파일에 커스텀 스킨 제작 가이드가 포함되어 있습니다.


3-4. themes/ — 프론트엔드 테마

HTML 레이아웃과 CSS를 관리합니다. 테마별로 폴더를 만들고, 없는 파일은 자동으로 default 테마에서 폴백됩니다. 따라서 커스텀 테마는 변경하고 싶은 파일만 만들면 됩니다.
 
themes/
├── default/              ← 기본 테마 (항상 존재, 폴백 기준)
│   ├── theme.json        ← 테마 메타 (이름•버전•옵션)
│   ├── style.css         ← 테마 전용 CSS
│   ├── layout/
│   │   └── main.php      ← 전체 레이아웃 (헤더+본문+푸터)
│   ├── board/
│   │   ├── list.php      ← 게시판 목록
│   │   ├── view.php      ← 게시글 보기
│   │   └── write.php     ← 게시글 작성/수정
│   ├── board_latest/
│   │   ├── list.php      ← 최신글 위젯 (기본)
│   │   ├── card.php      ← 최신글 위젯 (카드형)
│   │   └── simple.php    ← 최신글 위젯 (간소)
│   ├── page/
│   │   ├── home.php      ← 홈 페이지
│   │   ├── 403.php
│   │   └── 404.php
│   ├── parts/
│   │   └── pagination.php← 페이지네이션 파셜
│   ├── search/
│   │   └── list.php      ← 검색 결과
│   └── icons/            ← SVG 아이콘
└── (my-theme)/           ← 커스텀 테마 (변경 파일만 있으면 됨)

 

폴백 체인 우선순위

  • themes/[현재테마]/board/list.php    ← 1순위: 현재 테마 파일
  • themes/default/board/list.php        ← 2순위: default 테마 폴백
  • 404 오류                                             ← 3순위: 최종 실패


3-5. plugins/ — 플러그인

에디터•결제•소켓 등 선택적 기능을 플러그인으로 제공합니다. 각 플러그인 폴더의 plugin.php가 dx_register_plugin()을 호출해 시스템에 등록됩니다.
 
플러그인 타입 설명
dx-socket socket 실시간 WebSocket (접속자 표시, 채팅, 알림)
jodit-editor editor Jodit WYSIWYG 에디터
tinymce-editor editor TinyMCE 에디터
tosspay-payment payment 토스페이 결제 연동 
example-plugin - 플러그인 개발 예제 템플릿
 
// 플러그인 등록 예시 (plugins/my-plugin/plugin.php)
dx_register_plugin(array(
    'id'      => 'my-plugin',
    'type'    => 'editor',
    'name'    => 'My Editor',
    'version' => '1.0.0',
    'settings' => array(
        'api_key' => array('label'=>'API 키', 'type'=>'text'),
    ),
));


3-6. extend/ — 코드 삽입 슬롯

훅 등록 없이 파일을 폴더에 넣기만 하면 자동으로 실행됩니다. 파일명 오름차순으로 실행되며, 에러가 발생해도 다른 파일에는 영향을 주지 않습니다.
 
폴더 실행 시점 주요 용도
extend/top/ DB•세션•인증 완료 직후, 라우팅 전 점검 모드, IP 차단, 커스텀 인증, 글로벌 변수 주입
extend/middle/ 라우트 확정 직후, 핸들러 실행 전 방문자 로그(기본 포함), A/B 테스트, 접근 제어
extend/bottom/ 렌더링 완료 후, 출력 직전 성능 로그, 캐시 저장, 정리 작업

✅ extend/ 파일은 파일명 앞에 숫자를 붙여 실행 순서를 제어합니다. 예: 01_maintenance.php, 02_ip_block.php


3-7. data/ — 설정•업로드•캐시 (웹 비공개)

웹 브라우저로 직접 접근이 차단된 폴더입니다. DB 접속 정보, 업로드된 파일, 파일 캐시가 저장됩니다.
 
data/
├── config.php       ← DB 연결 정보 + 설정 캐시 (설치 시 자동 생성)
├── cache/           ← 파일 캐시 저장소 (Redis/APCu 없을 때 사용)
│   └── *.cache      ← 직렬화된 캐시 파일
├── uploads/         ← 업로드 파일 저장소
│   └── .htaccess    ← PHP 실행 차단 (보안)
└── boards/          ← 게시판별 업로드

⚠ data/ 폴더는 절대 웹 루트 외부에 위치시키는 것이 가장 안전합니다. .htaccess로 PHP 실행이 차단됩니다.


3-8. assets/ — 정적 에셋

CDN 의존 없이 로컬에서 서빙하는 정적 파일들입니다.
 
경로 내용
assets/ckeditor4/ CKEditor 4.25.1-LTS 전체 파일 (로컬 서빙, CDN 없음)
assets/ckeditor4/config.js CKEditor 설정 (툴바, 언어, 업로드 URL)
assets/js/dxb-css.js Tailwind 호환 런타임 CSS 엔진
assets/js/dx.js 공통 JavaScript (CSRF 헤더, 플래시 메시지 등)


4. CORE 파일 상세 분석

core/ 폴더 안의 모든 파일을 하나씩 자세히 설명합니다. 각 파일의 역할, 주요 메서드, 사용 방법을 포함합니다.


4-1. Secure.php — 보안 전담 파일 (v5.2.2)

CMS 전체의 보안을 책임지는 핵심 파일입니다. 보안 패치가 필요하면 이 파일 하나만 교체하면 됩니다.


담당 기능

  • 세션 보안 — HttpOnly•Secure•SameSite=Lax 쿠키 설정
  • CSRF 토큰 — 발급•검증 (TTL 24시간, 활동 시 자동 갱신)
  • 보안 헤더 — X-Frame-Options, X-Content-Type-Options, Referrer-Policy
  • XSS 방어 — 출력 이스케이프 (dx_esc 함수)
  • WAF — SQL Injection, XSS 패턴 탐지 (POST 본문 에디터 필드 제외)
  • Rate Limit — Redis 기반 (파일 폴백) 요청 제한
  • Bot 탐지 — 검색엔진 봇은 허용, 의심 봇은 로그만 기록
  • 업로드 검증 — MIME + 확장자 이중 검증, 이중 확장자 차단
  • 비밀번호 해시 — bcrypt (PHP 5.6 폴백 포함)
  • 안전 난수 — random_bytes 폴백 체인 (PHP 5.6 호환)
  • Redis 연결 관리 — DxCache와 공유하는 단일 Redis 인스턴스

주요 메서드
메서드 설명
getInstance() 싱글턴 인스턴스 반환
initSession() 보안 세션 초기화 (쿠키 설정 적용)
startSession() 비로그인 GET 요청은 세션 시작 생략 (성능)
sendSecurityHeaders() CSRF 토큰 문자열 반환 (없으면 새로 생성)
csrfField() <input type="hidden"> HTML 태그 반환
csrfCheck() POST 요청의 CSRF 토큰 검증 (실패 시 403)
validateUpload($file) 업로드 파일 보안 검증 (MIME•확장자•이중확장자)
bcryptHash($password) 비밀번호 bcrypt 해시 생성
bcryptVerify($pw, $hash) 비밀번호 해시 검증
rateLimit($key, $max, $window) Rate Limit 검사 (초과 시 true 반환)
clientIp() 클라이언트 실IP 반환 (프록시 투과)
getRedis() Redis 인스턴스 반환 (없으면 null)
sanitize($input) HTML 특수문자 이스케이프
esc($str) HTML 출력 이스케이프 (= dx_esc)
 
// 사용 예시
$secure = Secure::getInstance();

// CSRF 보호 (폼)
echo $secure->csrfField();           // <input type="hidden" ...>
$secure->csrfCheck();                // POST 수신 시 검증

// Rate Limit
if ($secure->rateLimit("login_" . dx_ip(), 5, 60)) {
    dx_json(["error" => "너무 많은 시도"], 429);
}

// 업로드 검증
$err = $secure->validateUpload($_FILES["file"]);
if ($err) dx_json(["error" => $err], 400);


4-2. functions.php — 공통 헬퍼 함수 라이브러리

CMS 전체에서 사용하는 60여 개의 전역 함수를 정의합니다. 모든 함수는 dx_ 접두어를 사용합니다.


카테고리별 함수 목록

보안 난수
함수 설명
dx_random_bytes($length) PHP 7 random_bytes → OpenSSL → mcrypt 폴백 체인
dx_random_hex($length) 16진수 난수 문자열 생성

URL•경로 유틸
함수 설명
dx_base_url($path) 사이트 기본 URL 반환 (HTTPS 자동 감지)
dx_static_url($path) 정적 파일 URL 반환
dx_request_uri() 현재 요청 URI 반환 (Rewrite 환경 대응)
dx_current_url() 현재 전체 URL 반환
dx_redirect($url, $code) HTTP 리다이렉트 (기본 302)
dx_redirect_back($fallback) 이전 페이지로 리다이렉트
dx_realpath($path) Windows 백슬래시 통일 realpath
dx_path_inside($path, $base) 경로 이탈 공격 방어 검사

입력 처리
함수 설명
dx_get($key, $default, $type) $_GET 안전 읽기 (string/int/float/bool 타입 캐스팅)
dx_post($key, $default, $type) $_POST 안전 읽기
dx_request($key, $default, $type) $_REQUEST 안전 읽기
dx_method($method) 현재 HTTP 메서드 확인 (dx_method("POST"))

설정
함수 설명
dx_config($key, $default) DB 설정값 읽기 (캐시에서 조회)
dx_set_config($key, $value) 설정값 저장 (DB + 캐시 갱신)

출력•응답
함수 설명
dx_esc($str) HTML 출력 이스케이프 (htmlspecialchars)
dx_safe_url($url) URL 안전 이스케이프
dx_json($data, $code) JSON 응답 전송 후 exit
dx_error($msg, $code) HTTP 오류 응답 (기본 500)
dx_csrf_token() CSRF 토큰 문자열 반환
dx_csrf_field() CSRF hidden input HTML 반환
dx_csrf_check() CSRF 토큰 검증

문자열•날짜
함수 설명
dx_substr($str, $length, $suffix) mbstring 폴백 포함 문자열 자르기
dx_mb_substr($str, $start, $length) mb_substr PHP 5.6 폴백
dx_date($datetime, $format) 날짜 포맷 변환
dx_time_ago($datetime) "3분 전" 상대 시간 문자열
dx_filesize($bytes) 파일 크기 포맷 (KB/MB/GB)

플래시 메시지•로그
함수 설명
dx_set_flash($msg, $type) 플래시 메시지 저장 (세션)
dx_get_flash() 플래시 메시지 읽기 후 삭제
dx_log($message, $level) 로그 기록 (error/warning/info)

게시판 유틸
함수 설명
dx_board_posts($boardKey, $limit) 게시판 최신글 배열 반환
dx_board_latest($boardKey, $limit, $skin) 게시판 최신글 HTML 위젯 출력
dx_pagination($total, $perPage, $current, $urlPattern) 페이지네이션 HTML 생성
dx_upload_url($path) 업로드 파일 공개 URL 반환
dx_is_ajax() AJAX 요청 여부 확인


4-3. db/Database.php — PDO 래퍼 싱글턴

MySQL/MariaDB PDO 연결을 관리하는 싱글턴 클래스입니다. prefix 기반 테이블 관리, 안전한 파라미터 바인딩, 트랜잭션을 지원합니다.

주요 메서드
메서드 반환 타입 설명
getInstance() Database 싱글턴 인스턴스
connect($host, $name, $user, $pass) string prefix 붙인 테이블명 반환 (예: dx_posts)
row($sql, $params) array|null SELECT 단일 행
rows($sql, $params) array SELECT 전체 행
value($sql, $params) mixed SELECT 단일 값 (COUNT 등)
find($table, $conditions) array|null WHERE 조건으로 단일 행 조회
findAll($table, $conditions) array WHERE 조건으로 전체 행 조회
insertRow($table, $data) int 행 삽입, insert_id 반환
updateRow($table, $data, $conditions) int 행 수정, 영향 행 수 반환
deleteRow($table, $conditions) int 행 삭제
query($sql, $params) PDOStatement 직접 쿼리 실행
execute($sql, $params) PDOStatement 파라미터 바인딩 실행
beginTransaction() void 트랜잭션 시작
commit() void 트랜잭션 커밋
rollback() void 트랜잭션 롤백
tableExists($table) bool 테이블 존재 여부 확인
pdo() PDO PDO 인스턴스 직접 접근
 
$db = Database::getInstance();

// 단일 행 조회
$post = $db->row("SELECT * FROM `{$db->table('posts')}` WHERE id=?", [123]);

// 조건부 조회
$member = $db->find('members', ['login_id' => 'admin', 'status' => 1]);

// 삽입
$id = $db->insertRow('posts', [
    'title'      => '제목',
    'content'    => '내용',
    'created_at' => date('Y-m-d H:i:s'),
]);

// 트랜잭션
$db->beginTransaction();
try { /* ... */ $db->commit(); }
catch (Exception $e) { $db->rollback(); }


4-4. db/QueryBuilder.php — 빌더 패턴 쿼리

라라벨 Query Builder와 동일한 철학으로 구현된 쿼리 빌더입니다. 기존 Database 메서드와 100% 하위 호환됩니다.
 
/ 기본 사용 ($db->table()로 빌더 시작)
$posts = $db->table('posts')
    ->where('status', 1)
    ->orderBy('id', 'desc')
    ->paginate(20);

// 복합 조건
$members = $db->table('members')
    ->where('level', '>=', 5)
    ->orWhere('is_admin', 1)
    ->get();

// whereIn
$db->table('posts')->whereIn('id', [1, 2, 3])->first();

// JOIN
$db->table('posts')
    ->join('members', 'posts.member_id', '=', 'members.id')
    ->select(['posts.*', 'members.name'])
    ->get();


4-5. DxCache.php — 멀티 드라이버 캐시 (v5.0.0)

Redis → APCu → 파일 캐시 순서로 자동 드라이버를 선택합니다. 개발자는 드라이버 종류에 상관없이 동일한 API를 사용하면 됩니다.


드라이버 선택 우선순위

  • 1순위: Redis — REDIS_SESSION_URL 상수 설정 + Redis 익스텐션
  • 2순위: APCu — apc.enabled + apcu_fetch 함수 존재
  • 3순위: 파일 캐시 — data/cache/ 폴더 쓰기 가능
  • 4순위: none — 캐시 없이 동작 (모두 실패 시)

캐시 항목별 TTL
캐시 항목 TTL 무효화 시점
전체 설정 (dx_settings) 5분 설정 저장 시 전체 flush
게시판 목록 캐시 1분 게시글 작성/수정/삭제 시
사이트맵 XML 10분 게시글 변경 시

주요 메서드
메서드 설명
DxCache::get($key) 캐시 읽기 (없으면 null)
DxCache::set($key, $value, $ttl) 캐시 저장 (ttl=0 영구)
DxCache::delete($key) 캐시 삭제
DxCache::flush() 전체 캐시 삭제
DxCache::remember($key, $ttl, $callback) 없으면 콜백 실행 후 저장
DxCache::driver() 현재 사용 중인 드라이버명 반환
 
// 기본 사용
$settings = DxCache::get("dx_settings");
if ($settings === null) {
    $settings = $db->rows("SELECT * FROM dx_settings");
    DxCache::set("dx_settings", $settings, 300);
}

// remember 패턴 (더 간편)
$board = DxCache::remember("board_" . $id, 60, function() use ($id, $db) {
    return $db->find("boards", ["id" => $id]);
});


4-6. DxTheme.php — 테마 파일 해석기

테마 파일 경로를 결정하는 폴백 체인 엔진입니다. 현재 테마에 파일이 없으면 자동으로 default 테마로 폴백합니다.

폴백 체인
// 게시판 목록 예시: themes/my-theme/board/list.php 없으면
//                   themes/default/board/list.php 사용
$file = DxTheme::getInstance()->resolve("board/list.php");

주요 메서드
메서드 설명
resolve($relPath) 테마 파일 절대 경로 반환 (폴백 체인 적용)
resolveBoardSkin($skin, $action) 게시판 스킨 파일 경로 반환
getTheme() 현재 테마명 반환
getThemeDir() 현재 테마 폴더 절대 경로
getMeta($theme) theme.json 메타 배열 반환
getAll() 설치된 모든 테마 목록


4-7. router/Router.php + Dispatcher.php — URL 라우팅

Router는 URL을 파싱해 라우트 타입과 파라미터를 결정하고, Dispatcher는 라우트에 맞는 핸들러를 실행합니다.

Router 타입 상수
상수 URL 패턴 예시
TYPE_HOME home /
TYPE_BOARD board /free, /free/view/123, /free/write
TYPE_PAGE page /about, /contact
TYPE_ADMIN admin /admin, /admin/boards
TYPE_AUTH auth /auth/login, /auth/register
TYPE_API api /api/upload, /api/comment
TYPE_SEARCH search /?s=검색어
TYPE_404 404 존재하지 않는 경로


Dispatcher 실행 흐름

  1. Router::resolve() 호출 → 라우트 타입•파라미터 결정
  2. $GLOBALS["dx_route"] 에 라우트 정보 저장
  3. extend/middle/ 실행
  4. 라우트 타입에 따라 dispatchHome / dispatchBoard / dispatchAdmin 등 실행
  5. boards/handler.php 또는 DxTheme 폴백으로 파일 렌더링

URL Rewrite 없는 환경 지원
Apache mod_rewrite나 Nginx 없는 저가형 공유호스팅에서는 ?_url=/free/view/123 방식으로 자동 전환됩니다.


4-8. hook/HookManager.php — 훅 시스템

WordPress 훅과 유사한 액션/필터 시스템입니다. 훅에 콜백을 등록하면 해당 포인트에서 자동으로 실행됩니다.

주요 훅 포인트
훅 이름 위치 설명
dx_head   <head> 내부 커스텀 CSS/JS 태그 삽입
dx_body_bottom </body> 직전 공통 스크립트 삽입
dx_board_list_context 목록 컨텍스트 생성 후 목록 데이터 수정
dx_board_view_context 보기 컨텍스트 생성 후 게시글 데이터 수정
dx_board_after_save 게시글 저장 후 저장 후처리 (알림, 통계 등)
dx_admin_top 관리자 본문 상단 관리자 페이지 커스텀
dx_editor_render 에디터 렌더링 시 에디터 커스텀
dx_extend_top extend/top/ 실행 후 추가 초기화
dx_extend_middle extend/middle/ 실행 후 라우팅 후 처리
dx_extend_bottom extend/bottom/ 실행 후 렌더링 후 처리
 
// 훅 등록
dx_add_hook("dx_head", function() {
    echo '<link rel="stylesheet" href="/my.css">';
}, 10); // 세 번째 인자: 우선순위 (낮을수록 먼저)

// 필터 훅 (값 변형)
dx_add_filter("dx_board_list_context", function($ctx) {
    $ctx["extra_data"] = "추가 데이터";
    return $ctx;
});

// 훅 실행 (코어에서 호출)
dx_run_hook("dx_head");
$ctx = dx_apply_filter("dx_board_list_context", $ctx);


4-9. auth/Auth.php — 세션 기반 인증

로그인•로그아웃•회원 정보 관리를 담당합니다. 세션에 사용자 정보를 저장하고, 권한 검사 메서드를 제공합니다.

주요 메서드
메서드 설명
getInstance() 싱글턴 인스턴스
login($loginId, $password) 로그인 처리, 성공 시 세션 저장
logout() 로그아웃 (세션 파괴)
check() 로그인 여부 확인 (bool)
user() 현재 로그인 회원 배열 반환
id() 현재 회원 ID 반환
isAdmin() 관리자 여부 확인
can($permission) 특정 권한 확인
loginById($memberId) 관리자 대리 로그인
refresh() 세션의 회원 정보 갱신 (프로필 수정 후)
 
$auth = Auth::getInstance();

if (!$auth->check()) {
    dx_redirect("/auth/login");
}

$user = $auth->user();
echo $user["nickname"] . "님 환영합니다.";

if ($auth->isAdmin()) {
    // 관리자 전용 코드
}


4-10. DxSanitizer.php — HTML 입력 정제

에디터로 작성된 HTML을 서버사이드에서 XSS 공격으로부터 보호합니다. 허용 태그 화이트리스트 방식으로 동작하며, script•iframe 등 위험 태그는 완전 차단합니다.

화이트리스트 허용 태그

텍스트: p, br, b, strong, i, em, u, s, strike, del 구조: h1~h6, ul, ol, li, blockquote, pre, code 링크/미디어: a, img, video, source 테이블: table, thead, tbody, tfoot, tr, th, td 기타: span, div, hr, sup, sub, figure, figcaption

차단 태그

script, iframe, object, embed, form, input, style, link, meta, svg, canvas, frame


주요 메서드
메서드 설명
DxSanitizer::html($content) 에디터 HTML 정제 (화이트리스트 필터링)
DxSanitizer::text($input) 일반 텍스트 정제 (태그 완전 제거)
DxSanitizer::filename($filename) 파일명 안전하게 정제
DxSanitizer::url($url) URL 안전성 검증


4-11. DxSeo.php — SEO 메타 자동 생성

페이지 타입(게시글•목록•홈 등)에 따라 title, description, OG 태그, Twitter Card, JSON-LD 구조화 데이터를 자동 생성합니다.

지원 페이지 타입
타입 값 해당 페이지 자동 생성 내용
board_view 게시글 보기 제목, 본문 앞 150자 설명, 첫 이미지 OG, Article JSON-LD
board_list 게시판 목록 게시판명 + 카테고리 title, 게시판 설명
page 정적 페이지 페이지 title, 설명
home 홈 페이지 사이트명, 기본 설명, 기본 OG 이미지
search 검색 결과 noindex 자동 설정


자동 처리 항목

  • 비밀글 → noindex 자동 설정
  • ?s= 검색 결과 → noindex 자동 설정
  • canonical URL → 쿼리스트링 제거
  • 본문 첫 이미지 → OG 이미지 자동 추출
  • Google Analytics ID → 레이아웃 자동 삽입
  • 멀티도메인 → 도메인별 독립 사이트맵/canonical


4-12. DxCategory.php — 카테고리 렌더링

게시판 카테고리를 DB에서 조회하고, 계층 트리 구조로 변환하며, 스킨 파일로 렌더링합니다.


카테고리 스킨 우선순위

// 우선순위 (높은 것부터)
1. themes/[테마]/category/list.php     ← 테마별 커스텀
2. boards/category/skins/[스킨]/list.php ← 지정 스킨
3. boards/category/skins/default/list.php ← 기본 폴백


주요 메서드
메서드 설명
getByBoard($boardId, $showIn) 게시판 카테고리 목록 (showIn: list/view/전체)
buildTree($rows, $parentId) 평면 배열 → 계층 트리 변환
flattenTree($tree, $depth) 트리 → select 옵션용 평면 배열 (들여쓰기 포함)
renderTabs($boardId, $skin, $active) 카테고리 탭 HTML 렌더링


4-13. DxSite.php — 멀티사이트 관리

같은 DB와 코드베이스로 여러 도메인을 운영할 수 있게 합니다. 도메인을 감지하고, dx_sites 테이블에서 해당 도메인의 설정을 로드해 전역 $dx_config를 오버라이드합니다.
 
// dx_sites 테이블 예시
// domain          | theme   | menu_group | site_name
// example.com     | default | main       | 메인사이트
// shop.example.com| clean   | shop       | 쇼핑몰
// blog.example.com| simple  | blog       | 블로그


도메인별 독립 항목

  • 사이트명•설명•기본 URL
  • 활성 테마
  • 메뉴 그룹
  • 언어•시간대
  • SEO 사이트맵 (각 도메인 기준으로 독립 생성)


4-14. DxExtend.php — extend/ 폴더 자동 실행

extend/ 폴더의 PHP 파일을 지정된 시점에 자동으로 실행하는 엔진입니다. 파일명 오름차순 실행, 에러 격리, 하위 폴더 재귀 탐색을 지원합니다.
 
// 실행 포인트 예시
// extend/top/01_maintenance.php  — 점검 모드
if (file_exists(DX_ROOT . "/maintenance.flag")) {
    header("HTTP/1.1 503 Service Unavailable");
    echo "점검 중입니다.";
    exit;
}

// extend/middle/01_visit_tracker.php — 방문자 로그 (기본 포함)
// extend/bottom/99_perf_log.php      — 성능 측정


4-15. DxPoint.php — 포인트/경험치/레벨

회원 활동에 따른 포인트 지급/차감, 경험치 누적, 레벨 계산을 담당합니다. 레벨은 1(새싹)~15(전설왕)까지 있습니다.

기본 포인트 규칙
활동 타입 포인트 경험치
signup (회원가입) 10 20
login (로그인) 1 2
write (글쓰기) 5 10
comment (댓글) 2 5
like_recv (좋아요 받음) 1 2
scrap_recv (스크랩 받음) 1 -


레벨 임계값 (누적 경험치 기준)

Lv.1(0) → Lv.2(50) → Lv.3(150) → Lv.4(350) → Lv.5(700) → Lv.6(1,200) → Lv.10(8,000) → Lv.15(50,000)


주요 메서드
메서드 설명
DxPoint::add($memberId, $type, $point) 포인트 지급/차감 (0이면 규칙 자동 적용)
DxPoint::addExp($memberId, $type, $exp) 경험치 지급 + 레벨업 처리
DxPoint::getPoint($memberId) 현재 포인트 잔액
DxPoint::getExp($memberId) 현재 누적 경험치
DxPoint::getLevel($memberId) 현재 레벨 숫자
DxPoint::getLevelName($level) 레벨 이름 문자열
DxPoint::getLevelInfo($memberId) 레벨•경험치•다음레벨 까지 정보 배열


4-16. DxNotification.php — 실시간 알림

댓글•친구추가•스크랩•쪽지 등의 이벤트를 DB에 저장하고, DXMB socket 플러그인이 활성화된 경우 실시간 push를 보냅니다.

알림 타입 상수
상수 발생 시점
TYPE_COMMENT comment 내 게시글에 댓글 달림
TYPE_COMMENT_REPLY comment_reply 내 댓글에 답글 달림
TYPE_FRIEND friend 친구 추가됨
TYPE_SCRAP scrap 내 게시글이 스크랩됨
TYPE_MEMO memo 쪽지 수신
 
// 알림 전송 예시
DxNotification::add(
    $postAuthorId,    // 수신자 member.id
    $commentAuthorId, // 발신자 member.id
    DxNotification::TYPE_COMMENT,
    $commenterName . "님이 댓글을 남겼습니다.",
    dx_base_url($board["board_key"] . "/view/" . $postId)
);


4-17. DxSocialAuth.php — 소셜 로그인

카카오•네이버•구글•GitHub OAuth2 소셜 로그인을 처리합니다. 각 제공자의 API 키는 관리자 설정에서 입력합니다.
 
제공자 필요 설정 키 특이사항
kakao social_kakao_client_id/secret 카카오톡 공유 스크랩도 봇 허용
naver social_naver_client_id/secret Naver Login API 사용
google social_google_client_id/secret Google OAuth 2.0
github social_github_client_id/secret GitHub OAuth Apps

주요 메서드
메서드 설명
providers() 지원 제공자 목록 배열
enabledProviders() 관리자에서 활성화된 제공자만 반환
getAuthUrl($provider) OAuth 인증 URL 생성
handleCallback($provider, $code) 콜백 코드로 사용자 정보 수신•로그인 처리
providerMeta($provider) 제공자 표시명•색상•아이콘 정보


4-18. DxContainer.php — 서비스 컨테이너 (DI)

라라벨 Service Container와 동일한 철학으로 구현된 경량 DI 컨테이너입니다. 기존 getInstance() 싱글턴과 100% 호환됩니다. 
// 바인딩
dx_app()->bind("mailer", function() {
    return new MyMailer(dx_config("smtp_host"));
});

// 싱글턴 바인딩
dx_app()->singleton("sms", function() {
    return new AlimtalkSMS(dx_config("alimtalk_key"));
});

// 꺼내 쓰기
$mailer = dx_make("mailer");
$mailer->send("to@example.com", "제목", "내용");

// 컨트롤러 자동 의존성 주입
dx_app()->call("BoardController@index");


4-19. DxMarket.php — 마켓 클라이언트

designonex.com 중앙 마켓 서버에서 플러그인과 테마를 검색•설치합니다. SHA-256 해시 검증으로 파일 무결성을 보장합니다.


설치 흐름

  1. getMarket() → 마켓에서 플러그인/테마 목록 탐색
  2. installItem() → 중앙 서버에서 download_url + file_hash 수신
  3. 개발자 서버에서 ZIP 직접 다운로드
  4. SHA-256 해시 검증 후 설치


4-20. PluginRegistry.php — 플러그인 등록소

플러그인이 자신의 타입(editor•payment•captcha•sms 등)을 등록하면, 관리자 설정 화면에 자동으로 선택 옵션이 나타납니다.

지원 플러그인 타입
타입 용도 활성 설정 키
editor 게시글 작성 에디터 active_editor
payment 결제 모듈 active_payment
captcha CAPTCHA 인증 active_captcha
sms SMS 발송 active_sms
socket 실시간 WebSocket active_socket
(임의) 개발자 정의 타입 (임의 설정 키)


5. 요청 처리 전체 흐름

브라우저에서 요청이 들어와 응답이 나가기까지의 전체 과정입니다.
 
브라우저 → HTTP 요청
         ↓
.htaccess / web.config / Nginx → index.php 로 모든 요청 전달
         ↓
index.php
  1. DX_CMS 상수 정의 (직접 접근 차단용)
  2. data/config.php 로드 (DB 접속 정보)
  3. core 클래스 파일 require (Secure, functions, Database, ...)
  4. Secure::initSession()  — 세션 + 보안 헤더
  5. Secure::WAF 검사      — SQL Injection, XSS 패턴 탐지
  6. Database::connect()    — DB 연결
  7. 설정 로드 (dx_settings 테이블 → DxCache)
  8. DxSite::getInstance()  — 멀티사이트 도메인 감지
  9. DxTheme::getInstance()  — 테마 결정
 10. load_plugins()           — plugins/ 플러그인 로드
 11. DxExtend::runTop()       — extend/top/ 실행
         ↓
Router::resolve()   — URL → 라우트 타입•파라미터 결정
         ↓
DxExtend::runMiddle() — extend/middle/ 실행
         ↓
Dispatcher::dispatch()
  ├─ home   → themes/[테마]/page/home.php
  ├─ board  → boards/handler.php → 스킨 파일
  ├─ page   → 정적 페이지 렌더링
  ├─ admin  → admin/[섹션]/index.php
  ├─ auth   → core/auth/[페이지].php
  ├─ api    → core/api/[핸들러].php
  └─ 404    → themes/[테마]/page/404.php
         ↓
DxExtend::runBottom() — extend/bottom/ 실행
         ↓
ob_end_flush() → 브라우저로 응답 전송


6. 확장 개발 가이드

DxCMS의 세 가지 확장 방법과 각각의 적합한 사용 사례를 정리합니다.
방법 난이도 적합한 경우 파일 위치
extend/ 쉬움 점검모드, IP차단, 방문 로그, 간단한 초기화 extend/top|middle|bottom/
훅(Hook) 보통 데이터 변형, 헤더/푸터 삽입, 저장 후 처리 plugin.php 또는 extend 파일
플러그인 어려움 에디터, 결제, SMS, 소켓 등 독립 기능 모듈 plugins/my-plugin/


6-1. 커스텀 테마 만들기

  • themes/my-theme/ 폴더 생성
  • theme.json 파일 생성 (이름•버전 정보)
  • 변경하고 싶은 파일만 추가 (없는 파일은 default 테마 자동 폴백)
  • 관리자 > 테마 관리에서 활성화


6-2. 게시판 커스텀 스킨 만들기

  • boards/skins/my-skin/ 폴더 생성
  • skin.json 파일 생성 (스킨 이름•버전)
  • list.php, view.php, write.php 생성
  • 관리자 > 게시판 관리에서 해당 게시판에 스킨 지정


6-3. 플러그인 개발 3단계

  • Step 1: plugins/my-plugin/ 폴더와 plugin.php 생성
  • Step 2: plugin.php에서 dx_register_plugin() 호출
  • Step 3: 해당 타입의 훅(dx_editor_init 등)에서 기능 구현
// plugins/my-editor/plugin.php
dx_register_plugin(array(
    'id'      => 'my-editor',
    'type'    => 'editor',
    'name'    => 'My Custom Editor',
    'version' => '1.0.0',
));

dx_add_hook('dx_editor_render', function() {
    echo '<script src="/plugins/my-editor/editor.js"></script>';
});


7. 보안 체크리스트

항목 구현 방법 담당 파일
CSRF 방어 모든 POST 폼에 dx_csrf_field() 삽입, 수신 시 dx_csrf_check() Secure.php
XSS 방어 출력 시 dx_esc(), 에디터 HTML은 DxSanitizer::html()

Secure.php,
DxSanitizer.php

SQL Injection PDO 파라미터 바인딩 (? 플레이스홀더) Database.php
업로드 보안 MIME+확장자 이중 검증, 이중확장자 차단, 업로드 디렉토리 PHP 실행 차단 Secure.php,
core/api/upload.php
경로 이탈 방어 dx_path_inside() 로 업로드•다운로드 경로 검증 functions.php
Rate Limit Secure::rateLimit() 또는 Secure.php 자동 적용 Secure.php
WAF SQL/XSS 패턴 자동 탐지 (에디터 필드 제외) Secure.php
세션 보안 HttpOnly•Secure•SameSite=Lax 자동 설정 Secure.php
data/ 보안 .htaccess로 PHP 실행 + 디렉토리 리스팅 차단 data/.htaccess
install/ 보안 설치 후 폴더 삭제 -

✅ 보안 패치가 필요한 경우 core/Secure.php 파일 하나만 교체하면 됩니다. 이 파일은 다른 CMS 기능과 분리되어 있습니다.


8. 캐시 및 성능 최적화


8-1. 동접 1만명 권장 서버 구성

컴포넌트 설정 권장값 효과
PHP OPcache opcache.enable=1,
emory_consumption=256
PHP 파싱 캐시 → 응답 2~5배 향상
PHP-FPM pm.max_children=200~500 동시 요청 처리 수 증가
Redis REDIS_SESSION_URL 설정 설정•게시판 캐시 메모리 저장
MySQL innodb_buffer_pool_size=RAM 70% DB 쿼리 캐시
Nginx 정적파일 CSS/JS/이미지 직접 서빙 PHP 히트 감소
Cloudflare CDN 앞단 CDN 적용 실제 PHP 히트 80% 감소


8-2. 세션 최적화

비로그인 GET 요청은 세션을 시작하지 않습니다. 이로 인해 파일 lock이 제거되어 동시 처리 성능이 향상됩니다.


8-3. 캐시 자동 무효화

설정 저장 → 전체 캐시 flush
게시글 작성/수정/삭제 → 해당 게시판 목록 캐시 삭제
카테고리 변경 → 전체 게시판 목록 캐시 삭제



 

댓글0

로그인 후 댓글을 작성할 수 있습니다.
22
전체 회원
69
전체 게시글
46
전체 댓글
569
오늘 방문
47,886
전체 방문
0
현재 접속
인기글 7일 이내
최신글
최신댓글