회원가입 | 고객센터 |
DESIGNONEX
디자인원엑스
About
Service
Q&A
PR리그
자유게시판N
갤러리
포인트게임
공지사항N
통계
로그인 회원가입
고객센터
3.10 모듈 로딩 구조

자동 로딩 구조

A Administrator
2026.04.21 01:03(수정됨) 102 0

1. 개요

DXCMS v8.1.0은 단일 진입점(index.php) 기반의 PHP 프레임워크로, PHP 5.6부터 8.x까지의 광범위한 버전 호환성을 유지하면서 모던 CMS 기능을 제공합니다. 모든 HTTP 요청은 index.php를 통과하며, 이 과정에서 엄격히 순서화된 자동 로딩 메커니즘이 동작합니다.


📌  자동 로딩의 핵심 철학

  • 단일 진입점(Single Entry Point): 모든 요청이 index.php를 통해 처리됩니다.
  • 순서 보장(Ordered Loading): 의존성 순서대로 클래스/함수가 로드됩니다.
  • 격리(Isolation): 플러그인•확장 오류가 전체 시스템에 영향을 주지 않습니다.
  • 보안 우선(Security First): 보안 클래스가 다른 모든 초기화보다 먼저 실행됩니다.


2. 전체 부트스트랩 흐름

index.php는 요청을 처리하기 위해 아래 5단계를 순서대로 실행합니다. 각 단계는 이전 단계가 완료된 이후에만 실행됩니다.
 
