Tag Archives: php

요쯤 개발한 CMS

기반은 PEAR 템플릿 엔진은 Smarty

1월달 기획부터 3월달 개발해서 오늘 드디어 本番リリース를 하네요…

preview

모두 잘되여야 하는데….

ps. 구글 Adsense 수익도 살짝 공개합니다.

일본엔 환율이 높은 관계로 9천7백엔 되네요…

계좌를 조회해보니 4월30일 입금 되여 있네요…

adsense

Flex와 PHP를 이용한 MyTube 구현(2)

Flex와 PHP를 이용한 MyTube 구현(2)

제공 : 한빛 네트워크
저자 : Jack Herrington
역자 : 노재현
원문 : Creating MyTube with Flex and PHP

[이전 기사 보기] Flex와 PHP를 이용한 MyTube 구현(1)

Flex를 이용한 인터페이스 구성 파트 1

Flex
를 이용해서 원하는 비디오를 재생시키기 위해서는 Flex에게 재생시킬 수 있는 비디오의 리스트를 알려줘야만 합니다. 어떻게
해야하냐면 XML파일을 이용해서 Flex에게 비디오 리스트 정보를 넘겨줄 수가 있는데요, 여기서는 PHP로 다시 돌아가서
데이터베이스에서 비디오 리스트를 읽어들인 후에 XML로 출력하는 스크립트를 만들어 보도록 하겠습니다. 다음 [리스트 6]의
movies.php 파일을 보도록 하죠.

[리스트 6] movies.php

<?php
require "DB.php";

$moviebase = 'http://localhost:8080/movies/';

header( 'content-type: text/xml' );

$dsn = 'mysql://[email protected]/movies';
$db =& DB::connect( $dsn );
if ( PEAR::isError( $db ) ) { die($db->getMessage()); }
?>
<movies>
<?php
$res = $db->query( 'SELECT title, source, thumb, width, height FROM movies' );
while( $row = $res->fetchrow( ) ) {
?>
<movie title="<?php echo( $row[0] ) ?>" source="<?php echo( $moviebase.$row[1] ) ?>"
thumb="<?php echo( $moviebase.$row[2] ) ?>" width="<?php echo( $row[3] ) ?>"
height="<?php echo( $row[4] ) ?>" />
<?php
}
?>
</movies>

위 PHP 스크립트를 만든 후에 커맨드 라인에서 실행시키거나 브라우저에서 실행시키게 되면 다음 [그림 3]과 같은 XML 리스트를 볼 수가 있습니다.


[그림 3] XML로 표현된 비디오 리스트

이제 XML로 비디오 리스트 정보를 넘겨줄 수 있으니 전에 만들었던 simplemovie.mxml 파일을 좀 더 개선해 보도록 하겠습니다. 다음 [리스트 7]은 simplemovie.mxml의 업그레이드 된 버전입니다.

[리스트 7] mytube1.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" creationComplete="movieXmlData.send()">

<mx:HTTPService method="get" url="http://localhost:8080/movies.php"
id="movieXmlData" result="onGetMovies( event )" />

<mx:Script>
import mx.rpc.events.ResultEvent;
import mx.controls.VideoDisplay;
import mx.controls.List;
import mx.rpc.http.HTTPService;
import mx.collections.ArrayCollection;

[Bindable]
private var movies : ArrayCollection = new ArrayCollection();

public function onGetMovies( event : ResultEvent ) : void
{
var firstMovie : String = event.result.movies.movie[0].source.toString();
videoPlayer.source = firstMovie;

movies = event.result.movies.movie;
movieList.selectedIndex = 0;
}

public function onPrevious() : void
{
if ( movieList.selectedIndex == 0 )
movieList.selectedIndex = movies.length - 1;
else
movieList.selectedIndex -= 1;
videoPlayer.source = this.movieList.selectedItem.source.toString();
}

public function onPlay() : void
{
videoPlayer.source = this.movieList.selectedItem.source.toString();
videoPlayer.play();
}

public function onNext() : void
{
if ( movieList.selectedIndex >= ( movies.length - 1 ) )
movieList.selectedIndex = 0;
else
movieList.selectedIndex += 1;
videoPlayer.source = this.movieList.selectedItem.source.toString();
}

public function onChange() : void
{
videoPlayer.source = this.movieList.selectedItem.source.toString();
}
</mx:Script>

<mx:HBox width="100%" paddingLeft="10" paddingTop="10" paddingRight="10">
<mx:VBox>
<mx:VideoDisplay width="400" height="300" id="videoPlayer" complete="onNext()" />
<mx:HBox width="100%" horizontalAlign="center">
<mx:Button label="<<" click="onPrevious()" />
<mx:Button label="Play" click="onPlay()" />
<mx:Button label=">>" click="onNext()" />
</mx:HBox>
</mx:VBox>
<mx:List width="100%" height="340" id="movieList"
dataProvider="{movies}"
change="onChange()"
labelField="title"></mx:List>
</mx:HBox>

</mx:Application>

전과 비교해서 크게 바뀐 부분이 있다면 파일의 상단에 있는 액션 스크립트(ActionScript)인데요, 이 코드로
전체적인 인터페이스를 관리하게 됩니다. 이 액션 스크립트가 하는 일은 먼저 onGetMovies 함수에 있는
HTTPService를 이용해서 movies.php 파일로부터 XML 정보를 읽어들이는 것입니다. HTTPService 클래스는
XML 리스트를 찾게 되면 XML 문서 객체모델(Document Object Model)로 변경하게 되고, 우린 이 문서 객체
모델을 이용해서 첫번째 비디오에 대한 정보를 얻어서 재생할 수가 있습니다. 또 onGetMovies 함수는 movies 라는
변수를 이용해서 페이지에 있는 리스트 박스에 비디오의 이름을 출력하게 됩니다. 나머지 액션 스크립트는 유저가 리스트 박스에 있는
비디오를 선택하거나 “이전”, “다음” 버튼을 선택했을 경우를 처리하기 위한 코드입니다.

