RSS구독하기:SUBSCRIBE TO RSS FEED
즐겨찾기추가:ADD FAVORITE
글쓰기:POST
관리자:ADMINISTRATOR
'2006/11'에 해당되는 글 9
서브쿼리란 무엇인가?

서브쿼리는, 핵심적으로, 다른 SELECT 구문의 부분으로서 자주 사용 되는 SELECT 구문이다. 물론 INSERT, UPDATE, DELETE나 다른 구문과 함께 사용 될 수 있다. 서브쿼리는 다양한 최적화를 위하는 것과 마찬가지로, 매우 복잡한 검색이나 복잡한 보고서를 저장하기 위하여 사용된다. 우리는 GROUP BY 절의 모든 개수 핵심적으로 갖고, 여러분의 결과를 좀더 세밀히 구별하기 위해 SELECT의 FROM 절로 사용할 수 있다.

시작하기

mysql에서 서브쿼리를 사용하기 위해서, 여러분은 MySQL 4.1의 버전이 필요할 것이다. 다만 4.1 alpha 버전만 제외하고, 어떤 버전이든 상관없다(4.1 이상으로). 여러분은 최신 버전을 원할 것이다. 만약 없다면, 이 기사를 읽어보고, 가서 mysql 공식 사이트에 가서 다운받자.

이 기사에 있는, 모든 여제는 world database을 이용할 것이다. 그것은 world.sql.gz으로 mysql 웹 사이트에서 사용할 수 있다.
http://www.mysql.com/get/Downloads/Manual/world.sql.gz/from/pick/

초 간단 예제

음. 처음 볼 것은 가능한한 가장 간결한 서브쿼리이다

SELECT (SELECT 1);

 +------------+
 | (SELECT 1)  |
 +------------+
 |          1     |
 +------------+

이것은 정말 간단하다.

SELECT (SELECT (SELECT 1));

 +---------------------+
 | (SELECT (SELECT 1))  |
 +---------------------+
 |                   1           |
 +---------------------+

어떤가? 그러나 별로 쓸모있진 않다.

보다 쓸모있는 예제
지금부터, 보다 효율적인 방법(JOINs같은)으로 될 수 있는 것들은 무시하자, 그리고 약간의 가능한 서브쿼리과 그 결과를 주목하자. 처음으로, 우리는 다른 방법의 개수가 되게 할수 있는 매우 간결한 쿼리를 볼 것이다.

SELECT name, headofstate
 FROM Country
 WHERE code=(SELECT "SWE");

 +--------+-----------------+
 | name   | headofstate          |
 +--------+-----------------+
 | Sweden | Carl XVI Gustaf     |
 +--------+-----------------+

그래, 나는 인정할 것이다. 그것은 별로 쓸모있지 않다. 가지말고 나와 함께 놀아죠.(Stay with me here!). 만약 여러분이 비슷한 쿼리를 시도한다면, 좀더 유용하게 시간을 써보자. 가장 인구가 많은 도시의 정보를 알아보자.
(population은 인구, head of state는 시장/대통령이라는 뜻)
SELECT name, headofstate, population
 FROM Country
 WHERE population=(SELECT MAX(population) FROM Country);

 +-------+-------------+------------+
 | name  | headofstate | population     |
 +-------+-------------+------------+
 | China | Jiang Zemin | 1277558000    |
 +-------+-------------+------------+

