회원가입 | 고객센터 |
DESIGNONEX
dxcms.kr
DX마켓
Service
PR리그
Q&AN
지식공유
공지사항
통계
로그인 회원가입
고객센터

DX 시도/시군구/동 선택 플러그인

D DX관리자
2026.07.24 03:42(수정됨) 4 0


1. 개요 특징

DX 시도/시군구/ 선택 플러그인은 DXCMS 게시판 글쓰기 폼에 ///// 3단계 연동 셀렉트 박스를 자동으로 삽입합니다. 선택된 값은 DXCMS 여분필드(BoardFields) 시스템에 저장되며, 뷰와 리스트 스킨에서 수동으로 가져와 표시합니다.

•  3단계 연동 셀렉트/ 선택// 자동 로드// 자동 로드
•  단계 선택 — 1단계(/도만) / 2단계(/+시군구) / 3단계(전체) 게시판별 독립 설정
•  필수 입력 설정 — ON / 미선택 상태에서 등록 차단
•  수정 자동 복원수정 진입 기존 선택값 자동 복원 (AJAX)
•  여분필드 자동 관리활성화 sido1/sido2/sido3 여분필드 자동 생성
•  검색 가능여분필드 검색으로 지역 필터링
•  PHP 5.6+ 호환외부 라이브러리 없음
 

데이터 흐름 요약

글쓰기 폼에서 지역 선택
    ↓
bf_sido1, bf_sido2, bf_sido3 로 POST 전송
    ↓
BoardFields가 post_meta 테이블에 자동 저장
    field_key: sido1 / sido2 / sido3
    ↓
뷰/리스트 스킨에서 수동으로 BoardFields 또는 직접 post_meta 조회
 
 
 

2. 설치 방법

파일 구조

plugins/
  dx-sido-select/
    manifest.php        ← 플러그인 메타 정보
    plugin.php          ← 핵심 로직 (훅, AJAX, 관리자)
    data/
      sido_data.php     ← 시/도/시군구/동 전체 데이터


설치 절차

1.  plugins/dx-sido-select/ 폴더를 DXCMS 루트의 plugins/ 폴더에 복사
2.  관리자플러그인 → DX 시도/시군구/ 선택활성화
3.  관리자 사이드바레이아웃시도 선택 필드 메뉴 확인
4.  설정 화면에서 게시판별 활성화 단계 설정
5.  글쓰기 폼에서 셀렉트가 표시되는지 확인
 
별도 DB 테이블 설치 없음 — DXCMS 기본 settings 테이블과 post_meta 테이블을 사용합니다.
 
 

3. 관리자 화면 사용법

관리자 사이드바레이아웃시도 선택 필드 접속
 

게시판별 설정

설정 항목 설명
활성 (토글) 해당 게시판에서 시도 선택 필드 ON/OFF
단계 1단계(/도만) / 2단계(/+시군구) / 3단계(전체)
필수 입력 체크 / 미선택 상태에서 등록 차단
 

단계 안내

단계 생성되는 여분필드 설명
1단계 sido1 /도만 선택
2단계 sido1, sido2 / + // 선택
3단계 sido1, sido2, sido3 / + // + // 선택
 

저장 자동 처리

•  활성화설정한 단계 수만큼 여분필드(sido1/sido2/sido3) 자동 생성
•  단계 변경기존 여분필드 삭제 단계에 맞게 재생성
•  비활성화여분필드 삭제 (DB 데이터는 유지)
 
여분필드는 is_list=1, is_search=1, is_view=1 생성되어 목록/검색/뷰에서 모두 활용 가능합니다.
 
 

4. 글쓰기 / 수정 동작

4-1. 글쓰기

게시판 글쓰기 폼에서 공지/비밀글 체크박스 아래에 지역 셀렉트가 자동으로 삽입됩니다.

•  / 선택 → AJAX // 목록 자동 로드
•  // 선택 → AJAX // 목록 자동 로드 (3단계 설정 )
•  선택값은 bf_sido1, bf_sido2, bf_sido3 이름으로 폼과 함께 전송
•  BoardFields 시스템이 post_meta 테이블에 자동 저장
 

