2007년 9월 30일 일요일

하이브리드 자전거를 타고 싶다

 

<출처: 유운님 http://blog.daum.net/ryuwoon>

마감도 끝나고...

그 사이 봄은 찾아와 날씨는 좋으시고...

 

다시 자전거를 탈 시즌이 왔구나 싶은데...

갑자기 타던 미니벨로 말고 하이브리드 자전거가 타고 싶어졌다.

 

하이브리드 자전거가 무엇인고 하니,

싸이클로크로스(Cyclocross) 자전거라고도 불리우는데

싸이클, 즉 로드레이서의 속도에 MTB의 튼튼함을 결합한 녀석을 일컫는다.

 

그럼 왜 이런 녀석이 나오게 됐는가.

로드레이서는 바퀴가 크고 크랭크 크기와 기어비도 높아서 속도가 잘 나지만

타이어가 얇아서 포장 도로가 아니면 펑크가 날 소지가 높고 충격 흡수가 잘 안 된다.

게다가 레이싱 특성 상 브레이크도 제동력이 아주 강하지는 않다.

또, 최대한 공기저항을 적게 하기 위해 상체를 많이 숙이도록 디자인돼있다.

때문에 로드레이서는 세심하고 어느 정도 전문적인 라이딩을 요구한다.

 

반면, MTB는 원래 산악이나 오프로드용으로 나온 녀석이라서

타이어가 굵고 펑크 위험이 낮고 요철이 있어 접지력이 강해 안정적인 주행을 할 수 있으며

그렇지 않은 경우도 있찌만 대개 앞이나 뒤 또는 앞뒤 모두에 샥(스프링)이 있어서

험한 길에서도 충격을 흡수해주므로 편안하게 운행할 수 있다.

이런 점 때문에 도로 사정이 좋지 않은 우리날에서는

자전거 하면 MTB라고 생각할 정도로 MTB 보급율이 높은 편이다.

 

그러나, MTB는 기본적으로 산악용, 때문에 등판 능력을 높이기 위해서

크랭크 크기가 작고 기어비도 낮기 때문에 속도면에서는 로드레이서에 뒤진다.

게다가 바퀴 크기도 로드레이서보다는 작으며

타이어가 굵은 것도 마찰력을 높여 가속에 불리하다.

뒤샥이 있는 것은 페달링하는 힘을 흡수해 더욱 가속하기 어려워서

대개 MTB를 타는 사람들도 어지간히 험한 길을 주로 달리지 않는 한

앞샥만 있는 하드테일 타입이나 아예 샥이 없는 것을 타는 경우가 많다.

 

하여간 속도 면에서는 절대적으로 불리한 것이 MTB지만

주행 상의 편리, 편안함은 단연 MTB가 낫다고 하겠다.

그러나 역시 로드의 빠른 속도는 매력적이며

무엇보다 일단 자전거의 기본은 로드인 것이다.

 

때문에 로드레이서의 주행성을 유지하면서도 MTB의 안정성을 더한,

또는 MTB를 타면서도 좀 더 빠른 속도를 낼 수 있는,

그런 자전거를 바라게 되었고 그래서 탄생한 게 하이브리드 또는 크로스 타입이다.

그 특성 상 몇 년 전부터 세계적으로 특히 도시용 자전거로 인기를 끌고 있기도 하다.

 

 

하여간 서론이 길었고.. -_-;;;

이런 류의 자전거가 타고 싶어졌다.

사실 지금 타고 있는 에뚜알보다 속도가 좀 더 나고 접히는 미니벨로를 고려하고 있었는데,

마음에 두고 있던 모델이 품절이 되어버리면서 아예 마음이 돌아서 버린 것이다.

 

그래서 작년 모 사이트에서 공구한 이후 인기가 높아진 국산 하이브리드로 눈을 돌렸는데,

이 놈도 05년도 신상품 생산을 위해 현재는 품절 상태...

신상품은 4월 중순에나 나올 듯 하다.

 

 

 

 

 

 

 

 

 

 

 

 

 

ALTON RCT 3.0

 

 

 

자, 사진이 나온 김에 하이브리드 자전거의 특성에 대해 좀 더 설명하자면