LIMIT를 왜 않쓰냐고?, 그러나 LIMIT는 MySQL-한정적이다, 그래서 다른 데이터베이스에 포터블한 해결책이 아니다. 그리고 항상 아주 정확한 결과가 되지 못한다. (ORDER BY와 LIMIT으로 하면, 만약 정확히 같고, 가장 인구가 높은 두 국가 중 하나만 선택(selete)된다. 위의 서브쿼리는 대부분의 데이터베이스에 호환성이 높다. 보다 복잡한 걸 해보자, 공식언어로 국가에 관한 정보이다.

테이블을 속여보자
FROM 절에서, 서브쿼리는 새로운 서브쿼리 지원하는 가장 유용한 특징중 하나이다. 특히, 그것은 쿼리의 FROM 부분에서 입력을 허락하게 되는 간결한 쿼리문이다. MySQL이 쿼리문을 처리할 때, 그것은 서브쿼리의 결과는 실제로는 다른 테이블이다. 처음에는 간결한 예제로 보자, 내 말을 보여주겠다.

SELECT foo
 FROM (SELECT 1 AS foo) AS tbl;

 +-----+
 | foo   |
 +-----+
 |   1   |
 +-----+

여러분들은 끝 부분을 주목할 것이다. 'FROM (SELECT 1 AS foo) AS tbl' 은 테이블의 목록을 찾기위한 입력이다. 여러분은 또한 내가 AS tbl로 서브쿼리(메인 쿼리 부분) 를 대응하는 것을 주목할 것이다. FROM 절에서, 모든 서브쿼리는 어떤 것이 모든 것이 대응할 것이다. 한편 여러분은 에러를 볼것이다. 모든 테이블은 이름이 있어야 하고 서브쿼리도 예외는 아니다.

만약 우리가 보다 어려운 (그러나 유용한) 예제로 옮긴다면, 우리는 서브쿼리의 힘을 보기시작할 것이다. 모든 국가에서 가장 많은 공식언어가 몇개인지 찾아보자.

/* 1 */
/* AS는 MAX()함수로 나온 값의 임시 필드명을 지정하는 것입니다. */
 SELECT MAX(tbl.nr) AS nr
 FROM
   (
     /* 2 */
     SELECT countrycode, COUNT(*) AS nr
     FROM CountryLanguage
     WHERE isofficial='T'
     GROUP BY countrycode
   ) AS tbl;

 +---------+
 | MAX(nr)   |
 +---------+
 |       4   |
 +---------+

다시, MySQL 전문가인 여러분들 중 몇몇은 ORDER BY 와 LIMIT로 찾았을 같은 결과를 주목할 지도 모른다. 다시, 필자는 서브쿼리 부분을 별명(alias)을 불러야 한다. 그리고 필자는 AS tbl을 선택했다. 서브쿼리 없이 쉽게 할 수 없는 것을 해보자: 공식언어의 최대 개수로 그의 국가에 대한 정보를 얻어보자.


/* 1 */
 SELECT name, population, headofstate, top.nr
 FROM
   Country,
   (
     /* 2 공식언어(official languages)의 개수에 기반한 국가 코드(country codes)를 비교한다.*/
     SELECT countrycode, COUNT(*) AS nr
     FROM CountryLanguage
     WHERE isofficial='T'
     GROUP BY countrycode
     HAVING nr=(
       /* 3 SELECT #4 번으로부터 nr_official_language의 최대크기를 알아낸다. */
       SELECT MAX(summary.nr_official_languages)
       FROM
         (
           /* 4 모든 국가와 각각의 공식언어(official languages)의 개수를 찾는다. */
           SELECT countrycode, COUNT(*) AS nr_official_languages
           /* CountryLanguage 테이블에서 */
           FROM CountryLanguage
           /* 공식언어가 있는 경우에만 */
           WHERE isofficial='T'
           /* countrycode 순서로 */
           GROUP BY countrycode
          /* 원래의 테이블 이름 AS 별칭으로 임시로 쓸 이름 */
         ) AS summary
       )
   ) as top
 WHERE Country.code=top.countrycode

 +--------------+------------+-------------+----+
 | name         | population | headofstate | nr         |
 +--------------+------------+-------------+----+
 | Switzerland  |    7160400 | Adolf Ogi   |  4          |
 | South Africa |   40377000 | Thabo Mbeki |  4       |
 +--------------+------------+-------------+----+

이 쿼리문은 간결하지 않다. 그것은 복잡한 결과를 얻기 위해 네개의 SELECT 구문으로 다른 부분으로 감쌌다. 필자는 /* 1 */ 이런 형식의 주석을 추가했다. 그래서 우리는 논리적으로 쿼리문은 분할할수 있다. 만약 우리는 숫자로 분리된 각 쿼리문을 보고, 역순으로, 이해하면 가장 쉽다.
(복잡한 서브쿼리문을 볼떄는 안에서 바깥으로 보면 쉽다는 얘기입니다)

4. 이 SELECT 문은 모든 국가와 각각의 공식언어(official languages)의 개수를 찾는다.
3. 이 SELECT 문은 SELECT #4 번으로부터 nr_official_language의 최대크기를 알아낸다. 동시에, 최대크기를 위해 countrycode 컬럼을 얻는 방법은 SQL-표준이 아니다.  
2. 이 SELECT에서, 우리는 공식언어(official languages)의 개수에 기반한 국가 코드(country codes)를 비교한다.
1. 마지막으로 우리는 매칭한(matching) 국가에 관해 국가정보(country information)를 찾기 위한 국가(country) 테이블에 기대어 JOIN을 사용할 수 있다.

필자는 여러분은 무언가를 배웠기를 희망한다. 그리고 필자는 서브쿼리에 관해 여러분 스스로 읽기를 바란다, 이 시리즈의 다음 기사는 Correlation, ANY, EXISTS를 논의할 것이다.

역자 한마디..
오류가 많으니 읽으시는 분들이 좀 주의해서 읽어 주시면 감사하겠습니다.

http://www.phpschool.com/ 에서 활동하고 계신 김영진님의 글입니다.
2006/11/29 12:34 2006/11/29 12:34
이 글에는 트랙백을 보낼 수 없습니다

아이덴티티(Identity : 2003)
다중인격(정신분열)을 소재로 하여, <와일드 씽>에서 선보였던 반전에 반전을 거듭하는 지능적인 범죄 스릴러물. 스토리가 대단히 매력적이다. 맨골드 감독 영화의 대부분과 <스크림> 시리즈를 제작했던 캐시 콘래드가 제작을 담당한 이 영화에는, 존 쿠색 외에 <나크(Narc)>에서 열연한 레이 리오타, <나인 야드>의 아만다 피트, <요람을 흔드는 손>의 레베카 디모나이 등이 공연하고 있다. 미국 개봉에선 2,733개 극장으로부터 1,623만불의 수입을 올리며 1위에 올랐다.
폭풍우가 몰아치던 어느날. 리무진 운전사(쿠색), 80년대 TV 스타(디모나이), 살인자(제이크 비지)를 수송중이던 경찰(리오타), 콜걸(피트) 등 서로 일면식이 없는 10명의 이방인들이 외딴 사막의 호텔로 모여든다. 시간이 지나면서 이들은 한 명씩 살해되고, 남아있는 이들은 서로를 의심하며 누가 살인범인지를 찾으려 애쓴다.
미국 개봉시 호러영화치고는 평론가들의 반응은 상당히 우수했다. 달라스 모닝 뉴스의 필립 원치는 "효과적이고, 매우 정교하게 만들어진 스릴러물."이라고 치켜세웠고, 시카고 선타임즈의 로저 이버트는 "내가 본 많은 영화들은 처음 3분의 2까지는 흥미진진하다가 마지막 3분의 1은 전형적인 결말을 나타내는 것들이었다. '아이덴티티'는 진기하게도, 처음 3분의 2는 전형적인 방식으로 진행되다가 마지막에 가서는 모든 것을 뒤집어 관객들이 지금까지 있었던 모든 일들을 다시 생각하게 만든다. 이 얼마나 단순하면서도 독창적인 방법인가?"라고 엄지손가락을 들어주었으며, LA 타임즈의 케빈 토마스는 "제임스 맨골드의 빈틈없는 연출력과 마이클 쿠니의 깊이있는 대본은 이 영화가 이탈하는 것을 방지한다."고 고개를 끄덕였다.
출연 :  존 쿠삭John Cusack(에드), 레이 리요타Ray Liotta(로디스),
       아만다 피트Amanda Peet(파리스) 

   







디 아더스 (The Others, 2001)

1950년대 영국의 외딴 대저택을 배경으로 펼쳐지는 심령 스릴러 영화로, <식스 센스>처럼 라스트의 반전에 핵심을 둔 작품. 니콜 키드만이 주연하고 그녀와 헤어진 전남편 톰 크루즈가 기획에 참여하여 두 부부가 마지막으로 함께 한 영화라는 점에서 영화 외적으로 화제가 되기도 했다. (크루즈와 키드만은 이 영화의 언론 시사회장에서 동석했으나 서로 피하는 눈치가 역력했다고 외신은 전한다.) 스페인 감독 알레한드로 아메나바르에겐 첫 영어권 영화로서, 그는 연출 뿐만 아니라 음악과 각본까지 담당했다. 니콜 키드먼과 아역 배우들의 연기가 훌륭하며, 미술과 무대 세트, 음향 효과 등 많은 부분이 수준급이다. 2001 제58회 베니스 국제영화제 경쟁부문 '베네치아 58' 초청, 2001 유럽 영화제 작품상 노미네이트. 원제는 '타인' 즉 '나 이외의 집안을 둘러싼 보이지 않는 존재'를 뜻하여 관객들로 하여금 이것을 추리하는 묘미를 갖게 한다.
2차대전이 종전된 직후, 1년전 남편이 전쟁에 참전한 뒤 아무런 소식이 없는 상태에서 그레이스(니콜 키드먼)는 그녀의 아픈 두 아이를 데리고 영국 남부해안의 아름다운 빅토리아풍 저택으로 이사한다. 햇빛 알레르기가 있는 그레이스의 아이들은 하루종일 어두운 집안에서 살아야 하고, 어쩔 수 없이 이들 가족은 외부와 단절된 시간을 보낸다. 하지만 그레이스의 딸이 유령과 대화하는 등, 그레이스 가족은 곧 이 집안에 자신들 외에 또 다른 존재가 있음을 느끼게 된다. 이들은 도대체 누구이고 그레이스 가족에게 무엇을 원하는가? 모든 것이 밝혀지는 라스트 10분. 충격적인 반전이 기다리고 있는데.

출연 :  니콜 키드먼Nicole Kidman(그레이스 스튜어트) , 피오눌라 플라나건 Fionnula Flanagan, 크리스토퍼 에클리스턴 Christopher Eccleston



   




메멘토 (Memento, 2000)

전직이 보험 수사관이었던 레너드에게 기억이란 없다. 자신의 아내가 강간당하고 살해되던 날의 충격으로 기억을 10분 이상 지속시키지 못하는 단기 기억상실증 환자가 되었던 것이다. 때문에 그가 마지막으로 기억하고 있는 것은 자신의 이름이 레너드 셸비 라는 것과 아내가 강간당하고 살해당했다는 것, 그리고 범인은 존 G 라는 것이 전부이다. 중요한 단서까지도 쉽게 잊고 마는 레너드는 자신의 가정을 파탄 낸 범인을 찾기 위한 방법으로 메모와 문신을 사용하게 된다. 즉, 묵고 있는 호텔, 갔던 장소, 만나는 사람과 그에 대한 정보를 폴라로이드 사진으로 남기고, 항상 메모를 해두며, 심지어 자신의 몸에 문신을 하며 기억을 더듬는 것이다.
하지만 시간이 지남에 따라 자신의 기억마저 변조되고 있음을 스스로도 알지 못한다. 그의 곁에는 '나탈리'라는 웨이트리스와 '테디'라는 직업을 알 수 없는 남자가 주위를 맴돌고 있다. 그들은 레너드를 잘 알고 있는 듯 하지만 레너드에게 그들은 언제나 새로운 인물이다.(그도 그럴 것이 레너드는 그들을 만났다는 것을 늘 잊고 만다.) 마약 조직의 오해를 받으면서까지 정보를 제공하는 나탈리는 테디가 범인임을 암시하는 단서를 보여주고, 테디는 절대 나탈리의 말을 믿지 말라는 조언을 한다. 과연 누구의 말이 진실인가?

출연 :  가이 피어스(레나드 쉘비), 캐리 앤 모스(나탈리), 조 판토리아노(테디 갬멜)


   



엑스텐션 (Switchblade Romance, Haute Tension, 2003)

고립된 대지 위에 선 외딴집. 메리가 친구 알렉스의 집을 방문한다. 도착 첫날 밤, 피에 굶주려 거리를 배회하던 의문의 남자가 집에 찾아오고 알렉스의 가족은 모두 살해된다. 알렉스를 데리고 어디론가 떠나는 살인마. 메리는 알렉스를 구하기 위해 그를 뒤따른다. 처절한 싸움 끝에 그를 죽이고, 알렉스를 구한 메리. 하지만, 알렉스는 미친 듯이 칼을 휘두르며 그녀를 거부한다.
"저리가, 니가 우리 가족을 죽였어!" 도대체, 누가 살인자인가? 두 소녀와 한 남자, 세 사람의 1:1 지능살인, 그 비밀은 무엇일까?



    







쏘우 (Saw, 2004)

어느 캄캄한 지하실. 자신들의 발목에 쇠줄이 묶인 채 마주하게 된 ‘아담’(리 웨넬)과 닥터 ‘고든’(캐리 엘위즈). 둘은 자신들이 왜 잡혀왔는지, 서로가 누군지조차 모르고 있다. 어떻게든 빠져나가려고 갖은 애를 써보지만 소용이 없다. 주머니 속에는 8시간 내에 고든이 아담을 죽이지 않으면 둘은 물론 고든의 부인과 딸까지 죽이겠다는 범인의 음성이 담긴 테이프가 들어 있을 뿐.
한편, 연쇄살인을 추적하던 ‘탭’형사(대니 글로버)는 닥터 ‘고든’을 범인으로 지목하고 그 뒤를 쫓는다. 범인의 윤곽은 좀처럼 드러나지 않고, 예정된 시간은 점점 가까워져 오는데..


    







식스 센스 (The Sixth Sense, 1999)
아동 심리학자 말콤 크로우(Malcolm Crowe: 브루스 윌리스 분)가 뛰어난 의사라는 칭송과 함께 상을 받고 부인 안나(올리비아 윌리암스 분)와 함께 자축을 하는 밤, 오래전에 치료를 받았던 환자가 미친 듯이 찾아와 말콤에게 총을 쏜 후 자살한다. 다음 해 가을, 닥터 크로우는 여덟살 난 콜 시어(Cole Sear: 할리 조엘 오스멘트 분)의 정신상담을 맡게 된다. 자신의 무성의한 치료에 앙심을 품고 총구를 겨눈 뒤 자살한 환자의 영혼을 달래주기 위하여 닥터 크로우는 정성을 다하여 콜의 상담 치료를 맡는다.
콜은 현재 정신적인 충격에 빠져있다. 그의 눈에 죽은 자들의 모습이 나타나기 때문이다. 문제는 죽은 자들이 나타났다가 그냥 사라지는 것이 아니라 자신들의 억울한 죽음에 대해 콜에게 뭔가를 호소한다는 점이다. 자살했던 환자의 증세와 비슷함을 감지한 말콤는 자신의 죄의식을 지워버리고자 소년에게 충실한 정성을 보이며 또 다른 비극을 막기 위하여 노력한다. 소년은 늘 우울하고 버림받은 듯한 모습으로 군인장난감을 가지고 놀면서 격한 그림과 글을 쓰고, 때로는 환영을 본다는가 묘한 소리를 들으므로 항상 위압당하는 곤혹을 표한다.
부모의 이혼으로 충격을 받은 것으로 말콤은 이해하려 하지만, 소년은 깊히 간직된 진실한 두려움의 원인을 말콤은 물론 엄마(토니 콜렛 분)에게도 밝히기를 꺼려한다. 치료과정이 심도를 더해 가면서 소년은 말콤을 신뢰하게 되고, 자신이 또 다른 감각을 지녔음을 그에게 알린다. 소년은 죽은 사람들을 볼 수 있을 뿐만 아니라 그들과 이야기를 할 수 있는 지각을 가진 것이다. 죽은 소녀가 나타나 토하면서 메시지를 전하고, 죽은 여인은 남편을 향해 소리지르는 듯이 콜에게 자신의 억울함을 털어놓는가 하면, 100년전 교수형에 처해졌던 가족의 처참한 모습이 소년에게 보이는 것이다. 말콤은 믿을 수 없는 사실에 의혹을 품으면서도 모든 수단을 이용하여 소년의 고난스러운 세계로 함께 파고든다.
한편 말콤은 개인적인 사생활의 위기도 맞는다. 그의 아내는 결혼식때 찍은 비디오만을 계속 보면서 과거 남편과의 즐거웠던 시절만을 그리며 생활할 뿐, 말콤과는 더 이상 대화를 하지 않고, 젊은 남자를 만나면서 외도를 범하는데.


   







유주얼 서스펙트 (The Usual Suspects, 1995)
산페드로 부두(San Pedro, California), 27명이 사망하고 9,100만달러가 증발하는 유혈극이 벌어진다. 수사관 데이브 쿠얀(Dave Koian: 채즈 팰민터리 분)은 유일한 생존자인 범죄자 버벌로부터 5인의 6주 동안의 범죄 행각에 대한 진술을 들으며 영화는 교차 진행된다.
6주전, 범죄 전문가 5명이 총기트럭 탈취 혐의에 대한 용의자들로 경찰에 불려온다. 그들은 키튼(Keaton: 가브리엘 바이른 분), 타드 하크, 절름발이 버벌(Verbal: 케빈 스페이시 분), 맥마이너스(McManus: 스테판 볼드윈 분), 펜스터(Fenster: 베니치오 델 토로 분)로서, 유치장에서 하루밤을 보내면서 의기투합, 범죄를 모의한다. '뉴욕 제일 택시회사'가 부패한 뉴욕 경찰들과 결탁, 밀수품과 마약을 전국에 운송해주고 있는데, 에메랄드 밀수업자 남미인을 태운 택시를 강탈한 뒤 이를 언론에 유출하여 부패한 경찰들만 체포되고 만다. 5명은 물건을 장물아비인 레드풋 일당과 거래하는데, 그들에게서 정보를 얻어 보석상 사울을 지하 주차장에서 털게 되는데, 이 과정에서 버벌이 사울을 죽이고 만다. 이때 이들은 턴 가방에는 돈과 보석이 아닌 마약이 있자 화가 나 레드풋 일당을 찾아간다. 레드풋은 자신도 어떤 다른 사람의 지시를 받았다고 하는 것인데.
한편 이들 앞에 코바야시(Kobayashi: 피트 포스틀스웨이트 분)라가 자가 나타나 자신의 보스가 전설과도 같은 무시무시한 지하 범죄 조직의 두목 카이저 소제(Keyser)라며 그가 키튼 일행을 고용하겠다는 제안을 해 온다. 그는 키튼 일행 5명의 범죄 행로를 모두 알고 이를 미끼로 삼고자하는데, 이에 분노한 펜스터가 소제에게 살해된다. 보복을 위해 4명은 코바야시를 미행하여 소제라는 자가 있는 빌딩으로 잠입한다. 하지만 키튼은 이미 카이저 소제가 여류변호사인 자신의 애인 이디 피너란(Edie Finneran: 수지 에이미스 분)에게 일을 의뢰하여 인질로 삼고 있었고 결국 카이저 소제가 원하는 대로 일을 하게 된다. 그것은 산페드로 부두에서 9천만불 상당의 마약을 거래하게 될 아르헨티나 조직을 치고 선적된 마약을 빼앗아오는 것이었다. 키튼 일행이 마약 조직을 덮쳤을 땐 마약은 없었고 일행 타드 하크와 맥 마이너 마저 죽고 만다. 그리고 마침내 키튼 앞에 카이저가 나타나 죽음을 당했다는 것이 버벌의 진술이었는데..


   

2006/11/15 20:40 2006/11/15 20:40
이 글에는 트랙백을 보낼 수 없습니다

SSH 기타 세팅 및 scp, sftp 사용


SSH 기타 세팅 및 scp, sftp 사용에대해 알아보자

특정 사용자 및 그룹의 로그인 제한

]# man sshd
AllowGroups
            This keyword can be followed by a list of group name patterns, separated by spaces.  
            If specified, login is allowed only for users whose primary group or supplementary group
            list matches one of the patterns.  `*' and `'?  can be used as wildcards in the patterns.  
            Only group names are valid; a numerical group ID is not recognized.  
             By default, login is allowed for all groups.
            (지정된 그룹에 포함된 사용자만이 SSH 로그인을 할 수 있다.
             그룹명은 공백으로 구분하여 와일드 문자(*, ?)를 사용 할 수 있다.)