단계 이름 주요 작업
STEP 1 클래스/함수 정의 로드 functions.php, DxCache, Secure.php, DxSanitizer, Database, HookManager, PluginRegistry, Auth 및 핵심 클래스 파일들을 require_once로 로드
STEP 2 보안 초기화 세션 설정 → 세션 시작(조건부) → 보안 헤더 발행 → CSRF 토큰 발급
STEP 3 DB 연결 + 설정 로드 data/config.php 로드 → DB 연결 → 시크릿 키 주입
STEP 4 DB 연결 후 초기화 HookManager → PluginRegistry → 플러그인 로드 → DxSite → DxTheme → Auth → DI 컨테이너 → DxExtend → extend/top/ 실행
STEP 5 라우팅 + 디스패치 routes/*.php 자동 로드 → DxRouter 매칭 시도 → 폴백: 파일 기반 Dispatcher → extend/bottom/ 실행


3. STEP 1 — 클래스/함수 정의 로드

STEP 1은 실행 없이 정의만 메모리에 올리는 단계입니다. 실제 동작은 STEP 2~4에서 이루어지며, STEP 1에서는 어떤 로직도 실행되지 않습니다.


3.1 로딩 순서

# 파일 역할 / 우선 로딩 이유
1 core/functions.php 전역 헬퍼 함수 정의 (dx_config, dx_log, load_plugins 등) — 다른 클래스가 이 함수들에 의존하므로 최우선 로드
2 core/DxCache.php 성능 최적화 우선 로드 — config.php 캐싱에 필요하여 DB 연결 전에 반드시 로드
3 core/security/{hash}/Secure.php 보안 전담 클래스 — 고유 해시 경로로 위치 예측 불가, 설치 시 생성된 경로에서 로드 (폴백: core/Secure.php)
4 core/DxSanitizer.php 입력값 정제(Sanitize) 클래스
5 core/db/Database.php DB 연결 클래스 (config.php 로드 전 클래스 정의만)
6 core/hook/HookManager.php 훅 시스템 (dx_add_hook, dx_run_hook 함수 정의)
7 core/PluginRegistry.php 플러그인 타입 등록소
8 core/auth/Auth.php 인증 클래스 (세션 검증 로직)
9 core/DxPoint.php ~ DxBoardSkin.php 각종 기능 클래스 (포인트, 친구, 샵, 사이트, 테마, SEO, 카테고리, 썸네일, 알림, 회원모니터, 팝업, 게시판스킨, 마켓)
10 core/DxSocialAuth.php 소셜 로그인 클래스 (파일 존재 시에만 로드)
11 core/DxExtend.php extend/ 폴더 자동 실행 엔진
12 core/router/Router.php 기존 파일 기반 라우터
13 core/router/Dispatcher.php 기존 디스패처
14 core/db/QueryBuilder.php QueryBuilder + dx_db() 헬퍼 (v6.2.0+)
15 core/DxContainer.php DI 컨테이너 (v6.2.0+)
16 core/DxRouter.php 클래스 기반 라라벨 스타일 라우터 (v6.2.0+)


3.2 보안 경로 해시 메커니즘

Secure.php는 설치 시 생성된 16자리 랜덤 해시를 경로로 사용합니다. 이 구조는 파일 경로 예측을 통한 직접 접근 공격을 방어합니다.
 
// data/config.php에 정의된 보안 경로 예시
define('DX_SECURITY_PATH', 'a1b2c3d4e5f6a7b8');  // 16자리 랜덤 해시

// 실제 로드 경로
// core/security/a1b2c3d4e5f6a7b8/Secure.php

// 폴백 처리 (파일 손실 또는 신규 설치 시)
if (!file_exists($_dxSecurePath)) {
    $_dxSecurePath = DX_CORE . '/Secure.php';
}

💡  DxCache 최우선 로드의 이유
DxCache는 STEP 1에서 가장 먼저 로드되는 비-함수 클래스입니다. 이는 다음 STEP 3에서 data/config.php를 로드할 때 설정 값을 파일 캐시로 빠르게 읽어오는 기능이 필요하기 때문입니다. DxCache가 없으면 매 요청마다 config.php를 파싱해야 합니다.

 
경로 패턴 세션 필요 이유
/admin 관리자 인증 상태 확인
/auth 로그인/로그아웃/회원가입 처리
/view/ 조회수 중복 방지 (같은 사용자가 새로고침해도 조회수 증가 방지)
/api/ 로그인 여부 확인이 필요한 AJAX API
/write 게시글 작성 권한 확인
/edit 게시글 수정 권한 확인
/reply 답글 작성 권한 확인


4.2 보안 헤더 자동 발행

Secure::sendSecurityHeaders()는 .htaccess나 web.config 없이도 저가형 공유 호스팅 환경에서 보안 헤더를 보장합니다.
  • Content-Security-Policy (CSP)
  • X-Frame-Options: SAMEORIGIN
  • X-Content-Type-Options: nosniff
  • Referrer-Policy
  • Permissions-Policy


5. STEP 3 — DB 연결 및 설정 로드

data/config.php를 require_once로 로드합니다. config.php 내부에서 DB 연결($db->connect())이 실행되므로, 이 시점부터 데이터베이스 쿼리가 가능해집니다.


5.1 시크릿 키 주입 (STEP 3-B)

DB 연결 직후, secret_key 기반으로 세션/CSRF/RateLimit 키 이름을 동적으로 도출합니다. 소스코드를 공개해도 키 이름을 예측할 수 없는 구조입니다.
 
// data/config.php에서 로드되는 핵심 상수들
define('DB_HOST',          'localhost');
define('DB_NAME',          'my_database');
define('DX_SITE_URL',      'https://example.com');
define('DX_SECURITY_PATH', 'a1b2c3d4e5f6a7b8');  // 보안 경로 해시
define('DX_SECRET_KEY',    '랜덤64자리키...');     // 시크릿 키

// Secure 클래스가 secret_key로 키 이름을 동적 생성
$_dxSecure->initSecretKeys($_dxSecretVal);


6. STEP 4 — 플러그인 및 확장 자동 로딩

가장 복잡한 단계입니다. DB 연결 완료 후 CMS의 확장 시스템이 순서대로 초기화됩니다.


6.1 초기화 순서

# 호출 이름 설명
1 HookManager::getInstance() 훅 시스템 인스턴스 생성 훅은 플러그인 로딩 전에 반드시 준비되어 있어야 합니다.
2 PluginRegistry::getInstance() 플러그인 타입 등록소 인스턴스 생성 editor, payment, captcha, sms 등의 타입 정의 초기화
3 load_plugins() 플러그인 자동 로드 ★ plugins/**/plugin.php 파일을 모두 require_once
4 _dx_register_point_hooks() 포인트 훅 등록 게시글 작성/삭제/댓글 등 포인트 지급 훅 일괄 등록
5 DxSite::getInstance() 멀티사이트 설정 적용 도메인별 설정을 $dx_config에 덮어씁니다.
6 DxTheme::getInstance() 테마 엔진 초기화 DxSite 이후 실행 (테마 확정 후 초기화)
7 Auth::getInstance() 인증 초기화 DB 연결 후 세션 검증, 로그인 상태 확인
8 DxContainer::getInstance()->registerCoreServices() DI 컨테이너 핵심 서비스 등록 db, auth, secure, cache, hook, seo, site, theme 등록
9 DxExtend::getInstance()->ensureDirs() extend/ 폴더 자동 생성 top/, middle/, bottom/ 폴더 없으면 자동 생성
10 dx_add_hook(팝업/모니터링) 시스템 훅 등록 팝업 자동출력, 로그인/로그아웃 모니터링, last_seen 갱신 훅 등록
11 DxExtend::runTop() extend/top/ 파일 자동 실행 사용자 커스텀 코드 실행 (점검모드, IP차단 등)

