OpenVPN 을 통한 VPN 구현
  -서버 : 리눅스
  -클라이언트 : Windows XP, Linux

0. 내가 원한는 것.
 1) 내가 어디에 있든 사설망에 접속할 수 있어야 한다.
    - 사설망 모든 자원 활용(사설의 모든 IP, 모든 PORT)
    - 요즘 ISP에서는 특정 포트를 막는다(예) samba, MS-SQL 포트)
 2) 사설망은 인터넷을 통해도 안전해야 한다. (SSL 암호화 제공)
 3) 사설망의 다른 PC(클라이언트)들과 통신이 가능해야 한다.
 4) 접속에 있어 ID/PASS인증을 거친다. (인증서 뿐만 아니라)
 5) 어디에 있든 사설망의 게이트웨이를 통해 인터넷에 접속한다.
    (외부에 알려지는건 내부 게이트웨이 IP가 보인다.)



1. 시스템 구성
  한대의 VPN서버에 여러대의 VPN 클라이언트들이 붙는 형태
  각 VPN클라이언트 끼리 통신 또한 가능해야 한다.
  -서버 : 리눅스
  -클라이언트 : Windows XP, Linux (RedHat 9.0)
  -네트웍 : 10.1.1.0 (10.1.1.1 ~ 10.1.1.255)
  -사용포트 : 1194/UDP

2. OpenVPN설치(서버)

 ## lzo설치 ( 실시간 압축 전송 라이브러리)
 #http://dag.wieers.com/packages/lzo/ 에서 적당한 버전의 rpm을 받는다.
 # 난 SULinux 1.0 이니 , RHEL4 버전을 받는다.
 wget http://dag.wieers.com/packages/lzo/lzo-1.08-4.2.el4.rf.i386.rpm
 wget http://dag.wieers.com/packages/lzo/lzo-devel-1.08-4.2.el4.rf.i386.rpm
 rpm -Uvh lzo*

 ## open vpn 받아서 rpm 만들고 설치
 wget http://openvpn.net/release/openvpn-2.0.7.tar.gz
 rpmbuild -tb openvpn-2.0.7.tar.gz
 rpm -Uvh  /usr/src/redhat/RPMS/i386/openvpn-2.0.7-1.i386.rpm