바퀴 사이즈는 로드와 같은 27인치이지만 두께가 조금 더 두껍고

크랭크 사이즈 역시 로드와 MTB의 중간 정도 된다.

그 외 부품은 고가인 로드용 부품보다는

비교적 저렴한 MTB와 전면 호환되는 것들로 구성돼있다.

예를 들면 핸들바 기어 변속기, 브레이크 같은 것은 전형적인 MTB용이다.

 

국산인 이 녀석의 가격은 정가는 25만원,

하지만 샵들이 올려놓은 실구매 예정가는 18만원 선이다. 싸다!

하이브리드의 장점은 바로 이 가격 대 성능비라고 할 수 있는 것이다.

 

자전거가 18만원이나 하는데 싸다고? 라고 하실 분들도 계시겠찌만,

일단 자전거에도 급수가 있고 동급의 해외 제조사 제품에 비하면 매우 싼 편이다.

성능면에서 큰 차이가 없는데 비싼 부품과 수입 마진 때문에 비싸진다.

 

 

 

그리고 보다 MTB에 가까운 하이브리드도 있다.

 

 

 

 

 

 

 

 

 

 

GIANT BOULDER DX


 

바퀴도 MTB용이고 프레임도 탑튜브가 낮은 MTB 스타일이다.

뿐만 아니라 앞 샥이 달려있어 외관 상으로는 그냥 MTB라고 해도 좋을 정도다.

하지만, 크랭크가 일반 MTB보다 크고, 기어도 기어비 높은 것을 쓰고 있어

확실히 한 눈에도 속도를 내기 위해 제작된 녀석이라는 걸 알 수 있다.

 

이 녀석의 가격은 해외 브랜드인지라 앞 것의 2배 수준인 39만원.

그러나 사실 상 이 앞 샥의 가격이 최하 20만원대이므로

어찌 보면 매우 합리적인 가격이라고 볼 수 잇다.

 

 

 

그런가 하면 앞 두 모델의 장점을 합한, 즉 앞샥도 있고 바퀴는 로드에 가까운

그런 궁극의 하이브리드 자전거도 50만원 안으로 구입할 수 있다.

 

 

 

 

 

 

 

 

 

 

 

FUJI  SUNFIRE CROSS


 

역시 모 수입 브랜드에서 들여온 이 녀석은 딱 보기에도 '폼'이 난다.

프레임은 MTB 쪽에 가깝긴 하지만 로드로 보기에도 무리가 없고,

바퀴는 두꺼운 로드용이며 크랭크나 기어도 로드용에 가깝다.  

이 시리즈는 사용 부품에 따라 3가지 타입으로 나뉘는데 가격도 각 40, 46, 50만원이다.

바로 앞 모델과 비슷한 부품 사양을 쓰고 있는 게 사진의 것으로 중간급인 46만원.

하지만 뭐 40만원 짜리도 나쁜 거 같지는 않고...

그럼 역시 가격 대비 성능면에서는 최고일 듯 하다.

 

그러나 문제는...

 

 

돈, 이, 없, 다.  으하하하하하하 -ㅁㅜ

2007년 9월 13일 목요일

Oracle DBMS_LOB

Oracle DBMS_LOB

Version 9.2

General Information
Source {ORACLE_HOME}/rdbms/admin/dbmslob.sql
Constants  
Dependencies  
Data Dictionary Objects dbms_lob

lob$
def$_lob

user_lobs
all_lobs
dba_lobs

user_lob_partitions
all_lob_partitions
dba_lob_partitions

user_lob_subpartitions
all_lob_subpartitions
dba_lob_subpartitions

user_part_lobs
all_part_lobs
dba_part_lobs
Object Privileges GRANT execute ON dbms_lob TO <schema_name>;
 
APPEND
appends the contents of a source internal LOB to a destination LOB dbms_lob.append(dest_lob IN OUT NOCOPY BLOB, src_lob IN BLOB);
CREATE OR REPLACE PROCEDURE Example_1a IS

dest_lob BLOB;
src_lob  BLOB;

