티스토리 뷰

김익중 (네오위즈 콘텐츠팀) rheastrike@hanmir.com
2004.11.12 / AM 11:01

[지디넷코리아]지난 시간까지 ODBC(Open DataBase Connectivity)와 DAO(Data Acces Object)에 대해 공부했습니다. 이들은 상당히 중요한 개념이지만 사실 시장에서 밀린 경향이 없지 않습니다. 그럼 DBMS를 위해 ODBC 이외에 무슨 방법이 있는 것일까요?

모처럼 친구들과 만난 주말의 술자리, 반년 전에는 학생이었지만 지금은 어엿한 사회인인 친구들이 각자 회사와 개발 이야기을 합니다. 막상 직장에서의 교육을 받거나 기술 회의시간에는 회의록을 낙서장으로 만드는 레아군도 왠일인지 친구들과의 대화에는 수많은 기술적인 이야기들이 흘러나오는군요. 레아군은 지난 달에 겪었던 데이터베이스를 날려버릴 뻔한 이야기와 당시의 ODBC 일기장 프로그램을 이야기했습니다. 친구들은 유나라는 개발자에게 대해 관심 있게 물어보지만 한 친구는 딴지를 거는군요.

“요즘도 ODBC 쓰냐?”

이 한마디에 레아군은 다시 불타올랐고 즐거운 모임도 빨리 끝나기만을 바랍니다. 집에 가서 MSDN을 뒤져볼 전의를 다집니다.

DB 접속 기술의 발전
다양한 종류의 데이터베이스들을 하나의 함수로써 접근, 제어하기 위해 탄생한 것이 ODBC였습니다. ODBC는 원격 데이터베이스와 로컬의 데이터베이스를 모두 지원해주지요. 하지만 이 둘을 모두 지원하는 만큼 덩치가 커진 게 사실입니다. 따라서 로컬 전용인 DAO를 만들게 되었습니다. 여기에 새롭게 RDO(Remote Data Object)가 있습니다. RDO는 원격지의 데이터베이스에 대해 관리할 수 있는 개체를 의미합니다.

물론 드라이버만 준비된다면 어떤 DBMS든 가리지 않습니다. 다시 말해 ODBC에서 로컬 접근을 제외하고 순수하게 원격지 DBMS를 위한 개체라 할 수 있습니다. 그러나 정확하게 이야기하면 DAO나 RDO 모두 ODBC를 이용한다고 할 수 있습니다. ODBC에서 로컬 부분만 가져와 개체화시킨 것이 DAO이며 원격지 부분만 가져와 개체화시킨 것이 RDO입니다. 여기에서 한 가지 알 수 있는 것이 있습니다. 모두 DBMS 접속 기술이지만 ODBC 이후에 등장한 기술들은 Object라는 단어로 끝이 납니다. 바로 DBMS 접속에도 COM이 본격적으로 활용되기 시작한 것이지요.

‘역사는 돌고 돈다’는 속담은 DB 접속 기술에도 예외는 아니었습니다. 속도 개선을 위해 DAO와 RDO로 나눠진 ‘COM을 이용한 DBMS 제어 기술’은 처음의 ODBC처럼 다시 하나로 합쳐지게 됩니다. 물론 합쳐지게 되더라도 여전히 COM 개체가 자리잡고 있지요. 이 합쳐진 기술을 가리켜 ADO(ActiveX Data Objects)라고 부릅니다. ADO는 비주얼 스튜디오 6.0이 발표될 때 지금의 ADO.NET만큼 마이크로소프트가 강조한 기술입니다. 닷넷 플랫폼이 아닌 Win32에서라면 지금도 최고의 성능을 자랑하는 DB 프로그래밍 기술입니다.

ADO를 이용하는 이유는 이러한 속도가 첫 번째 이유가 됩니다. ODBC가 단순 DLL 개념이었던데 반해 DBMS를 하나의 액티브X 개체 개념으로 보기 때문에 속도 면에서 상당히 유리합니다. 두 번째는 지원 데이터베이스의 확장입니다. ODBC는 관계형 데이터베이스만 지원이 되었으나 DAO를 공부했을 때와 마찬가지로 ADO는 비관계형 데이터베이스인 e메일, 텍스트, 오디오 등 다양한 소스를 지원합니다. 그리고 ODBC 브릿지를 일일이 만들어 주지 않더라도 문자열 기반의 연결을 통해 DBMS에 접근할 수 있습니다. ODBC 브릿지가 프로그램을 일일이 따라가지 않아도 된다는 것은 배포에 있어서도 대단히 편리하며 유지보수에 있어서도 마찬가지입니다.