### 설치되는 파일 및 디렉토리들
  /etc/openvpn
  /etc/rc.d/init.d/openvpn
  /usr/sbin/openvpn
  /usr/share/doc/openvpn-2.0.7/*
  /usr/share/man/man8/openvpn.8.gz
  /usr/share/openvpn
  /usr/share/openvpn/plugin/*
###############################


3. 인증서 생성 - 서버
  인증성 생성은 필수이다. 다음과 같이 생성한다.

 1) CA 생성 (상위 인증기관)
   cd /usr/share/doc/openvpn-2.0.7/easy-rsa/
   #vars 파일을 열어서 맨 마지막 줄을 수정한다.!!
     export KEY_COUNTRY=KR
     export KEY_PROVINCE=NA
     export KEY_CITY=BUSAN
     export KEY_ORG="superuser.co.kr"
     export KEY_EMAIL="doly@suidc.com"
  ####################################
  #인증서 생성시 마다 넣는게 귀찮아서 이렇게 정의 하는 것이니 하지 않아도 무관^^;
  . ./vars
  ## 위 명령은 , vars내용을 include한다는 명령이다.
  ./clean-all
  ## 기존에 생성된 것이 있으면 모두 삭제한다.
  ./build-ca
  ## CA 인증서를 생성한다.
  ## 이렇게하면 keys라는 폴더에 ca.key(개인키), ca.crt(공개인증서)가 생성된것을 확인한다.
  ## ca.crt파일은 모든 클라이언트에 배포. ca.key는 서버만 가지고 있음.

 2) 서버키 생성 (서버에 사용될 인증서 및 개인키)
   ./build-key-server server
  ## 뭐 많이 물어보는데 대충 대답하고 , y를 누른다.
  # keys 디렉토리에 server.crt  server.key 등이 생긴것을 확인할수 있다.
  # 이 키들은 CA에 의해 사인된 인증서이다.
  # server.crt, server.key 모두 서버에만 사용

 3) 클라이언트키 생성 (클라이언트에 사용될 인증서)
   ./build-key client
  ## 뭐 많이 물어보는데 대충 대답하고 , y를 누른다.
  # keys 디렉토리에 server.csr server.crt  server.key 등이 생긴것을 확인할수 있다.
  # 중요한건. Common Name은 client여야 한다.!!
  # keys 디렉토리에 client.crt client.key 를 볼 수 있다.
  # 이 키들은 CA에 의해 사인된 인증서이다.
  # client.key, client.crt 모두 클라이언트에만 사용됨.

 4) Diffie Hellman 파라메터 생성(암호화에 필요한 놈)
  ./build-dh
  # keys디렉토리에 dh1024.pem 파일이 생긴것을 확인할 수 있다.
  # dh1024.pem은 서버에만 가지고 있는다.

 5) 클라이 언트용 파일 복사 및 보관
    mkdir -p /root/client-keys
    cp keys/ca.crt keys/client.* /root/client-keys
    cd /root
    zip client-keys.zip client-keys/*



4. 설정파일(server.conf)파일 복사 및 편집 - 서버
 1) 설정파일 및 키 복사
    cd /usr/share/doc/openvpn-2.0.7/
    cp sample-config-files/server.conf /etc/openvpn/
    cp easy-rsa/keys/server.* /etc/openvpn/
    cp easy-rsa/keys/dh1024.pem /etc/openvpn/   
    cp easy-rsa/keys/ca.* /etc/openvpn/
    
 2) 설정파일 편집.(/etc/openvpn/server.conf)
    server 10.1.1.0 255.255.255.0
    client-to-client
    duplicate-cn
    max-clients 100
    plugin /usr/share/openvpn/plugin/lib/openvpn-auth-pam.so login

   ## 설명
   # sever 네트웍 설정은 10.1.1.0으로 한다.
   # client-to-client : 클라이언트 끼리 통신 가능하게
   # duplicate-cn : client인증서 하나로 여러대의 PC에서 사용할 수 있게한다.
   # max-clients 100 : 연결수를 100으로 제한한다.
   # plugin .... : user/pass인증을 받는다. (시스템 계정)



 3) G/W로 VPN서버를 쓰기 때문에 인터넷 공유 설정.
    echo 'iptables -t nat -A POSTROUTING -s 10.1.1.0/24 -o eth0 -j MASQUERADE' >> /etc/rc.d/rc.local
    iptables -t nat -A POSTROUTING -s 10.1.1.0/24 -o eth0 -j MASQUERADE
    iptables -t nat -L



5. 클라이언트 설치 및 설정(Linux RH9)
  # lzo 설치
  wget http://dag.wieers.com/packages/lzo/lzo-1.08-4.0.rh9.rf.i386.rpm
  wget http://dag.wieers.com/packages/lzo/lzo-devel-1.08-4.0.rh9.rf.i386.rpm
  rpm -Uvh lzo-*
 # openvpn 받아서 설치
 wget http://openvpn.net/release/openvpn-2.0.7.tar.gz
 rpmbuild -tb openvpn-2.0.7.tar.gz
 rpm -Uvh  /usr/src/redhat/RPMS/i386/openvpn-2.0.7-1.i386.rpm
 # 설정파일 복사 및 설정
 cp  /usr/share/doc/openvpn-2.0.7/sample-config-files/client.conf /etc/openvpn/
 cd /etc/openvpn
 wget http://su021.suidc.com/~mons/client-keys.zip
 unzip client-keys.zip
 mv client-keys/* .
 rm -rf client-keys*
 ## 설정파일 편집
  remote 222.97.189.21 1194
  auth-user-pass
 # 위 두줄 추가!!
 /etc/rc.d/init.d/openvpn start
 이렇게 시작하면, user/ pass 를 묻는다.!!
 예의상ㅇ!! ping 10.1.1.1 을 해 본다.!!! -- OK!



6. Windows XP에 설치!!
http://www.openvpn.se/files/install_packages/openvpn-2.0.7-gui-1.0.3-install.exe
위 파일을 받아서 설치!
  http://su021.suidc.com/~mons/vpn-client-win.zip
 이 키를 받아서.
 시작 -> 프로그램 -> OpenVPN -> Open VPN configuration file directory
 을 열고 거기에 복사한다.!

공개SW의 신뢰성 확보를 위해서 해야할 일
-소프트웨어의 안전성 확보


인기 많은 오픈소스 SW에는 버그가 적다?(2006.03. zdnet)

오픈소스 소프트웨어 중에서 가장 인기가 가장 높은 것이 버그의 수도 가장 적은 것으로 드러났다. 이는 소프트웨어의 안전을 확보하기 위해 미국 정부가 후원한 대책의 첫 번째 결과물에 의해서 밝혀졌다.
 
코드 분석 툴 업체인 커버리티(Coverity)의 최근 발표에 따르면 ‘LAMP’이라는 오픈 소스 스택을 조사한 결과 다른 32개 오픈소스 프로젝트의 기준에 비해 버그 밀도가 적은 것으로 나타났다. 버그 밀도란 일정한 행수의 프로그램 코드에 포함되는 버그의 수를 나타내는 것.

미국의 국토안전보장국은 지난 1월에 스탠포드 대학, 커버리티, 시만텍 등 3곳에 124만 달러의 자금 지원을 발표했다. 이들 3곳은 이 자금을 사용해 오픈소스 소프트웨어에 있는 보안 버그 탐색이나 커버리티에서 개발한 상용 소소 코드 분석 툴의 강화를 진행하고 있다. 이 자금 지원은 ‘오픈소스 강화 프로젝트(Open Source Hardening Project)’라는 3개년 계획의 일부이다.

LAMP란 리눅스 OS, 웹 서버의 아파치, 데이터베이스의 MySQL, PHP, 펄Perl, 파이톤 등의 스크립팅 언어를 가리킨다. LAMP은 주류의 기업 컴퓨팅 분야에 진출하고 있어 자바나 MS닷넷과 경쟁하는 존재가 되고 있다.

이번 분석에서는 32개의 오픈소스 프로젝트에서 1750만행 이상의 코드를 선택해 자세하게 확인했다. 그 결과, 평균 코드 1000행에서 0.434건의 버그가 발견되었다고 커버리티는 밝혔다. 이에 비해 LAMP 스택은 코드 1000행당 버그수가 평균 0.29건이다.

단 주의해야 점이 한가지 있다. LAMP 스택의 컴포넌트 중에서도 인기가 높은 프로그램 언어인 PHP만은 버그 밀도가 기준보다 높았다고 커버리티측은 전했다.

커버리티의 조사 결과에 따르면 이번에 조사한 다른 오픈소스 프로젝트 중에서는 아만다(Amanda)의 백업 툴이 코드 1000행당 버그수가 가장 많아, 버그 밀도는 1.237이었다. 가장 적은 것은 XMMS 오디오 플레이어로 코드 1000행당 버그수는 0.051건이었다.
 
발견된 버그수 면에서는 리눅스/유닉스용 그래픽 인터페이스 소프트웨어인 ‘X’에서 1681건의 버그가, ‘XMMS 오디오 플레이어’에서는 불과 6개의 버그가 발견되었다.

커버리티는 소프트웨어 코드 중에서 가장 중대한 보안 취약성이나 코딩 실수 가운데 40종류를 선택해 분석의 대상으로 삼았다. 커버리티는 발견된 취약성의 자세한 내용에 대해서는 공개하지 않았다.

연방 정부의 지원하에서 스탠포드 대학과 커버리티는 인기가 있는 오픈소스 프로젝트에 제공되는 코드를 일일 단위로 검사하는 시스템을 구축했다. 커버리티는 이 시스템에서 얻은 버그 데이터베이스를 개발자들에게 제공해 취약성 수정에 필요한 세부사항을 파악할 수 있게 할 계획이라고 밝혔다.

OpenVPN을 사용을 위한 미니 하우투(한소프트리눅스 오픈에디션 3)

I. 개요

본 문서는 OpenVPN 서버(한소프트리눅스 오픈에디션3), OpenVPN 클라이언트(윈도우 XP SP2)를 구성하여 공개SW기반의 VPN 기능을 사용하기위한 문서이다.

VPN을 이용하면 패킷을 암호화하는 것뿐만 아니라 파이어월을 사용할 때도 매우 편리하다. 외국  출장 등을 이유로 외부에서 접속하더라도 VPN을 통하면 항시 고정된 IP를 사용할 수 있기 때문이다. 따라서 파이어월에서는 접속을 허용해야 할 사용자가 유동 IP를 사용하더라도 단 한 개의 UDP 포트만 허용하면 되기 때문에 보안과 편리함 모두를 만족시킬 수 있다.

OpenVPN 특징)
-OpenVPN은 하나의 UDP 포트를 통해 모든 트래픽을 터널링할 수 있다. 즉 웹 접속(HTTP)을 하거나 DNS 질의를 할 때(UDP/53), ping(ICMP)을 날려도 중간에 패킷을 캡처하면 500/UDP를 통해 전송되는 것처럼 보이게 한다.
-안전한 VPN 통신을 위해 별도의 모듈이 필요없이 널리 사용하고 있는 OpenSSL에서 지원하는 강력한 암호화와 인증 기능 등을 그대로 이용할 수 있다.
-OpenVPN은 시스템 내에서 별도의 데몬 형태로 작동하기 때문에 IPsec 기반의 VPN 프로그램처럼 복잡한 커널 패치나 커널 모듈이 필요하지 않으며, 설치 방법도 간단하다.
-모든 패킷이 VPN을 통해 터널링되고 압축 혹은 암호화됨에도 불구하고 시스템에 부하를 유발하지 않으며, 속도도 빠르다.


II. OpenVPN 서버 설치

설치 전 설치에 필요한 라이브러리를 확인하여, 없는 경우 설치해 준다
OpenSSL(http://www.openssl.org/)
LZO(http://www.oberhumer.com/opensource/lzo/)

1. 소스다운로드(http://openvpn.net/)
[root@localhost src]# wget http://openvpn.net/release/openvpn-2.0.9.tar.gz

2. RPM Build
[root@localhost src]# rpmbuild -tb openvpn-2.0.9.tar.gz

3. 빌드 확인 및 설치
[root@localhost src]# cd /usr/src/Haansoft/RPMS/i386/
[root@localhost i386]# ls
openvpn-2.0.9-1.i386.rpm

[root@localhost i386]# rpm -Uvh openvpn-2.0.9-1.i386.rpm
준비 중...               ##                                          (100%)
#################                           (100%)

4. 스크립트를 이용한 인증키 생성
[root@localhost i386]# cd /usr/share/doc/openvpn-2.0.9/easy-rsa/
[root@localhost easy-rsa]# . ./vars
NOTE: when you run ./clean-all, I will be doing a rm -rf on /usr/share/doc/openvpn-2.0.9/easy-rsa/keys
[root@localhost easy-rsa]# ./clean-all
[root@localhost easy-rsa]# ./build-ca

Generating a 1024 bit RSA private key
................++++++
-----
Country Name (2 letter code) [KR]:
State or Province Name (full name) [NA]:
Locality Name (eg, city) [SEOUL]:
Organization Name (eg, company) [OpenVPN-OSTSC30]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:ostsc30
Email Address [localhost@locadomain]:

※ Common Name 을 정확히 적어준다

5. 서버 인증키 생성
[root@localhost easy-rsa]# ./build-key-server server
Generating a 1024 bit RSA private key
..............++++++


6. 클라이언트 인증키 생성
[root@localhost easy-rsa]# ./build-key client1
Generating a 1024 bit RSA private key
............++++++
Country Name (2 letter code) [KR]:
State or Province Name (full name) [NA]:
Locality Name (eg, city) [SEOUL]:
Organization Name (eg, company) [OpenVPN-OSTSC30]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:client1
Email Address [localhost@locadomain]:

※ Common Name 을 정확히 client1으로 적어준다

7. 암호화에 사용할 키 생성
[root@localhost easy-rsa]# ./build-dh
Generating DH parameters, 1024 bit long safe prime, generator 2
This is going to take a long time
...............................+.....+................+..................................................................+...
.................+..............+..................+.........................................................................
+................................+..................

8. ta.key 생성
[root@localhost easy-rsa]# cd keys
[root@localhost easy-rsa]# openvpn --genkey --secret ta.key

9. 서버 환경설정 파일 생성
vi /etc/openvpn/server.conf

local 210.183.235.30
port 5000
proto udp
dev tap0
ca /usr/share/doc/openvpn-2.0.9/easy-rsa/keys/ca.crt
cert /usr/share/doc/openvpn-2.0.9/easy-rsa/keys/server.crt
key /usr/share/doc/openvpn-2.0.9/easy-rsa/keys/server.key  # This file should be kept secret
dh /usr/share/doc/openvpn-2.0.9/easy-rsa/keys/dh1024.pem
server 10.8.0.0 255.255.255.0
tls-server
tls-auth ta.key 0 # This file is secret
comp-lzo
verb 4
mute 20

port 5000 : OpenVPN은 기본적으로 UDP를 이용해 패킷을 터널링해 전달하는데, 이때 포트는 사용되지 않은 어떤 포트를 사용해도 관계없다.
proto udp : 기본 값인 UDP를 사용하는 것이 좋다. TCP는 권장하지 않는다.
dev tap : OpenVPN 서버와 클라이언트 상호 통신에 필요한 인터페이스를 지정하는데, TUN이나 TAP을 지정할 수 있다.
ifconfig 10.105.11.1 255.255.0.0 : VPN 서버가 사용할 IP를 지정한다. TAP에 이 IP가 할당돼 원격지 PC와  통신할 수 있게 되는데, 가급적 사용하지 않는 사설 IP를 사용하는 것이 좋다.
keepalive 10 120 : 클라이언트와 서버 간에 VPN 연동이 활성화됐는지 체크하기 위해 사용되는데, 매 10초마다 ping을 발송해 120초 동안 응답이 없으면 원격지의 네트워크가 다운된 것으로 파악한다는 의미다.
comp-lzo : 압축 알고리즘을 사용하도록 한다. 서버에 이 같이 설정했다면, 클라이언트에도 동일하게 설정하도록 한다.
persist-key
persist-tun

user nobody          
group nobody   
: 초기화된 후에 OpenVPN 데몬이 nobody 권한으로 작동하도록 한다.

status       openvpn-status.log
log          openvpn.log              
log-append  openvpn.log
: OpenVPN의 로그를 생성하는 설정이다.

tls-server : SSL 키 교환 시에 서버 역할을 하므로 tls-server로 지정한다.

dh  dh1024.pem
ca  my-ca.crt             
cert  server.crt                  
key server.key
:  CA 파일이나 인증서의 공개키 혹은 비밀키를 지정한다

10. 서버 구동
[root@localhost ~]# /etc/init.d/openvpn restart
Shutting down openvpn:                                     [  OK  ]
Starting openvpn:                                          [  OK  ]


III. OpenVPN 클라이언트 설치

OpenVPN GUI라는 프로그램이 많이 사용되는데, 웹 사이트(http://openvpn.se/) 에서 다운로드해 일반적인 윈도우 프로그램 설치와 동일하게 설치하면 된다.

1. 클라이언트 환경설정
설치 이후 '시작->프로그램->OpenVPN'을 선택
여기에서 OpenVPN GUI를 실행.
이후 우측의 트레이에 생긴 아이콘에 오른쪽 마우스를 클릭하면 사용 가능한 메뉴가 나오는데,
여기에서 Edit Config를 선택하면 메모장이 뜨면서 설정작업을 진행할 수 있다.

2. 클라이언트 환경설정 파일
서버에서 생성한 ca.crt , client1.crt , client1.key, ta.key 파일을 클라이언트의 환경설정 디렉토리(C:\Program Files\OpenVPN\config\)안에 복사하고 아래내용으로 설정파일을 만들어준다 : client.ovpn

client
dev tap
proto udp
remote 210.183.235.30 5000
ca "C:\\Program Files\\OpenVPN\\config\\ca.crt"
cert "C:\\Program Files\\OpenVPN\\config\\client1.crt"
key "C:\\Program Files\\OpenVPN\\config\\client1.key"
tls-auth ta.key 1
comp-lzo
verb 3


설정이 끝나면 트레이의 OpenVPN GUI 아이콘을 더블클릭하면 연결된다
VPN에서 지정된 IP를 할당받게 되고, 비공인 VPN IP로 접속하면 VPN을 통해 안전하게 터널링돼 접속하게 된다.
이때의 VPN 트래픽은 암호화되고 터널링되므로 누군가가 중간에서 가로챘다 하더라도 패킷 내용을 해석할 수 없으므로 스니핑이 불가능하다.

오픈아이디로 사용가능한 웹서비스


스프링 노트

집, 학교, 회사 언제 어디서나 쓸 수 있는 노트 한 권, 스프링노트는 함께 쓰는 인터넷 노트 입니다.
나만의 스프링노트에 글을 쉽게 쓰고 관리할 수 있으며, 노트를 여럿이 함께 쓸 수 있습니다.
오픈아이디로 누구나 스프링노트를 개설하고, 친구들을 초대할 수 있습니다.


라이프팟

라이프팟은 일정관리용 인터넷 캘린더로 내 일정관리는 물론, 일정 공유 기능을 활용하여

애인과 함께 커플일정을 관리하거나, 회사 내 팀원들과 일정을 공유하고 관리할 수 있습니다.

펌핏

자신의 블로그나 새로운 정보를 비롯한 세상의 모든 콘텐츠 중 공유하고 싶은 정보를 만났을 때 간단한 주소(URL) 등록을 통해서 실시간으로 다른 회원들과 공유할 수 있는 서비스입니다.

특히 부가기능인 미니펌핏붐바는 자신의 블로그를 가장 빨리, 가장 쉬운 방법으로 홍보할 수 있는 수단으로도 활용할 수 있습니다.

뿐만 아니라 댓글를 통한 토론도 함께 할 수 있습니다. 이렇게 등록된 정보는 추천(펌프업)에 따라 인기도가 산정됩니다.

펌핏의 최종 모델은 온라인 토론 플랫폼입니다. 이를 위해 조만간 회원들이 실시간으로 가볍게 토론하고 설문조사도 할 수 있는 기능을 추가할 계획입니다.
 

레뷰

레뷰는 리뷰를 중심으로 다양한 상품, 문화, 경험에 대한 쇼핑과 선택을 지원하는 소셜 쇼핑 사이트 입니다. 

사용자는 오픈ID를 이용하여 로그인하실 수 있고, 로그인 후 다양한 관심 아이템의 등록, 평가, 태깅을 하실 수 있으며,관심있는 아이템들을 모아서  '내가 추천하는 핸드폰", "최고의 와인바", "여름 피서지 10선"등의 컬렉션도 만드실 수 있습니다. 

여러분이 관심을 갖는 많은 상품이나 서비스에 대해 다른 사용자가 어떤 리뷰를 하고 있는지,어떤 평가를 하고 있는지 참고하시기에 가장 유용한 사이트입니다. 물론 가격이나 위치 정보도 보실 수 있고요.

'개발도 하냐?' 카테고리의 다른 글

새로운 웹 표준 테스트, Acid3  (0) 2008.01.11
웹접근성  (0) 2008.01.03
Struts에서 Spring으로의 이주 가이드.  (0) 2007.07.26
사파리 윈도우용 출시  (0) 2007.07.03
미래를위한선택-웹호환성  (0) 2007.06.18
클래스?
클래스란 객체의 특성을 정의하는 원형이다. 특정한 객체의 자료 구조와 접근 가능한 루틴의 정보를 표현하는 클래스를 개별 ... 하나의 클래스

란 하나의 패키지로 선언된 이름공간을 의미한다. 객체지향이란 그렇게 분리된 이름공간을 활용하는 것이다

서블릿이란?
웹 응용프로그램을 만드는 자바 기술로서 실행 결과값은 html 로 작성된다

보통 서블릿 서버, 서블릿 컨테이너, JSP 컨테이너, 웹서버 라는 등등의 말을 많이 사용합니다. 그렇지만 실제로 각각에 대한 정확한 의미를 알고 있는 경우는 드문데 각각의 의미를 살펴보면 다음과 같습니다.

서블릿서버 : 현재는 거의 사용되지 않는 말입니다. 공식적으로 사용되는 단어라기 보다는 우리나라에서 관습적으로 사용이 되고 있는 의미로 서블릿을 돌릴 수 있는 서버라는 의미입니다. 실제로 서블릿 컨테이너라는 말을 사용하는 것이 좋습니다. (초기에는 서블릿을 돌리기 위해서 아파치 등에 모듈로 연동을 해서 사용을 했기 때문에 이런 말이 생겨난 듯 합니다.)

서블릿 컨테이너 : 서블릿을 동작 시킬수 있는 환경을 제공하는 서버 프로그램입니다. 즉 HTTP 요청을 받아서 해당 서블릿을 동작을 시키고 그 결과를 사용자의 브라우저로 전달을 해줄 수 있는 기능을 제공합니다. 보통 컨테이너라고 하는 이유는 서블릿 프레임워크 안에서 동작을 하고 서블릿이 동작할 수 있는 환경을 제공해주며, 기타 필요한 작업등을 제공해주기 때문에 그렇게 얘기를 합니다. 즉 HTTP 파라미터 파싱 및 결과 전달 컨트롤, Forwarding, Redirecting 등의 기능을 컨테이너에서 제공을 해줍니다. 이때 서블릿 개발자는 자신이 만든 서블릿을 이 컨테이너에 등록을 하게 되고, 실제 동작을 컨테이너가 알아서 하게 되기 때문에 사용되는 언어입니다.

JSP 컨테이너 / 엔진: 실제로 JSP 컨테이너의 의미는 서블릿 컨테이너의 개념과 동일합니다. 그렇지만 조금 자세히 보면 실제로 JSP 컨테이너라는 것은 별도로 존재하지 않습니다. 실제로는 서블릿 컨테이너가 JSP 컨테이너가 됩니다. 그 이유는 JSP는 PHP/ASP와 같이 완전히 스크립트 형식으로 동작하지 않고 서블릿으로 변환이 된 이후에 실행되기 때문입니다. 그리고 JSP를 서블릿으로 컴파일을 해주는 것이 바로 JSP 엔진입니다. 다른 프로그램은 잘 모르겠지만 톰캣의 경우에는 JSP엔진이 바로 JSPServlet 입니다. 즉 JSP를 컴파일하고 동작을 시켜주는 것을 특정 서블릿이 담당하고 있습니다. 여기서 보면 JSP 자체가 완전한 서블릿으로 컴파일 되지 않는 다는 것을 알 수 있습니다. 즉 JSPservlet이 구동 할 수 있는 형태의 서블릿으로 바뀌게 됩니다. 그런 의미에서 보면 별도의 JSP 컨테이너가 있다고 할 수도 있을 것 같습니다.

서블릿특징
html의 정적인 문제점을 해결할 수 있는 동적인 특징을 갖는다.
자바언어로 작성되어 자바의 일반적인 특징을 모두 갖는다.
객체지향적이다.
다른 자바기술과 연동 가능하다. ( JDBC , EJB 등 )
container 라는 특별한 환경에서 실행된다.
Container 종류에 상관없이 작동된다. ( 플랫폼 독립적 )
프로세스 방식이 아닌 스레드 방식으로 실행된다.
Server Side에 적합한 자바기술이다.
보안모델 적용이 수월하다.
저장 파일의 확장자는 java 이고 컴파일된 바이트코드가 container 에서 실행된다.
웹 응용프로그램이기 때문에 브라우저를 통해서 요청한다.



Beans란?

Beans는 일종의 특정한 일을 독립적으로 수행하는 콤포넌트이다.
Beans는 크게 JavaBeans와 EJB(Enterprise JavaBeans)가 있는데, 두 가지는 콤포넌트라는 개념 외에는 많이 다르다.
JSP 문서에서는 JavaBeans와 EJB 모두 사용할 수 있다.
-JavaBeans 자체에 대해서 더 알고 싶은 분은 썬의 JavaBeans 스펙을 참고하기 바란다.

하나의 bean은 속성을 갖는 개체이다. 또한, bean은 그 속성의 값을 설정하고 얻는 방법도 갖고 있다. 뿐만 아니라, 속성을 제어하고 지정한 여러가지 일을 수행하는 방법들도 갖추고 있다. Bean은 한 프로그램에 전속하지 않는 독립적인 객체로서 다른 프로그램에서도 사용할 수 있다.

Bean의 정의는 클래스로서 표현되며 개별 bean은 정의된 클래스의 인스턴스로서 구별된다. 어떤 것도 bean으로 추상화될 수 있다.

왜 Beans를 사용하는가?

크게 세 가지 이유가 있다.

1)form을 통한 데이터 프로세싱이 매우 용이하다는 장점을 들 수 있다.
동적인 웹 페이지 생산의 중요한 요소는 클라이언트로부터 데이터를 입력받아 이를 처리하는 것인데, http 프로토콜을 사용하는 HTML은 GET 또는 POST 방법을 통해 이를 처리한다. JSP 문서에서는 간단하게 request.getParameter()를 통해 GET 또는 POST로 넘어오는 데이타를 전달받을 수 있지만 프로그래밍 코드가 지저분해지기 쉽다. 또한, request라는 JSP Engine(JSP 문서를 Servlet 코드로 변환시키는 일을 한다)이 내부적으로 사용하는 인스턴스를 참조하는 것도 어딘지 석연치 않다. 이후에 살펴보겠지만 beans를 사용하면 번잡한 form 제어를 우아하게 할 수 있다.

2)클라이언트의 데이터를 여러가지 범위에서 지속적으로 유지할 수 있다는 이유가 있다.
간단한 예를 들어보자. 쇼핑몰을 운영하는 사이트는 장바구니 개념이 구현되어야 한다. 소비자가 물건을 사이트에서 살피고 이를 장바구니에 담으면 이 정보는 소비자가 구입을 모두 끝마칠 때까지 유효해야 한다. 이런 장바구니를 구현하기 위해서는 다음의 세 가지 요건이 모두 잘 해결되어야 한다.

3)Beans를 사용하는 가장 중요한 이유는 컴포넌트 기반 개발을 하기 위한 것이다.
Beans를 잘 사용하면 보여주기와 구현하기를 분리하여 비즈니스 로직을 보다 잘 설계할 수 있다.


EJB
EJB는 스펙이다. 그것의 가장 토대가 되는 부분은 Javasoft에 의해 구현되어있으며, 이것을 바탕으로 EJB에 관심을 가진 여러 벤더들이 스펙의 나머지 부분을 구현하였고, 여기에 나름대로의 독특한 기술들을 첨가하여 어플리케이션 서버라는 이름으로 시장에 출시하였다 (물론, 어플리케이션 서버가 EJB 제품군만 있는 것은 아니다.). 그 종류는 세계적으로 40여가지에 이르며, 국내에서는 약 다섯 가지의 제품이 도입되어 어플리케이션 서버시장을 놓고 각축을 벌이고 있다.
EJB는 분산객체 기술에 기반을 둔 컴포넌트 모델이다. 따라서 EJB를 사용하기에 앞서 분산객체 기술에 대해 이해해야한다.
분산 객체 기술은 특정 컴퓨터에서 동작중인 객체를 가깝게는 같은 컴퓨터 내의 다른 프로세스로부터 멀게는 인터넷으로 연결된 원격지 컴퓨터들까지 일관된 방식으로 접근하여 이용할 수 있게 만드는 기술로써,  자바RMI나 CORBA, 그리고 MS 의 DCOM등이있으며, 이러한 분산객체 시스템은 3계층 아키텍처의 근간이된다.


EJB 서버(Server) - 컨테이너(Container) – 빈(Bean) 아키텍쳐
컨테이너는 각 유형의 빈을 위한 EJB객체들과 EJB홈들을 관리한다. 그리고 이것들이 빈 자원들을 관리하고 트랜잭션, 보안, 동시성 제어 및 네이밍 등의 주요 서비스를 적용받을 수있도록 도와준다. 빈은 실제로 우리가 접근하고자 하는 객체이다.
서버-컨테이너-빈의 순서는 상위로부터 하위로 내려가며 포함하는것-포함되는것의 순서로 배열한것인데, 상위는 하위에 대해 라이프 사이클을 관리하고, 동작환경을 제공한다.
빈과 컨테이너 사이에는 분명한 역할의 구분이 있지만, 사실 컨테이너와 서버 사이의 규약은 EJB 스펙에서 정의되지 않았다. EJB스펙에는 빈과 컨테이너 간의 규약에 대해서만 정의하고있는데, 사실상 서버 프로세스가 없이는 EJB는 구동되지 않는다. 이것은 프로그래밍을 약간만 해 본 독자라면 누구나 유추할 수있는 당연한 사실임에도 불구하고, 컨테이너 와 서버간의 규약을 명시하지 않은 것은 EJB컨테이너와 서버간의 역할경계를 불분명하게 만드는 원인이 된다. 이로인해 각 벤더들은 나름대로의 기술을 적용하여 서버와 컨테이너를 분리하였고, 사실상 서로 다른 벤더가 내놓은 EJB서버들과 그들의 컨테이너들은 호환이 거의 불가능한 특성을 갖게되었다. 도미노 효과처럼, 뒤에 나올 컨테이너 관리 빈은 컨테이너 종속적이라는 특성으로 인해, 다른 벤더의 컨테이너에 끼워넣기가 또한 거의 불가능하다.
실제의 개발에 있어서 서버와 컨테이너를 명확하게 구분해야 할 필요는 없다. EJB적인 모든 특징과 기능들은 컨테이너가 하고, 컨테이너를 담기위한 환경 및 여타의 미들웨어적 특성들은 EJB서버가 담당한다라고만 보면 일단은 충분하다. 보다 자세한 사항은 자신이 쓰고자 하는 제품의 벤더가 제공하는 매뉴얼을 참조해야한다.


엔터티 빈(Entity Bean)  - 세션빈(Session Bean) 아키텍쳐
여러분이 프로그래머라면 프로그램이 데이터와 로직으로 구성된다는 것을 알 것이다. 데이터는 영속적인 데이터와 일시적인 데이터로 나뉘어진다. 영속적이라는 것은 파일이나 데이터베이스등의 영구저장매체에 저장되고, 프로그램이 종료된 후에도 다시 로드하여 쓸 수있는 종류의 데이터이다. 반대로 일시적이라는 것은 프로그램 수행중에 변수에 저장되었다가 프로그램이 종료하고, 메모리상의 기억장소가 해제되는 순간에 사라지는 데이터이다. 이러한 일시적인 데이터들은 주로 로직의 진행에 필요한 것으로 로직의 일부로 보는 것이 더욱 타당하다. 이후 데이터라 하면 데이터베이스에 보관되는 영속적인 데이터를 칭하는것으로 이해해주기 바란다.

로직은 데이터의 조작과 처리를 말하며, 업무에 종속적인 로직과 독립적인 로직으로 나뉘어진다. 이러한 업무독립적인 로직들은 라이브러리화되어 대부분의 프로그램이 공유할 수있다. 그러나, 업무에 종속적인 로직은 일반적으로 그렇지못하다. 증권사에서 개발한 증권거래용 프로그램의 증권거래 라이브러리들을 물류회사의 물류관리업무나 일반기업의 인사관리에서 사용할 수는 없다.  이러한 업무종속적인 로직을 일반적으로 비즈니스 로직이라 칭한다. 객체지향 프로그래밍에서는 데이터를 가진 객체는 데이터를 외부와 교환하기위해 데이터 출납용 메소드를 함께 갖는 것이 권장된다. 이러한 데이터 출납용 메소드들은 업무의 흐름에 독립적인 로직을 갖는것으로, 객체지향 프로그래밍에서는 데이터의 일부로 보는 것이 타당하다.

엔터프라이즈 자바 빈의 종류는 두 가지가 있는데, 이는 엔터티 빈과 세션 빈이다.
이 중, 데이터베이스와 맵핑된 영속적인 데이터를 보관하고, 데이터베이스에 직접 접근하여 데이터를 출납하는 일은 엔터티빈이 맡는다.
세션빈은 비즈니스 로직을 포함한다. 이 구조는 EJB스펙에 지정된 것으로 EJB의 가장 핵심적인 프레임웍이다. 이것은 데이터와 비즈니스 로직의 분리를 통한 개발/유지/보수의 편의성 외에도 원거리 호출을 줄임으로써 어플리케이션의 수행성능을 향상시키는 효과도 포함한다.
물론, 서로의 영역을 넘어서 비즈니스 로직을 엔터티빈이 갖는다든지 데이터를 세션빈이 유지한다든지 하는 것도 얼마든지 가능하고, 클라이언트가 세션빈이 가질 로직을 몽땅 갖게되기도한다. 실제적으로 이러한 시도는 빈번하게 발생한다. 하지만, 이렇게 만들어진 어플리케이션은 이미 EJB를 사용하는 의미를 잃는다. 단지 자바와 RMI의 조합만을 이용하는 것일 뿐 EJB 어플리케이션이라고 볼 수가 없다. 결국, EJB가 주는 개발의 신속성과 유지보수의 편의성은 무시되고, EJB도 별 게 아니더라 라는 결과만을 얻게되는것이다.

엔터티 빈에서 제공하는 메소드를 이용하여 빈의 attribute를 변경하면, 이 변경은 Database의 해당 Table의 해당 Attribute에 자동으로 반영되는것이다. 이때, 엔터티 빈을 참조하는 쪽에서는 전혀 Database의 테이블 구조 및, DBMS와의 통신에 신경을 쓰지 않게된다.  DBMS와의 통신에 신경을 쓰지 않는다는 말은 SQL문을 전혀 사용할 필요가 없음을 의미한다.
그러나, 위에서 한 말은 엄밀히 말하면, 이미 만들어진 엔터티 빈을 사용하는 입장의 개발자에게는 100퍼센트 사실일 수 있겠지만, 아래에서 소개할 Bean managed 방식의 빈개발자는 데이터베이스와 객체를 매핑시키는 작업을 스스로 해 줘야만 하므로, 어쩔 수 없이 SQL을 다루게된다. Container managed방식의 경우라면, 매핑 작업을 EJB 서버의 벤더가 제공하는 툴이 대신해주므로, 엔터티 빈을 만드는 쪽이나, 사용하는 쪽이나 SQL을 전혀 사용할 필요가 없다.

커넥션 풀 ( Connection Pool)
풀이란것은 미리 일정량을 비축해두는 장소라고 보면 된다. 어플리케이션이 DBMS와 통신을 하기위해서는 DBMS와의 커넥션이 필요한데, 어플리케이션이 DB에 SQL을 던지고, 그 수행이 끝날때까지의 시간의 대부분은 DBMS와 커넥션을 맺는데 소요된다.
따라서, 미리 몇 개의 커넥션을 맺어서 커넥션 풀에 이것을 저장해두었다가 이를 필요로하는 객체에게 할당함으로써 수행성능을 향상시킬 수있다. 커넥션을 할당받은 객체는 이 커넥션을 통해 원하는 DB 오퍼레이션을 수행하고, 수행이 완료된 후엔 커넥션을 다시금 풀로 되돌린다. 커넥션은 무한히 쓸 수있는게 아니고, 그 수가 DBMS에 따라 제한되어있다. 만일 저장된 커넥션의 수보다 이를 요구하는 객체의 수가 더 많으면 커넥션을 할당받을 수 없는 나머지 객체들은 풀이 가진 커넥션에 여유가 생길 때까지 대기한다


UDDI
 UDDI 프로젝트는 웹 서비스의 상호 운용성과 채택(adoption)을 촉진시킨다. 이 프로젝트는 산업계와 비지니스 리더들 사이의 파트너쉽이고 IBM, Ariba, Microsoft에 의해 설립되었다. 지금 현재 300개가 넘는 기업들이 참여하고 있다. UDDI는 서비스 설명과 서비스 발견(discovery)에 대한 표준 기반의 스팩은 물론 인터넷 기반 구현을 제공한다. UDDI는 계속적으로 빠르게 진화하고 있으며 산업계의 지원을 받고있다. 이 스팩은 빠르게 개발되고 있다.

UDDI는 비지니스의 많은 문제점들에 관심을 기울이고 있다. 첫째, business-to-business (B2B) 인터랙션의 확장과 단순화에 기여한다. 다양한 고객과 많은 관계를 창출해야하는 제조사에게, UDDI는 각 표준과 프로토콜 별로 가상의 모든 인터페이스를 사용하여 매우 유연한 서비스 기술(description)을 지원한다. 예를 들어 전 세계의 모든 시장에 연결을 원하지만 방법을 모르고 있는 호주의 플라워 샵의 경우 UDDI는 이 방법을 제공한다. 이 스팩은 레지스트리에 플라워 샵을 나타내어 그들이 제공하는 비지니스와 서비스를 효율적이며 간단하게 발견할 수 있도록 한다.

공급자용 카탈로그 데이터 뿐만아니라 영수증 서비스, 포장, 선적, 보험관계자와 관계를 원하는 B2B 마켓플레이스 제공자에게 UDDI는 동적 발견과 관련 웹 서비스를 전체 비지니스 프로세스로 통합할 수 있도록 한다. UDDI는 비지니스 및 전자 서비스에 관한 정보에 대해 원스탑(one-stop) 쇼핑을 제공한다. UDDI에 비지니스 및 서비스 정보를 퍼블리쉬 하면 다른 것에 광범위하게 액세스 할 수 있다.

UDDI는 Extensible Markup Language (XML)와 Simple Object Access Protocol (SOAP) 같은 기존 표준에 기반하고 있다. UDDI를 따르는 모든 구현들은 UDDI 스팩을 지원한다. 공식 스팩은 회원들에 의해 공개적이고 포괄적으로 개발되었다. 앞으로 독립적인 표준 단체로 향후 개발 소유권을 넘기기 전에 세 개의 연속적인 버전을 만들고 구현하기 위함이다. UDDI Version 1 스팩은 2000년 9월, Version 2는 2001년 6월에 발표되었다. Version 3 스팩은 지금 개발중이며 2002년 중순에 발표될 예정이다. Version 1이 레지스트리에 대한 기초를 확립했다면 Version 2는 비지니스 관계 같은 기능을 추가했다. Version 3은 보안, 국제화, 레지스트리 상호운용성, 다양한 API 향상과 같은 웹 서비스의 지속적인 개발을 통해 툴링 향상을 목표로하고 있다.

'삽질로그' 카테고리의 다른 글

80x15 배너이미지 만들기  (0) 2007.08.02
RSS 관리  (0) 2007.08.02
자바에 사용되는 용어들  (0) 2007.07.26
FCKeditor java 버전 설치  (0) 2007.07.26
PCI-X 와 PCI-Express 의 비교사진  (0) 2007.07.12
클래스?
클래스란 객체의 특성을 정의하는 원형이다. 특정한 객체의 자료 구조와 접근 가능한 루틴의 정보를 표현하는 클래스를 개별 ... 하나의 클래스

란 하나의 패키지로 선언된 이름공간을 의미한다. 객체지향이란 그렇게 분리된 이름공간을 활용하는 것이다

서블릿이란?
웹 응용프로그램을 만드는 자바 기술로서 실행 결과값은 html 로 작성된다

보통 서블릿 서버, 서블릿 컨테이너, JSP 컨테이너, 웹서버 라는 등등의 말을 많이 사용합니다. 그렇지만 실제로 각각에 대한 정확한 의미를 알고 있는 경우는 드문데 각각의 의미를 살펴보면 다음과 같습니다.

서블릿서버 : 현재는 거의 사용되지 않는 말입니다. 공식적으로 사용되는 단어라기 보다는 우리나라에서 관습적으로 사용이 되고 있는 의미로 서블릿을 돌릴 수 있는 서버라는 의미입니다. 실제로 서블릿 컨테이너라는 말을 사용하는 것이 좋습니다. (초기에는 서블릿을 돌리기 위해서 아파치 등에 모듈로 연동을 해서 사용을 했기 때문에 이런 말이 생겨난 듯 합니다.)

서블릿 컨테이너 : 서블릿을 동작 시킬수 있는 환경을 제공하는 서버 프로그램입니다. 즉 HTTP 요청을 받아서 해당 서블릿을 동작을 시키고 그 결과를 사용자의 브라우저로 전달을 해줄 수 있는 기능을 제공합니다. 보통 컨테이너라고 하는 이유는 서블릿 프레임워크 안에서 동작을 하고 서블릿이 동작할 수 있는 환경을 제공해주며, 기타 필요한 작업등을 제공해주기 때문에 그렇게 얘기를 합니다. 즉 HTTP 파라미터 파싱 및 결과 전달 컨트롤, Forwarding, Redirecting 등의 기능을 컨테이너에서 제공을 해줍니다. 이때 서블릿 개발자는 자신이 만든 서블릿을 이 컨테이너에 등록을 하게 되고, 실제 동작을 컨테이너가 알아서 하게 되기 때문에 사용되는 언어입니다.

JSP 컨테이너 / 엔진: 실제로 JSP 컨테이너의 의미는 서블릿 컨테이너의 개념과 동일합니다. 그렇지만 조금 자세히 보면 실제로 JSP 컨테이너라는 것은 별도로 존재하지 않습니다. 실제로는 서블릿 컨테이너가 JSP 컨테이너가 됩니다. 그 이유는 JSP는 PHP/ASP와 같이 완전히 스크립트 형식으로 동작하지 않고 서블릿으로 변환이 된 이후에 실행되기 때문입니다. 그리고 JSP를 서블릿으로 컴파일을 해주는 것이 바로 JSP 엔진입니다. 다른 프로그램은 잘 모르겠지만 톰캣의 경우에는 JSP엔진이 바로 JSPServlet 입니다. 즉 JSP를 컴파일하고 동작을 시켜주는 것을 특정 서블릿이 담당하고 있습니다. 여기서 보면 JSP 자체가 완전한 서블릿으로 컴파일 되지 않는 다는 것을 알 수 있습니다. 즉 JSPservlet이 구동 할 수 있는 형태의 서블릿으로 바뀌게 됩니다. 그런 의미에서 보면 별도의 JSP 컨테이너가 있다고 할 수도 있을 것 같습니다.

서블릿특징
html의 정적인 문제점을 해결할 수 있는 동적인 특징을 갖는다.
자바언어로 작성되어 자바의 일반적인 특징을 모두 갖는다.
객체지향적이다.
다른 자바기술과 연동 가능하다. ( JDBC , EJB 등 )
container 라는 특별한 환경에서 실행된다.
Container 종류에 상관없이 작동된다. ( 플랫폼 독립적 )
프로세스 방식이 아닌 스레드 방식으로 실행된다.
Server Side에 적합한 자바기술이다.
보안모델 적용이 수월하다.
저장 파일의 확장자는 java 이고 컴파일된 바이트코드가 container 에서 실행된다.
웹 응용프로그램이기 때문에 브라우저를 통해서 요청한다.



Beans란?

Beans는 일종의 특정한 일을 독립적으로 수행하는 콤포넌트이다.
Beans는 크게 JavaBeans와 EJB(Enterprise JavaBeans)가 있는데, 두 가지는 콤포넌트라는 개념 외에는 많이 다르다.
JSP 문서에서는 JavaBeans와 EJB 모두 사용할 수 있다.
-JavaBeans 자체에 대해서 더 알고 싶은 분은 썬의 JavaBeans 스펙을 참고하기 바란다.

하나의 bean은 속성을 갖는 개체이다. 또한, bean은 그 속성의 값을 설정하고 얻는 방법도 갖고 있다. 뿐만 아니라, 속성을 제어하고 지정한 여러가지 일을 수행하는 방법들도 갖추고 있다. Bean은 한 프로그램에 전속하지 않는 독립적인 객체로서 다른 프로그램에서도 사용할 수 있다.

Bean의 정의는 클래스로서 표현되며 개별 bean은 정의된 클래스의 인스턴스로서 구별된다. 어떤 것도 bean으로 추상화될 수 있다.

왜 Beans를 사용하는가?

크게 세 가지 이유가 있다.

1)form을 통한 데이터 프로세싱이 매우 용이하다는 장점을 들 수 있다.
동적인 웹 페이지 생산의 중요한 요소는 클라이언트로부터 데이터를 입력받아 이를 처리하는 것인데, http 프로토콜을 사용하는 HTML은 GET 또는 POST 방법을 통해 이를 처리한다. JSP 문서에서는 간단하게 request.getParameter()를 통해 GET 또는 POST로 넘어오는 데이타를 전달받을 수 있지만 프로그래밍 코드가 지저분해지기 쉽다. 또한, request라는 JSP Engine(JSP 문서를 Servlet 코드로 변환시키는 일을 한다)이 내부적으로 사용하는 인스턴스를 참조하는 것도 어딘지 석연치 않다. 이후에 살펴보겠지만 beans를 사용하면 번잡한 form 제어를 우아하게 할 수 있다.

2)클라이언트의 데이터를 여러가지 범위에서 지속적으로 유지할 수 있다는 이유가 있다.
간단한 예를 들어보자. 쇼핑몰을 운영하는 사이트는 장바구니 개념이 구현되어야 한다. 소비자가 물건을 사이트에서 살피고 이를 장바구니에 담으면 이 정보는 소비자가 구입을 모두 끝마칠 때까지 유효해야 한다. 이런 장바구니를 구현하기 위해서는 다음의 세 가지 요건이 모두 잘 해결되어야 한다.

3)Beans를 사용하는 가장 중요한 이유는 컴포넌트 기반 개발을 하기 위한 것이다.
Beans를 잘 사용하면 보여주기와 구현하기를 분리하여 비즈니스 로직을 보다 잘 설계할 수 있다.


EJB
EJB는 스펙이다. 그것의 가장 토대가 되는 부분은 Javasoft에 의해 구현되어있으며, 이것을 바탕으로 EJB에 관심을 가진 여러 벤더들이 스펙의 나머지 부분을 구현하였고, 여기에 나름대로의 독특한 기술들을 첨가하여 어플리케이션 서버라는 이름으로 시장에 출시하였다 (물론, 어플리케이션 서버가 EJB 제품군만 있는 것은 아니다.). 그 종류는 세계적으로 40여가지에 이르며, 국내에서는 약 다섯 가지의 제품이 도입되어 어플리케이션 서버시장을 놓고 각축을 벌이고 있다.
EJB는 분산객체 기술에 기반을 둔 컴포넌트 모델이다. 따라서 EJB를 사용하기에 앞서 분산객체 기술에 대해 이해해야한다.
분산 객체 기술은 특정 컴퓨터에서 동작중인 객체를 가깝게는 같은 컴퓨터 내의 다른 프로세스로부터 멀게는 인터넷으로 연결된 원격지 컴퓨터들까지 일관된 방식으로 접근하여 이용할 수 있게 만드는 기술로써,  자바RMI나 CORBA, 그리고 MS 의 DCOM등이있으며, 이러한 분산객체 시스템은 3계층 아키텍처의 근간이된다.


EJB 서버(Server) - 컨테이너(Container) – 빈(Bean) 아키텍쳐
컨테이너는 각 유형의 빈을 위한 EJB객체들과 EJB홈들을 관리한다. 그리고 이것들이 빈 자원들을 관리하고 트랜잭션, 보안, 동시성 제어 및 네이밍 등의 주요 서비스를 적용받을 수있도록 도와준다. 빈은 실제로 우리가 접근하고자 하는 객체이다.
서버-컨테이너-빈의 순서는 상위로부터 하위로 내려가며 포함하는것-포함되는것의 순서로 배열한것인데, 상위는 하위에 대해 라이프 사이클을 관리하고, 동작환경을 제공한다.
빈과 컨테이너 사이에는 분명한 역할의 구분이 있지만, 사실 컨테이너와 서버 사이의 규약은 EJB 스펙에서 정의되지 않았다. EJB스펙에는 빈과 컨테이너 간의 규약에 대해서만 정의하고있는데, 사실상 서버 프로세스가 없이는 EJB는 구동되지 않는다. 이것은 프로그래밍을 약간만 해 본 독자라면 누구나 유추할 수있는 당연한 사실임에도 불구하고, 컨테이너 와 서버간의 규약을 명시하지 않은 것은 EJB컨테이너와 서버간의 역할경계를 불분명하게 만드는 원인이 된다. 이로인해 각 벤더들은 나름대로의 기술을 적용하여 서버와 컨테이너를 분리하였고, 사실상 서로 다른 벤더가 내놓은 EJB서버들과 그들의 컨테이너들은 호환이 거의 불가능한 특성을 갖게되었다. 도미노 효과처럼, 뒤에 나올 컨테이너 관리 빈은 컨테이너 종속적이라는 특성으로 인해, 다른 벤더의 컨테이너에 끼워넣기가 또한 거의 불가능하다.
실제의 개발에 있어서 서버와 컨테이너를 명확하게 구분해야 할 필요는 없다. EJB적인 모든 특징과 기능들은 컨테이너가 하고, 컨테이너를 담기위한 환경 및 여타의 미들웨어적 특성들은 EJB서버가 담당한다라고만 보면 일단은 충분하다. 보다 자세한 사항은 자신이 쓰고자 하는 제품의 벤더가 제공하는 매뉴얼을 참조해야한다.


엔터티 빈(Entity Bean)  - 세션빈(Session Bean) 아키텍쳐
여러분이 프로그래머라면 프로그램이 데이터와 로직으로 구성된다는 것을 알 것이다. 데이터는 영속적인 데이터와 일시적인 데이터로 나뉘어진다. 영속적이라는 것은 파일이나 데이터베이스등의 영구저장매체에 저장되고, 프로그램이 종료된 후에도 다시 로드하여 쓸 수있는 종류의 데이터이다. 반대로 일시적이라는 것은 프로그램 수행중에 변수에 저장되었다가 프로그램이 종료하고, 메모리상의 기억장소가 해제되는 순간에 사라지는 데이터이다. 이러한 일시적인 데이터들은 주로 로직의 진행에 필요한 것으로 로직의 일부로 보는 것이 더욱 타당하다. 이후 데이터라 하면 데이터베이스에 보관되는 영속적인 데이터를 칭하는것으로 이해해주기 바란다.

로직은 데이터의 조작과 처리를 말하며, 업무에 종속적인 로직과 독립적인 로직으로 나뉘어진다. 이러한 업무독립적인 로직들은 라이브러리화되어 대부분의 프로그램이 공유할 수있다. 그러나, 업무에 종속적인 로직은 일반적으로 그렇지못하다. 증권사에서 개발한 증권거래용 프로그램의 증권거래 라이브러리들을 물류회사의 물류관리업무나 일반기업의 인사관리에서 사용할 수는 없다.  이러한 업무종속적인 로직을 일반적으로 비즈니스 로직이라 칭한다. 객체지향 프로그래밍에서는 데이터를 가진 객체는 데이터를 외부와 교환하기위해 데이터 출납용 메소드를 함께 갖는 것이 권장된다. 이러한 데이터 출납용 메소드들은 업무의 흐름에 독립적인 로직을 갖는것으로, 객체지향 프로그래밍에서는 데이터의 일부로 보는 것이 타당하다.

엔터프라이즈 자바 빈의 종류는 두 가지가 있는데, 이는 엔터티 빈과 세션 빈이다.
이 중, 데이터베이스와 맵핑된 영속적인 데이터를 보관하고, 데이터베이스에 직접 접근하여 데이터를 출납하는 일은 엔터티빈이 맡는다.
세션빈은 비즈니스 로직을 포함한다. 이 구조는 EJB스펙에 지정된 것으로 EJB의 가장 핵심적인 프레임웍이다. 이것은 데이터와 비즈니스 로직의 분리를 통한 개발/유지/보수의 편의성 외에도 원거리 호출을 줄임으로써 어플리케이션의 수행성능을 향상시키는 효과도 포함한다.
물론, 서로의 영역을 넘어서 비즈니스 로직을 엔터티빈이 갖는다든지 데이터를 세션빈이 유지한다든지 하는 것도 얼마든지 가능하고, 클라이언트가 세션빈이 가질 로직을 몽땅 갖게되기도한다. 실제적으로 이러한 시도는 빈번하게 발생한다. 하지만, 이렇게 만들어진 어플리케이션은 이미 EJB를 사용하는 의미를 잃는다. 단지 자바와 RMI의 조합만을 이용하는 것일 뿐 EJB 어플리케이션이라고 볼 수가 없다. 결국, EJB가 주는 개발의 신속성과 유지보수의 편의성은 무시되고, EJB도 별 게 아니더라 라는 결과만을 얻게되는것이다.

엔터티 빈에서 제공하는 메소드를 이용하여 빈의 attribute를 변경하면, 이 변경은 Database의 해당 Table의 해당 Attribute에 자동으로 반영되는것이다. 이때, 엔터티 빈을 참조하는 쪽에서는 전혀 Database의 테이블 구조 및, DBMS와의 통신에 신경을 쓰지 않게된다.  DBMS와의 통신에 신경을 쓰지 않는다는 말은 SQL문을 전혀 사용할 필요가 없음을 의미한다.
그러나, 위에서 한 말은 엄밀히 말하면, 이미 만들어진 엔터티 빈을 사용하는 입장의 개발자에게는 100퍼센트 사실일 수 있겠지만, 아래에서 소개할 Bean managed 방식의 빈개발자는 데이터베이스와 객체를 매핑시키는 작업을 스스로 해 줘야만 하므로, 어쩔 수 없이 SQL을 다루게된다. Container managed방식의 경우라면, 매핑 작업을 EJB 서버의 벤더가 제공하는 툴이 대신해주므로, 엔터티 빈을 만드는 쪽이나, 사용하는 쪽이나 SQL을 전혀 사용할 필요가 없다.

커넥션 풀 ( Connection Pool)
풀이란것은 미리 일정량을 비축해두는 장소라고 보면 된다. 어플리케이션이 DBMS와 통신을 하기위해서는 DBMS와의 커넥션이 필요한데, 어플리케이션이 DB에 SQL을 던지고, 그 수행이 끝날때까지의 시간의 대부분은 DBMS와 커넥션을 맺는데 소요된다.
따라서, 미리 몇 개의 커넥션을 맺어서 커넥션 풀에 이것을 저장해두었다가 이를 필요로하는 객체에게 할당함으로써 수행성능을 향상시킬 수있다. 커넥션을 할당받은 객체는 이 커넥션을 통해 원하는 DB 오퍼레이션을 수행하고, 수행이 완료된 후엔 커넥션을 다시금 풀로 되돌린다. 커넥션은 무한히 쓸 수있는게 아니고, 그 수가 DBMS에 따라 제한되어있다. 만일 저장된 커넥션의 수보다 이를 요구하는 객체의 수가 더 많으면 커넥션을 할당받을 수 없는 나머지 객체들은 풀이 가진 커넥션에 여유가 생길 때까지 대기한다


UDDI
 UDDI 프로젝트는 웹 서비스의 상호 운용성과 채택(adoption)을 촉진시킨다. 이 프로젝트는 산업계와 비지니스 리더들 사이의 파트너쉽이고 IBM, Ariba, Microsoft에 의해 설립되었다. 지금 현재 300개가 넘는 기업들이 참여하고 있다. UDDI는 서비스 설명과 서비스 발견(discovery)에 대한 표준 기반의 스팩은 물론 인터넷 기반 구현을 제공한다. UDDI는 계속적으로 빠르게 진화하고 있으며 산업계의 지원을 받고있다. 이 스팩은 빠르게 개발되고 있다.

UDDI는 비지니스의 많은 문제점들에 관심을 기울이고 있다. 첫째, business-to-business (B2B) 인터랙션의 확장과 단순화에 기여한다. 다양한 고객과 많은 관계를 창출해야하는 제조사에게, UDDI는 각 표준과 프로토콜 별로 가상의 모든 인터페이스를 사용하여 매우 유연한 서비스 기술(description)을 지원한다. 예를 들어 전 세계의 모든 시장에 연결을 원하지만 방법을 모르고 있는 호주의 플라워 샵의 경우 UDDI는 이 방법을 제공한다. 이 스팩은 레지스트리에 플라워 샵을 나타내어 그들이 제공하는 비지니스와 서비스를 효율적이며 간단하게 발견할 수 있도록 한다.

공급자용 카탈로그 데이터 뿐만아니라 영수증 서비스, 포장, 선적, 보험관계자와 관계를 원하는 B2B 마켓플레이스 제공자에게 UDDI는 동적 발견과 관련 웹 서비스를 전체 비지니스 프로세스로 통합할 수 있도록 한다. UDDI는 비지니스 및 전자 서비스에 관한 정보에 대해 원스탑(one-stop) 쇼핑을 제공한다. UDDI에 비지니스 및 서비스 정보를 퍼블리쉬 하면 다른 것에 광범위하게 액세스 할 수 있다.

UDDI는 Extensible Markup Language (XML)와 Simple Object Access Protocol (SOAP) 같은 기존 표준에 기반하고 있다. UDDI를 따르는 모든 구현들은 UDDI 스팩을 지원한다. 공식 스팩은 회원들에 의해 공개적이고 포괄적으로 개발되었다. 앞으로 독립적인 표준 단체로 향후 개발 소유권을 넘기기 전에 세 개의 연속적인 버전을 만들고 구현하기 위함이다. UDDI Version 1 스팩은 2000년 9월, Version 2는 2001년 6월에 발표되었다. Version 3 스팩은 지금 개발중이며 2002년 중순에 발표될 예정이다. Version 1이 레지스트리에 대한 기초를 확립했다면 Version 2는 비지니스 관계 같은 기능을 추가했다. Version 3은 보안, 국제화, 레지스트리 상호운용성, 다양한 API 향상과 같은 웹 서비스의 지속적인 개발을 통해 툴링 향상을 목표로하고 있다.

'삽질로그' 카테고리의 다른 글

RSS 관리  (0) 2007.08.02
자바에 사용되는 용어들  (0) 2007.07.26
FCKeditor java 버전 설치  (0) 2007.07.26
PCI-X 와 PCI-Express 의 비교사진  (0) 2007.07.12
소프트웨어기술자 등급별 노임단가기준(2008)  (0) 2007.07.09
원문 : http://www.devx.com/Java/Article/29208


Struts에서 Spring으로의 이주 가이드.

당신은 이 글을 통해 Struts애플리케이션에서 Spring MVC애플리케이션으로 변형하는 방법뿐 아니라 두 프레임워크사이의 논리적인 맵핑과 Struts개념을 Spring MVC개념에 관련시키는 수단을 배울것이다.


사실 Struts프레임워크는 기술발전이나 채택이 감소하기 시작하고 있다고 몇몇 사람들이 제기한다. 사실 Struts의 책임 개발자인 Craig McClanahan또한 Struts사용자에게 새로운 웹 프레임워크로의 이전을 권하고 있는 상황이다. 반면에 J2EE웹 공간에서, Spring MVC는 꾸준한 채택과 자바 개발자의 주의를 끌고 있다. 가장 인기있는 Spring프레임워크는 잘 디자인되었으며, 잘 만들어졌고, 혁신적이다. 그래서 많은 Struts사용자는 Struts를 위한 대체 프레임워크처럼 Spring을 MVC를 사용할것이다.


이 글은 Struts애플리케이션을 Spring MVC로 이전하길 원하는 개발자들을 도와준다. 그리고 다음의 두가지 핵심부분으로 나누어져있다.

Struts와 Spring MVC프레임워크의 기본 개념사이의 논리적인 맵핑.
이전 대체물을 위한 기본적인 추천사항들.

논리적인 맵핑 : 다른 프레임워크간의 유사함.
Struts와 Spring은 MVC패턴 구현에서 본질적으로 유사하다. 둘다 핵심 J2EE컴포넌트인 Servlet과 JSP에 기반한 모델2 타입의 개발방식을 주로 할려는 경향이 있다. Struts에 친숙한 개발자는 하나의 프레임워크에서 다른것으로 개념적으로 쉽게 이주할수 있다. 두가지 프레임워크 모두 View, Controller, Model의 역활을 제공하는 컴포넌트를 명백하게 서술하고 있다. 유사성은 구현레벨에서 멈춘다. Struts디자인은 각각의 사용자지정 action이 Struts Action컴포넌트의 구조적인 상속이 된다는것을 의미하는 견고한 상속에 기반을 둔다. Spring컨트롤러는 인터페이스이기 때문에, 어떠한 컴포넌트도 컨트롤러의 역활을 수행할수 있다. 이것은 애플리케이션 디자이너에게 컴포넌트 디자인의 좀더 나은 유연함을 제공한다.


프레임워크 컴포넌트 레벨에서 Struts는 Form Beans (정적이거나 동적인), Actions, Action Mappings, Action Forwards, 그리고 Request Processors와 같은 Struts 특유의 객체 사용을 요구한다. Spring MVC는 주요한 컴포넌트가 인터페이스처럼 정의된것처럼 좀더 유연하다.


Struts는 오직 웹 프레임워크일 뿐이다.
Struts는 애플리케이션 개발에서 오직 presentation계층에만 할당한다. 반면에 Spring MVC는 비지니스 컴포넌트에다가 Spring 기업용 개발의 다른 부분을 관리하는 Spring 프레임워크의 다른 부분과 완벽하게 통합되는 Spring프레임워크의 주요한 부분일뿐이다. 이제 좀더 상세하게 프레임워크 컴포넌트를 보자.


Struts Actions는 대략 Spring Controllers이다.
Struts에서 Action은 프레임워크의 핵심 "processing"객체이다. 그것들은 MVC패턴에서 컨트롤러의 역활을 수행한다. Struts Actions의 Spring이 가진 대안은 Controller인터페이스이다. 반면에 Controller는 Spring에서 사용자 입력을 처리하고 View컴포넌트로 전달한다. Struts Actions과 Spring Controller사이의 가장 명백한 차이점은 Actions는 추상 클래스이고 Controllers는 인터페이스라는 것이다. Spring MVC 컨트롤러처럼 설정되기 위해서, 객체는 오직 다음의 메소드를 구현할 필요가 있을것이다.


ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception; 


이 디자인(인터페이스에 의한 디자인)은 애플리케이션과 프레임워크간의 커플링을 최소화한다. 또한 이것은 Controllers의 디자인에서 구조적으로 좀더 유연성을 제공한다. 이것을 염두해 두고, Struts에서 Spring으로의 가장 간단한 중계역활을 하는 이전(transition) 단계는 Action을 다시 쓰는 것이다. 그래서 그것들은 Controller인터페이슬ㄹ 구현하고 존재하는 코드를 재사용하는것이다. 이것은 애플리케이션 작동을 유지하는 동안 모든 Struts의존성의 제거를 증가시키는것을 허용한다.


Spring은 다른 Action대체물도 제공한다. 많은 수의 프레임워크가 제공하는 Controller구현물은 가장 공통적인 웹애플리케이션 작업에 대응된다. 몇몇 제공되는 Controller는 당신이 친숙한 Struts Action에 좀더 특성화된 것에 대응된다. 예를 들어, 당신이 DispatchActions을 사용한다면, MultiActionControllers와 좀더 잘 다듬어진 AbstractWizardFormControllers가 도움을 줄것이다. 다른 Controller구현문은 Spring MVC에 딸려나온다.


Action Forms이 없다.
Spring프레임워크내에서 가장 크고 가장 긍정적인 차이점중에 하나는 특성화된 ActionForm객체가 없다는 것이다. 프레임워크는 HTTP폼 값을 직접적으로 POJO에 바인딩하는것을 지원한다. 이 기능은 생성하고 유지할 클래스의 수를 제한하여 애플리케이션 유지관리를 단순화한다. 이 경우, 이전(migration)은 폼빈즈를 삭제하고 직접적으로 도메인 객체를 사용하는것을 의미한다. 어쨌든, 이것은 당신이 폼입력과 도메인 객체간의 맵핑처럼 Form Bean객체를 사용할수 있다면 필수단계는 아니다. Spring MVC에서, AbstractFormController구현물을 확장하는 특수한 목적의 Controllers는 폼을 지지하는 빈즈를 지원한다. AbstractFormController의 사용자지정 하위클래스는 폼객체처럼 폼을 지지하는(Command) Beans를 사용한다. 다시 말해, 이러한 빈즈를 정의하는 요구사항은 없다. Command객체는 java.lang.Object의 어떠한 하위클래스도 될수 있다.


ActionForwards vs. ModelAndView
Struts ActionMapping에서, 객체는 표현자원(Actions, JSPs, Tiles, HTML 파일들 등등.)을 가리킨다. Spring MVC에서 ActionMapping에 대해 가장 가까운 의미의 컴포넌트는 ModelAndView인터페이스이다. Spring Controllers는 사용자에 의해 구현될수 있는것처럼 ModelAndView인터페이스의 구현물을 반환한다. 또는 당신이 원한다면 Spring MVC에 의해 제공되는 ModelAndView구현물을 사용할수도 있다. 내포하는 이름처럼, ModelAndView객체는 Model과 View컴포넌트를 가진다. Model컴포넌트는 View컴포넌트를 통해 표시되기 위한 비지니스 객체를 포함한다. 시나리오에 따르면, ModelAndView구현물은 포함된 어떠한 Model컴포넌트를 가지지 않는다. 그것들은 아마도 실질적인 View컴포넌트(JSP, XSLT, Tiles, HTML, XML, 등등)의 몇몇 형태로 이끌것이다. Controller구현물에서 처럼, 나는 Spring MVC가 제공하는 Model의 구현물과 View인터페이스 그리고 View해석자(Resolver)를 조사하는것을 강력히 권한다.


사용자지정 JSP 태그들
Spring MVC는 표준 JSP태그 라이브러리의 의미있는 힘을 신뢰한다. Struts와는 달리, Spring MVC는 HTML, logic, 또는 bean처리를 위한 분리된 태그 라이브러리를 제공하지 않는다. 이것은 Command객체에서 Web form으로의 바인딩을 가능하게 하는 작은 태그라이브러리만을 제공한다. 당신은 다른 모든 작업을 위해 표준적인 템플릿 라이브러리(JSTL)를 사용할것이다.


유효성체크(Validation)
만약 당신이 Struts의 Commons Validator을 사용한다면, 당신은 Spring내에서 완벽하게 재사용할수 있을것이다. Spring 1.2는 Commons기반 유효성체크를 지원하지 않지만 Spring MVC의 "sandbox"버전은 Commons Validator마크업 (validator.xml 과 validation-rules.xml)으로 쓰여진 유효성체크 정의의 재사용을 지원한다. 유효성체크 선언를 가진 당신의 XML파일을 버리지 마라. 그것들은 Spring내에서 재사용가능할것이다.


Error 와 Validation Messages
좀더 좋은 소식이 있다. Spring은 동일한 형태로 Struts message번들을 인식한다. Spring MVC내 존재하는 Message자원들을 재사용하기 위해서, 당신은 Spring MVC 설정파일내 messageSource가 다음처럼 설정한다.


<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
 <property name="basename">
  <value>resources.ApplicationResources</value>
 </property>
</bean> 


또한, 당신은 Controller구현물내 messageSource프라퍼티로써 당신의 Controller처럼 이것을 사용할 필요가 있다. 요구되는 변경사항은 없다.


Dispatcher Servlet
Spring MVC는 Request Processor/Action Servlet의 자신만의 버전을 가진다. 이것은 URL표시그룹으로 맵핑되는 DispatcherServlet이다. Dispatcher Servlet의 개념을 이해하기 위해서, Controller를 Spring MVC내 설정하는 방법을 보자.


설정파일들
Struts사용자라면, 당신은 모든 forward, action mapping, form definition 그리고 플러그인 선언등을 가지는 적어도 하나의 struts-config.xml파일을 사용한다. Spring MVC에서, 모든 웹 애플리케이션관련 컨트롤러 선언은 Spring Beans처럼 설정된다. 하나이상의 Dispatcher Controller는 웹자원을 위한 모든 요청을 적당한 Controller로 보낸다. 예를 들면, 만약 당신이 ".do"애플리케이션을 Spring MVC애플리케이션으로 다시 맵핑시키길 원한다면, 당신은 애플리케이션의 web.xml에 다음처럼 서블릿 맵핑을 등록하라. (나는 당신이 .do 확장자를 사용하는것을 실질적으로 권하지 않는다. Struts만 사용하는 규칙처럼 ".do"를 남겨두라.)


<servlet>
 <servlet-name>applicationDispatcher</servlet-name>
 <servlet-class>
  org.springframework.web.servlet.DispatcherServlet
 </servlet-class>
 <load-on-startup>1</load-on-startup>
</servlet>

        ...

<servlet-mapping>
 <servlet-name>applicationDispatcher</servlet-name>
 <url-pattern>*.do</url-pattern>
</servlet-mapping>   


지금 당신은 Spring MVC Controller선언을 가진 Spring 설정파일(applicationDispatcher-servlet.xml)을 가진다. "-servlet.xml"는 applicationDispatcher파일을 위한 접미사이다. 이것은 Spring MVC맵핑파일을 자동 리로드하는 DispatcherServlet을 가능하게 하는 Spring MVC규칙이다.


Spring MVC내에서 웹 action을 적당한 컨트롤러로 맵핑하는것은 매우 쉽다. 이것은 Spring애플리케이션의 일부처럼 같은 "wiring"형태로 수행된다. 다음의 예제는 URL expression /showCatalog.do를 Controller showCatalog로 포워드하는 방법을 보여준다.


<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
 <property name="mappings">
  <props>
          <prop key="/showCatalog.do">showCatalog</prop>
  </props>
 </property>
</bean> 


Controller showCatalog는 Controller인터페이스를 구현하는 클래스에 의해 구현된 다른 빈처럼 설정될것이다. 이 예제에서, showCatalog는 URL요청을 카테고리로 명명된 ModelAndView컴포넌트로 포워드하는 간단한 포워딩 컨트롤러에 지나지 않는다.


<bean id="showCatalog" name="showCatalog"
class="org.springframework.web.servlet.mvc.ParameterizableViewController">
 <property name="viewName" value="catalog"/>
</bean> 


Struts에서 Spring MVC로의 이전 경로.
Struts애플리케이션을 Spring MVC로 이전하기 위해서는 3가지 접근법이 있다. 몇몇은 애플리케이션을 점차적으로 이전할것이다. 다른것들은 Struts프레임워크를 완벽하게 포기하고 완전히 다시 쓰는 작업을 수행할것이다. 접근법들은 아래에서 개요를 말하고, 이전의 완벽함 순서대로 정렬된다.


1. Spring은 Struts컴포넌트를 가능하게 한다. 천천히 이전하길 원하는 사람들을 위해, 첫번째이고 완벽하게 이전에 따른 무리가 없는것은.? Spring Beans처럼 Struts Actions를 가능하게 하는것이다. 이것은 간단한 작업이고, Spring문서에 잘 설명되어 있다. 이것은 Struts코드에 대한 변경을 요구하지 않지만, 이것은 Spring Beans처럼 처리되기 위해 Struts Controller컴포넌트, Actions를 가능하게 한다. 이 처리로, Actions은 Spring Beans의 상태를 상속한다. 그러므로, Spring Controller처럼 많은 것을 보기 시작하라. 늦으면서 단계별로 현명한 이전은 이 처리로 가능하다. 각각의 Action은 애플리케이션 재작성과 현재 웹 연속물의 중단없이 Spring Controller에 의해 한번에 대체될수 있다.


2. Tiles를 사용하는 Spring Spring프레임워크에 의해 완전히 제공되는 다른 대체물은 순수한 "view" 프레임워크처럼 Tiles를 유지하는 동안 Spring MVC컴포넌트로 Struts Controller과 관련 컴포넌트(Actions, Form Beans, 등등)를 대체하는것이다. Spring MVC는 Tiles에 대한 특정 대안을 가지지 않는다. 그래서 구조는 Tiles에 대한 것을 유지하기로 결정하고 Spring MVC를 통해 그 작업을 하도록 만든다. 이 접근법의 하나의 심각한 단점은 당신이 웹애플리케이션내 두개의 다양한 웹 프레임워크를 효과적으로 유지관리하기 위해 유지관리를 위한 많은 노력과 두가지 프레임워크를 위한 추가적인 학습이 필요하다는 것이다.


3. 완전한 이전 완전한 이전은 Struts프레임워크의 모든 컴포넌트를 Spring MVC로 교체하는것을 의미한다. 이 처리의 마지막에는 Struts특성의 컴포넌트는 애플리케이션에 남지않는다.

'개발도 하냐?' 카테고리의 다른 글

웹접근성  (0) 2008.01.03
오픈아이디로 사용가능한 웹서비스  (0) 2007.07.27
사파리 윈도우용 출시  (0) 2007.07.03
미래를위한선택-웹호환성  (0) 2007.06.18
EMAIL 에러메세지  (0) 2007.04.19

FCKeditor java 버전 설치
- 환경
O/S : Window XP Professional
Servlet Engine : Tomcat 5.0.28
Character Set : UTF-8
IDE Tool : Eclipse 3.2
FCKEditor Version : 2.3.1( http://prdownloads.sourceforge.net/fckeditor/FCKeditor_2.3.1.zip?download )FCKEditor.Java Version 2.3
( http://sourceforge.net/project/showfiles.php?group_id=75348&package_id=129511 )
1. editor 폴더를 생성하고 톰캣 컨텍스트의 루트를 editor 폴더 경로로 지정
2. fckeditor 다운로드
2-1. http://www.fckeditor.net/download/ 에서 다운로드
2-2. editor 폴더에 다운로드 된 압축 파일의 압축을 풉니다.
2-3. 압축을 풀면 나오는 디렉토리인 FCKeditor 폴더를 editor 하위 폴더로 되게끔 이동합니다.


3. 톰캣을 가동한 후 FCKeditor\_samples\default.html 을 실행하여 fckeditor 를 실행


4. 그러나 이미지 업로드를 할려고 서버 보기를 할 경우 에러가 발생합니다.


5. java 버전용 fckeditor 를 editor 폴더로 다운로드(FCKeditor-2.3.zip)
5-1. http://sourceforge.net/project/showfiles.php?group_id=75348&package_id=129511 에서 다운로드
5-2. editor 폴더에 다운로드 된 압축 파일의 압축을 풉니다.


6. 지정폴더\editor\FCKeditor-2.3\web 하위에 있는
_samples 폴더와 WEB-INF 폴더를 각각 이동.
6-1. 2번에서 만들어진 \editor\FCKeditor\_samples 폴더에
\editor\FCKeditor-2.3\web\_samples 폴더를 붙여넣기 합니다.
6-2.  \editor\WEB-INF 폴더에 \editor\FCKeditor-2.3\web\WEB-INF 폴더를 붙여넣기 합니다.


* 새로운 컨텍스트라면 web.xml 을 그대로 덮어씌운 후 복사하고,
기존에 컨텍스트에 다른 체계가 돌아가 있다면 web.xml 내용 중 <web-app> 부분을
기존 사용중인 컨텍스트에 web.xml 에 붙여넣기 합니다.
( load-on-startup 이 이미 있다면 숫자를 변경함 )

완료하면 폴더 구조는 다음과 같습니다.
( UserFiles 디렉토리는 사용자가 업로드한 이미지 저장 디렉토리입니다. )


* 톰캣 리스타트시에 콘솔 창에 다음과 같이 업로드 제한 파일 확장자 리스트가 나옵니다.
( web.xml 파일에 DeniedExtensionsFile 이란 param-name 으로 지정되어 있습니다. )


7. jsp 샘플을 실행
그러나 다음과 같이 fckeditor.html 파일을 찾을수 없다는 메시지가 뜹니다.


\editor\FCKeditor\_samples\jsp\sample01.jsp 내용을 보면
oFCKeditor.setBasePath( "/FCKeditor/" ) ;
위와 같은 부분이 있습니다.


컨텍스트의 루트 폴더가 FCKeditor 이라면 에러 없이 수행되었겠지만
루트가 editor 폴더로 지정되어 있으므로
oFCKeditor.setBasePath( "/editor/FCKeditor/" ) ;
위처럼 수정해주면 제대로 수행되는 것을 확인할수 있습니다.


7-3. 이미지 버튼을 눌러서 서버보기를 눌러보지만 4. 처럼 스크립트 오류가 발생합니다.


8. sample02.jsp 의 태그 라이브러리를 이용한 파일 브라우저 경로 수정
8-1. \editor\FCKeditor\_samples\jsp\sample02.jsp 를 보면 7. 처럼 fckeditor.html 을 찾을수 없다는 메시지가 뜹니다.
<FCK:editor id="EditorDefault" basePath="/FCKeditor/"
위 부분에서 basePath 를 현재 테스트 경로에 맞게끔
<FCK:editor id="EditorDefault" basePath="/editor/FCKeditor/" 로 수정 후 sample02.jsp 를 수정하면
에디터는 잘 나오나 역시 이미지 뷰어나 업로드 부분은 작동하지 않습니다.

sample02.jsp 에선 다음과 같이 브라우저 URL 과 업로드 URL 을 정의한 부분을 볼수 있습니다.
imageBrowserURL="/FCKeditor/editor/filemanager/browser/default/browser.html?Type=Image&Connector=connectors/jsp/connector"
linkBrowserURL="/FCKeditor/editor/filemanager/browser/default/browser.html?Connector=connectors/jsp/connector"
flashBrowserURL="/FCKeditor/editor/filemanager/browser/default/browser.html?Type=Flash&Connector=connectors/jsp/connector"
imageUploadURL="/FCKeditor/editor/filemanager/upload/simpleuploader?Type=Image"
linkUploadURL="/FCKeditor/editor/filemanager/upload/simpleuploader?Type=File"
flashUploadURL="/FCKeditor/editor/filemanager/upload/simpleuploader?Type=Flash"


editor 폴더 하위에 FCKeditor 폴더가 위치한 구조이니 /FCKeditor/editor... 부분 앞에
/editor/FCKeditor/editor... 형식으로 수정하고,


web.xml 의
<servlet-mapping>
 <servlet-name>Connector</servlet-name>
 <url-pattern>/editor/filemanager/browser/default/connectors/jsp/connector</url-pattern>
</servlet-mapping>
<servlet-mapping>
 <servlet-name>SimpleUploader</servlet-name>
 <url-pattern>/editor/filemanager/upload/simpleuploader</url-pattern>
</servlet-mapping> 


위 url-pattern 경로대로 Connector 부분과 UploadURL 을 현재 경로를 예를 들어 재구성하자면
다음과 같이 수정하여 sample02.jsp 을 작성하면 됩니다.
imageBrowserURL="/editor/FCKeditor/editor/filemanager/browser/default/browser.html?Type=Image&Connector=/editor/editor/filemanager/browser/default/connectors/jsp/connector"
linkBrowserURL="/editor/FCKeditor/editor/filemanager/browser/default/browser.html?Connector=/editor/editor/filemanager/browser/default/connectors/jsp/connector"
flashBrowserURL="/editor/FCKeditor/editor/filemanager/browser/default/browser.html?Type=Flash&Connector=/editor/editor/filemanager/browser/default/connectors/jsp/connector"
imageUploadURL="/editor/editor/filemanager/upload/simpleuploader?Type=Image"
linkUploadURL="/editor/editor/filemanager/upload/simpleuploader?Type=File"
flashUploadURL="/editor/editor/filemanager/upload/simpleuploader?Type=Flash"


위 URL은 web.xml 의 url-pattern 과 매핑된다는 점을 이해하셔야 합니다.
이런 특징을 통하여 경로를 판별할수 있습니다.


8-2. 이미지링크,플래쉬 브라우저 및 업로드가 제대로 동작하지 않을 경우...

8-2-1. browser.html 파일의 경로가 틀렸을 경우
basePath 만 수정한 후 위 8-1. 에서처럼 경로를 수정하지 않을 경우
다음과 같은 화면을 볼수 있습니다.


8-2-2. Connector 부분의 경로가 틀릴 경우
Connector 의 경로는 수정하지 않은채 browser.html 의 경로만 옳바르게 설정할 경우
다음과 같은 화면을 볼수 있습니다.


* Connector 의 경로는 web.xml 의 Connector 의 url-pattern 과 관련이 되어있습니다.
8-1. 에서 보신 web.xml 처럼 /editor/filemanager/browser/default/connectors/jsp/connector 으로
지정되어 있따면 Connector 의 주소는
http://서버url/컨텍스트명/editor/filemanager/browser/default/connectors/jsp/connector 이 됩니다.



위 화면처럼 파일을 찾을수 없다는 화면이 아닌 다른 화면이 나오게 되면 맞는 경로이므로
Connector 부분은 http://서버url/ 을 제외한 나머지 주소를 기술하면 됩니다.
( 8-1. 의 Connector 주소 설정 참조 )


* 옳바른 주소 설정에도 불구하고 위 화면에서처럼 Connector 을 브라우저에서 실행했을 때
다른 에러가 발생한다면 XML 을 생성하는 xalan 콤포넌트가 존재하는지 의심해봐야 합니다.


왜 에러가 발생하는지 보기 위한 테스트URL)
http: //서버url/컨텍스트명 /editor/filemanager/browser/default/connectors/jsp/connector?Command=GetFoldersAndFiles&Type=Image&CurrentPath=/


위 화면에서처럼
javax.xml.transform.TransformerFactoryConfigurationError: Provider org.apache.xalan.processor.TransformerFactoryImpl not found
에러가 발생한다면 Xerces-J-tools의 xalan.jar 를(http://www.apache.org/dist/xml/xerces-j/)

찾아 다운로드 하여 \WEB-INF\lib 폴더에 넣은 후 톰캣 재가동후 새로운 브라우저에서
테스트 URL 을 확인해보면 다음과 같이 에러 없이 XML 화면이 나오는 것을 확인할수 있습니다.


8-2-3. 업로드 URL 의 확인
Connector 와 마찬가지로 web.xml 의 SimpleUploader 의 url-pattern 의 영향을 받습니다.
위 web.xml 에선 url-pattern 이 /editor/filemanager/upload/simpleuploader 이므로
테스트 URL)
http://서버url/컨텍스트명/editor/filemanager/upload/simpleuploader 을 쳤을 경우 다음과 같은 화면이 나와야 정상입니다.


위 결과대로 나온다면 image,link,flash UploadUrl 을 설정하면 됩니다.( 8-1. 의 각 UploadUrl 확인 )


9. 테스트
이미지를 업로드하고, 목록에 정상적으로 출력된다면 모든 설치가 성공적으로 완료된 것입니다.


10. 샘플이 아닌 기존 체계에 fckeditor 를 적용할 경우.
태그 라이브러리 사용을 위한
<%@ taglib uri="http://fckeditor.net/tags-fckeditor" prefix="FCK" %> 를 페이지 상단에 삽입 하고,
<TEXTAREA></TEXTAREA> 부분에 sample02.jsp 의 <FCK:editor ~ </FCK:editor> 부분을 복사하여 붙여넣기 합니다.
기본 sample02.jsp 에는 <FCK:editor id="EditorDefault" 처럼 id 가 EditorDefault 로 되어있는데
만약 <TEXTAREA name = "contents" 와 같이 name 이 contents 였다면
<FCK:editor id="contents" 로 지정하면 받는 부분에서 contents 로 받을 수 있습니다.


예)
- \editor\board\create_form.jsp(UTF-8 로 작성)

<%@ taglib uri="http://fckeditor.net/tags-fckeditor" prefix="FCK" %>

<%@ page contentType = "text/html;charset=utf-8" %>
<HTML>
<HEAD>
<TITLE>글 입력 폼</TITLE>
<META http-equiv = "Content-Type" content = "text/html;charset=utf-8" />
<SCRIPT>
 function send()
 {
  create_form.submit();
 }
</SCRIPT>
</HEAD>
<BODY>
<FORM name = "create_form" method = "post" action = "./create.jsp">
 <FCK:editor id="contents" basePath="/editor/FCKeditor/"
  imageBrowserURL="/editor/FCKeditor/editor/filemanager/browser/default/browser.html?Type=Image&Connector=/editor/editor/filemanager/browser/default/connectors/jsp/connector"
  linkBrowserURL="/editor/FCKeditor/editor/filemanager/browser/default/browser.html?Connector=/editor/editor/filemanager/browser/default/connectors/jsp/connector"
  flashBrowserURL="/editor/FCKeditor/editor/filemanager/browser/default/browser.html?Type=Flash&Connector=/editor/editor/filemanager/browser/default/connectors/jsp/connector"
  imageUploadURL="/editor/editor/filemanager/upload/simpleuploader?Type=Image"
  linkUploadURL="/editor/editor/filemanager/upload/simpleuploader?Type=File"
  flashUploadURL="/editor/editor/filemanager/upload/simpleuploader?Type=Flash">
  This is some <strong>sample text</strong>. You are using <a href="http://www.fredck.com/fckeditor/">FCKeditor</a>.
 </FCK:editor>
</FORM>
<INPUT type = "button" onClick = "return send()" value = "전송">
</BODY>
</HTML>


- \editor\board\create.jsp(UTF-8 로 작성)

<%@ page contentType = "text/html;charset=utf-8" %>
<%
 String contents = request.getParameter("contents");

 contents = new String(contents.getBytes("8859_1"), "UTF-8");
%>
<HTML>
<HEAD>
<TITLE></TITLE>
<META http-equiv = "Content-Type" content = "text/html;charset=utf-8" />
</HEAD>
<BODY>
<%= contents %>
</BODY>
</HTML>


11. 몇가지 Tip.
11-1. 공백 값 입력을 방지하기 위해선 스크립트를 다음과 같이 수정합니다.

/**
 * 데이터 전송전 체크
 */