BEGIN
  -- get the LOB locators
  -- note that the FOR UPDATE clause locks the row
  SELECT b_lob INTO dest_lob
  FROM lob_table
  WHERE key_value = 12
  FOR UPDATE;

  SELECT b_lob INTO src_lob
  FROM lob_table
  WHERE key_value = 21;

  dbms_lob.append(dest_lob, src_lob);
  COMMIT;
END;
dbms_lob.append(
dest_lob IN OUT NOCOPY CLOB CHARACTER SET ANY_CS,
src_lob  IN             CLOB CHARACTER SET dest_lob%CHARSET);
CREATE OR REPLACE PROCEDURE Example_1b IS

dest_lob, src_lob BLOB;

BEGIN
  -- get the LOB locators
  SELECT b_lob INTO dest_lob
  FROM lob_table
  WHERE key_value = 12
  FOR UPDATE;

  SELECT b_lob INTO src_lob
  FROM lob_table
  WHERE key_value = 12;

  DBMS_LOB.APPEND(dest_lob, src_lob);
  COMMIT;
END;
 
CLOSE
   
 
 
COMPARE
   
 
 
CONVERTOCLOB
   
 
 
COPY
   
 
 
CREATETEMPORARY
Initialize A CLOB Variable dbms_lob.createtemporary(<clob_variable_name>, TRUE);
DECLARE

clobvar CLOB := EMPTY_CLOB;
len     BINARY_INTEGER;
x       VARCHAR2(80);

BEGIN
  dbms_lob.createtemporary(clobvar, TRUE);
  dbms_lob.open(clobvar, dbms_lob.lob_readwrite);
  x := 'before line break' || CHR(10) || 'after line break';
  len := length(x);
  dbms_lob.writeappend(clobvar, len, x);
  dbms_lob.close(clobvar);
END;
/
 
EMPTY_BLOB
Null BLOB EMPTY_BLOB()
INSERT INTO pdm
(dname, sname, fname, iblob)
VALUES
(pdname, psname, pfname, EMPTY_BLOB());
 
ERASE
   
 
 
FILECLOSE
Closes a file opened with dbms_lob.file_open dbms_lob.fileclose(<bfile>);
dbms_lob.fileclose(src_file);
 
FILECLOSEALL
Closes all files opened with dbms_lob.file_open dbms_lob.filecloseall();
dbms_lob.fileclose();
 
FILEEXISTS
Determine whether a file exits

The FILEEXISTS function in the DBMS_LOB package works only with BFILES. In that case, the BFILE pointer must previous be declared and stored in a BFILE column. Without a BFILE pointer, you can not use the FILEEXISTS function.
 
 
 
FILEGETNAME
   
 
 
