'php'에 해당되는 글 8건

  1. 2007/07/10 페이지 소스
  2. 2007/03/08 mysql
  3. 2007/01/31 mysql -펌 (1)
  4. 2007/01/13 그누 $member Array 함수 (1)
  5. 2007/01/01 RSS 수집 로봇 구현·분석

페이지 소스

php 2007/07/10 16:35
ㅡㅡ;

2007/07/10 16:35 2007/07/10 16:35

mysql

php 2007/03/08 05:02

데이터베이스 관리자와 개발자들은 정기적인 데이터 백업의 중요성을 잘 알 것이다. 만약 디스크나 서버가 고장날 경우 백업을 미리 해 뒀는지 여부는 1년치 업무결과를 잃어버리느냐 아니면 몇시간만에 정상으로 복귀하느냐를 결정한다.

하지만 다행스럽게도 MySQL 사용자는 백업과 복구를 할 수 있는 간편하게 할 수 있는 내장 전용 툴을 사용할 수 있다. 이 툴을 이용하면 이기종 플랫폼으로 MySQL 데이터베이스를 간편하게 옮길 수 있으며, 또 다른 포맷으로 레코드를 저장하거나 불러오기도 가능하다.

데이터베이스 파일 복사
MySQL 데이터베이스 백업의 기본은 데이터베이스 파일 자체를 복사하는 것이다. MySQL은 이기종 플랫폼에서도 동일한 테이블 포맷을 사용하므로 MySQL 테이블과 인덱스 파일을 플랫폼을 넘나들며 쉽게 복사할 수 있다(물론 양쪽 플랫폼에 동일한 MySQL 버전이 설치돼 있어야 한다).

실제 복사하는 방법을 살펴 보자. 먼저 MySQL은 모든 데이터베이스를 data/ 디렉토리에 저장되며, 이는 다시 각 데이터베이스를 위한 서브디렉토리로 구분된다. 테이블과 테이블 인덱스는 파일로 저장되고, 파일명은 테이블명과 확장자를 합쳐서 붙여진다.

가장 쉬운 데이터베이스 복사 방법은 전체 data/ 디렉토리를 백업용 미디어에 복사하고, 언제든지 복구할 수 있도록 저장해 두는 것이다. 복사를 자동화하는 스크립트를 작성하는 것도 좋은 방법이다. 스크립트를 작성했으면 이를 crontab에 추가해 데이터베이스 업데이트 주기에 따라 매일 혹은 매주 단위로 실행되도록 설정할 수 있다.

한가지 주의할 것은 윈도우와 유닉스 플랫폼 사이에서 파일을 이동하는 경우다. 유닉스 파일명은 대소문자를 구분하지만 윈도우는 그렇지 않으므로, MySQL 테이블명에 대소문자가 뒤섞인 있으면 문제가 발생할 가능성이 있다(물론 테이블내의 데이터는 영향을 받지 않는다). 최악의 경우 데이블명과 코드를 수정하기 전까지 제대로 실행되지 않을 수도 있다. 따라서 최선의 방법은 테이블명을 소문자만으로 작성하는 것이다.

테이블을 텍스트 파일로 저장하기
파일복사 외에 MySQL에 기본 설치된 mysqldump 툴을 사용하는 방법도 있다. 이툴은 테이블과 데이터베이스는 물론 데이터베이스 전체를 텍스트 파일로 변환해 저장한다. 사용법도 매우 단순해, 내보낼 데이터베이스 이름을 인자로 다음과 같이 실행하면 된다.


$ mysqldump -u root -p secret stocksdb

mysqldump 툴은 MySQL 서버와 접속해 주어진 암호정보로 로그인한 후, 일련의 SQL 명령어를 이용해 테이블 구조와 데이터를 다음과 같은 형태로 출력한다.


--
-- Dumping data for table 'portfolio'
--

INSERT INTO portfolio VALUES (1,'DHDU',2589,77.56); INSERT INTO portfolio VALUES (2,'YHOO',3200,45.65); INSERT INTO portfolio VALUES (3,'WMT',100,53.29);

물론 이를 콘솔에 출력하는 것은 그리 유용하지 못하다. 여러분이 원하는 것은 이를 파일로 저장해 백업하고나 복구하는데 이용할 수 있어야 한다. 이를 위해서는 출력 형태를 파일로 다시 정해주기만 하면 된다.


$ mysqldump -u root -p secret stocksdb > stocksdb.sql [/code]

만약 특정 테이블만 백업하려면 데이터베이스 이름 뒤에 테이블 이름을 붙이면 된다. 다음은 stocksdb 데이터베이스에서 users 테이블에 저장된 구조와 데이터만을 추출하는 구문이다.


$ mysqldump -u root -p secret stocksdb users > users.sql

