IT 이야기2009. 1. 20. 16:51

앞서 말했듯이 라이브러리를 통한 소규모 재사용은 아주 성공적이었다.

만약 여러 프로젝트와 다양한 도메인 사이에 비슷한 문제가 충분히 많이 존재한다면 좀 더 큰 규모에서도 성공적일거라 낙관하였다. 그러나 많은 사람들이 의심- 앞서 말했듯이 규모의 증가는 전혀 다른 문제를 야기시킨다 - 하는 바와 같이, 소프트웨어의 다양성으로 인해 프로젝트와 도메인에 상관없이 공통되는 기능과 작업으로 일반화할수 있는 부분이 많지 않다면 소규모의 재사용과 대규모의 재사용은 다른 문제가 된다.

대규모 재사용을 지지하는 사람들은 대규모 재사용이 널리 퍼지지 못한 이유를 사람들의 무지, 혹은 다른사람의 작업을 인정하지 않는 NIH 신드롬 때문이라고 생각하곤 한다. 따라서 이들에게 대규모 재사용은 기술의 문제가 아니라 의지와 정책의 문제이며 경영진의 관리를 통해 이런 문제를 타개해야 한다고 생각한다. 

아무튼 사람들은 좀 더 큰 규모의 대규모 재사용을 시도하였다. 이러한 방식을 관계있는 여러 라이브러를 묶어서 컴포넌트화 하여 이들간의 조립으로 소프트웨어를 구축 할 수 있다는 개념을 컴포넌트 지향 프로그래밍(CBD)라고 한다. 그러나 이는 본래 의미부터 약점을 가지고 있다. 관계있는 여러 라이브러를 묶을때.. "관계 있는" 이라는 말은 어디까지나 주관적인 판단이며 그러한 판단은 아주 주관적인 상황에서 내려지게 된다. 즉 현재 자신의 도메인과 프로젝트를 초월한 "관계 있는" 이라는 것은 불가능 까지는 모르겠지만 아주아주 어렵다는 것을 뜻한다.

사실 대규모 재사용 낙관론파는 인정하지 않지만 모든 프로젝트와 도메인 혹은 대부분의 프로젝트와 도메인에 공통적인 무언가를 찾는 것은 아주 어렵고 그 비율도 생각보다 높지 않다. 이는 논리적으로는 불가능하지는 않지만 실제 프로그래밍을 하고 있는 사람은 대부분 인정하는 현실상의 문제이다.



어쟀든 소스의 재사용을 위해 초기 라이브러리가 탄생했고 그를 좀더 대규모로 확장하기 위해 CBD가 나타난 시기와 비슷한 시기에 재사용의 성배를 찾던 탐구자들은 새로운 의미의 재사용의 해석을 도입하게 된다. 대규모 재사용에서 도메인의 영향을 피할수 없다면 도메인에는 단순히 소스의 공통점뿐 아니라 다른 부분의 공통점도 찾을 수 있다. 즉 구조의 재사용의 문제이다. 예컨데 Web이라는 도메인에서 클라이언트가 request를 던지고 response를 받는 과정에 있어서 Web이라는 기술 도메인 하에서 많은 구조적 동일성을 발견할수 있다.

프레임워크가 프로그래머들에게 가장 일상적으로 들리기 시작한것은 이러한 웹 프레임워크를 통해서였다. 프레임워크는 CBD나 이전의 라이브러리와는 다르게 소스 자체의 재사용보다는 구조적 재사용을 추구하였고 이는 CBD보다는 훨씬 더 큰 반향을 불러 일으켰다. 개발자 구인 조건이 특정 프레임워크를 사용 가능하냐는 여부였으니 더 말해 무엇하랴. 그리고 이런 프레임워크에 대한 지나친 기대와 포장은 자신이 무엇을 개발하는지도 모른채 xml 파일의 바다에 헤매이게 만드는 단점을 나았다.