4-2. 수정

수정 진입 기존 선택값이 자동으로 복원됩니다.

•  post_meta 테이블에서 sido1/sido2/sido3 값을 조회
•  sido1 값으로 / 선택 자동 설정
•  AJAX // 목록 로드 sido2 자동 선택
•  AJAX // 목록 로드 sido3 자동 선택
 
중요: DXCMS post_id 18자리 숫자입니다. 반드시 문자열(string) 처리해야 합니다. (int 캐스팅 값이 잘림)
// 올바른 방법
$postId = (string)$editPost['id'];

// 잘못된 방법 — 18자리 숫자가 잘려 수정 시 기존값 복원 안 됨
$postId = (int)$editPost['id']; // ← 절대 사용 금지
 
 
 

5. DB 저장 구조

선택된 지역 값은 DXCMS 기본 post_meta 테이블에 저장됩니다.
 

post_meta 테이블 저장 예시

id post_id field_key value
19 1784825082393178 (문자열) sido1 서울
20 1784825082393178 (문자열) sido2 강남구
21 1784825082393178 (문자열) sido3 역삼동
 
post_id 18자리 BIGINT이지만 PHP에서는 반드시 문자열로 처리해야 합니다.
field_key 항상 sido1 / sido2 / sido3 고정입니다.
 

settings 테이블 저장 형식

setting_key setting_value 의미
dxsido_board_{게시판ID} 3r 3단계 + 필수 입력
dxsido_board_{게시판ID} 2 2단계 + 선택 입력
dxsido_board_{게시판ID} 1r 1단계 + 필수 입력
 
 

6. (view) 스킨에서 데이터 가져오기  ★

스킨에서 지역 정보를 표시하려면 수동으로 가져와야 합니다. 3가지 방법을 제공합니다.
 

방법 A — BoardFields 시스템 사용 (권장)

BoardFields require하면 DXCMS 자동으로 해당 게시글의 여분필드 값을 모두 로드합니다.
 
boards/skins/{스킨명}/view.php 상단에 BoardFields require 코드를 추가합니다.

view.php — BoardFields 로드
<?php
/**
 * 게시판 뷰 스킨 — view.php
 * BoardFields를 통해 여분필드(sido1/sido2/sido3) 가져오기
 */

// ① BoardFields 인스턴스 생성
//    $board, $post 변수는 DXCMS가 스킨에 주입해줌
if (function_exists('dx_board_fields')) {
    $bf     = dx_board_fields();
    $fields = $bf->getValues($post['id']);
    // $fields = array(
    //   'sido1' => '서울',
    //   'sido2' => '강남구',
    //   'sido3' => '역삼동',
    //   ... 기타 여분필드
    // )
} else {
    $fields = array();
}

// ② 값 추출
$sido1 = isset($fields['sido1']) ? $fields['sido1'] : '';
$sido2 = isset($fields['sido2']) ? $fields['sido2'] : '';
$sido3 = isset($fields['sido3']) ? $fields['sido3'] : '';

// ③ HTML 출력
if ($sido1):
    echo '<div class="post-location">';
    echo '<i class="fa-solid fa-location-dot"></i> ';
    echo htmlspecialchars($sido1, ENT_QUOTES, 'UTF-8');
    if ($sido2) echo ' › ' . htmlspecialchars($sido2, ENT_QUOTES, 'UTF-8');
    if ($sido3) echo ' › ' . htmlspecialchars($sido3, ENT_QUOTES, 'UTF-8');
    echo '</div>';
endif;
?>
 

방법 B — post_meta 직접 조회

BoardFields 사용하지 않고 post_meta 테이블을 직접 조회하는 방법입니다.
 
⚠ post_id 반드시 (string)으로 캐스팅해야 합니다. (int) 사용 18자리 숫자가 잘려 조회 실패.
 
<?php
// post_meta 직접 조회
$db     = Database::getInstance();
$tblMeta = $db->table('post_meta');

// ⚠ 반드시 (string) 캐스팅 — post_id는 18자리
$postId = (string)$post['id'];

$metaRows = $db->rows(
    "SELECT field_key, value FROM `{$tblMeta}`
     WHERE post_id = ? AND field_key IN ('sido1','sido2','sido3')",
    array($postId)
);