또한 시스템 내의 모든 데이터베이스를 저장하려면 다음과 같이 --all-databases 옵션을 이용한다. --all-databases 옵션을 사용하면, mysqldump 명령 결과에 각 데이터베이스를 초기화하는 CREATE DATABASE문이 포함된다. 이렇게 하면 데이터베이스 전체를 한 번에 복구하기가 더 쉬워진다.


$ mysqldump -u root -p secret --all-databases > backup.sql

테이블 구조만 백업하고자 하면 다음과 같이 --no-data 옵션을 사용하면 된다. 이 옵션은 애플리케이션을 처음 설치해서, 레코드가 없는 테이블의 복사본을 만들어야 하는 경우 대단히 유용하다.


$ mysqldump -u root -p secret --no-data stocksdb > stocksdb.sql

물론 테이블 구조는 제외하고 데이터만 백업하는 경우는 다음과 같은 구문을 이용하면 된다.


$ mysqldump -u root -p secret --no-create-info stocksdb > stocksdb.sql

텍스트 백업 파일로 MySQL 테이블 복구하기
지금까지 데이터베이스와 테이블 백업 방법을 살펴 봤다. 그러나 이것은 문제 해결의 절반에 불과하다. 나머지 절반은 실제 문제가 발생했을 때 이를 복구하는 방법을 아는 것이다. 다행스럽게도 MySQL은 복구과정도 손쉽다. mysqldump 명령의 결과물은 일련의 SQL 명령어로 구성돼 있기 때문에, MySQL 클라이언트가 간단하게 기존 데이터베이스 구조와 컨텐트를 재구축할 수 있다.

모든 데이터베이스를 mysqldump--all-databases 명령을 이용해 backup.sql 파일에 복사했다고 가정하면 다음과 같은 구문으로 이를 복구할 수 있다.


$ mysql -u root -p secret < backup.sql

--all-databases 옵션을 사용하지 않고 일부 테이블이나 데이터베이스를 선택적으로 백업한 경우는 MySQL 명령 실행시 데이터베이스의 위치를 알려주는 -D 옵션을 추가한다. 예를 들어 stock2 데이터베이스의 stocksdb.sql 파일에 저장된 테이블을 복구하는 구문이라면 다음과 같다.


$ mysql -u root -p secret -D stocks2 < stocksdb.sql

다른 포맷으로 내보내고 읽어들이기
MySQL 데이터베이스는 SQL 포맷 외에도 다양한 형식으로 저장할 수 있다. mysqldump 툴은 CSV나 사용자가 원하는 구분문자(delimiter)를 이용해 다양한 포맷으로 레코드를 저장할 수 있는데, 이를 위해서는 mysqldump 명령어에 --fields-terminated-by 인자만 추가하면 된다.


$ mysqldump -u root -p secret --no-create-info --tab=/tmp --fields-terminated-by=',' stocksdb

이와 같이 실행하면 mysqldump는 stocksdb 테이블에 있는 레코드의 각 필드를 쉼표로 분리해 /tmp 디렉토리에 저장한다. 별도의 라인 터미네이터를 사용하려면 --lines-terminated-by 인자를 사용해 특정 구분문자로 라인을 표시할 수 있다.

다른 데이터 포맷을 불러들이는 것도 가능하다. 예를 들어 다음과 같이 탭으로 분리한 테이블 레코드가 있다고 가정하자.


1 DHDU 2589 77.56
2 YHOO 3200 45.65
3 WMT 100 53.29

이 때 mysqlimport 툴을 이용하면 MySQL 데이터베이스 파일로 읽어들일 수 있다. 단 소스 파일의 베이스 이름이 데이터가 삽입될 위치를 결정한다는 점에 유의하자.


$ mysqlimport -u root -p secret --fields-terminated-by='\t' test /tmp/portfolio.txt

백업을 할때 항상 두 카피 이상을 유지하도록 한다(하나는 다른 위치에). 또한 MySQL 매뉴얼 내용 가운데 다양한 데이터를 내보내고 불러들이는 방법을 참고해 여러분의 환경에 응용할 수 있는 가장 좋은 방법을 찾길 바란다.

무엇보다 필자는 여러분이 문제가 발생한 데이터베이스를 복구해야 하는 상황에 놓이지 않기를 진심으로 바란다. 그러나 효율적으로 복구할 수 있는 툴이 있고, 이를 이용하면 최악의 경우에도 사용자의 불편을 최소화할 수 있다는 사실만으로도 여러분은 좀더 쉽게 잠을 청할 수 있을 것이다. @

2007/03/08 05:02 2007/03/08 05:02

mysql -펌

php 2007/01/31 18:41
1. mysql DB 백업 
mysqldump -u 계정이름 -p DB이름(기본셋팅시 계정이름과 DB이름은 동일) 
> 백업할파일이름(파일이름.sql)  엔터 
password : 패스워드입력 엔터 
=> 파일이름.sql로 DB의 데이터가 백업됨. 
  