OLE DB는 무엇인가?
이제 OLE(Object Linking and Embedding) DB를 알아봐야겠군요. 사실 COM에 대해 상식이 있다면 이름만 듣고도 대강 눈치챌 수 있을 것입니다. OLE 기술을 바탕으로 COM이 만들어졌으니 OLE DB는 ADO를 이루는 하위 기술인 셈입니다. OLE DB는 관계형, 비관계형 데이터베이스에 접근할 수 있는 인터페이스를 하나로 묶어둔 개체입니다. ADO는 OLE DB를 통하여 DBMS에 접근하는 것이지요. 만약 ADO가 관계형 DBMS에 접근하려고 한다면 OLE DB는 기존의 ODBC 드라이버(브릿지가 아닙니다)를 이용해 해당 DBMS에게 접근하도록 해줍니다. 반대로 ADO가 비관계형 데이터베이스에 접근을 요구하면 OLE DB는 OLE나 COM 기술을 이용해 해당 데이터베이스(이메일, 텍스트 파일 등)에게 접근합니다. ADO를 이용한다면 수많은 DBMS와 파일 시스템에 대해 전혀 모르더라도 모두 접근이 가능한 것입니다.

지난 시간에 ODBC 브릿지를 이용하여 액세스와 SQL 서버 사이의 데이터를 이동시켰습니다. 그때에도 DBMS의 내용을 옮기는데 반드시 다른 관계형 DBMS가 아닌 다양한 파일 시스템을 지원해줬다는 것을 기억하나요? 이런 것이 OLE DB가 해주는 역할입니다.

<화면 1> OLE DB는 관계형 DBMS와 비관계형 데이터를 가리지 않습니다.

어떤 측면에서 보면 ADO는 OLE DB를 이용하는 라이브러리, 혹은 래퍼(Wrapper)라고 할 수도 있습니다. 사실 ADO가 만들어진 이유에는 비주얼 베이직이 큰 비중이 차지하고 있습니다. OLE DB는 로우 레벨(low level)의 COM 인터페이스이므로 비주얼 베이직 같은 RAD 툴에는 맞지 않았습니다. 또한 비주얼 베이직 개발자들이 OLE나 COM을 전혀 모르더라도 빠른 속력으로 데이터베이스 프로그래밍을 할 수 있도록 지원해 주기 위해서이죠.

그 이후 ADO가 장착된 비주얼 베이직은 SI 현장에서 ‘DB 프로그래밍 전용 툴’이란 별명이 붙을 정도로 높은 인기를 끌었습니다. 이러한 ADO의 수혜를 가장 많이 받은 분야는 비주얼 베이직 스크립트를 이용한 ASP 웹 개발자라는 생각이 듭니다. ADO는 완벽한(?) 액티브X 컨트롤입니다. 서버 사이드에서 DBMS 프로그래밍의 쓴맛을 전혀 맛보지 못한 개발자라 하더라도 단지 CreateObject 하나만으로 이 막강한 개체를 불러와 쓸 수 있는 것이죠.

하지만 슬프게도 바로 이점에서 VC++의 약점이 드러납니다. VC++에서 ADO를 사용하기 위해서는 COM에 관한 공부를 필요로 합니다. 특히 안타까운 것은 ADO가 원래 비주얼 베이직과 비주얼 베이직 스크립트를 위해 개발된 만큼 VC++ 개발자를 위해선 자료나 서적이 거의 없다는 점입니다. 물론 OLE와 COM, DBMS를 공부하면 하나씩 알아갈 수 있지만 VC++ 개발자에게 너무 많은 시간을 요구합니다(거기다 ADO.NET도 봐야 하잖아요?).

<그림 1> ADO와 OLE DB의 관계

현실적으로 VC++에서 ADO를 공부하고 사용하기 위해선 비주얼 베이직용 ADO 서적에서 객체와 메쏘드를 익히면서 MSDN에서 C++용 예제를 보신 후 코드구루(www.codeguru.com)나 코드프로젝트(www.codeproject.com)에 있는 ADO를 또 다시 래핑한 클래스를 살펴보는 것이 가장 좋다고 생각합니다. 비록 이 시간에 OLE DB를 공부할 것이지만 너무나 준비할 것이 많은 OLE DB보다는 ADO가 더 나은 선택이 될 것 같습니다(<그림 1>).

“유나는 정말 넘해요. 흑흑.”
“네? 갑자기 왜요?”
“ADO를 공짜로 쓰잖아요. 흐흐흑”
“네?”

OLE DB 소비자의 구현
사연 많은 DB 접속 기술을 논했으니 이제 OLE DB를 공부해 봅시다. 먼저 인터페이스는 <그림 2>와 같이 크게 3가지로 구분됩니다. 데이터 소비자, 데이터 서비스 제공자, 데이터 제공자의 세 가지 인터페이스가 있군요. 데이터 소비자는 개발자가 OLE DB를 통해 데이터를 접근할 때 사용하는 인터페이스를 의미합니다. OLE DB 인터페이스를 이용하는 애플리케이션의 코드입니다. 데이터 서비스 제공자는 데이터 제공자와 소비자간의 매개 역할을 하는 인터페이스로 ADO가 이 부분에 포함된다고 할 수 있습니다. 실제 데이터는 갖고 있지 않지만 OLE DB 인터페이스를 통해 캡슐화되어 있습니다. 데이터 공급자는 실제 데이터를 갖고 있으며 행 집합(rowset)을 의미합니다.