function send()
{
 var oEditor = FCKeditorAPI.GetInstance('contents') ;

 var div = document.createElement("DIV");
 
 div.innerHTML = oEditor.GetXHTML();

 if( isNull( div.innerText ) )
 {
  alert("내용을 입력하세요."); 
  oEditor.Focus();
  return false; 
 }

 create_form.submit();
}

/**
 * 정규표현식을 이용한 공백 체크
 */
function isNull( text ) 

 if( text == null ) return true; 

 var result = text.replace(/(^\s*)|(\s*$)/g, ""); 

 if( result ) 
  return false; 
 else 
  return true; 
}



11-2. 페이지 로딩시 바로 포커스를 주고 싶다면
\editor\FCKeditor\fckconfig.js 의 FCKConfig.StartupFocus 의 값을 true 로 변경하거나

태그라이브러리 옵션으로 startupFocus="true" 를 설정합니다.


11-3. 읽기 전용으로 변환하고 싶다면

var oEditor = FCKeditorAPI.GetInstance('contents') ;
oEditor.EditorDocument.body.contentEditable = false;
oEditor.EditorDocument.body.unselectable = true;


11-4. 기타 환경 설정은 fckconfig.js 파일을 참조하고 아래 사이트를 참조하시기 바랍니다.
http://sourceforge.net/forum/forum.php?forum_id=257180 ( fckeditor help 포럼 )
http://java.lin4u.com/my/index.php?category=&keyfield=title&keyword=fck&favorite ( 폰트 관련 참조 )
http://wiki.fckeditor.net/ ( fckeditor 위키 사이트 )