AllowUsers
            This keyword can be followed by a list of user name patterns, separated by spaces.  If specified,
            login is allowed only for users names that match one of the patterns.  `*' and `'?  can be
            used as wildcards in the patterns.  Only user names are valid; a numerical user ID is not
            recognized.  By default, login is allowed for all users.  If the pattern takes the form USER@HOST
            then USER and HOST are separately checked, restricting logins to particular users from particular
            hosts. (지정된 사용자만이 SSH 로그인을 할 수있다.. 사용법은 AllowGroups과 같다.)

DenyGroups
            This keyword can be followed by a list of group name patterns, separated by spaces.  Login is
            disallowed for users whose primary group or supplementary group list matches one of the
            patterns. `*' and `'?  can be used as wildcards in the patterns.  Only group names are valid; a
            numerical group ID is not recognized. By default, login is allowed for all groups.
            (지정된 그룹에 대한 로그인을 거부한다.)

DenyUsers
            This keyword can be followed by a list of user name patterns, separated by spaces.  Login is
            disallowed for user names that match one of the patterns.  `*' and `'?  can be used as wildcards
            in the patterns.  Only user names are valid; a numerical user ID is not recognized.  By default,
            login is allowed for all users. If the pattern takes the form USER@HOST then USER and HOST are
            separately checked, restricting logins to particular users from particular hosts.
            (지정된 사용자에 대한 로그인을 거부한다.)