FILEISOPEN
Determine whether a file is open with the DBMS_LOB package dbms_lob.fileisopen(
 
 
FILEOPEN
Open a file for reading dbms_lob.fileopen(<bfile>, <file_open_mode>);
dbms_lob.fileopen(src_file, dbms_lob.file_readonly);
 
FREETEMPORARY
   
dbms_lob.freetemporary(clobvar);
 
GETCHUNKSIZE
   
 
 
GETLENGTH
Gets the length of a file in bytes lgh_file is a variable of type binary_integer <binary_integer> := dbms_lob.getlength(<bfile>);
DECLARE

src_file BFILE;
dst_file BLOB;
lgh_file BINARY_INTEGER;

BEGIN
  src_file := bfilename('CTEMP', 'myfile.txt');
  lgh_file := dbms_lob.getlength(src_file);
END;
/
 
INSTR
Test for a string in a CLOB  
 
 
ISOPEN
Test for whether a file has been opened with dbms_lob.fileopen  
 
 
ISTEMPORARY
   
 
 
LOADBLOBFROMFILE
   
 
 
LOADCLOBFROMFILE
   
 
 
LOADFROMFILE
Reads the binary file into a BLOB type variable dbms_lob.loadfromfile(<blob_var>, <bfile>, <binary_integer>);
exec dbms_lob.loadfromfile (dst_file, src_file, lgh_file);
 
OPEN
   
 
 
READ
Reads the contents of a file for loading a CLOB type variable dbms_log.read(
 
 
SUBSTR
   
 
 
TRIM
   
 
 
WRITE
   
 
 
WRITEAPPEND
   
 
 
DBMS_LOB Demo
Blob Load Demo /*
define the directory inside Oracle when logged on as SYS
create or replace directory ctemp as 'c:\temp\';

grant read on the directory to the Staging schema
grant read on directory ctemp to staging;
*/

-- the storage table for the image file
CREATE TABLE pdm (
dname   VARCHAR2(30),   -- directory name
sname   VARCHAR2(30),   -- subdirectory name
fname   VARCHAR2(30),   -- file name
iblob   BLOB)           -- image file
pctfree  5
pctused 95
tablespace <tablespace_name>;

-- create the procedure to load the file
CREATE OR REPLACE PROCEDURE load_file (
pdname VARCHAR2,
psname VARCHAR2,
pfname VARCHAR2) IS

src_file BFILE;
dst_file BLOB;
lgh_file BINARY_INTEGER;

BEGIN
   src_file := bfilename('CTEMP', pfname);

   -- insert a NULL record to lock
   INSERT INTO pdm
   (dname, sname, fname, iblob)
   VALUES
   (pdname, psname, pfname, EMPTY_BLOB())
   RETURNING iblob INTO dst_file;

   -- lock record
   SELECT iblob
   INTO dst_file
   FROM pdm
   WHERE dname = pdname
   AND sname = psname
   AND fname = pfname
   FOR UPDATE;

   -- open the file
   dbms_lob.fileopen(src_file, dbms_lob.file_readonly);

   -- determine length
   lgh_file := dbms_lob.getlength(src_file);

  -- read the file
  dbms_lob.loadfromfile (dst_file, src_file, lgh_file);

  -- update the blob field
  UPDATE pdm
  SET iblob = dst_file
  WHERE dname = pdname
  AND sname = psname
  AND fname = pfname;

  -- close file
  dbms_lob.fileclose(src_file);

END load_file;
/
  How to save a BLOB to a file on disk in PL/SQL
From: Thomas Kyte <tkyte@oracle.com>

Use DBMS_LOB to read from the BLOB

You will need to create an external procedure to take binary data and write it to the operating system, the external procedure can be written in C. If it was CLOB data, you can use UTL_FILE to write it to the OS but UTL_FILE does not support the binary in a BLOB.

There are articles on MetaLink explaining how to do and it has a C program ready for compiling and the External Procedure stuff, i'd advise a visit.

Especially, look for Note:70110.1, Subject: WRITING BLOB/CLOB/BFILE CONTENTS TO A FILE USING EXTERNAL PROCEDURES

Here is the Oracle code cut and pasted from it. The outputstring procedure is the oracle procedure interface to the External procedure.

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

DECLARE

i1    BLOB;
len   NUMBER;
my_vr RAW(10000);
i2    NUMBER;
i3    NUMBER := 10000;

BEGIN
  -- get the blob locator
  SELECT c2
  INTO i1
  FROM lob_tab
  WHERE c1 = 2;

  -- find the length of the blob column
  len := dbms_lob.getlength(i1);
  dbms_output.put_line('Column Length: ' || TO_CHAR(len));

  -- Read 10000 bytes at a time
  i2 := 1;
  IF len < 10000 THEN
    -- If the col length is < 10000
    dbms_lob.read(i1,len,i2,my_vr);

    outputstring('p:\bfiles\ravi.bmp',
    rawtohex(my_vr),'wb',2*len);

    -- You have to convert the data to rawtohex format.
    -- Directly sending the buffer
    -- data will not work
    -- That is the reason why we are sending the length as
    -- the double the size of the data read

    dbms_output.put_line('Read ' || to_char(len) || 'Bytes');
  ELSE
    -- If the col length is > 10000
    dbms_lob.read(i1,i3,i2,my_vr);

    outputstring('p:\bfiles\ravi.bmp',
    rawtohex(my_vr),'wb',2*i3);

    dbms_output.put_line('Read ' || TO_CHAR(i3) || ' Bytes ');
  END IF;

  i2 := i2 + 10000;

  WHILE (i2 < len )
  LOOP
    -- loop till entire data is fetched
    dbms_lob.read(i1,i3,i2,my_vr);

    dbms_output.put_line('Read ' || TO_CHAR(i3+i2-1) ||
    ' Bytes ');

    outputstring('p:\bfiles\ravi.bmp',
    rawtohex(my_vr),'ab',2*i3);

    i2 := i2 + 10000 ;
  END LOOP;
END;
/
  CREATE OR REPLACE PROCEDURE read_file IS

src_file BFILE := bfilename('DOCUMENT_DIR', 'image.gif');
dst_file BLOB;
lgh_file BINARY_INTEGER;

BEGIN
  -- lock record
  SELECT bin_data
  INTO dst_file
  FROM db_image
  FOR update;

  -- open the file
  dbms_lob.fileopen(src_file, dbms_lob.file_readonly);

  -- determine length
  lgh_file := dbms_lob.getlength(src_file);

  -- read the file
  dbms_lob.loadfromfile(dst_file, src_file, lgh_file);

  -- update the blob field
  UPDATE db_image
  SET bin_data = dst_file;
  COMMIT;

  -- close file
  dbms_lob.fileclose(src_file);

EXCEPTION
  WHEN access_error THEN

  WHEN invalid_argval THEN

  WHEN invalid_directory THEN

  WHEN no_data_found THEN

  WHEN noexist_directory THEN

  WHEN nopriv_directory THEN

  WHEN open_toomany THEN

  WHEN operation_failed THEN

  WHEN unopened_file THEN

  WHEN others THEN

END read_file;
/
Replaces All Code Occurences Of A String With Another Within A CLOB -- 1) clob src - the CLOB source to be replaced.
-- 2) replace str - the string to be replaced.
-- 3) replace with - the replacement string.