http://www.ghlab.com/blog/fckeditor/editor.zip ( 위 샘플들을 테스트한 컨텍스트 모든 파일들 )

출처 : Tong - 디트리히님의 자바관련통

사용자 삽입 이미지

PCI-X 와 PCI-Express 는 호환되지 않는다.

'삽질로그' 카테고리의 다른 글

자바에 사용되는 용어들  (0) 2007.07.26
FCKeditor java 버전 설치  (0) 2007.07.26
소프트웨어기술자 등급별 노임단가기준(2008)  (0) 2007.07.09
[펌]자격증정보  (0) 2007.07.09
오라클설정내용  (0) 2007.07.05

All about google!


특집 2부 성공의 원천, 탄탄한 기술 인프라 대해부


노희섭 | 시니어 개발자


구글은 처음부터 다른 서비스와는 차별되는 검색엔진과 아키텍처, 새로운 개념의 랭킹 모델들을 사용함으로써 그간의 웹 검색에 대한 개념을 크게 바꾸어 놓았다. 구글의 기술은 검색 업계에서 일하는 개발자들은 물론 일반 개발자들까지도 관심을 갖게 만드는데, 그 핵심은 탄탄한 기반 기술들과 그것들을 하나로 묶는 거대한 프레임워크에 있다. 이번 특집 2부를 통해 구글의 기술이 어떤 그림을 갖고 있는지에 대해 이해할 수 있는 시간이 될 것으로 기대한다.