라이브러리 단위의 재사용이 규모가 커지면서 CBD와 Framework로 다른 길을 선택하였지만 성배 추구자들은 끊임없이 의미를 탐구하였고 좀더 다른 의미의 재사용을 꿈꾸었다. 이 결과로 나온게 서비스 레벨의 재사용 즉 SOA 이다. 소스레벨도 아니고 구조적 레벨도 아닌 더 큰단위인 서비스 레벨에서 재사용을 추구하는 SOA는 그자 체가 재사용의 성배 추구 과정에서 필연적인 결과이다.

그러나 SOA의 미래가 어두운 점은 서비스가 너무 많다는데 있다. MFC의 함수보다 많은 서비스 중에서 내가 원하는 서비스들을 골라내기란 - 게다가 MFC와는 달리 그 모든 서비스의 상당부분은 매우 저품질이다. - 수만 픽셀에서 필요한 1000픽셀만 찾아 조각맞추기 하는것만큼이나 어렵다.(매쉬업은 아직 유틸리티 성격이 강하니 제외하자) 결국 이전의 CBD처럼 관련있는 것들을 묶어주는 무언가가 필요하겠지만 이는 개별 서비스 주체들의 동의를 이끌어내야하는 비기술적인 문제에 봉착하게 된다.



Posted by bleujin
IT 이야기2009. 1. 20. 15:12

"성배"는 단순히 종교의 문제를 벗어나 인디아나 존스나 트레져 헌터, 최근의 다빈치 코드에 이르기까지 영화나 소설에까지 흔히 소재로 체택되곤 한다. 성배는 예수가 최후의 만찬에 사용했다는 은으로 만든 잔을 뜻한다. 영화“다빈치 코드”의 저자는 성배는 인디아나 존스에서 나온것처럼 하나의 보물로서의 찻잔이 아니라 성배가 예수와 막달레나 사이에서 태어난 혈통을 가리킨다고 주장한다.

머 영화이야기를 하려는건 아니지만 IT업계에도 성배를 찾아헤매는 트레져 헌터처럼 끝없이 갈구하는 소재가 있다. 바로 "재사용"이다. 20년전의 객체지향 10년전의 패턴이나 CBD 그리고 그나마 최근인 프레임워크나 SOA에 이르기까지 주제에 상관없이 항상 그 논란의 핵심에는 "재사용"이라는 성배가 있었다.

사실 재사용이라는 개념은 소프트웨어라는 개념이 존재할때부터 파생된 오래된 말이다. 1950년 IBM 메인프레임 시대에 - 소프트웨어는 하드웨어에 딸려나오는 엑세서리 쯤으로 생각되던 그 시기에 이미 Share라는 공유 라이브러리를 제작하던 사용자 조직이 있었다.

갑자기 이 얘기를 왜 하냐면 오늘날의 재사용의 의미가 사실 매우 오래된 아이디어이며 현재의 재사용의 성공과 실패를 인식하는데 있어 아주 중요하기 때문이다.

앞서 말했듯 처음 재사용이라는 단어가 사용된건 1950년이며 이미 Ada라는 언어부터 구조적 프로그래밍이라는 패러다임이 이미 존재했다. 당시의 주류 언어이던 어셈블리어가 코드의 라인수가 점차 커짐에 따라 동일하거나 비슷한 코드를 함수와 라이브러리 단위로 묶어서 재사용의 시초라면 이후 SOA까지 재사용은 항상 그 중심에 있었다.

초기에 라이브러리 함수까지는 재사용에 있어서 그 찬란한 미래를 보장해 주는듯 했다. "바퀴를 재 발명할 필요는 없다"라는 구호를 가지고 객체지향이 나올때까지도 그 미래는 현실이 되는듯 했다. 하지만 CBD에서부터 먼가 삐걱거리는 조짐이 일어났다. 전병선씨가 그의 책에 상.상.한 CBD 미래는 10년전이나 지금이나 요원해 보인다.

