2013년 12월 17일 화요일

[Python] 파이썬으로 하는 웹 클라이언트 프로그래밍

자료출처: 한빛미디어
저자: 데이브 워너(Dave Warner), 역 전순재
웹 클라이언트 프로그래밍은 웹에서 정보를 찾게 도와주는 강력한 테크닉이다. 웹 클라이언트는 (웹 주소 앞에 붙은 http) 하이퍼 텍스트 전송 프로토콜[1]을 사용하여 웹 서버로부터 데이터를 열람하는 프로그램 모두를 말한다. 웹 브라우저는 클라이언트이다. 웹 크롤러(crawler) 역시 클라이언트이다. 이 프로그램은 웹을 자동적으로 돌아다니면서 정보를 수집한다. 웹 클라이언트를 사용하면 웹에서 다른 사람들이 제공하는 서비스들을 이용할 수 있으며 웹 사이트에 역동적인 특징들을 추가할 수도 있다.

개발자들이 사용하는 툴박스에는 자연스럽게 웹 클라이언트 프로그래밍이 들어있다. 펄(Perl) 열성팬들은 이미 수년간 웹 클라이언트 프로그래밍을 이용해 왔다. 이런 웹 클라이언트 프로그래밍은 파이썬으로 처리하면 편리성과 유연성이 더욱 높은 수준에 이른다. 여기에 필요한 모든 기능들은 모듈 3개로 해결할 수 있다. HTTPLIB, URLLIB, 그리고 더 새로워진 XMLRPCLIB가 바로 그것들이다. 진정한 파이썬 스타일로, 각 모듈은 기존의 모듈 위에 구축되어 애플리케이션에 견고하면서도 잘 디자인된 기반을 제공한다. XMLRPCLIB는 다음에 논하기로 하고 본 기사에서는 첫 번째 모듈 두 개에 대해 다루겠다.