구글 검색엔진


검색엔진은 대상이 되는 문서들을 수집하고, 수집된 문서들로부터 키워드를 추출하여 키워드-문서 간의 역 색인(inverted index)을 생성한 후, 사용자의 질의어(query)를 입력받아 해당 쿼리를 역 색인 구조를 찾아, 매칭된 문서를 결과로 반환해 준다. 구글의 검색엔진 역시 이러한 전통적인 검색엔진의 구조와 크게 다르지 않다. 구글의 검색엔진은 웹 문서들을 수집하고, 웹 문서들로부터 키워드를 추출하여 역 색인 구조를 생성하고, 생성된 역 색인 구조로부터 질의어를 매칭하여 결과를 반환해준다. 그러나 구글의 검색엔진은 기존의 검색 시스템과는 스케일이나 기능 면에서 많은 차이를 보여준다.


전통적인 키워드 매칭(keyword matching)을 기반으로 한 자동화된 검색엔진(automated search engine)은 몇 가지 약점을 갖고 있었다. 기본적으로 낮은 질의 매칭 결과가 너무 빈번하게 나타났다. 게다가 광고주들이 웹 문서에 포함된 키워드들을 조작해 엉뚱한 결과가 노출되도록 하는 것이 가능했다. 구글은 이런 문제점을 해결하기 위해 웹 문서의 하이퍼텍스트에 존재하는 부가적인 구조적 정보들을 사용하기 시작했다. 또한 방대한 웹 문서 데이터들을 처리하기 위해 매우 거대한 스케일의 검색 아키텍처를 구축했다.


구글 검색엔진의 지향점


웹을 효율적으로 검색하기 위해서는 몇 가지의 필수적인 기술들이 요구된다. 웹 문서들을 신속하고 효율적으로 수집하고, 수집된 데이터들을 최신의 상태로 유지하기 위한 크롤링(crawling) 기술, 대용량 데이터 처리를 위해 효율적으로 공간을 사용할 수 있는 색인 구조, 대용량 데이터를 신속하게 처리할 수 있는 색인기(indexer) 기술, 다량의 질의어들을 처리할 수 있는 질의어 분석/처리 시스템 등이 그것이다.


웹이 성장하면서 이러한 기술들이 감당해야 하는 목표들은 급격하게 상향 조정된다. 게다가 단순히 하드웨어의 발전만으로는 웹의 발전 속도를 감당할 수 없다. 하드웨어의 발전이 검색 시스템의 성능을 증가시키지만, 기본적으로 디스크 탐색 시간(disk seek time)이나 운영체제의 강력함(robustness)은 그렇게 주목할 만한 요소가 아니다. 구글 검색엔진은 극단적으로 큰 데이터 셋(data set)을 커버하기 위한 확장형 구조이며, 효율적인 색인 구조를 사용함으로써 데이터에 대한 신속하고 효율적인 액세스가 가능하도록 최적화된 구조이다.