6.2 플러그인 자동 로드 (load_plugins)

load_plugins() 함수는 plugins/ 디렉터리의 모든 서브폴더를 탐색하여 plugin.php 파일을 자동으로 로드합니다.
 
function load_plugins()
{
    if (!defined('DX_PLUGINS') || !is_dir(DX_PLUGINS)) return;
    $dirs = glob(DX_PLUGINS . '/*', GLOB_ONLYDIR);
    if (!$dirs) return;
    foreach ($dirs as $dir) {
        $f = $dir . '/plugin.php';
        if (file_exists($f)) {
            require_once $f;  // 각 플러그인의 진입점 로드
        }
    }
    // DXB CSS 엔진 자동 주입
    _dx_inject_dxb_css();
    // 에디터 훅 브릿지 등록
    dx_add_hook('dx_editor_init', function($args) { ... }, 10);
}


플러그인 디렉터리 구조:

plugins/
  my-editor/
    plugin.php          ← load_plugins()가 자동 로드하는 진입점
    editor.js
    style.css
  kg-inicis/
    plugin.php
    inicis.php


6.3 PluginRegistry — 플러그인 타입 등록소

각 플러그인은 plugin.php 내에서 dx_register_plugin()을 호출하여 자신의 "타입"을 등록합니다. 관리자 설정 화면에 해당 타입의 선택 박스가 자동으로 나타납니다.
 
타입 ID 라벨 설정 키 용도
editor 에디터 active_editor TinyMCE, CKEditor, Quill 등 게시글 편집기
payment 결제 모듈 active_payment KG이니시스, 토스페이 등 PG사 연동
captcha CAPTCHA active_captcha reCAPTCHA v2/v3, hCaptcha, Turnstile
sms SMS 발송 active_sms 알리고, 네이버 클라우드 SMS 등
social_login 소셜 로그인 active_social_login 카카오, 네이버, 구글, GitHub OAuth
socket 실시간 소켓 active_socket WebSocket 기반 실시간 채팅·모니터링


6.4 DxContainer — 경량 DI 컨테이너

DxContainer는 Laravel의 Service Container와 동일한 철학으로 설계된 PHP 5.6 호환 경량 DI 컨테이너입니다. 기존 getInstance() 싱글턴 패턴을 유지하면서 추가적인 의존성 주입을 지원합니다.