6. 원격지 호스트로의 로그인


[in4mania@ilinuxbay in4mania]$ ssh in4mania@192.168.1.154
in4mania@192.168.1.154's password:
Last login: Sun Sep  7 18:36:21 2003 from ns.ilinuxbay.net

7. Allowusers, Denyusers 옵션을 적용한 원격지 로그인 실습
/etc/ssh/sshd_config 파일에 Allowusers와 Denyusers 두개의 옵션을 이용해 각각의 유저를 추가 한 후
원격지에서 ssh 서버에 접근이 가능한지 테스트 해본다.

8. scp 사용법
scp는 자신의 컴퓨터에서 원격의 컴퓨터로 또는 원격의 컴퓨터에서 자신의 컴퓨터로 간단하게
파일을 전송할 수 있는 프로그램이다.
다음은 현재 디렉토리에 있는 sshd.txt 라는 파일을 IP가 192.168.1.154 인 컴퓨터에 root 라는 계정으로
접속하여 /usr/local/src/ 디렉토리 밑에 복사해 넣는 명령이다.


[root@in4nux root]# scp ./sshd.txt root@192.168.1.154:/usr/local/src/

다음은 IP가 192.168.1.154 인 컴퓨터에 root 라는 계정으로 접속하여 /usr/local/src/ 디렉토리 밑에 있는
sshd.txt 라는 이름의 파일을 자신의 컴퓨터로 현재 위치한 디렉토리에 복사하는 명령이다.


[root@in4nux root]# scp root@192.168.1.154:/usr/local/src/sshd.txt ./

9. sftp 사용법

sftp는 대화식의 파일전송 프로그램으로 ftp와 비슷하며, 모든 작동은 암호화된 ssh 전송상에서 실행이 된다.


[root@in4nux ssh]# sftp in4mania@192.168.1.152
Connecting to 192.168.1.152...
in4mania@192.168.1.152's password:
sftp>

10. 윈도우용 ssh
http://www.ssh.com => download => Evaluation Versions => SSH Secure Shell for Workstations

2006/11/14 13:48 2006/11/14 13:48
이 글에는 트랙백을 보낼 수 없습니다


많이 빨라졌습니다.
2006/11/13 18:49 2006/11/13 18:49
이 글에는 트랙백을 보낼 수 없습니다

-

이 테스트는 미국의 ULLA ZANG 이라는 한국계 미국인에 의해 개발된 것으로, 색깔과 형태등은 여러해에 걸쳐 전 세계인을 대상으로 테스트 되었습니다. 이 그림들은 9가지의 기본적인 성격 유형을 나타냅니다.

그럼 지금부터 위의 그림에서 제일 눈길이 가는 그림을 하나 고르세요.


1.내성적 (Introspective) 민감 (Sensitive) 사려가 깊은 (Harmonious)
당신은 당신 자신과 당신의 환경에 대해 대부분의 다른 사람들에 비해 보다 많이 고민하는 편입니다. 당신은 피상적인 것을 싫어해서 다른 사람과 이런 저런 잡담을 하기보다는 차라리 혼자 있기를 좋아합니다. 친구를 매우 주의 깊게 사귀는데 이로 인해 당신은 내적 평화와 안정감을 얻습니다. 그렇지만 당신은 아무리 오래 혼자 있더라도 조금도 지루함을 느끼지는 않는 성격입니다.

-----------------------------------------------------------------------
2.독립 (Independent) 얽매이지 않음 (Unconventional) 속박을 싫어함( Unfettered)
당신은 당신 스스로 자신의 인생행로를 선택할 수 있게끔 자유롭고 얽매이지 않길 바랍니다. 당신은 직장생활 또는 여가활동 심지어는 공부까지도 예술가적인 성향을 나타냅니다. 당신이 가지고 있는 자유에 대한 열망으로 인해 당신은 때때로 주위 사람들이 바라는 것과 정반대의 행동을 하기도 합니다. 당신의 라이프 스타일은 매우 개성적이기 때문에 유행을 무조건 모방하진 않습니다. 반면, 당신은 비록 대세를 거스르는 일이 있더라도 당신 스스로의 생각과 신념에 의해 행동하길 바랍니다.

-----------------------------------------------------------------------
3.역동적 (Dynamic) 활동적 (Active) 외향적 (Extroverted)
당신은 재미를 느끼고 다양한 경험을 하기 위해서는 다소의 위험을 감수하고서라도 그 일에 빠져들기를 서슴지 않는 사람입니다. 일상적인 것은 당신에게 무미건조한 것에 지나지 않습니다. 당신은 무슨 일이든지 주도적으로 하길 좋아하고 그렇게 할 때 당신의 진취적인 성격은 더욱 빛을 발합니다.

-----------------------------------------------------------------------
4.현실적 (Down to Earth) 편파적이지 않음  (Well-Balanced) 남과 잘 어울림 (Harmonious)
당신은 이상보다도 일상생활에 비중을 두고 있으며 사랑도 복잡하게 얽히고 섥히는 것보다는 평범한 사랑을 추구합니다. 당신은 모든 문제를 현실적인 바탕위에서 생각하기 때문에 당신 친구들은 당신으로부터 현실감각을 느끼는 것은 물론 여유로움 또한 느끼게 됩니다. 따라서 당신은 주위사람들로부터 따뜻하고 인간적인 사람으로 인정받고 있습니다. 또한 화려한 것과 진부한 것 모두 싫어하기 때문에 변덕스럽게 변하는 유행을 회의적인 시각으로 바라보며 옷입는 것 역시 실용적이면서도 단정하고 품위있게 입기를 좋아하는 타입입니다.

-----------------------------------------------------------------------
5.프로기질 (Professional) 실용주의적 (Pragmatic) 자기 만족적 (Self-Assured)
당신은 그 누구보다도 당신 자신을 믿으며 우연한 행운보다는 당신이 스스로 한 행위를 더 믿습니다. 당신은 당신에게 주어진 일을 현실적이면서도 단순한 방법으로 해결합니다. 즉 일상생활속에서 당신의 생활 태도는 매우 실용주의적인 관점을 유지합니다. 이런 이유로 사람들은 당신을 의지할만한 사람으로 평가하기도 합니다. 그러다 보면 본의아니게 해야할 일이 많아질 때도 있습니다. 이러한 당신의 의지는 매우 단호하기 때문에 다른 사람들이 당신을 자신에 대한 신뢰가 강한 사람으로 평가하는 일도 있습니다. 또한 당신은 당신이 생각했던 것이  현실화되기 전까지는 좀체 만족하려 들지 않는 성격입니다.

-----------------------------------------------------------------------
6.평온 (Peaceful) 신중 (Discreet) 온순 (Non-Aggressive)
당신은 태평스러우면서도 매사에 사려가 깊은 사람입니다. 그리고 당신은 친구를 사귀는데 별 어려움을 느끼지 않으면서도 프라이버시를 즐기며 자유를 누립니다. 당신은 모든것으로부터 한발짝 떨어져 인생의 의미를 심사숙고해보기도 하지만 인생 자체를 즐기기도 합니다. 당신은 삶의 여유를 추구하기 위해 당신만의 은신처로 도피하기도 하지만 당신은 결코 외로운 사람은 아닙니다. 당신 자신과 세상은 평화롭게 공존하며 이 세상이 당신에게 주는 혜택에 감사하며 당신 자신의 삶을 사랑하며 살고 있습니다.

-----------------------------------------------------------------------
7.낙천적 (Carefree)  놀기 좋아함 (Playful)  쾌활 (Cheerful)
당신은 자유롭고 충동적으로 살기를 좋아합니다. 그리고 당신은 "인생의 단 한번뿐" 이라는 좌우명에 따라 최대한 인생을 즐기려 합니다. 당신은 매우 호기심이 많아 새로운 것이면 무조건 개방적입니다. 물론 지루한 것은 아주 질색입니다. 따라서 당신은 주위 환경으로부터 매우 다양한 경험을 할 뿐아니라 뜻밖의 일들도 즐깁니다.
-----------------------------------------------------------------------