2. mysql DB 복구 
mysql -u 계정이름 -p DB이름 < 파일이름.sql( 1.의 과정에서 백업한 파일이름) 
password : 패스워드입력 엔터 
=> 파일이름.sql로 백업된 DB의 데이터가 복구됨. 
  
3. 2.의 과정에서 DB복구시 오류메시지가 출력되는 경우가 있습니다. 
@계정이름>xxx TABLES already exists in xxx.sql ... 
 이것은 동일 DB에 기록되어 있는 DB 데이터가 존재할 경우에 발생되는데 일반적으로 다음과 유사한 메시지가 출력됩니다. 
 이럴 경우에는 현재의 DB 데이터를 보존해야 할 경우, 1의 과정을 통해 현재 복구하려는 파일이름과 동일하지 않은 특정한 파일 이름으로 백업하십시오. 
그리고 나서, 4.의 과정을 수행합니다. 
  
4. mysqladmin을 이용해 DB를 한꺼번에 삭제하기 
 위험한 명령입니다. 반드시 필독하시고, 주의하시기 바랍니다.
 본 명령을 통해 삭제된 데이터는 절대 복구될 수 없습니다. 
 위험하고, 위험한 명령이라서 다시 한번 필독하시고 숙지하시기 바랍니다. 
 (경우에 따라서는 root(최고관리자) 에 의해 수행권한이 막혀있을 수 있습니다.)
  
@계정이름>mysqladmin drop -u 계정이름 -p DB이름 엔터 
password : 패스워드입력 엔터 
are you progress? (비슷한 메시지 출력됩니다. 머릿속에서 나오는 내용이라... 출력되는 메시지는 다를 수 있습니다.) 
yes/no ? (만약 확신이 서지 않는다면, no) <= 키보드 y키 또는 n키 사용. 
  
이 방법은 DB내에 존재하는 table과 table내부에 존재하는 각각의 레코드를 삭제하는 명령이 아닙니다. 
DB자체를 삭제하는 명령입니다.
반드시 이점을 명심하시고 실행시 주의하시기 바랍니다. 
하단에 기재되는 5.의 내용을 반드시 수행하셔야 정상적인 DB관련 작업을 수행하실 수 있습니다. 
놓치지 마시고 수행하시기 바랍니다. 
간혹, DB 자체를 삭제하고 나서, mysql DB 및 관련 오류메시지가 출력된다고 말씀하시는 분들이 계십니다. 
이유는 단 한가지 하단 5.의 내용을 수행하지 않으셔서 발생되는 내용입니다. 
  
5. 4. 의 과정에서 DB자체를 삭제한 경우, DB를 생성하는 방법 
@계정이름>mysqladmin create -u 계정이름 -p DB이름 엔터 
password : 패스워드입력 엔터 
=> 정상적으로 DB가 생성됩니다. 
('혹시, 이러한 방법을 사용한다면, 계정사용자 한명이 여러개의 DB를 생성할 수 있지 않을까?' 라는 생각을 하시는 분도 계십니다. 
그러나, NO!, 기존의 DB가 존재한다는 가정하에 수행할 수 있는 명령이므로,
전혀 새로운 DB를 생성하실 수 없습니다. 
새로운 DB 생성은 오직 root만이 수행할 수 있습니다.) 
  
6. 상기한 5.의 과정까지 모두 수행하셨다면, 안전하게 DB를 복구하실 수 있습니다. 
@계정이름>mysql -u 계정이름 -p DB이름 엔터 
password : 패스워드입력 엔터 
2007/01/31 18:41 2007/01/31 18:41

그누 $member Array 함수

php 2007/01/13 22:51
$member Array
(
    [mb_id]
    [mb_password]
    [mb_name]
    [mb_nick]
    [mb_nick_date]
    [mb_email]
    [mb_homepage]
    [mb_password_q]
    [mb_password_a]
    [mb_level]
    [mb_jumin]
    [mb_sex]
    [mb_birth]
    [mb_tel]
    [mb_hp]
    [mb_zip1]
    [mb_zip2]
    [mb_addr1]
    [mb_addr2]
    [mb_signature]
    [mb_recommend]
    [mb_point]
    [mb_today_login]
    [mb_login_ip]
    [mb_datetime]
    [mb_ip]
    [mb_leave_date]
    [mb_intercept_date]
    [mb_email_certify]
    [mb_memo]
    [mb_mailling]
    [mb_sms]
    [mb_open]
    [mb_profile]
    [mb_memo_call]
    [mb_1]
    [mb_2]
    [mb_3]
    [mb_4]
    [mb_5]
    [mb_6]
    [mb_7]
    [mb_8]
    [mb_9]
    [mb_10]
    [mb_dir]
)
2007/01/13 22:51 2007/01/13 22:51

1회.
블로거들의 집합소 메타 사이트 구현하기
2회. RSS 수집 로봇 구현과 문제점 분석

