1장. 플러그인 개요
1.1 소개
DX QBank는 DXCMS 위에서 동작하는 문제은행 · 온라인 시험 플랫폼 플러그인입니다. 관리자가 문제를 등록하고 시험지를 구성하면, 사용자는 웹 브라우저에서 바로 응시하고 즉시 채점 결과를 확인할 수 있습니다.
1.2 주요 기능
- 문제 관리 — 객관식(단일/복수), OX, 단답형, 서술형 5가지 유형
- 이미지 삽입 — 문제 본문·선택지·해설에 이미지 직접 업로드
- 카테고리 — 다단계 카테고리로 문제 분류
- 시험지 — 문제 선택, 배점 설정, 문항·선택지 순서 섞기
- 응시 제어 — 시험 기간, 시간 제한, 재응시 허용/불가
- 자동 채점 — 객관식·OX·단답형 즉시 채점, 서술형 수동 채점
- 결과 리포트 — SVG 원형 점수, 오답 분석, 답안 해설
- 개인 현황 — 내 학습 통계, 시험별 합격 이력, 취약 문제 TOP5
- 반응형 UI — 모바일·태블릿·PC 모두 지원
- 카테고리 필터 — 헤더 네비 및 모바일 메뉴에서 카테고리별 시험 필터
1.3 요구 사항
| 항목 |
최소 요구 사항 |
| DXCMS |
v8.5.0 이상 |
| PHP |
5.6 이상 (7.x / 8.x 권장) |
| MySQL / MariaDB |
5.5 이상 |
| 웹 서버 |
Apache / Nginx / IIS |
| 디스크 여유 공간 |
50MB 이상 (업로드 이미지 별도) |
2장. 설치 방법
2.1 파일 복사
플러그인 ZIP 파일의 압축을 풀고 아래 두 폴더를 DXCMS 루트에 복사합니다.
- plugins/dx-qbank/ — 플러그인 본체
- extend/top/00_qbank_router.php — URL 라우터 훅
2.2 플러그인 활성화
- DXCMS 관리자 → 플러그인 관리에서 DX QBank 활성화
2.3 테이블 설치
브라우저에서 아래 URL에 접속하면 7개의 DB 테이블이 자동 생성됩니다 (관리자 로그인 필요).
https://사이트주소/qbank/install
※ 설치 완료 후 이 URL로 다시 접속해도 이미 존재하는 테이블은 변경되지 않습니다.
2.4 설치 확인
- 사이트주소/qbank 접속 → 시험 목록 페이지 정상 출력 확인
- DXCMS 관리자 → DX QBank 메뉴 노출 확인
3장. 파일 구조
| 경로 |
설명 |
| plugins/dx-qbank/ |
플러그인 루트 |
| manifest.php |
플러그인 메타 정보 (이름, 버전, 요구 사항) |
| plugin.php |
DXCMS 훅 등록 (관리자 메뉴, 라우터) |
| router.php |
프론트엔드 URL 분기 처리 |
| core/install.php |
DB 테이블 생성 함수 |
| core/DxQBank.php |
공통 유틸리티 클래스 |
| core/DxQBankExam.php |
시험지 CRUD 클래스 |
| core/DxQBankQuestion.php |
문제 CRUD 클래스 |
| admin/index.php |
관리자 POST 처리 + 레이아웃 진입점 |
| admin/layout.php |
관리자 사이드바 레이아웃 |
| admin/blocks/*.php |
관리자 각 화면 블록 |
| views/layout.php |
프론트엔드 공통 헤더/CSS |
| views/index.php |
시험 목록 메인 페이지 |
| views/exam.php |
시험 응시 화면 |
| views/result.php |
결과/채점 화면 |
| views/my.php |
개인 학습 현황 프로필 |
| views/already_done.php |
재응시 불가 안내 |
| views/closed.php |
기간 외 시험 안내 |
| extend/top/00_qbank_router.php |
DXCMS extend 훅 — URL 라우터 연결 |
4장. 데이터베이스 설계
설치 시 7개 테이블이 생성됩니다. 모든 테이블은 설정된 DB prefix가 자동 적용됩니다 (기본값: dx_).
4.1 qb_categories — 카테고리
| 컬럼 |
타입 |
설명 |
| id |
INT UNSIGNED |
자동 증가 PK |
| parent_id |
INT UNSIGNED |
상위 카테고리 ID (0 = 최상위) |
| name |
VARCHAR(100) |
카테고리 이름 |
| sort |
INT UNSIGNED |
정렬 순서 |
| q_count |
INT UNSIGNED |
포함된 문제 수 (캐시) |
4.2 qb_questions — 문제
| 컬럼 |
타입 |
설명 |
| id |
BIGINT UNSIGNED |
자동 증가 PK |
| category_id |
INT UNSIGNED |
카테고리 FK |
| type |
ENUM |
single / multi / ox / short / essay |
| difficulty |
ENUM |
low / mid / high |
| score |
DECIMAL(5,1) |
기본 배점 |
| content |
TEXT |
문제 본문 (HTML 포함 가능) |
| content_html |
TINYINT(1) |
HTML 렌더링 여부 (1=HTML, 0=텍스트) |
| explanation |
TEXT |
해설 (채점 후 표시) |
| answer_short |
VARCHAR(500) |
단답형 정답 |
| tags |
VARCHAR(500) |
태그 목록 (쉼표 구분) |
| used_count |
INT UNSIGNED |
출제 횟수 |
| correct_cnt |
INT UNSIGNED |
정답 횟수 |
| wrong_cnt |
INT UNSIGNED |
오답 횟수 |
| created_by |
INT UNSIGNED |
작성자 member ID |
| created_at |
DATETIME |
생성일시 |
| updated_at |
DATETIME |
수정일시 |
4.3 qb_options — 선택지
| 컬럼 |
타입 |
설명 |
| id |
BIGINT UNSIGNED |
자동 증가 PK |
| question_id |
BIGINT UNSIGNED |
문제 FK |
| content |
TEXT |
선택지 내용 (HTML 포함 가능) |
| content_html |
TINYINT(1) |
HTML 렌더링 여부 |
| is_correct |
TINYINT(1) |
정답 여부 |
| sort |
INT UNSIGNED |
정렬 순서 |
4.4 qb_exams — 시험지
| 컬럼 |
타입 |
설명 |
| id |
BIGINT UNSIGNED |
PK |
| title |
VARCHAR(200) |
시험지 제목 |
| description |
TEXT |
시험 안내 |
| status |
ENUM |
draft / active / closed |
| time_limit |
INT UNSIGNED |
시간 제한 (분, 0=무제한) |
| pass_score |
DECIMAL(5,1) |
합격 기준점 |
| total_score |
DECIMAL(7,1) |
총점 |
| shuffle_q |
TINYINT(1) |
문제 순서 섞기 |
| shuffle_o |
TINYINT(1) |
선택지 순서 섞기 |
| show_result |
TINYINT(1) |
즉시 결과 공개 |
| show_answer |
TINYINT(1) |
정답·해설 공개 |
| allow_retake |
TINYINT(1) |
재응시 허용 |
| retake_limit |
INT UNSIGNED |
재응시 최대 횟수 (0=무제한) |
| start_at |
DATETIME |
응시 시작일시 |
| end_at |
DATETIME |
응시 종료일시 |
| attempt_count |
INT UNSIGNED |
누적 응시 수 |
4.5 qb_exam_questions — 시험지-문제 매핑
| 컬럼 |
타입 |
설명 |
| exam_id |
BIGINT UNSIGNED |
시험지 FK |
| question_id |
BIGINT UNSIGNED |
문제 FK |
| sort |
INT UNSIGNED |
문제 순서 |
| score |
DECIMAL(5,1) |
이 시험에서의 배점 |
4.6 qb_attempts — 응시 세션
| 컬럼 |
타입 |
설명 |
| id |
BIGINT UNSIGNED |
PK |
| exam_id |
BIGINT UNSIGNED |
시험지 FK |
| member_id |
INT UNSIGNED |
응시자 FK |
| status |
ENUM |
ongoing / submitted / graded |
| score |
DECIMAL(7,1) |
획득 점수 |
| total_score |
DECIMAL(7,1) |
이 응시의 총점 |
| pass |
TINYINT(1) |
합격 여부 (NULL=채점 전) |
| started_at |
DATETIME |
응시 시작일시 |
| submitted_at |
DATETIME |
제출일시 |
| duration_sec |
INT UNSIGNED |
소요 시간 (초) |
| q_order |
TEXT |
문제 순서 JSON (섞기 적용 시) |
4.7 qb_answers — 답안
| 컬럼 |
타입 |
설명 |
| id |
BIGINT UNSIGNED |
PK |
| attempt_id |
BIGINT UNSIGNED |
응시 FK |
| question_id |
BIGINT UNSIGNED |
문제 FK |
| answer_text |
TEXT |
주관식 답안 |
| option_ids |
VARCHAR(500) |
선택한 선택지 ID (쉼표 구분) |
| is_correct |
TINYINT(1) |
정답 여부 (NULL=채점 전) |
| score_given |
DECIMAL(5,1) |
부여 점수 |
| grader_note |
TEXT |
채점자 메모 (서술형) |
5장. 관리자 기능
관리자 메뉴 경로: DXCMS 관리자 → DX QBank
5.1 대시보드
플러그인 전체 현황을 한눈에 확인합니다.
- 총 문제 수 / 총 시험지 수 / 누적 응시 수
- 최근 7일 응시 추이 차트
- 최근 응시 10건 목록 (응시자, 시험명, 점수, 합격 여부)
5.2 문제 관리
5.2.1 문제 목록
- 전체 문제 목록 (카테고리, 유형, 난이도, 정답률 표시)
- 카테고리 / 난이도 / 유형별 필터
- 문제 수정 · 삭제
5.2.2 문제 등록 · 수정
- 카테고리, 유형, 난이도, 기본 배점 설정
- 문제 본문 — contenteditable 에디터 (B/I/U 서식 + 이미지 직접 삽입)
- 선택지 — 항목별 contenteditable 에디터, 이미지 삽입 가능, 동적 추가/제거
- 해설 — 이미지 포함 HTML 서식 지원
- 태그 입력 (쉼표 구분)
- 이미지 업로드 경로: data/uploads/qbank/
5.3 카테고리 관리
- 카테고리 추가 / 삭제
- 카테고리별 문제 수 표시
- 카테고리는 헤더 네비 메뉴 · 모바일 메뉴 · 시험 목록 필터에 자동 노출
5.4 시험지 관리
5.4.1 시험지 목록
- 시험지 제목, 상태(초안/진행중/종료), 응시자 수, 총점 표시
- 시험지 편집 · 삭제
5.4.2 시험지 만들기
- 제목, 설명 입력
- 시간 제한 (분 단위, 0 = 무제한)
- 합격 기준점 설정
- 문제 순서 섞기 / 선택지 순서 섞기
- 즉시 결과 공개 / 정답·해설 공개 여부
- 재응시 허용 및 횟수 제한
- 응시 기간 설정 (시작일시 ~ 종료일시)
5.4.3 시험지 편집
- 문제 검색 및 시험지에 추가
- 카테고리 / 난이도 / 유형 필터로 문제 자동 선택
- 문제별 배점 개별 설정
- 총점 자동 계산
- 시험지 상태 변경 (초안 → 진행중 → 종료)
5.5 응시 관리
5.5.1 응시 현황
- 시험지별 · 응시자별 응시 목록
- 상태 (진행중 / 제출됨 / 채점완료) 표시
- 응시 상세 보기 — 답안 확인
5.5.2 서술형 채점
- 서술형 답안 목록 필터링
- 답안 내용 확인 후 점수 직접 입력
- 채점자 메모 입력 가능
- 채점 완료 시 합격 여부 자동 판정
6장. 프론트엔드(사용자) 기능
6.1 시험 목록 메인
- 히어로 섹션 — 로그인 사용자 이름 인사 / 비로그인 시 가입 유도
- 플랫폼 통계 바 — 진행 중인 시험 수 / 누적 응시 / 응시자 수
- 카테고리 필터 칩 — qb_categories 기준 필터링
- 시험 카드 그리드 — 카테고리 뱃지, HOT/마감임박 뱃지, 내 응시 상태 표시
- 반응형 — 1024px 이하 2열, 768px 이하 1열
6.2 시험 응시
- 응시 시작 화면 — 시험 정보 카드 (문제 수, 총점, 합격 기준, 시간, 재응시 여부)
- 스티키 상단바 — 시험명 + 남은 시간 카운트다운
- 문제 유형별 UI — 라디오(단일), 체크박스(복수), OX, 단답형 입력, 서술형 textarea
- 시간 초과 시 자동 제출
- 제출 확인 모달
6.3 결과 확인
- SVG 원형 점수 게이지 (합격=초록, 불합격=빨강)
- 점수 / 총점 / 합격 기준 3칸 요약
- 답안 확인 — 정답/오답 색상 구분, 선택지 정답 표시, 해설 출력
6.4 개인 학습 현황
- 프로필 — 이름, 아이디, 이메일, 레벨, 프로필 이미지, 합격 횟수, 총 학습 시간
- 핵심 통계 4칸 — 총 응시 / 합격 / 불합격 / 평균 정답률
- 전체 합격률 프로그레스 바
- 시험별 현황 — 최고점 프로그레스 바, 합격 여부, 마지막 결과 링크
- 자주 틀린 문제 TOP5 — 오답 횟수 순위
- 최근 응시 기록 테이블
- 반응형 — 768px 이하 2열, 640px 이하 테이블 가로 스크롤
6.5 접근 제어
| 상황 |
처리 |
| 비로그인 → 내 현황(/qbank/my) |
로그인 페이지로 리디렉트 |
| 재응시 불가 시험 재시도 |
이전 결과 안내 화면 출력 |
| 응시 기간 외 접근 |
기간 안내 화면 출력 |
| 존재하지 않는 시험 ID |
404 안내 화면 출력 |
7장. URL 구조
| URL |
설명 |
| /qbank |
시험 목록 메인 페이지 |
| /qbank?cat={카테고리ID} |
카테고리 필터링된 시험 목록 |
| /qbank/{시험ID} |
시험 응시 (시작 화면 또는 진행) |
| /qbank/{시험ID}/result/{응시ID} |
결과 확인 페이지 |
| /qbank/my |
개인 학습 현황 (로그인 필요) |
| /qbank/install |
DB 테이블 설치 (관리자 전용) |
URL Rewrite가 비활성화된 환경에서는 index.php?_url=/qbank/... 형식으로 접근합니다.
8장. PHP 클래스 레퍼런스
8.1 DxQBank — 공통 유틸리티
| 메서드 |
반환값 |
설명 |
| DxQBank::db() |
Database |
DB 인스턴스 반환 |
| DxQBank::prefix() |
string |
qb_ prefix 반환 |
| DxQBank::url($path) |
string |
프론트엔드 URL 생성 |
| DxQBank::adminUrl() |
string |
관리자 URL 반환 |
| DxQBank::types() |
array |
문제 유형 목록 반환 |
| DxQBank::difficulties() |
array |
난이도 목록 반환 |
| DxQBank::getCategories() |
array |
전체 카테고리 목록 |
8.2 DxQBankExam — 시험지
| 메서드 |
반환값 |
설명 |
| DxQBankExam::getList($opts) |
array |
시험지 목록 조회 (페이징, 상태 필터) |
| DxQBankExam::get($id) |
array|null |
시험지 단건 조회 |
| DxQBankExam::create($data) |
int|false |
시험지 생성, 생성된 ID 반환 |
| DxQBankExam::update($id, $data) |
bool |
시험지 수정 |
| DxQBankExam::delete($id) |
bool |
시험지 삭제 |
| DxQBankExam::getQuestions($id) |
array |
시험지 문제 목록 (선택지 포함) |
| DxQBankExam::startAttempt($id) |
array|false |
응시 세션 시작 |
| DxQBankExam::saveAnswer($aid,...) |
void |
답안 저장 |
| DxQBankExam::submit($aid) |
bool |
응시 제출 + 자동 채점 |
| DxQBankExam::getAttemptAnswers($aid) |
array |
응시 답안 목록 조회 |
8.3 DxQBankQuestion — 문제
| 메서드 |
반환값 |
설명 |
| DxQBankQuestion::getList($opts) |
array |
문제 목록 (카테고리·유형·난이도 필터) |
| DxQBankQuestion::get($id) |
array|null |
문제 단건 조회 (선택지 포함) |
| DxQBankQuestion::create($data) |
int|false |
문제 생성 |
| DxQBankQuestion::update($id,$data) |
bool |
문제 수정 |
| DxQBankQuestion::delete($id) |
bool |
문제 삭제 |
| DxQBankQuestion::saveOptions($qid,$opts) |
void |
선택지 저장 (기존 삭제 후 재삽입) |
9장. 설정 및 커스터마이징
9.1 이미지 업로드 경로
문제·해설·선택지 이미지는 아래 경로에 저장됩니다.
data/uploads/qbank/YYYYMMDDHHmmss_xxxxxxxx.{확장자}
9.2 파일 크기 제한
기본값 5MB. admin/index.php의 이미지 업로드 처리 부분에서 수정 가능합니다.
if ($__file['size'] > 5*1024*1024) { ... } ← 이 숫자를 변경
9.3 CSS 커스터마이징
- 프론트엔드 CSS 변수는 views/layout.php의 :root 블록에서 관리
- --primary: 주색상 / --success: 합격색 / --danger: 불합격색
- qb-* 클래스가 모든 UI 요소에 적용되어 있어 개별 오버라이드 가능
9.4 URL 슬러그 변경
기본 URL 슬러그는 /qbank 입니다. 변경하려면:
- extend/top/00_qbank_router.php 의 슬러그 조건 수정
- plugin.php 의 관리자 링크 URL 수정
10장. 자주 묻는 질문 (FAQ)
Q. 설치 후 시험 목록이 비어 있습니다.
A. 관리자에서 시험지를 생성하고 상태를 "진행중"으로 변경해야 합니다. 초안(draft) 상태는 사용자에게 노출되지 않습니다.
Q. 카테고리 필터 칩이 헤더에 보이지 않습니다.
A. qb_categories 테이블의 q_count 컬럼이 0인 카테고리는 필터에 표시되지 않습니다. 카테고리에 문제를 등록하면 자동으로 노출됩니다.
Q. 서술형 문제는 자동 채점이 안 되나요?
A. 서술형(essay) 유형은 자동 채점이 불가하며, 관리자 → 서술형 채점 메뉴에서 수동으로 점수를 입력해야 합니다. 채점 완료 후 합격 여부가 자동 판정됩니다.
Q. 이미지 업로드 시 "저장 실패" 오류가 납니다.
A. data/uploads/qbank/ 폴더의 쓰기 권한을 확인하세요. 폴더가 없는 경우 자동 생성을 시도하지만 권한 부족 시 실패할 수 있습니다.
Q. 기존 설치 환경에서 업데이트하면 DB가 초기화되나요?
A. 아니요. CREATE TABLE IF NOT EXISTS 방식이라 이미 존재하는 테이블은 변경되지 않습니다. 신규 컬럼 추가는 PHP로 컬럼 존재 여부를 확인 후 ALTER TABLE을 실행하므로 데이터가 유지됩니다.
라이선스
| 항목 |
내용 |
| 재배포·판매 |
❌ 금지 (원천 소스 90% 이상 수정 시 재배포 및 판매 가능) |
| 플러그인 원천 시스템 |
DesignOneX 소유 |
| 상업적 사용 |
✅ 상업적 제작에만 허용, 학습용 |
| 라이선스 |
디자인원엑스 라이선스 |
⚠️ 플러그인 코어(plugin.php, core/, admin/) 자체의 재배포 및 판매는 금지됩니다.