<그림 2> OLE DB 인터페이스

데이터 소비자는 DBMS 클라이언트로서의 이제까지 예제들과 같은 역할을 한다면 데이터 공급자는 OLE DB를 지원하는 DBMS를 만드는 데 사용할 수 있습니다. 공급자에 맞는 OLE DB 인터페이스를 정확하게 사용한다면 COM 서버이면서 OLE DB 소비자가 접근할 수 있는 자신만의 DBMS를 구축하는 셈이 됩니다. 그러한 OLE DB는 다음과 같은 개체로 구성되어 있습니다. 개체들을 이루는 인터페이스는 분량이 꽤 많으니 MSDN에서 OLE DB를 찾아 소개글(introduction)을 함께 보면서 어떤 인터페이스가 있는지 반드시 살펴보기 바랍니다. 참고로 이번 시간에는 직접 해당 인터페이스를 불러 쓰지 않을 것이니 복잡한 인터페이스들을 보며 울상은 짓지 마세요.

◆ 열거자(Enumerators) : 사용 가능한 데이터 소스(DBMS)를 검색합니다.
◆ 데이터 소스(Data Source) : DBMS나 파일에 연결하기 위한 장치를 의미합니다.
◆ 세션(Session) : DBMS에 대한 연결을 의미합니다.
◆ 명령(Command) : SQL문이나 저장 프로시저 같은 텍스트 기반의 명령을 실행합니다.
◆ 행 집합(Rowset) : 테이블 형식으로 데이터를 노출합니다. 데이터를 이용하는 가장 중요한 개체가 됩니다.
◆ 에러(Error) : 모든 OLE DB 개체들의 에러에 추가적인 정보를 포함해 줍니다.
◆ 트랜잭션(Transaction) : 롤백, 커밋 등의 트랜잭션을 관리합니다.


<그림 3> 필수적인 OLE DB 개체 순서와 해당 인터페이스 및 메쏘드 순서

여기서 7가지 개체들을 살펴보았으니 슬슬 OLE DB 프로젝트를 시작해보죠. 먼저 DBMS 클라이언트인 OLE DB 소비자부터 만들어보겠습니다. 먼저 VC++를 열고 대화상자 기반의 새 프로젝트를 만듭니다. OLE DB를 사용하기 위해 VC++에는 OLE DB 템플릿을 제공해 주고 있습니다. 이 템플릿은 소비자와 공급자를 모두 만족시켜 주는 무척 유용한 템플릿입니다. VC++의 메뉴바에서 「Insert | New ATL Object」를 선택하기 바랍니다.

New ATL Object 메뉴를 선택하면 MFC 프로젝트에 ATL을 이용하겠냐고 묻는 창이 나옵니다. 당연히 YES를 눌러줘야죠. 클래스 위저드에서가 아닌 ATL 개체에서 가져온 만큼 OLE DB 템플릿은 이제까지 봐왔던 MFC 코드가 아닌 STL 기반의 ATL 코드입니다. 그러나 같은 C++이므로 MFC에서 사용하지 못한다는 법은 없지요. 또한 단지 이용만 하는 것이기 때문에 당장 STL을 잘 몰라도 사용하는 데는 지장이 없습니다. 비록 지금은 기존 템플릿을 통해 구현하겠지만 API 수준에서 직접 OLE DB를 구현해 보는 공부도 언젠가는 필요할 것입니다.

<화면 2> ATL 개체 위저드에서 OLE DB 템플릿을 선택합니다.

<화면 2>와 같은 윈도우가 나올 것입니다. 이것은 ATL 프로젝트에서 각종 개체를 추가시켜주는 ATL 개체 위저드입니다. 대화상자 같은 것도 보이죠? 네 번째 Data Access에 있는 Consumer(소비자)를 선택합니다. 이제 <화면 3>과 같은 DBMS를 선택하라는 윈도우로 바뀝니다. 오른쪽 상단에 있는 Select Datasource를 눌러 DBMS를 결정합니다.

<화면 3> OLE DB 소비자 클래스를 위한 준비