웹 검색의 초창기에 많은 사람들이 검색엔진의 색인이 완전하고 무결성을 갖는다면 어떤 키워드에 대해서도 원하는 웹 문서를 검색할 수 있다고 믿었다. 그러나 웹 검색이 발전하면서 색인의 완전성과 무결성이 검색 품질을 좌우하는 유일한 요소가 아님이 밝혀졌다. 웹 검색은 일반적으로 입력되는 질의어에 대해 매칭되는 문서의 개수가 대단히 많다. 즉, 검색 대상이 되는 색인 내에서 검색 결과로 재현될 수 있는 비율이 대단히 크다. 그러나 일반적인 사용자들은 많은 검색 결과 중에서 상위의 일부 결과만을 보고 검색 결과의 모든 품질을 평가하려는 성향이 있다. 관련 있는 검색 결과가 상위에 랭크되어 있지 않고 몇 십 페이지 뒤에 랭크되어 있다면, 그것을 찾기 위해 페이지를 클릭할 사용자는 그렇게 많지 않다. 따라서 사용자의 만족감을 충족시키기 위해서는 극도로 높은 정확도에 기반한 검색 결과를 제공해야 한다. 정확도는 대용량 데이터의 검색 결과 품질을 좌우하는 요소이기 때문에, 재현율을 희생해서라도 정확도를 확보하는 것이 사용자들의 만족감을 위해 가장 중요하다⑴.


구글 검색엔진은 이러한 이유로 정확도 중심의 엔진으로 설계됐다. 구글의 정확도는 극도의 관계성 판단(relevance judgement)에 의해 산출되는데, 그 기반에는 링크 구조와 앵커 텍스트(anchor text)를 분석한 정보에 의한 질적인 필터링(filtering)이 존재한다. 구글은 이러한 정보들의 정확도를 높이는 두 가지 방법을 사용한다. 하나는 개별 웹 페이지의 품질 순위 할당을 위한 페이지 랭크 알고리즘이고, 다른 하나는 검색 결과 개선을 위한 앵커 텍스트 사용이다.


참고로, 구글이 검색엔진을 발표했던 초창기에는 또 한 가지 목표를 가지고 있었다. 그것은 대용량 웹 문서들과 대용량 트래픽을 감당할 수 있는 거대한 웹 시스템을 만들고, 실제로 많은 사용자들이 그것을 사용하면서 얻는 데이터(usage data)를 학술적인 연구에 제공하겠다는 것이었다.


구글 검색엔진의 특징


페이지 랭크의 사용


웹 문서에 존재하는 레퍼런스(링크) 그래프는 구글 검색엔진이 거의 최초로 주목한 요소이다. 페이지 랭크는 이러한 요소들로부터 사용자들이 생각하는 특정 페이지의 중요성(importance)에 부합하는 정확도(precision)의 객관적인 척도를 산출해낸다. 사용자들의 생각과 관련을 갖기 때문에 페이지 랭크는 웹 문서에 순위를 할당하는데 매우 합리적인 수단이다. 질의어를 문서 제목과 매칭되는지 여부만을 평가하는 단순한 텍스트 검색엔진에는 물론, 풀 텍스트(full text, 제목과 내용을 모두 포함) 검색엔진이나 페이지 랭크로 순위를 매기는 경우에도 상당한 성능을 보여주기 때문이다.


페이지 랭크는 한 페이지의 인용 횟수(백 링크, back link)를 카운팅하는 방식으로 계산된다. 한 페이지가 얼마나 많은 레퍼런스를 받고 있느냐의 수준이 그 페이지의 중요성이나 품질(quality)을 추정할 수 있는 요소로 간주된다. 페이지 랭크는 이 기본적인 아이디어를 확장하여 그 링크가 어떤 페이지에서 왔는지를 차별화하고, 링크하는 페이지에서 외부로 나가는 총 링크 개수로 노멀라이징(normalizing)을 수행했다.


페이지 랭크를 간략하게 정리하자면 다음과 같다. 페이지 A를 링크하는 다른 페이지들의 set을 (T1, T2, T3, ...., Tn)이라고 한다면, 파라미터 d는 0~1 사이의 값을 갖는다. C(A)는 페이지 A에서 외부로 나가는 아웃 링크(out link)의 개수이다. 이 때 페이지 A의 페이지 랭크 값 PR(A)은 다음과 같은 수식으로 표현된다.


페이지 랭크 PR(A)은 반복 알고리즘(iterative algorithm)으로 계산할 수 있으며, 그 값은 웹 링크를 노멀라이징해서 행렬로 바꾸었을 때 주 고유 벡터(principal eigen-vector)에 해당한다. 참고로 이것은 약 2600만 페이지의 페이지 랭크를 계산하는데 중급의 워크스테이션으로 수 시간 내에 연산이 가능한 수준이다.


페이지 랭크는 또한 사용자의 행동 패턴을 모델링하고 있다. 무작위로 선택한 하나의 웹 페이지에서 출발해서 백 버튼을 누르지 않은 상태로 계속 링크를 따라 네비게이션하는 랜덤 서퍼(random surfer)는 네비게이션 도중 지루해지면 다시 무작위로 페이지를 선택해서 네비게이션을 시작한다. 한 페이지의 페이지 랭크는 랜덤 서퍼가 그 페이지를 방문할 확률을 나타낸다. 페이지 랭크에서 주요 파라미터 중 하나가 댐핑 팩터(damping factor) d이다. 페이지 랭크에서는 파라미터 d를 특정 페이지 하나 또는 일련의 페이지에만 선택적으로 적용함으로써 개인화(personalization)를 가능하게 하며, 페이지에 대한 랭킹을 올리기 위한 속임수(abusing)를 사실상 불가능하게 만들 수 있다.


페이지 랭크의 직관적인 요소 중 또 하나는 페이지 랭크 값이 커지기 위해서는 많은 페이지가 어떤 한 페이지를 집중적으로 레퍼런스하고 있거나, 특정 페이지를 레퍼런스하는 페이지 자체의 페이지 랭크 값이 커야 한다는 것이다. 예를 들어 많은 페이지로부터 인용되고 있는 페이지는 살펴볼 만한 가치가 있는 것이고, 야후 같은 메이저 페이지(major page)에서 링크되고 있는 페이지는 그렇지 않은 페이지보다 중요하다고 간주되는 것이다. 페이지 랭크에 대한 더 자세한 내용은 뒤에서 따로 다루겠다.


앵커 텍스트의 사용


구글 검색엔진은 링크의 텍스트 자체를 특별하게 취급한다. 대부분의 검색엔진들은 링크의 텍스트(앵커 텍스트)를 링크를 담고 있는 페이지 자체의 정보 중 일부로만 취급하고 있지만, 구글의 검색엔진은 링크가 가리키고 있는 페이지를 링크의 텍스트와 연관시켜 처리한다. 이런 방법은 몇 가지 장점을 가진다. 첫째, 앵커 텍스트는 링크를 담고 있는 페이지에 대한 설명보다 링크가 가리키고 있는 페이지에 대해 더 정확한 설명을 담고 있는 경우가 대부분이다. 둘째, 일반적인 텍스트 검색엔진이 색인할 수 없는 이미지나 프로그램, 데이터베이스로의 앵커(링크)도 존재할 수 있다. 따라서 앵커를 사용한다면 크롤링되지 않는 웹 페이지들까지도 찾아낼 수 있다. 물론 이러한 링크에 걸려있는 대상들은 검색에 유효하지 않은 대상일 수 있으므로 사용자에게 보여주기 전에 먼저 유효성 검사를 통과해야 한다. 존재하지 않는 페이지를 가리키는 앵커의 경우에도 유효성 검사를 거치면 큰 문제는 없다.


앵커 텍스트를 그 앵커가 가리키는 페이지로 전파시켜 나간다는 아이디어는 World Wide Web Worm(WWWW) 검색엔진에서 먼저 구현됐다. 앵커 텍스트가 텍스트 이외의 데이터에 대한 검색을 용이하게 해 주었고, 검색엔진이 크롤링한 웹 문서보다 훨씬 더 많은 영역을 포괄하게 해주는 것에 이 아이디어의 유용성이 있다. 다만, 이를 위해서는 대용량 데이터 처리를 위한 구조가 필수적이다.


그 밖의 특징


페이지 랭크와 앵커 텍스트에 대한 접근 방식 외에도 구글 검색엔진은 몇 가지 특징을 갖는다. 첫째, 구글 검색엔진은 문서로부터 추출된 모든 키워드들에 대한 위치 정보(positional information)를 저장한다. 위치 정보의 저장은 검색 수행 시 근접도의 광범위한 사용을 가능케 한다. 둘째, 구글은 문서 내에서 추출된 키워드의 폰트 크기, 대소문자 여부 등에 대한 부수적이고 시각적인 세부 요소들을 추적한다. 폰트 크기가 큰 단어나 볼드체로 된 단어, 대문자로 작성된 단어의 경우에는 그렇지 못한 단어에 비해 더 높은 가중치(weight)가 부여된다. 셋째, 구글 검색엔진은 수집된 웹 문서를 완전한 HTML 형식으로 압축 저장하기 때문에 이를 활용할 수 있는 여지가 있다.


<그림 1> 구글 검색엔진의 아키텍처


구글 검색엔진의 전반적인 구조


지금까지 구글 검색엔진의 특징을 살펴보았고, 이제는 구글 검색엔진의 구조에 대해 알아보자. <그림 1>은 구글 검색엔진의 아키텍처를 표현하고 있다. 구글 검색엔진의 구조는 일반 검색엔진과 큰 차이가 없다. 구글 검색엔진은 크게 웹 문서를 수집하는 크롤러(crawler) 영역과, 역 색인(inverted index)을 생성하는 색인기(indexer) 영역, 그리고 검색을 수행하는 검색기(searcher) 영역으로 구분된다. 구글 검색엔진이 데이터를 수집하고 색인을 생성하여 검색을 수행하는 전반적인 시퀀스는 다음과 같다.


크롤링

- 분산 배치된 크롤러에 의해 웹 페이지들이 다운로드된다.
- 크롤러가 수집한 문서들은 URL server로 보내져서 URL list로 변환된다.
- 크롤러로부터 패치(fetch)된 웹 문서들은 Store server에 저장된다.
- Store server에 저장된 웹 문서들은 압축되어 리파지토리에 저장된다.
- 저장된 웹 문서들은 특정한 docID를 부여받는다.


색인

- Indexer가 리파지토리를 읽어 압축된 웹 문서들의 압축을 해제한다.
- Indexer가 압축 해제된 웹 문서를 파싱하여 문서에 포함된 부수적인 정보(위치 정보, 폰트 크기, 대소문자 여부)와 함께 추출한 키워드 정보(Hits라고 불린다)의 set을 생성하고, 링크들을 분석하여 링크의 방향성과 앵커 텍스트들을 추출해서 anchor file을 생성한다.
- Indexer가 문서 당 추출된 키워드들의 set을 Barrel에 일부분 정렬이 이루어진 forward index 형태로 분산 저장한다.
- URL resolver가 anchor file을 분석하여 상대 URL(relative URL)을 절대 URL(absolute URL)로 변환하고, 변환된 URL 정보를 Barrel에 저장되어 있는 forward index의 docID와 조합한다.
- Sorter가 Barrel에 docID 순으로 정렬되어 있는 정보를 키워드 별로 정렬하여 wordID를 할당한다.
- Indexer가 wordID 순으로 정렬된 정보를 이용하여 최종적으로 역 색인(inverted index)을 생성하여 Lexicon에 저장한다.


<그림 2> 라파지토리의 자료구조


검색

- 입력 받은 질의어를 분석한다.
- Lexicon을 뒤져서 분석을 통해 추출된 키워드에 해당하는 wordID를 찾는다.
- 발견된 wordID에 해당하는 doclist의 시작 위치를 Barrel을 뒤져서 찾는다.
- doclist를 스캔하여 입력된 search term과 매칭되는 도큐먼트들을 찾는다.
- 탐색된 도큐먼트들에 대해서 페이지 랭크를 계산한다.


구글 검색엔진의 자료구조


구글 검색엔진은 기본적으로 대용량 데이터를 다룬다. 기본적인 정보 외에도 부수적인 정보들을 충분히 다루고 있는 만큼 모든 색인 구조를 비롯한 자료구조는 매우 효율적이고 최적화돼 있어야 한다. 머신의 성능은 급격하게 발전하고 있지만 디스크 I/O 속도는 크게 변함이 없는 현실에서 자료구조는 훨씬 더 중요한 위치를 차지한다. 다음은 구글 검색엔진에서 사용하고 있는 자료구조들이다. 구글 검색엔진의 자료구조를 살펴보면, 구글 검색엔진의 내부 프로세스와 구조를 더 자세히 볼 수 있다.


리파지토리
리파지토리는 크롤러에 의해 수집된 웹 문서의 full HTML을 zlib를 이용해 압축, 저장한다(zlib은 다른 압축 솔루션에 비해 압축과 압축 해제 속도가 뛰어나다). 리파지토리에 저장되는 각 웹 문서들은 docID를 prefix로 사용하여, 기타 정보들을 함께 묶은 형태의 자료구조로 표현된다. 웹 문서의 consistency 유지나 크롤러의 에러는 리파지토리의 모든 자료구조를 재생성(rebuilding)함으로써 해결한다. <그림 2>는 리파지토리의 자료구조를 나타낸 그림이다.


도큐먼트 인덱스(Document Index)
도큐먼 트 인덱스는 각 도큐먼트의 정보들을 저장하며, 기본적으로 docID에 의해 정렬된 fixed width ISAM(Index sequential access mode)이다. 이것은 도큐먼트에 대한 추가적인 정보로 도큐먼트의 상태 정보, 리파지토리 내에서의 해당 도큐먼트에 대한 위치, 도큐먼트 체크섬(checksum), 기타 수치적 정보들을 포인터로 담고 있다. 포인터 정보만 사용함으로써 콤팩트한 자료구조의 구성이 가능하며, 검색을 수행하는 동안 디스크 탐색 시간을 줄일 수 있다. 추가로, 도큐먼트의 정보 중 URL과 docID의 관계를 저장해 두기 위해 URL을 docID로 변환한 관계를 저장하는 파일이 존재한다. 이것은 URL 체크섬을 키(key)로 갖고, docID를 데이터로 갖는 자료구조로 일반적인 btree(binary tree) 검색과 유사한 방식에 의해, URL 체크섬을 키로 던져 해당 URL의 docID를 찾아내는데 사용된다. 이 방식은 URLresolver가 URL을 docID로 변환하는데 사용된다.


Lexicon
Lexicon은 실제 검색을 수행할 때 반드시 필요한 역 색인 구조를 만들기 위한 자료구조이다. 검색엔진의 성능과 처리 가능한 용량이 대부분 Lexicon과 역 색인 구조에 기반해 결정되기 때문에 Lexicon의 자료구조는 검색엔진의 전체 구조 중 매우 중요한 요소를 차지한다. 검색엔진의 속도 향상을 위한 기초적인 접근 방식은 Lexicon을 메모리에 구동 가능한 크기로 쪼개는 것이다. 초기 구글 검색엔진의 경우에는 256MB 메인 메모리에 올라갈 수 있는 크기로 설계됐고, 256MB 안에 1,400만 개의 단어를 올릴 수 있었다. 구글의 Lexicon은 추출된 단어들의 리스트와 포인터의 해시(hash) 테이블, 두 가지 요소로 구성된다.


Hit Lists
Hit는 하나의 도큐먼트에서 추출된 하나의 단어에 대한 부가적인 위치 정보, 폰트 정보, 대문자 여부 등의 집합이다. Hit List는 forward index와 inverted index에서 모두 사용되며 검색엔진 내의 정보 중 상당 부분을 차지하기 때문에 가능한 효율적인 구조를 가져야 한다. 구글 검색엔진은 하나의 hit를 2바이트로 인코딩하는 방식을 취한다.

Hit는 다시 각 도큐먼트에서 URL, title, anchor text, meta tag로부터 추출된 정보를 저장하는 fancy hit, anchor text로부터 정보를 추출된 정보를 저장하는 anchor hit, 그리고 그 밖의 요소들로부터 추출되는 plane hit 등 3개의 hit로 구분된다. <표 1>은 인코딩된 fancy hit과 plane hit, anchor hit의 구조를 나타낸다.

Anchor hit에 포함된 4비트짜리 해시는 해당 anchor가 출현한 웹 문서의 docID에 대한 해시 값을 저장한다. 이것은 anchor file에 저장되어, 랭크 산출에 가중치 요소로 사용된다. 최종적으로 hit list들은 Barrel에 forward index를 구성하면서 wordID를 기준으로 저장되고, inverted index에 docID를 기준으로 저장된다.


Forward Index
Forward Index는 도큐먼트에 대한 docID를 기준으로 추출된 hit list를 wordID와 함께 붙여서 barrel에 분산해놓은 구조이다. Barrel 자체가 wordID의 특정 range에 대해 분산되도록 설계되어 있기 때문에 docID가 중복 저장될 가능성이 있다. 하지만 inverted index를 구성할 때 Sorter에 의해 wordID를 중심으로 재구성되어야 하기 때문에, 실제로는 이와 같은 방식이 조금 더 효율적일 수 있다. Barrel 내에 forward index가 저장될 때는 wordID 24비트와 hit list length에 대한 정보가 8비트 추가된다.


Inverted Index
Inverted Index는 forward index가 Sorter에 의해 wordID 순으로 정렬된 구조이다. 유효한(valid) wordID는 Lexicon에 저장되고, 각 wordID가 속한 도큐먼트에 대한 docID는 Barrel 내에 역 색인으로서 저장된다. Lexicon의 각 wordID는 inverted barrel 내의 docID를 가리키는 포인터를 갖는다.


<그림 3>은 Forward Index, Inverted Index, Lexicon의 구조에 대한 그림이다. Forward Barrel에 저장된 docID의 리스트는 최종적으로 Lexicon과 Inverted Barrel에 저장되면서 최종적인 역 색인 구조를 구성하게 된다.


<그림 3> Forward/Bcakward Index와 Lexicon의 자료구조


<표 1> 인코딩된 fancy hit과 plane hit, anchor hit의 구조
구분 내용
Plane Hit capitalization: 1 font info: 2 position: 12
Fancy Hit capitalization: 1 font info: 7 type; 4 position: 8
Anchor Hit capitalization: 1 font info: 7 type; 4 hash: 4 position: 4

<표 2> 구글 검색엔진의 퍼포먼스 수치 정보
Storage Statistics
Total Size of Fetched Pages 147.8GB
Compressed Repository 53.5GB
Short Inverted Index 41GB
Full Inverted Index 37.2GB
Lexicon 293MB
Temporary Anchor Data 6.6GB
Document Index Incl. Variable Width Data 9.7GB
Links Database 3.9GB
Total without Repository 55.2GB
Total with Repository 108.7GB
Web Page Statistics
Number of Web pages fetched 24 million
Number of URLs seen 76.5 million
Number of Email Address 1.7 million
Number of 404's 1.6 million
Search Times
  Initial Query Same Query Repeated
Query CPU time Total time CPU time Total time
al gore 0.09 2.13 0.06 0.06
vice president 1.77 3.84 1.66 1.8
hard dixks 0.25 4.86 0.2 0.24
search engine 1.31 9.63 1.16 1.16

