'내 폴더/스크랩'에 해당되는 글 88건
- 2007.11.30 PHP사용 테스트
- 2007.11.15 석사과정
- 2007.11.15 웹로그 분석기 Webalizer
- 2007.10.12 mod_rewrite의 개념
- 2007.10.11 '터닝 포인트(Turning Point)'
- 2007.10.11 Apache Modules .. [ mod_rewrite ]
- 2007.10.08 Php5에서 다른 새로운 것들
- 2007.10.07 FreeMind - free mind mapping software
- 2007.10.06 스크립트 언어의 새로운 보석 루비 (Ruby)
- 2007.09.26 웹 프로그래밍 언어 php의 새로운 도전「php5」
?=PHPE9568F36-D428-11d2-A769-00AA001ACF42
?=PHPE9568F34-D428-11d2-A769-00AA001ACF42
?=PHPE9568F35-D428-11d2-A769-00AA001ACF42
?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000
일단 돈이나 많이 모아놔야겠다..
2년하고 2개월 조금 안 남았다.................
이건 뭐.. 군대야? ;;
정작 서울대 애들은 외국 대학원으로 가고.
서울대 대학원을 포함한 대부분의 메이커 대학원들은 타대학 학부생들이란다.
뭐 당연한 말이겠지만. 일단 name value를 우선시 하니까.
문제는 역시 영어인가? 아~ 놔 ~~ 스트레스~!!!!
출처 : http://blog.naver.com/minuk3542?Redirect=Log&logNo=90009748577
웹로그 분석기 Webalizer
mod_rewrite의 개념
일반 적인 아파치의 기능은
요청된 URL에 적절한 파일을 HTTP에 맞게 전송하는 것이다.
mod_rewrite는 요청된 URL에 대해
관리자가 목적에 맞게 변경하여 요청자에게 응답할 수 있는 기능을 제공한다.
예 일반적인 경우
httpd.conf :
DocumentRoot : /some/local/path/요청 :
http://host/somedir/somefile.html서버가 응답하는 실제 내용
/some/local/path/somedir/somefile.html
예 :Rewrite
httpd.conf :
DocumentRoot : /some/local/path/
RewriteRule ^/somedir/(.*)$ /anotherdir/$1요청 :
http://host/somedir/somefile.html서버가 응답하는 실제 내용
/anotherdir/somefile.html
이와 같이 실제 요청자의 웹브라우저에 표시되는 URL을 통해
서버의 예상되는 위치에 존재하는 파일을 읽어 전송하는 것이 아니라,
별도의 위치에서 전송할 수 있도록 해주는 것이다.
이런 기능외에 로드발랜싱이나 프록시와 같은 기능으로 연결하거나,
혹은 다른 URL로 redirect를 시킬 수도 있다.
기본적으로 rewrite엔진에 넘겨지는 것은 경로(path)이다.
경로라 하면... http://host:80/somedir/somefile.html 에서
/somedir/somefile.html 까지를 의미하고, 포트와 호스트네임은 포함되지 않는다.
웹서버는 이 내용을 기준으로 하여 절적한 파일을 읽어 들이게 되는데...
바로 mod_rewrite는 웹서버가 이 경로와 다른 경로를 읽어 들일 수 있도록 하는 기능을 제공하는 것이다.
몇가지 접근하는대 필요한 개념은 아래와 같다.
입력자 : 웹서버
응답대상: 웹서버
입력값 : "(상대) 경로(path)"
출력값 : "(절대)경로 혹은 요청자에게 답변하는 내용."
mod_rewrite라고 했듯이 모듈이기 때문에..
상대자는 오직 웹서버 뿐이다. 즉 입력값을 받는 것도 답변을 하는 것도
웹서버라는 것이다.
그리고... 입력값은 상대 경로이다. (당연하겠지만)즉 서버내 물리적 위치가 아니다.
하지만 응답을 하는 것은 절대경로로 응답해야 한다. 서버가 실제로 읽어 들일
물리적 위치를 지정하는 것이다.
RewriteRule 1
RewriteRule은 입력값을 변경해주는 유일한 키워드이며, mod_rewrite의
핵심이라고 할 수 있다.
#Syntax:
RewriteRule Pattern Substitution flags
패턴에 따라 넘겨 받은 값을 치환(Substitution)하는 것이다.
패턴과 치환에 관한 방식은 펄의 정규화 표현식과 유사하다.
php의 ereg_replace나 혹은 sed, vi의 치환 명령에 익숙하다면
쉽게 접근할 것이다.
이 것에 대한 자세한 내용은 나중에 다루고..
이번엔 이명령의 중요한 개념에 대해서 설명하고자 한다.
문법에서 보여주는 것대로 한다면,
패턴에 맞게 입력값을 나누고, 거기에 맞게 치환하는 것으로 보인다.
근데 여기에 함정이 있다.
아래의 PHP Code를 보자.
<?php
function RewriteRule($pattern, $Substitution, $flags= 0)
{
//웹서버에서 넘겨 받아 거나 이전의 RewriteRule의 결과값
global $URL;
// 정규화 표현식 실행
$tmp = ereg_replace($pattern,$Substitution,$URL);
// 결과물이 URL과 일치하면.. 즉 패턴에 일치하지 않고
//아무런 변화가 없으면 함수를 빠져나간다.
if($tmp == $URL) return ;
//정규화표현식의 실행값을 반영한다.
$URL = $tmp;
//추가적인 기능이 지정되어 있지 않으면, 함수를 종료한다.
if($flags== 0) return ;
//추가적인 기능에 L이 있으면 해당 기능을 수행한다.
if(ereg("L",$flags){
something about "L";
}
//추가적인 기능에 P가 있으면 해당 기능을 수행한다.
if(ereg("P",$flags){
something about "P";
}
.
.
.
.
}
?>
좋은 코드는 아니다.
하지만.. RewriteRule의 동작방식을 이해하는 데는 충분하다고 본다.
RewrieRule은 단순히 치환기능만이 있는 것이 아니라
Condition 즉 특정한 패턴의 검출 여부에 따라
동작을 수행 혹은 수행하지 않는
조건문을 함께 포함하고 있는 구조다.
이 점을 놓치면, rewrite를 이해하는데 매우 고생스럽다.
RewriteRule /cgi-bin(/.*)$ /cgi-bin$1 [L,PT]
먼저 설명이 안됀 플래그 L,PT가 있다..
PT에 대해서는 나중에 설명을 하고..
L에 대해서만 설명하겠다.
L이란 Last Rule의 약자로... 이 RewriteRule 뒤의 라인을 점부 무시하라는 뜻이다.
위의 내용은
요청된 URL중에 /cgi-bin이란 내용이 포함된 내용을 치환하고,
/cgi-bin$1이란 내용을 중심으로 Rewrite를 종료하라는 뜻이다.
그런데.. 요청된 내용에 /cgi-bin이란 내용이 없으면 어떻게 될까?
정답은 해당 RewriteRule은 무시가 된다.
이렇듯 단순한 치환명령이 아니라, 조건이 포함되어 있는 명령이라는 것을 명심하자.
'터닝 포인트(Turning Point)'
현재 상황이나 환경은
당신이 지금까지 해온 생각의 결과다.
사람들은 대부분 자신의 현 상태를 바라보면서
"이게 나야"라고 말한다. 그건 당신이 아니다.
그건 과거의 당신이다. 예를 들어 당신에게
현재 돈이 얼마 없거나, 원하는 배우자가 곁에 없거나,
원하는 만큼 건강하지 않다고 해보자.
그건 당신이 아니라, 과거의 생각과 행동이 만들어낸 결과다.
- 론다 번의《시크릿(The Secret)》중에서 -
Apache Modules .. [ mod_rewrite ]
4. Apache Modules .. [ mod_rewrite ]
mod_rewrite module은 재작성 패턴(rewrite pattern)을 받아들여 URL에 적용을 한다. 여기서 패턴이라는 것은 정규 표현식(regular expression)을 의미하며 이 정규 표현 식에 match가 되는 pattern을 요청한 url에서 출력을 하게 되는 것이다.
이 module은 설정 전체, virtual host, Directory 지시자, .htaccess에서 사용이 가 능하다.
머 이렇다 저렇다 설명하는 것 보다 몇가지 예제를 보는 것이 더 낳을 것이다. 여기 서는 2가지의 예를 들려고 한다. mod_rewrite module에 대해서 전반적으로 다 다루기 에는 양이 너무 많고 혹시 관심이 있는 사람은 O'reilly 에서 나온 Apache: The Definitive Guide 의 8장 Redirection 을 참조하면 되겠다. 참고로 "아파치 핵심 가이드"라는 책으로 변역서 가 출판되어 있다. 1. domain.com/~id 를 id.domain.com 으로.. 이 작업을 하기 전에 먼저 선행되어야 할 일이 있다. 일단 name server에서 a.com 에 대해서 설정을 하자면 a.com의 어떠한 서브 도메인들도 다 등록이 되어 있어야 한다. bind8 부터는 *.a.com 을 등록하여 이를 행할수가 있다. |
Hanterm - cat /etc/httpd/conf/httpd.conf |
[root@bbuwoo /etc]$ cat /etc/httpd/conf/httpd.conf 생략... RewriteEngine on RewriteCond %{HTTP_HOST} ^[^.]+\.oops\.org$ RewriteRule ^(.+) %{HTTP_HOST}$1 [C] RewriteRule ^([^.]+)\.oops\.org(.*) /home/$1/htdocs$2 생략... [root@bbuwoo /etc]$ |
RewriteEngine을 on하여 Rewrite 기능을 활성화 한다. RewriteCond 는 RewriteModule이 URI만 다룰수 있기 때문에 RewriteRule에서 domain 부분까지 다루기 위하여 %{HTTP_HOST}를 match시키게 한다. RewriteRule로 먼저 접속한 서버의 경로(URI) 즉 domain.com의 뒤의 경로 부분을 %{HTP_HOST} 뒤로 매치시킨다. [C] 는 서로 연결된 규칙들을 순차적으로 적용을 하는 것을 의미한다. RewriteRule을 한번더 적용시켜서 domain.com의 앞부분을 $1변수로 받고 뒤의 경로들을 $2로 받은 다음 읽혀져야할 절대 경로에 매치를 시킨다. 그리고 apache 를 재시작 한후에 id.domain.com 으로 접속을 해보기 바란다. :-)
이것을 설명하기 전에 어떠한 상황인지 예를 들어 보자. 일단 나의 홈페이지는 http://www.oops.org, http://oops.kr.net, http://goes.co.kr (외에도 2개가 더있다 ^^) 등으로 접속을 할수가 있다. 그런데 http://goes.co.kr 로 접속을 했을 경우 http://goes.co.kr/bbuwoo.html 이 아니라 http://www.oops.org/bbuwoo.html 로 자동으로 포워딩이 되게 하고 싶을때 아래처럼 구현을 하면 가능하다. 즉 위의 url중에서 domain부분만 자신의 대표 도메인으로 싸악 바꿔치기를 하기위한 방법이다. 실제로 예를 보고 싶다면 내 홈페이지의 아무 페이지나 oops.org외의 도메인으로 접근을 해 보기 바란다. 접근을 하는 순간 url이 www.oops.org로 바뀌는 것을 볼수 있을 것이다. 이것을 구현하기 위해서는 rewrite rule만으로는 불가능하고 domain 부분을 www.oops.org 로 변경해 주는 하나의 script가 필요하다. 일단 www.oops.org 의 웹 경로중의 하나에 Rewrite 라는 디렉토리를 만들고 위에서 domain부분을 바꿔 치기 하는 script를 아래와 같이 하나를 만들어 넣는다. 아래의 script 예는 PHP로 예를 들겠다. |
Hanterm - cat /home/httpd/Rewrite/index.php |
[root@bbuwoo Rewrite]$ cat index.php <? $que = getenv("REQUEST_URI"); $path = "http://www.oops.org$que"; echo "<META HTTP-EQUIV=\"refresh\" CONTENT=\"0;URL=$path\">"; ?> [root@bbuwoo Rewrite]$ |
위의 script를 분석해 보면 getenv("REQUEST_URI") 는 domain name 뒤의 경로를 받아오는 apache 환경 변수이다. 그리고 $path라는 변수에 메인 domain을 지정 하고 나머지 경로를 변수값으로 부여를 해 준다. 즉 경로없이 도메인으로만 접 근했을 경우를 위해서 위와 같이 구성이 된다.
다음 실질적으로 matching을 해 주는 apache에서의 Rewrite rule을 살펴 보도록 한다. |
Hanterm - cat /etc/httpd/conf/httpd.conf |
[root@bbuwoo /etc]$ cat /etc/httpd/conf/httpd.conf RewriteEngine on RewriteCond %{HTTP_HOST} (.+)\.(co\.kr|kr\.net)$ RewriteRule ^(.+)$ %{HTTP_HOST}$1 [C] RewriteRule (.+)\.(co\.kr|kr\.net)(.*) /Rewrite/index.php [root@bbuwoo /etc]$ |
위의 Virtual Host에서 Rewrite를 살짝 분석해 보자.
RewriteEngine을 on하여 Rewrite 기능을 활성화 한다. 이렇게 하는 이유는 Rewrite는 url을 바꾸는 것이 아니라 해당 url로 접속을 했을때 보여주는 부분만 match를 시키기 때문이다. 그래서 우리는 url을 바꾸기 위해서 특정 script를 이용하기 위함이다. 일단 Rewrite Rule에 적용되어진 도메인 즉, 예를 들어 http://www.goes.co.kr/bbuwoo.html 같은 경우 *.co.kr에 match가 되어 Rewrite/index.php를 출력하게 되고, index.php에서는 URI부분을 받은 다음 도메인 부분만 바꿔치기 하여 새로운 URL로 forwarding을 하게 되는 것이다. |
출처 : Tong - heheya님의 WEB통
Php5에서 다른 새로운 것들
이 문서는 http://www.zend.com/php5/andi-book-excerpt.php/ 의 내용을 제가 번역, 수정한 내용입니다. 질문이나 의견 있으신 분은 이메일이나 코멘트를 이용해 주시면 감사하겠습니다. 부분적으로 귀찮아서 생략한 부분도 있는데, 꾸준히 보강하겠습니다. 이 문서는 php5에 관심있는 모든 프로그래머를 위해 씌여졌습니다.
목차
- 소개
- 언어 특징
- 새로운 객체지향 모델
- 새로운 객제지향 특징
- 다른 새로운 언어 특징
- 일반적인 언어 변화
- XML과 웹 서비스
- 새로운 MySQLi(MySQL) 확장
- SQLite 확장
- Tidy 확장
- Perl 확장
- PHP 5에서 다른 새로운 부분
- 요약
미래를 준비하는 가장 좋은 방법은 미래와 직면하는 것이다.(존 스컬리)
1. 소개
만약 PHP 5가 이전 버전(php 3, php 4)처럼 성공할 것인지는 시간이 말해 줄 것이다. 모든 단점의 PHP를 제거하기 위한 목적 바뀐 새로운 특징과 변화는 전세계에서 최고의 웹 스크립트 언어로서 선도적인 위치를 지킬 것이다. 이 책은(이 문서는 PHP 5 Power Programming라는 책의 2장입니다) PHP 5를 다루고 있고, 자세하게 새로운 특징도 있다. 그렇지만, PHP 4에 익숙한 사람들을 위해 PHP 5에서 새로운 점을 알고 싶은 사람을 위해 이 장을 썼다.
2. 언어 특징
새로운 객체 지향 모델
지브 사라스키(Zeev Suraski, 일본인?)가 PHP 3시절에 객체 지향 문법을 추가했을 때, 그것은 객체에 접근하기 위한 문법적인 설탕처럼 추가했다. 객체지향 모델은 상속을 지원했고 메소드와 속성을 둘 다 합치기 위해 클래스를 만들었다. 그러나 그 이상은 아니었다. 지브와 앤디가 php 4를 위한 스크립트 엔진을 다시 작성할 때, 그것은 완전히 새로운 엔진이었고, 보다 빠르게 돌아갔고, 보다 많은 특징에 적합했다. 그렇지만 객체지향 모델은 PHP 3에서 처음 도입되었고, 미숙한 부분이 있었다.비록 객체 모델이 심각한 한계가 있었지만 그것이 큰 규모의 PHP 어플리케이션으로 전세계에서 확산되어 사용되었다. 그것이 단점에도 불구하고 PHP 4로 OOP 패러다임의 인상적인 사용은 PHP 5 버전을 위한 주요 관심이 되었다.
PHP 3 & 4의 한계가 무엇인가? 가장 큰 단점은 객체의 복사 의미가 네이티브 타임을 위한것과 같다는 사실이다. PHP 개발자에게 어떠한 영향을 미쳤는가? 우리가 변수를 (객체에 대한 참조) 다른 변수에 할당할 때, 객체의 복사는 생성된다. 이것은 강한 성능 뿐만 아니라 php4 어플리케이션에서 버그를 유발한다. 왜냐하면 많은 개발자는 변수
예를 들면
class Person { var $name; function getName() { return $this->name; } function setName($name) { $this->name = $name; } function Person($name) { $this->setName($name); } } function changeName($person, $name) { $person->setName($name); } $person = new Person("Andi"); changeName($person, "Stig"); print $person->getName(); |
php4에서 이런 코드는 “Andi”를 출력한다. 이 이유는 우리가 변수로 changeName() 함수에 객체 $person을 넘기고, 그래서, $person은 복사되고 changeName()은 $person의 복사에서 작업한다. 이런 동작은 자바 같은 동작을 기대했던 많은 개발자에게는 직관적이지 않다. 자바에서 변수는 정확이 핸들(또는 포인터)을 객체에 붙들고 있다. 그러므로 그것은 단지 핸들만 복사될 뿐 전체 객체는 복제되지 않는다.
PHP 4에서 사용자는 두가지 부류가 있다, 이런 문제를 인식하는 개발자와 인식하는 개발자이다.
구형 객체 모델은 위에 말한 문제를 유발할 뿐만 아니라 존재하는 객체 모델의 상위에 추가적인 특징을 구현하는데 방해되는 기본적인 문제를 유발하기도 한다.
PHP 5에서, 객체 모델의 기반은 객체 핸들로 다시 작성되었고, 여러분이 clone 키워드를 사용하여 객체의 클론을 명시하지 않는 한, 여러분은 여러분의 객체의 내부에서 절대 만들 지 않는다. PHP5에서 참조로 객체를 넘기는 것이 필요하지 않고 참조로 그것은 할당하지도 않는다.
알아두기:참조로 넘기는 것과 참조로 할당하는 것은 여전히 지원한다. 이경우에 여러분은 변수의 내용을(객체나 다른 타입) 정확히 바꾸기를 원한다.
새로운 객체 지향 특징
새로운 객체지향 특징은 이 절에서 상세히 설명하기에 너무 방대하다. 객체지향 언어 챕터에서 자세히 나와있다.주로 새로운 특징 목록은 밑에 나열해 놓았다.1. 메소드와 속성을 위한 public/private/protected 접근 수정자
일반적인 OO 접근 수정자의 사용은 메소드나 속성에 접근을 제어하게 해준다.
class MyClass { private $id; public function getId() { return $this->id; } } |
2. 유일(unified) 생성자 이름 __construct()
클래스의 이름이 되는 생성자 대신에, 이제는 __construct()로 선언 된다. 클래스 계층 안에서 클래서의 이동을 쉽게 만든다.
class MyClass { function __construct() { print "생성자 내부"; } } |
3. __destructor() 메소드를 정의함으로서, 객체 소멸자를 지원한다.
객체가 파괴될 때, 실행되던 소멸 함수를 정의가 허락한다.
<? class MyClass { function __destruct() { print "객체 파괴"; } } ?> |
4. 인터페이스
is-a 관계 보다 완전하게 하기 위한 클래스를 위한 능력을 준다. 클래스는 한 클래스로부터 상속받을 수 있으나 그것이 원하는 것처럼 많은 인터페이스처럼 구현하지는 않는다.
interface Display { function display(); } class Circle implements Display { function display() { print "Displaying circle"; } } |
5. instanceof 연산자
is-a 관계 확인을 위해 언어 수준의 지원. Php4의 is_a() 함수는 지금 비난받는다.
if ($obj instance of Circle) { print '$obj 은 Circle'; } |
6. final 메소드
final 메소드 키워드는 여러분이 상속하는 클래스가 그것을 오버로드 할수 없는 것을 표시하는 메소드이다.
class MyClass { final function getBaseClassName() { return __CLASS__; } } |
7. final 클래스
final로서 클래스를 선언하고, 그것은 상속할 수 없다. 다음과 같은 예제는 에러를 내보인다.
final class FinalClass { } class BogusClass extends FinalClass { } |
8. 명시 객체 복제(cloning)
객체를 복제하기 위해, 여러분들은 clone 키워드를 사용해야 한다. 여러분은 아마 복제 처하는 동안 호출될 __clone() 메소드를 선언했을 것이다.
class MyClass { function __clone() { print "Object is being cloned"; } } $obj = new MyClass(); // 이것은 인스턴스를 만들고 clone $obj; // 이것은 객체를 복제함 |
9. 클래스 상수
클래스 정의는 상수를 포함 할 수있고, 클래스를 이용하여 참조된다
class MyClass { const SUCCESS = "Success"; const FAILURE = "Failure"; } print MyClass::SUCCESS; |
10. 정적 멤버
클래스 정의는 이제 클래스를 통해 접근 가능한 정적 멤버(속성)를 포함 할 수있다. 정적 멤버의 일반적인 사용은 독자 패턴에서 이다.
class Singleton { static $instance = NULL; function getInstance() { if ($this->instance == NULL) { $this->instance = new Singleton(); } return $this->instance; } } |
11. 정적 메소드
여러분은 이제 비객체 문맥으로부터 호출되는 것 허락하게하는 정적으로 메소드를 정의할 수 있다. 정적 메소드는 그들이 모든 특정 객체에 묶이지 않고 $this 변수를 정의 하지 않는다.
<? class MyClass { static function helloWorld() { print "Hello, world"; } } MyClass::helloWorld(); ?> |
12. 추상 클래스
클래스는 인스턴스되는것으로부터 그것을 방해하기 위해 추상으로 선언될 수 있다. 그렇지만, 여러분들은 추상 클래스로부터 상속할 수 있다.
abstract class MyBaseClass { function display() { print "Default display routine being called"; } } |
13. 추상 메소드
메소드가 추상으로 선언되고, 그 때문에 상속하는 클래스에 그 정의를 양보한다. 추상메소드를 포함하는 클래스는 추상으로 선언된다.
abstract class MyBaseClass { abstract function display(); } |
14. 클래스 타입 힌트
함수 선언은 파라미터를 위해 클래스 타입 힌트를 포함하기도 한다. 만약 함수가 부적절한 클래스 타입으로 호출되면, 에러가 발생한다.
function expectsMyClass(MyClass $obj) { } |
15. 메소드에서 리턴되는 역참조(defrferencing)를 지원한다.
PHP 4, 여러분은 메소드로부터 반환되는 객체를 반참조할수 없었다. 여러분은 더미(dummy 변수에 첫 객체를 할당해야하고, 그것을 역참조 한다.
PHP 4: $dummy = $obj->method(); $dummy->method2(); PHP 5: $obj->method()->method2(); |
16. 반복자(Iterators)
php5는 php 클래스와 php 확장 클래스 둘 다 반복자 인터페이스을 구현하게 해준다. 여러분은 여러분이 foreach() 언어 생성자를 사용으로 클래스의 인스턴스를 반복할수 있을 인터페이스를 구현한다.
$obj = new MyIteratorImplementation(); foreach ($obj as $value) { print "$value"; } function __autoload($class_name) { include_once($class_name . "php"); } $obj = new MyClass1(); $obj2 = new MyClass2(); |
이상 새롭게 강화된 객체지원에 관해 나열했는데, 쉽게 애기하면, 자바만큼 객체를 지원한다. 대략 이런 애기입니다.
다른 새로운 언어 특징
1. 예외 핸들링PHP 5에서 잘 알고있는 try/throw/catch/ 구조적 예외 처리 개념을 추가했다. 여러분은 Exception 클래스에서 상속한 객체를 던지게(throw) 만들 수 있다. (자바 써 보신 분은 대단히 반가워 할 내용입니다. 이제 if문을 줄이자!)
class SQLException extends Exception { public $problem; function __construct($problem) { $this->problem = $problem; } } try { ... throw new SQLException("Couldn’t connect to database"); ... } catch (SQLException $e) { print "Caught an SQLException with problem $obj->problem"; } catch (Exception $e) { print "Caught unrecognized exception"; } |
현재, 이전버전과 호환성 목적을 위해, 대부분의 내부 함수는 예외로 던질 수 없다. 이미 존재하는 set_error_handler()과 비슷하게, 여러분은 스크립트 종료전에 처리할 수 없는 예외를 잡기위해 set_exception_handler()를 사용한다.
2. 참조를 이용한 foreach
php4에서 여러분은 그 배열을 통해 반복하거나 그 변수를 수정할수 없었다. Php5는 ‘&’(reperence) 표시로 foreach() 반복문을 표시함으로서 지원한다.
foreach ($array as &$value) { if ($value === "NULL") { $value = NULL; } } |
3. 참조 인자를 위한 디폴트 변수
php4에서 디폴트 변수는 변수로 넘겨지는 파라미터만 주어졌다. 참조 파라미터로 넘지겨지는 디폴트 변수를 주는 것은 지금 지원된다.
function my_func(&$arg = null) { if ($arg === NULL) { print '$arg is empty'; } } my_func(); |
3.일반적인 PHP 변화
XML과 웹 서비스
언어에서 다음과 같은 변화로는, php5에서 XML 업데이트는 아마도 중요하고 멋진것이다. Php5에서, 강화된 XML 기능은 다른 언어와 비교해서 동등하거나 따라잡았다.기반
php4에서 xml지원은 다양한 바탕 XML 라이브러리를 사용하여 구현되었다. SAX 지원은 오래된 Expat 라이브러리를 사용하여 구현 되었고, XSLT는 Sablotron 라이브러리를 사용하여 구현되었고, DOM은 그놈(GNOME) 프로젝트에 의해 보다 강력한 libxml2 라이브러리를 사용하여 구현되었다. 다양한 라이브러리의 사용은 그것이 xml 지원할때 php4를 뛰어나게 만들지 못했다. 관리가 어설펐다(poor). 새로운 XML 표준은 항상 지원되지 않았고, 성능은 그것을 가졌을 때 만큼 좋진 않았고, 다양한 XML 확장 사이에 상호운영성은 존재하지 않았다.
Php 5에서 모든 XML 확장은 suberb libxml2 XML toolkit(http://www.xmlsoft.org)을 사용하여 재작성되었다. 그것은 관리하기 좋고 XML 기술을 php로 가져오는 XML 표준의 효과적인 구현하는 매우 다양한 특징이 있다.
이상 언급한 확장(SAX, DOM 그리고 XSMT)는 지금 새로운 추가 확장 SimpleXML과 SOAP을 포함하는 libxml2를 사용한다.
SimpleXML
아마도 1-2년 전으로 뒤돌아 보면, SimpleXML이 XML 파일로 작업하는 php 개발자에게 혁명임이 명확하다. SimpleXML은 정말 바보(dummies)를 위한 XML로 불려졌다. DOM과 SAX로 처리하는 대신에, SimpleXML은 PHP 객체로서 XML 파일을 보여준다. 여러분은 쉽게 접근하는 요소(elements)와 속성(attributes)를 읽고 작성하거나 반복할 수 있다.다음 XML 파일을 보자
<clients> <client> <name>John Doe</name> <account_number>87234838</account_number> </client> <client> <name>Janet Smith</name> <account_number>72384329</account_number> </client> </clients> |
다음의 코드는 클라이언트 이름과 계좌번호를 출력한다.
$clients = simplexml_load_file('clients.xml'); foreach ($clients->client as $client) { print "$client->name has account number $client->account_number "; }SimpleXML이 얼마나 간결한지 명백하다.
SOAP
Php4의 공식적인 SOAP지원은 부족했었다. 대부분 일반적이로 사용되는 SOAP 구현은 PEAR이다 그러나 그것은 php에서 전체적으로 구현되었으나, C 확장과 마찬가지로 수행할 수 없었다. 다른 이용 가능한 C 확장은 안정적이지도 널리 채택되지도 않았다. 그러므로 php 5 배포판에 포함되지 않았다.Php5에서 SOAP 지원은 C 확장으로서 완벽하게 재작성되었고, 비록 그것이 늦은 단계에 완성되었지만, 그것은 표준의 대부분의 구현 때문에, 디폴트 배포판에 협력된다.
다음은 WSDL 파일에서 정의 된 SomeFuncion()을 호출한다
$client = new SoapClient("some.wsdl"); $client->SomeFunction($a, $b, $c);
New MySQLi(MySQL Improved) 확장
Php5를 위해, MySQL AB (http://www.mysql.com)은 MySQL 4.1과 그 이상버전에서, 새로운 기능의 포든 장점을 취하는 새로운 MySQL 확장을 작성했다. 구형 MySQL 확장에 반하여, 새로운 것은 여러분에게 함수형, 객체지향 인터페이스 둘다 사용할 수 있고, 그래서 여러분은 여러분이 좋아하는 것을 선택할 수 있다. 이 확장으로 지원되는 새로운 특징은 다음과 같다.미리 준비된 문장(Prepared statements), 가변 결속(variable binding), SSL과 압축된 커넥션, 트랜젝션 제어, 복제(replication)…
SQLite 확장
SQLite(http://www.sqlite.org)의 지원은 php 4.3.x에서 처음 도입되었다. 그것은 SQL 서버를 요구하지 않는 내장형 SQL 라이브러리이고 SQL 서버의 규모를 요구하지 않는 어플리케이션에 매우 적합하다. 또는 만약 여러분이 ISP에서 SQL 서버에 접근할 수 없는 경우에도 적합하다. SQLite라는 이름과는 다르게 그것은 매우 다양한 특징과 트랜젝션, sub-select, view 그리고 대규모 DB file을 지원한다. 그것은 php 5버전으로서 언급되었다.왜냐하면 그것은 php4의 뒤늦게 도입되었고, 객체지향 인터페이스와 반복자를 지원을 제공되면서 php 5의 장점을 취했기 때문이다.
Tidy 확장
Php 5는 유용한 Tidy (http://tidy.sf.net/) 라이브러리를 포함한다 그것은 php 개발자가 HTML 문서를 구문분석, 분류, 청소, 복구하도록 도와준다. Tidy 확장은 함수, 객체지향 인터페이스를 지원하고 그것의 API는 php 5 예외 메커니즘을 사용한다.펄 확장
기본 php5 패키지에서 포함되지는 않지만, 펄 확장은 여러분이 펄 스크립트를 호출하는 것을 가능하게 한다. 펄 객체를 사용하고 다른 펄 기능을 php에서 사용할 수 있다. 이런 새로운 확장은 PECL (PHP Extension Community Library) 저장소(repository) http://pecl.php.net/package/perl 에 있다. (php가 펄객체를 사용할 수 있다고 합니다)Php5에서 다른 새로운 것들
새로운 메모리 메니저젠드 엔진은 새로운 메모리 관리자를 가지고 있다. 두 주요 장점은 멀티 쓰레드 환경을 위한 지원과 각 요청 후에 할당된 메모리 블록은 보다 효율적이다.
윈도우 95 지원의 취소
윈도우 95 플랫폼상에 운영되는 php는 더 이상 지원되지 않는다. 왜냐하면 MS사가 윈도우 95를 공식적으로 지원하지 않을 거라고 했기 떄문에, php 개발 공동체도 그렇게 하기로 결정했다.
4. 요약
여러분은 php5에서 많은 발전이 인상적일것이다. 위에 언급했듯이, 이 챕터는 모든 발전을 다 다루지는 않는다. 다른 추가적인 발전은 많은 버그가 수정되었고 대단히 발전했다는 것이다.FreeMind - free mind mapping software
FreeMind is a premier free mind-mapping (http://en.wikipedia.org/wiki/Mind_map) software written in Java. The recent development has hopefully turned it into high productivity tool. We are proud that the operation and navigation of FreeMind is faster than that of MindManager because of one-click "fold / unfold" and "follow link" operations.
So you want to write a completely new metaphysics? Why don't you use FreeMind? You have a tool at hand that remarkably resembles the tray slips of Robert Pirsig, described in his sequel to Zen and the Art of Motorcycle Maintenance called Lila. Do you want to refactor your essays in a similar way you would refactor software? Or do you want to keep personal knowledge base, which is easy to manage? Why don't you try FreeMind? Do you want to prioritize, know where you are, where you've been and where you are heading, as Stephen Covey would advise you? Have you tried FreeMind to keep track of all the things that are needed for that?
Did FreeMind make you angry? Write a complaint (http://sourceforge.net/forum/forum.php?forum_id=320014).
http://freemind.sourceforge.net/wiki/index.php/Main_Page
스크립트 언어의 새로운 보석 루비 (Ruby)
속도가 빠르고 배우기 쉬운 인터프리팅 방식의 스크립트 언어 루비(Ruby). 그 힘과 인기가 IT의 본고장인 미 대륙을 넘어 점차 국내에까지 이르고 있다. 이런 루비의 상승세에 불을 댕긴 것은 바로 루비 온 레일스의 등장. 루비의 장점을 극대화한 이 오픈소스 프레임워크는 지난 2년의 시간 동안 자바, 닷넷 진영의 주류 프레임워크들을 긴장시키면서, 루비를 진정한 스크립트 언어의 보석으로 재탄생시키고 있다. 그렇다면 루비와 루비 온 레일스의 어떤 매력들이 이런 반향을 불러일으켰을까? 이번 스페셜 리포트에서 그 해답을 찾아보고, 아울러 웹2.0 시대에 어울릴만한 루비 온 레일스 활용법을 소개한다.
웹 프로그래밍 언어 php의 새로운 도전「php5」
php5가 새로이 릴리즈 되었다. 아니 정확히 말하면 5.0.0 beta부터 말하자면 이미 나온 지는 1년이 넘어간다. 그리고 이제 5.01이 릴리즈 되었다.
아직 대부분의 사이트에서는 5.0은 그리 많아 보이지 않는다. 솔직히 4.x 버전도 크게 문제되진 않는다. 하지만 5.0 버전이 새로이 나왔다는 것은 필자를 포함하여 여러 사람에게 꽤나 흥미 있는 이야기가 아닐 수 없다. 이 글은 php5의 새로운 기능과 그에 관련된 전반적인 내용에 대해 알고 싶어하는 사람을 위한 글이다.
옛것 그리고 새로운 것
php는 현재 가장 많이 사용되고 있는 웹 프로그래밍 언어중 하나이다. 엄청나게 강력한 기능을 제공함에도 불구하고 공짜로 구할 수 있으며 또한 여러 플랫폼의 지원까지 이루 말할 수 없는 수많은 장점을 지닌 언어라는 것은 따로 말할 필요가 없을 것이다.
그러나 이러한 강점들도 완벽한 것은 아니다. 필자 역시 개발 당시 “역시 이러한 것은 아직 안 되는군” 이라고 말하며 아쉬워했던 부분이 있었으니 말이다. 독자 역시 그러한 경험이 있었을 것이다.
그리고 php5가 나왔다. 다음에 무슨 말이 나올지 당연히 짐작되는 바와같이 php5는 php4의 수많은 문제점들이 수정되었다. 그리고 여러 가지 새로운 개념이 들어가게 되었다.
필자는 php5의 새로운 기능에 대해서 여러 가지로 보여 줄 것이다. 그러나 php5의 모든 기능을 다루진 못할 것이다. 좀 더 많은 아직 php5의 소식을 듣지 못한 개발자나 혹은 듣기만 했을 뿐 아직 다뤄보지 않은 개발자 그리고 관심을 갖는 모른 사람들은 지금 당장 php5를 설치해 보기 바란다. 그리고 좀더 새로운 php5의 세계에 발을 담가보기 바란다. 자 그럼 이제부터 php의 새로운 기능에 폭 빠져보도록 하자!
“php5는 객체 지향적인 웹 프로그래밍 언어이다.”
필자는 방금 제목에서부터 거짓말을 했다. php는 객체지향 프로그래밍 언어가 아니다. 하지만 php5는 그런 거짓말을 진실로 만들어 버릴지도 모른다는 생각이 든다. php는 객체 지향적인 언어가 아니다. 그러나 php5는 상당히 많은 부분의 객체 지향적인 부분을 지원하게 되었다. 그리고 이 점이 바로 php5의 가장 큰 수정 부분이고 또한 가장 매력적인 부분일 것이다.
php4도 객체 지향적인 부분을 이미 지원하고 있었다. 즉 class를 사용할 수 있는 기능이 있었고 또한 수많은 전 세계의 개발자들이 이를 사용하여 프로그래밍을 하였다. 물론 필자도 그 중 하나이다. 그러나 (아닌 사람도 있을 수 있겠지만) 꽤나 많은 사람들은 이 기능에 실망을 했으리라 믿는다. php4에서 지원하는 객체 지향적이란 의미는 상당히 제한적이며 수많은 기능이 빠진 절제된 객체 지향이라고 할 수 있었다.
php4의 객체 지향적인 의미를 이렇게까지 낮게 평가하는 이유가 무엇일까? 아주 단순하다. php5가 그만큼 많은 것이 바뀌었기 때문이다. php5는 객체에 대한 코드가 완전히 새로이 쓰여졌다. 그만큼 성능 향상이 올라간 것은 물론이고 개념 역시 완전히 바뀌어서 대부분의 객체지향적인 의미의 내용이 포함되게 되었다. 그럼 이제부터 php5의 객체지향적인 부분의 새로운 면을 살펴 보도록 하자.
생성자와 소멸자 (Constructors And Destructors)
생성자와 소멸자는 각각 클래스의 인스턴스가 처음 생성될 때 그리고 그 인스턴스가 소멸될 때 자동으로 불려지는 메소드이다. php5 이전의 class에서도 생성자가 존재 했었다. class의 이름과 같은 이름의 메소드가 바로 이전 버전의 생성자이다.
그러나 php5 에서는 유일한 이름의 생성자가 사용된다. 이전 버전에서는 class의 이름과 같은 이름의 함수가 class의 생성자로 사용되었다면 이제는 생성자의 이름이 __consturct()인 메소드가 생성자로 선언되게 되는 것이다. 또한 이전에는 존재하지 않았던 소멸자 역시 __destruct() 라는 이름으로 새로이 생겼다.
위는 php5의 새로운 생성자와 소멸자를 보여주는 소스이다. 위에서 볼 수 있듯이 생성자와 소멸자는 __construct()와 __destruct()라는 이름의 함수로 정의된다. 그리고 상속된 클래스의 인스턴스가 생성되고 소멸될 때에는 암묵적으로 부모 클래스의 생성자와 소멸자는 호출되지 않는다. 즉 부모 클래스의 생성자와 소멸자를 호출하고 싶으면 위의 소스에서 볼 수 있듯이 직접 부모 클래스의 생성자와 소멸자를 다음과 같이 호출해 주어야 한다.
parent::__construct();
parent::__destruct();
접근 제한자 (public/protected/private)
이전 버전에서는 클래스의 멤버 변수를 지정할 때에 var이라는 키워드가 사용되었다. 하위 호환을 위해서 php5에서도 var를 쓴다고 해서 작동하지 않는 것은 아니지만 기본적으로 php5에서는 멤버 변수를 선언할 때에는 public, protected, private를 사용하도록 되어 있다. C++이나 JAVA를 이용해 본 사용자라면 너무나도 익숙한 키워드일 것이다.
이를 사용함으로써 php 도 진정한 의미의 캡슐화(encapsulation)를 지원하게 된 것이다. 미리 말하자면 C++이나 JAVA를 사용해 본 유저라면 위의 키워드들의 의미를 쉽게 상상할 수 있을 것이고 그 상상이 틀리진 않을 것이다. 그러면 이제부터 의미를 간단히 살펴보면 다음과 같다.
public : 어디서나 접근 가능한 제한자
protected : 클래스의 내부에서 사용 가능하다. 그러나 상속될 수 있다.
private : 클래스 내부에서만 사용 가능하다.
이전의 var를 사용하여 클래스 변수를 선언했을 때에는 위에서 public을 사용하여 변수를 지정한 것과 같은 효과를 나타냈었다. 결국 어디서나 접근 가능한 변수는 진정한 의미의 캡슐화를 지원하지 못했던 것이다.
정적 멤버, 클래스 상수(static, const)
php5는 정적 멤버 변수와 클래스 상수를 선언할 수 있다 정적 멤버 변수는 static 키워드를 사용하여 선언이 가능하고 클래스 상수의 경우는 const 키워드를 사용하여 선언 가능하다. 한가지 알아둬야 할 것은 const로 선언된 클래스 상수의 경우에는 변수가 아니기 때문에 $가 붙지 않는다.
| ||||
| ||||
![]() |
위에서 볼 수 있듯이 정적 멤버변수로 선언된 변수는 어느 인스턴스에서 수정되어도 모든 인스턴스에 적용이 된다. 위에서 21째 줄에서 보이듯이 $obj 인스턴스에 의해 수정된 정적 멤버 변수는 $obj2의 다른 인스턴스에도 모두 영향을 미친다. 그리고 주의해야 할 점이 한 가지 있는데 20 번째 줄에서 알 수 있듯이 정적 변수는 인스턴스에 의해서 직접 억세스될 수 없다는 점이다. 이는 클래스 상수에서도 동일하게 적용된다.
즉 클래스 상수도 생성된 인스턴스에서 직접 접근이 불가능하다. 이는 다른 말로 바꾸면 클래스 안에서 $this 키워드를 이용해서도 접근이 불가능하다는 말과 같다. 즉 위에서 보인 것과 같이 self 키워드를 이용해서 접근해야만 할 것이다.
추상 클래스, 추상 메소드(abstract)
추상 클래스란 abstract로 선언된 클래스를 말한다. 그리고 추상 클래스는 인스턴스화 될 수 없다는 특징을 가지고 있다. 즉 추상 클래스로 만들어진 클래스는 오직 상속을 하는 용도로만 사용될 수 있다는 뜻이다.
추상 메소드로 선언된 메소드는 그 정의를 상속하는 메소드로 넘기게 된다. 추상 메소드로 선언된 메소드를 포함하고 있는 클래스는 또한 추상 클래스로 선언된다. 이때 알아두어야 할 사항은 추상 메소드가 protected 로 선언되었다면 상속하는 클래스는 반드시 그 메소드를 public 이나 protected 접근자로 재정의해야만 한다. 추상 클래스와 추상 메소드의 사용 방법은 다음과 같다.
| ||||
| ||||
![]() |
위의 소스에서 추상 클래스를 상속받는 SubClass나 SubClass2에서 추상 메소드로 선언된 getValue()를 재정의하지 않았다면 이 코드는 다음과 같은 에러를 출력했을 것이다.
Fatal error: Cannot instantiate abstract class SubClass2
인터페이스(interface)
php5는 인터페이스를 지원한다. 인터페이스는 위의 추상 클래스와 같이 다른 클래스들이 구현할 행동을 제시할 수 있다. 인터페이스는 생성해야 할 클래스가 어떤 메소드를 포함해야 할지를 보여준다. 인터페이스는 interface라는 키워드를 사용하여 선언된다. 이때 선언되는 방법은 class를 선언하는 것과 같은 방법으로 선언하면 된다. 이 인터페이스를 사용하는 방법은 implements를 이용하면 된다.
다음은 interface를 사용하는 예제이다.
| ||||
| ||||
![]() |
final 키워드
final로 선언된 클래스나 메소드는 더 이상 상속되거나 재정의 될 수 없다. 만약 final로 정의된 클래스나 메소드를 상속하거나 재정의 할 경우에는 Fatal Error를 낼 것이다. 이는 예제로 보여주진 않겠다.
명시적인 객체의 복사(clon)
php5에서는 객체를 복사하기 위한 방법으로 clon이라는 키워드가 제공된다. clon을 이용하면 핸들의 복사가 아닌 직접적으로 객체 자체가 복사가 된다. 이때 그 복사되는 클래스에 __clon() 이라는 메소드를 지정할 수 있는데 이 메소드는 clon을 이용하여 객체가 복사될 때 불리어지는 메소드이다.
| ||||
| ||||
![]() |
위는 clone의 예제를 보인 것이다. 위에서 알 수 있듯이 clone을 사용하면 복사되는 클래스의 __clone()이 자동으로 실행되게 된다.
위에서 알 수 있듯이 php5는 php4와는 객체 지향적이라는 관점에서 봤을 때 상당히 다르다는 것을 알 수 있다. 그리고 그 다르다의 의미는 확실히 긍정적인 의미의 발전임을 알 수 있을 것이다.
php5는 예전의 상당히 부족해 보이고 또 맛보기 정도로만 제공되었던 수준을 넘어서 비로소 자바와 같은 순수 객체지향적인 언어에서 제공하는 듯한 느낌의 객체 지향적 프로그래밍이 가능해지게 되었다. (예전과 비교해 보라) 이는 php5가 가장 많이 변한 점이라 할 수 있겠다.
예외 처리
php5 에서는 try, throw, catch를 이용한 구조적 예외처리를 지원한다. 예외처리를 사용하고자 하는 개발자는 Exception class를 상속한 객체를 throw할 수 있다. Exception class는 built-in 된 클래스로 이미 제공되는 것이니 그냥 상속해서 사용하면 된다.(Exception class는 아래를 참고하길 바란다.)
예외 처리는 php에서 그 동안 사용하던 if 문 등의 예외 방식에서 벗어나 좀더 명시적인 예외 처리 구문이 가능하게 될 것이다. 그러나 하위 호환등의 이유로 대부분의 내부 함수들은 예외로 던질 수 없다는 것도 알아두기 바란다. 예외처리에 대한 예는 아래를 참고하기 바란다.
| ||||
| ||||
![]() |
| ||||
| ||||
![]() |
참조에 관한 여러 가지...
php는 변수나 함수에 대한 참조가 가능하다. 그리고 php5에서는 이전 버전과는 다른 사항이 몇 가지 추가되었다. 우선 array에 관한 내용을 들 수 있다.
php 이전 버전에서는 foreach를 이용하여 array에 대한 반복문을 수행할 때 그 변수를 수정할 수 없었다. 그러나 php5 에서는 참조를 이용하여 foreach 문을 수행할 수 있게 바뀜으로써 그 변수를 바로 수정이 가능하도록 바뀌었다.
또한 과거에는 함수의 디폴트 변수를 지정할 때 참조를 이용한 디폴트 변수의 지정은 불가능했었다. 그러나 이제는 참조를 이용한 디폴트 변수의 지정이 가능하게 되었다. 다음의 코드를 보면 더욱 확실히 이해가 될 것이다.
| ||||
| ||||
![]() |
MySQLi(ext/mysqli)
mysql은 php와 더불어 가장 많이 사용되는 DB이다. mysql은 php와 궁합을 같이 한지 상당히 지났다. 그러나 php5와 mysql4.1의 소개 이후 이 둘 사이에는 문제가 생긴 것 같아 보였다. 그러나 mysql 4.1이후 버전을 지원하는 용도로 php5를 위한 mysqli 확장을 개발했다. 하지만 특별한 문제가 없다면 그냥 이전의 것을 사용하는 것도 별 문제가 없어 보인다.
그러나 php5에서 제공되는 mysqli 확장은 이전에 비해 엄청난 속도가 보장된다. 심지어 특정 조건에서 40배 가량의 속도 향상을 보일 수 있다고 하니 말이다. 그리고 이전의 확장보다 훨씬 안전한 보안을 책임진다.
그렇다면 mysqli 확장 기능은 어떻게 사용하는 것일까? 이전의 확장기능과 비슷한 방식의 사용법이 존재하지만 여기서는 객체 지향적인 접근을 시도해 보도록 하겠다.
| ||||
| ||||
![]() |
위는 mysqli 확장을 prepared statement 와 함께 사용한 예이다. 이전의 사용 방법과는 좀 다르다는 것을 알 수 있을 것이다. 상당히 객체 지향적인 방법을 사용하고 있으며(이렇게 사용하지 않아도 된다.) Query 문이 완성되어 있지 않다는 것도 알게 될 것이다. 쿼리문은 prepare를 이용하여 미리 준비해 놓고 bind_param를 이용하여 특정 변수를 쿼리에 string으로 추가한다는 내용이다.
php5의 도전 그리고 php5로의 도전
php5 는 기존의 유명세에 힘입어 새로운 패러다임을 향해 나아가고 있다. 위에서 설명한 것만이 php5에 추가된 모든 기능들은 아니다. 위에서 설명한 것 이외에도 SQLite의 지원이나 펄 확장(PECL:PHP Extension Community Library) 그리고 새로운 Zend 엔진 등등 php5는 많은 추가적인 기능들이 들어 있다. 게다가 php는 이전에 비해 훨씬 좋아지고 있으며 이 글을 쓰는 동안에도 php 개발팀은 또 다른 버그와 그리고 새로운 기능들과 싸우고 있을 것이다.
php5는 아직 php4를 완벽히 대체했다고는 할 수 없다. 왜냐하면 아직도 많은 곳에서 php4를 이용하여 웹 서비스를 하고 있기 때문이다. 하지만 대세는 곧 바뀌게 될 것이다. 이전의 것을 아는 것은 상당히 중요하다. php 역시 이전 버전의 내용을 아는 것은 앞으로의 진전에도 큰 도움이 된다. 그러나 새로운 것을 알아가는 것 역시 상당히 중요하다. 독자는 php5의 위에서 설명해 놓은 기능들 뿐만 아니라 그 외에 다른 기능들을 찾아보길 바란다. @
* 이 기사는 ZDNet Korea의 자매지인 마이크로소프트웨어에 게재된 내용입니다.
정준영 (마이크로소프트웨어)
2004/12/20
원문 : http://www.zdnet.co.kr/techupdate/lecture/etc/0,39024989,39132314,00.htm