FUNCTION replaceClob (
srcClob IN CLOB,
replaceStr IN VARCHAR2,
replaceWith IN VARCHAR2)
RETURN CLOB IS

vBuffer    VARCHAR2 (32767);
l_amount   BINARY_INTEGER := 32767;
l_pos      PLS_INTEGER := 1;
l_clob_len PLS_INTEGER;
newClob    CLOB := EMPTY_CLOB;
   
BEGIN
  -- initalize the new clob
  dbms_lob.createtemporary(newClob,TRUE);
   
  l_clob_len := dbms_lob.getlength(srcClob);

  WHILE l_pos < l_clob_len
  LOOP
    dbms_lob.read(srcClob, l_amount, l_pos, vBuffer);

    IF vBuffer IS NOT NULL THEN
      -- replace the text
      vBuffer := replace(vBuffer, replaceStr, replaceWith);
      -- write it to the new clob
      dbms_lob.writeappend(newClob, LENGTH(vBuffer), vBuffer);
    END IF;
    l_pos := l_pos + l_amount; 
  END LOOP;
   
  RETURN newClob;
EXCEPTION
  WHEN OTHERS THEN
    RAISE;
END;
/

2007년 9월 5일 수요일

GAUCE Demo 사이트

쉬프트 정보통신 제품인 가우스 데모 사이트

 

http://demo.shift.co.kr

 

 

 

 

 

 

 

 

 

 

 

 

 

 
 
"GAUCE"는 변화하는 e-비지니스 환경에서 귀사를 선두 그룹으로 만들어 드릴 것 입니다.
GAUCE는 X-Internet 기반의 웹 어플리케이션의 개발/운영을 위한 솔루션으로 4GL 수준의 역동적인 UI의 구성은 물론 높은 생산성과 확장성을 비롯해 개발 비용절감의 효과를 가져올 수 있으며 새로운 패러다임에 맞추어 기업의 핵심업무를 웹 기반으로 통합해 줍니다.
GAUCE는 XML, JAVA, JSP, ASP, .NET등의 표준 웹 개발 언어를 지원하며 다양한 플랫폼과 손쉽게 연동해 다양한 웹 어플리케이션 구축에서 레포팅까지 포괄적이고 일원화 된 웹 어플리케이션 개발 및 운영환경을 제공합니다.
  GAUCE는 400여 사이트의 고객이 선택하여 사용하고 있는 검증된 솔루션이며, 공공, 금융, 제조, 통신, 유통 등 다양한 분야에서 Client/Server 스타일 및 대용량 데이터처리가 요구되는 BackOffice데이터 관리등이     요구되는모든 사업영역에 활용할 수 있습니다.
 
 
   
 
 
 
 