자동 등록되는 핵심 서비스

서비스 키 클래스 별칭 / 설명
db Database::getInstance() 별칭: database — 쿼리빌더, 직접 쿼리 모두 지원
auth Auth::getInstance() 로그인 상태, 회원 정보 접근
secure Secure::getInstance() 보안 헤더, CSRF, 세션 관리
cache DxCache (클래스명) static 메서드 기반 파일 캐시
hook HookManager::getInstance() 별칭: hooks — 훅 등록/실행
seo DxSeo (클래스명) title, description, OG 태그 등
site DxSite::getInstance() 멀티사이트 설정 관리
theme DxTheme::getInstance() 테마 경로, 변수 관리


컨트롤러 자동 로드 경로

DxContainer::call()로 컨트롤러를 호출할 때, 클래스가 없으면 다음 경로를 순서대로 탐색합니다.
  • controllers/{ClassName}.php
  • controllers/{lowercase_name}.php (예: BoardController → board.php)
  • core/controllers/{ClassName}.php
  • plugins/*/controllers/{ClassName}.php (플러그인 컨트롤러)
// 컨트롤러 자동 의존성 주입 사용 예시
dx_app()->call('BoardController@index', ['slug' => 'free']);

// 서비스 바인딩 (플러그인에서)
dx_app()->singleton('mailer', function() {
    return new MyMailer(dx_config('smtp_host'));
});

// 서비스 꺼내기
$mailer = dx_make('mailer');


6.5 DxExtend — extend/ 폴더 자동 실행 엔진

DxExtend는 파일을 지정된 폴더에 넣는 것만으로 코드를 자동 실행할 수 있는 노-코드 확장 시스템입니다. 훅(Hook)이 개발자 코드에서 등록하는 방식인 것과 달리, DxExtend는 파일 배치만으로 동작합니다.
 
슬롯 실행 시점 주요 용도
extend/top/ 모든 초기화(DB·세션·Auth) 완료 직후, 라우팅 전 점검 모드, IP 차단, 커스텀 인증, 글로벌 변수 주입, 방문자 제한
extend/middle/ 라우트 확정 직후, 실제 핸들러 실행 전 방문자 로그, A/B 테스트, 접근 로그, 라우트별 처리 ($GLOBALS['dx_route'] 사용 가능)
extend/bottom/ 렌더링 완료 후, ob_end_flush() 직전 캐시 저장, 성능 로그, 정리 작업


파일 수집 및 실행 규칙

  • 폴더 내 *.php 파일을 파일명 오름차순으로 자동 수집
  • 파일명으로 실행 순서 제어 가능: 01_init.php → 02_log.php → 03_custom.php
  • 하위 폴더도 1단계까지 재귀 탐색
  • 에러 발생해도 다른 파일 계속 실행 (set_error_handler로 격리)
  • 보안: extend/ 내부 파일만 실행 (realpath 검증으로 경로 탈출 방지)
extend/
  top/
    01_maintenance.php   // 점검 모드 체크
    02_ip_block.php      // IP 차단
    03_custom_auth.php   // 커스텀 인증
  middle/
    01_access_log.php    // 방문자 로그
  bottom/
    01_cache_save.php    // 캐시 저장
    02_perf_log.php      // 성능 로그


7. STEP 5 — 라우팅 및 디스패치

모든 초기화가 완료된 후 요청 URL에 맞는 핸들러를 찾아 실행합니다. DXCMS는 두 가지 라우팅 방식을 지원하며, DxRouter(클래스 기반) → Dispatcher(파일 기반) 순으로 폴백됩니다.


7.1 routes/ 폴더 자동 로드

routes/ 폴더의 모든 .php 파일을 파일명 오름차순으로 자동 로드합니다.
 
$_dxRouteDir   = DX_ROOT . '/routes';
$_dxRouteFiles = glob($_dxRouteDir . '/*.php');
sort($_dxRouteFiles);  // 파일명 오름차순 정렬
foreach ($_dxRouteFiles as $_dxRouteFile) {
    require_once $_dxRouteFile;
}

// routes/web.php 예시
DxRouter::get('/mypage/dashboard', 'MemberController@dashboard')
         ->middleware('auth');
DxRouter::post('/api/update', 'MemberController@update')
         ->middleware(['auth', 'csrf']);


7.2 이중 라우팅 폴백 구조

라우터 동작 방식 설명
DxRouter (1순위) routes/*.php에서 등록된 URI 패턴 매칭 Laravel 스타일 — GET/POST/PUT/PATCH/DELETE, 그룹, 미들웨어, 리소스 라우트 지원 (v6.2.0+)
Dispatcher (폴백) URI를 파일 경로로 변환하여 해당 PHP 파일 실행 기존 파일 기반 라우팅 유지 — DxRouter에 매칭 라우트가 없을 때만 실행


7.3 DxRouter 지원 HTTP 메서드

메서드 함수 설명
GET DxRouter::get($uri, $action) 조회 요청
POST DxRouter::post($uri, $action) 생성 요청
PUT DxRouter::put($uri, $action) 전체 수정
PATCH DxRouter::patch($uri, $action) 부분 수정
DELETE DxRouter::delete($uri, $action) 삭제 요청
GET+POST DxRouter::any($uri, $action) GET과 POST 동시 등록
REST DxRouter::resource($uri, $controller) index/show/store/update/destroy 자동 등록


8. HookManager — 훅 시스템

HookManager는 WordPress 스타일의 훅/필터 시스템을 구현합니다. 플러그인과 테마가 CMS 동작을 수정할 수 있는 핵심 확장 메커니즘입니다.


8.1 훅 유형

유형 함수 설명
Action dx_add_hook() / dx_run_hook() 반환값 없이 동작을 수행. 예: 로그인 후 포인트 지급, 게시글 저장 후 알림 발송
Filter dx_add_filter() / dx_apply_filter() 값을 변형하여 반환. 예: 게시글 내용 필터링, URL 변환, HTML 정제


8.2 표준 훅 포인트

각 페이지 렌더링 시 dx_hook_top(), dx_hook_middle(), dx_hook_bottom() 함수가 자동으로 호출됩니다. 이 함수들은 전역 훅 외에 페이지 타입별, 슬러그별 훅도 연쇄 실행합니다.
 
함수 실행되는 훅 예시
dx_hook_top($context) dx_top dx_{type}_top dx_page_{slug}_top dx_top, dx_board_top, dx_page_free_top — 전역→타입별→슬러그별 순으로 실행
dx_hook_middle($context) dx_middle dx_{type}_middle dx_page_{slug}_middle dx_middle, dx_board_middle, dx_page_free_middle
dx_hook_bottom($context) dx_bottom dx_{type}_bottom dx_page_{slug}_bottom dx_bottom, dx_board_bottom, dx_page_free_bottom


8.3 우선순위 정렬

dx_add_hook()의 세 번째 파라미터로 priority를 지정합니다. 숫자가 낮을수록 먼저 실행됩니다. 기본값은 10입니다.
 
// 우선순위 예시
dx_add_hook('dx_after_login', function($args) {
    // priority 5: 다른 훅보다 먼저 실행
    record_login_log($args['user']['id']);
}, 5);

dx_add_hook('dx_after_login', function($args) {
    // priority 20: 나중에 실행
    DxMemberMonitor::onLogin($args['user']['id']);
}, 20);


9. 자동 로딩 구조 전체 요약

아래 다이어그램은 HTTP 요청부터 응답까지의 전체 자동 로딩 흐름을 요약합니다.
 
HTTP 요청
    │
    ▼
┌─────────────────────────────────────────────────────────┐
│  index.php (단일 진입점)                                │
│                                                         │
│  [STEP 1] 클래스/함수 정의 로드                         │
│    functions.php → DxCache → Secure → DxSanitizer       │
│    → Database → HookManager → PluginRegistry → Auth     │
│    → 기능 클래스들 → DxExtend → Router → DxContainer    │
│                                                         │
│  [STEP 2] 보안 초기화                                   │
│    Secure::initSession() → startSession() → 보안헤더    │
│    → CSRF 토큰 발급                                     │
│                                                         │
│  [STEP 3] DB 연결 + 설정 로드                           │
│    data/config.php 로드 → DB 연결 → 시크릿키 주입       │
│                                                         │
│  [STEP 4] DB 연결 후 초기화                             │
│    HookManager → PluginRegistry → load_plugins()        │
│    → DxSite → DxTheme → Auth → DxContainer              │
│    → DxExtend::ensureDirs() → extend/top/ 실행          │
│                                                         │
│  [STEP 5] 라우팅 + 디스패치                             │
│    routes/*.php 로드 → DxRouter::dispatch()             │
│    → 매칭 실패 시: Dispatcher::dispatch() (폴백)        │
│    → extend/bottom/ 실행                                │
│    → ob_end_flush()                                     │
└─────────────────────────────────────────────────────────┘
    │
    ▼
HTTP 응답

✅  핵심 설계 원칙 요약
  1) 보안 우선: Secure.php는 DB 연결보다 먼저, 고유 해시 경로에서 로드
  2) 성능 최적화: DxCache 최우선 로드, GET 요청 조건부 세션 생략
  3) 확장성: 플러그인(plugin.php), 훅(HookManager), 확장(extend/) 세 가지 계층
  4) 하위 호환: 파일 기반 라우팅(Dispatcher)은 유지, DxRouter가 먼저 시도
  5) 격리: DxExtend의 safeExec()으로 확장 파일 오류가 시스템에 전파되지 않음


10. 자동 로딩 관련 전역 헬퍼 함수

함수 정의 파일 설명
dx_app() DxContainer.php DxContainer 인스턴스 반환
dx_make($abstract) DxContainer.php 컨테이너에서 서비스 꺼내기
dx_bind($abstract, $factory) DxContainer.php 팩토리 바인딩 등록
dx_singleton($abstract, $factory) DxContainer.php 싱글턴 바인딩 등록
dx_add_hook($name, $cb, $priority) HookManager.php 훅 Action 등록
dx_run_hook($name, $args) HookManager.php 훅 Action 실행
dx_add_filter($name, $cb, $priority) HookManager.php 훅 Filter 등록
dx_apply_filter($name, $value) HookManager.php 훅 Filter 실행
dx_remove_hook($name, $callback) HookManager.php 훅 제거
dx_has_hook($name) HookManager.php 훅 등록 여부 확인
load_plugins() functions.php plugins/**/plugin.php 자동 로드
dx_register_plugin($info) PluginRegistry.php 플러그인 타입 등록
dx_extend_top($ctx) DxExtend.php extend/top/ 수동 실행
dx_extend_middle($ctx) DxExtend.php extend/middle/ 수동 실행
dx_extend_bottom($ctx) DxExtend.php extend/bottom/ 수동 실행
dx_hook_top($context) HookManager.php 페이지 최상단 표준 훅 실행
dx_hook_middle($context) HookManager.php 페이지 중간 표준 훅 실행
dx_hook_bottom($context) HookManager.php 페이지 최하단 표준 훅 실행

댓글0

로그인 후 댓글을 작성할 수 있습니다.
3.10 모듈 로딩 구조 자동 로딩 구조 2026.04.21 3.10 모듈 로딩 구조 플러그인 / 확장 로딩 방식 2026.04.21
30
전체 회원
269
전체 게시글
144
전체 댓글
181
오늘 방문
28,530
전체 방문
1
현재 접속
인기글 7일 이내
최신글
최신댓글
목록