8.낭만적 (Romantic) 몽상가적 기질 (Dreamy)  감성적 (Emotional)
당신은 매우 감정이 풍부한 사람입니다. 당신은 사물은 냉정하고 이상적인 관점에서 보기를 싫어하며 당신이 느끼는 감정에 따라 생각하고 행동합니다. 또한 당신은 인생을 살아가면서 꿈을 잃지 않는 것을 매우 중요하게 생각합니다. 따라서 당신은 인간의 낭만을 배척하고 오직 이성에 의해서먼 살아가야한다고 생각하는 사람들을 싫어합니다. 당신은 당신의 다양한 기분과 풍부한 감정을 한두마디로 정의하는 어떠한 시도도 거부합니다.

-----------------------------------------------------------------------

9.분석적 (Analytic)  믿음 (Trustworthy)  자기 만족적 (Self-Assured)
당신의 끊임없는 감수성은 지속적이면서도 가치있는 무언가를 추구하고 있다는 것을 나타냅니다. 다시 말해 당신은 다른 사람들이 별 흥미를 보이지 않는 자신만의 작은 '보석'들에 둘러싸여 있기를 좋아합니다. 그래서 당신은 자신만의 독특한 행동방식과 가치관에 따라 행동합니다. 당신은 변덕이 심한 유행과는 상관없이 스스로 개발한 자신만의 고상한 행동방식을 갖고 있습니다. 당신이 당신의 인생의 토대로 두고 있는 이상은 자신만의 행동양식에서 오는 즐거움입니다. 당신은 당신이 사귀고 있는 사람들을 문화적인 수준이 어느 정도인가 하는 기준으로 평가합니다.

2006/11/13 10:24 2006/11/13 10:24
이 글에는 트랙백을 보낼 수 없습니다
HTML  2006/11/03 15:49

iframe 태그 속성


1. src

  IFRAME 에 들어갈 파일의 주소(URL)를 입력
  예) src=http://cafe.naver.com/swingme.cafe

2. width, height

  IFRAME 창의 가로, 세로의 길이를 결정하는 요소

  숫자를 입력해야 하며, 단위는 픽셀(Pixel)

  예) width="500", height="600"


3. align

  IFRAME 을 페이지안에 추가할때 좌,우,중앙 정렬을 어떻게 할것이지 결정

  화면왼쪽은 left, 오른쪽은 rignt, 중앙은 center

  예) align="left"


4. frameborder

  웹 페이지안에 iframe 을 추가할때 iframe 의 테두리선을 보이게 할것인지 아닌지를 결정

  보이게 할려면 1 또는 yes, 안보이게 할려면 0 또는 no

  예) frameborder="0"


5. scrolling

  IFRAME 내부에 상하스크롤을 나타나게 할 것인지 아닌지를 결정

  'Yes' 라고 하면 페이지 내용의 많고 적음에 상관없이 스크롤이 생기고,
  'No' 라고 하면 무조건 스크롤이 생기지 않음
  'Auto' 로 설정하면 내용에 따라 자동으로 스크롤의 생성 여부를 결정


6. name

  IFRAME 도 FRAME 이기 때문에 FRAME 에서 사용하는 NAME 속성이 존재한다.
  그래서 만약 IFRAME 의 NAME 을 "swingme" 이라고 설정한 후,
  다른 프레임의 하이퍼링크에서 TARGET="swingme" 와 같이 설정한다면
  이 링크를 눌렀을 때 IFRAME 안에 있는 페이지가 링크를 따라 이동하게 된다.


7. marginwidth, marginheight

  이 기능은 IFRAME 내부 페이지의 간격(여백)을 설정
  즉, IFRAME 의 테두리와 내부 페이지 내용 사이에 어느 정도의 간격을 둘 것인가를 설정
  숫자가 클 수록 테두리와 내용 사이의 거리는 멀어지게 되고, 숫자가 작을 수록 내용이

   테두리와 가까워짐

  예) marginwidth="10", marginheight="5"


8. allowtransparency

  iframe 은 다른 페이지의 내부에 입력되므로 해당 페이지의 디자인 또는 색상에

  영향을 받는다.

  즉, swingme.html 페이지의 배경색상이 파랑 이라면 iframe 의 배경색도 파랑색으로 된다.


  예를 들자면 하나의 iframe 을 a.html 과 b.html 에 삽입할때

  a.html 은 배경색이 파랑, b.html 은 배경색이 빨강일 경우 어떻게 될까?

  이럴때 유용하게 사용하는 속성이 바로 allowtransparency 속성이다.

  이 속성은 현재 iframe 페이지의 배경색을 투명하게 만들어주는 속성으로

  a.html 에 넣으면 파랑으로 b.html 에 넣으면 빨강으로 보여지게 된다.

  ( 참고로 이 속성은 Internet Explorer 5.5 버전 이상부터 지원 )

  아이프레임으로 불러올 문서의 배경색을 우선
  bgcolor="transparent" 로 해주세요~
  그리고 아이프레임을 삽입하실때 아래처럼 적어주세요~
  <
iframe src="불러올 문서주소"   allowTransparency="true">

9. hspace, vspace

  가로,세로 여백을 정함


예)

<iframe src="http://cafe.naver.com/swingme.cafe" frameborder="no" width="565" height="800"

align="left" scrolling="no"></iframe>

<IFRAME language=javascript dataFld=dataField class=blue lang=ko id=iframeId dir=ltr title="iframe 제목" style="BORDER-RIGHT: blue 1px dotted; BORDER-TOP: blue 1px dotted; BEHAVIOR: url(../public/hilite.htc); BORDER-LEFT: blue 1px dotted; BORDER-BOTTOM: blue 1px dotted" dataSrc=dataUrl border=1 name=iframeName align=center marginWidth=0 marginHeight=0 src="http://trio.co.kr/club/public/clock.html" frameBorder=0 width=114 scrolling=no longDesc="IFRAME 설명을 위한 예제" height=25 cite="iframecite" hasMedia="false" timeContainer="none" systemLanguage="ko" systemCaptions="on" systemBitrate="5000" label="iframelabel" blockDirection="ltr" end="99" begin="0"><span>자식 SPAN 안보임</span></IFRAME>

2006/11/03 15:49 2006/11/03 15:49
이 글에는 트랙백을 보낼 수 없습니다
HTML  2006/11/02 14:19
다른 domain 간의 페이지(origin check)


두 개 이상의 프레임을 가진 페이지 간에 참조를 할 수 없는 경우가 있는데, 세가지 이유가 있습니다.
1. domain, 2. protocol, 3. port 이 다를 때, 서로 참조할 수 없습니다.


http://company.com/dir/page.html에서 아래의 URL을 참조 했을때의 결과입니다.

URL 결과이 유
http://company.com/dir2/other.html가능
http://company.com/dir/inner/another.html가능
http://www.company.com/dir/other.html불가능다른 domain
file://D|/myPage.htm불가능다른 protocol
http://company.com:80/dir/etc.html불가능다른 port

위의 경우 중에서 참조할 수 있는 한 가지 예외가 있습니다. domain입니다.
http://www.company.com/dir/other.html 에서 document.domain = "company.com";로 지정하면 서로 참조할 수 있습니다. 이것의 실행 후에 http://company.com/dir/page.html 페이지를 참조할 수 있습니다.



참조 가능할 때 사용할 수 있는 Properties
ObjectProperties
Imagessrc, lowsrc
Layersrc
Locationx, y 외에 모두
Windowfind
DocumentFor both read and write: anchors, applets, cookie, domain, elements, embeds, forms, lastModified, length, links, referrer, title, URL, formName (for each named form), reflectedJavaClass (for each Java class reflected into JavaScript using LiveConnect)

For write only: all other properties


NN3와 NN4에서 달라진 Origin Check(domain, protocol, port가 다른 페이지간의 참조시 일어남.)
1. form

이름이 있는 form은 NN4에서 origin check에 걸립니다. 이것을 피하기 위해서 폼 이름을 외부변수로 저장하여 window object의 property로 만들면 이 때부터 그 외부변수는 지정받은 폼이 됩니다. 이 외부변수로 참조할 form을 사용하면 됩니다.

2. file:URL

NN3에서는 <script SRC="...">로 아무런 protocol(file:, http:)도 사용할 수 있었지만, NN4에서는 한가지 제한 사항이 새로이 생겼습니다. 그것은 <script SRC="...">의 ...에 file: 외의 protocol을 가진 화일을 열었을 때, 열린 화일에서는 <script SRC="file:...">을 사용할 수 없습니다. file:을 사용할려면 한가지를 Netscape 사용자 폴더의 prefs.js화일에 넣어 줘야 하는데, 그것은 아래입니다.