SSL Protocol 개념과 동작 원리

웹을 이용한 전자 상거래, 인터넷 뱅킹 등이 더욱더 증대되면서 이제 인터넷은 정보의 바다가 아니라 하나의 커다란 시장이라 부를 수도 있는 상황이다. 온라인 입금이나 최근에는 소액의 경우 휴대폰 결재를 선택하기도 하지만 뭐니뭐니 해도 국내 인터넷 쇼핑 이용자들이 가장 선호하는 수단은 신용 카드다. 그런데 바로 이점이 보안적인 허점을 가져오는 주 원인이 될 수 있다.

 

실제로 신용카드로 결제하는 경우 인터넷이라는 공용망을 타고 서버에 전송되는 고객의 신용카드 정보는 신용카드 번호, 유효기간 등을 포함하고 있기 때문에 실제 전자 상거래 시 필요한 대부분의 데이터가 언제 어떻게 도용될지도 모르는 위험에 노출되어 있는 것이다. 그렇다면 개인의 금융정보를 공용망인 인터넷상에서 보호할 것인가?

 

이 질문에 대한 답으로 현재 가장 많이 사용되는 방법이 SSL(Secure Socket Layer)이다.

 

1. SSL(Secure Socket Layer) 개념

 

SSL은 Netsape에서 개발된 프로토콜로서 1995년 히크만(Hickman)에 의해서 개발되었으며 현재 인터넷 사용자들에게 안전한 개인 정보를 교환하기 위한 사실상의 표준 프로토콜로 인정되어 많은 온라인 상거래에 사용되고 있다. SSL은 실제로 다양한 장점을 지닌 암호화 기법들을 사용해 세계 각국에서 사용되는 대부분의 암호화 기법들을 지원할 수 있다.


SSL은 버전 3.0 이후 IETF(Internet Engineering Task Force)에서 표준화되어 TLS(Transport Layer Security)로 명명되었지만 실제 그 내용은 SSL 3.과 TLSv1.0이 같으며 MS Explorer나 Netscape 등 대부분의 브라우저에서 지원하고 있다. SSL 프로토콜에서 사용되어질 수 있는 다양한 애플리케이션 프로토콜이 있지만 주로 사용되는 부분은 WEB(HTTP)이라고 볼 수 있다.

 

SSL 은 크게 3가지 기능들을 제공함으로 공개되어 있는 인터넷상에서 일어나는 트랜잭션의 기밀성(Privacy)을 보장한다.

 

○ Site Authentication

User가 선택한 상대편 Web Site를 인증한다는 의미다. 우리가 인터넷 뱅킹이나 인터넷 쇼핑몰을 사용할 때 상대편이 실제 신뢰할 수 있는 은행이나 쇼핑몰의 웹서버 인지를 인증한다는 것으로, 상대 사이트에 대한 신뢰성 있는 인증이 없다면 우리는 불확실한 누군가에게 우리의 금융정보를 넘기는 위험에 처하게 된다.

 

○ Data Privacy(기밀성)

전달되는 데이터가 도중에 누군가에 의해 판돈되지 않는 다는 것을 보장한다. SSL은 다양한 암호화 알고리즘을 사용하여 인터넷을 통해 전송되는 개인의 사적인 정보를 외부로부터 불법적인 판독을 막는다.

 

○ Data Integrity(무결성)

사용자의 브라우저로부터 상대방 웹서버까지 전달되는 동안 데이터가 도중에 누군가에 의해 변경되지 않도록 보장한다.

 

SSL은 위와 같은 요소들을 보장하여 보다 안전한 커뮤니케이션을 할 수 있도록 도와주며 또한 MS 익스플로러나 넷스케이프 등과 같이 널리 보급된 대부분의 웹브라우저와 웹서버들에서 지원된다. 웹브라우저가 SSL 통신을 하는지 여부는 브라우저 오른쪽 하단의 잠금쇠 표시를 가지고 판별할 수 있는데 경우에 따라서는 브라우저 대신에 다른 보안 애플리케이션이 대신하기도 한다.

 

HTTPS 는 SSL상에서 HTTP 를 구현한 형태로 실제 HTTP 가 기본 포트 80 을 사용하는 대신 HTTPS 는 433 포트를 사용한다.

 

