Spyce를 이용한 PSP 프로그래밍
이번 호에서는 사용자와 대화하는 웹 사이트를 만들기 위해 많은 웹 개발자들이 사용하는 일반적인 언어가 아닌 파이썬의 특별한 웹 개발 도구인 Spyce를 사용해 웹 프로그래밍을 하는 방법에 대해 소개하고자 한다.
이상호 search5@gmail.com
현재 리눅스 엔지니어로 일하고 있으며, 웹과 그 기반 기술들에 대해 관심이 많다. 파이썬과 PostgreSQL에도 관심이 많아 항상 이 둘을 어떻게 하면 잘 사용할까 생각한다. 요즘은 동갑내기 여자 가수인 이소은을 쫓아다니며 어떻게 하면 고백할 수 있을까 고민 중이다.
연재순서
1회 2005.10 Spyce를 통한 PSP 프로그래밍
2회 Spyce와 데이터베이스 연동
3회 Spyce와 Cheetah를 이용한 템플릿 사용
웹 프로그램은 C, C++와 같이 컴파일된 언어로 구성하는 방법도 있고 PHP, Perl, VBScript 등 스크립트 언어로 구성할 수도 있다. 물론 이번 연재에서 살펴보고자 하는 파이썬도 웹 프로그래밍을 할 수 있는 언어이다. 그렇다면 파이썬으로 하는 웹 프로그래밍에는 어떤 장점이 있을까? 앞으로 연재를 통해 지속적으로 살펴보겠지만 파이썬은 배우기 쉽고 강력하다. 그리고 다양한 표준 인터페이스와 스크립트 언어로 동작하기 때문에 다른 스크립트들과 동일하게 에러 처리를 빠르게 할 수 있다(다른 스크립트 언어도 에러 처리가 있지만 파이썬과 같이 에러 처리를 빠르게 할 수 있는 것은 없다고 개인적으로 생각한다).
파이썬으로 웹 프로그래밍을 할 수 있는 도구는 비교적 다양한 편이다. Spyce는 PSP(Python Server Page) 프로그래밍을 위한 대표적인 도구이다. 물론 PSP를 위한 도구에는 webware(webware.sourceforge.net)도 있지만 구분자 문법은 비슷해도 전반적으로 Spyce에서 만드는 PSP가 성능과 제작 측면에 있어 앞선다. 이번 연재에서는 Spyce(spyce.sourceforge.net)를 이용해 PSP를 만드는 방법을 살펴볼 것이다. 물론 독자가 파이썬을 알고 있다는 것을 기준으로 하니 파이썬을 모른다면 파이썬 사용자 모임과 파이썬 튜토리얼을 보시길 권고한다.
<화면 1> Spyce 홈페이지 [picture-1.jpg]
간편하고 쉬운 Spyce
Spyce 외에도 사용하는 도구는 Zope, Mod_Python 등이 있다. Spyce는 현존하는 파이썬 웹 도구 중에는 설치가 간편하고 사용하기 쉬워 많은 곳에서 사용되고 있다. 하지만 기본적으로 단순하기 때문에 PHP나 Mod_python 같이 독립적이 아닌 웹 서버 또는 다른 파이썬 도구와 같이 동작하게 된다. Spyce를 이용해 본격적으로 프로그래밍을 즐기기 이전에 Spyce 환경을 어떻게 구성할지 살펴보자. Spyce 환경은 크게 다음과 같이 세 가지로 나눠서 설치를 진행할 수 있다.
◆ 웹 서버가 사용하지 않는 포트를 사용하는 방법 : 아파치 자카르타의 JSP 컨테이너인 톰캣 컨테이너에는 JSP 페이지 개발과 테스트를 위한 웹 서버 구현 기능이 있다. spyce에도 이러한 웹 서버 구현 기능이 존재하는데 이 방법을 이용하면 아파치와 같은 웹 서버를 구동하지 않아도 spyce를 테스트 할 수 있는 환경을 쉽게 갖출 수 있다.
◆ FastCGI를 사용한 방법 : FastCGI는 웹 서버의 메모리에서 동작하며 사용자의 응답에 대해 별도의 프로세스를 생성하지 않고 빠르게 응답한다. Spyce에서는 운영체제가 리눅스와 윈도우일 때 설정이 다소 다르므로 주의해서 설치해야 한다.
◆ Mod_Python를 사용한 방법 : Mod_Python 모듈을 사용함으로써 웹 서버의 안정적인 응답과 웹 서버의 보안성을 높일 수 있다. 아직 윈도우 환경에서는 문제가 있어 이 부분은 spyce 문서를 참조하길 바란다.
여기서는 Spyce를 이용해 프로그래밍하기 전에 테스트 웹 서버를 구동하고 이를 이용해 Spyce를 테스트해 볼 것이다.
Spyce 설치와 구동
Spyce는 현재 SVN을 이용해 다운받을 수 있다. 소스포지(www.sourceforge.net)에서 가장 최근 버전인 spyce-2.0.3-1.zip을 다운받고 Spyce를 설치할 적당한 디렉토리에 압축을 푼다. 압축이 풀린 디렉토리에는 contrib, misc, modules, tags, www 디렉토리가 포함되어 있어야 한다.
필자는 D:\htdocs 안에 압축을 풀고 압축이 풀린 디렉토리를 Spyce로 변경해두었다. 완성된 경로는 D:\htdocs\Spyce가 된다. 설치가 완료됐다면 Spyce를 구동한다. 자신의 Spyce가 설치된 디렉토리로 이동해서 다음과 같은 명령을 내린다.
D:\htdocs\Spyce>Spyce -l -p 8000
Spyce 2.0.3 starting
# Spawning another server (for check_modules_and_restart option)
Spyce 2.0.3 starting
# Running reloading file monitor (for check_modules_and_restart option)
# Starting web server with configuration specified by D:\htdocs\Spyce\Spyceconf.
py
cache miss for ('D:\\htdocs\\Spyce\\modules\\error.py', 'defaultErrorTemplate')
cache miss for ('D:\\htdocs\\Spyce\\tags\\core.py', 'core')
cache miss for ('D:\\htdocs\\Spyce\\tags\\form.py', 'form')
# Server IP:Port: :8000
# Server Root: D:\htdocs\Spyce\www
# (server root is set by the "root = " line in your configuration file)
# MIME file: D:\htdocs\Spyce\Spyce.mime
handlers are {None: <unbound method myHTTPhandler.handler_dump>, 'spy': <unbound
method myHTTPhandler.handler_Spyce>}
# Ready.
명령과 실행 결과에서 눈여겨봐야 할 부분은 다음과 같다.
◆ -l : Spyce에게 listen 모드로 동작을 지시한다.
◆ -p : Spyce에게 listen 모드로 몇번 포트 감시를 지시한다. 이 명령에선 8000포트를 주시하라고 명령한다.
출력 결과에선 다음과 같은 부분을 눈여겨봐야 한다.
# Server Root: D:\htdocs\Spyce\www
# (server root is set by the "root = " line in your configuration file)
우선 Server Root라고 출력된 부분은 앞으로 Spyce 서버에 접속했을 때의 문서 루트를 의미한다. 그 다음 줄의 결과를 보자. 이 부분의 수정은 Spyce 실행 당시 수정하는 것이 아니라 Spyce 디렉토리의 spyceconf.py 파일에 있는 “root = ” 라인을 수정해야 한다고 나와 있다. 이렇게 해서 Spyce 구동이 완료됐다면 이제 Spyce의 간단한 예제를 살펴보자.
Hello World! 예제
거의 모든 프로그래밍 언어와 도구들의 예제와 마찬가지로 Spyce도 비슷한 출발을 해보자.
[hello.spy]
<html>
<head><title>Hello Spyce</title></head>
<body>
Hello [[print 'world!']]
</body>
</html>
출력 결과는 <화면 2>와 같다.
<화면 2> hello.spy 실행 화면 [picture-2.jpg]
이제 hello.spy를 분석해보자. 4번째 줄의 다음 구문이 Spyce 구문이다.
Hello [[print 'world!']]
Spyce는 [[와 ]]로 둘러싸여 파일을 실행하며 그 안에 파이썬 구문이 들어간다. 파일 이름을 잘 살펴보면 뭔가 특이한 구석을 발견할 수 있다. PHP나 ASP 등은 확장자가 HTML이나 HTM일 경우만 html 구문을 해석하고, 본래 언어가 가지고 있는 부분을 해석하게 되는데 Spyce의 경우는 확장자가 spy임에도 불구하고 HTML에 Spyce 구문을 집어넣는다는 것을 알 수 있다.
Spyce의 또 다른 구분자 문법
그런데 Spyce 구문은 [[와 ]] 외에는 쓸 수 없을까? 천만의 말씀이다. ASP/JSP 구분자를 따서 다음과 같이 작성할 수도 있다.
[hello-asp.spy]
<html><body>
Hello <%print 'world!'%>
</body></html>
결과는 hello.spy와 동일한 것을 볼 수 있는데 ASP와 JSP 구분자를 따르는 방법을 조금 더 살펴보자.
<%-- Spyce comment --%>
<%@ Spyce directive %>
<% Python statement(s) %>
<%\ Python chunk %>
<%! Python class chunk %>
<%= Python expression %>
<%spy [parameters] : Spyce lambda code %>
구분자는 %와 %로 시작되고 끝난다. 대부분은 %로 시작되고 기술하고자 하는 부분에 따라 --, @, \, !, =, spy로 나눌 수 있다. 여기서 유일하게 주석의 경우에만 끝날 때 % 앞에 --가 따라붙는다(자세한 것은 Spyce 문서 참조).
◆ <%-- --%> : Spyce 주석을 의미하며 실제 웹 서버에 의해 처리된 내용에는 보이지 않는다.
◆ <%@ %> : Spyce의 지시자를 넣는다. 주로 Spyce로 프로그래밍 하기 전에 사용하는 것들 import, compact 등의 지시자가 포함된다.
◆ <% %> : 파이썬의 일반적인 구문. print, for문 등이 포함된다.
◆ <%\ %> : 파이썬 함수를 넣는다.
◆ <%! %> : 파이썬 클래스를 정의한다.
◆ <%= %> : 파이썬 표현식을 기술한다.
◆ <%spy [parameter] : Spyce lambda code %> : 파이썬 람다 식을 정의하며 C의 define과 비슷한 역할을 수행한다.
REQUEST와 RESPONSE 객체 살펴보기
사용자의 요청을 받아들이고 다시 요청을 하는 것은 어려운 것일까? PHP를 예로 든다면 $_REQUEST, $_POST, $_GET 등으로 구분해서 사용자의 데이터를 받아들이게 된다. Spyce에서는 request라는 객체가 있고 이 안에 여러 메쏘드가 있어 실제 데이터는 이 메쏘드로 처리할 수 있다.
REQUEST 객체
사용자의 데이터를 처리하는 객체이다. 대표적인 메쏘드로 다음과 같은 것이 있다.
◆ method : 사용자로부터 요청된 메쏘드 타입을 반환한다. GET, POST, HEAD 등이 있다.
◆ get : 사용자로부터 전송된 get 데이터를 반환한다. 형식은 다음과 같다.
get( [name], [default], [ignoreCase] )
아무런 인자 없이 실행할 경우 사전 형태로 모든 get 데이터를 반환하며 사전의 값은 list로 반환한다. get 메쏘드로 name을 호출했을 경우 데이터가 없다면 default를 호출한다. 여기서 name은 대소문자를 구별하므로 대소문자 구별을 할 경우 ignoreCase=1 인자를 호출한다. 기본적으로 name은 소문자를 기본으로 한다. name을 줘서 호출하면 값은 list 형태를 반환한다.
◆ get1 : get 메쏘드와 하는 일이 같다. get과 다른 점은 사전의 데이터 값이 list 형태가 아닌 문자열 형태를 반환한다는 것이다. name을 줘서 호출하면 값은 문자열 형태를 반환한다.
◆ post : post 메쏘드의 데이터를 반환한다. 형식은 다음과 같다.
post( [name], [default], [ignoreCase] )
아무런 인자 없이 실행할 경우 사전 형태로 모든 post 데이터를 반환하며 사전의 값은 list로 반환한다. post 메쏘드로 name을 호출했을 경우 데이터가 없다면 default를 호출하며 여기서 name은 대소문자를 구별하므로 대소문자 구별을 할 경우 ignoreCase=1 인자를 호출한다. 기본적으로 name은 소문자를 기본으로 한다. name을 주어 호출하면 값은 list 형태를 반환한다.
◆ post1 : post 메쏘드와 동일한 역할을 수행하지만 값은 list 형태가 아닌 문자열 형태를 반환한다는 것이 다르다. name을 줘서 호출하면 값은 문자열 형태를 반환한다.
이번부터 소개하는 메쏘드는 특징은 조금 다르다.
◆ getpost : 앞에서 소개한 get, post, get1, post1과 동일한 인자와 형식을 갖지만 이 메쏘드는 get 메쏘드의 데이터를 먼저 검색하고 post 메쏘드의 데이터를 검색한다는 것이 다르다. 형식은 다음과 같다.
getpost( [name], [default], [ignoreCase] )
메쏘드 이름에서 알 수 있듯이 이 메쏘드는 get 메쏘드에 요청한 name이 있을 경우 get 메쏘드의 name을 먼저 반환하고 post 메쏘드는 검색하지 않는다. 아무런 인자 없이 실행하면 모든 get과 post 메쏘드 모두를 반환한다. 반환 값은 사전 형태로 값을 반환하며, 사전의 값은 list 형태로 반환한다. 기본적으로 대소문자를 구별한다. name을 줘서 호출하면 값은 list 형태를 반환한다.
◆ getpost1 : getpost 메쏘드와 동일한 역할을 수행한다. getpost 메쏘드와 다른 점은 값을 list가 아닌 문자열 형태로 반환한다는 점이다. name을 줘서 호출하면 값은 문자열 형태를 반환한다.
◆ postget : getpost와 정반대의 검색 순서를 가지는 메쏘드이다. post 메쏘드의 데이터를 먼저 검색하며 이후 get 메쏘드의 데이터를 반환한다. 형식은 다음과 같다.
postget( [name], [default], [ignoreCase] )
◆ postget1 : postget 메쏘드와 기능상 동일한 역할을 수행하지만 postget과 다른 점은 값의 형태가 문자열 형태를 반환한다는 점이다.
◆ env : CGI 환경 변수를 반환한다. 형식은 다음과 같다.
env( [name], [default] )
일례로 사용자의 브라우저를 출력하는 것은 다음과 같이 호출한다.
env('HTTP_USER_AGENT')
더 자세한 변수는 뒤에서 언급할 스크립트를 이용해 볼 수 있다.
◆ default : 디폴트 값을 반환하며 요청한 value가 없을 경우 value2가 반환된다. 형식은 다음과 같다.
default( value, value2 )
지금까지 설명한 여러 메쏘드를 사용하지 않고 html의 form 데이터를 가져올 수 있는 방법은 없을까? 다음과 같은 방법이 있다.
print request['Name']
메쏘드를 사용하지 않고 HTML의 값을 반환하는 것은 request 객체를 직접 사용하면 내부적으로 __getitem__(key)를 사용해 값을 반환하게 된다. 자세한 것은 ‘이달의 디스켓’의 getpost.spy 파일을 실행해 보기 바란다.
앞서 ASP/JSP 구분자 문법을 따르는 곳에서 주석과 데이터를 기록하는 구분자에 대해 잠시 살펴보았다. [[, ]]를 구분자로 하는 spy 파일에도 주석은 [[--, --]]로 구성되며 print 또는 reponse.write 메쏘드를 사용하지 않고도 [[=, ]]를 사용해 데이터를 출력할 수 있다. ‘이달의 디스켓’에 포함된 스크립트는 Spyce의 example 리스트에서도 볼 수 있다.
<화면 3> getpost.spy 실행 화면 [picture-3.jpg]
RESPONSE 객체
브라우저에 명령을 내리는 객체이다. 이 객체에 포함되어 있는 일부 메쏘드는 파이썬이 사용한 일부 파이썬 구문과 겹칠 수 있기 때문에 한 가지 방식만을 사용해 통일하는 것을 권장한다. 대표적인 메쏘드는 다음과 같다.
◆ write(string) : 파이썬의 print와 같으며 string을 화면에 출력한다.
◆ writeln(string) : 하는 일은 write와 같지만 string을 출력하고 새 줄을 하나 더 출력한다.
◆ clear() : 버퍼를 지우는 역할을 수행한다.
◆ flush() : clear와 하는 일은 같지만 먼저 버퍼를 출력한다.
◆ setContentType(contentType) : 출력하는 데이터의 컨텐츠 타입을 결정한다. MIME 형식을 따른다.
◆ setReturnCode(code) : HTTP 리턴코드를 반환한다. 예) 404, 403, 500 에러
◆ AllHeader(type, data, [replaced]) : HTTP 헤더를 설정한다. type은 헤더 이름, data는 헤더 데이터이다. replaced를 기재하면 데이터는 추가되는 것이 아닌 교체된다.
◆ expires([thetime]) : 문서의 유효기간을 설정한다. thetime은 생략될 수 있는 값이다.
◆ lastModified([thetime]) : 문서가 언제 마지막으로 수정되었는지 설정할 수 있는 메쏘드이다. thetime은 생략될 수 있다.
◆ uncacheable() : 문서의 캐시를 해지한다. 아무런 인자 없이 실행한다.
브라우저의 요청 가로채기
지금까지의 방법은 브라우저가 데이터를 넘겨주면 그걸 스크립트 상에서 사용자에게 출력하는 기능을 수행했다. 하지만 Spyce는 도중에 이걸 넘겨받아 처리할 수 있다. 이러한 역할을 수행하는 함수는 다음과 같은 두 가지가 있다.
◆ SpyceFileHandler(request, response, filename, [sig], [args], [kwargs], [config_file])
◆ SpyceStringHandler(request, response, code, [sig], [args], [kwargs], [config_file])
요청을 가로챘다면 이것으로 할 수 있는 일은 어떤 것들이 있을까? 데이터를 이메일로 보내거나 이것을 데이터베이스에 삽입할 수 있다. SpyceStringHandler 함수는 code라는 인자를 받음으로서 코드에 해당되는 데이터만 처리하게도 할 수 있다. 자세한 것은 직접해보자.
에러 처리
프로그램을 만들다보면 의외로 문제가 많이 일어난다는 것을 알 수 있다. 초보 프로그래머든 숙련된 프로그래머든 에러는 피해갈 수 없는 문제이다. Spyce에서는 error 객체를 제공함으로써 에러를 빨리 처리할 수 있게 도와준다. error 객체에는 다음과 같은 메쏘드들이 존재한다.
◆ getMessage() : 파이썬이 반환하는 에러 메시지이다.
◆ getFile() : 에러가 나타난 파일 이름을 반환한다.
◆ getTraceback() : 에러를 추적할 수 있게 추적 결과를 반환한다.
실제 에러 처리를 살펴보자.
[error.spy]
[[.module name=transform]] // transform 모듈을 불러들인다. Spyce 디렉티브 부분이다.
[[transform.expr('html_encode')]] // 출력되는 데이터는 html로 엔코딩하도록 설정한다.
<html>
<title>Spyce exception: [[=error.getMessage()]]</title> // 브라우저의 타이틀을 에러 메시지로 설정한다.
<body>
<table cellspacing=10 border=0>
<tr><td colspan=2><h1>Spyce exception</h1></td></tr>
<tr><td valign=top align=right><b>File:</b></td><td>[[=error.getFile()]]</tr>
// 에러가 나타난 파일 위치와 이름을 반환한다.
<tr><td valign=top align=right><b>Message:</b></td>
<td><pre>[[=error.getMessage()]]</pre></tr> // 에러 메시지를 반환한다.
<tr><td valign=top align=right><b>Stack:</b></td><td>
[[
L = list(1,2)
L.reverse()
]]
[[ for frame in error.getTraceback(): { ]]
[[=frame[0] ]]:[[=frame[1] ]], in [[=frame[2] ]]:<br>
<table border=0><tr><td width=10></td><td>
<pre>[[=frame[3] ]]</pre>
</td></tr></table>
[[ } ]] // 추적 메시지로부터 for를 돌면서 데이터를 반환한다. frame 0부터 3까지 데이터를 살펴보자. getTraceback의 0번째 원소는 파일 이름을 반환하며 첫 번째 원소는 에러가 나타난 라인번호, 두 번째 원소는 파일의 어떤 부분인지 출력한다. 마지막 세 번째 원소가 에러가 나타난 라인의 내용을 나타낸다.
</td></tr>
</table>
</body></html>
<화면 4> error.spy 실행 화면 [picture-4.jpg]
파일에 포함
웹 사이트의 경우 페이지의 일부는 항상 유지되고 변경되지 않는 부분이 있다. 가장 큰 예로 메뉴바가 그러한 종류의 일부이다. 그렇다고 해서 이것들이 아예 변경되는 것은 아니다. 아주 소폭 변경되는 경우도 자주 있을 수 있다. Spyce에서는 이러한 것을 내부적으로 include 모듈을 불러들여 쉽게 처리할 수 있다.
[include.spy]
[[.import name=include]]
<html><body>
main file<br>
<hr>
[[
context = {'foo': 'old value'}
result=include.Spyce('include.spi', context)
]]
<hr>
main file again<br>
context: [[=context]]<br>
return value: [[=result]]<br>
</body></html>
[include.spi]
begin include<br>
context: [[=include.context ]]<br>
from: [[=request.stack()[-2] ]]<br>
foo was [[=include.vars.foo]]<br>
setting foo to 'new value' [[include.vars.foo = 'new value']]<br>
returing 'retval'<br>
end include<br>
[[ return 'retval' ]]
이 파일에는 파일을 포함하는 것에 대한 실마리가 담겨 있다. 처음 1라인을 살펴보자.
[[.import name=include]]
이 부분이 include 모듈을 임포트한다는 의미이다. 그리고 실제 임포트를 수행하는 부분은 5~8 라인까지이다.
[[
context = {'foo': 'old value'}
result=include.Spyce('include.spi', context)
]]
include 모듈에는 몇 개의 메쏘드가 있는데 Spyce라는 메쏘드는 다이내믹한 파일을 포함시키는데 사용한다. 형식은 다음과 같다.
Spyce(file, [context]) : file에는 실제 포함할 파일을 명시하며 context에는 포함되는 파일에 변수를 전달한다.
그리고 spi 파일의 내용을 살펴보자.
라인 2 : context: [[=include.context ]]<br>
라인 3 : from: [[=request.stack()[-2] ]]<br>
라인 4 : foo was [[=include.vars.foo]]<br>
라인 5 : setting foo to 'new value' [[include.vars.foo = 'new value']]<br>
라인 2는 상위 파일의 context 변수 내용을 출력한다. 라인 3에서는 request 객체의 stack 메쏘드를 사용하는데 stack 메쏘드는 지나온 파일들의 파일경로와 이름을 담고 있다. 자료구조인 stack처럼 맨 끝에 들어온 게 맨 끝에 먼저 나가게 되므로 맨 마지막 이름이 현재 파일 이름이다. 라인 4는 자신을 불러들인 파일. include.spy의 foo 변수 내용을 출력한다. 라인 5는 include.spy 파일의 foo 변수를 새로운 값으로 설정한다. 이 때 ‘설정된 값이 정말 바뀔까?’라는 생각은 일찌감치 포기하는 것이 좋은데 파이썬에서는 값을 복사하는 게 아니라 값의 위치를 전달한다.
<화면 5> 인클루드 예제 [picture-5.jpg]
동적 파일 인클루드에서 포함되는 파일이 변수를 참조할 수 있지만, 이 변수의 참조는 다음과 같은 방법으로도 참조가 가능하다.
head.spy의 내용
[[include.spyce('lib/head.spi',
{'pagename': 'Documentation',
'page': 'manual.html'}) ]]
lib/head.spi 파일의 내용
[[=include.context['pagename'] ]]
지금까지는 동적인 include를 살펴봤다면 다음으로 정적인 예제를 보자.
[inclusestatic.spy]
<html><body>
[[x=1]]
main file<br>
x=[[=x]]<br>
<hr>
[[.include file="includestatic.spi"]]
<hr>
main file again<br>
x=[[=x]]
</body></html>
[includestatic.spi]
begin included file<br>
changing value of x<br>
[[x=2]]
end included file<br>
여기서도 불러들인 파일의 변수를 수정할 수 있음을 주의해서 보자. 단 변수 전달은 허용되지 않는다.
<화면 6> includestatic.spy 실행 화면 [picture-6.jpg]
spyce 람다(Lambdas)
파이썬에는 람다라는 c에 있는 define이 또 다른 일과 비슷한 일을 간이 함수식이 있다. c에서 define이 하는 일은 매크로 작업이지만, 파이썬에서 람다는 함수가 필요하지만 함수를 집어넣지 못할 경우 쓰는 표현식이다. 사실 어떻게 보면 define이 하는 매크로 작업 같기도 하지만 말이다. 부르는 사람에 따라 람다라는 이름은 조금씩 다르게 불려지고 있긴 하지만 통상적으로 람다라고 부른다.
spyce에서 람다는 다음과 같은 형식을 띄고 있다.
[[spy [params] : spyce lambda code ]] 또는
[[spy! [params] : spyce lambda code ]]
조금더 빠른 이해를 돕기 위해 다음의 예제를 보자.
[lambdas.spy]
[[
# table template
table = [[spy! title, data:
<table>
<tr>
[[for cell in title: {]]
<td><b>[[=cell]]</b></td>
[[}]]
</tr>
[[for row in data: {]]
<tr>
[[for cell in row: {]]
<td>[[=cell]]</td>
[[}]]
</tr>
[[}]]
</table>
]]
# table information
title = ['Country', 'Size', 'Population', 'GDP per capita']
data = [
[ 'USA', '9,158,960', '280,562,489', '$36,300' ],
[ 'Canada', '9,220,970', '31,902,268', '$27,700' ],
[ 'Mexico', '1,923,040', '103,400,165', '$9,000' ],
]
]]
<html><body>
[[ table(title, data) ]]
</body></html>
앞의 예제에서 람다식을 정의한 부분을 살펴보자. 람다식을 실행할 변수는 table이라는 이름에 다음과 같이 선언된 것을 볼 수 있다.
[[spy! title,data: 중략 ]]
위 줄에서 title,data는 람다식에서 사용할 파라메터이고 파라메터 다음에는 : 나오고 이후 실제 람다식이 수행할 내용이 들어가게 된다. 실제 수행 부분을 보면 html이 람다식 table에 데이터를 넘겨주게 된다. 이후 람다식 table이 파라메터에 전달된 변수를 받아 람다식을 수행하게 되는데, 람다식에서 볼 수 있는 한가지 특이한 건 spyce 내에서 파이썬 구문을 기술하는 구분자인 [[, ]]를 쓸 수 있다는 것이다. 그럼 이게 실제 실행에서 영향를 줄까? 라는 의문에는 영향을 주지 않는다라고 말할 수 있다. 위의 예제에서는 데이터를 리스트 데이터로 만들어서 table 람다식에 넘긴 이후 table 람다식이 다시 각 row별과 column별로 람다식을 수행하게 된다.
다만 람다식 내에서도 구분자인 [[, ]]를 사용하고 닫거나 열지 않고 닫아버린다면 문제가 발생할 수 있으므로 이 부분에 대해선 프로그래머의 주의가 필요하다.
쿠키와 세션
쿠키와 세션은 사용자의 정보를 서버가 가지고 사용자의 취향에 맞는 정보를 push 하거나 내부적으로 사용하기 위해 쓰는 방법이다.
쿠키
- 사용자의 컴퓨터에 데이터가 저장된다. 누구나 열어볼 수 있으며 자칫잘못할 경우 사용자의 정보를 그대로 방출하게 될수도 있다. 특별한 일이 없는 경우 쿠키는 항상 사용자의 컴퓨터에 기간에 상관없이 남아 있을 수 있다.
세션
- 서버에 사용자의 데이터가 저장된다. 세션의 정의는 두 개의 호스트간 연결을 위한 논리적 연결 이다. 세션의 데이터는 일반적으로 사용자의 개인정보나 아이디/비밀번호 등을 보관한다. 세션은 브라우저와 서버간 맺은 논리 연결이 종료될 경우 데이터가 사라지게 된다.
쿠키 사용
spyce에서 쿠키는 다음 3가지의 메쏘드를 제공한다.
get( [key] )
- key를 주어 쿠키값을 얻어온다. 이때의 key는 식별자. identifier 이다.
set( key, value, [expire], [domain], [path], [secure] )
- 쿠키값을 설정하며 기본적으로 키와 값을 인자로 요구한다. expire는 유닉스 타임을 입력한다. 별도 입력하지 않을 경우 브라우저가 종료될때 쿠키도 종료하게 된다. domain은 쿠키가 동작할 도메인, path는 쿠키가 도메인 내의 어떤 path에서만 유효할 것인가를 지정한다. secure는 보안 연결일 경우만 1로 설정한다.
delete( key )
- 쿠키를 삭제한다. get과 동일하게 key 값을 인자로 받으며 해당 쿠키는 삭제되게 된다.
세션 사용
세션은 몇가지의 메쏘드가 더 존재하지만 크게 쓰이는 것은 아래 3가지의 메쏘드이다.
get( id )
- 세션을 얻어온다. 세션 id를 인자로 준다. 세션 ID를 인자로 주면 세션값을 인자로 받아오게 된다.
set( data, expire, [id] )
- 세션을 설정한다. 첫 번째 data는 세션에 저장할 값이며 세션에 저장되는 값은 객체로도 저장이 가능하다. expire는 세션이 유효할 기간을 설정한다. id는 생략이 가능하지만 가급적 넣어주는 것을 권장한다.
delete( id )
- 인자로 주어진 id를 가진 세션을 삭제한다.
다음 호엔 DB 연동을
지금까지 파이썬 웹 프로그래밍 도구인 Spyce에 대해 간단한 예제를 통해 알아보았다. 다음 호에서는 Spyce의 pool에 대해 알아보고, 파이썬 DB-API를 함께 사용해 웹 프로그램에서 빠뜨려 놓을 수 없는 DB를 사용한 간단한 애플리케이션과 사용 방법을 배워볼 것이다. 마지막으로 궁금한 사항은 필자에게 언제든지 메일을 보내주면 친절하게 답변할 것을 약속한다.
정리 강경수 elegy@imaso.co.kr
이달의 디스켓 spyce01.zip www.imaso.co.kr