개발자 가이드

스킨·레이아웃 제작

스킨은 모듈의 겉모습, 레이아웃은 사이트 전체의 틀입니다. 만드는 방법은 거의 같고 놓이는 위치와 선언 파일이 다릅니다.

위치선언 파일적용 대상
모듈 스킨modules/{모듈}/skins/{스킨}/skin.xml그 모듈의 인스턴스(mid)
레이아웃layouts/{레이아웃}/conf/info.xml사이트(또는 mid별 지정)

모듈 스킨 만들기

기존 모듈에 새 겉모습을 입히려면, 그 모듈의 skins/default/ 를 통째로 복사해 이름을 바꾸는 것에서 시작하세요. 어떤 템플릿 파일이 필요하고 어떤 변수가 내려오는지는 기본 스킨이 정답지입니다.

modules/board/skins/myskin/
├── skin.xml
├── list.html        ← 목록 (+ 상세는 _read.html 포함 방식)
├── _read.html
├── _comment.html
├── write_form.html
├── css/skin.css
└── ...

skin.xml

<?xml version="1.0" encoding="UTF-8"?>
<skin version="0.2">
	<responsive>true</responsive>
	<title xml:lang="ko">내 스킨</title>
	<description xml:lang="ko">설명</description>
	<version>1.0.0</version>
	<date>2026-08-05</date>
	<author email_address="you@example.com" link="https://example.com">
		<name xml:lang="ko">제작자</name>
	</author>
	<extra_vars>
		<var name="list_style" type="select" default="list">
			<title xml:lang="ko">목록 형태</title>
			<options value="list"><title xml:lang="ko">목록형</title></options>
			<options value="card"><title xml:lang="ko">카드형</title></options>
		</var>
	</extra_vars>
</skin>
  • <responsive>true</responsive> 는 이 스킨이 좁은 화면까지 감당한다는 표시입니다. 반응형 뷰와 반응형 표시 참고.
  • <extra_vars> 로 선언한 스킨 설정은 템플릿에서 $module_info->{변수명} 으로 읽습니다.

지켜야 할 것

  • 스킨은 화면만 바꿉니다. 서버가 내려주는 변수와 폼 규약은 기본 스킨과 같게 유지해야 합니다. 폼의 hidden 필드(module, act, mid 등)를 빼먹으면 저장이 안 됩니다.
  • 게시판 목록 칼럼처럼 관리자 설정과 연동되는 부분($list_config 등)은 하드코딩하지 말고 설정값을 따르세요.
  • 아이콘은 이미지 파일 대신 인라인 SVG를 권장합니다.

레이아웃 만들기

layouts/mylayout/
├── layout.html      ← 뼈대. {!! $content !!} 자리에 본문이 들어감
├── conf/info.xml
├── css/layout.css
└── js/layout.js

layout.html 최소 골격

@version(2)
@load('css/layout.css')
@load('js/layout.js')

<div class="my-layout">
	<header>
		<a href="{{ getUrl('') }}">{{ $layout_info->logo_text ?: '사이트' }}</a>
		<nav>
			@foreach ($gnb->list ?? [] as $item)
			<a href="{{ $item['href'] }}" @if (!empty($item['selected'])) class="on" @endif>{{ $item['text'] }}</a>
			@endforeach
		</nav>
	</header>

	<main>{!! $content !!}</main>

	<footer>{{ $layout_info->copyright }}</footer>
</div>
  • 본문은 {!! $content !!} 로 출력합니다. 이스케이프하면 안 됩니다.
  • 메뉴는 info.xml의 <menus> 선언에 따라 $gnb->list 등으로 내려옵니다. 각 항목은 text(이름) href(주소) selected/open(현재 위치) list(하위 메뉴) 를 가집니다.

conf/info.xml

<?xml version="1.0" encoding="UTF-8"?>
<layout version="0.2">
	<responsive>true</responsive>
	<title xml:lang="ko">내 레이아웃</title>
	<version>1.0.0</version>
	<author email_address="you@example.com" link="https://example.com">
		<name xml:lang="ko">제작자</name>
	</author>

	<menus>
		<menu name="gnb" maxdepth="3" default="true">
			<title xml:lang="ko">상단 메뉴</title>
		</menu>
	</menus>

	<extra_vars>
		<group>
			<title xml:lang="ko">기본</title>
			<var name="logo_text" type="text">
				<title xml:lang="ko">로고 텍스트</title>
			</var>
			<var name="point_color" type="color" default="#2677e3">
				<title xml:lang="ko">포인트 색상</title>
			</var>
		</group>
	</extra_vars>
</layout>
  • extra_vars의 <var> 는 반드시 <group> 안에 두세요. 레이아웃 상세설정은 그룹을 탭으로 그리므로 그룹 밖의 변수는 화면에 보이지 않습니다.
  • 설정값은 템플릿에서 $layout_info->{변수명} 으로 읽습니다.
  • 슬라이더·배너처럼 반복되는 항목은 반복 필드로 선언하세요.

레이아웃 CSS에서 지킬 것

  • html, body { margin: 0; background: ... } 를 반드시 함께 선언하세요. 최상위 div에만 배경을 칠하면 body 기본 여백과 스크롤 거터가 흰색으로 남아, 다크 모드에서 화면 사방에 흰 테두리처럼 보입니다.
  • 다크 모드를 지원한다면 색을 CSS 변수로 모으고 data-theme 속성 또는 prefers-color-scheme 으로 전환하세요.
  • 포인트 색상 설정을 받는다면 style="--brand: {{ $layout_info->point_color }}" 처럼 변수로 내려서 CSS 전체가 따라가게 만드는 것이 관리하기 쉽습니다.

배포

스킨·레이아웃은 폴더째 압축해 스토어에 등록하거나 직접 설치(해당 경로에 업로드)합니다. 레이아웃과 모듈 스킨을 세트로 배포하려면 테마 패키지로 묶으세요.