가장 먼저 ‘공급자’라는 탭이 보입니다. 이것은 자신의 PC에 설치된 ODBC 드라이버를 의미합니다. OLE DB라 할지라도 관계형 DBMS에는 이렇듯 드라이버가 필요합니다. 간단하게 사용하기 위해 지난 호에서 이용했던 MS SQL 서버의 Diary 데이터베이스를 그대로 사용하겠습니다. 따라서 Microsoft OLE DB Provider for MS SQL을 선택합니다.
드라이버를 선택하면 ‘연결’ 탭으로 자동적으로 이동합니다. 각자 자신의 MS SQL 서버와 로그인 ID, 암호 그리고 사용할 데이터베이스를 선택합니다.

<화면 4> MS SQL 서버를 선택한 화면

<화면 4>와 같은 형식으로 입력하면 됩니다. 연결 테스트 버튼을 눌러 정상적으로 연결이 되는지 확인해 봅시다. 왠지 연결 테스트조차도 빠른 것 같은 느낌이 오지 않나요? 이제 확인 버튼을 누르고 테이블을 선택합니다. 모든 과정을 마치면 선택한 테이블이 클래스화되어 여러분의 코딩을 기다립니다. 구조가 이제까지의 CRecordset과는 달라져 당황스러울 수도 있습니다. 그러나 ‘테이블이름.h’ 헤더 파일만 집중적으로 보면 됩니다.

 <리스트 1> OLE DB 연결 루틴

<리스트 1>을 보면 가장 먼저 CdboDiaryAccessor라는 클래스가 있습니다. 이것은 접근자로 원형은 CAccessor입니다. 이 클래스는 CRecordset에서와 마찬가지로 실제 DBMS 내 필드를 VC++의 자료형에 맞게 바인딩시키고 필드를 멤버 변수로 지정하는 부분입니다. 이렇듯 OLE DB의 기본적인 개념은 CRecordset과 비슷합니다. 만약 OLE DB 템플릿이 DBMS의 필드 구조를 모를 때는 CAccessor 대신 CDynamicAccessor 클래스를 이용하게 됩니다. DBMS을 여는 OpenDataSoure() 역시 대단히 중요합니다. 데이터 소스 개체가 CDataSource 클래스 형태로 지원되는 것을 볼 수 있습니다.

OLE DB에는 여러 인터페이스들이 존재하지만 클래스 형태로 쉽게 사용할 수 있도록 되어 있습니다. CDataSource::Open()은 실제 DBMS와 연결하는 부분입니다. OLE DB의 중요한 특징 중 하나는 레지스트리 기반의 연결 정보가 아닌 단순 텍스트 기반의 연결이란 사실입니다. <리스트 1>에서는 AddProperty 메쏘드를 이용하여 DBMS의 주소, 사용 데이터베이스, 로그인 ID 등을 하나씩 붙이고 있지만 Open()에서 dbinit 대신, 다음과 같은 식으로 적어 넣어도 완벽하게 연결됩니다. 혹시 비주얼 베이직이나 ASP 경험이 있는 독자라면 연결 문자열이 대단히 반가울 것입니다.

그리고 VC++에서도 똑같은 문자열이 쓴다는 사실이 신기할지도 모르겠습니다. 비주얼 베이직과 ASP가 OLE DB를 이용하고 OLE DB는 이러한 문자열 기반의 연결을 하기 때문입니다. 따라서 만약 VC++ 개발자도 ADO를 사용한다면 다른 스크립트 언어와 같은 메쏘드를 호출합니다(지난 1~3월에 공부한 액티브X 컨트롤을 기억하세요).

Provider=sqloledb;Data Source=“IP 주소나 컴퓨터 이름” Initial Catalog= “DB이름”;
User Id=“DBMS 아이디"; Password=”비밀번호“"

실제로 Open()에서 연결 문자열만 바꾸면 다른 DBMS 연결이 가능합니다. 이것이 OLE DB의 장점 중 하나입니다. COM답지 않게 레지스트리를 더럽히지 않으니까요. ODBC 브리짓 역시 사실은 레지스트리의 키 하나입니다. 따라서 각각의 DBMS마다 연결 문자열은 중요한 자료이며 ‘OLE DB 연결 문자열’나 ‘ADO 연결 문자열’ 같은 검색어로 인터넷을 살펴봐도 금방 찾을 수 있습니다. 예컨대 오라클의 경우에는 다음과 같은 식으로 프로바이더의 이름부터 사소한 몇 가지가 달라집니다.

Provider=OraOLEDB.Oracle; Data Source="DB이름";User Id="아이디";Password="패스워드";