이번 강좌는 지난 호에 이은 메타 사이트 만들기 강좌 마지막 편으로 XML 파일을 이용하여 RSS 주소들의 목록을 관리하는 클래스의 제작, RSS 파일들로부터 읽은 정보들을 데이터베이스에 저장하는 방법에 대해 알아보겠습니다. 그리고 그를 구현하는 테이블, 저장 프로시저, 클래스들을 제작하고, 간단한 RSS 수집 로봇 프로그램을 제작해 보도록 하겠습니다.

연+재+순+서
1회 2004. 11 | 블로거들의 집합소 메타 사이트 구현하기
2회 2004. 12 | RSS 수집 로봇 구현과 문제점 분석

자동차는 수많은 부품들을 각각 생산하여 설계도에 맞게 각각을 연결하고 조립하는 과정을 통해 만들어집니다. 우리가 만들고자 하는 메타 사이트도 핵심 부품들을 하나하나 만들고 마지막에 그러한 각각의 부품들을 조립하여 우리가 원하는 하나의 기능을 수행하는 프로그램을 완성하는 단계로 진행되고 있습니다. 지난 시간을 통해 우리는 다음과 같은 내용을 진행하였습니다.

메타 사이트는 RSS 파일로부터 블로그의 정보를 얻는다는 사실을 이해한다.
RSS 파일의 구조에 대해서 공부한다.
RSS 파일의 내용을 저장할 클래스를 제작한다.
RSS 파일로부터 내용을 읽어오는 RssReader 클래스를 제작한다.

이번 연재는 지난 호에 이은 메타 사이트의 부품 만들기 강좌 마지막 편으로 RSS 주소들을 저장하는 클래스와, XML 파일을 이용하여 RSS 주소들의 목록을 관리하는 클래스 제작, RSS 파일들로부터 읽은 정보들을 데이터베이스에 저장하는 방법과 그를 구현하는 테이블, 저장 프로시저, 클래스들을 제작하고 간단한 RSS 수집 로봇 프로그램을 만들어 보도록 하겠습니다.

RSS 파일들의 주소들을 관리하자
지난 호를 통해 한 개의 파일 또는 주소로부터 RSS 정보를 읽을 수 있는 RssReader 클래스가 완성되었습니다. 남은 문제는 여러 RSS 주소들을 관리하는 작업입니다. 이러한 작업은 데이터베이스를 이용하면 손쉽게 제작할 수 있지만, 데이터베이스를 이용하는 방법은 이후 RSS 파일의 내용들을 기록할 때 다룰 예정이니, 우선은 XML 파일을 이용하여 저장하는 방법으로 RSS 주소들의 리스트를 관리해 보겠습니다.
RSS 주소들을 관리하기 위해서는 RSS 주소와 더불어 사이트에 대한 간략한 설명과 부가적인 자료들이 포함되면 됩니다. 예를 들어 블로그의 이름 또는 블로그의 종류 등 RSS 주소를 보고 이해하기 쉽도록 추가할 수 있습니다. 지면상 가장 간단하게 RSS 파일의 경로와 블로그의 제목 정도만 가지고 있는 클래스를 만들어 보도록 하겠습니다.











이번 글은 지난번에 이은 메타 사이트 만들기 강좌 마지막 편으로 XML 파일을 이용하여 RSS 주소들의 목록을 관리하는 클래스의 제작, RSS 파일들로부터 읽은 정보들을 데이터베이스에 저장하는 방법에 대해 알아보겠습니다. 그리고 그를 구현하는 테이블, 저장 프로시저, 클래스들을 제작하고, 간단한 RSS 수집 로봇 프로그램을 제작해 보도록 하겠습니다.

자동차는 수많은 부품들을 각각 생산하여 설계도에 맞게 각각을 연결하고 조립하는 과정을 통해 만들어집니다. 우리가 만들고자 하는 메타 사이트도 핵심 부품들을 하나하나 만들고 마지막에 그러한 각각의 부품들을 조립하여 우리가 원하는 하나의 기능을 수행하는 프로그램을 완성하는 단계로 진행되고 있습니다. 지난 글을 통해 우리는 다음과 같은 내용을 진행하였습니다.

[1] 메타 사이트는 RSS 파일로부터 블로그의 정보를 얻는다는 사실을 이해한다.
[2] RSS 파일의 구조에 대해서 공부한다.

[3] RSS 파일의 내용을 저장할 클래스를 제작한다.

[4] RSS 파일로부터 내용을 읽어오는 RssReader 클래스를 제작한다.

이번 글은 지난 시간에 이은 메타 사이트의 부품 만들기 강좌 마지막 편으로 RSS 주소들을 저장하는 클래스와, XML 파일을 이용하여 RSS 주소들의 목록을 관리하는 클래스의 제작, RSS 파일들로부터 읽은 정보들을 데이터베이스에 저장하는 방법과 그를 구현하는 테이블, 저장프로시저, 클래스들을 제작하고 간단한 RSS 수집 로봇 프로그램을 만들어 보도록 하겠습니다.