위 리스트의 제일
아래를 보면 전체 유저 인터페이스를 구성하는 Flex 오브젝트를 볼 수 있습니다. 여기에 이전 비디오와 다음 비디오를 선택할 수
있는 버튼을 배치하고, 오른쪽에는 현재 비디오 리스트를 출력하는 리스트 박스가 배치되어 있습니다.

이제 Flex Builder를 이용해서 위 프로그램을 컴파일하고 실행시키게 되면 [그림 4]와 같은 화면을 볼 수 있습니다.


[그림 4] Flex를 이용해서 구성한 첫 번째 인터페이스

리스트 박스에서 비디오를 선택할 수도 있고, 이전, 다음 버튼을 이용해서 비디오를 선택할 수도 있습니다. 멋있죠? 이제 미리보기 이미지를 제공해 주면 더 멋있어질 것 같네요.

Flex를 이용한 인터페이스 구성 파트 2 – 미리보기 이미지


리보기 이미지를 비디오 리스트에 출력하려면 리스트 박스를 비디오의 제목과 미리보기 이미지를 같이 출력할 수 있도록 수정해야
합니다. 다행히도 Flex의 기능을 이용하면 아주 쉽게 수정이 가능합니다. 우선 <List> 태그에
itemRenderer를 추가하도록 하고, 다음 [리스트 8]을 보겠습니다.

[리스트 8] mytube2.mxml

...
<mx:List width="100%" height="340" id="movieList"
dataProvider="{movies}"
change="onChange()"
itemRenderer="MovieItem"></mx:List>
...

여기서 MovieItem이라는 item renderer MXML 컴포넌트를 만들었습니다. 이 컴포넌트를 만들려면
메뉴에서 “New > MXML Component”를 선택하고 [리스트 9]와 같이 컴포넌트를 코드에 넣으면 됩니다.

[리스트 9] MovieItem.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" height="80">
<mx:Image source="{data.thumb}" width="{data.width/3}"
height="{data.height/3}" rotation="5" left="10" top="0" />
<mx:Label text="{data.title}" fontWeight="bold" top="10" left="100" fontSize="18" />
</mx:Canvas>

여기서는 Canvas 라는 컨테이너를 이용했지만, 원한다면 마음에 드는 컨테이너를 선택해서 설정하셔도 괜찮습니다.
그리고 나서 미리보기 이미지 추가를 위해서 <mx:Image> 태그를 사용하고 비디오 제목을 출력하기 위해서
<mx:Label>을 이용하면 됩니다. 좀 더 재밌게 해보기 위해서 미리보기 이미지를 약간 회전시켜 봤습니다. [그림
5]를 보도록 하죠.


[그림 5] 미리보기 이미지를 추가한 리스트 박스

꽤 괜찮은 비디오 플레이어가 됐네요. 여기에 추가적으로 비디오 설명, 재생 시간, 링크, 추천 버튼과 같은 기능을 추가하면 더 좋을 것 같습니다.

저장소와 대역폭


이터베이스를 구성하고 비디오 공유 사이트 페이지를 만들어 내는것 자체는 지금까지 잘 해결했는데, 사실 이것말고 한가지 더
고려해야 할 것이 있습니다. 바로 대역폭을 고려해야 합니다. 플래시 비디오 파일 자체가 인코딩이 잘 된다고 해도 역시 비디오
파일이기 때문에 크기가 큰 편에 속하게 됩니다. 그렇기 때문에 중간에 끊김없이 비디오 재생을 얼마나 할 수 있는지 파악하는 것이
무엇보다 중요하게 됩니다.

확실한 방법중 하나는 인터넷 데이터 센타에서 서비스를 하는 것입니다. 다른 방법으로는
비디오 공유 사이트에서는 비디오 자체에 대한 데이터를 가지지 않고 링크만 저장하고 실제 비디오 데이터는 다른 곳에 저장하는
방법입니다. 아마존의 S3 서비스 같은 경우가 좋은예인데요, 저렴한 가격으로 좋은 저장소로 활용할 수가 있고, 어느정도 사이트가
커질때까지는 안정적으로 활용할 수 있습니다.

결론

플래시를 이용한 비디오의 등장과
광대역폭의 보편화로 인해서 이제 적은 예산으로 비디오 공유 사이트를 운영한다는 것이 현실로 다가왔습니다. 바라기는 이 글을
통해서 여러분이 좀 더 멋있는 비디오 공유사이트를 만들어냈으면 하는 것입니다.

Flex와 PHP를 이용한 MyTube 구현(1)

Flex와 PHP를 이용한 MyTube 구현(1)

제공 : 한빛 네트워크
저자 : Jack Herrington
역자 : 노재현
원문 : Creating MyTube with Flex and PHP