user_pref("javascript.allow.file_src_from_non_file", true);

이것은 주의해서 사용해야 합니다. 보안상 문제가 있을 수 있습니다.

3. Layer

Layer에서 origin check는 다른 origins의 layer에서 일어납니다.
어떤 페이지가 하나 이상의 layer를 가지고 있을 때, 페이지 간의 layer를 먼저 사용하기 전에 origin check를 먼저 합니다.

4. Java Applet에서 Origin Check가 일어나는 때.

Applet가 JavaScript를 사용할 수 있게 하는 MYSCRIPT attribute를 가지고 있는 Applet가 JavaScript를 호출할 때 일어납니다. 여기서 applet의 origin은 applet 택을 가지고 있는 페이지의 URL입니다.



이 페이지 Origin Check는 확인 해보지 못했습니다.
Netscape 사의 설명을 번역한 것입니다.

IE에서는 다를 수 있습니다.



--
ie4에서 프레임에서 두 페이지가 같은 domain 이라도 host가 다를때 서로 페이지를 참조할 수 없습니다. ie4에서 다른 zone(지역도메인) 의 페이지를 참조하기 위해서는 두 페이지에 모두에
<script>	document.domain = "mySite.com"</script>
으로 같은 도메인을 지정하여야 하면 다른 호스트의 페이지를 참조할 수 있습니다. 위의 설정을 host1.mySite.com 과 host2.mySite.com 에 있는 두 페이지에서 지정을 해야합니다. 이것은 ie3.x대 에서는 없고 ie4에 추가된 cross-frame security 입니다.
2006/11/02 14:19 2006/11/02 14:19
이 글에는 트랙백을 보낼 수 없습니다
게임  2006/11/01 19:20


서부의 총잡이 죽이는구먼 헐헐..

님들은 몇점 ?
2006/11/01 19:20 2006/11/01 19:20
이 글에는 트랙백을 보낼 수 없습니다
Smarty에 내장된 캐시 내용들을 다양한 저장장치에 담을 수 있고, 사이트 내의 컨텐츠들이 업데이트될 때 손쉽게 캐시를 갱신할 수 있다. 이번 호에는 각 상황에 맞는 캐시 사용 방법과 Smarty의 보안 설정 방법에 대해 알아보도록 하겠다.
조한석 |마소 Jr.에 PHP를 연재하던 필자는 최근 Smarty에 흠뻑 빠져 살고 있다. 많은 PHP 프로그래머들과 Smarty를 함께 공유하고 싶은 마음이 간절하며, 지금도 틈틈이 Smarty 매뉴얼을 번역중이고, 최근 들어 학교 프로젝트를 수행하기 위해 파이썬을 공부하는 중이다.

지금까지 템플릿 파일들은 $template_dir에만 위치해 있었고, 이것을 읽어 들이는 방법은 다음과 같았다.

// PHP Script에서
$smarty->display(‘index.tpl’);
{* 템플릿에서 *}
{include file=’home/index.tpl’}

만일 $template_dir에 없는 템플릿들을 불러오기 위해서는 다음과 같이 절대경로를 이용해 템플릿을 가져오면 된다.

// PHP Script에서(Unix)
$smarty->display(‘/home/sizer/template/index.tpl’);
{* 템플릿에서(Windows) *}
{include file=’C:/My Website/template/index.tpl’}

앞의 표현들은 사실 웹 브라우저에서 ‘http://’를 생략하고 URL을 입력하는 것처럼 완전한 것은 아니다. 웹 브라우저들이 프로토콜 타입인 ‘http://’가 생략된 URL에 대해 기본적으로 ‘http://’라고 가정하는 것처럼, Smarty 엔진은 앞에서 생략된 리소스 타입으로 로컬 머신의 파일 시스템에 있는 파일들을 가리키는 리소스 타입인 ‘file’을 가정하고 있다. 그리고 앞의 표현들은 다음과 같이 좀더 길게 타이핑해줄 수도 있다.

$smarty->display(‘file:index.tpl’);
{include file=’file:home/index.tpl’}
$smarty->display(‘file:/home/sizer/template/index.tpl’);
{include file=’file:C:/My Website/template/index.tpl’}

리소스 플러그인 작성하기
Smarty를 사용하는 프로그래머는 파일 시스템이 아닌 데이터베이스나 LDAP, 혹은 공유 메모리 같은 저장장치에 저장할 수 있도록 별도의 리소스 플러그인을 작성하는 것이 가능하다. 그러나 다른 저장장치를 템플릿의 저장소로 사용하는 것은 아주 규모가 큰 카페와 같은 기능을 구현할 때나 고려해 볼 만한 것이고, 일반적인 성격의 웹 사이트에서는 거의 쓰일 일이 없다고 생각된다. 그런 이유로 데이터베이스에서 템플릿을 읽는 리소스 플러그인은 이 글을 다 읽고나서 독자 여러분들이 스스로 해보기를 바라며(Smarty 매뉴얼에 그렇게 실전적이지는 않은 예제가 있으니 참조하기 바란다), 이번 호에는 스킨 기능을 이용하는 웹 애플리케이션에서 필요한 템플릿들을 좀더 편리하게 지정할 수 있도록 리소스 플러그인을 추가하는 예제를 알아보도록 하겠다. <리스트 1>에 나와 있듯이 리소스 플러그인에 필요한 함수는 다른 플러그인과는 달리 4개가 필요하다.

◆ smarty_[resource_name]_template($tpl_name, &$tpl_source, &$smarty) : 템플릿 내용을 &$tpl_source를 통해 반환하는 함수, 지정한 템플릿을 찾는 데 성공하면 true를, 실패하면 false를 반환한다.
◆ smarty_[resource_name]_timestamp($tpl_name, &$tpl_source, &$smarty) : 템플릿이 만들어진 시간을 &$tpl_timestamp를 통해 반환하는 함수, 지정한 템플릿을 찾는 데 성공하면 true를, 실패하면 false를 반환한다.
◆ smarty_[resource_name]_secure($tpl_name, &$smarty) : 해당 리소스 타입이 안전한 것인지를 체크하는 함수(뒤에 나오는 보안과 관련된 함수)
◆ smarty_[resource_name]_trusted($tpl_name, &$smarty) : 해당 리소스 타입이 신뢰할 수 있는 것인지를 체크하는 함수(뒤에 나오는 보안과 관련된 함수)

<리스트 1>은 이와 같은 형식으로 작성된 리소스 플러그인을 plugins 디렉토리에서 자동으로 읽어 들이게 하는 방식이 아니라, 수동으로 register_resource() 함수로 등록시켰는데(이런 경우 플러그인 함수 이름 앞에 ‘smarty_’ 접두어를 붙일 필요가 없다), 일부 특정한 Smarty 자식 클래스에서만 사용하는 플러그인의 경우 이런 식으로 플러그인을 등록하는 방법이 종종 이용되므로 참조하기 바란다. 그리고 스킨을 순수한 템플릿만으로 만드는 것이 아니라 설정파일도 같이 사용하고 싶다면, 스킨 디렉토리의 설정파일을 로드할 수 있는 {skin_config_load} 같은 함수도 만들어 등록해줘야 할 것이다.

기본적인 캐시 사용법
사실 템플릿 리소스들은 컴파일된 이후에는 사용되지 않으므로 아무리 빠른 저장장치(예를 들어, 공유 메모리와 같은)에 저장한다고 해도 웹 사이트에서 얻는 성능상의 이익은 거의 없다고 봐야한다. 실제로 Smarty로 된 웹 애플리케이션의 성능을 개선하기 위해서는 지난 호에 배운 필터와 이번 호의 캐시 기능을 잘 활용해야 한다. 간단하게 Smarty에서 캐시를 활성화시키기 위해서는 다음과 같이 $cache_dir에 웹 서버가 읽기/쓰기가 가능하게 디렉토리의 퍼미션을 줄 필요가 있다.
// ‘/any_cache_path’는 읽기 쓰기가 가능해야 한다.
$smarty->cache_dir = ‘/any_cache_path’;

$smarty->caching을 1이나 2로 설정해주면 된다.

// 캐시가 종료되는 시간을 $cache_lifetime에 설정된 값으로 결정
$smarty->caching = 1;
// 캐시가 종료되는 시간을 캐시가 생성될 때 기록된 cache_lifetime에 의해 결정
$smarty->caching = 2;

또한 $cache_lifetime은 기본적으로 3600초(1시간)로 설정되어 있으며, 0일 경우 항상 캐시를 다시 만들어내고 -1일 경우 명시적으로 캐시를 지우지 않는 이상 영속적으로 사용된다.