SSL은 다양한 어플리케이션들을 지원하기 위해 각각의 응용된 어플리케이션 프로토콜을 가지고 있는데, 이는 SSL의 구조를 보면 이해하기 쉽다. SSL은 OSI 7 계층에서 5 계층인 Session Layer에 속하며, 지원 가능한 프로토콜은 어플리케이션 레이어 상에 위한 하부 프로토콜로 한정될 수 밖에 없는데 HTTP, IMAP, FTP, NNTP 등이다.

 

2. SSL 동작 원리

 

 

SSL이 수행되는 단계는 총 3가지로 분류된다.

 

○ SSL Server Authentication

사용자의 웹브라우저가 상대방의 웹서버를 인증하는 단계이다.

SSL을 지원하는 웹브라우저는 표준 공용키 암호화 기법을 사용하여 서버의 인증서와 공용 ID를 실제로 브라우져가 신뢰하는 인증기관(Trusted CA)으로부터 발급받았는지 여부를 인증하는 기능을 내장하고 있다.

 

○ SSL Client Authentication

웹서버가 자신에게 요청한 클라이언트를 인증하는 단계이다.

서버 인증 시에 사용했던 동일한 기법으로 인증하는데 서버에 내장된 SSL 지원 소프트웨어나 서버 앞에 배치된 SSL 하드웨어는 클라이언트의 인증서와 공용 ID 를 실제로 서버가 신뢰하는 인증기관(Trusted CA)으로부터 발급 받았는지 여부를 인증하는 기능을 내장하고 있다.

 

○ Encrypt Connection

서로에 대한 인증단계 이후 정상적으로 종결되면 클라이언트와 서버사이에 교환되는 모든 데이터는 사적인 내용을 보호하기 위한 암호화를 요구받는다. 또한 SSL커넥션을 통해 암호화된 데이터 역시 전송 중 변경을 방지(Message Integrity)하기 위해 Hash 알고리즘이라고 불리는 기술에 의해 보호된다.

 

위의 3가지 단계를 기반으로 실제로 구현되는 순서는 다음과 같으며, 다음 순서를 진행하기에 앞서 SSL 또한 TCP 프로토콜에 기반을 두고 있으므로 반드시 TCP 3 Handshake는 이루어져 있어만 한다.

 

A. 클라이언트는 서버에게 Client Hello Message를 전송


일반적으로 브라우저를 통해 서버에게 SSL 연결 요청을 하기 위한 초기 단계이다.

 

B. 서버는 클라이언트로 Server Hello Message와 서버 인증서를 전송하며, 만약 클라이언트 인증서가 필요한 경우에 인증서 요청도 함께 전송

 

서버는 클라이언트가 자신이 적합한 서버인지를 인증할 수 있도록 공신력 있는 기관으로부터 발급받은 자신의 공인 인증서를 발송한다. 이때 일반적으로 서버 인증서와 함께 서버의 공용키가 클라이언트측에 전달된다. 만약 클라이언트에 대한 인증을 필요로 하는 트랜잭션이라면 이에 대한 요청도 함께 발송한다.

 

C. 클라이언트는 암호화에 사용되는 세션 키와 함께 클라이언트에서 지원하는 Cipher Suite를 서버로 전송하며, 서버가 인증서를 요청한 경우에는 클라이언트의 인증서도 함께 전송

 

서버의 인증서에 대해 클라이언트는 브라우저내에 저장되어 있는 신뢰기관으로부터의 발급여부를 확인하고 암호화에 사용될 Session Key를 생성해 서버 공용키로 Session Key를 암호화 하여 서버에게 전달한다. 또한 암호화된 Session Key와 함께 브라우저가 지원할 수 있는 Chiper Suite, 즉 암호화 기법 리스트와 함께 서버측에서 클라이언트의 인증서를 요청한 경우 스스로의 인증서를 발송한다.

 

D. 서버는 Chiper Suite를 받아들이고(또는 거부하고) Finished message를 클라이언트로 전송한 후 데이터 전송단계로 이동