$sido1 = ''; $sido2 = ''; $sido3 = '';
foreach ($metaRows as $mr) {
    if ($mr['field_key'] === 'sido1') $sido1 = $mr['value'];
    if ($mr['field_key'] === 'sido2') $sido2 = $mr['value'];
    if ($mr['field_key'] === 'sido3') $sido3 = $mr['value'];
}

// 출력
if ($sido1):
    echo '<span class="location">';
    echo htmlspecialchars($sido1, ENT_QUOTES, 'UTF-8');
    if ($sido2) echo ' ' . htmlspecialchars($sido2, ENT_QUOTES, 'UTF-8');
    if ($sido3) echo ' ' . htmlspecialchars($sido3, ENT_QUOTES, 'UTF-8');
    echo '</span>';
endif;
?>
 

방법 C — 여분필드 배열 직접 접근 ($extraFields)

일부 스킨에서는 DXCMS $extraFields 배열을 자동으로 주입합니다. 경우 바로 사용 가능합니다.
 
<?php
// $extraFields 배열이 스킨에 자동 주입된 경우
// (스킨의 handler.php 또는 render.php에서 확인 필요)

$sido1 = isset($extraFields['sido1']) ? $extraFields['sido1'] : '';
$sido2 = isset($extraFields['sido2']) ? $extraFields['sido2'] : '';
$sido3 = isset($extraFields['sido3']) ? $extraFields['sido3'] : '';
?>
$extraFields 자동 주입되는지 확인하려면 view.php에서 var_dump($extraFields) 확인하세요.

출력 HTML 예시

<!-- 기본 텍스트 출력 -->
<?php if ($sido1): ?>
<div class="post-region">
  <span class="label">지역</span>
  <span class="value">
    <?php echo htmlspecialchars($sido1, ENT_QUOTES, 'UTF-8'); ?>
    <?php if ($sido2) echo ' › ' . htmlspecialchars($sido2, ENT_QUOTES, 'UTF-8'); ?>
    <?php if ($sido3) echo ' › ' . htmlspecialchars($sido3, ENT_QUOTES, 'UTF-8'); ?>
  </span>
</div>
<?php endif; ?>

<!-- 뱃지 스타일 출력 -->
<?php if ($sido1): ?>
<div class="region-badges">
  <span class="badge sido1"><?php echo htmlspecialchars($sido1, ENT_QUOTES, 'UTF-8'); ?></span>
  <?php if ($sido2): ?>
  <span class="badge sido2"><?php echo htmlspecialchars($sido2, ENT_QUOTES, 'UTF-8'); ?></span>
  <?php endif; ?>
  <?php if ($sido3): ?>
  <span class="badge sido3"><?php echo htmlspecialchars($sido3, ENT_QUOTES, 'UTF-8'); ?></span>
  <?php endif; ?>
</div>
<?php endif; ?>
 
 
 

7. 리스트(list) 스킨에서 데이터 가져오기  ★

게시글 목록(list)에서 행에 지역 정보를 표시하려면 게시글 목록 조회 별도로 post_meta 가져와야 합니다.
 
중요: 목록의 게시글마다 개별 쿼리를 날리면 N+1 문제가 발생합니다. 반드시 IN 절로 번에 조회하세요.
 

방법 A — 목록 조회 일괄 IN 조회 (권장)

게시글 목록을 가져온 , 모든 post_id 모아서 post_meta 번에 조회합니다.
 
<?php
/**
 * 리스트 스킨 — list.php
 * 게시글 목록에서 sido1/sido2/sido3 일괄 조회
 */

// ① $posts 배열이 이미 있다고 가정
//    (DXCMS 스킨에서 $posts 는 자동 주입됨)

// ② 모든 post_id 수집 — 반드시 string으로 처리
$postIds = array();
foreach ($posts as $p) {
    $postIds[] = (string)$p['id']; // ⚠ (string) 필수
}

// ③ sido 데이터 일괄 조회 (IN 절 — 쿼리 1번)
$sidoMap = array(); // [ post_id => ['sido1'=>...,'sido2'=>...,'sido3'=>...] ]

