템플릿 문법 오류와 해결법

템플릿 문법 오류와 해결법

PCRE Recursion Limit 오류

증상

  • 복잡한 조건문이나 반복문 사용 시 백지 화면 표시
  • 특히 cond 속성이 많이 중첩된 경우 발생

원인

PHP의 PCRE(Perl Compatible Regular Expression) 재귀 제한 설정 때문에 발생합니다.

해결 방법

  1. index.php 파일 수정
define('__XE__', TRUE);
// PCRE 재귀 제한 늘리기
@ini_set('pcre.recursion_limit', 500000);
@ini_set('pcre.backtrack_limit', 500000);
  1. .htaccess 파일에 추가 (Apache 서버)
php_value pcre.recursion_limit 500000
php_value pcre.backtrack_limit 500000
  1. 설정 확인 방법
<?php
// test.php 파일 생성
ini_set('pcre.recursion_limit', 500000);
echo ini_get('pcre.recursion_limit');
// 500000이 출력되면 정상

근본적인 해결책

템플릿 파일을 분리하여 복잡도를 줄입니다:

<!-- 나쁜 예: 하나의 파일에 모든 조건문 -->
<div cond="$a">
    <div cond="$b">
        <div cond="$c">
            <!-- 깊은 중첩 -->
        </div>
    </div>
</div>

<!-- 좋은 예: 파일 분리 -->
<include target="_section.html" cond="$a" />

일반적인 문법 오류

1. 따옴표 오류

<!-- 잘못된 예 -->
<div class="wrapper" cond="$type == "main"">  <!-- 따옴표 충돌 -->

<!-- 올바른 예 -->
<div class="wrapper" cond="$type == 'main'">
<!-- 또는 -->
<div class="wrapper" cond="$type == &quot;main&quot;">

2. 변수 범위 오류

<!-- 잘못된 예 -->
<ul>
    <li loop="$list => $item">
        {$item->title}
    </li>
</ul>
<p>{$item->title}</p>  <!-- $item은 loop 밖에서 사용 불가 -->

<!-- 올바른 예 -->
{@ $last_item = null}
<ul>
    <li loop="$list => $item">
        {$item->title}
        {@ $last_item = $item}
    </li>
</ul>
<p cond="$last_item">{$last_item->title}</p>

3. 중첩 루프 변수 충돌

<!-- 잘못된 예 -->
<div loop="$categories => $item">
    <ul loop="$item->children => $item">  <!-- $item 변수 충돌 -->
        <li>{$item->title}</li>
    </ul>
</div>

<!-- 올바른 예 -->
<div loop="$categories => $category">
    <ul loop="$category->children => $child">
        <li>{$child->title}</li>
    </ul>
</div>

4. 조건문 문법 오류

<!-- 잘못된 예 -->
<div cond="$logged_info->is_admin = 'Y'">  <!-- = 대신 == 사용 -->

<!-- 올바른 예 -->
<div cond="$logged_info->is_admin == 'Y'">

<!-- 잘못된 예 -->
<div cond="$count => 0">  <!-- => 대신 >= 사용 -->

<!-- 올바른 예 -->
<div cond="$count >= 0">

5. include 경로 오류

<!-- 잘못된 예 -->
<include target="/skins/board/normal/header.html" />  <!-- 절대 경로 -->

<!-- 올바른 예 -->
<include target="header.html" />  <!-- 상대 경로 -->
<!-- 또는 -->
<include target="./header.html" />

성능 관련 문제

1. 반복문 내 무거운 연산

<!-- 나쁜 예 -->
<li loop="$documents => $doc">
    {@ $member_info = getMemberInfo($doc->member_srl)}  <!-- 매번 쿼리 -->
    {$member_info->nick_name}
</li>

<!-- 좋은 예 -->
{@ 
    // 미리 회원 정보 로드
    $member_srls = array();
    foreach($documents as $doc) {
        $member_srls[] = $doc->member_srl;
    }
    $member_infos = getMembersInfo($member_srls);
}
<li loop="$documents => $doc">
    {$member_infos[$doc->member_srl]->nick_name}
</li>

2. 불필요한 조건 검사

<!-- 나쁜 예 -->
<block cond="$document_list">
    <block cond="count($document_list) > 0">
        <block cond="is_array($document_list)">
            <!-- 중복 검사 -->
        </block>
    </block>
</block>

<!-- 좋은 예 -->
<block cond="$document_list && count($document_list) > 0">
    <!-- 내용 -->
</block>

호환성 문제

1. PHP 버전별 차이

<!-- PHP 5.x와 7.x 호환 -->
{@ 
    // 배열 선언
    $arr = array();  // PHP 5.x 호환
    // $arr = [];    // PHP 5.4+
}

<!-- 널 병합 연산자 -->
<!-- PHP 7.0+ -->
{$title ?? '기본 제목'}

<!-- PHP 5.x 호환 -->
{isset($title) ? $title : '기본 제목'}

2. XE/Rhymix 버전 차이

<!-- Rhymix 전용 기능 사용 시 -->
<!--@if(defined('RX_VERSION'))-->
    <!-- Rhymix 전용 코드 -->
    {rx_lang('message')}
<!--@else-->
    <!-- XE 호환 코드 -->
    {$lang->message}
<!--@endif-->

디버깅 팁

1. 변수 확인

<!-- 개발 중 변수 내용 확인 -->
<!--@if(__DEBUG__)-->
<div style="background: #ffc; padding: 10px; margin: 10px 0;">
    <h4>디버그 정보</h4>
    <pre>{print_r($variable, true)}</pre>
</div>
<!--@endif-->

2. 에러 추적

{@ 
    // 에러 로깅
    if(!$document) {
        debugPrint('Document not found: ' . $document_srl);
    }
}

3. 템플릿 컴파일 캐시 확인

템플릿 수정 후 변경사항이 반영되지 않을 때:

  1. files/cache/template_compiled/ 디렉토리 삭제
  2. 브라우저 캐시 삭제
  3. 디버그 모드 활성화

권장사항

  1. 템플릿 검증: 수정 후 항상 문법 오류 확인
  2. 점진적 개발: 복잡한 템플릿은 단계별로 개발
  3. 코드 분리: 로직은 PHP, 표현은 템플릿으로 분리
  4. 주석 활용: 복잡한 조건문에는 주석 추가
  5. 테스트: 다양한 조건에서 템플릿 동작 확인