작은 규모의 재사용이 아주 효과적이었다고 해서 대규모의 재사용도 충분히 효율적이라고 생각하는 것은 억지가 되버렸다. 규모의 문제는 무시해도 좋을만큼 단순한 문제가 아니었던 것이다. 어릴적에 난 과학 기술의 발전으로 40m의 크기가 된 울트라맨이나 마징기 제트 - 비록 그게 일본문화이더라도 - 만화를 보고 자랐다. 지금 보면 그 만화들은 만화라는 상상력을 벗기면 형편없는 오류를 저지르고 있다. 짧게 말하면 발의 평면은 2차원인데 부피가 3차원으로 자라면 ^2과 ^3의 차이만큼 발에는 추가적인 압력이 가해지고 어느 순간에는 그 차이가 견딜수 있는 수치를 넘어가게 된다. 예컨데 산양과 코끼리의 다리는 그 크기의 차이만큼이 아니라 그 부피만큼의 비율 이상이 유지되야 지상을 걸어다닐 수 있게된다. (발의 평면 크기가 ^2이 아니라 ^3으로 증가해야 되고 따라서 발의 부피는 ^3이 아니라 ^4가 되어야 한다.) 단순히 발의 크기뿐 아니라 들숨과 날숨의 문제로 인한 허파의 크기 등 수많은 문제가 있다.


이야기가 많이 빠졌지만 소규모 재사용과 대규모의 재사용은 전혀 비슷한 난이도가 아니었고 따라서 그 효율성도 달성하기 어렵다. 얼마나 어려운가 하면 O의 n승 만큼 어려워진다. 이는 단순히 가능 불가능의 문제가 아니라 효율성의 문제이기 때문이다. 일반적으로 공통 코드는 보통의 코드에 비해 3배의 노력이 든다는 것이 정설이다. 라이브러리 단위의 작은 코드일때는 이 정도도 효율적이라고 할 수 있지만 2배 정도의 긴 코드를 작성해야 할때 공통 코드는 단순히 6배가 아니라 9배 이상이라고 했을때는 문제는 전혀 달라지는 것이다.

전병선씨나 대규모 재사용의 지지자들은 이미 만들어 놓은 컴포넌트들을 조립하여 마치 레고블럭을 쌓는 방식이 프로그래밍의 미래라고 생각하지만 사실 그건 이룰수 없는 꿈과 같다고 생각한다.. 컴포넌트 지향의 성과가 없는 것은 아니지만 그보다 훨씬 더 빠르게 코드의 크기와 시간이 갈수록 다양해지는 소프트웨어의 요구사항들을 생각해 볼때 이는 자동차와 로켓의 속도 차이만큼 그 거리는 점점 멀어지고 있기 때문이다.

'IT 이야기' 카테고리의 다른 글

좋은 프로그램과 위대한 프로그램  (0) 2009.02.03
재사용이라는 성배 2  (0) 2009.01.20
멘델의 우열의 법칙  (0) 2009.01.15
좋은 프로그래밍과 훌륭한 프로그래밍  (0) 2009.01.13
타협할 수 있나요?  (0) 2009.01.09
Posted by bleujin

굳이 메쉬업 프로그래밍을 하지 않더라도 하다보면 인터넷에서 자료를 쭉 긁어오고 싶을때가 있다.
이건 사실은 신문사 만화 사이트를 일일이 클릭해가면서 - 게다가 그 수많은 광고를 참으며 - 보느니
로컬에 그림만 다운로드 받아봐야지 하고 후다닥 만들었다-ㅅ-


이 작업을 하려면 먼저 bleujin Framework core의 jar 파일을 아래 포스팅에서 다운로드 받고..


위 3개의 jar가 추가적으로 필요하다. 예전에 작성할때 다운로드 받은거라 최근에는 버전업이 됐겠지만 그냥 쓴다-ㅅ-
아마 common-io랑 common-lang도 필요하겠지만 그건 그냥 apache 에서 다운로드 추천-ㅅ-
(오늘까지 방문자가 한명도 없으니 다소 무책임해도 상관없으리라.. 쿨럭)

Framework에는 html Parsing에 관련된 - jericho의 소스에 Facade 패턴을 사용해서 간단하게 만들 수 있었다. - 부분만 있어서 먼저 인터넷에 접속해서 InputStream을 받아오는 로직을 작성해야 한다.



public class Spider {

 private Logger log = LogBroker.getLogger(Spider.class) ;
 
