고급 템플릿 문법¶
PHP 코드 직접 사용¶
템플릿에서 PHP 코드를 직접 사용할 수 있습니다:
{@
// PHP 코드 블록
$total = 0;
foreach($list as $item)
$total += $item->price;
}
<p>총액: {number_format($total)}원</p>
{@
블록의 제한사항¶
❌ 중요:
{@
블록 내에서는 중괄호{}
를 중첩해서 사용할 수 없습니다.
잘못된 예:
{@
if($condition) { // ❌ 오류! 중괄호 사용 불가
$value = 'yes';
}
}
올바른 예:
{@
if($condition) // ✅ 중괄호 생략
$value = 'yes';
else
$value = 'no';
}
복잡한 로직은 별도 파일로:
// includes/calculate_total.php
$total = 0;
foreach($list as $item) {
$total += $item->price;
}
return $total;
{@ $total = include 'includes/calculate_total.php'}
<p>총액: {number_format($total)}원</p>
인라인 PHP 표현식¶
<!-- 삼항 연산자 -->
<div class="{$is_mobile ? 'mobile' : 'desktop'}">
<!-- 함수 호출 -->
<p>현재 시간: {date('Y-m-d H:i:s')}</p>
<!-- 복잡한 표현식 -->
<p>{sprintf($lang->welcome_msg, $logged_info->nick_name)}</p>
고급 조건문¶
switch문 구현¶
<!--@switch($document->status)-->
<!--@case('PUBLIC')-->
<span class="public">공개</span>
<!--@break-->
<!--@case('SECRET')-->
<span class="secret">비밀</span>
<!--@break-->
<!--@default-->
<span class="temp">임시저장</span>
<!--@endswitch-->
복잡한 if-elseif-else¶
<!--@if($point >= 1000)-->
<span class="level gold">골드 회원</span>
<!--@elseif($point >= 500)-->
<span class="level silver">실버 회원</span>
<!--@elseif($point >= 100)-->
<span class="level bronze">브론즈 회원</span>
<!--@else-->
<span class="level basic">일반 회원</span>
<!--@endif-->
고급 반복문 기법¶
foreach with 조건¶
{@ $published_count = 0}
<ul>
<block loop="$documents => $document">
<li cond="$document->status == 'PUBLIC'">
{$document->title}
{@ $published_count++}
</li>
</block>
</ul>
<p>공개 문서: {$published_count}개</p>
반복문 제어¶
<block loop="$items => $i, $item">
<!--@if($i >= 10)-->
<!--@break-->
<!--@endif-->
<!--@if($item->is_deleted)-->
<!--@continue-->
<!--@endif-->
<div>{$item->title}</div>
</block>
필터와 파이프¶
기본 필터¶
<!-- 자동 이스케이프 (기본) -->
<p>{$user_input}</p>
<!-- HTML 허용 -->
<div>{$html_content|noescape}</div>
<!-- 자동 링크 변환 -->
<p>{$text|autoescape}</p>
<!-- 줄바꿈을 <br>로 변환 -->
<p>{$text|nl2br|noescape}</p>
커스텀 필터 체인¶
{@
// 필터 함수 정의
function truncate($str, $len = 100)
return cut_str($str, $len, '...');
}
<!-- 필터 체인 적용 -->
<p>{$document->content|strip_tags|truncate:200}</p>
주의:
{@
블록 내에서는 중괄호를 사용할 수 없으므로 함수 정의에서도 중괄호를 생략해야 합니다.
템플릿 상속과 블록¶
레이아웃 정의¶
<!-- layout.html -->
<!DOCTYPE html>
<html>
<head>
<title><!--@block('title')-->기본 제목<!--@endblock--></title>
<!--@block('head')--><!--@endblock-->
</head>
<body>
<header>
<!--@block('header')-->
<h1>사이트 제목</h1>
<!--@endblock-->
</header>
<main>
<!--@block('content')--><!--@endblock-->
</main>
<footer>
<!--@block('footer')-->
<p>Copyright © 2024</p>
<!--@endblock-->
</footer>
</body>
</html>
레이아웃 상속¶
<!-- page.html -->
<!--@extends('layout.html')-->
<!--@block('title')-->게시판 - {$module_info->browser_title}<!--@endblock-->
<!--@block('head')-->
<load target="board.css" />
<!--@endblock-->
<!--@block('content')-->
<div class="board">
<include target="list.html" />
</div>
<!--@endblock-->
매크로와 함수¶
매크로 정의¶
<!--@macro('pagination', $page, $total_page)-->
<ul class="pagination">
<li cond="$page > 1">
<a href="{getUrl('page', $page-1)}">이전</a>
</li>
<block loop="$i=1;$i<=$total_page;$i++">
<li class="active"|cond="$i == $page">
<a href="{getUrl('page', $i)}">{$i}</a>
</li>
</block>
<li cond="$page < $total_page">
<a href="{getUrl('page', $page+1)}">다음</a>
</li>
</ul>
<!--@endmacro-->
<!-- 매크로 사용 -->
<!--@call('pagination', $page_navigation->cur_page, $page_navigation->total_page)-->
캐싱과 최적화¶
템플릿 캐싱¶
<!--@cache('sidebar', 3600)-->
<aside class="sidebar">
<!-- 무거운 연산이나 쿼리가 필요한 내용 -->
<include target="widgets/recent_posts.html" />
<include target="widgets/popular_tags.html" />
</aside>
<!--@endcache-->
조건부 캐싱¶
<!--@cache('user_info_' . $member_srl, 1800, $is_logged)-->
<div class="user-info">
{@ $member_info = getMemberInfo($member_srl)}
<img src="{$member_info->profile_image}" />
<p>{$member_info->nick_name}</p>
</div>
<!--@endcache-->
보안 고려사항¶
XSS 방지¶
<!-- 위험: 사용자 입력을 그대로 출력 -->
<div>{$user_content|noescape}</div> <!-- 위험! -->
<!-- 안전: HTML 이스케이프 -->
<div>{$user_content}</div>
<!-- 안전: 허용된 태그만 허용 -->
<div>{$user_content|removeHackTag|noescape}</div>
CSRF 토큰¶
<form method="post">
<input type="hidden" name="csrf_token" value="{$csrf_token}" />
<!-- 폼 필드들 -->
</form>
디버깅 도구¶
변수 덤프¶
<!--@if(__DEBUG__)-->
<div class="debug">
<pre>{var_dump($variable)}</pre>
<pre>{print_r($array, true)}</pre>
</div>
<!--@endif-->
실행 시간 측정¶
{@ $start_time = microtime(true)}
<!-- 템플릿 내용 -->
{@ $execution_time = microtime(true) - $start_time}
<!-- 실행 시간: {$execution_time}초 -->
모범 사례¶
- 변수 검증: 사용 전에 항상 변수 존재 여부 확인
<div cond="isset($document) && $document">
{$document->title}
</div>
- 기본값 설정: null 가능성이 있는 변수에 기본값 제공
<p>{$document->title ?: '제목 없음'}</p>
- 반복문 최적화: 불필요한 연산은 반복문 밖에서
{@ $total_count = count($list)}
<ul>
<li loop="$list => $item">
{$item->title} ({$total_count}개 중)
</li>
</ul>
- 템플릿 분리: 복잡한 로직은 별도 파일로
<include target="_item.html" loop="$list => $item" />