이제 연결과 DBMS 이용을 구현해보겠습니다. UI에 관해서는 이전과 다를 바가 없으니 필자는 간단하게 에디트박스 하나만 올려 필드를 살펴보겠습니다. CRecordset과 마찬가지로 사용하고자 하는 클래스에서 CDiary 클래스의 인스턴스를 선언합니다. <리스트 2>는 OLE DB 템플릿으로 만들어진 클래스를 실제 사용하는 루틴입니다. 특별한 점 없이 Open()으로 열고 MoveNext와 같은 함수를 사용하여 테이블 내의 필드가 여전히 멤버 변수인 점을 알 수 있습니다. 하지만 OLE DB는 여전히 저수준의 기법입니다. BOF(Begin Of File), EOF(End Of File)을 검사할 수도 없습니다. 개발자가 직접 구현해줘야 하는 것이죠. 연결을 끊을 때에는 m_DiaryDB.Close(), 즉 CAccessRowset::Close() 뿐만 아니라 현재 연결을 유지하는 세션 역시 반드시 종료시켜 줘야 합니다.

<화면 5> OLEDBConsumerDlg.dsw의 실행 결과


 <리스트 2> OLEDBConsumerDlg.cpp


OLE DB는 INSERT나 UPDATE 같은 함수가 없습니다. 내용을 수정하려면 직접 SQL문을 날려야 합니다. 그러기 위해선 m_DiaryDB 개체 속에 있는 m_spCommand->Execute() 메쏘드를 이용해야 합니다. Execute()를 사용해 쿼리를 전송하는 것은 독자들의 몫으로 남기겠습니다. 참고로 MSDN에서 m_spCommand으로 검색해 보면 예제가 나올 것입니다.

OLE DB란 게 이렇게 복잡한 것이라니! ODBC 안 쓰기 위해 이렇게 고생해야 한다는 거야? 으음, 현실과 타협해 ADO의 대열로 끼어들어야겠어.

컨트롤로 맛보는 ADO
안타깝게도 VC++에서 ADO는 MFC 클래스도 ATL 템플릿도 제공되지 않습니다. 하지만 앞서 말한 선행학습 없이도 ADO를 사용할 수는 있습니다. 바로 액티브X 형식으로 제공되는 ADO 데이터 컨트롤을 이용하는 것이죠. 액티브X 컨트롤은 메뉴바에서 「Project | Add To Project | Components and Controls」를 선택하면 찾을 수 있습니다. 액티브X 제작기 하면서 배웠었죠? 「Registered ActiveX Controls」 폴더에서 「Microsoft ADO Data Control, version 6.0(OLEDB)」를 찾아 「Insert」 버튼을 누릅니다.

ADO 컨트롤을 찾아 대화상자에 그리면 UI는 볼품없습니다. 앞뒤로 이동하는 버튼들이 네 개 있을 뿐이지요. ADO 컨트롤은 ADO를 이용한 연결 및 다양한 SQL 쿼리를 해결해 줍니다. 데이터베이스 내의 내용을 보기 위해서는 다른 컨트롤이 있어야 하는데 여기에서는 데이터그리드 컨트롤을 이용하겠습니다. ADO 컨트롤과 데이터그리드 컨트롤은 데이터베이스 프로그래밍에서 떼기 힘든 콤비죠. 데이터그리드 컨트롤은 역시 액티브X 컨트롤이므로 방금과 같은 방법으로 「Microsoft DataGrid Control, Version 6.0(OLEDB)」를 선택하면 됩니다.

<화면 6> 모처럼 열어보는 액티브X 컨트롤 폴더

먼저 컨트롤을 멤버 변수로 만듭니다. 클래스 위저드에서 ADO 컨트롤은 m_ctlADO라는 멤버변수로 만들었습니다. 이젠 ADO로 연결을 해봐야겠죠. ADO 연결은 무척 쉽습니다. ADO 컨트롤에서 엔터키를 누르거나 마우스 오른쪽 버튼으로 「Property」 창을 꺼냅니다. 두 번째 탭인 「일반」에서 우리는 다양한 데이터를 연결할 수 있습니다. 파일 기반, ODBC, 문자열 기반 등 이제까지 우리가 배워왔던 모든 접속 방법들이 ADO에선 다 지원되고 있다는 것을 알 수 있습니다.

어떤 형식의 데이터를 열 것인지는 여러분이 각자 결정해 보세요. ODBC를 이용하여 텍스트 파일이나 엑셀을 읽어도 될 것이며 문자열로 SQL 서버를 이용해도 될 것입니다. 특히 연결 문자열을 이용할 경우 ADO 컨트롤은 문자열을 자동으로 만들어 줍니다. 다양한 DBMS를 선택해 보며 연결 문자열이 어떻게 변경되는지 확인해보는 것도 좋을 것입니다. ADO 컨트롤 역시 연결 후 기본적으로 날릴 SQL문을 설정할 수 있습니다. 네 번쨰 탭인 ‘레코드 원본’에서 명령 텍스트라고 적힌 곳에 SQL문을 입력합니다. 필자는 역시 SQL 서버에 있는 Diary 데이터베이스를 이용하며 모든 것을 다 가져오기 위해 SELECT * FROM DIARY라고 입력했습니다. 이것으로 ADO 연결 준비는 끝났습니다. 이제 ADO 컨트롤이 가져온 데이터를 보여줄 데이터그리드 차례입니다.