 public Reader getPageContent(String httpURL) throws HttpException, IOException {
  String content = IOUtils.toString(getInputStream(httpURL), "EUC-KR") ;
  return new StringReader(content) ;
 }

 public InputStream getInputStream(String httpURL) throws HttpException, IOException {
  HttpClient httpclient = new HttpClient();
  GetMethod httpget = new GetMethod(httpURL);
  try {

   httpclient.executeMethod(httpget);
   log.info("recevied data : " + httpURL) ;
   
   InputStream input = httpget.getResponseBodyAsStream() ;
   InputStream result = new ByteArrayInputStream(IOUtils.toByteArray(input)) ;
   input.close() ;
   return result ;
   
  } catch (Exception ex) {
   log.warning(ex.getMessage()) ;
   throw new HttpException(ex.getMessage(), ex) ;
  } finally {
   httpget.releaseConnection() ;
  }
 }
}

EUC-KR의 상수 부분이 걸리긴 하지만 머 대충 만들고 넘어가자-ㅅ-(사실 사이트를 제대로 만들었다면 EUC-KR은 요즘의 국제화 시대에 맞지 않는 인코딩방법이다. )

사용은 대충 아래와 같이 한다.

 public void testSportChosun() throws Exception {
  String httpURL = "http://manhwa.sportschosun.com/enter/cartoon/juyu/cartoon_juyu2.asp?num=138&title=juyu&Direct=Next" ;
  Spider s = new Spider() ;
  Reader content = s.getPageContent(httpURL) ;
  HTag tag = HtmlParser.parse(content) ;
  
  HTag img = tag.findElementBy(IMG, "src", "http://manhwa.sportschosun.com/enter/cartoon/juyu/image_cartoons/20071119y_233.gif") ;
  System.out.println(img.toString());
  System.out.println(img.getPath());
  
  
  String imgPath = img.getAttributeValue("src") ;
  System.out.println(imgPath);
  
  content.close() ;
 }


 public void testSave() throws Exception {

  int current = 100 ;
  Spider s = new Spider() ;
  for (int i = 1; i <= current; i++) {
   String path = "http://manhwa.sportschosun.com/enter/cartoon/juyu/cartoon_juyu2.asp?num=" + i + "&title=juyu&Direct=Next" ;
   Reader content = s.getPageContent(path) ;
   HTag tag = HtmlParser.parse(content) ;
   HTag img = tag.getChild("body[0]/table[4]/tr[0]/td[2]/table[1]/tr[8]/td[0]/img[0]") ; // /html/body/table/tr/td/table/tr/td/img
   String imgSrc = img.getAttributeValue("src");
   
   FileOutputStream output = new FileOutputStream(new File("c:/temp/" + StringUtil.substringAfterLast(imgSrc, "/")));
   IOUtils.copy(s.getInputStream(imgSrc), output) ;
   output.close() ;
  }
 }


HTag가 클래스가 Facade 클래스인데 이런저런 다양한 파싱에 관련된 메소드들을 모두 가지고 있다.

이를테면 getChild("body/table[4]/tr[0]/td[2]/table[1]/tr[8]/td[0]/img[0]") 는
body안에 5번째 table 태그안에 첫번째 tr안에 3번재 td안에 2번째 table안에 9번째 tr안에 첫번째 td안에 첫번째 img Tag를 가져오라는 뜻이다 -ㅅ-;;


만화그림 다운로드 받는데 쓰다가.
나중에 네이버나 다음에 있는 상장된 기업정보 페이지를 모두 긁어서 데이타베이스 구축하는데도 사용했다.


야후는 일정시간에 많은 GET이 날라가면 자동으로 해당 아이피 Block을 시켜버린다=ㅅ=
외국 기업이라 그런지 그런 기본적인 것에 충실하다.



'Framework > 아키텍쳐 일반' 카테고리의 다른 글

Class Design  (0) 2009.03.07
나쁜 디자인의 징후  (0) 2009.02.22
Design Principle - SRP  (0) 2009.02.22
Method Design  (0) 2009.02.11
몇가지 프로그래밍 조언  (0) 2009.02.10
Posted by bleujin