렴한 광랜의 등장과 대용량 하드디스크 가격의 하락, 그리고 Adobe 사의 플래시 플레이어(Flash Player), 플래시
비디오(Flash Video)의 등장으로 인터넷을 통한 비디오 공유가 정말 많이 보편화 되었습니다. 구글
비디오(http://video.google.com)와 YouTube(http://www.youtube.com)가 이미 이런
비디오 사업을 시작한지 오래됐지만, 여전히 공략할 수 있는 틈새 시장이 굉장히 많이 있다고 할 수 있는데, 그럼 우리도 한 번
틈새 시장을 공략해 보면 어떨까? PHP, 플래시, Adobe의 Flex를 이용해서 어떻게 하면 비디오 공유 사이트를 만들 수
있을까? 사실 알고보면 정말 쉽게 만들 수 있습니다.

여기서는 PHP를 이용해서 웹 사이트를 만드는 방법 그리고
Flex를 이용해서 Flash로 된 비디오 뷰어를 만드는 방법에 대해서 설명을 하겠습니다. 그럼 먼저 더 진행하기 전에 준비해야
하는 소프트웨어 몇 가지를 살펴보도록 하죠.

우선 서버쪽에서는 PHP와 MySQL이 필요합니다. MySQL은
비디오에 대한 정보(예를 들면, 비디오의 파일 이름, 미리보기 파일, 미리보기 파일의 너비와 높이, 제목, 그리고 기타 정보
등)를 저장하는데 사용되겠습니다. PHP는 전체적인 페이지를 구성하는데 사용되게 됩니다.

그리고
ffmpeg(http://ffmpeg.mplayerhq.hu/) 이라고 하는 유틸리티 프로그램도 필요한데요, 이 프로그램은
유저가 올리는 비디오 파일을 플래시 비디오 파일(FLV)로 변환하는 역할을 수행하게 됩니다. ffmpeg은 비디오의 변환외에도
비디오의 스냅샷을 찍어서 미리보기 파일을 만들어 낼 수도 있습니다. 이 ffmpeg을 이용하게 되면 사실상 어려운 작업을 손쉽게
처리할 수가 있어서 우리가 MyTube를 구현하는데 상당히 유용하게 활용이 됩니다.

클라이언트쪽에서는 두 가지
방법이 있는데요. 하나는 YouTube에서와 같이 HTML과 Flash를 같이 이용해서 인터페이스를 구성하는 방법이 있고, 두
번째로 플래시만으로 인터페이스를 구성하는 방법이 있습니다. 이 글에서는 Flex 프레임워크를 이용해서 비디오를 보고 등록된
비디오를 탐색하고 찾기 위해서 리스트를 생성하도록 할 예정입니다.

PHP로 서버쪽 코드 구성하기

서버쪽 코드 작성을 하기에 앞서, MySQL에 데이터 스키마를 생성해야 합니다. 우선 사용할 데이터베이스를 생성하기 위해서, 다음과 같이 mysqladmin 명령어를 사용합니다.

mysqladmin create movies 

스키마가 생성되었으면 데이터베이스를 로드합니다. 스키마 파일은 아래 [리스트 1]과 같습니다.

[리스트 1] movies.sql

DROP TABLE IF EXISTS movies; 
CREATE TABLE movies (
movieId INTEGER NOT NULL AUTO_INCREMENT,
title VARCHAR( 255 ),
source VARCHAR( 255 ),
thumb VARCHAR( 255 ),
width INTEGER,
height INTEGER,
PRIMARY KEY( movieId )
);

이제 위의 movies.sql 스키마 파일을 다음과 같은 명령어를 이용해서 데이터베이스에 테이블을 생성할 수 있습니다.

mysql movies < movies.sql 

데이터베이스에 무비 데이터를 넣기 위해서는 HTML을 이용해서 업로드 기능을 만들어야 합니다. 즉 비디오 파일을 받아서 플래시 비디오 파일로 변환하고 미리보기 파일을 만든후에 데이터베이스에 넣으면 되겠습니다.

업로드 페이지의 제작

비디오 파일을 업로드 하기 위한 HTML 파일은 다음 [리스트 2]에서 보는 것과 같이 아주 간단합니다.

[리스트 2] addmovie.html

<html>
<body>
<form enctype="multipart/form-data" method="post" action="upload.php">
<input type="hidden" name="MAX_FILE_SIZE" value="300000" />
<table>
<tr><td>Title</td><td><input type="text" name="title"></td></tr>
<tr><td>Movie</td><td><input type="file" name="movie"></td></tr>
</table>
<input type="submit" value="Upload" />
</form>
</body>
</html>

위 HTML은 입력받은 정보를 upload.php 페이지로 전송하게 되는데, 이 페이지에서 비디오를 변환하고 미리보기를 만들어 내고 데이터베이스에 저장하게 되는 것입니다. 다음의 upload.php 코드를 보도록 하겠습니다.

[리스트 3] upload.php

<html><body>
<?php
require "DB.php";

function converttoflv( $in, $out )
{
unlink( $out );
$cmd = "ffmpeg -v 0 -i $in -ar 11025 $out 2>&1";
$fh = popen( $cmd, "r" );
while( fgets( $fh ) ) { }
pclose( $fh );
}

function getthumbnail( $in, $out )
{
unlink( $out );
$cmd = "ffmpeg -i $in -pix_fmt rgb24 -vframes 1 -s 300x200 $out 2>&1";
$fh = popen( $cmd, "r" );
while( fgets( $fh ) ) { }
pclose( $fh );
}

function flv_import( $upfile, $fname, $title )
{
$fname = preg_replace( '/..*$/', '', basename( $fname ) );
$flvpath = "$fname.flv";
$thumbpath = "$fname.gif";

converttoflv( $upfile, "movies\$flvpath" );
getthumbnail( $upfile, "movies\$thumbpath" );

$dsn = 'mysql://[email protected]/movies';
$db =& DB::connect( $dsn );
if ( PEAR::isError( $db ) ) { die($db->getMessage()); }

$sth = $db->prepare( 'INSERT INTO movies VALUES ( 0, ?, ?, ?, ?, ? )' );
$db->execute( $sth, array( $title, $flvpath, $thumbpath, 300, 200 ) );
}

flv_import( $_FILES['movie']['tmp_name'], $_FILES['movie']['name'], $_POST['title'] );
?>
File sucessfully uploaded
</body></html>

위 코드에서 flv_import 함수를 중점적으로 봐야 합니다. flv_import 함수내에서 converttoflv
함수로 비디오 파일을 플래시 비디오 파일로 변경하고 있고, getthumbnail 함수로 미리보기 파일을 생성하고 있습니다.
그리고 다음으로 업로드가 완료된 무비에 대한 정보를 데이터베이스에 저장합니다. 위 리스트 3에 있는 FLV 플래시 비디오 파일과
미리보기 파일을 생성하는 함수는 ffmpeg 라는 명령어와 여러가지 명령어를 이용해서 변환을 수행하게 됩니다.

그럼 다음 [그림 1]처럼 addmovie.html 페이지를 브라우저로 한 번 보도록 하겠습니다.


[그림 1] 비디오를 업로드하는 페이지

여기서 비디오 파일을 지정하고 Upload 버튼을 눌러서 비디오 파일을 처리하기 위해 서버에 보낼 수가 있습니다.


실 upload.php 파일은 아주 기본적인 부분만 작성이 되어 있기때문에, 실제 서비스 용도로 사용하기 위해서는 에러 체크
루틴을 추가 적으로 작성해야 합니다. 그리고 그것보다도 더 큰 문제는 크기가 큰 비디오 파일을 업로드 하려고 할 때인데, 이런
경우에는 파일의 크기가 크기 때문에 비디오 변환 과정이 오래 걸리게 되고 유저의 대기시간이 상당히 길어지면서 더 큰 문제가
됩니다.

그럼 이런 문제를 해결하기 위한 방법은 뭐가 있을까요? 한 가지 방법으로 큰 크기의 비디오 파일이
업로드가 되면(10초 이상의 비디오 파일) 유저에게는 잠시 후에 비디오가 게시될 것이라고 말을 해 놓고 서버내의 다른 폴더에
비디오 파일을 저장한 후에 또 다른 스크립트를 이용해서 비디오를 변환하는 것입니다.

더 진행하기 전에 왜 꼭
플래시 비디오 파일로 변환을 해야 하는지에 대해서 생각을 해보도록 합시다. 그냥 원본 그대로 저장해도 되는데 왜 플래시 비디오로
변환을 하려고 하는 걸까요? 그건 원본 상태로 저장을 해 놓게 되면 각 비디오 파일의 타입 별로 비디오 플레이어를 찾아서 수행할
수 있는 코드를 작성을 해야만 하기 때문에, 굉장히 힘든 일이 될 것이라고 생각합니다.

이 과정을 플래시 파일로 변환하여 해결하게 되면 코드도 간단해지고 많은 OS에서 실행될 수 있도록 할 수도 있습니다.

그럼 이제 HTML과 플래시를 이용해서 유투브와 같은 입력양식을 간단하게 만들어 보겠습니다.

HTML과 플래시를 이용한 인터페이스 구성


력받은 URL을 가지고 플래시 비디오 파일을 재생하는 프로그램을 만들기 위해서는 Adobe Flex Builder 2를 이용해서
새로운 프로젝트를 만들어야 합니다. 새로운 프로젝트를 생성했다면 simplemovie.mxml 이라는 Flex 애플리케이션을
만들어야 합니다. 이 애플리케이션 파일의 내용은 다음 [리스트 4]와 같습니다.

[리스트 4] simplemovie.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:VBox backgroundColor="white" width="400" height="335">
<mx:VideoDisplay width="400" height="300" id="videoPlayer"
source="{Application.application.parameters.movie}" />
<mx:HBox width="100%" horizontalAlign="center">
<mx:Button label="Play" click="videoPlayer.play()" />
</mx:HBox>
</mx:VBox>
</mx:Application>

위 [리스트 4]에서 두가지 중요한 요소를 볼 수 있습니다 : VideoDisplay 요소는 비디오를 재생하는 역할을
하고 “Play”라는 이름을 가진 버튼은 비디오의 재생이 끝난 후에 유저가 클릭할 경우 비디오를 다시 재생하는 역할을 하게
됩니다.

VideoDisplay 요소는 “source”라는 속성을 가지게 되는데요, source 속성으로
재생해야 하는 플래시 비디오 파일의 URL을 지정하게 됩니다. 위 리스트에서 source 속성이 가지고 있는 값은 HTML
파일에 있는 <object>나 <embed> 태그에 있는 FlashVars 속성의 값이 되게 됩니다.

Flex
Builder를 이용하게 되면 위 [리스트 4]의 simplemovie.mxml 프로그램을 simplemovie.swf 파일로
변환할 수가 있고, 변환된 swf 파일을 bin 디렉토리에서 PHP가 있는 곳의 디렉토리로 이동시켜야 합니다. 그리고 PHP
페이지를 하나 만들어서 비디오를 재생시킬 수가 있습니다. 다음 [리스트 5]를 보도록 하죠.

[리스트 5] simpletest.php

<?php
require "DB.php";

$moviebase = 'http://localhost:8080/movies/';

$dsn = 'mysql://[email protected]/movies';
$db =& DB::connect( $dsn );
if ( PEAR::isError( $db ) ) { die($db->getMessage()); }

$source = null;
$movieId = 1;
if ( array_key_exists( 'movie', $_GET ) )
$movieId = $_GET['movie'];

$movies = array();
$res = $db->query( 'SELECT movieId, source, title FROM movies' );
while( $row = $res->fetchrow( ) ) {
$movies []= $row;
if ( $row[0] == $movieId )
$source = $row[1];
}

if ( $source == null )
$source = $movies[0][1];
?>
<html>
<body>
<table>
<tr><td valign="top">
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="400"
height="335"
codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
<param name="movie" value="simplemovie.swf" />
<param name="quality" value="high" />
<param name="flashVars" value="movie=<?php echo( $moviebase.$source ) ?>">
<embed src="simplemovie.swf" quality="high"
width="400" height="335" play="true"
loop="false"
quality="high"
flashVars="movie=<?php echo( $moviebase.$source ) ?>"
type="application/x-shockwave-flash"
pluginspage="http://www.adobe.com/go/getflashplayer">
</embed>
</object>
</td><td valign="top">
<?php
foreach( $movies as $movie ) {
?>
<a href="simptest.php?movie=<?php echo( $movie[0] )?>"><?php echo( $movie[2] )?></a><br/>
<?php
}
?>
</td></tr></table>
</body>
</html>

위 PHP 스크립트는 우선 데이터베이스에 접속한 후에 비디오 리스트를 받아오고 있습니다. 그리고 나서 URL을 통해서
넘어온 ID와 읽어온 비디오 리스트를 비교해서 동일한 ID를 가진 비디오가 있는지를 확인하게 됩니다. 동일한 ID를 찾을 경우
이 ID 값을 simplemovie.swf 파일로 넘기기 위해서 flashVars 속성에 지정하고 있습니다.

PHP
스크립트 다음 부분에서는 HTML 태그가 시작되고 simplemovie.swf 파일을 페이지에 표시하기 위한 태그인
<object>, <embed> 태그를 사용하고 있습니다. 물론 여기에 재생해야 하는 비디오에 대한
URL도 지정해 주고 있는 걸 볼 수 있습니다. 그리고 바로 아래에 현재 비디오외에 볼 수 있는 비디오에 대한 링크를 만들어
주고 있는 걸 볼 수 있습니다.

이제 웹 브라우저에서 [리스트 5]에 있는 페이지를 한 번 보도록 하겠습니다. 다음 [그림 2]와 같이 나오네요.


[그림 2] 간단한 비디오 플레이어와 함께 볼 수 있는 비디오에 대한 리스트가 출력되었다.

웹 브라우저를 열자마자 첫번째 비디오가 재생이 되게 되고, 오른쪽에 있는 비디오 리스트중에서 하나를 선택하면 페이지가 다시 로딩되면서 선택된 비디오가 재생되게 됩니다.

정말 간단하죠? Flex 파일 하나와 PHP 파일 하나, 그리고 데이터베이스만 가지고 위와 같이 비디오 공유 사이트를 만들었습니다.

이제 그럼 Flex를 조금 더 이용해서 유저 편의성을 향성시켜 보도록 하겠습니다.


역자 노재현님은 어렸을 때부터 컴퓨터를 접하게 된 덕에 프로그래밍을 오랫동안 정겹게 하고 있는 프로그래머 입니다. 특히나 게임
및 OS 개발에 관심이 많으며, 심심할 때면 뭔가 새로운 프로그램을 만들어내는 것을 좋아합니다. 다음에서 웹 관련 개발을 한
후에 현재는 www.osguru.net이라는 OS관련 웹사이트를 운영하며 넥슨에서 게임 개발을 하고 있습니다.
* e-mail: [email protected]
* homepage: http://www.oguru.net

Smarty 한글 메뉴얼

# PHPSCHOOL

– 원문 : http://www.phpschool.com/bbs2/inc_view.html?id=7186
&code=tnt2&start=0&mode=search&field=title&search

Smarty 메뉴얼을 번역하기 전 준비운동으로 먼저 이 문서를 번역해 봤습니다.
(세시간밖에 안 걸린 날림 번역이라 오역이 있을 수도있습니다. ^^;)
classroom에 올려야 할지 Tip & Tech에 올려야 할지 고민하다가 그냥 이곳으로
올립니다.

역자 : 조한석 <[email protected]>

역자의 변
———

메뉴얼도 아니고 가이드이므로 되도록 너무 딱딱하지 않게 원문의 뜻을 훼손하지 않는 범
위에서 직역보다는 의역으로 번역했습니다(그런 이유로 거북한 느낌을 가질 분도 생길지도
모르지만 그에 대해서는 책임지지 않겠습니다. 잘못 번역 된 부분의 있다면 위의 메일 주
소로 연락 부탁드리며, 특별히 사이트에서 참조하고 싶으신 분은 역자의 신상을 그대로 유
지하는 한 얼마든지 가능합니다(특별히 역자에게 허락을 받을 필요는 없고, 알려줄 필요도
없지만, 해 주면 고맙겠죠. ^^;).

SMARTY QUICKSTART GUIDE (Smarty 빠르게 시작하기)
————————————————

Smarty QuickStart Guide(Smarty 빠르게 시작하기)에 오신 것을 환영해요~ 이 가이드는
Smarty에 처음 발을 적시는 당신에게 Smarty가 어떻게 동작하는지 안내해 줄 거랍니다.

우리는 여기서 몇 가지 가정을 해볼 생각인데요. 당신이 이미 웹 서버에 PHP를 어떻게 설
치해야 하는지라던가, Unix 파일 퍼미션들에 대한 기초지식이나 그리고 PHP가 어떻게 동작
한다든지 등에 대한 기초지식을 가지고 있어야 하겠지요. 만약 당신이 Unix 환경이 아닌
곳에서 Smarty를 사용하고 있다면 당신은 자신의 OS와 관련된 파일 파미션 시스템이 Unix
와 어떤 차이점을 가지고 있는지 알고 있을 필요가 있답니다.

INSTALLATION (설치하기)
———————–

Smarty 압축 파일을 풀면 당신은 Smarty.class.php, Smarty_Compiler.class.php,
Config_File.class.php 그리고 “plugins” 디렉토리 같은 여러 파일들을 볼 수 있을 텐데
우선 이 모든 파일들을 당신의 PHP include_path에 지정되어 있는 디렉토리 어딘가에 옮
길 필요가 있어요. 그러고 나서  PHP 스크립트에[역주: 원문에서는 PHP 스크립트라고 하
는 대신 “your application”이라고 했지만, 이 편이 더 이해가 빠를 것 같아 이렇게 번역
했습니다] require(“Smarty.class.php”) 문장을 적어주면 해당 클래스를 찾을 수 있게 되
겠지요. 음, 하지만 다른 방법으로 당신의 PHP 스크립트에 SMARTY_DIR 상수를 설정하는 방
법도 있어요. Smarty 클래스 파일들이 위치한 패스가 있는 디렉토리들은 이 두 가지 방식
을 사용할 수 있는데, 여기서 매우 중요한 것 하나는 SMARTY_DIR 패스를 지정할 때는 끝에
슬래쉬를 꼭 붙여야 한다는 것이겠죠!

자 그럼 이제 실제로 당신의 웹 서버의 Document Root 디렉토리 어딘가로 시야를 옮겨 보
도록 하지요. 이 가이드에서는 당신이 웹 서버의 Document Root에 만들 디렉토리 이름으
로 Smarty를 사용할 텐데, 모든 작업은 여기에서 이루어지고 있음을 잊지 마세요.

$> cd /home/htdocs
$> mkdir Smarty
$> cd Smarty

다음 차례는 Smarty가 사용할 디렉토리들을 만들 차례가 되겠군요.

$> mkdir templates
$> mkdir templates_c
$> mkdir configs

Smarty는 쓰기가 가능한 templates_c 디렉토리를 필요로 한답니다. 그러므로 당연히 당신
은 해당 디렉토리를 웹 서버 유저(보통 Unix에서는 “nobody:nobody”이 사용되고 Max OS에
서는 “www:www”이 사용되지요.[역주:레드햇 리눅스에서는 “apache:apache”가 사용됩니다])
가 쓰기가 가능하도록 해당 디렉토리의 소유주와 퍼미션을 아래와 같이 고쳐주어야겠지요.

물론 당신은 ‘chmod 777’을 사용할 수도 있어요. 음 그렇지만, 글쎄요. 많은 사용자들이
사용하는 시스템에서는 보안 문제도 있고 하니 별로 권장하고 싶지는 않군요. 이것에 대
해서는 메뉴얼에서 보다 많은 정보를 찾아보는 것이 좋을 것 같군요.

$> chown nobody:nobody templates_c
$> chmod 700 templates_c
$> ls -l
drwxrwxr-x   2 user    group        512 Jan 18 14:18 configs/
drwxrwxr-x   2 user    group        512 Jan 18 14:18 templates/
drwx——   2 nobody   nobody       512 Jan 18 14:18 templates_c/

위와 같이 하거나 덜 안전한 방법으로 아래와 같이 해 줄 수도 있어요.

$> chmod 777 templates_c
$> ls -l
drwxrwxr-x   2 user    group        512 Jan 18 14:18 configs/
drwxrwxr-x   2 user    group        512 Jan 18 14:18 templates/
drwxrwxrwx   2 user    group        512 Jan 18 14:18 templates_c/

 
자 이제 당신은 index.php와 templates/index.tpl이라는 두 개의 파일을 만들 차례가 되
었네요. 물론 index.php는 당신의 웹 브라우져에서 부를 수 있는 것이어야겠지요.

index.tpl은 Smarty가 템플릿 파일로서 사용할 파일인데, 이것은 브라우져에서 직접 엑세
스되지는 않고, 오직 Smarty 클래스에 의해서만 접근된답니다[역주:실제로 위와 같이 하
면 웹 서버에 특별한 설정을 추가하지 않는 웹 브라우져를 통해 접근할 수 있습니다].

——— index.php ——–
<?php
require(“Smarty.class.php”);
$smarty = new Smarty;
$smarty->assign(“Name”,”Ned”);
$smarty->display(“index.tpl”);
?>

——— templates/index.tpl ——–
<HTML>
<TITLE>Hello</TITLE>
<BODY>
   Hello, {$Name}!
</BODY>
</HTML>

자 이제 잘 작동하고 있는지 index.php를 당신의 웹 브라우져로부터 불러 보세요.

http://your.host.com/Smarty/index.php

당신의 브라우져로부터 “Hello, Ned!”를 볼 수 있나요? 그렇지 않다면 지금까지 위에서
해 온 과정들을 잘 따라 했는지 살펴보시고 다시 시도해 보세요. 아니면 메뉴얼에 있는
설치 작업에 관한 부분을 체크해 보고, 당신이 PHP 설치를 제대로 했는지도 살펴볼 필요
가 있을 거에요. 그래도 여전히 문제가 있다면 메일링 리스트에 질문을 던져 보던가 FAQ
에서 문제를 해결할 수 있을지도 모르겠네요.

이제 “Hello, Ned!”를 브라우져로부터 볼 수 있다구요? 좋아요~[역주: 차범근 스타일로
읽어 보세요. :)]

Smarty가 index.tpl를 어떻게 php 스크립트로 컴파일했는지 궁금하시다면 templates_c 디
렉토리를 찾아보시면 알 수 있어요. Smarty는 이렇게 맨 처음 한번만 컴파일하고 그 다음
에는 게속 이 컴파일된 스크립트를 가지고 작동하게 된답니다. 물론 index.tpl이 바뀌게
된다면 자동으로 재컴파일해서 대체하게 되지요[역주:이것은 JSP가 채택하고 있는 방식과
굉장히 유사하다고 볼 수 있습니다].

이런 이유로 당신은 templates_c 디렉토리에 대해서는 관심을 끄셔도 좋아요. 당신은 이
런 기술적 부분에 대해서 걱정할 필요가 하나도 없고, 이런 부분은 Smarty에게 떠넘겨 버
리면 되요. 참, 그리고 당신은 템플릿으로부터 컴파일된 PHP 스크립트를 볼 수 있고 그것
을 아마 고칠 수도 있을 거에요 하지만, 이것들을 고칠 생각은 절대로 하지 않는 게 신상
에 이로울 테죠?

여기까지 잘 되었다면, 이제 당신은 잘 작동하는 Smarty를 가지게 되었으므로 이제
Smarty에서 사용하고 있는  템플릿 언어의 특징들 중 몇 가지를 살펴보도록 하지요.

ASSIGNING VARIABLES (변수 대입)
——————————-

템플릿으로의 변수 대입은 변수와 값을 쌍으로 해서 직접 대입되게 되는데, 예를 들면 아래와 같이 소스가 구성된답니다.

——— index.php ——–
<?php
require(“Smarty.class.php”);
$smarty = new Smarty;
$smarty->assign(“Name”,”Ned”);
$smarty->assign(array(
                     “FirstName” => “Ned”,
                     “LastName” => “Flanders”,
                     “Address” => “Springfield”
                     ));
$zipcode = “55555”;
$smarty->assign(“Zipcode”,$zipcode);
$smarty->display(“index.tpl”);
?>

——— templates/index.tpl ——–
<HTML>
<TITLE>Hello</TITLE>
<BODY>
   Hello, {$Name}!<br>
   {$FirstName}, {$LastName}<br>
   {$Address}, {$Zipcode}
</BODY>
</HTML>

당신은 변수들을 일 대 일로 대입할 수도 있고, 혹은 연관 배열을 사용할 수도 있고 대입
된 변수들을 추가할 수도 있는데, 이것에 대해서 메뉴얼에서 자세히 설명해주니까 그것을
참조하면 되겠지요.

INCLUDE (템플릿 포함하기)
————————-

이제는 Smarty에서 다른 템플릿 파일들을 어떻게 포함하는지 살펴보도록 하지요. 이것은
당신이 headers나 footers같은 반복적인 템플릿 데이터를 사용할 경우를 위한 것인데요.
이를 위해서는 templates/header.tpl과 templates/footer같은 별도의 템플릿 파일들을 만
들 필요가 있답니다.

——— index.php ——–
<?php
require(“Smarty.class.php”);
$smarty = new Smarty;
$smarty->assign(“Name”,”Ned”);
$smarty->assign(array(
                     “FirstName” => “Ned”,
                     “LastName” => “Flanders”,
                     “Address” => “Springfield”
                     ));
$zipcode = “55555”;
$smarty->assign(“Zipcode”,$zipcode);
$smarty->display(“index.tpl”);
?>

——— templates/index.tpl ——–
{include file=”header.tpl” title=”Home Page”}
   Hello, {$Name}!<br>
   {$FirstName}, {$LastName}<br>
   {$Address}, {$Zipcode}
{include file=”footer.tpl”}

——— templates/header.tpl ——–
<HTML>
<TITLE>{$title|default:”no title”}</TITLE>
<BODY>

——— templates/footer.tpl ——–
</BODY>
</HTML>

우리가 포함한 header.tpl에 어떻게 “title”이라는 변수를 넘겨주고 있는지 주목해 보세
요. 당신은 이런 식으로 당신이 원하는 더 많은 변수들을 넘겨줄 수 있어요. 포함된 템플
릿 파일들은 현재 템플릿 변수들을 모두 물려받게 되고 또한 위와 같이 넘겨진 변수들도
가지게 되는데, 이렇게 넘겨진 변수들은 오직 포함된 템플릿 파일에만 유효한 변수가 되
지요[역주: 함수에 넘겨진 변수는 함수 내에서만 접근되고 그 다음 사라지듯이 Smarty도
템플릿에서 포함한 파일로 이루어지는 변수 전달을 같은 방식으로 처리한다는 뜻입니다].

그리고 templates/header.tpl에서 $title 변수를 어떻게 출력하는지도 주목할 필요가 있
겠지요. 이것은 “default”라고 불리는 변수 변환자[역주: “variable modifier”가 원문인
데 변수 치환자라고 할까 하다가 이렇게 번역했습니다]를 사용한 모습이랍니다.

{$title}이라는 문장이 $title로 대입된 변수가 없으면 아무것도 하지 않는데 반하여
{$title|default:”no title”}이란 문장은 $title로 대입된 변수가 없어도 앞의 경우처럼
빈둥거리는 대신 “no title”이라는 출력을 수행한답니다.

IF/ELSEIF/ELSE
————–

아래 에제는 매우 직접적인 문법을 보여주고 있을 뿐이랍니다. 메뉴얼에서 좀 더 자세하
게 이 문법에 대해 설명해 주니까 좀 더 알고 싶은 분은 메뉴얼을 참조하도록 하세요.

——— templates/index.tpl ——–
{include file=”header.tpl” title=”Home Page”}
       {if $Name eq “”}
               Hello, Noname!<br>
       {elseif $Name eq “Ned”}
               Hello, Neddy!<br>
       {else}
               Hello, {$Name}<br>
       {/if}

       {$FirstName}, {$LastName}<br>
       {$Address}, {$Zipcode}
{include file=”footer.tpl”}

SECTIONS: Dynamic Blocks (섹션: 동적 블럭)
——————————————

Smarty에서 {section} 기능을 사용하면 비교적 간단하게 배열들을 반복해서 출력할 수 있
어요. 여기서 section에는 두가지 속성이 필요로 한답니다. 하나는 name인데 말 그대로
이것은 section의 이름이랍니다[역주: 아래 예제를 보시면 아시겠지만, 이 name 속성은
템플릿 내에서 사용됩니다]. 그리고 또 다른 하나는 loop라는 속성인데, 이 loop는
section에서 몇 번이나 반복할 지 반복횟수를 설명하고 있는 배열의 이름을 가리킨답니
다[역주: 아래 예제에서 “FirstName”과 “LastName”이라는 변수와 함께 지정된 배열의 크
기가 3이므로 3번 반복하게 됩니다.]

——— index.php ——–
<?php
require(“Smarty.class.php”);
$smarty = new Smarty;
$smarty->assign(“FirstName”,array(“Ned”,”Bart”,”Montgomery”));
$smarty->assign(“LastName”,array(“Flanders”,”Simpson”,”Burns”));
$smarty->display(“index.tpl”);
?>

——— templates/index.tpl ——–
{include file=”header.tpl” title=”Home Page”}
   {section name=people loop=$FirstName}
       {$smarty.section.people.rownum} {$FirstName[people]} {$LastName[people]}<br>
   {sectionelse}
       There are no values to loop through.
   {/section}
   <p>
   There were {$smarty.section.people.loop} names in this list.
{include file=”footer.tpl”}

여기서 템플릿 내에서 사용된 {$smarty}라는 변수에 대해서 소개할 필요가 있을 것 같네
요. section 내에서 출력되는 변수들을 주목해 보세요. 이처럼 section 내에서 출력할 변
수들은 모두 반드시 섹션 이름으로 참조될 필요가 있음을 잊지 마세요. 이것은 당신이 출
력하고 싶은 값을 배열에서 현재 반복 횟수를 가지고 찾기 위해 필요한 거에요. 또한 내
부 템플릿 변수들을 가지고 현재 반복 중인 section의 총 반복횟수와 현재 반복 횟수 같
은 것도 출력이 가능하답니다. {sectoinelse}도 중요한 건데, 이것은 만일 반복할 배열인
$FirstName이 빈 배열의 경우 대신 출력되는 부분이 된답니다.

그리고 아래 예제에서 사용된 문법처럼 배열의 키들을 가지고 접근할 수도 있어요.

——— index.php ——–
<?php
require(“Smarty.class.php”);
$smarty = new Smarty;
$smarty->assign(array(“ContactInfo” =>
     array(
   array(“FirstName” => “Ned”,”LastName” => “Flanders”),
   array(“FirstName” => “Monty”,”LastName” => “Burns”)
   )
                     ));
$smarty->display(“index.tpl”);
?>

——— templates/index.tpl ——–
{include file=”header.tpl” title=”Home Page”}
   {section name=people loop=$ContactInfo}
       {$ContactInfo[people].FirstName}
               {$ContactInfo[people].LastName}<br>
   {sectionelse}
       There are no values to loop through.
   {/section}
   <p>
   There were {$smarty.section.people.loop} names in this list.
{include file=”footer.tpl”}

혹은 아래 예제처럼 당신은 복합 중첩 section 문을 시도해볼 수도 있답니다.

——— index.php ——–
<?php
require(“Smarty.class.php”);
$smarty = new Smarty;
$smarty->assign(“FirstName”,array(“Ned”,”Bart”,”Montgomery”));
$smarty->assign(“LastName”,array(“Flanders”,”Simpson”,”Burns”));
$smarty->assign(“ContactNames”,
array(
     array(“email”,”home”,”cell”),
     array(“email”,”home”),
     array(“email”,”home”,”fax”)
     ));
$smarty->assign(“ContactVals”,
array(
     array(“[email protected]”,”555-666-7777″,”555-444-3333″),
     array(“[email protected]”,”555-111-2222″),
     array(“[email protected]”,”555-888-9999″,”555-234-5678″),
     ));

$smarty->display(“index.tpl”);
?>

——— templates/index.tpl ——–
{include file=”header.tpl” title=”Home Page”}
   {section name=people loop=$FirstName}
       {$smarty.section.people.rownum} {$FirstName[people]} {$LastName[people]}<br>
       {section name=contacts loop=$ContactNames[people]}
           {* for fun, lets bold every other row *}
           {if $smarty.section.contacts.rownum is even}<b>{/if}
            {$ContactNames[people][contacts]}: {$ContactVals[people][contacts]}<br>
           {if $smarty.section.contacts.rownum is even}</b>{/if}
       {/section}
       <br>
   {sectionelse}
       There are no values to loop through.
   {/section}
   <p>
   There were {$smarty.section.people.loop} names in this list.
{include file=”footer.tpl”}

FOREACH (반복문)
—————-

특별히 당신이 오직 한 가지 변수를 통해 반복문을 만들고 싶다면, 그런 당신을 위해 좀
더 쉬운 방법으로 연관배열을 반복시킬 수도 있는데, 이를 보여주는 아래 예제는 Smarty
와 함께 제공하는 디폴트 index.php에서 작동하는 템플릿인데,

{foreach name=outer item=contact from=$contacts}
 {foreach key=key item=item from=$contact}
   {$smarty.foreach.outer.iteration}. contact {$key}: {$item}
 {/foreach}
{foreachelse}
 no contacts
{/foreach}

여기서 가능한 속성들로는 다음과 같은 것들이 있어요[역주: 아래의 item, key, from은
PHP에서는 foreach($array as $key=>$item)와 각각 대입된다고 생각하시면 됩니다]

from: 반복의 대상이 되는 배열
item: 배열의 현재 요소를 가리키는 변수의 이름
key:  배열의 현재 키를 가리키는 변수의 이름(선택적)
name: foreach의 이름 (선택적)

그리고 당신이 만일 ‘name’을 사용한다면 다음과 같이 보다 다양한 foreach 속성들을 추
가할 수도 있으며[역주: first, last, show는 무슨 소리를 하고 있는지 잘 모르겠습니다.
메뉴얼에도 이 부분은 설명한 게 없고요. 실제 예제를 작성해 봐야 알 것 같군요. –;],

name:      foreach의 이름
iteration: 현재 반복 횟수
total:     반복할 전체 횟수
first:     if it’s first iteration
last:      if it’s last iteration
show:      if foreach was shown at all

아래 있는 템플릿은 foreach의 모든 속성들을 출력해 주는 예제랍니다[역주:두번째
foreach 문장에서 $smarty.foreach.outer가 from 속성의 값으로 지정된 것을 주목하
시기 바랍니다. 여기에 contact를 지정한 경우 전혀 다른 출력이 나옵니다].

{foreach name=outer item=contact from=$contacts}
 {foreach key=key item=item from=$smarty.foreach.outer}
   {$key}: {$item}
 {/foreach}
{/foreach}

자, 이제 Smarty에 들여놓은 당신의 발은 어느 정도 충분히 적셔졌을 거에요. 그러나, 아
직 config 파일 변수들이나, built-in 함수들, 커스텀 함수들, 변수 변환자 같은 굵직굵
직한 공부거리가 남아 있답니다. 지금 당장 메뉴얼을 읽으러 가세요[역주: 각종 템플릿
라이브러리 중에서 가장 방대한 양을 자랑하는 메뉴얼입니다. ^^;]. 메일링 리스트에도
가입하시는 것이 좋겠지요. 그럼 앞으로도 Smarty를 즐기시기를!!

역자가 추가한 문서 내 리소스
 Smarty 웹 사이트 : http://smarty.php.net
 Smarty 메일링 리스트 아카이브
  일반:   http://news.php.net/group.php?group=php.smarty.general
  개발:   http://news.php.net/group.php?group=php.smarty.dev
  CVS:   http://news.php.net/group.php?group=php.smarty.cvs