if (!empty($postIds)) {
    $db      = Database::getInstance();
    $tblMeta = $db->table('post_meta');

    // IN 절 플레이스홀더 생성
    $ph      = implode(',', array_fill(0, count($postIds), '?'));
    $params  = array_merge($postIds, array('sido1','sido2','sido3'));

    $metaRows = $db->rows(
        "SELECT post_id, field_key, value FROM `{$tblMeta}`
         WHERE post_id IN ({$ph})
         AND field_key IN ('sido1','sido2','sido3')",
        $params
    );

    foreach ($metaRows as $mr) {
        $pid = (string)$mr['post_id']; // ⚠ (string) 필수
        if (!isset($sidoMap[$pid])) {
            $sidoMap[$pid] = array('sido1'=>'','sido2'=>'','sido3'=>'');
        }
        $sidoMap[$pid][$mr['field_key']] = $mr['value'];
    }
}

// ④ 목록 출력 시 $sidoMap에서 꺼내 사용
foreach ($posts as $p):
    $pid   = (string)$p['id']; // ⚠ (string) 필수
    $sido  = isset($sidoMap[$pid]) ? $sidoMap[$pid] : array();
    $sido1 = isset($sido['sido1']) ? $sido['sido1'] : '';
    $sido2 = isset($sido['sido2']) ? $sido['sido2'] : '';
    $sido3 = isset($sido['sido3']) ? $sido['sido3'] : '';
?>
  <li>
    <a href="..."><?php echo htmlspecialchars($p['title'], ENT_QUOTES, 'UTF-8'); ?></a>
    <?php if ($sido1): ?>
    <span class="region">
      <?php echo htmlspecialchars($sido1, ENT_QUOTES, 'UTF-8'); ?>
      <?php if ($sido2) echo ' ' . htmlspecialchars($sido2, ENT_QUOTES, 'UTF-8'); ?>
    </span>
    <?php endif; ?>
  </li>
<?php endforeach; ?>
 

방법 B — BoardFields getValuesBulk 사용 (지원 )

DXCMS 버전에 따라 BoardFields 일괄 조회 메서드가 있을 있습니다.
 
<?php
// BoardFields 일괄 조회 (DXCMS 8.7+ 지원 여부 확인 후 사용)
if (function_exists('dx_board_fields')) {
    $bf       = dx_board_fields();
    $postIds  = array_map(function($p){ return (string)$p['id']; }, $posts);

    // getValuesBulk 메서드 존재 여부 확인
    if (method_exists($bf, 'getValuesBulk')) {
        $allFields = $bf->getValuesBulk($postIds);
        // $allFields = [ post_id => [ 'sido1'=> ..., 'sido2'=>... ] ]
    }
}

// 지원하지 않는 경우 방법 A (IN 절 직접 조회) 사용
?>
getValuesBulk 메서드가 없으면 방법 A (IN 직접 조회) 사용하세요.

목록 출력 HTML 예시

<!-- 테이블 형태 목록 -->
<table>
  <thead>
    <tr>
      <th>제목</th>
      <th>지역</th>
      <th>작성일</th>
    </tr>
  </thead>
  <tbody>
  <?php foreach ($posts as $p):
    $pid   = (string)$p['id'];
    $sido  = isset($sidoMap[$pid]) ? $sidoMap[$pid] : array();
    $sido1 = isset($sido['sido1']) ? $sido['sido1'] : '';
    $sido2 = isset($sido['sido2']) ? $sido['sido2'] : '';
  ?>
  <tr>
    <td><a href="..."><?php echo htmlspecialchars($p['title'], ENT_QUOTES, 'UTF-8'); ?></a></td>
    <td>
      <?php if ($sido1): ?>
        <span class="badge-region"><?php echo htmlspecialchars($sido1, ENT_QUOTES, 'UTF-8'); ?></span>
        <?php if ($sido2) echo '<span class="badge-region">' . htmlspecialchars($sido2, ENT_QUOTES, 'UTF-8') . '</span>'; ?>
      <?php else: ?>
        <span class="text-muted">-</span>
      <?php endif; ?>
    </td>
    <td><?php echo $p['created_at']; ?></td>
  </tr>
  <?php endforeach; ?>
  </tbody>
