Spyce와 함께 하는 파이썬 웹 프로그래밍 3
Spyce와 Cheetah 템플릿 프로그래밍
이번호에서는 웹 프로그래머와 웹 디자이너 간에 싸우지 않는 범위를 제공하는 특별한 유틸리티인 Cheetah 템플릿을 Spyce에서 사용하는 방법과 2편에서 배웠던 데이터베이스 사용을 Cheetah 템플릿을 통해 구현해보기로 한다.
현재 리눅스 엔지니어로 일하고 있으며, 웹과 그 기반 기술들에 대해 관심이 많다. 파이썬과 PostgreSQL에도 관심이 많아 항상 이 둘을 어떻게 하면 잘 사용할까 생각한다. 요즘은 동갑내기 여자 가수인 이소은을 쫓아다니며 어떻게 하면 고백할 수 있을까 고민 중이다.
연재순서
1회 2005.10 Spyce를 통한 PSP 프로그래밍
2회 2005.11 Spyce와 데이터베이스 연동
3회 2005.12 Spyce와 Cheetah를 이용한 템플릿 사용
웹 프로그래머는 웹 프로그램을 설계하고 제작하는 동안에 디자이너와 싸우는 일이 일상에 포함되어 있다고 말할정도로 사이가 좋지 않다. 서로간의 의사소통이 잘 되지 않는 것이 그 첫 번째 이유가 되겠지만 다른 이유도 있다. 서로간의 일의 영역을 직접적으로 침범하는 것이 그 2번째 이유가 있다.
예전과는 세태가 많이 변한 지금은 영역 침범에 있어 그다지 깊게 침범하지 않게 되었는데 이러한 것의 주요한 변화의 중심에는 템플릿이 존재한다. 그렇다면 템플릿은 무엇이고 왜 사용하는가를 먼저 알아보도록 한다.
템플릿은 영한사전에서 다음과 같은 뜻을 가지고 있다.
① 어떤 도식이나 서식에서 자주 사용되는 기본 골격. 스프레드시트에서 각종 데이터 처리를 위해 표의 일정한 구조를 만들어 놓고 사용자가 데이터를 입력만 하면 되도록 해 놓은 것이 한 예이다.
② 그래픽 프로그램에서 자주 사용하기 위해 미리 정해 놓은 그림이나 이미지의 일정한 패턴
꺼내서 이야기 하고자 하는 주제는 1번의 뜻이다. 웹에서 템플릿의 사용은 프로그램과 디자인의 분리에 그 이유가 있다. 템플릿은 현재 프로그래밍에 쓰이는 언어와 상관없이 웹 프로그래밍을 하는 곳이라면 사용되어 지고 있다.
그렇다면 웹에서의 템플릿은 어떻게 사용되어지고 있을까? 웹에서의 템플릿 사용은 사용자에게 보여지는 페이지. 다시 말해 순수한 HTML 페이지안에 프로그램에서 출력하는 값을 출력하기 위해 특정한 코드를 넣는 방법으로 템플릿은 사용된다.
파이썬에서는 많은 템플릿 언어가 있다. 지금 이야기하고자 하는 Cheetah 템플릿 외에도 Empy, SimpleTAL 등이 있는데 여기서는 이전 2편에서 예고한대로 Cheetah 템플릿을 Python에서 사용하는 것을 다룬다.
Cheetah 템플릿은 Python 기반의 템플릿 언어이다. Cheetah 템플릿은 배우기 쉬운 언어중 하나이다. Cheetah 템플릿은 다음의 사이트에서 얻을 수 있다.
(cheetah-homepage.png)
[그림 1] Cheetah 템플릿 사이트(http://www.cheetahtemplate.org/)
Cheetah 템플릿 설치
이제 Cheetah 템플릿을 사용하기 위해서 Cheetah 템플릿을 설치하고 사용해보자. 우선 할 것은 Cheetah 템플릿 홈페이지에 방문하고 Cheetah 템플릿을 설치하는 것이다.
Cheetah 템플릿을 다운로드 받기 위해 Download 링크로 가면 SourceForgeproject page 라는 링크를 볼 수 있다. 이 링크를 눌러 Sourceforge.net의 프로젝트 사이트로 이동한다. 그럼 화면 중간에 Latest File Releases 라는 섹션이 있고 바로 아래 Cheetah 라는 낯 익은 이름과 옆쪽으로 현재 버전인 1.0rc2 가 명시되어 있고 그 옆에 Download 라는 링크를 클릭하면 Cheetah 템플릿을 다운로드 받을 수 있다. 제공되는 형식은 tar.gz 형식이다.
http://sourceforge.net/project/showfiles.php?group_id=28961&package_id=20864&release_id=372298
Cheetah 템플릿의 설치는 Linux에서 다음과 같은 절차를 따라 설치한다.
* Cheetah 템플릿을 다운로드 받는다.
* gzip으로 압축된 tarball 형식의 압축을 임의의 디렉토리에 풀어낸다.
* 루트 유저로 계정을 변경한다.
* 임의의 디렉토리에서 다음의 명령을 내린다.: python setup.py install
* 다음의 디렉토리로 이동한다.: /usr/lib/python2.3/site-packages/
* 다음 명령을 내린다: chmod -R a+r Cheetah*
* 다음 명령을 내린다: chmod a+x `find Cheetah -type d`
Cheetah 템플릿을 설치하기 위해선 python-dev 패키지가 필요하다. 파이썬 버전에 따라 site-packages 디렉토리의 위치는 조금씩 다를 수 있다. 필자의 경우는 파이썬 버전은 2.3에서 하였다.
이제 Cheetah 템플릿 설치를 마쳤으니 본격적으로 Cheetah 템플릿에 대해 알아보고 Spyce에서 어떻게 Cheetah 템플릿을 사용해서 PSP 페이지를 만들어내는지 보자.
Cheetah 템플릿 언어 구성
Cheetah 템플릿은 크게 11개 부분으로 표 1과 같이 구성되어 있다.
요약 이름 | 포함되는 내용 |
주석 | (a) ## single line (b) #* multi line *# |
Generation, caching and filtering of output | (a) plain text (b) lookup a value : $placeholder (c) evaluate an expression : #echo ... (d) same but discard the output: #silent (e) one-line if: #if EXPR then EXPR else EXPR (f) gobble the EOL : #slurp (g) parsed file includes : #include (h) raw file includes : #include raw (i) verbatim output of Cheetah code: $raw .. #end raw (j) cached placeholders: $*var, $* (k) cached regions: #cache ... #end cache (l) set the output filter: #filter (m) control output indentation: #indent |
파이썬 모듈 임포트 | #import ..., #from ... |
상속 | (a) set the base class to inherit from: #extends (b) set the name of the main method to implements ... |
컴파일 시간에 정의 | (a) define class attributes: #attr (b) define class method: #def ... #end def |
실행시간에 할당 | (a) local vars: #set (b) global vars: #set global (c) deleting local vars: #del |
순서 제어 | (a) #if ... #else ... #else if(aka #elif) ... #end if (b) #unless ... #end unless (c) #for ... #end for (d) #repeat ... #end repeat (e) #while ... #end while (f) #break (g) #continue (h) #pass (i) #stop |
에러/예외 핸들링 | (a) #assert (b) #raise (c) #try ... #except ... #else ... #end try (d) #try ... #finally ... #end try (e) #errorCatcher ...set a handler for exceptions raised by $placeholder calls. |
파서/컴파일러 명령어 | (a) #braekpoint (b) #compiler-settings |
파이썬 코드 이스케이프 | (a) evaluate expression and print the output: <%= ... %> (b) execute code and discard output: <% ... %> |
Cheetah로부터 생성된 파이썬 모듈 제어 | (a) set the source code encoding of compiled template modules: #encoding (b) set the sh-bang line of compiled template modules: #shBang |
<표1> Cheetah 템플릿 언어 구성
11개 부분은 또 다시 몇 개의 세세한 부분으로 나뉘어진다. 표1에서는 필자가 글을 쓰면서 혹시 오역한 부분이 있을까 하여 원문 설명을 기재하였다. 이제 서서히 11개 부분의 구성 요소에 대해 알아보며 사용방법을 익혀보기로 한다.
1. 주석
주석은 어떤 프로그래밍 언어든 매우 중요한 요소로 군림되어 온다. 요약해서 주석 없는 프로그램은 쓰레기일 뿐이다. 물론 오래전이야 주석은 없거나 말거나 크게 신경 쓸 요소는 아니었다지만, 소프트웨어 개발비용의 80% 이상을 가져가는 요소가 유지보수라고 하니 유지 보수에 필요한 주석은 몇 번을 말해도 크게 어긋나지 요소가 아닐 수 없을 것이다.
하지만 이러한 주석의 사용에는 무조건 많이 다는 것보다 적재적소에 배치하는 것이 주석을 사용하는 올바른 방법이다. Cheetah에서도 주석을 사용할 수 있는데 크게 2가지의 사용방법을 가지고 있다.
싱글 라인 주석 : ## single line
멀티 라인 주석 : #* multi line *#
코드1은 주석의 간단한 사용방법을 보여주고 있다.
## Cheetah 의 한 라인 주석입니다.
#*
여기에는 여러줄의 주석을 만들 수 있습니다.
주석이 길면 여기에 넣으면 되겠지요?
*#
[코드1]
2. Generation, caching and filtering of output
템플릿의 사전적 의미를 기억한다면 템플릿은 단지 틀이라는 것이 기억날 것이다. 그렇다면 틀에 데이터를 어떻게 넣을 수 있는가에 대한 질문은 프로그램에서 템플릿으로 데이터를 내보내는 것으로 답을 나타낸다. 물론 이 부분에서는 단순한 출력 이외에 다양한 출력 요소가 포함되어 있다. 다음에 나열할 요소는 실제 활용되고 있는 주요한 요소들이다.
(a) 일반 텍스트
(b) 값 찾기 : $placeholder
(c) 수식 계산 : #echo ...
(d) 수식이 실행된 결과를 출력하지 않는다 : #silent ...
(e) 1라인 조건문 : #if ... then ... else ...
(f) gobble the EOL : #slurp
(g) 파일 인클루트 : #include ...
(h) 변수 캐쉬 : $var, $*
(i) 영역 캐쉬 : #cache ... #end cache
(a) 일반 텍스트
일반적인 텍스트를 출력하며 별도로 텍스트를 감싸거나 하는 것은 없다. 일반적인 텍스트를 써주면 출력된다.
(b) 값 찾기 : $placeholder
스크립트에서 보내온 값을 찾아 출력한다. 별도로 $placeholder라는 변수나 제어문은 아니다. 값 찾기는 다양한 방법으로 찾을 수 있는데 권장되는 방법은 중괄호({ }) 로 둘러싸인 형식이다.
${var}
${var['abc']}
참고박스 - $placeholder 란?
본문에서 $placeholder 란 이름을 자주 쓰게 될 텐데 Cheetah 템플릿에서 변수를 지정하는 별도의 룰의 이름이다. 실제 이 이름은 쓰이지 않으므로 여기서는 변수를 이름짓는 룰이라고 생각하자.
한가지 주의할 것은 값을 찾을 때 변수명은 대소문자를 구별한다는 것이다. 다음의 예를 보면 이해가 쉬울 것이다.
(O) ${var} (X) ${Var} (X) ${vAR} (X) ${vaR}
(c) 수식 계산
지시어명 : #echo
문법 : #echo EXPR
수식을 계산해 출력한다. 수식 값을 바로 출력할 필요가 있을 때 유용하게 사용할 수 있다. 물론 이러한 수식 계산은 템플릿 안에서 수행되고 이러한 수식이 캐싱될 경우 서버로 가해지는 부담이 덜어질 수 있다. 다음은 수식의 사용 예와 그림2의 출력결과를 보여준다. 예제는 예제1에서 (c), (d), (e) 의 spy 스크립트 파일과 템플릿 파일을 보여준다.
예) Here is my #echo ', '.join(['silly'])*5) #example
(d) 수식이 실행된 결과를 출력하지 않는다
지시어명 : #silent
문법 : #silent EXPR
#echo 와 다르게 수식이 실행된 결과를 출력하지 않는다. 이 지시어는 수식이 필요한데 계속 출력될 경우에 수식값을 출력하지 않음으로서 나중에 수식을 재이용할 수 있도록 한다. 그림2는 #slient의 출력 결과를 보여주지 않는다.
(e) 1라인 조건문
지시어명 : #if ... then ... else ...#
문법 : #if EXPR1 then EXPR2 else EXPR3#
1라인 조건문은 즉석에서 바로 조건에 따라 결정해야 할 경우 사용할 수 있다. 1라인 조건문은 c나 PHP에서 다음과 같은 문장과 같은 기능을 수행한다. 그림2는 #silent의 출력 결과를 보여주지 않는다.
(EXPR1) ? EXPR2 : EXPR3
--- (echo_not_if.spy) ---
[[.import name=template]]
[[=template.cheetah('echo_not_if.tmpl')]]
--- (ehco_not_if.tmpl) ---
## echo directive execute
Here is my #echo ', '.join (['silly'])*5 # example
## slient directive execute
#silent 1+2
## 1line if directive execute
#if (1+2) == 4 then 3+4 else "values not equal 3"#
<예제1> #echo, #silent, 1라인 #if 지시어 사용 예제
(equal_not_if.png)
<그림2> #echo, #silent, 1라인 #if 지시어 출력
(f) gobble the EOL
지시어명 : #slurp
문법 : #slurp
Python은 값을 출력한 이후 자동적으로 개행을 한다. 이러한 개행을 억지로 막기 위해서 #slurp 지시어를 사용한다. #slurp 지시어는 개행을 처리하는 문장뒤에 붙을 수 있다. #slurp 지시어는 #if, #for, #while 등의 개행을 자동적으로 처리하는 지시어 등에서 사용된다.
(g) 파일 인클루드
지시어명 : #include
문법 : #include FILENAME_EXPR
Cheetah 템플릿에서는 직접적으로 파일을 인클루드 할 수 있다. 물론 spyce 내에서도 include 문을 사용해서 파일을 인클루드 할 수 있다. 그렇지만 템플릿 내에서 인클루드 하는 것은 조금 더 특별한 의미를 지닐 수 있다. 예를 들어 head.html 파일을 인클루드 하는데 이 것을 모든 페이지에서 스크립트 파일이 제어한다면 디자이너는 항상 스크립트 파일을 수정하거나 프로그래머에게 맡겨야 하지만 바로 필요한 파일을 직접 인클루드 할 수 있다면 마찰도 조금 더 적게 일어날 수 있을 것이다.
#include 지시어는 크게 2가지 문법이 있다. 코드2는 그 문법을 보여준다. 그림3과 예제2는
인클루드의 사용 예를 보여준다.
#include "includeFileName.txt"
#include source=$myParseText
<코드2> 인클루드 예
--- (include.spy) ---
[[.import name=template]]
[[
myParseText="/var/www/apache2-default/included_file.txt"
]]
[[=template.cheetah('include.tmpl')]]
--- (include.tmpl) ---
## included_file.txt including
#include "/var/www/apache2-default/included_file.txt"
## include source attribute including
#include source=$myParseText
##include source="/var/www/apache2-default/included_file.txt"
--- (included_file.txt) ---
인클루드 되는 파일입니다. 이 파일은 2번 인클루드 될 것입니다
<예제2> 인클루드 실행 예제
(include_executing.png)
<그림3> 인클루드 실행 예제
참고박스 - #include 지시어 사용시 경로사용에 대해서
앞서 예제에는 크게 2가지 문법으로 파일을 읽어들인다고 했는데, 인클루드의 경로를 자세히 보면 알 수 있겠지만 2가지 문법으로 파일을 인클루드할 때 반드시 시스템(웹이 아님)의 / 를 기준으로 절대 경로를 써주어야 한다.
(h) 변수 캐쉬
문법 : $var, $*
변수 캐쉬는 어떤 변수를 캐싱할 필요가 있을 때 유용하게 사용할 수 있는데 크게 3가지의 사용용법이 존재한다.
표2는 변수를 캐쉬하는 방법을 보여준다.
변수 사용 | 영향 |
$var, ${var} | dynamic - 요청할때마다 변수를 갱신한다. |
$var, $*{var} | static - 변수는 캐싱되서 변하지 않는다. |
$*5*var, $*5*{var} | timed refresh - interval이 지나면 요청했을 때 값을 갱신한다. |
<표2> 변수 캐쉬 사용방법 예
interval을 사용한 방법에서 주의할 점은 interval은 초를 의미한다.
(i) 캐쉬 영역
지시어 : #cache ... #end cache
문법 :
지시어명 | 문법 |
#cache | #cache [id=EXPR] [timer=EXPR] [test=EXPR] EXPR #end cache |
<표3> 캐쉬 영역에 사용되는 문법
Cheetah에서는 변수 값뿐만 아니라 일정 영역을 캐쉬 영역으로 지정해서 캐싱이 가능하다. 캐쉬 영역에서는 변수 캐시 방법을 사용할 수 있으며, 캐시가 지속될 시간을 지정할 수 있다.
3. 파이썬 모듈 임포트
지시어명 : #import, #from
문법 :
지시어명 | 문법 |
#import | #import moduleName |
#from | #from moduleName import (methodName or ClassName) |
<표4> 파이썬 모듈 임포트 문법
Cheetah에선 #import 지시어와 #from 지시어를 사용해서 파이썬 모듈들을 임포트해서 사용할 수 있는데 본래의 템플릿 사용 용도를 위해하니 권장하지 않는다.
예) #import math
#from math import sin, cos
4. 상속
지시어명 : #extends
문법 : #extends className
템플릿 페이지 내에서 #extends 지시어를 사용하면 템플릿 페이지는 서브 클래스가 되어 페이지를 만들 수 있다. 이 외에 #implements 지시어가 있다.
5. 컴파일 시간에 정의
지시어명 : #attr, #def
문법명 :
지시어명 | 문법 |
#atrr | #attr $placeholder=값 |
#def | ##def METHOD[ (ARGUMENTS) ] ... #end def // 이 문법은 여러줄의 메소드를 정의하기에 좋다. |
#def METHOD[ (ARGUMENTS) ] : TEXT_AND_PLACEHOLDERS // 이 문법은 1 라인으로 이루어진 메소드를 정의하는데 사용된다. |
<표5> 컴파일 시간에 정의하는 지시어 문법
Cheetah 템플릿을 컴파일 할 때 2가지의 지시어를 사용해서 템플릿 프로그래밍을 더욱 유용하게 할 수 있는데, 다음의 2가지는 템플릿 자체에 유용하기 보다 템플릿 자체적으로 사용하기 위해서 유용한 것이다.
#attr : 클래스 내의 속성을 정의한다.
#def : 클래스 내의 메소드를 정의한다.
1번째 문법은 파이썬에서 너무나 자주 사용하는 문법이지만 2번째 문법은 흡사 람다식을 연상케 한다.
이렇게 정의된 메소드는 $METHOD() 형식으로 호출한다. 예제3과 그림4는 attr 지시어와 #def 지시어의 사용을 실례로 보여준다. 메소드는 소괄호를 명시하지 않아도 호출이 가능하다.
--- (attr_def.spy) ---
[[.import name=template]]
[[\
a = "a"
b = "b"
def c(number):
return number
]]
[[=template.cheetah('attr_def.tmpl')]]
--- (attr_def.tmpl) ---
## attr directive usage
#attr $title = "Rob Roy"
#attr $author = "Sir Walter Scott"
#attr $version = 123.4
$title, by $author, version $version
## def directive usage
#def myMeth()
This is the text in my method
$a $b $c(123) ## these placeholder names have been defined elsewhere
#end def
## and now use it...
$myMeth()
## 1 line def directive usage
#attr $adj = 'Travel'
#def myMeth2: This is the $adj method
$myMeth2
<예제3> #attr 지시어와 #def 지시어 예제
(attr_def.png)
<그림4> #attr 지시어와 #def 지시어를 사용한 것을 출력
6. 실행 시간에 할당
지시어명 : #set, #del
문법 :
지시어명 | 문법 |
#set | #set $adj = 100 // adj 란 이름의 지역변수 선언 |
#set global $adj // adj 란 이름의 전역변수 선언, 지역변수가 선언되어 있으면 지역변수가 우선한다. | |
#del | #del 변수명 // 변수를 삭제하며 삭제할 수 있는 변수 범위는 지역변수만 삭제할 수 있다. |
<표6> 실행시간에 사용할 수 있는 지시어의 문법
실행 시간에 값을 할당하는 것은 혹시나 모를 상황에 대비해서 값이 스크립트에 없을 경우 임의의 값으로 처리하기 위해서이다. 값의 선언은 2개방법이 있지만 값의 삭제는 1개방법만 있다. 흔히 지역 안에서 선언되는 값을 지역변수라고 한다.
#set $adj = 100 ## 지역변수 선언
#set global $adj = 100 ## 전역변수 선언
물론 이 값을 삭제하기 위해선 #del 지시어를 사용할 수 있다. 그렇지만 여기서 주의할 것은 #del 지시어는 지역변수 값만 삭제한다는 사실이다. 값의 삭제는 한번에 여러개의 값이 삭제가 가능하다. 다음은 그 방법을 보여주고 있다.
#del $adj, $ss501
7. 순서 제어
템플릿이 단지 틀만 제공하는 것이라 하지만 스크립트에서 미처 처리하기 어려운 것은 템플릿에서 프로그래밍을 처리가 가능하다. 앞서 컴파일과 실행시간에 정의하고 할당하는 것은 미처 처리하기 어려운 것을 처리하기 위해 효과적이다. 하지만 여기서 순서 제어는 단지 처리하기 어려운 것만을 처리하기 위해서만은 아니다. 이러한 예를 가장 잘 뒷받침 해주는 것은 테이블인데, 테이블에는 서로 다른 데이터가 같은 열(column)을 유지하며 새로운 행(row)를 출력하는데, 이러한 데이터를 출력하기 위해선 반복이 필수적이다. 다음은 이러한 제어를 하는데 필요한 몇 가지 주요한 지시어를 설명한다.
지시어명 : #for ... #end for
문법 :
지시어명 | 문법 |
#for | #for $placeholder in EXPR EXPR #end for |
<표7> #for 지시어 문법
지시어명 : #if .. #end if
문법 :
지시어명 | 문법 |
#if | #if EXPR ... #else if EXPR ... #elif EXPR ... #else ... #end if |
<표8> #if 지시어 문법
#if 지시어의 주 사용 용도는 너무도 자명한데, 다시한번 설명을 들어보면 어떤 표현식이나 $placeholder 에 따라 서로 다른 표현식 또는 $placeholder를 출력한다. #if 지시어는 #else if 지시어와 #elif 지시어 와 동등한 순위를 갖게 되는데 #else if 지시어는 #elif 지시어는 서로 같은 의미이다. 사용할 경우 어떤 것을 사용한다고 먼저 명시해두고 사용하는게 좋다.
지시어명 : #break, #continue
문법 :
지시어명 | 문법 |
#break | #break |
#continue | #continue |
<표9> #break, #continue 지시어 문법
#break 지시어는 for 지시어에서 사용 가능하며 #continue 지시어는 while 지시어에서 사이 가능하다
지시어명 : #stop
문법 : #stop
템플릿 수행을 정지한다. 이때의 템플릿 컴파일 수행은 잠시 정지되는 것이 아니라 템플릿 컴파일을 멈추어 버린다.
8. 에러/예외 핸들링
파이썬에서만 에러와 예외 처리가 가능한 것은 아니다. 템플릿 내에서도 예외와 에러 처리가 가능한데 다음의 방법과 문법으로 에러와 예외 처리가 가능하다.
지시어명 | 문법 |
#try | #try ... #except [ErrorClass] ... #end try |
#try .. #except [ErrorClass] ... #else ... #end try | |
#try ... #flnally ... #end try |
<표10> 예외/에러 핸들링 문법
ErrorClass는 파이썬의 에러 클래스를 사용한다. 에러 클래스에 대해 알고 싶으면 파이썬 에러 클래스를 찾아보시길 바란다.
위와 같은 수동적인 방법으로 에러 처리를 외에도 #errorCatcher 지시어와 ErrorCatcher 객체를 이용해서 에러를 자동적으로 처리할 수 있는 방법도 존재한다.
9. 파서/컴파일러 명령어
지금까지 지나왔던 내용이 단지 템플릿을 구성했다면 지금 알아볼 것은 템플릿을 디버깅하고 제어하는 부분이다.
지시명 : #breakpoint
문법 : #breakpoint
#breakpoint 지시어는 #stop지시어와 기능상 거의 동일하지만 사용 위치가 다르다. #stop은 제어 지시어인 #if 등에 상관없이 아무곳에서나 동작하지만 #breakpoint 지시어는 제어 지시어의 위치에 삽입되어 동작한다. 조금 복잡하게 설명한 감이 있지 않나 싶은데 #stop은 템플릿의 실행을 완전히 정지하는 것이고 #breakpoint 지시어는 템플릿 실행중에 디버깅할 때 사용하는 지시어라는 차이점이 존재한다.
지시어 : #compiler-settings
문법 :
지시어명 | 문법 |
#compiler-settings | #compiler-settings ... #end compiler-settings |
<표11> compilert-settings 문법
#compiler-settings 지시어는 템플릿 컴파일 환경을 지정할 수 있다. 지정할 수 있는 것은 문법과 코드 생성에 관해서 컴파일러 설정이다.
syntax settings | code generation settings |
(a) cheetahVarStartToken (b) commentStartToken (c) multilineCommentStartToken (d) multilineCommentEndToken (e) directiveStartToken (f) directiveEndToken | (a) commentOffset (b) outputRowColComments (c) defDocStrMsg (d) useNameMapper (e) useAutocalling (f) reprShortStrConstants (g) reprNewlineThreshold |
<표12> compiler-settings에서 사용 가능한 설정값
#compiler-settings 지시어에 설정값을 설정할때는 #compiler-settings 지시어와 #end compiler-settings 지시어 사이줄에 넣어야 한다. 설정값에 대한 내용은 컴파일할 때 쓸 코드에 관해서는 Cheetah의 가이드를 참조하길 바라며, 여기서는 syntax settings에 관해서만 간략하게 설명하고 넘어가도록 한다. syntax settings은 문법에 관한 것으로 지시어 설정에 쓰이는 기호의 시작,끝 기호를 사용할 수 있으며 주석에 관해서도 같은 방법을 사용할 수 있다. 만약 C++ 스타일의 주석을 사용하고 싶다면 다음과 같이 compiler setting 을 설정하면 된다. 그렇지만 기존에 사용하던 ##, #* *# 방식의 주석은 사용할 수 없게 되니 사용에 주의하는 것이 좋다.
#compiler-settings
commentStartToken = //
multilineCommentStartToken = /*
multilineCommentEndToken = */
#end compilet-settings
<코드3> C++ 스타일의 주석을 설정할 수 있도록 사용하기
다른 설정값에 대해서는 한번씩 해보고 결과를 익혀두면 공동 작업시 능률을 기대할 수 있을 것으로 보인다.
10. 파이썬 코드 이스케이프
문법 : <%=expr%>, <% expr %>
앞서서 언급되었던 내용 중에는 실제 템플릿에 목적에 맞는 지시어들(#for, #if 등)도 있지만 템플릿답지 않게 만드는 지시어들도 몇 가지 포함되어 있었다. 이러한 지시어들 중에는 파이썬 코드만을 이스케이프 하는 방법도 있는데 파이썬 코드를 직접 템플릿 내에 구사하는 것은 올바르지 않다. 여러 데이터를 출력하기 위한 for문이나 출력을 결정하기 위한 if 문등은 예외가 될 수 있겠지만 말이다.
expr은 표현식을 의미하며 첫 번째 문법(<%=%>)은 값을 출력하는데 많이 쓰인다. 물론 여기서 이 부분은 앞서 언급되어진 #echo 지시어와 #silent 지시어와 동일한 기능을 수행한다.
11. Cheetah로부터 생성된 파이썬 모듈 제어
Cheetah는 템플릿을 컴파일 후에 최종적인 파이썬 모듈을 만들어 내는데 다음 2개 지시어는 파이썬 모듈을 수동적으로 실행할 때 파이썬 프로그램의 위치와 모듈의 엔코딩 값을 바꾼다.
지시어명 : #encoding
문법 : #ecoding UTF-8
모듈의 엔코딩을 지정하며 다음은 출력 예제를 보여준다.
result) # -*- coding: UTF-8 -*-
지시어명 : #shbang
문법 : #shbang #!파이썬 인터프리터 위치
모듈을 수동적으로 실행할 경우 파이썬 프로그램의 위치를 지정한다.
result) #!/usr/bin/env python
이 지시어는 기본적으로 다음의 값을 기본값으로 가져간다.
#!/usr/bin/env python
Tip : 템플릿 내에서 request 객체의 값 가져오기
템플릿 내에서 request 객체로 전달된 필드 값을 바로 가져올 수 있다. 다음과 같이 사용하면 된다.
${request.field('getArgs')}
여기서 getArgs는 실제 URL이나 POST 메소드로 전달될 필드명을 적어준다. 그러면 굳이 템플릿의 사전형 값에 추가하지 않아도 request 객체의 값을 받을 수 있게 된다.
spyce에서 cheetah 템플릿 사용하기
지금까지는 cheetah 템플릿의 문법에 치중하여 cheetah 템플릿을 알아보았다. 지금 알아볼 것은 spyce에서 cheetah 템플릿을 사용하는 것이다. spyce에서 Cheetah 템플릿을 사용하려면 다음과 같은 문법을 사용하면 된다.
문법 : te,plate.cheetah( file, [lookup] )
여기에서 lookup은 선택적 인자인데, 사전형 데이터를 인자로 받는다. 이 인자를 적지 않으면 스크립트 내에 있는 모든 인자의 값이 템플릿으로 전달된다. 이 방법으로 구현된 예제는 지금까지 알게 모르게 모든 예제가 그러했으니 지금 볼 예제는 템플릿으로 넣을 인자만 사전에 넣은 후 그 사전을 템플릿으로 전달해 보는 방법의 예제4를 살펴보고 그림 5의 실행 결과를 보자.
참고박스 -- 키워드 인자
예제4에는 키워드 인자의 사용을 볼 수 있는데, 필자가 이제까지 써놓은 문법들에는 모두 키워드 인자를 바로 사용할 수 있도록 되어 있다. 이때 키워드 인자는 튜플형 인자와 사전형 인자를 받을 수 있는데 메소드나 함수 정의시에 사용된 원형 이름으로 값을 넘길 수 있다. 물론 메소드나 함수에 따라 다르게 선언되어 있으므로 사용시 매뉴얼이나 소스코드를 충분히 살펴보아야 할 것이다. cheetah 함수를 예로 든다면 다음과 같이 키워드 인자를 넘길 수 있다.
예) template.cheetah(file="soeunlee.tmpl", lookup=[templateOutValue])
키워드 인자에 대해서는 파이썬 입문서에 보면 자세히 잘 나와 있으니 참조해보길 바란다.
--- (choiceargs.spy) ---
[[.import name=template]]
[[\
lookvalue = {'lookvalue':"123"}
]]
[[=template.cheetah('choiceargs.tmpl', lookup=[lookvalue])]]
--- (choiceargs.tmpl) ---
${lookvalue}
#try
${lookvalue2}
#except
#pass
#end try
<예제4> 선택적 인자만 템플릿에 전달하기
(choiceargs.png)
<그림5> (예제4)의 실행 결과
예제4를 유심히 보면 lookvalue 라는 변수에 사전형 데이터를 넣는데 이 사전형 데이터에 템플릿에 출력할 데이터를 모두 넣고 template를 출력할 때 lookup 키워드 인자에 넣어주면 템플릿엔 사전에 포함된 데이터만 출력되게 된다.
그리고 예제4의 choiceargs.tmpl에는 키워드 인자 전달과 상관없이 $lookvalue 만 적었는데도 불구하고 값이 출력되어져 있다. 그렇다면 전달될 때 사전 이름은 적지 않아도 되는 걸까? 답은 적지 않아도 된다이다. 템플릿으로 전달한 사전형 값은 이름, 값만을 템플릿에 전달하기 때문이다.
여기서 잠깐 --
Spyce와 함께하는 파이썬 웹 프로그래밍 2편에서 데이터베이스에서 반환되는 자료형은 사전형 데이터라는 것을 기억했다면 템플릿 인자로 한 번에 하나의 사전 인자만 전달할 수 없지 않나?라는 의문을 가질지 모르겠다. 그러나 이런 의문을 가진 독자가 있다면 무척 눈치가 빠르다고밖에 할 수 없을 것 같다. 이 연재에서는 파이썬 자료형에 모두 다루지 않았으나 파이썬 자료형은 List, Tuple, Dictionary 의 값에는 중첩된 자료형으로 만들 수 있다. 다시 말해 Dictionary는 자료들의 컨테이너 일뿐이고 이 안에 다른 사전형 데이터를 넣을 수 있다. 다음의 예제를 보면 쉽게 이해가 될 것이다.
myDictionary = {'name':'So Eun Lee'} // 일반적인 문자열 값
myDictionary['profile'] = rsProfile // rsProfile 은 사전형으로 이루어진 데이터베이스 반환값
위와 같이 스크립트에서 정의되고 myDictionary가 템플릿에 사전 인자로 전달되면 템플릿에선 다음과 같은 방법으로 사용이 가능하다.
// 템플릿 파일 내용
${name}
필드명 | 필드값
#for $key, $value in ${profile}
$key | $value
#end for
위와 같이 템플릿으로 사전형 데이터를 전달하는 것은 파이썬 데이터 타입인 사전형의 특성으로 인해 어렵지 않게 여러개의 사전형 데이터를 전달할 수 있게 된다.
---
지금까지 Spyce에서 파이썬 기반의 Cheetah 템플릿에 대해 알아보고 사용하는 것까지 마쳤다. 3회 동안 연재하면서 실질적인 예제보다 어떻게 하면 된다 라는 가이드만 독자들에게 제시해 준 것 같아 미련이 남는다. 지면이 조금 더 할애되었더라면 파이썬에서 직접 Cheetah 템플릿을 사용하는 것까지 하고 싶었는데 조금씩 편집 당하는 기쁨(??) 때문에 그러하지 못해 아쉽긴 하지만 여기까지 한 것만 해도 혼자서 장하다고 기뻐하고 있다. 원고해산의 기쁨은 곧 독자들에겐 멀고도 긴 웹 프로그래밍의 시간대로 나아가는 지평선이 아닐까 혼자서 중얼거리고 있다. “휴우 손이 다 떨린다~”
댓글 없음:
댓글 쓰기