우리가 볼 예제에서는 미어캣(Meerkat)을 사용하겠다. 이럴 경우 여러분이 필자와 같은 생각을 가지고 있다면 시간을 들여 오픈 소스 공동체의 동향과 개발 상황들을 추적해서 경쟁력을 확보할 것이다. 미어캣(Meerkat)은 이 작업을 훨씬 더 쉽게 만들어주는 도구이다. 미어켓은 오픈 와이어 서비스(open wire service)로서 오픈 소스 컴퓨팅과 관련된 방대한 양의 정보를 수집하고 정리한다. 미어캣의 브라우저 인터페이스는 유연하고 맞춤가능하지만, 웹 클라이언트 프로그래밍을 사용하면 우리는 이 정보를 훓어보고, 추출하는 것은 물론이고 나중에 사용하기 위해 오프 라인에 저장할 수도 있다. 우리는 먼저 HTTPLIB를 상호대화적으로 사용하여 미어켓에 접근할 것이다. 그리고 나서 URLLIB를 통해 미어켓의 개방 API(Meerkat's Open API)에 접근해 들어가 맞춤가능한 정보 수집도구를 만들어 볼 것이다.

HTTPLIB

HTTPLIB는 소켓(socket) 모듈을 살짝 감싼 포장자(wrapper)이다. 앞에서 언급한 3개의 라이브러리 중에서 웹 사이트에 접근할 때 가장 제어가 쉬운 모듈이 HTTPLIB이다. 그렇지만 과업을 달성하기 위해서는 추가 작업을 더 해야만 제대로 제어할 수 있다. http 통신규약(protocol)은 "정보를 저장하지 않기(stateless)" 때문이다. 따라서 이전의 요구는 전혀 기억하지 않는다. 각 요구에 대해 여러분은 HTTPLIB 객체를 새롭게 구성하여 웹 사이트에 접속해야 한다. 요구들은 웹 서버와 대화를 형성하고 웹 브라우저를 흉내낸다. 라엘 돈페스트(Rael Dornfest)의 개방 API를 사용해서 미어켓에 접속해 보자. 그리고 어떤 결과를 얻는지 살펴 보자. 대화는 일련의 서술문들을 구축함으로써 시작된다. 먼저 원하는 작업이 무엇인지 서술한다. 그리고 나서 웹 서버에게 여러분을 식별시킨다.
>>> import httplib
>>> host = 'www.oreillynet.com'
>>> h = httplib.HTTP(host)
>>> h.putrequest('GET', '/meerkat/?_fl=minimal')
>>> h.putheader('Host', host)
>>> h.putheader('User-agent', 'python-httplib')
>>> h.endheaders()
>>>
GET 요청은 어느 페이지를 받기 원하는지 서버에게 전달한다. 호스트 헤더(Host header)는 질의하고자 하는 도메인 이름을 서버에게 전달한다. 현대적인 서버들은 HTTP 1.1을 사용하여 여러 도메인을 같은 주소에서 사용할 수 있다. 만약 서버에게 어떤 도메인 이름을 원하는지 알려주지 않는다면, 여러분은 '302' 출력전환(redirection) 응답을 반환 코드로 얻게 될 것이다. 사용자-에이전트 헤더(User-agent header)는 서버에게 여러분이 어떤 종류의 클라이언트인지 알려 준다. 그래야만 서버는 여러분에게 보낼 수 있는 것과 없는 것이 무엇인지를 이해할 수 있기 때문이다. 이것이 웹 서버가 요구를 처리하기 위해 필요한 정보이다. 다음으로 여러분은 응답을 요구한다.
>>> returncode, returnmsg, headers = h.getreply()
>>> if returncode == 200:  #OK
...         f = h.getfile()
...         print f.read()
...
이렇게 하면 현재의 미어켓 페이지를 간략한 형태(minimal flavor)로 출력할 것이다. 응답 머리부와 응답 내용은 개별적으로 반환되며, 이렇게 하면 반환된 데이터의 문제를 해결하거나 해석하는데 모두 도움이 된다. 만약 응답 머리부를 보고 싶다면, print headers를 사용하면 된다.

HTTPLIB 모듈은 소켓 프로그래밍의 기계적인 면을 구별해준다. 게다가 HTTPLIB 모듈은 버퍼링을 위해 파일 객체를 사용하기 때문에 친숙하게 데이터 조작에 접근할 수 있지만 더욱 강력한 웹 클라이언트 애플리케이션을 위한 빌딩 블록이나 문제가 생긴 웹사이트와 상호 대화를 나누기 위한 빌딩 블록으로 더 잘 맞는다. HTTPLIB 모듈이 가지는 유용한 디버그 능력은 두 영역 모두에 도움을 준다. 객체 초기화 후에 어느 곳에서나 h.set_debuglevel(1) 메소드를 호출하면 HTTPLIB에 접근할 수 있다. (예제에서는 다음의 h = httplib.HTTP(host) 라인이다). 디버그 수준이 1에 설정되어 있으면 HTTPLIB 모듈은 getreply()을 호출한 결과들과 요청들을 화면에 응답할 것이다.

파이썬의 상호대화적인 특성 덕분에 즐겁게 HTTPLIB를 사용하여 웹 사이트를 분석할 수 있다. 이 모듈을 익히면 웹 사이트의 문제점들을 진단하기 위한 강력하고 유연한 도구를 가지게 되는 것이다. 또 시간을 가지고 HTTPLIB에 대한 소스를 살펴보라. 200줄도 안되는 코드임에도 불구하고, HTTPLIB를 사용하면 빠르고 쉽게 파이썬으로 소켓 프로그래밍을 시작할 수 있다.

URLLIB

URLLIB는 HTTPLIB에서 발견되는 기능에 대해 세련된 인터페이스를 제공한다. URLLIB 모듈은 웹 사이트를 분석하는 것보다는 데이터 그 자체를 찾아 내는데 가장 유용하게 사용된다. 다음 코드는 URLLIB를 사용해서 위와 똑같은 상호작용을 한다. (주의: 마지막 줄을 화면 출력을 위해 두 줄로 쪼개었지만, 여러분의 스크립트에서는 나누지 말 것!)
>>> import urllib
>>> u = urllib.urlopen
('http://www.oreillynet.com/meerkat/?_fl=minimal')
이것이 다이다! 한 줄로 미어켓(Meerkat)에 접근해서 데이터를 얻었으며, 그 데이터를 임시 저장소에 보관했다. 해더 정보에 접근하려면
>>> print u.headers
그리고 전체 파일을 보려면
>>>print u.read()
그러나 이것이 전부는 아니다. URLLIB는 HTTP뿐만 아니라 FTP, Gopher, 심지어는 같은 방식으로 지역 파일에도 접근할 수 있다. 이 모듈이 제공하는 많은 유틸리티 기능에는 url 해석하기, 문자열을 url-안전 형태로 코드전환(encode)하기, 그리고 한참 긴 데이터 전송 중에 진행 표시를 제공하기가 있다.

미어켓을 사용하는 예제 하나

한 그룹의 고객(client)들이 있는데 그들이 최신 리눅스 소식을 이메일로 꾸준히 받아보기를 바라고 있다고 상상해보자. 우리는 짧은 스크립트를 작성할 수 있다. URLLIB를 사용하여 이 정보를 Meerkat으로부터 얻는다. 링크의 목록을 구축한다. 그리고 그 링크들을 나중에 전송하기 위해 파일에 저장한다. 미어켓(Meerkat)의 저자인 라엘 돈페스트(Rael Dornfest)는 미어켓 API를 통해 우리 대신 대부분의 작업을 이미 완성해 놓았다. 남아있는 것은 요구를 구성하고, 링크를 해석하며, 나중에 전송하기 위해 그 결과를 저장하는 것 뿐이다.

단지 이것 때문에 사람들이 미어캣으로 전향하는 것일까? 이러한 "정보받기(passive)" 서비스를 제공하면 사람들은 그 정보를 한가할 때 볼 수 있다. 그리고 그 정보를 골라서 친숙한 형식(예를 들어 이메일)으로 저장할 수 있다. 월요일 아침에 메일함에서 뉴스들이 도착하기를 기다리기만 하면, 한 주간 "말려 올라간" 정보들을 하나도 놓치지 않을 것이다.

미어캣의 간략한 형식(minimal flavor)은 기사가 15개로 제한되므로 데이터를 놓칠 가능성을 줄이기 위해 우리는 스크립트를 (즉, Unix의 cron 작업 또는 NT의 AT 명령어를 사용하여) 매 시간 실행시킬 것이다. 여기에 우리가 사용할 url이 있다 (주의: 우리는 이 줄을 두 개의 줄로 나누어 화면에 표시했다. 이 URL을 사용한 결과는 여기에서 볼 수 있다).
http://www.oreillynet.com/meerkat/?p=5
&t=1HOUR&_fl=minimal&_de=0&_ca=0&_ch=0&_da=0
이 코드는 지난 한 시간 동안에 있었던 모든 리눅스 이야기들(profile=5)을 끌어 와서, 데이터를 간략한 형식(minimal flavor)으로 보여준다. 설명도 없고, 범주정보도 없으며, 채널 정보, 데이터 정보도 없다. 우리는 또한 정규 표현식 모듈의 도움을 받아 링크 정보를 추출하고 출력결과를 추가 모드로 열려진 파일 객체로 방향전환할 것이다.

결론

우리는 겨우 이 모듈들의 표면만을 건드려 보았다. 웹 클라이언트 작업에 사용할 수 있는 것 말고도 파이썬에는 다른 많은 네트워크 프로그래밍 모듈을 사용할 수 있다. 웹 클라이언트 프로그래밍은 특히 방대한 양의 계산표형 테이터를 다룰 때 유용하게 사용할 수 있다. 최근의 한 전자 데이터 교환(EDI) 프로젝트에서 우리는 웹 클라이언트 프로그래밍을 사용하여 거추장스러운 독점 소프트웨어 패키지를 우회하였다. 갱신된 가격 정보를 웹으로부터 직접 얻어서 데이터베이스에 집어 넣었다. 그렇게 함으로써 우리는 많은 시간을 절약하고 좌절감을 극복할 수 있었다.

웹 클라이언트 프로그래밍은 웹 사이트의 구조와 견고성을 테스트하는 데에도 유용하게 사용될 수 있다. 일반적으로는 죽은 링크들을 점검하는 방법으로 사용된다. 표준 파이썬 배포본에는 이것에 대한 완전한 예제가 딸려온다. 이 예제는 URLLIB에 기초한다. Tk-기반의 프론트 엔드[2] 모듈인 웹체커(Webchecker)는 파이썬 배포본의 tools 하부디렉토리 아래에서 찾아볼 수 있다. 또다른 파이썬 도구인 린봇(Linbot)은 URLLIB 모듈의 기능을 개선해 준다. 린봇으로 여러분은 웹 사이트의 문제를 모두 해결할 수 있다. 웹 사이트들이 점점 더 복잡해짐에 따라 웹 사이트의 질을 확인하기 위해서는 다른 웹 클라이언트 애플리케이션들이 필요하게 될 것이다.

웹 클라이언트 프로그래밍에는 함정이 하나 있다. 여러분의 프로그램은 페이지의 형식이 조금만 변경되어도 영향을 받는다. 반드시 웹 사이트가 오늘 데이터를 출력하는 방식이 내일도 그대로 유지된다고 장담할 수는 없다. 페이지의 형식이 바뀌면 프로그램도 바뀌어야 한다. 사람들이 XML에 그렇게 흥분하는 이유 중 하나가 바로 이것 때문이다. 웹에서 데이터에 태그를 붙여 의미를 주면 형식은 중요하지 않게 된다. XML 표준이 진화하고 범세계적으로 인정됨에 따라, 훨씬 더 쉽게 그리고 튼튼하게 XML 데이터를 처리하게 될 것이다.

우리가 여기에서 다룬 도구들에는 약간의 제한이 있다. HTTPLIB 모듈과 URLLIB모듈은 클라이언트-기반 작업에는 탁월하지만 오직 한 번에 한 개의 요청만을 처리할 수 있기 때문에 서버를 구축하는데 사용해서는 안된다. 비동기적인 처리방법을 제공하기 위해 샘 러싱(Sam Rushing)은 멋진 도구모음을 구축하였다. 이 도구모음은 asyncore.py 를 포함하여 표준 파이썬 배포본에 딸려 온다. 이 접근법을 사용하는 가장 강력한 예제는 조프(ZOPE)이다. 조프는 애플리케이션 서버로서 샘 러싱(Sam Rushing)의 메듀사 엔진(Medusa engine)을 사용하여 구축한 빠른 http 서버를 포함하고 있다.

다음 기사에서는 XML과 웹 클라이언트 프로그래밍을 어떻게 XMLRPCLIB 모듈에 결합하는지에 대해 논의해볼 생각이다. XML을 사용하면 미어켓(Meerkat) API로부터 더욱 많은 기능을 짜낼 수 있다.

각주
[1] Hyper Text Transfer Protocol
[2] front end: 프론트 엔드
    예) GUI는 front end 이며 구현된 기능들은 back end이다.

데이브 워너(Dave Warner)는 Federal Data Corporation사의 선임 프로그래머이자 데이터베이스 관리자(DBA)이다. 그는 P자로 시작하는 언어(Python, Perl, PowerBuilder)로 관계형 데이터베이스에 접근하는 방법을 연구하고 있다.

댓글 없음:

댓글 쓰기