</table>
 
 
 

8. 검색 필터 사용법

sido1/sido2/sido3 여분필드는 is_search=1 생성되어 DXCMS 게시판 검색 기능에서 필터링 가능합니다.
 

8-1. DXCMS 기본 검색 URL

// 시/도 검색
/게시판키/list?search_key=sido1&search_val=서울

// 시/군/구 검색
/게시판키/list?search_key=sido2&search_val=강남구

// 동/읍/면 검색
/게시판키/list?search_key=sido3&search_val=역삼동
 

8-2. 목록 스킨에서 지역 검색 직접 구현

<!-- 시/도 필터 셀렉트 -->
<form method="get">
  <select name="search_val">
    <option value="">전체 지역</option>
    <option value="서울" <?php echo (isset($_GET['search_val']) && $_GET['search_val']==="서울") ? 'selected' : ''; ?>>서울</option>
    <option value="경기">경기</option>
    <option value="인천">인천</option>
    <!-- ... -->
  </select>
  <input type="hidden" name="search_key" value="sido1">
</form>
 
 
 

9. 실전 예제 모음

예제 1 — 뷰에서 지역 뱃지 표시 (Bootstrap 스타일)

<?php
// view.php 상단
if (function_exists('dx_board_fields')) {
    $bf     = dx_board_fields();
    $fields = $bf->getValues((string)$post['id']);
    $sido1  = isset($fields['sido1']) ? $fields['sido1'] : '';
    $sido2  = isset($fields['sido2']) ? $fields['sido2'] : '';
    $sido3  = isset($fields['sido3']) ? $fields['sido3'] : '';
}
?>

<!-- 출력 -->
<?php if (!empty($sido1)): ?>
<div class="d-flex gap-1 mb-3">
  <span class="badge bg-primary"><?php echo htmlspecialchars($sido1, ENT_QUOTES, 'UTF-8'); ?></span>
  <?php if (!empty($sido2)): ?>
  <span class="badge bg-secondary"><?php echo htmlspecialchars($sido2, ENT_QUOTES, 'UTF-8'); ?></span>
  <?php endif; ?>
  <?php if (!empty($sido3)): ?>
  <span class="badge bg-light text-dark"><?php echo htmlspecialchars($sido3, ENT_QUOTES, 'UTF-8'); ?></span>
  <?php endif; ?>
</div>
<?php endif; ?>
 

예제 2 — 리스트에서 카드 형태로 지역 표시

<?php
// list.php — 카드형 목록

// 게시글 목록 $posts 에서 post_id 수집
$postIds = array_map(function($p){ return (string)$p['id']; }, $posts);
$sidoMap = array();

if (!empty($postIds)) {
    $db      = Database::getInstance();
    $tblMeta = $db->table('post_meta');
    $ph      = implode(',', array_fill(0, count($postIds), '?'));
    $params  = array_merge($postIds, array('sido1','sido2'));
    $rows    = $db->rows(
        "SELECT post_id, field_key, value FROM `{$tblMeta}`
         WHERE post_id IN ({$ph}) AND field_key IN ('sido1','sido2')",
        $params
    );
    foreach ($rows as $r) {
        $pid = (string)$r['post_id'];
        if (!isset($sidoMap[$pid])) $sidoMap[$pid] = array();
        $sidoMap[$pid][$r['field_key']] = $r['value'];
    }
}
?>

<!-- 카드 목록 출력 -->
<div class="post-grid">
<?php foreach ($posts as $p):
    $pid   = (string)$p['id'];
    $sido  = isset($sidoMap[$pid]) ? $sidoMap[$pid] : array();
    $sido1 = isset($sido['sido1']) ? $sido['sido1'] : '';
    $sido2 = isset($sido['sido2']) ? $sido['sido2'] : '';
