DXCMS v10.2.0 패치 노트
릴리즈 버전: v10.2.0
기준 버전: v10.1.0
작성일: 2026-09-29
1. 활성 플러그인만 로드 (core-plugin-status-filter · 작업명 v10.1.0)
대상 파일
core/functions.phpadmin/plugins/index.php
변경 내용
- 기존:
plugins/폴더의 모든 플러그인을 읽은 뒤 각 플러그인이 스스로 활성 여부 검사 - 변경:
dx_plugins.status = 1인 플러그인만 로드 — 비활성 플러그인은 파일을 읽지 않음 dx_active_plugin_dirs()신설 — 요청 내 static →DxCache(600초) → DB 순 조회, 방문자 요청은 캐시만 읽음dx_refresh_active_plugins()신설 — 관리자에서 활성·비활성·삭제 시 캐시 즉시 갱신- DB 조회 실패(설치 중·테이블 없음) 시
null→ 전체 로드(기존 동작)로 폴백해 사이트가 멈추지 않음 DX_PLUGIN_STATUS_FILTER상수 — 코어가 이미 걸렀다는 신호(플러그인 측 자체 검사 생략 가능)- 폴더가 없는 플러그인은 활성화할 수 없도록 차단
2. 플러그인 DB 테이블 보관 · 완전 삭제 (plugin-status-db-tables · 작업명 v10.1.1)
대상 파일
admin/plugins/index.phpinstall/migrate.php·install/schema.sql—dx_plugins.db_tables컬럼
변경 내용
dx_plugins.db_tables컬럼 신설 — 플러그인 manifest 의tables를 prefix 포함 전체 이름으로 저장(목록을 열 때 자동 동기화) → 폴더가 없어져도 어떤 DB 테이블을 지워야 하는지 알 수 있음- 테이블명 정규화 — prefix 포함·미포함 모두 허용,
dx_dx_이중 prefix 방지 - 삭제 순서 재정리: ① 비활성화 → ② 삭제 대상 테이블 확정(manifest 우선, 없으면
db_tables) → ③ 폴더 삭제(Windows 읽기전용 속성 대비 chmod) → ④ 선택 시 DB 테이블 삭제(폴더 삭제 성공 여부와 무관) → ⑤ 레코드 삭제 → ⑥ 캐시 갱신 - 폴더 삭제에 실패하면 레코드를 비활성으로 남기고 직접 삭제 안내
- 결과 안내: 삭제한 테이블 수, 없는 테이블 목록
- FTP 등으로 폴더를 직접 지운 플러그인 자동 정리
- 등록된 테이블 없음 → 목록·DB 에서 자동 제거
- 등록된 테이블 있음 → 비활성 처리 후 "폴더 없음"으로 표시, 휴지통 버튼의 파일 + DB 모두 삭제로 테이블까지 정리
- 플러그인 카드에 사용 중인 DB 테이블 목록 표시
3. 방문 기록 복구 · 현재 접속자 (online-fix)
대상 파일
extend/middle/01_visit_tracker.phpthemes/default/layout/_widgets.php
변경 내용
- 버그:
visit_logsINSERT 컬럼 11개(is_404포함)에 자리표시자?10개 → PDOHY093오류가catch에 묻혀 v10 이후 방문 기록이 한 건도 저장되지 않음- 영향: 현재 접속자(항상 0), 유입 경로·페이지별·브라우저·404 통계 전부 (
dx_visits기반 오늘/전체 방문자는 정상이었음) - PHP 버전과 무관하게 실패하던 코드 — 자리표시자 11개로 수정
- 영향: 현재 접속자(항상 0), 유입 경로·페이지별·브라우저·404 통계 전부 (
- 현재 접속자 기준 시각을 PHP 에서 계산 — 기록(
date())과 조회(MySQLNOW()) 시간대가 다르면 10분 창이 어긋나던 문제 - 현재 접속자 캐시 60초 → 30초 (주석의 원래 의도대로)
4. 멀티도메인 — 등록된 도메인만 접속 (strict-domain)
대상 파일
core/DxSite.phpindex.php
변경 내용
- 사이트 관리에 등록되지 않은 도메인(예:
test.designonex.com)으로 들어오면 같은 경로로 기본 도메인에 이동 (GET 301, POST 308) - 이동할 도메인 결정 순서
- 서브도메인을 뗀 상위 도메인 중 등록된 도메인 (
test.example.com→example.com) dx_settings.site_url도메인- 사이트 관리의 첫 번째 활성 도메인
- 서브도메인을 뗀 상위 도메인 중 등록된 도메인 (
- 허용: 등록된 활성 도메인, 기본 도메인,
localhost·사설 IP(개발·NAS 내부 접속) - 봇 대응: 등록 도메인 목록 전체를 캐시 키 하나(
site_domains)로 보관하고 호스트는 메모리에서만 비교 → 무작위 서브도메인 30회 접속 시 DB 조회 60회·캐시 파일 32개 → 0회·1개 - 목록 조회 실패 시 이동하지 않음 (등록 도메인 오판 방지)
- 끄기:
dx_settings.strict_domain = 0 index.php(웹 진입점)에서만 적용 —dx_load.php를 쓰는 외부 스크립트는 제외- 비활성 도메인도 미등록으로 간주해 이동
5. 통계 > 유입 경로 전면 개편 (referer-v3)
대상 파일
extend/middle/01_visit_tracker.phpcore/api/visit_ping.php← 신규assets/js/dx-visit.js← 신규admin/statistics/index.phpadmin/statistics/_referer_v3.php← 신규core/DxSite.php(registeredHosts())install/migrate.php·install/schema.sql—visit_logs컬럼·인덱스
집계 방식
- 방문(세션) 단위 유입: 30분 방문 쿠키(
dx_vk)로 첫 페이지만is_entry = 1 - 출처가 바뀌면 새 유입: 방문 중이라도 외부 도메인·캠페인 링크로 다시 들어오면 새 유입 (출처는
dx_vr쿠키에 해시로 기억 — 같은 출처 새로고침은 중복 제외)- 수정 전: 사이트를 열어 둔 채 다른 사이트 링크로 돌아오면 유입으로 세지 않아 외부 도메인이 보이지 않았음
- 내 도메인 제외: 현재 호스트,
site_url, 사이트 관리 등록 도메인과 그 하위 도메인 - 캠페인:
?ref=/utm_source·utm_medium·utm_campaign - 사람 확인: 실제 상호작용(스크롤·터치·마우스·키) 시 HMAC 서명(
DX_SECRET_KEY) 신호 →is_human = 1- 위조 서명은 무시하고 204 응답, HTML 응답에만 스크립트 삽입(JSON·파일 응답 무영향), 봇에는 미삽입
- 마이그레이션 전에도 기본 방문 기록은 유지 (새 컬럼 존재 여부 자동 판별)
통계 화면
- 필터: 사람 확인만(기본) / 전체
- 요약: 유입 합계, 외부 사이트, 캠페인, referer 없음
- 외부 사이트 — 출처 이름·분류 표시(Google·네이버·다음·카카오·페이스북·유튜브·ChatGPT 등), 클릭 시 들어온 경로 상세
- referer 없이 들어온 방문 — 들어온 페이지 기준, 깊은 페이지는 "링크 유입 추정"
- 캠페인 링크, 검색어(전달된 경우만)
- 봇 방문 (유입 집계 제외 · 참고) — 봇 이름·분류(검색 / AI 수집 / SEO 수집 / SNS 미리보기 / 모니터링 / 스크립트)·요청 수·IP·마지막 방문, 이름에 User-Agent 원문
- 봇이 보낸 referer 도메인 — 리퍼러 스팸 확인용
- 새 컬럼이 없으면(마이그레이션 전) 기존 화면 그대로 표시
봇 판별 보강
- 버그: 네이버
Yeti, 다음Daumoa, 카카오톡·페이스북 링크 미리보기(kakaotalk-scrap,facebookexternalhit)가 UA 에bot이 없어 사람 방문·유입으로 집계되던 문제 → 판별 목록에 추가 - 추가:
google-inspectiontool,mediapartners-google,feedfetcher,chatgpt-user,claude-user,perplexity,whatsapp등 - 네이버 앱·카카오톡·다음 앱 내 브라우저로 들어온 실제 사람은 그대로 사람으로 기록
DB (visit_logs)
- 컬럼:
is_entry,is_human,visit_key,src,src_medium,src_campaign - 인덱스:
idx_entry_date (is_entry, visit_date),idx_visit_key (visit_key)
참고: 링크에 rel="noreferrer" 가 있거나 상대 사이트가 Referrer-Policy: no-referrer 를 쓰면 브라우저가 도메인까지 보내지 않음(HTML 표준) — 이런 방문은 "referer 없음"으로 들어온 페이지 기준 집계
6. 다크모드 복구 · 자동 변환 강화 (darkmode-fix)
대상 파일
assets/dx-dark.cssassets/dx-dark-admin.css← 신규assets/js/dx-darkmode-engine.js(v4.2 → v4.8)extend/top/01_darkmode_early.phpextend/bottom/02_darkmode_engine.php
v10.0.0 다크모드 패치에서 생긴 문제 복구
dx-dark.css색상값 공백: JS 의 CSS 를 정적 파일로 옮기며 색상 변수가 빈칸으로 빠짐(144개 규칙) → v9 엔진을 브라우저에서 실행해 실제 생성 CSS 를 추출·복원- 엔진 JS 미로드:
extend/bottom에서dx_body_bottom훅에 등록했으나 훅이 이미 지난 뒤라 출력되지 않음 → v9 처럼 직접 출력 - 자동 변환 삭제:
processEl·scanAll· MutationObserver 를 v9 원문 그대로 복원 - 관리자 전용 규칙(선택자 범위 제한 없음)은
dx-dark-admin.css로 분리해 관리자 페이지에서만 로드 (v9 와 동일 범위)
자동 인지 강화 (플러그인 개별 수정 불필요)
- CSS 파일에서 온 밝은 테두리 자동 변환 — 1~2px·무채색·불투명 선만(색깔 강조선·3px 이상·반투명 선 유지)
color(srgb …)계산값 인식 —dxb-css투명도 클래스(bg-slate-50/50등)·color-mix()가 변환되지 않아 회색 띠가 생기던 문제:hover·:focus·:active규칙 자동 변환 — 오버 시 흰 배경·안 보이는 글자 방지,@media안 규칙·나중에 추가되는 CSS 포함- 스크립트가 인라인 색을 다시 써 넣는 경우(
onmouseout="this.style.background='#fff'", 클릭 처리 등) 즉시 다크로 교체 — 알림 목록이 오버 후 하얗게 남던 문제 - CKEditor 테두리·툴바 구분선(
::after)·드롭다운 구분선 다크 처리
깜박임(FOUC) 제거 — 관리자 포함
- 초기 단계에서 관리자 다크 CSS 도 함께 삽입
- 다크 CSS 로드 + 첫 자동 변환 완료 후 화면 공개 (숨김 상태 첫 변환은 프레임 분할 없이 일괄 처리)
- 초기 단계에서 받은 CSS 는 다시 받지 않음, 로딩 중 전환 애니메이션 억제
- 안전장치: 엔진 로드 실패 시에도 1.5초(이중 3초) 뒤 반드시 공개
- 측정(CSS·JS 300ms 지연): 흰 요소가 보인 프레임 메인 35→0, 관리자 69→0
안정성
- 엔진 자신의 DOM 변경을 관찰 대상에서 제외, 글자색
#94a3b8↔#64748b핑퐁 방지 — 정지 상태 DOM 변경 0회
적용 방법
권장 적용 순서 (겹치는 파일은 뒤의 압축이 최신)
| 순서 | 압축 | 비고 |
|---|---|---|
| 1 | dxcms_v10_1_1_plugin-status-db-tables.zip |
v10_1_0 압축 내용을 모두 포함 |
| 2 | dxcms-referer-v3.zip |
online-fix · strict-domain 내용을 모두 포함하고 더 최신, migrate.php · schema.sql 은 1번 위에 v10.2.0 블록을 더한 것 |
| 3 | dxcms-darkmode-fix.zip |
다른 압축과 겹치는 파일 없음 |
| 4 | version.php → return '10.2.0'; |
1번 압축의 version.php 는 10.1.1 이므로 반드시 수정 |
dxcms_v10_1_0_core-plugin-status-filter.zip,dxcms-online-fix.zip,dxcms-strict-domain.zip은 위 압축에 포함되어 있어 따로 적용할 필요 없음 (1·2번보다 나중에 적용하면 구버전으로 덮어써짐)
기존 사용자
- 위 순서대로 파일 덮어쓰기
version.php를10.2.0으로 수정install/migrate.php실행 (필수) —dx_plugins.db_tables,visit_logs컬럼 6개·인덱스 2개 추가,cms_version10.2.0 자동 기록- Ctrl+F5 — 다크모드 CSS·JS 가 바뀌었으므로 버전을 올려야 방문자 브라우저 캐시가 갱신됨
신규 설치자: install/schema.sql 에 모든 컬럼 포함
변경 파일 전체 목록 (v10.2.0)
| 파일 | 패치 |
|---|---|
version.php |
10.2.0 |
index.php |
미등록 도메인 이동 호출 |
core/functions.php |
활성 플러그인만 로드 |
core/DxSite.php |
미등록 도메인 이동 · 도메인 목록 단일 캐시 · registeredHosts() |
core/api/visit_ping.php |
신규 · 사람 확인 신호 수신 |
admin/plugins/index.php |
플러그인 상태 필터 · DB 테이블 보관 · 완전 삭제 · 폴더 없는 플러그인 정리 |
admin/statistics/index.php |
유입 경로 v3 연결 |
admin/statistics/_referer_v3.php |
신규 · 유입 경로 · 봇 방문 화면 |
extend/middle/01_visit_tracker.php |
INSERT 수정 · 방문 단위 유입 · 출처 전환 · 캠페인 · 봇 판별 보강 |
extend/top/01_darkmode_early.php |
관리자 다크 CSS 초기 삽입 · 공개 시점 엔진 위임 · 안전장치 |
extend/bottom/02_darkmode_engine.php |
엔진 스크립트 직접 출력 |
themes/default/layout/_widgets.php |
현재 접속자 기준 시각 · 캐시 30초 |
assets/js/dx-visit.js |
신규 · 사람 확인 신호 |
assets/js/dx-darkmode-engine.js |
v4.8 — 자동 변환 복원 · 테두리 · color(srgb) · :hover · 인라인 재작성 대응 · 깜박임 제거 |
assets/dx-dark.css |
색상값 복원 · CKEditor · 로딩 중 전환 억제 |
assets/dx-dark-admin.css |
신규 · 관리자 전용 다크 규칙 |
install/migrate.php |
v10.1.1 plugins.db_tables · v10.2.0 visit_logs 컬럼·인덱스 |
install/schema.sql |
plugins.db_tables · visit_logs 컬럼·인덱스 |
DXCMS — Copyright (C) 2026 designonex [디자인원엑스]
License: GNU Lesser General Public License v3.0 (LGPL-3.0)