지금까지 구글 검색엔진에 대한 특징과 아키텍처, 자료구조에 대해 살펴보았다. 구글이 등장한지 많은 시간이 흘렀지만, 구글의 검색엔진은 여전히 최적화된 혁신적인 구조로 개발자들에게 받아들여지고 있다. 많은 검색엔진들은 여전히 구글 검색엔진을 벤치마크 대상으로 이용하고 있고, 구글 검색엔진이 갖고 있는 합리적인 랭킹 모델이나 데이터 처리 모델과 자료구조는 많은 검색엔진이 닮고 싶어하는 요소들이다.


현대적 랭킹 모델, 페이지 랭크 알고리즘


구글은 처음 등장할 때 대량의 웹 페이지 데이터들에 대한 새로운 개념의 랭킹 모델 적용으로 가장 주목받았다. 페이지 랭크라 불리는 이 랭킹 모델(ranking model)은 각 웹 페이지들의 중요성(importance) 을 기반으로 계산(scoring)된, 사용자 입장에서 상당히 정확해 보이는 랭킹을 제공한다.


세르게이 브린(Sergey Brin)이 제안한 페이지 랭크 알고리즘은 웹 페이지의 중요성에 기반을 둔 일종의 보팅 알고리즘(voting algorithm)으로, 사용자 중심의 주관적 영역에 놓여있던 ‘중요성’을 상대적이고 기계적인 관점에서 정량화가 가능한 객관적 영역으로 변환시킨다. 이것은 기존의 야후나 기타 검색엔진들이 제공했던 사람이 직접 웹 페이지의 중요도를 등록하여 결과로 제공하는 것이 웹 페이지의 랭크라고 믿어오던 사람들의 생각을 완전히 바꿨다. 구글은 모든 페이지들의 중요도를 인터넷에서 웹 페이지를 생산해내는 사람들과 사용자들이 웹 페이지에 접근하는 행태를 분석하여 자동으로 랭킹이 계산되는 구조를 만들어 냈다. 인력으로 랭킹을 처리하는 데에는 한계가 있었기 때문에, 비교할 수 없을 정도로 훨씬 더 많은 데이터들에 대해 유효해 보이고 자동화된 랭킹을 제공한 구글은 단숨에 검색 사용자들의 이목을 끌 수밖에 없었다.


<그림 4> 역 링크: 링크 A와 링크 B는 페이지 C에 대한 역 링크이다.


랭크를 갖는 링크: 링크를 통한 랭킹의 전파


웹 링크의 중요성에 대한 접근은 구글 이전에도 있었는데 대부분 웹 공간 상에서 링크는 논문에 기재되는 학술적 레퍼런스와 유사한 개념으로 보아, 레퍼런스 구조를 분석하고 중요성을 계산하는 테크닉들이 대부분이었다. 예를 들어, 학술적으로 자주 인용되는 논문은 그렇지 않은 논문에 비해 중요한 논문일 가능성이 크다고 보는 것이다. 페이지 랭크의 기본적인 아이디어는 웹 상의 이러한 레퍼런스 구조를 웹 공간의 링크 구조로 더욱 포괄적으로 확장하는 데 있다.


웹 페이지는 그 페이지에서 밖으로 나가는 순 링크(forward link, outedge)와 외부에서 그 페이지를 가르키는 역 링크(back link, inedge)를 포함한다. 기본적으로 페이지 랭크에서 측정되는 웹 도큐먼트의 중요성은 웹 도큐먼트의 컨텐트와 상관없이 그 웹 도큐먼트가 갖고 있는 링크 구조를 분석함으로써 측정된다.


페이지 랭크에서 중요성에 대해 가장 주요한 요소로 간주된 것은 링크가 많이 된 페이지가 그렇지 못한 페이지보다 대부분 더 중요하다는 가정이었다. 역 링크라 불리는, 외부 페이지로부터의 레퍼런스 횟수는 중요성을 계산하는데 기본적인 요소로 사용되었다. <그림 4>는 역 링크의 일반적인 형태를 나타낸다.


하지만 역 링크의 개수를 세는 것만으로 중요성을 매기는 것은 유효하지 않을 수도 있다. 어떤 웹 페이지가 달랑 야후 하나에 링크되어 있다면 그 도큐먼트는 단 1개의 역 링크를 갖고 있지만, 그 링크는 중요하지 않은 페이지로부터의 역 링크 몇 개보다 훨씬 더 중요한 링크라고 간주될 수 있다. 페이지 랭크는 링크를 통해 랭킹을 전파하는 구조이다. 모든 역 링크에는 랭크 값이 있고, 랭크 값이 높은 역 링크의 레퍼런스를 많이 갖는 웹 도큐먼트일수록 웹 도큐먼트의 랭크가 올라간다.


페이지 랭크의 개념


페이지 랭크를 단순하게 모델링한다면 다음과 같은 간단한 수식으로 표현할 수 있다.


어떤 웹 페이지를 u라고 하고, 웹 페이지 u가 레퍼런스하고 있는 페이지의 집합을 Fu, 웹 페이지 u를 역 링크하고 있는 페이지의 집합을 Bu로 표현한다. Nu는 웹 페이지 u로부터 나가는 순 링크의 개수(| Fu |)이다. c는 웹 페이지의 랭크 총합을 일정 레벨로 맞추기 위한 노멀라이징 팩터(normalizing factor)이다. <그림 5>는 페이지 랭크가 계산되는 방식을 간단하게 보여준다.


그러나 웹 공간 상의 복잡한 링크 구조는 이와 같은 수식으로 해결하기 어려운 그래프를 구성하기도 하는데, 랭크 싱크(rank sink)와 댕글링 링크(dangling link)가 그것이다 ⑵. 페이지 랭크에서는 이런 문제를 해결하기 위해 사용자 정의 파라미터를 하나 더 둔다. 다음은 사용자 정의 파라미터 E가 추가된 페이지 랭크 모델을 표현한다.


추가 파라미터 E(u)는 웹 페이지 u로부터 또 다른 특정 페이지로 이탈할 확률 분포에 대한 모델이다. 앞서 검색엔진을 설명하면서 잠시 거론되었던 페이지 랭크의 사용자 행동 패턴에 대한 모델링(랜덤 서퍼 모델)이 바로 파라미터 E이다. 즉, 파라미터 E는 랜덤 서퍼가 특정 확률 주기에 의해 다른 페이지로 이탈하는 것을 의미하며 이것은 댕글링 링크를 이탈하는 행동의 모델링으로 볼 수 있다. 구글 검색엔진은 일반적으로 모든 페이지에 동일한 확률 주기의 E 값을 셋팅하여, 모든 서퍼들이 주기적으로 링크의 그래프를 이탈한다고 보지만 E 값을 특정 페이지로 지정함으로써, 개인화된 페이지 랭크 모델을 만들 수도 있다.


만약 2개의 페이지 랭크 모델을 만들어서 하나는 E를 일반 포탈 사이트의 홈페이지로, 나머지 하나는 E를 컴퓨터 사이언스 관련 커뮤니티의 홈페이지로 셋팅한다면, 일반 포탈 쪽 랭크보다 컴퓨터 사이언스 관련 커뮤니티 쪽의 랭크들이 더 큰 값을 가지게 될 것이다.


페이지 랭크의 구현


페이지 랭크는 일반적인 재귀 연산(recursive operation)의 형태이지만, 효율성을 위해 컴퓨터 상에서는 벡터의 형태로 변환되어 계산된다. 이에 관련된 정보를 얻고 싶다면 Taher H. Haveliwala가 쓴 『Efficient Computation of PageRank(Stanford Technical Report, 1999)』를 참조하기 바란다. 페이지 랭크가 컴퓨터 상에서 처리되는 방식은 다음과 같다.


 R0 ← S loop : Ri + 1 ← ARi d ← ||Ri||1 - ||Ri + 1 ||1 Ri + 1 ← Ri + 1 + dE δ ← ||Ri + 1 - Ri||1 while δ > ∈

S는 한 웹 페이지의 초기 벡터 값이다.
Ri는 i번째 페이지 랭크 벡터 값을 나타낸다.
||R||1은 벡터 R의 노름(norm) 값이다.
d는 댐핑 팩터(damping factor)이다.
A는 한 웹 페이지 u에서 다른 웹 페이지 v로 연결되는 포워드 링크의 개수의 역수이다. 만약 서로 연관된 링크가 없다면 0이 된다.

<그림 5> 페이지 랭크의 계산


이와 같은 연산은 수렴(convergence)이 이루어질 때까지 반복적으로 이루어진다. 구글 검색엔진 내부에서는 방대한 웹 페이지들의 페이지 랭크 계산을 위해 다음과 같은 방식으로 프로세스를 진행한다.


① docID를 이용하여 링크 구조를 정렬한다.
② 링크 데이터베이스에서 댕글링 링크를 제거한다.
③ 랭크 값을 초기화한다.
④ 각 페이지의 가중치를 저장하기 위한 메모리를 할당한다.
⑤ 한 단계의 계산이 완료되면 디스크에 가중치를 저장하고, 다음 단계의 계산을 메모리 상에서 진행한다.
⑥ Stet 5를 수렴할 때까지 반복된다.


페이지 랭크의 의미


페이지 랭크는 본질적으로, 웹 링크의 그래프 상에서의 랜덤 서퍼가 갖는 행동 패턴을 제한된 분포로 결정짓는 작업이다. 그래프 상의 한 노드의 중요도는 충분한 시간이 흐른 후에 랜덤 서퍼가 그 노드 위에 있을 확률이다. 확률이 높다면 웹 상의 서퍼들이 접근할 가능성은 높아진다. 이것은 웹 페이지의 컨텐츠와 상관없이 웹 상에 존재하는 가중치가 부여된 링크 구조에 의한 중요성을 산출한다는 의미이다. 이런 특징은 대부분 사용자들의 웹 페이지 접근 의도에 대한 일반적인 케이스(common case) 처리가 가능토록 한다.


예를 들어 꽃이라는 키워드를 쳤을 때, 일반적인 케이스는 꽃에 대한 설명이 담긴 페이지들이 아니라 꽃 구입이나 배달과 관련된 페이지들이다. 일반적으로 사람들이 특정 질의어를 입력했을 때 특정 페이지가 일반적인 케이스라는 정보는 HTML 자체에는 담겨져 있지 않기 때문에, 링크 구조를 분석하는 페이지 랭크는 일반적인 케이스 처리에 매우 효과적이다. 또한 페이지 랭크는 사용자에게 자신이 찾고 있는 링크가 중요도 측면에서 어느 정도의 위치를 차지하고 있는지에 대한 인디케이터(indicator)가 될 수도 있다.


참고로, 페이지 랭크의 요소들은 지금도 계속해서 튜닝되고 있다. 예를 들면 웹 페이지의 컨텐츠가 얼마나 자주 갱신되는가에 대한 빈도수(frequency) 등이 새롭게 추가되는 요소들 중 하나이다.


대용량 파일의 분산 처리를 위한 구글 파일 시스템


검색엔진의 성능이 검색엔진의 자료구조와 아키텍처에 밀접한 관계가 있는 것은 사실이지만, 어느 수준의 성능 이상을 요구하는 경우에는 반드시 최적화된 하부 구조가 필요하다. 앞서 살펴보았던 구글 검색엔진은 대용량의 웹 데이터를 다루고, 그에 따른 대용량 데이터와 색인 구조들을 다루고 있다. 대용량 처리를 위해서는 비용 문제를 간과하기 힘들기 때문에, 구글은 저 사양의 머신들을 대량 배치하여 분산 처리하는 것으로 대용량 데이터와 대용량 트래픽에 대응하고 있다. 이를 가능하게 한 데에는 효율적으로 대용량 파일의 분산 처리와 성능을 위해 자체적으로 개발된 구글 파일 시스템의 역할이 크다.


<그림 6> 구글 파일시스템 아키텍처


구글 파일 시스템의 특징


대용량 분산 파일 시스템이 가져야 하는 요소에는 확장성(scal ability), 성능(performance), 신뢰성(reliability), 가용성(avail ability) 등이 있다. 구글 파일 시스템 역시 이런 특징적 요소들을 모두 포함하고 있다. 구글 파일 시스템은 리눅스 파일 시스템을 기반으로 개발되었으며, 추가적으로 다음과 같은 접근 특성들에 대한 처리 목표를 취하고 있다.


분산 처리 서버들의 오류(failure)에 대한 대응
- 애플리케이션 버그, 디스크 오류, 메모리 오류, 커넥션 오류, 네트워킹 오류, 파워 서플라이 오류 등에 대해서 모니터링, 오류 허용(fault-tolerance), 자동 복구(automatic recovery) 등이 시스템에 포함


기존의 파일에 비해 훨씬 더 큰 대용량 파일의 처리
- Multi-GB 파일들이 사용되기 때문에 I/O 오퍼레이션과 블럭 크기(block size)에 대한 파라미터 조정을 통해 효율적으로 관리


특징적인 읽기/쓰기 패턴에 대한 최적화
- Large streaming reads
- Small random reads
- Large, sequential writes
- Small writes


Well-defined semantics를 갖는 구조
- 동일 파일에 읽기/쓰기를 하려는 다수의 클라이언트의 오퍼레이션을 처리하기 위해 동기화(synchronization) 처리


고속의 대역폭(bandwidth) 유지
- 읽기/쓰기에 대해 엄격한 응답 시간(response time) 유지


구글 파일 시스템 아키텍처


구글 파일 시스템은 하나의 마스터 서버(master server)와 다수의 청크 서버(chunk server), 그리고 다수의 클라이언트(client)로 구성되어 있다(이러한 서버들은 모두 표준화된 형태인데, 구글에서는 표준화된 서버를 pizza server box라고 부른다). <그림 6>은 이러한 구글 파일 시스템의 아키텍처에 대한 그림이다.


마스터 서버는 청크 서버에 대한 메타 데이터들을 관리한다. 청크 서버는 정해진 크기의 청크들을 저장하고, 클라이언트는 마스터 서버의 메타 데이터들을 확인하고, 청크 서버에 접근하여 필요한 데이터를 읽고 쓴다.


각 파일들은 정해진 크기의 청크(chunk)로 나뉜다. 각 청크는 생성 시점에 마스터 서버에 의해 글로벌하게 유니크한(globally uni que) 청크 핸들(chunk handle)을 할당받는다. 청크 핸들과 바이트 레인지(byte range)에 의해 결정된 청크 데이터들은 청크 서버의 로컬 디스크에 저장되는데, 저장되는 청크 데이터는 기본적으로 3개의 복제본을 가지게 된다. 하나의 청크 서버에서 청크들을 로컬 파일로 존재하므로 별도의 캐시(cache) 없이 리눅스의 버퍼 캐시 효과를 그대로 사용한다. 구글 파일 시스템의 청크 크기는 64MB로 일반적인 리눅스 파일 시스템의 블럭 크기보다 크다. 이처럼 큰 청크 크기를 사용함으로써, 클라이언트가 동일한 청크에 접근할 때 불필요하게 마스터 서버와의 통신을 줄일 수 있고, 클라이언트의 네트워크 오버헤드와 마스터 서버에 저장되는 메타 데이터의 크기도 줄일 수 있다.


마스터 서버는 모든 파일 시스템의 네임 스페이스(name space), 액세스 컨트롤 정보(access control information), 파일-청크 간의 맵핑 정보 등의 메타 데이터를 관리한다. 마스터 서버는 이 정보를 이용하여 청크 서버들과 Heart Beat 메시지에 의한 커뮤니케이션을 통해 청크에 대한 가비지 컬렉션(garbage collection), 청크 서버 간의 마이그레이션(migration)을 수행한다. 마스터 서버의 메타 데이터들은 모두 메모리 상에 저장되기 때문에, 마스터 서버의 오퍼레이션이 매우 빠르다. 이는 주기적으로 상태를 스캐닝하여 청크 서버의 오류 상황이 발생했을 때 복제본을 재배치한다거나 청크 서버들의 디스크 사용 상태에 따라 청크 마이그레이션을 수행하는데 매우 효율적인 방식이다.


클라이언트는 구글 파일 시스템 API에 의해 구현된 애플리케이션을 담고 있으며, 마스터 서버 및 청크 서버와 커뮤니케이션하면서 애플리케이션에 필요한 데이터를 읽고 쓴다. 클라이언트는 마스터 서버와의 메타 데이터와 오퍼레이션 내용과 커뮤니케이션하고, 모든 실제 데이터와의 커뮤니케이션을 청크 서버와 직접 하게 된다.


구글 파일 시스템의 일관성 모델(Consistency Model)


클라이언트에 의해 파일이 청크 서버에 저장될 때는 오류 발생에 대비해서 3개의 복제본으로 저장된다. 만약, 데이터가 변경/추가된다면 청크 서버 내의 모든 복제본에 대해 동기화가 이루어져야 한다. 파일 쓰기가 이루어졌을 때 다음과 같은 순서로 복제본의 동기화가 이루어진다.


① 클라이언트가 마스터 서버에게 현재 사용하고 있는 청크와 또 다른 복제본들의 위치에 대한 정보를 요청한다.
② 마스터 서버가 클라이언트에게 1차 복제본(primary replica)의 ID와 2차 복제본(secondary replica)의 위치 정보를 보내준다.
③ 클라이언트가 모든 복제본에 대해 데이터를 푸시한다. 각 청크 서버는 넘어온 데이터들을 저장한다.
④ 모든 복제본들이 데이터를 받은 것에 대한 완료 여부(acknowledge)가 확인되면 클라이언트는 1차 복제본에 쓰기 요청을 한다.
⑤ 1차 복제본은 모든 2차 복제본에 쓰기 요청을 전달한다.
⑥ 2차 복제본의 오퍼레이션이 완료되면 1차 복제본에 완료 시그널을 보낸다.
⑦ 모든 2차 복제본에서 완료 시그널이 오면 1차 복제본은 쓰기 요청이 완료되었음을 클라이언트에게 회신한다.


<그림 7>은 이와 같은 동작의 흐름을 나타낸 그림이다. 이러한 동작은 기본적으로 컨트롤 플로우(control flow)와 데이터 플로우(data flow)가 구분되어 네트워크를 효율적으로 사용하는 방식으로 구성되어 있다.


구글 파일 시스템의 마스터 서버 오퍼레이션


마스터 서버는 구글 파일 시스템 내의 모든 네임 스페이스와 청크들의 복제본에 대한 관리를 처리한다. 마스터 서버에서 진행되는 오퍼레이션들을 간단하게 살펴보면 다음과 같다.


네임 공간에 대한 관리 및 락킹(locking)
- 네임 공간은 풀 패스 명(full path name)의 맵핑 테이블에 의해 관리된다.
- 읽기/쓰기가 발생할 때 lock 처리를 해 conflict가 발생하는 상황을 방지한다.


복제본 배치
- 청크의 복제본을 데이터의 신뢰성과 가용성을 최대화하는 방향으로 배치한다.
- 청크의 복제본을 네트워크 사용성(utilization)을 최대화하는 방향으로 배치한다.


<그림 7> Write Control and Data Flow


청크와 복제본에 대한 관리
- 새로운 청크를 생성할 때 청크 서버의 디스크 사용 수준이나 최근 영역의 분포 등을 확인하여 생성한다.
- 오류가 발생하여 복제본 간의 내용이 맞지 않다면(corrupted 되었다면) 정상적인 복제본을 재배포한다.
- 청크 서버의 디스크 상태와 부하(load) 상태를 확인하여 좀 더 나은 상태의 청크 서버로 복제본을 재분산(rebalancing)한다.