RSS 파일들의 주소들을 관리하자
지난 호를 통해 한 개의 파일 또는 주소로부터 RSS 정보를 읽을 수 있는 RssReader 클래스가 완성되었습니다. 남은 문제는 여러 RSS 주소들을 관리하는 작업입니다. 이러한 작업은 데이터베이스를 이용하면 손쉽게 제작할 수 있지만, 데이터베이스를 이용하는 방법은 이후 RSS 파일의 내용들을 기록할 때 접할 예정이니, 우선은 XML 파일을 이용하여 저장하는 방법으로 RSS 주소들의 리스트를 관리해 보도록 하겠습니다.

RSS 주소들을 관리하기 위해서는 RSS 주소와 더불어 사이트에 대한 간략한 설명과 부가적인 자료들이 포함되면 됩니다. 예를 들어 블로그의 이름 또는 블로그의 종류 등 RSS 주소를 보고 이해하기 쉽도록 추가할 수 있습니다. 지면상 가장 간단하게 RSS 파일의 경로와 블로그의 제목 정도만 가지고 있는 클래스를 만들어 보도록 하겠습니다.

Public Class RssAddress
   Public RssURL As String
   Public BlogName As String

   Public Sub New()
   End Sub

   Public Sub New(ByVal RssURL As String, ByVal BlogName As String)
       Me.New()
       Me.RssURL = RssURL
       Me.BlogName = BlogName
   End Sub
End Class

아무런 작업을 하지 않는 기본 생성자와 데이터를 입력하며 객체를 생성하기 편리하게 하기 위해 RSS 파일의 주소와 블로그의 이름을 인자로 받는 생성자가 있습니다. 여기서는 아무런 작업도 하지 않는 기본 생성자를 굳이 선언한 이유가 있습니다.

우리는 RSS 정보들을 저장하기 위해서 XML 파일을 사용하며 아주 간편하게 XML 파일로 만들기 위해 직렬화(serialization)를 사용하려고 합니다. 이를 위해 닷넷 프레임워크에서 직렬화를 지원하는 System.Xml.Serialization.XmlSerializer 클래스를 이용하려고 하는데, 어떤 객체를 직렬화하기 위한 조건 중 하나가 객체는 반드시 기본 생성자를 가지고 있어야 한다는 것입니다. 일반 생성자에 Optional을 사용하여 기본 값을 지정해 주는 생성자를 만들어도 직렬화는 되지 않습니다.

이렇게 한 개의 RSS 파일의 정보를 가지고 있는 RssAddress 클래스가 완성되었습니다. 이제 다수의 RssAddress들을 저장할 컬렉션 클래스를 만들어야 합니다. CollectionBase 클래스를 상속받고, 인덱서와 메쏘드 등을 구현하여 컬렉션 클래스를 만드는 방법은 지난 호에서 RssItemCollection 클래스를 통해 소개했습니다. 그와 같은 방법으로 RssAddressCollection 클래스를 만들어줍니다. 그리고 여기에 XML 파일로부터 손쉽게 데이터를 불러오고, XML 파일로 손쉽게 저장할 수 있는 2개의 메쏘드를 추가하려고 합니다.

<리스트 1> RssAddressCollection 클래스

Imports System.IO
Imports System.Xml.Serialization

Public Class RssAddressCollection
   Inherits CollectionBase

   Public Shared Function LoadFromXml(ByVal XmlFileName As String) As RssAddressCollection

       Dim serializer As New XmlSerializer(GetType(RssAddressCollection))
       Dim rssAddrs As RssAddressCollection
       Dim sr As New StreamReader(XmlFileName)
       rssAddrs = serializer.Deserialize(sr)
       sr.Close()

       Return rssAddrs

   End Function

   Public Shared Sub SaveToXml(ByVal XmlFileName As String, ByVal RssAddrs As RssAddressCollection)

       Dim serializer As New XmlSerializer(GetType(RssAddressCollection))
       Dim sw As New StreamWriter(XmlFileName)
       serializer.Serialize(sw, RssAddrs)
sw.Close()

   End Sub
   ...
   Collection 구현 관련 내용은 생략
   ...
End Class

추가한 메쏘드들은 Shared 키워드를 이용하여 객체를 생성하지 않아도 사용할 수 있도록 선언하고 있습니다. SaveToXml 메쏘드는 인자로 파일명과 RssAddressCollection을 받아 이를 해당 파일로 클래스의 직렬화 결과를 저장합니다. 그리고 LoadFromXml 메쏘드는 인자로 받은 파일로부터 역직렬화된 RssAddressCollection 클래스를 반환해 줍니다.

이들을 이용해서 손쉽게 객체를 XML 파일로 만들거나, 이미 저장되어 있는 XML 파일로부터 객체를 생성할 수 있습니다. 이렇게 만들어진 클래스들은 다음과 같은 방법으로 사용해볼 수 있습니다.