데이터그리드에도 다양한 프로퍼티가 있지만 우리가 사용할 것은 단 하나 Data Source뿐입니다. 로우셋을 비롯한 모든 내용들은 ADO 컨트롤이 다 구현해주므로 데이터그리드는 단지 내용을 뿌릴 뿐입니다. Data Source는 데이터그리드 프로퍼티 마지막 탭인 「All」에서 찾을 수 있으며 클릭하여 ADO 컨트롤을 선택해 줍니다. 컴파일해보면 코딩 하나 없이 ADO를 이용해 데이터를 볼 수 있게 됩니다.

<화면 7> ADO 컨트롤을 이용한 데이터베이스 접속

<화면 8> 데이터그리드는 데이터 소스를 ADO 컨트롤로 맞춰줍니다.

<화면 9> 컨트롤를 효과적으로 사용하면 짧은 시간에 강력한 기능을 쓸 수 있습니다.

컨트롤에 의해 만들어진 프로그램이지만 보다 능동적인 사용도 물론 가능합니다. ADO 컨트롤을 이용해 DBMS에게 SQL만 날려줄 수 있다면 되는 것이니까요. SQL문을 날려보기 위해 버튼을 하나 만들고 더블 클릭해 OnSql()이란 함수를 만들었습니다. 여기에서 모든 필드를 보는 것이 아닌 일기의 제목(title)만 보고 싶다면 어떻게 하면 될까요?

 <리스트 3> ADO 컨트롤을 이용한 쿼리의 전송

SetRecordSource()는 SQL문을 전송하고 Refresh()는 변경된 결과를 다시 뿌려줍니다. 이 두 개의 메쏘드만 알고 있어도 대부분의 작업들을 처리할 수 있습니다. ODBC나 DAO와 달리 최신이라는 ADO는 데이터 조작를 위한 함수를 거의 갖추고 있지 않습니다. 어느 정도 SQL문에 익숙해지면 그런 함수 자체가 필요 없기 때문입니다. 또한 VC++ 개발자라도 필수 SQL은 알고 있어야 한다는 증거라면 지나친 해석일까요? <리스트 3>은 기존 결과에서 원하는 집합만 본 것이었고 새로이 추가를 위해서는 INSERT문을 이용하면 됩니다.

m_ctlADO.SetRecordSource("INSERT INTO Diary \
   ( Date, Weather, Title, Contents) \
   VALUES( GETDATE(), 1, '마소 Jr', 'DB 연재를 마쳤습니다.')");

몇 가지 컨트롤을 덧붙이고 ADO 컨트롤의 메쏘드만 잘 살펴보더라도 아주 짧은 시간으로 효율적인 ADO 프로그래밍을 할 수 있는 것이죠. 필자의 연재에서는 코드가 필요 없는 예제와 그 내부를 코드로 재진입하는 예제들이 이제까지 나왔었지만 ADO의 직접 구현은 역시 독자의 몫으로 남겨둘까 합니다.

그래, 결심했어. OLE DB든 ADO든 제 스타일에 맞는 녀석으로 오랫동안 사용할 수 있는 레아군 전용 클래스를 만들어야지.

데이터베이스 프로그래밍은 실전 프로그래밍
추측컨대 세 달 동안 진행된 이 강좌는 평소에 비해 재미없었을 것이라 확신합니다. 필자가 초보일 때 바로 그랬습니다. 무언가 색상이 바뀌고 움직이는 것이 아닌 값들을 집어넣고 수정하고 검색하는 것은 대단히 지루했습니다. 그러나 데이터베이스 프로그래밍은 피할 수 없는 분야입니다. 막강한 데이터베이스를 다루면서 공부할 수 있는 예제라곤 언제나 값을 넣고 수정하고 읽어오는 것 밖에 없지요. 우리가 만들었던 일기장처럼요. 그리고 데이터그리드 같은 컨트롤을 사용한다 하더라도 액세스나 엔터프라이즈 매니저, 토드 같은 전문 툴에 비해 대단히 불편한 것도 사실입니다.

그렇다면 이 재미없는 과목을 왜 공부해야 하는 것일까요? 데이터베이스 연재를 시작하면서 데이터베이스는 자료 저장소이며 프로그래밍을 편리하게 하기 위해 사용한다고 밝혔습니다. 고작 친구 주소록, 개인 일기장이라면 텍스트 파일이 더 편리하겠지만 만약 1000명, 10000명이 동시에 사용하는 일기장이라면 관리와 운영에 있어 DBMS가 막강한 힘을 냅니다. 이런 DBMS의 파워는 개인 습작이나 짧은 예제로 쉽게 맛볼 수 없습니다.