?>
<div class="post-card">
  <h3 class="post-title">
    <a href="..."><?php echo htmlspecialchars($p['title'], ENT_QUOTES, 'UTF-8'); ?></a>
  </h3>
  <?php if ($sido1): ?>
  <div class="post-meta">
    <i class="fa-solid fa-map-pin"></i>
    <span><?php echo htmlspecialchars($sido1, ENT_QUOTES, 'UTF-8'); ?></span>
    <?php if ($sido2) echo '<span class="sep">›</span><span>' . htmlspecialchars($sido2, ENT_QUOTES, 'UTF-8') . '</span>'; ?>
  </div>
  <?php endif; ?>
</div>
<?php endforeach; ?>
</div>
 

예제 3 — 특정 지역 게시글만 조회 (직접 쿼리)

<?php
// 서울 강남구 게시글만 가져오기
$db      = Database::getInstance();
$tblPost = $db->table('posts');
$tblMeta = $db->table('post_meta');

$sidoPosts = $db->rows(
    "SELECT p.*, m1.value AS sido1, m2.value AS sido2
     FROM `{$tblPost}` p
     INNER JOIN `{$tblMeta}` m1 ON m1.post_id = p.id AND m1.field_key = 'sido1'
     INNER JOIN `{$tblMeta}` m2 ON m2.post_id = p.id AND m2.field_key = 'sido2'
     WHERE p.board_id = ? AND p.status = 1
       AND m1.value = '서울'
       AND m2.value = '강남구'
     ORDER BY p.id DESC",
    array($board['id'])
);
?>
 
 
 

10. 주의사항 FAQ

 

절대 지켜야 규칙

post_id 18자리 숫자입니다. PHP에서 (int) 캐스팅하면 값이 잘리거나 변환되어 조회가 실패합니다. 항상 (string) 사용하세요.
 
// ✅ 올바름
$postId = (string)$post['id'];
$postId = (string)$editPost['id'];
$postIds[] = (string)$p['id'];
$pid = (string)$mr['post_id'];

// ❌ 잘못됨
$postId = (int)$post['id'];    // 18자리 숫자 잘림
$postId = intval($post['id']); // 동일하게 잘림
 

Q. 수정 지역 선택이 복원되지 않아요.

plugin.php에서 $postId = (int)$editPost['id'] 캐스팅되어 있는지 확인하세요. (string)으로 변경해야 합니다. 현재 v2.0.0에서는 이미 수정되어 있습니다.
 

Q. 리스트에 지역이 표시되지 않아요.

리스트 스킨에는 자동으로 주입되지 않습니다. 설명서 7장의 방법 A(IN 직접 조회) 사용하세요.
 

Q. 뷰에서 $extraFields 비어있어요.

스킨이 BoardFields 자동으로 로드하지 않는 경우입니다. 방법 A(dx_board_fields() 직접 호출) 또는 방법 B(post_meta 직접 조회) 사용하세요.
 

Q. 목록에서 N+1 문제가 우려돼요.

반드시 방법 A(IN 일괄 조회) 사용하세요. 게시글당 개별 쿼리를 날리면 목록 20 기준 20번의 추가 쿼리가 발생합니다. IN 절을 사용하면 쿼리 1번으로 처리됩니다.
 

Q. 2단계로 설정했는데 sido3 남아있어요.

관리자 화면에서 저장 기존 여분필드를 삭제하고 단계에 맞게 재생성합니다. 단계를 2 변경하고 저장하면 sido3 여분필드가 삭제됩니다. , post_meta 이미 저장된 sido3 값은 남아있습니다.
 

Q. 글쓰기 폼에서 셀렉트 위치를 바꾸고 싶어요.

plugin.php dx_board_write_context 훅에서 삽입 위치 결정 로직을 수정하세요. 현재는 "공지/비밀글 체크박스 아래" → "제목 입력 아래" → " 최상단" 순으로 시도합니다.
 
첨부파일 1개 300P

댓글0

로그인 후 댓글을 작성할 수 있습니다.
Plugin 21
41
전체 회원
1,365
전체 게시글
2,408
전체 댓글
11
오늘 방문
51,074
전체 방문
0
현재 접속
인기글 7일 이내
최신글
최신댓글
내 플레이리스트
플레이리스트가 비어있습니다
스튜디오 게시판에서
플레이리스트에 담기 버튼을
눌러보세요
목록
목록