' RSS 주소들을 추가하고, XML 파일로 저장
Dim rssaddrs As New RssAddressCollection
rssaddrs.Add(New RssAddress("http://php.chol.com/~ppk314/tt/index.xml", "하늘이네 블로그"))
rssaddrs.Add(New RssAddress("http://namida.pe.kr/tt/index.xml", "나미다님의 블로그"))
RssAddressCollection.SaveToXml("MyRssAddressCollection.xml", rssaddrs)

' XML 파일로부터 객체를 생성
Dim loadedRssAddrs As RssAddressCollection = RssAddressCollection.LoadFromXml("MyRssAddressCollection.xml")

이제 RssReader 클래스를 함께 이용하여 RSS 주소들로부터 내용을 읽어와서 콘솔에 표시하는 간단한 프로그램을 제작해 보도록 하겠습니다. 테스트에 사용할 RSS 주소들은 앞의 RSS 주소들을 XML 파일로 저장하는 예제에서 생성한 MyRssAddressCollection.xml을 이용하도록 하겠습니다.

<리스트 2> RSS 파일들로부터 내용을 읽어 표시하는 프로그램

Dim rssAddrs As RssAddressCollection = RssAddressCollection.LoadFromXml("MyRssAddressCollection.xml")

Dim rssReader As New RSSReader
For addrIndex As Integer = 0 To rssAddrs.Count - 1
   Console.WriteLine(rssAddrs(addrIndex).BlogName + " 블로그의 글 목록입니다.")
   rssReader.XmlAddress = rssAddrs(addrIndex).RssURL
   rssReader.readItems()

   For itemIndex As Integer = 0 To rssReader.Items.Count - 1
       Console.WriteLine(rssReader.Items(itemIndex).PubDate.ToString("[MM:dd HH:mm] ") + rssReader.Items(itemIndex).Title)
   Next
Next

<리스트 2>를 실행하면 각각의 주소들로부터 RSS 파일을 불러와서 다음과 같이 결과를 표시해 주게 됩니다.

하늘이네 블로그 블로그의 글 목록입니다.
[11:09 11:25] 생각만으론 바뀌지 않는다.
... 생략 ...
나미다님의 블로그 블로그의 글 목록입니다.
[11:09 15:14] BRIDGET JONES: THE EDGE OF REASON
... 생략 ...

여기까지의 과정을 통해서 우리는 RSS 파일 주소들로부터 모든 정보를 얻어오는 과정까지 완성하게 되었습니다. RSS 수집 로봇 제작에 있어서 가장 바탕이 되는 처리 부분을 완성한 것입니다.

RSS의 내용을 정리하자
RSS 파일들로부터 블로그의 모든 내용들을 가져오는 과정까지 완성하게 되었습니다. 이제 이러한 블로그의 내용들을 하나로 정리하는 작업만을 남겨두고 있습니다.

정리한다는 것의 의미는 이렇게 볼 수 있습니다. 내용들 중에서 새롭게 업데이트된 내용과 이전의 내용들을 분류해내고, 각각의 데이터들을 각각 다른 기준으로 저장하는 것과 많은 블로그들의 각 글들의 남다른 기준은 무엇일까요? 그 글만이 가지는 유일한 정보 말입니다. 날짜나 제목도 있을 수 있겠지만 그것들은 다른 글이라고 하더라도 같을 수 있는 가능성이 있습니다. 하지만 웹에서 그 글을 표시하는 주소는 단 1개뿐이겠지요?

그리고 혹시라도 RSS 주소들의 리스트에 같은 RSS 파일이 여러 개가 저장되는 문제가 생기더라도 주소를 기준으로 저장한다면 같은 글이 2개로 저장되는 문제는 발생하지 않게 됩니다. 이러한 내용들을 바탕으로 RSS 파일의 내용들을 저장할 데이터베이스 테이블을 만들어보도록 하겠습니다.

<표 1> RSS 내용을 저장할 Rss_Datas 테이블

테이블의 구조는 RssItem과 비슷한 모양을 가지고 있습니다. 여기에 Link와 PubDate에 인덱스를 걸어주도록 하겠습니다. 차후에 주소를 기준으로 데이터를 자주 불러오고, 날짜순으로 정렬을 많이 시도할 예정이기 때문입니다. 여기에 차후 부가적인 내용들을 추가하면 되지만 이 시간에는 가장 기본적인 내용들을 기준으로 만들어 보았습니다.