$smarty->cache_lifetime = 60; // 캐시 종료시한을 1분으로 결정
$smarty->cache_lifetime = -1; // 캐시 만료시한을 두지 않는다.
$smarty->cache_lifetime = 0; // 캐시를 항상 다시 만들어낸다(테스트할 때 유용).

Smarty는 캐시를 활성화시킨 뒤 템플릿이나 설정파일에 변화가 있을 때마다 새롭게 캐시를 생성하게 되는데 $compile_check를 false로 설정하면 템플릿이나 설정파일이 바뀌어도 이전의 캐시를 그대로 사용하게 되며, 이것은 실제 사이트를 운영할 때 약간의 성능 개선 효과를 준다.

// 템플릿, 설정파일이 바뀌어도 캐시가 갱신되지 않는다.
$smarty->compile_check = false;

그럼 여기서 캐시의 종료시한을 15분으로 설정하고 템플릿과 설정파일의 변화유무를 감지할 수 있도록 설정한 <리스트 2>를 살펴보도록 하자. 얼핏 보면 <리스트 2>에는 별 문제가 없어 보인다. 하지만 이 스크립트는 성능상으로 그다지 캐시의 효과를 얻을 수 없고 사이트의 갱신된 내용을 효과적으로 반영하지도 못하는데, 그 이유는 다음과 같다.

짾 첫째, 만약 $mode가 ‘list’인 상태라면 캐시가 되었든 안되었든 항상 데이터베이스에 접속해서 결과를 가져오는 루틴이 필요하다. 데이터베이스에 저장된 내용의 변화가 없는 상태라면 이런 동작은 할 이유가 전혀 없고, 귀중한 데이터베이스 서버의 리소스만 낭비할 뿐이다.
짿 둘째, 템플릿이나 설정파일의 변화는 캐시에 반영되지만 PHP 스크립트의 변화는 캐시에 반영되지 않으므로 막상 데이터베이스에 변화가 있다고 하더라도 사이트 방문자는 왜 새로운 글이 올라가지 않는지 화를 낼 것이다(운 나쁘면 15분 정도 기다려야 새로운 글이 게시판에 확인할 수 있을 것이다).
스크립트 내에서 캐시 행동 제어하기
먼저 필요 없는 데이터베이스 연결 루틴 부문을 캐시 유무에 따라 수행여부를 결정할 수 있도록 개선해 보자. 특정한 템플릿이 캐시가 되었는지 안되었는지는 is_cached($tpl_name) 메쏘드를 통해 알아낼 수 있다. 다음과 같이 하면 캐시가 된 상태에서는 쓸데없이 데이터베이스에 접속하지 않게 될 것이다.

if (!$smarty->is_cached(‘list.tpl’)) {
// 데이터베이스에 접속해 결과를 가져온다.
}
$smarty->display(‘list.tpl’);

그 다음에 clear_cache() 메쏘드를 이용하면 해당 템플릿의 캐시된 결과를 명시적으로 지울 수 있다. <리스트 3>은 이 두 개의 메쏘드를 이용해서 기존의 캐시를 사용할지 아니면 데이터베이스에 업데이트된 내용을 반영해서 새롭게 캐시를 만들어내야 할지 처리하는 스크립트이다.

템플릿마다 별도의 캐시를 만들어내고 제어하기
<리스트 3>을 보면 $mode가 ‘list’인 경우 리스트가 길어도 그냥 한 페이지에 다 출력한다. 그러나 게시판과 같은 기능을 구현할 때는 리스트를 일정한 길이로 잘라 페이지별로 보여줄 필요가 있다. 이런 경우 $page_num과 같은 별도의 변수에 따라 출력을 달리해서 출력해야 한다.

$smarty->display(‘list.tpl’);

같은 식으로 템플릿을 출력한다면 ‘list.tpl’에 대해 오직 하나의 캐시만을 가지기 때문에 제대로 된 페이지 네비게이션을 구현할 수 없게 된다. 마찬가지로 게시판에서 특정한 글을 읽는 동작 역시 다음과 같이 하면 ‘view.tpl’에 대해 오직 하나의 캐시만을 가지므로 게시판에 접속하는 사용자들은 언제나 같은 글만을 읽게 될 것이다.

$smarty->display(‘view.tpl’);

이것을 해결하는 가장 간단한 방법은 특정한 매개변수에 따라 변동이 심한 페이지 영역에 대해서 캐시 기능을 끄는 것일 테지만, 게시판과 같은 웹 애플리케이션에서 리스트를 보여주는 부분과 글을 읽은 부분에서 캐시 기능을 끄는 것은 사실상 캐시 기능을 사용하지 않겠다는 소리나 마찬가지이다. 지금까지 $smarty->display($tpl_ name)과 같은 형식으로만 템플릿을 읽어 들여 출력했지만, 사실 display() 메쏘드의 완전한 형식은 다음과 같다.

display($tpl_name, $cache_id, $compile_id);

여기서 $cache_id 매개변수를 달리 설정하면 같은 템플릿에 대해 별도의 캐시를 만들어줄 수 있다. ? 과 같은 코드는 같은 ‘list.tpl’에 대해 각각 다른 캐시를 만들어 내는데, ? 와 같이 하면 $page_num에 따라 별도의 캐시들이 생성하게 된다.

$smarty->display(‘list.tpl’, ‘1’); → ?
$smarty->display(‘list.tpl’, ‘2’); → ?
$smarty->display(‘list.tpl’, $page_num); → ?

이렇게 생성된 별도의 캐시들을 지우기 위해서는 clear_cache()를 display()와 같은 형식으로 호출하면 된다.

$smarty->clear_cache(‘list.tpl’, $page_num);

그러나 아쉽게도 이런 방법으로 진행해도 문제는 발생한다. 만약 게시판에 새로운 글이 올라온다면, 리스트와 관련된 모든 캐시를 지워줘야 하는데, 앞과 같이 캐시를 생성했다면 다음과 같은 코드로 캐시를 하나하나 지워줘야 할 것이다.

for ($i=0; $i < $page_total; $i++) {
$smarty->clear_cache(‘list.tpl’, $i);
}

이런 식으로 하면 캐시 제어가 너무 복잡해질 가능성이 있다. 하지만 관련된 페이지들을 묶어서 $cache_id로 표현할 수 있으므로 걱정하지 말기 바란다. 게시판의 예를 계속해서 들어보면, 게시판의 리스트나 글 조회로 인해 생성되는 캐시들은 ‘|’를 이용해서 다음과 같이 그룹핑해주는 것이 가능하다(‘|’로 그룹핑하는 깊이에는 한계가 없다).

$smarty->display(‘list.tpl’, “board|list|$page_num”);
$smarty->display(‘view.tpl’, “board|view|$id”);

만일 특정한 글이 수정되었다면 리스트에는 변동이 없을 테니, “board|view|$id”에 해당하는 캐시만 새롭게 생성해 주면 될 것이다.

$smarty->clear_cache(‘view.tpl’, “board|view|$id”);

그러나 새로운 글이 올라왔다면 리스트 전체에 해당하는 캐시를 갱신해 줄 필요가 있는데, 다음과 같이 “board|list|$page_num”에서 $page_num을 생략한 채 캐시를 clear_cache()를 호출해 주면 자동으로 ‘board|list’에 속하는 모든 캐시들이 만료된다.

$smarty->clear_cache(‘list.tpl’, ‘board|list’);
또한 게시판 전체의 모든 캐시를 깨끗이 지우고 싶다면 clear_all_cache()를 사용해도 어느 정도 비슷한 효과를 낼 수 있겠지만, 그것보다는 다음처럼 $tpl_name을 null로 지정한 채 clear_cache()를 호출하면 list.tpl과 view.tpl과 상관없이 ‘board’에 속하는 모든 하위 캐시들을 만료시키게 된다.

$smarty->clear_cache(null, ‘borad’);

캐시 핸들러 제작과 등록하기
앞에서 리소스들은 아무리 빠른 장치에 저장하더라도 그로부터 발생하는 성능상의 이득은 그렇게 크지 않다고 했다. 하지만 캐시의 경우는 저장하고자 하는 장치가 빠르면 빠를수록 좋다. 여건만 된다면 모든 캐시된 내용들을 메모리에 저장해 보는 것도 생각할 수 있다. 로컬 파일 시스템이 아닌 다른 저장소를 캐시로 이용하기 위해서는 $cache_handler_func에 적당한 캐시 핸들러 함수를 만들어 등록시키면 된다.