그래서 데이터베이스 프로그래밍은 실전 프로그래밍에 들어가서야 제대로 맛볼 수 있습니다(실제 서비스 진행 중인 DBMS를 조작할 때의 그 두려움이란!). 또한 동시에 1000명, 10000명이 사용하는 애플리케이션이라면 클라이언트 프로그램이 아닌 대부분 소켓 서버 프로그램을 의미합니다. 만약 서버 개발자를 꿈꾸는 분이 있다면 TCP/IP와 소켓만으로는 서버를 절대 만들 수 없습니다. 가장 기본적인 기능인 로그인조차 DBMS를 모르고는 불가능합니다.

로그인이란 뭘까요? DBMS에 쌓인 사용자의 ID와 패스워드를 SELECT문으로 검색하는 것입니다. 먼저 SELECT문으로 ID를 검색하고 결과 값이 없으면 회원가입을 요청하고 ID는 검색되지만 패스워드가 결과 셋에 없다면 패스워드가 틀린 것이겠죠. 마지막으로 ID와 패스워드가 한 사용자를 구성하는 결과 셋에 정확하게 놓여 있다면 로그인을 시켜주는 것이죠.

성공적으로 로그인한 후, 해당 클라이언트의 ID로 역시 SELECT문을 돌려 사용자의 아이템이나 전적을 표시해 줍니다. 레벨 업이나 새 아이템을 얻었다면 데이터베이스에 INSERT와 UPDATE를 하면 됩니다. 간단한 온라인 게임의 경우를 든 것이지만 우리 주변의 모든 정보는 이렇게 DBMS에 담겨져 있으며 C/S 개발 능력이 현재 개발자의 기본 능력이 되었기에 서버 필수 기술로써 데이터베이스 프로그래밍의 중요성이 부각되는 것이죠.

여름 맞이 사이트 개편으로 개발자들이 지친 저녁입니다.
“레아군, 정말 뛰어난 개발자가 된다면 언젠가 만들어줘요, 조립만 하면 뭐든지 되는 웹 사이트 제작 컴포넌트 모음집을요. HTML 템플릿으로 모양만 바뀌는 것 말고요.”

기술에서 아키텍처로
이제까지 우리는 ODBC, DAO, RDO, OLE DB, ADO 등 무려 다섯 가지나 되는 데이터베이스 기술들을 살펴보고 네 가지 기술들의 예제를 만들어 보았습니다. 이 안에는 훨씬 더 많은 기능들이 포함되어 있지만 가장 본질적인 요소들은 한번씩 접해본 셈입니다. 그렇다면 이제 ADO를 컨트롤 대신 코드로 구현할 수 있게만 되면 데이터베이스 프로그래밍의 모든 것을 다 공부한 것일까요? 기쁘게도 절대 아닙니다. ADO만 알아서는 2-티어 애플리케이션 밖에 만들 수 없습니다. 언급한 모든 데이터베이스 접속 기술은 다 브릿지(bridge)입니다. MFC 애플리케이션과 DBMS가 C/S 구조로 데이터를 주고받는 것이고 ODBC나 ADO는 TCP/IP에서 소켓과 비슷한 역할을 하는 구조입니다.

만약 DBMS에 질의하는 클라이언트의 수가 많아진다면 이러한 2-티어 구조는 취약성을 지니게 됩니다. 대역폭과 트랜잭션에서 말이죠. 여기서 잠시 90년대 중후반으로 타임머신을 타보죠. NT 4.0과 SQL 서버 6.5, 7.0이 활약하던 시기입니다. 당시 불붙은 웹의 인기는 수많은 기업과 조직으로 하여금 웹 서버를 운영하게 했고 회원 관리, 게시판 같은 기본적인 서비스를 위해서도 반드시 DBMS를 필요로 하게 되었습니다. 큰 웹 사이트일 경우에는 늘어나는 다양한 서비스들을 추가하고 관리하기 위해서 엄청나게 복잡한 코드들이 난무하게 됐습니다.

따라서 DBMS에 대한 접속을 더 발전시키는 것과 함께 화면에 보이는 코드, 즉 프리젠테이션 영역과 업무를 처리하는 영역인 비즈니스 영역이 분리될 필요성이 대두됩니다. 당연히 DBMS는 DBMS대로 데이터 영역이지요. ODBC, ADO 역시 같은 시기의 기술이지만 그것들의 한계를 극복하기 위하여 프리젠테이션, 비즈니스, 데이터 영역으로 나눈 3-티어 형태가 급부상하게 됩니다. 이것이 바로 2-티어의 한계를 극복하는 3-티어 구조이며 지금도 여전히 이런 구조를 취하고 있습니다.