<그림 8> 구글플렉스의 논리적 구조


<그림 9> 구글의 주요 기술 요소들을 나타내는 다이어그램


가비지 컬렉션
- 파일 삭제가 일어나면 마스터 서버에 삭제 시간을 비롯한 정보가 로그로 남는다. 실제 청크 서버에서는 파일 삭제가 바로 이루어지지 않고, 히든 타입으로 리네임(rename) 처리가 된다.
- 마스터 서버에서는 청크 네임 공간 스캔을 통해 3일 이상된 히든 타입의 파일들을 삭제한다.
- 파일이 네임 공간에서 삭제되면 마스터 서버의 메타 데이터가 삭제된다.


구글 파일 시스템의 오류 복구


마스터 서버와 청크 서버는 각각 메모리에 올라갈 수 있는 수준의 메타 데이터를 가지고 있다. 서버에 문제가 생겨서 재시작되는 경우 빠른 시간 안에 재동작을 할 수 있는 상황으로 복구될 수 있다.


각 청크는 여러 대의 서로 다른 랙(rack)에 위치한 청크 서버에 복제본을 기본적으로 3개 배치한다. 각 청크들은 체크섬 버전 정보를 가지고 관리되며 이에 의해 각 복제본 간의 동기화 작업이 이루어진다. 데이터를 읽기 위해 접근한 청크 서버가 문제가 있다면 또 다른 청크 서버에 담겨있는 복제본에 의해 데이터 읽기 작업은 무사히 수행될 수 있다.


마스터 서버 역시 마스터 서버에서 일어나는 모든 오퍼레이션의 로그와 상태(state), 체크 포인트들은 여러 대의 머신으로 복제한다(Shadow master라고 불린다). 마스터 서버의 디스크에 오류가 있거나, 외부 모니터링 툴에 의해 이상이 발견되는 경우 복제된 마스터 서버에 의해 파일 시스템 오퍼레이션은 정상 수행되도록 조정된다.


구글 파일 시스템은 구글 검색엔진과 서비스에 적합하도록 심플하고 효과적인 파일 시스템으로 설계되어 있다. 구글에서 일어나는 대부분의 데이터 액세스는 추가(append) 중심의 쓰기 작업과 빈번한 읽기 중심의 작업들이고, 저가의 머신에 의한 클러스터(cluster) 구성이기 때문에 오류 처리 역시 중요한 이슈가 된다.


구글의 파일 시스템은 시스템 내의 중심적인 읽기/쓰기 패턴을 명확하게 정의하고 오류 처리를 중심으로 견고하고 효과적으로 설계되어 있다. 검색엔진에서 하부 저장 구조라는 것은 검색엔진 자체의 성능을 뛰어넘도록 하고 검색엔진 자체의 안정성을 확장하는 요소로, 구글이 갖고 있는 효율적인 하부 저장 구조는 구글의 기반을 다진 핵심 기술 요소 중 매우 중요한 요소로 볼 수 있다.


모든 기술을 아우르는 거대한 프레임워크


지금까지 구글이 갖고 있는 기술들 중에 핵심 기술(core technology)이라고 불릴 수 있는 요소들에 대해 간략하게 살펴보았다. 이 기술들은 현재의 구글을 있게 만든 구글만의 독자적인 기술임에 틀림없다. 하지만 구글의 기술은 이것이 전부가 아니다. 구글은 모든 애플리케이션과 기능들을 웹 중심(web-centric)으로 흡수하기 위한 작업을 하고 있다. 그 기반에는 구글의 기술들을 모두 아우르는 거대한 프레임워크가 존재한다.


구글플렉스


구글플렉스(Googleplex, 구글 본사 건물의 별칭이기도 하다)는 구글의 프레임워크에서 매우 중요한 위치를 차지하는 요소이다. 구글플렉스는 동일한 개체들이 모여 거대한 시스템을 구성하는 논리적 구조이다. 하나의 서버는 다른 서버들과 기능과 속성들을 공유한다. 이런 서버들이 모여서 클러스터를 구성한다. 클러스터들을 모여서 데이터 센터(data center)를 구성한다. 또 다시 데이터 센터들은 다른 애플리케이션 서버들과 모여서 구글의 온라인 시스템을 구성한다.


<그림 8>은 구글플렉스의 타이트하고 규칙적으로 조직화된 모습을 보여준다. 그림을 살펴보면 구글플렉스 내의 모든 레벨에 걸쳐 동일한 패턴이 반복되고 있음을 알 수 있다. 다시 말해 구글플렉스의 모든 구성 요소들은 동형(homogeneous)의 컴퓨팅 시스템이다. 구글 버전의 리눅스 위에서 돌아가는 구글 애플리케이션들의 집합은 슈퍼컴퓨터를 이용해 애플리케이션을 돌리는 것과 유사하다.


동형의 컴퓨팅 시스템은 몇 개의 장점을 갖고 있다. 모든 데이터 센터를 구성하고 있는 서버들의 구성 역시 동일한 구성이기 때문에, 시스템 규모의 확장시 단순히 서버 랙을 꽂고(plugged-in) 케이블을 연결하는 작업만으로도 셋팅과 설정(configuration)을 가능하게 한다. 앞서 살펴보았던 구글 파일 시스템 내에서 마스터가 청크 서버에 청크들을 복제하는 작업 역시 동형의 컴퓨팅 시스템에 대한 접근이므로 매우 친숙하고 쉬운 오퍼레이션으로 구현될 수 있다. 즉, 구글플렉스는 구글 파일 시스템의 기능과 목적들을 효율적이고 효과적으로 지원할 수 있는 논리적 구조이다.


구글 컴퓨팅 프레임워크


개발자들이 흔히 말하는 ‘구글스럽다’라는 말의 의미는 무엇인가. 검색 영역의 개발자와 일반 영역의 개발자가 바라보는 관점이 약간의 차이는 있을 수 있겠지만, 대부분의 경우 구글을 구글스럽게 만드는 것은 검색 기술처럼 특화된 기술 자체가 아니라 일반적이고 연구 개발적인 관점에서 접근하는 소프트웨어 공학적이면서 하드웨어 공학적인 솔루션들이 일으키는 시너지이다.


<그림 9>는 구글 프레임워크의 전체적인 모습을 나타낸 다이어그램이다. 이 그림을 보면 구글의 프레임워크에 포함되어 있는 중요한 기술들에 대해 알 수 있다.


대용량 파일 및 function 가속을 위해 수정된 리눅스
- 기능에 적합하게 튜닝된 리눅스를 사용한다.


기능 추가 및 규모 확대에 플러그인 방식에 의해 별도로 손이 가지 않을 정도로 표준화된 분산 구조
- 구글플렉스는 자기 유사 구조를 가지며, 서버의 추가와 오류에 대한 대응이 쉽다.


스케일 레벨(scale level)에 관계없이 유사한 기술 구조
- 동형(homogeneous) 구조에 의해 모든 요소들이 구성된다.


프로그래밍 언어에 관계없이 기능 구현이 가능한 웹 기반 아키텍처
- 프레임워크의 인터페이스로 WSDL, XML, HTML, POP3, SMTP 등과 같은 플랫폼 독립(platform-independent)적인 프로토콜을 제공한다.


<그림 10> Google's fuction: Hardware and Software Innovations


<그림 11> 구글 검색과 LostGoocle을 이용한 검색의 비교


구글의 프레임워크는 구글 파일 시스템에 의해 구성된 데이터 센터와 분석적 방법으로 광고를 집행하는 구글 광고 시스템(Ad System), 각종 서비스 시스템(gmail, News 등), 검색엔진 등을 모두 포함한다. 구글플렉스의 외부와 내부에는 새로운 서비스 시스템과 애플리케이션들이 추가될 수 있고, 기본적인 인터페이스들을 통해 구글 프레임워크로의 접근과 구글 프레임워크의 기능을 사용할 수 있는 확장적이고 오픈된 구조이다(구글의 피카사(Picasa)나 구글 어스(Earth)는 로컬 머신에서 수행되는 애플리케이션을 구글 프레임워크로 포괄시키는 좋은 예이다).


조금 다른 관점에서 본다면, 구글 프레임워크는 소프트웨어 공학과 하드웨어 공학의 접점에 놓여 있다. 소프트웨어적인 관점에서 성능을 확보하면서 동시에 하드웨어 공학적인 관점에서 비용 절감을 위한 기술들을 모두 포함한다. 이는 비용 절감, 저가형 하드웨어, 스마트한 소프트웨어에 대해 집중하는 구글 문화의 주요 부분이다.


구글 프레임워크는 구글을 여타 다른 경쟁업체와 차이를 갖도록 하는 명확한 요소이다. 구글플렉스는 구글 파일 시스템과 구글이 지향하는 성능과 비용절감의 측면에서 매우 효율적인 구조이다. 서버 랙이나 데이터 센터가 오류를 일으키더라도 데이터의 손실이나 구글플렉스 전체의 다운은 방지된다. 또한, 동형 시스템의 사용으로 인해 머신의 설치 과정이나 설정(configuration)의 표준화와 자동화를 가능케 했다. 이는 타 업체가 소프트웨어 중심의 튜닝이나 하드웨어의 업그레이드에 의존해 성능과 안정성을 유지하는 모습과는 상당한 차이를 보인다.


구글의 프레임워크는 또한 구글 내의 개발자는 물론, 일반적인 개발자들에게 아주 좋은 장난감 꾸러미(toy box)이다. 구글 프레임워크의 인터페이스를 통해 언제 어디서나 웹과 연결된 환경이라면 구글의 강력한 기능을 그대로 활용할 수 있는 것이다. 이러한 확장적이고 오픈되어 있는 프레임워크 구조는 많은 개발자들의 호응을 얻고 있다.


구글 APIs


구글은 개발자들이 쉽게 구글 프레임워크에 접근할 수 있는 API set을 제공한다. 구글이 갖고 있는 기술에 쉽게 접근하여 방대한 데이터와 강력한 기능들을 사용할 수 있는 구글 API는 개발자들에게 매력적인 요소일 수밖에 없다. 앞서 1부에서 소개한 것처럼 구글에서는 다양한 API들을 제공하는데, 여기서는 가장 대표적으로 사용되고 있는 구글 웹 검색 API에 대해 살펴보겠다.


구글 웹 검색 APIs


구글 웹 검색 API는 SOAP과 WSDL 표준을 기반으로 구글과 통신할 수 있는 방식을 제공한다. 개발자는 어떤 프로그래밍 언어를 사용하든 상관없이 구글과의 프로토콜만 맞춰줌으로써 구글의 기능을 그대로 사용할 수 있다. 구글 웹 검색 APIs 페이지(http://www.google. com/apis/)에는 다음과 같은 프로그래밍 아이디어들이 기재되어 있다.


- 주제에 맞는 새로운 정보에 대한 자동 모니터링
- 시간의 흐름에 따른 마켓 분석과 트렌드 분석
- 온라인 게임의 개발 - 새로운 검색 UI의 개발
- 구글의 스펠 체크 기능을 애플리케이션에 추가


<표 3> 구글 웹 검색 APls를 통한 검색 요청에 사용되는 기본적인 파라미터

파라미터 명 설명
key 구글 인증키. APls를 다운받은 후 구글로부터 메일로 인증 키를 받아야 한다.
q 질의어
start 검색 결과 중 불러올 index 번호. 0부터 시작
maxResults 한 페이지에 최대로 불러올 검색 결과의 건 수
filter 검색 결과 중 특정 결과들을 필터하기 위한 조건
restricts 구글 웹 색인 중 서브 셋을 검색하기 위한 조건
safeSearch 성인 필터링을 위한 Boolean 파라미터
lr 언어 제한. 특정 나랏말로 된 문서만을 검색하기 위한 조건

구글 웹 검색 APIs는 SOAP을 사용하는 웹 서비스 모델과 만나면 굉장한 효과를 발휘할 수 있다. LostGoogle(http://lostgoggles.com) 은 구글 API를 이용하여 웹 검색 결과에 해당 페이지의 스크린샷을 썸네일로 제공한다. 만약 LostGoogle을 이용하여 아마존닷컴(http:// www.amazon.com)의 내용을 검색하고자 하면 아마존닷컴에서 웹 서비스로 제공하고 있는 요소들과 합쳐져 도서에 관련된 훨씬 더 풍부한 정보 도서의 형태, 가격, 인기도 등을 볼 수 있다.


구글 웹 검색 APIs를 통한 검색 요청


구글 웹 검색 APIs를 통해 구글로 검색 요청을 보내기 위해 사용하는 기본적인 파라미터는 <표 3>과 같다. 질의어 파라미터에 해당되는 는 <표 4>와 같은 형식으로 기술할 수 있다. 부수적인 qualifier들을 사용함으로써 검색 결과를 특정 조건에 맞게 필터링할 수 있다. 파라미터들을 이용하여 SOAP을 구성한다면 <화면 2>와 같은 형식으로 구글에 리퀘스트를 날리게 될 것이다.

 

<화면 2> SOAP으로 구성된 구글 검색 요청

 

<화면 3> SOAP으로 구성된 구글 검색 결과 포맷

 

<표 4> 질의어 파라미터의 기술 형식

쿼리의 성격 예제 설명
특정 질의어를 포함 Star Wars Episode +1 일번적인 질의어에 "+ 특정 질의어"를 붙여 일반적인 질의어와 특정 질의어가 모두 출현한 검색 결과만을 출력한다.
특정 질의어를 제외 bass-music 일반적인 질의어에 "- 특정 질의어"를 붙여 일반적인 질의어는 출현하지만 특정 질의어가 출현하지 않는 검색 결과만을 출력한다.
특정 어구 검색 "yellow pages" 특정 어구가 출현한 검색 결과만을 출력한다.
Boolean or 검색 vacation london OR paris "word A OR word b" 는 word A 와 word B에 대해 Boolean or 검색 결과만을 노출한다.
사이트 제한 검색 admission site: www.stanford.edu 특정 domain에 포함되어 있는 도큐먼트에 대한 결과만을 노출한다.
날짜 제한 검색 Star Wars datarange:2452122-2452234 Jullian Date 포맷으로 입력된 날짜 기간동안 생성된 웹 페이지드에 대한 검색 결과만을 노출한다.
제목 검색(팀) intitle:Google search "intitle:" 바로 뒤에 명시된 질의어가 제목에 출현한 검색 결과만을 노출한다.
제목 검색(전체) allintitle:Google search "alltitle:" 뒤에 명시된 모든 쿼리 팀들이 제목에 출현한 검색 결과만을 노출한다.
URL 검색(팀) inurl: Google search "inurl:" 바로 뒤에 명시된 질의어가 URL에 포함되어 있는 웹 문서만을 노출한다.
URL 검색(전체) allinurl: Google search "allinurl:" 로 시작되는 질의어의 경우 명시된 모든 질의어가 URL에 포함되어 있는 웹 문서만을 노출한다.
텍스트만 검색 allintext: Google search "alltext:"로 시작되는 질의어의 경우, 명시된 질의어가 웹 문서의 body text 부분에서 출현한 문서만을 노출한다.
링크만 검색 allinlinks: Google search "allinlinks:"로 시작되는 질의어의 경우, 명시된 모든 질의어가 앵커 텍스트에서 출현한 문서만을 노출한다.
파일 타입 포함 필터링 Google filetype: doc OR filetype:pdf "filetype:" 뒤에 명시된 파일 타입을 포함하고 있는 문서만을 노출한다.
파일 타입 제외 필터링 Google filetype: doc-filetype:pdf "-filetype:" 뒤에 명시된 파일 타입을 포함하지 않는 문서만을 노출한다.
웹 문서 정보 info:www.google.com 특정 URL에 해당되는 페이지 하나만을 검색 결과로 노출한다.
역 링크 link:www.google.com 특정 URL에 역 링크하고 있는 페이지들을 노출한다.
관련 링크 related:www.google.com 특정 URL의 페이지와 유사한 페이지들을 노출한다.
캐시된 결과 페이지 cache:www.google.com web 구글이 수집하여 캐시해 놓은 페이지를 보여준다. 특정 질의어와 함께 입력되면 해당 질의어에 하이라이팅 처리를 해준다.

구글 웹 검색 API를 이용한 검색 결과의 수신

 

SOAP을 이용하여 리퀘스트를 날리면, 구글은 SOAP으로 검색 결과를 회신한다. 회신되는 결과에 포함되는 주요 정보들은 다음과 같다.

<summary> - 검색결과가 ODP 디렉토리 내의 리스트의 경우, ODP 서머리에 해당되는 텍스트 스트링
<URL> - 검색 결과의 URL path
<snippet> - 검색 결과 웹 페이지 중 입력된 질의어가 출현한 부분을 볼드 처리하여 추출한 웹 페이지 컨텐츠의 일부 스트링
<title> - 검색 결과의 타이틀 - 캐시된 페이지의 KB 크기
<relatedInformationPresent> - related: 요청에 대한 true/false 값
<hostName> - 필터링이 수행되어 한 호스트에서 두 개의 결과가 노출되는 경우, 두 번째 결과에 추가적으로 호스트 네임이 기술된다.

SOAP에 의해 넘어온 검색 결과는 <화면 3>과 같은 형태가 될 것이다. 구글 웹 검색 APIs를 다운로드하면 자바로 작성된 간단한 패키지가 포함되어 있다. 이것은 자바를 통해 SOAP 메시지를 구성해 구글과 간단하게 통신할 수 있는 환경을 제공한다. 굳이 자바뿐 아니라 SOAP 처리를 위한 기타 프로그래밍 언어의 라이브러리도 다수 공개되어 있으니 개발자가 편의에 맞는 언어를 선택해 SOAP 프로토콜을 처리하는 데에는 그리 큰 어려움이 없다.

 

구글만이 가진 튼튼한 인프라 구조

 

지금까지 구글의 핵심 기술이라고 불릴 수 있는 요소들에 대해서 간략하게나마 살펴보았다. 검색에 대한 기술들이 상당 부분 오픈되어 있는 현재 상황으로 볼 때, 검색 기술에 대한 진입 장벽은 많이 높은 편이 아니다. 그럼에도 불구하고 구글이 검색 업계에서 독보적인 위치를 차지할 수 있는 것은 구글만이 갖고 있는 핵심 기술들이 선구적이고 핵심에 집중하며 멈추지 않고 성장하고 있기 때문이다. 게다가 그 기술들은 숨겨져 있는 것이 아니라 많은 개발자들을 위해 개방되어 있다. 구글의 기술이 개발자들에게 전파되고 전파된 기술들이 역으로 다시 구글을 발전시킨다.

 

사용자들이 흔히 말하는 바와 같이, 구글의 서비스가 구글스러울 수밖에 없는 것은 구글만이 갖고 있는 인프라 구조들이 버티고 있기 때문이다. 최하단의 인프라 구조들과 그것을 아우르는 프레임워크, 그리고 구글이 기술을 바라보는 철학이 최상단의 서비스에 영향을 미치고 있는 것이다.

 

제공 : DB포탈사이트 DBguide.net

+ Recent posts