$smarty->cache_handler_func = ‘database_cache_handler’;

등록할 캐시 핸들러 함수의 레이아웃은 다음과 비슷한 모습으로 작성하게 된다.

function any_cache_handler($action, &$smarty, &$cache_content,
$tpl_file = null,
$cache_id = null,
$compile_id = null) {
switch ($action) {
case ‘read’: // 캐시로부터 캐시된 내용을 읽는 루틴
case ‘write’: // 캐시에 새로운 캐시 내용을 쓰는 루틴
case ‘clear’: // 캐시 내용을 삭제하는 루틴
default: // ‘read’, ‘write’, ‘clear’이외의 행동은 에러이다.
}
}

<리스트 5>는 Smarty 메뉴얼에 있는 MySQL용 캐시 핸들러 예제인데, 이것은 앞에서 소개한 캐시 그룹핑 기능을 지원하지 못한다. 따라서 앞에서 언급한 대로 캐시들을 하나하나 제거하는 루틴을 구현해 주거나 좀더 기능을 추가할 필요가 있다. $CacheId 이외에 $tpl_file, $cache_id, $compile_id를 나타내는 컬럼을 테이블에 추가한 뒤 그에 맞는 쿼리문을 수행하는 루틴을 핸들러에 삽입하면 될 텐데, 이것은 다음 시간까지 독자 여러분들의 숙제로 남기도록 하겠다(기본 캐시 핸들러의 알고리즘을 살펴보려면 ‘Smarty.class.php’를 참조하면 된다).

Smarty를 안전하게 실행시키기
Smarty는 템플릿 안에 {php}..{/php}나 {include_php}..{/include_ php}를 통해 PHP 코드들이 삽입돼 실행될 수 있다. 그리고 말한 적은 없지만 {if}..{/if} 동적 블럭문이나 변수 변환자에서 일반 PHP 함수를 사용할 수도 있다.
{if count($array) > 1}
..
{/if}
즉, 템플릿 내에서 이와 같은 문장을 사용할 수 있다는 의미인데, 여기서 물론 count는 템플릿 함수가 아닌 PHP 함수 count를 가리킨다. 이런 특징들은 잘만 사용되면 나름대로 편리함을 줄 수도 있겠지만, 편리함을 위해 여러분의 웹 사이트의 안전을 포기할 수는 없는 법이다. Smarty는 보안에 민감한 영향을 줄 수 있는 특징들을 템플릿에서 사용할 수 없도록 하거나, 또 신뢰할 수 있는 위치에 있는 템플릿만을 처리할 수 있도록 멤버 변수들을 설정해 줄 수 있다. 먼저 가장 기본적인 보안 관련 멤버 변수에는 $security가 있는데, 이것을 true로 하면 기본적으로 Smarty 템플릿 엔진은 다음과 같이 행동하게 된다(다음에 나오는 행동들은 $security_setting에 의해 조정될 수 있다).

◆ $secure_dir에 설정된 디렉토리들 밑에 있는 템플릿들만을 사용할 수 있다. (display(), fetch() 메소드와 {include} 템플릿 함수 등에서 이 값을 체크한다)
◆ 만일 $php_handling가 SMARTY_PHP_ALLOW로 설정되어 있으면, 이 값은 묵시적으로 SMARTY_PATH_PATHTHRU로 교체된다.
◆ {php}..{/php} 템플릿 함수는 허용되지 않는다.
◆ {if}..{/if} 동적 블럭문에서 $security_setting에서 허용하는 함수를 제외한 일반 PHP 함수를 사용할 수 없다.
◆ 변수 변환자에서 $security_setting에서 허용하는 함수를 제외한 일반 PHP 함수를 사용할 수 없다.

앞에 나오는 멤버 변수들을 하나하나 살펴보도록 하자. 우선 $secure_dir의 값은 허용할 템플릿 디렉토리를 다음과 같이 설정하면 되는데, 허용할 템플릿 디렉토리가 많다면 배열로 설정해주면 된다.

$smarty->template_dir = ‘/home/sizer/public_html/source/template’;
$smarty->compile_dir = ‘/tmp/site/localhost/compile’;
$smarty->security = true;
$smarty->secure_dir = ‘/home/sizer/public_html/source/template’;
$smarty->display(‘/home/sizer/public_html/source/not_allowed_template/index.tpl’);
$smarty->display(‘/home/sizer/public_html/source/template/index.tpl’);

허용되지 않는 템플릿을 포함하는 부분에서 다음과 같은 메시지를 볼 수 있다.

◆ PHP Warning: Smarty error : (secure mode) accessing “/home/sizer/ public_html/source/not_allowed_template/index.tpl” is not allowed in /usr/local/share/php/smarty/Smarty.class.php on line 595

두 번째로 $php_handling 멤버변수는 템플릿 내에 삽입된 {php}..{/php} 문장을 어떻게 처리할지 결정하는 함수로서 다음과 같이 네 가지 동작을 따른다.

짾 SMARTY_PHP_PASSTHRU : 해당 태그 내용을 있는 그대로 출력한다.
짿 SMARTY_PHP_QUOTE : 해당 태그 내용을 HTML 태그로 감싸 출력한다.
쨁 SMARTY_PHP_REMOVE : 해당 태그 내용을 삭제한다.
쨂 SMARTY_PHP_ALLOW : 태그 안에 있는 PHP 코드를 실행한다.

다음으로 $security_setting 멤버변수는 $security가 true로 설정된 상태에서 보안 수준을 결정할 수 있는 배열로서 다음과 같은 요소들을 가지고 있다.

◆ INCLUDE_ANY : true로 설정하면 $secure_dir에 있는 값을 무시한다. 기본 값은 false이다.
◆ PHP_TAGS : true로 설정하면 템플릿 내에서 {php}..{/php}를 사용할 수 있다. 기본 값은 false이다.
◆ PHP_HANDLING : true로 설정하면 $php_handling에 있는 값을 체크하지 않고 PHP 코드를 항상 실행한다.
◆ IF_FUNCS : {if}..{/if} 문에서 사용할 수 있는 함수들을 설정하며, 기본적으로 허용되는 함수로는 ‘array’, ‘list’, ‘isset’, ‘empty’, ‘count’, ‘sizeof’, ‘in_array’, ‘is_array’가 있다.
◆ MODIFIER_FUNCS : 변수 변환자에서 사용할 수 있는 함수들을 설정하며, 기본적으로 허용되는 함수는 ‘count’이다.

그리고 $trusted_dir이라는 멤버변수가 있는데, 이 변수로 설정한 디렉토리 밑에 있는 템플릿들은 {include_php}를 통해 PHP 코드를 실행할 수 있게 되는데, $secure_dir과 $trusted_dir에 같은 디렉토리가 중복되어 있다면 $secure_dir이 우선권을 가진다.

다음에는 스킨 메모장 제작
이번 호에는 리소스 플러그인과 캐시 제어법, 그리고 보안과 관련된 멤버변수들에 대해 알아보았다. 여러분들은 이제 Smarty 템플릿 엔진에 대해 대부분의 이론적인 지식을 쌓은 셈인데, 막상 Smarty를 이용해서 웹 사이트를 어떻게 구축할 것인가에 대해 고민이 될 것이다. 사실 필자도 아직까지 짙은 안개 속에서 방황하는 감이 없지 않았는데, 아무래도 Smarty를 이용한 실전 코드들이 아직 그렇게 많이 살펴보지 않은 탓이라고 생각한다(Smarty를 이용한 사이트나 웹 애플리케이션은 아직까지 그렇게 많지 않은 편이기도 하다). 약속한 커리큘럼을 따르려면 다음 호에는 Smarty를 이용해서 간단한 스킨 메모장을 만들어 봐야겠지만, 사정이 된다면 PEAR와 Smarty를 이용한 좀 더 큰 규모의 웹 사이트 구축 방법을 소개할지도 모르겠다.

2006/11/01 18:43 2006/11/01 18:43
이 글에는 트랙백을 보낼 수 없습니다
웅쓰:웅자의 상상플러스
웅자의 상상플러스
전체 (379)
게임 (5)
영화 (2)
기타 (23)
맛집 (5)
영어 (2)
대수학 (3)
형태소 (5)
Hacking (9)
Linux (112)
HTML (48)
Application_developing (48)
Web_developing (102)
Window (11)
«   2006/11   »
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
  1. 2016/01 (1)
  2. 2015/12 (3)
  3. 2015/10 (3)
  4. 2015/03 (2)
  5. 2015/01 (4)