그동안 이러한 3-티어 구조에 관한 강좌가 많았습니다. 그리고 2-티어에서 3-티어로 넘어가는 순간, 잘 만든 코드에서 잘 만든 아키텍처를 볼 수 있는 시선이 생기게 됩니다. 현재 중심을 이루는 기술도 이 시기에 대두되어 꾸준히 발전되어 온 것들입니다. 그럼 3-티어는 어떻게 만드는 것일까요? 우리가 만든 애플리케이션과 DBMS 사이에는 미들웨어 혹은 미들티어라고 불리는 중간 서버가 존재합니다. MS에서는 이 서버를 NT 4.0 시절 옵션 팩 안에 무료로 제공하였고 윈도우가 버전 업되면서도 IIS 웹 서버와 함께 무료로 제공되고 있습니다. 바로 MTS(Microsoft Transaction Server)라는 서버이며 윈도우 2000부터는 ‘구성 요소 서비스’라는 조금 난해한 이름으로 바뀌었습니다.

<화면 10> 3-티어 아키텍처를 위한 서버인 MTS

비즈니스 계층의 중심인 MTS를 사용하기 위해서는 In-Process 액티브X 형태의 DLL을 만들어야 합니다. 이때 이벤트(Loosely Coupled Event)의 발생, 클러스터 서비스와 큐 서비스를 위해 COM+를 지원하며 그리고 여전히 ADO가 널리 이용됩니다. 아쉽게도 여기에서 MFC의 약점이 드러나는데 비즈니스 계의 주요 형태인 액티브X DLL을 만들기 위해서는 MFC의 UI는 필요 없어지게 됩니다. 바로 이때 VC++의 ATL(ActiveX Template Library)가 맹활약하게 됩니다. ATL은 이것을 위해 태어난 라이브러리이죠. 닷넷 역시 닷넷 프레임워크가 있다는 점을 제외한다면 이와 별반 다르지 않습니다. VC++는 결코 MFC 전용 코딩 툴이 아니며 항상 확장자가 EXE로 끝나는, 스탠드 얼론(Stand Alone) 애플리케이션만 만드는 것이 아닙니다. 이런 서버 쪽 시장은 클라이언트 애플리케이션만큼 거대하며 초보 개발자에게 보다 넓은 시야를 요구합니다.

갑자기 평소 잘 듣지 못한 용어들이 나와서 당혹스러울 수도 있을 것입니다. 만약 당혹스럽다면 아직도 즐거운 공부꺼리가 남았다는 사실에 기뻐하기 바랍니다. 그리고 이런 것들이 친근해질 때 서버 측 아키텍처가 다시 보여질 것입니다. 비록 웹 이야기와 함께 비즈니스 로직을 이야기했지만 결코 웹 전용이 아니라는 사실을 잊지 마세요(사실 웹은 TCP/IP 80번 포트를 이용하는 텍스트 기반의 프로토콜에 불과합니다). 소켓 기반의 C/S에서도 여전히 유효합니다. 또한 기업에 따라선 마이크로소프트의 아키텍처나 썬의 아키텍처가 아닌 독자적인 자신만의 비즈니스 로직을 구현해 운영하는 곳도 많습니다. 그렇다 하더라도 마이크로소프트나 썬의 아키텍처를 이해하고 있다면 다른 아키텍처도 분명히 이해가 빠를 것입니다.

MFC 여행을 마치며
필자는 후배들을 만나면 항상 UI 프로그램, 데이터베이스 프로그래밍, 소켓 프로그래밍, 이 세 가지를 자신있게 할 수 있다면 어떤 분야로 가더라도 사랑(?)받는다고 이야기합니다. 이번 강좌에서 소켓을 다루지는 못했지만 UI와 데이터베이스 강좌가 프로그래밍이라는 험난한 과정에 도움이 되었기를 바랍니다. 아직 방향조차 못 잡은 독자에게는 조금이나마 길을 밝혀주고 매너리즘의 늪에 빠지려는 개발자에게는 기존 기술을 정리하는 시간으로 활용됐기를 바랍니다.

계속해서 MFC를 공부할 초보 개발자라면 이 글을 다 읽고 다음으로는 소켓을 공부하기 바랍니다. UI, 데이터베이스, 소켓이 붙으면 만들고 싶은 대부분의 애플리케이션을 만들 수 있을 것입니다. 그러나 이 세 가지를 다 배웠다 하더라도 인터넷 익스플로러에 붙는 밴드나 툴바 같이 조그만 애플리케이션을 만들 수는 없습니다. COM과 같은 윈도우의 표준 대화방식을 알아야 하기 때문이며 이때부터 본격적인 중급 개발자로 나아가는 것입니다. 이 시기까지 오더라도 자신을 어느 분야로 특화시키기가 힘들 것입니다. 시대가 변해 이 정도는 알고 있어야 ‘범용 개발자’라 할 수 있거든요. 그리고 수많은 예제를 컴파일해 보고 만들어 보세요. 그 가운데 자신이 가장 끌리는 분야가 조금씩 떠오를 것입니다. @

댓글