서버는 클라이언트로부터 클라이언트 브라우저가 지원하는 암호화 기법 리스트를 받고 클라이언트에게 종결 메시지를 보내고 데이터 전송단계로 돌입한다. 여기까지 정상적으로 완료가 되면 클라이언트가 생성한 Session Key를 클라이언트와 서버가 모두 공유하게 된다.


E. 클라이언트는 최종메시지를 서버로 전송하고 데이터 전송단계로 이동

 

위 단계까지 정상적으로 완료되면 클라이언트는 종결 메시지를 서버에 보내고 실제 데이터를 전송하기 위한 단계로 돌입한다.


F. 상호 합의한 사이퍼 수트에 의해서 암호화된 메시지를 교환

 

앞 단계에서 서로 나누어 가진 Session Key로 암호화 된 데이터를 교환하게 된다.

 

3. SSL 암호화

 

SSL이 수행되는 단계에 보면 Session Key라는 것이 등장한다. Session Key는 한마디로 클라이언트 측에서 생성하여 서버로 전달된 하나의 키로, 하나의 동일한 키를 클라이언트와 서버가 각각 보관함으로 이후 전달되는 암호화된 데이터를 복호화 할 수 있도록 한다. 이 Session Key의 생성 및 전달 과정에 대한 보다 깊은 이해는 사실상 암호화 기법에 대한 이해를 그 바탕으로 한다.

 

이번에는 주로 SSL에 대한 개략적인 부분만 다루고 있기 때문에 암호화에 대한 부분은 간단하게만 살펴보도록 하겠다.


SSL 수행단계에서 교환되는 Session Key는 비밀키 암호화(Secret key cryptography). 즉, 대칭적 암호화에서 사용되는 키로서 하나의 키를 양쪽 상대방이 각기 나누어 가짐으로써 하나의 키로 암호화한 데이터를 송신측에서 전송하면 수신측에서 암호화 시 사용한 동일한 키로 복호화하는 단순한 구조를 가진다.

 

비밀키 암호화 기법은 그 사용이 간단하고 속도가 빠른 반면 크게 두 가지 문제를 가지고 있다.

첫번째는 어떻게 동일한 키를 서버와 클라이언트가 서로 공유하여 가질 것인가이며,

두번째는 서버측에서 볼 때 하나의 클라이언트당 각기 다른 세션키가 필요하기 때문에 어떻게 키를 관리할 것인가다.

 

위와 같은 문제 때문에 등장한 것이 공개키 암호화 즉 비대칭키 암호화 기법이다. 이 암호화 기법은 비밀키와 공개키라고 불리는 각기 다른 키로 구성된 한 쌍의 키를 클라이언트와 서버가 나누어 가지고 비밀키로 암호화된 데이터는 그와 같은 쌍이 공개키로만 복호화되는 알고리즘을 제공하고 있다.  이 암호화 기법은 비밀키 암호화 시 발생하는 키 교환의 문제를 해결해 주었다. 그러나 각기 나누어 갖은 한 쌍의 키를 가진 상대방에 대한 인증에 대한 문제와 암호화/복호화 과정에 많은 부하가 걸리는 단점을 가지고 있다. 따라서 실제로 SSL 수행의 경우 이 두 가지 암호화 기법과 PKI 기반의 디지털 인증서를 사용한 인증을 혼합하여 사용할 수 있다.


먼저 디지털 인증서(Digital Certificate) 교환을 통해 상대방을 인증, 공개키 암호화의 약점을 줄였으며 서버에서 클라이언트로 전달된 서버의 공개키로 클라이언트에서 생성된 세션키를 암호화하여 서버로 전달하는 공개키 암호화 기법을 사용하여 비밀키 암호화의 키 교환 문제를 없앴고 세션키가 전달된 후 세션키를 통해 실제 데이터를 암호화/복호화함으로 공개키 암호화 시 발생하는 부하로 인한 서비스 지연현상을 방지할 수 있다.


참고로 SSL에서 세션키를 통해 암호화하는 암호화 기법으로는 DES, 3DES, RC2, RC4등이 있고 40비트부터 168비트까지 사용된다. 메시지 무결성(Message Integrity) 보장을 위해 사용되는 Hash 알고리즘으로는 MD5나 SHA1.등이 주로 사용 된다.