이제 이렇게 만들어진 테이블에 간편히 데이터를 동기화할 수 있는 저장 프로시저 한 개를 만들어 보도록 하겠습니다. 이 저장프로시저는 인자 값으로 RssItem의 내용을 주면 데이터베이스와 동기화하게 됩니다. 즉 데이터베이스에 이미 존재하는 경우 내용을 업데이트하고, 존재하지 않는 경우 새로운 글을 추가하게 됩니다. 차후 동기화에 따른 몇 가지 조건들을 추가하고자 할 때에도 이 저장 프로시저를 통해 만들면 됩니다. 우선은 가장 기본적인 동기화 프로시저를 만들어보도록 합시다.

<리스트 3> RSS 정보를 데이터베이스와 동기화하는 저장 프로시저

CREATE PROCEDURE sp_Rss_DataSync
@Link varchar(200),
@PubDate smalldatetime,
@Title varchar(200),
@Author varchar(50),
@Description text
AS
   DECLARE @OldLink varchar(200)
   SELECT @OldLink = Link FROM Rss_Datas
   WHERE Link = @Link

   IF @OldLink IS NULL
       BEGIN
           INSERT INTO Rss_Datas(Link, GroupIdx, PubDate, Title, Author, Description)
           VALUES (@Link, @GroupIdx, @PubDate, @Title, @Author, @Description)
       END
   ELSE
       BEGIN
           UPDATE Rss_Datas SET
               PubDate = @PubDate,
               Title = @Title,
               Author = @Author,
               Description = @Description
           WHERE Link = @Link
       END
GO

해당 링크와 같은 글이 있는지를 체크하고 결과에 따라서 글을 저장하거나, 업데이트하는 간단한 쿼리 문장들을 사용한 저장 프로시저입니다. 차후에 동기화에 대한 여러 가지 기능들을 추가하고자 할 때 이 저장 프로시저만을 수정하면 됩니다.
간단한 예를 들면, 블로그에는 글을 쓰고 삭제하는 경우가 있습니다. 같은 내용인데 다시 정리해서 새롭게 쓰고자 하는 경우이지요.

이런 경우 같은 도메인이나 같은 블로그 주소이지만, 링크가 약간 달라집니다. 이런 경우 제목과 주소의 일부가 같은 경우 기존 글의 주소를 업데이트한다거나, 또는 시간대별로 동기화를 제한하는 기능 등을 들 수 있습니다. 이제 이렇게 만든 저장 프로시저를 쉽게 사용할 수 있는 RssItemSync 클래스를 만들어보도록 하겠습니다.

<리스트 4> RssItemSync 클래스

Imports System.Data.SqlClient

Public Class RssItemSync
   Private sqlCon As SqlConnection

   Public Sub New(ByVal ConnectionObject As SqlConnection)
       sqlCon = ConnectionObject
   End Sub

   Public Sub ItemSync(ByVal Item As RSSItem)
       Dim isClosed As Boolean = False

       If sqlCon.State = ConnectionState.Closed Then
           isClosed = True
           sqlCon.Open()
       End If

       Dim sqlCmd As New SqlCommand("sp_Rss_DataSync", sqlCon)
       With sqlCmd
           .CommandType = CommandType.StoredProcedure
           .CommandTimeout = 180
           .Parameters.Add(New SqlParameter("@Link", SqlDbType.VarChar)).Value = Item.Link
           .Parameters.Add(New SqlParameter("@PubDate", SqlDbType.SmallDateTime)).Value = Item.PubDate
           .Parameters.Add(New SqlParameter("@Title", SqlDbType.VarChar)).Value = Item.Title
           .Parameters.Add(New SqlParameter("@Author", SqlDbType.VarChar)).Value = Item.Author
           .Parameters.Add(New SqlParameter("@Description", SqlDbType.Text)).Value = Item.Description
       End With
       sqlCmd.ExecuteNonQuery()

       If isClosed Then
           sqlCon.Close()
       End If
   End Sub
End Class

우선 이 클래스는 생성자로 SqlConnection을 받습니다. 그리고 ItemSync 메쏘드에서는 연결 객체가 닫혀 있는 경우 열고 작업을 하고 다시 닫아주고, 열려 있다면 열린 상태로 유지하도록 코드를 만들었습니다. 이는 이 메쏘드가 데이터 동화에서 여러 번 반복 사용되므로 연결?닫기의 작업을 반복하지 않게 하기 위해서 간단하게 구현해 보았습니다.

이제 여기까지의 완성된 각각의 클래스들을 이용하여 RSS 파일들로부터 데이터베이스와 동기화하는 프로그램을 간단히 만들어 보도록 하겠습니다.

<리스트 5> RSS 정보를 읽어 데이터베이스와 동기화하는 RSS 수집 로봇

Dim rssAddrs As RssAddressCollection = RssAddressCollection.LoadFromXml("MyRssAddressCollection.xml")
Dim rssReader As New RSSReader
Dim sqlcon As New SqlClient.SqlConnection("[데이터베이스 연결 문자열]")
Dim ris As New RssItemSync(sqlcon)

Console.WriteLine(rssAddrs.Count + "개의 블로그의 싱크를 시작합니다.")
sqlcon.Open()
For addrIndex As Integer = 0 To rssAddrs.Count - 1
   Console.WriteLine(rssAddrs(addrIndex).BlogName + " 블로그를 싱크 시작")
   rssReader.XmlAddress = rssAddrs(addrIndex).RssURL
   rssReader.readItems()

For itemIndex As Integer = 0 To rssReader.Items.Count - 1
ris.ItemSync(rssReader.Items(itemIndex))
   Next
   Console.WriteLine(rssAddrs(addrIndex).BlogName + " 블로그 싱크 완료!")
Next
sqlcon.Close()
Console.WriteLine("전체 싱크가 완료되었습니다.")

여기에 시간대별로 반복해서 작업을 수행하게 하거나, MyRssAddressCollection.xml 파일을 메모장이 아닌 좀 더 쉽게 수정할 수 있는 방법만 만들어주고, 표현 계층을 멋지게 꾸미는 건 여러분들에게 맡기도록 하겠습니다. 멋진 RSS 수집 로봇을 완성해 주세요.

RSS 수집 로봇의 문제점
이번 강좌를 통해서 만들어본 RSS 수집 로봇은 RSS 파일을 읽고 관리하는 최소한의 기능들을 비교적 쉽게 구현하기 위해서 만들어진 프로그램입니다. 덕분에(?) 이 RSS 수집 로봇을 만들면서 여러 문제점들을 발견할 수 있었을 것입니다. 바로 RSS 파일을 일정 시간 간격으로 계속해서 읽는다면 네트워크 트래픽과 그것을 데이터베이스에 저장하는 과정에서 데이터베이스 처리량이 상당히 증가한다는 점인데요.

이러한 문제점들을 해결하기 위해서는 RSS 파일을 지금과 같이 RssTextReader 클래스를 이용하지 않고, HttpRequest, HttpResponse 클래스를 이용해서 RSS 파일을 읽는 방법을 사용하면 됩니다. 이 경우 파일을 요청할 때 HTTP 프로토콜에 있는 If-Modified-Since 필드를 사용하면 변경되지 않은 파일의 경우 데이터의 내용 대신에 헤더의 값만 넘어오게 되므로 트래픽은 물론 처리해야 할 데이터도 줄어들게 됩니다.

<그림1> RSS 내용을 저장할 Rss 수집로봇의 원리

그리고 RSS 파일의 주소가 몇 개 안 되는 지금 상태에서는 상관이 없지만, 100개가 넘어가는 경우 전체 RSS 파일을 싱크하는 시간은 점점 길어지게 됩니다. 하지만 자세히 살펴보면 데이터베이스를 처리하는 시간보다는 네트워크에서 파일을 불러오는 것에 상당한 시간이 소요되는 것을 볼 수 있습니다. 이 부분은 쓰레드를 이용하여 처리하면 더욱 빠른 속도로 싱크 작업을 할 수 있는 RSS 수집 로봇을 만들 수 있을 것으로 생각됩니다.

이밖에도 일정 시간 간격으로 올라오는, 흔히 ‘도배’라고 불리는 글들에 대해서는 싱크하지 않게 하는 방법 등 여러 가지 기능들에 대해서 생각해 보기 바랍니다. 여기까지 완성되었다면 ASP.NET을 이용하여 메타 사이트의 모습을 만드는 마지막 과정은 여러분에게 맡겨도 되겠지요?

메타 사이트 완성을 위해서 앞으로 해야 할 일들
[1] RSS 파일을 읽어오는 부분의 보완
[2] 싱크 기능을 멀티 쓰레드를 이용하여 처리하기
[3] 데이터베이스 싱크 기능의 강화(도배 방지 등의 기능)
[4] ASP.NET으로 웹 사이트 제작하기

더 멋진 메타 사이트를 꿈꾸다
아쉽게도 국내 3개 메타 사이트들의 기능은 모두 비슷합니다. RSS 파일을 읽고 그것을 표시해 주는 기본적인 기능들이죠. 메타 사이트의 등장은 오래 되었지만 아직도 메타 사이트는 걸음마 수준이라고 말하고 싶습니다. 이 말은 아직도 이 부분은 많은 실험과 도전 정신을 테스트해 볼 수 있는 미개척지란 말입니다.

이 강좌를 통해 메타 사이트를 만들기 위한 아주 기본적인 기술들을 익혔다면 이제 그것을 활용하여 지금까지 없었던 새로운 메타 사이트를 설계해 보는 것은 어떨까요? 저는 인터넷 강국 대한민국이 블로그에서도 강국이 되기를 바라며 오늘도 더 멋진 메타 사이트를 꿈꾸고 있습니다. 이제 여러분의 상상력을 보여주세요.@

* 이 기사는 ZDNet Korea의 제휴매체인 마이크로소프트웨어에 게재된 내용입니다.
2007/01/01 03:22 2007/01/01 03:22
TAG , ,