구글와이드(336x280)_상단 2개


효과적인 DB SW 개발 비법「데이터레이어」 DB

효과적인 DB SW 개발 비법「데이터레이어」
[데이터레이어를 이용한 DB 개발] ① 데이터레이어의 개발 배경과 구조
박문찬 ( 마이크로소프트웨어 ) 2004/06/07
데이터베이스 응용 프로그램 개발할 때 공통적인 고민은 “데이터 관리를 어떻게 하면 잘할 수 있을까”이다. 서버와 클라이언트의 쿼리 전송, 결과 값의 반환, 데이터의 추가, 삭제, 갱신 등을 효율적인 방법으로 개발하는 것. 필자는 그 대안으로 데이터레이어를 이용한 개발을 제안한다.
처음 데이터베이스 응용 프로그램을 개발하게 되면 데이터와 관련된 부분 때문에 많은 어려움을 겪게 된다. 물론 개발 경험을 갖고 있다고 하더라도 이런 문제는 쉽게 해결되지 않는다. 필자는 앞으로 3회에 걸쳐 필자가 직접 만든 데이터레이어(Datalayer)를 통해 여러 형태의 데이터를 효과적으로 관리하는 방법을 설명한다. 데이터 관리 부분에 대한 문제점 해결, 개발시간의 단축, 프로그램 수정의 용이성, 데이터에 관련된 공통적인 인터페이스 제공 등이 이뤄졌으면 한다.

데이터레이어에 대한 소개부터 시작해 기존 데이터베이스 응용 프로그램 개발시의 문제점을 살펴보며, 이러한 문제점을 해결하기 위한 개발 배경과 구조적 설명과 사용 등에 대해 알아본다.

데이터레이어는 액티브X 클래스 모듈
데이터레이어는 데이터베이스 응용 프로그램에서 사용할 수 있는 액티브X 클래스 모듈이다. 데이터레이어의 사용기술 및 환경은 비주얼 베이직 6.0 sp5, MS-SQL 2000 sp3, MS XML 3.0 sp4, MDAC 2.7 sp1(ADO 2.7)의 내용들을 포함하고 있다. 또한 데이터의 정의, 공통적인 인터페이스 제공, 쿼리의 효율적인 관리, 바이너리 데이터와 컨텍스트 파일의 입출력, XML-RSS 데이터의 레코드셋으로의 변환 등을 지원한다.

그럼 기존 데이터베이스 응용 프로그램 개발시에 발생할 수 있는 데이터 관련 문제점이 무엇인지 살펴보고, 데이터레이어로 이런 문제점을 어떻게 해결할 수 있는가를 알아보자.

DB와 관련한 몇 가지 문제점
많은 프로그래머들이 프로그램 개발 방법으로 구조적 프로그래밍 기법, 모듈화 방법을 사용하고 있으나 프로그램의 크기가 커지고 프로젝트 개념으로 변하면서 몇몇 문제점을 드러내고 있다.

첫 번째로 변수와 관련해 변수명에 대한 표기방식의 차이로 인한 문제이다. 모든 프로그래머가 정해진 표기를 따르는 것이 아니어서 개인적인 차이가 발생하게 되는데, 이로 인하여 서로간의 의미전달이 정확하게 이루어지지 못하는 것이다. 예를 들면 한글 발음을 영문 표기한 변수명이나 약자에 의한 변수명 사용 등이 그것이다.

두 번째는 개발 프로그램의 양적 확장으로 인해 쿼리의 수와 종류가 늘어남에 따라 효율적인 관리가 어려워지며, 개발 기간이 길어지거나 수개월 후 수정해야 하는 경우 쿼리에 대한 이해 정도와 반환된 데이터에 대한 신뢰성이 떨어지는 문제가 발생한다.

세 번째로 동일한 결과를 얻어내는 쿼리를 프로그램의 여러 곳에 삽입했을 때 그 쿼리의 반환 값에 오류가 있어 쿼리를 수정해야 할 경우이다. 이때 프로그램의 여러 부분에 퍼져 있는 쿼리를 모두 수정해야 하는데, 이런 문제의 발생 원인은 모듈화를 극대화하기 위해서 전역변수의 사용을 최대한 억제하였기 때문이다.

물론 저장 프로시저나 뷰를 사용할 수도 있지만, 기본적으로 프로그램의 개발 단계 및 수정 단계에서는 쿼리가 프로그램의 소스 내에 존재하는 것이 수정하기에 용이하고 더불어 저장 프로시저나 뷰의 수가 증가할수록 수정의 어려움이 더욱 커지기 때문에 사용을 자제하는 것이 좋다. 일반적으로 쿼리는 한번의 작성으로 끝나는 경우보다 사용자로부터의 입력 값을 쿼리에 이용해야 할 경우가 많은데, 이런 부분이 많으면 많을수록 오류 발생 확률이 높아지게 된다.

ADO로 인해 발생하는 문제
그렇다면 ADO(ActiveX Data Object)를 사용하면서 발생하는 문제점에는 무엇이 있을까? 데이터베이스 응용 프로그램 개발시 다수의 레코드셋을 열어 놓고 사용하게 되는 데, 이 때 각 레코드셋은 서버와의 커넥션을 유지하게 되고 그런 것이 많아질수록 서버가 부담을 갖게 된다. 또한 다수의 레코드셋 변수의 관리 소홀로 인한 자원 낭비가 발생하는 경우가 종종 있다. 바로 ADO를 사용하기 위해서는 객체를 New 키워드로 생성하고 Nothing으로 소멸을 시켜주어야 자원의 낭비를 줄일 수 있는데, 이 부분에 대해 신경을 쓰지 못하기 때문이다.

그리고 단일 계산 값을 반환해야 하는 경우에 반드시 레코드셋 객체를 선언하고 사용해야 하는 것도 효율적이지 못한 경우이다. 예를 들면 매출전표의 매출 금액을 알고자 한하면 Sum 함수를 이용해 알 수 있는데, 이때 단 한 개의 반환 값을 위해 레코드셋 객체가 만들어지고 만들어진 객체는 Nothing으로 소멸시키기 전까지는 메모리에 유지되므로 프로시저나 함수의 마지막에 추가적인 코딩이 꼭 필요하게 된다.

데이터레이어가 어떻게 해결할 수 있는가?
앞에서 데이터 관리의 문제점을 살펴보았는데 그렇다면 이런 문제들을 데이터레이어가 어떻게 해결할 수 있을까? 먼저 변수와 관련된 문제점의 해결 방법으로는 변수 이름의 선언 방법과 사용 방법에 대한 공통적인 인터페이스를 제공해 프로그래머들이 사용할 변수명의 규칙을 통일할 수 있도록 하는 것이다. 공통적인 인터페이스의 제공은 CField 객체에 한글 이름을 붙여서 변수와 동일한 개념으로 사용하는 것을 의미하며, 이렇게 사용함으로서 해당 객체에 의미 또한 더욱 정확하게 부여된다.

[예제 1] 기존 변수 이름과 CField를 이용한 이름 지정의 차이
① curSaleTotalAmount = 10000
② curTotal = 10000
③ curMeChul = 10000
④ dlCustomer(“매출총액”).pValue = 10000 ‘dlCustomer는 CDatalayer 객체입니다.

[예제 1]을 보면 변수명의 다양한 형태를 볼 수 있는 데, ①번부터 ③번까지는 프로그래머에 따라 자신이 사용하고 싶은 방식으로 골라서 사용할 수 있으나 나중에 이런 변수명들을 자신이나 혹은 타인이 본다면 아마도 그 의미를 찾기 위해서 걸리는 시간이 처음에 개발할 때 소요되는 시간보다 곱은 더 걸릴 것이다. 그러나 ④번의 경우는 비록 길이가 약간 길어졌지만 객체명만으로도 어떤 변수인지 한 눈에 파악이 가능하게 되며, 특히 ①번과 비교했을 때 curSaleTotal Amount라고 하면 자사의 매출총액인지 특정 거래처의 매출총액인지 등의 성격 구분이 명확치 않으나 dlCustomer라는 부분이 있으므로 해서 거래처의 매출총액임을 좀 더 명확하게 알 수 있다.

다음으로 데이터베이스와 관련된 문제점 중 쿼리의 문제 해결방법을 보면 쿼리의 선언이 특정 장소에서 이루어지지 않고 프로그램의 여러 곳에서 선언되어 발생되는 문제이므로, 폼(Form)이나 전체 프로그램에서 사용되는 쿼리들을 특정 프로시저에서 일괄 입력시킬 수 있도록 하여 문제를 해결했다. 또한 입력시에 쿼리에 이름을 붙여주므로 쿼리의 사용 용도, 사용 방법 등을 이해하기가 수월해져 차후 수정 및 검색이 용이하게 된다.

프로그램의 여러 부분에서 사용되는 동일한 결과의 쿼리를 Public형의 CDatalayer 객체에 입력하면 프로그램 전체에서 필요할 때에 사용이 가능하므로 차후 쿼리를 단 한번만 수정해도 그 효과가 일괄 적용된다. 물론 이 부분은 일반 전역변수를 선언해 사용할 수 있지만 여러 개의 개별적으로 존재하는 전역변수와 한글명으로 되어 있는 쿼리를 사용하는 것과 비교해 보면 어떤 것이 더 효율적인지 알 수 있을 것이다.

CDatalayer 객체는 쿼리를 입력하면 쿼리가 사용할 입력 값, 출력 값들을 저장하고 사용할 수 있는 CField 객체를 자동으로 생성해 주므로 추가적인 변수를 선언할 필요가 없게 된다. 이는 쿼리의 구성 요소에 기본적으로 ‘어디서’, ‘무엇을’, ‘어떻게’라는 정보를 포함하고 있기 때문이다.

[예제 2] 기본적인 쿼리문의 구성
Select Cust_ID, Cust_Name_VC, Cust_Alias_VC From Cust_T Where Cust_ID = 1

[예제 2]에서 ‘어디서’는 Cust_T라는 어떤 데이터베이스의 테이블이고, ‘무엇을’은 쿼리에서 반환될 필드이름 (Cust_ID, Cust_Name_ VC, Cust_Alias_VC)으로 조회할 수 있는 데이터들이며 ‘어떻게’는 검색조건(Cust_ID = 1)에 만족하는 레코드라고 정의할 수 있다. 쿼리가 이와 같은 구조를 가지고 있기 때문에 프로그래머가 CData layer 객체에 쿼리를 입력하면 쿼리의 구조를 분석해 CDatalayer 객체 자신이 자동으로 쿼리에서 사용되는 필드들의 이름으로 CField 객체를 생성할 수 있다.

이러한 기능으로 얻을 수 있는 장점으로는 레코드셋 객체를 반드시 선언해서 결과 값을 반환받을 필요가 없다는 것이다(실제 레코드셋을 만들어서 결과를 반환받는 처리는 CDatalayer 객체가 수행을 하게 된다).

쿼리의 또 다른 문제 중에 하나가 쿼리를 사용자가 입력한 값에 따라 재작성하는 것이었는데, 이는 CDatalyaer 객체가 입력용 CField 객체의 값으로 쿼리를 다시 만들어서 실행하므로 재작성에 의한 오류를 줄일 수 있게 된다. MS SQL에서는 Declare라는 예약어를 이용해서 쿼리 내부에서 사용하는 변수를 선언하고 사용할 수 있는데, 이 기능을 이용해 구현한 것이다.

[예제 3] 일반적인 쿼리 작성
Select Cust_ID, Cust_Name_VC, Cust_Alias_VC
From Cust_T
Where Cust_ID = 100

[예제 4] Declare를 사용한 쿼리
Declare @CustID int
Set @CustID = 100
Select Cust_ID, Cust_Name_VC, Cust_Alias_VC
From Cust_T
Where Cust_ID = @CustID

[예제 3]은 일반적인 쿼리이고 [예제 4]는 Declare를 이용한 쿼리이다. [예제 3]에서 @CustID는 쿼리에서 사용되어질 변수이며 그 변수에 100을 넣어주고 Select문의 Where절에서 비교 값으로 사용하므로 [예제 3]과 [예제 4]는 동일한 결과를 반환하게 된다. [예제 3]을 프로그램으로 만들기 위해서는 [리스트 1]의 방법으로 코딩한다. 또한 [예제 4]의 쿼리를 데이터레이어를 이용해 만들기 위해서는 [리스트 2]와 같이 코딩한다.

[리스트 1] 일반적인 쿼리 작성 방법

[리스트 2] 데이터레이어를 이용한 쿼리 작성 방법

앞의 [리스트 2]에서 Init 프로시저가 실행되면서 mAddQuery 메쏘드를 이용해서 쿼리를 추가하면 그 내용을 dlCustomer 객체가 분석해 Declare문에 @CustID라는 이름의 입력용 CField 객체와 각 필드들의 이름을 가지는 출력용 CField 객체가 만들어진다. TestQuery 프로시저를 실행하면 사용자로부터 입력받은 값을 dlCustomer (“@CustID”).pValue 객체에 넣어 주고 mExecuteQuery 메쏘드를 사용하면 dlCustomer 객체는 “거래처 기본정보보기”라는 이름의 쿼리를 재작성한 후 실행하게 되는데, 이 때 dlCustomer(“@CustID”). pValue의 값을 사용한다.

ADO의 문제 해결방법
두 번째로 ADO의 문제 해결방법을 보면 데이터레이어는 기본적으로 결과 레코드셋을 반환한 후 바로 데이터베이스와의 연결을 끊어 서버의 부담을 덜어 주게 구성되어 있으며, 모든 레코드셋의 구성은 클라이언트 전진커서(adOpenForwardOnly)와 읽기전용(adLockRead Only)으로 만들도록 설계되어 있어 가장 빠른 결과의 반환을 받을 수 있다. 이는 C/S 환경에서 쿼리를 이용하지 않고 레코드셋을 이용한 레코드 수정(Insert, Update, Delete) 방법은 바람직한 방법이 아니기 때문이다.

데이터레이어를 사용하면 더 이상 결과 값을 반환하기 위해 레코드셋 객체를 만들지 않아도 된다. 이로 인해 레코드셋의 수를 줄일 수 있으며 더불어 데이터레이어 객체의 소멸만으로 내부에서 사용하던 모든 객체를 일괄 소멸해 주므로 효율적인 자원관리가 용이하다. 이로서 문제점에 대한 해결방법에 대해서 알아보았다. 이제부터 본격적으로 데이터레이어에 대한 세부적인 내용을 알아보도록 하겠는데, 가장 먼저 이야기하고 싶은 부분은 데이터레이어의 설계 배경에 대한 내용이다.

데이터레이어의 설계 배경
프로그래머가 프로그램 개발시에 비중을 두는 부분이 데이터베이스 구조, 쿼리 작성, 필드 구조, 인덱스 관리 등이다. 그러나 그러한 부분들은 하위 개념(하드웨어적인 개념)이며 진짜 비중을 두어야 하는 것은 여러 프로그램의 차이점인 데이터의 구성요소(육하원칙에 의거한)를 정의하는 것에 있다.

[그림 1] 데이터레이어의 적용 위치

데이터레이어는 하위 개념의 공통적인 부분을 처리해 주고 프로그램마다 서로 다른 차이점을 프로그래머가 쉽게 접근해 사용할 수 있도록 고안됐다. 다음의 [그림 1]과 같이 각 서비스와 사용자의 중간에 위치를 하게 된다.

데이터의 구성요소에 대해 잠시 살펴보면, 가령 ‘홍길동’이라는 데이터가 있다고 한다면 이 데이터에 대한 누가, 언제, 어디서, 무엇을, 어떻게, 왜라는 부분들에 대해 명시를 해준다면 ‘홍길동’이라는 데이터의 성격 및 의미를 정확하게 파악할 수 있게 된다. 즉, ‘홍길동’은 “프로그래머가/ 쿼리를 실행해/ 거래처 테이블의/ 거래처 명을/ 조건은 거래처명이란 필드의 값이 ‘홍길동’이라고 하는/ 화면에 출력하기 위한/”이라고 정의할 수 있으며, 이를 데이터의 구성 요소라고 보는 것이다.

좀 더 설명하면 데이터는 우리가 사용하는 시점에 컴퓨터 내부 기억장치 속에 들어가 있게 되고 그 기억장치의 주소를 변수 이름으로 찾아서 사용할 뿐 실제 데이터는 거래처 테이블의 몇 번째 레코드의 ‘거래처명’이라는 필드에서 가져온 값이라는 것이다.

[그림 2] 데이터레이어의 기본구조

데이터의 의미는 사실 누가 언제 어디서 무엇을 어떻게 왜 가지고 온 것인지가 더 중요한 것임을 생각해봐야 할 것이며, 이는 ‘홍길동’이라는 데이터가 데이터베이스가 아닌 전혀 다른 곳에 있는 데이터라면 그 단어는 전혀 다른 의미를 가지기 때문이다. 예를 들면 인터넷상의 어떤 사이트에서 어떤 폴더의 동화책이란 파일의 몇 번째 줄의 몇 번째 단어일 경우를 생각해 보라.

데이터레이어의 기본구조 및 설명
기본적인 설계 방향은 최대한 사용자가 쉽게 사용할 수 있도록 만드는 것이었다. 이는 사용자가 CDatalayer 객체에서 제공하는 프로퍼티와 메쏘드만을 이용하더라도 쉽게 원하는 결과를 얻을 수 있도록 하여 새로운 것을 배워야하는 부담을 줄여 많은 이들이 사용하도록 하기 위함이다.

◆ CDatalayers : CDatalayer 객체를 포함할 수 있는 Collection 객체
◆ CDatalayer : 가장 중요한 객체로서 데이터를 관리하기 위한 환경을 제공하며 데이터베이스와의 연결을 위한 프로퍼티, 쿼리를 입력받아 처리하기 위한 프로퍼티와 메쏘드, CField 객체를 위한 프로퍼티와 메쏘드, CRecordArray 객체를 위한 프로퍼티와 메쏘드, CRSS 객체를 위한 메쏘드와 이벤트 등을 포함하고 있고 프로그래머는 대부분 이 객체를 이용해 모든 처리를 할 수 있다.
◆ CFields : CField 객체를 포함할 수 있는 Collection 객체
◆ CField : 데이터를 보관하고 관리하는 객체이며, 사용자의 필요에 의해 생성 소멸이 가능하다. 사용자가 입력한 쿼리에 의해서 자동으로 생성된다.
◆ CValue : CField 객체 내부에 위치하며 데이터를 저장하는 객체
◆ CQuerys : CQuery 객체를 포함할 수 있는 Collection 객체이며 사용자가 직접 접근할 수 없다.
◆ CQuery : 사용자가 입력한 쿼리를 저장하고 있는 객체이며 사용자가 직접 접근할 수 없으나 CDatalayer에서 제공하는 CQuery 관련 메쏘드를 이용해 사용할 수 있다.
◆ CQueryStructure : 사용자가 입력한 쿼리의 구조를 해석하고 저장하고 있는 객체이며 사용자가 직접 접근할 수 없다.
◆ CRecordArray : 쿼리를 실행한 후 반환된 결과 레코드셋을 배열 형태로 저장하고 있는 객체이며 사용자가 직접 접근할 수 없으나 CDatalayer에서 제공하는 CRecordArray 관련 프로퍼티와 메쏘드를 이용해 사용할 수 있다.
◆ CRSS : RSS 형식의 XML 문서를 분석해 레코드셋 형태로 만들어주는 객체이며 사용자가 직접 접근할 수 없으나 CDatalayer에서 제공하는 CRSS 관련 메쏘드와 이벤트를 이용해 사용할 수 있다.
◆ CXML : 사용자가 입력한 주소에서 XML 문서를 불러오는 작업을 하는 객체이며 사용자가 직접 접근할 수 없다.
◆ CReadyStateChange : XML 문서의 내용을 가져오는 과정에서 사용되는 객체이며 사용자가 직접 접근할 수 없다.
◆ CWords : CWord 객체를 포함할 수 있는 Collection 객체
◆ CWord : 단어 데이터를 저장하는 객체로서 CDatalayer의 여러 구성 요소에 사용되어 지고 있으며 사용자가 직접 선언해 사용할 수 있는 객체이다.

공통적인 개발환경 구축을 위해
지금까지 데이터레이어에 대해 기본적인 사항을 알아봤다. 필자가 이야기했던 기존 프로그래밍 방식의 문제점에 대해 모든 이들이 공감하지 않을 수도 있고 그에 대한 나름대로의 해결 방법을 가지고 있을 것이라 생각한다. 그러나 프로그램 개발 단계에서 공통적인 무언가를 유지하려는 노력을 한다면 앞으로 좀 더 효율적인 개발환경이 이루어질 것이다.

데이터레이어를 이용해 프로그램을 개발하는 것이 모든 문제를 해결할 수 있는 것은 아니지만 이것으로 인해 일관된 개발환경 구축을 위한 시작이 됐으면 하는 바람이다. 아직까지 기능이나 여러 가지 면에서 부족한 부분이 있고 더 많이 발전해야 한다고 생각하기 때문에 많은 독자들의 관심과 조언을 통해 더 좋은 툴로 발전할 수 있기를 바란다.

다음 글에서는 거래처 위치정보 관리 프로그램 버전 1.5를 이용해 데이터레이어를 사용하는 실제 예를 살펴본다. 거래처 위치정보 관리 프로그램은 인터넷 포털 사이트에서 서비스하고 있는 지도검색 서비스를 이용해 검색된 지도를 거래처 데이터에 추가하고 거래처를 찾아가는 방법을 표시해 배송자가 쉽게 찾아갈 수 있도록 도와주는 프로그램으로, UI 설계 방법에 대한 방향 제시, 전체적인 설계, 데이터레이어를 이용한 데이터 처리 등의 내용을 이야기할 것이다. 데이터레이어에 대한 궁금한 점은 아이마소(www.imaso.co.kr) ‘필자에게 묻는다’와 본인의 클럽 게시판(club.nate.com/kakisoft)으로 문의하기 바란다. @

* 이 기사는 ZDNet Korea의 자매지인 마이크로소프트웨어에 게재된 내용입니다.
http://www.zdnet.co.kr/builder/dev/db/0,39031604,10068607,00.htm
-------------------------------------------------------------------------
데이터레이어 실전「거래처 위치정보 관리 SW」만들기
[데이터레이어를 이용한 DB 개발] ② 거래처 위치정보 관리 프로그래밍
박문찬 ( 마이크로소프트웨어 ) 2004/06/18
지난 호에서는 데이터레이어에 대한 기본적인 설명과 기존 프로그래밍 방식과의 차이점을 살펴봤다. 이번 호에서는 거래처 위치정보 관리 프로그램을 통해 데이터레이어의 실제 사용 방법에 대해 알아본다.
============================================================================================
데이터레이어를 이용한 DB 애플리케이션 개발
[데이터레이어를 이용한 DB 개발] ③ BLOB와 XML-RSS 다루기
박문찬 ( 마이크로소프트웨어 ) 2004/07/30
BLOB(Binary Large OBject)란 이진 대형 객체로 그래픽, 사운드, 컴파일된 코드와 같이 이진 형태의 데이터가 들어 있는 데이터 열 형식을 말한다. 프로그램을 개발하다 보면 BLOB 파일을 데이터베이스에 입력하고 조회하는 방법에 대해 다루게 되는데, 이번에 다루는 BLOB 파일의 기본적인 입출력 방법과 이런 작업을 데이터레이어에서는 어떻게 처리하는지 살펴보면 조금이나마 도움이 될 것이다.

BLOB 데이터를 DB에 입출력하기
데이터베이스 필드의 일반적인 크기의 한계는 255까지이나 필드에 이미지 파일, 사운드 파일 등의 큰 데이터를 저장해야 할 경우가 있다. 이때 필드의 종류를 nText나 Image 형태로 설정하고 데이터를 입출력하는 방법 중 ADO를 이용해 작업하는 방법은 AppendChunk 및 GetChunk 메쏘드를 사용하거나 스트림(stream) 객체를 이용하는 방법을 사용한다. AppendChunk와 GetChunk 메쏘드를 이용한 방법은 여러 곳에서 다루고 있으므로 생략하기로 하고 스트림 객체를 이용한 방법에 대해서만 살펴 본다.

스트림 객체는 ADO에서 독립적인 형태로 존재하며, 주로 계층 구조 형태의 저장 장치에서 데이터를 불러오거나 저장하는 역할을 수행하고, ADO 2.5 이상의 버전에서만 사용이 가능하다. 스트림 객체에 대한 자세한 사항은 MSDN을 참고하기 바란다.

<리스트 1> 스트림 객체를 이용한 이미지 저장법

<리스트 1>은 pub_info라는 테이블의 레코드셋을 구성하고 스트림 객체를 생성, 스트림 객체의 형식은 바이너리로 지정하고 Open 메쏘드로 활성화시킨 후 LoadFromFile 메쏘드를 이용해서 이미지 파일을 스트림 객체로 불러들인다. 불러들인 바이너리 데이터를 Read 메쏘드를 이용해서 pub_info테이블의 레코드셋의 첫 번째 레코드의 logo 필드에 입력하고, 마지막으로 Update문을 이용해서 데이터베이스에 저장한다. 이 방법은 AppendChunk를 이용한 방법에 비해 매우 단순한 것이다. 이번에는 데이터베이스에 저장되어 있는 이미지를 파일로 저장하는 방법에 대해 알아보자.

<리스트 2> DB에 저장된 이미지를 파일로 저장

<리스트 2>에서 스트림 객체의 Write 메쏘드를 사용해 레코드셋의 이미지를 입력받고, SaveToFile 메쏘드를 이용해 파일로 저장하고 있다. 이미지를 파일로 저장할 때 주의할 사항으로는 원본 이미지의 확장자를 저장해 주어서 파일로 다시 저장할 때 참고할 수 있어야 한다는 것이다.

이것으로 스트림 객체를 이용한 BLOB 파일의 입출력 방법을 간단하게 살펴봤다. 이제 거래처 위치관리 프로그램에서는 데이터레이어를 이용해서 어떻게 이미지를 입출력하고 있는지 알아보자.

<리스트 3> 거래처 폼에서 지도 추가하기

<리스트 3>을 보면 이미지 파일을 데이터베이스에 추가할 때 mFileAndDB 메쏘드를 사용한 것을 알 수 있다. mFileAndDB 메쏘드는 BLOB 파일을 데이터베이스에 입력하거나 데이터베이스에서 파일로 저장할 때 사용되는 메쏘드로 사용 방법은 아래 박스 기사를 참고하기 바란다.

mFileAndDB의 사용방법

형식 : mFileAndDB(eWhatHow As enmWhatAndHow, strFileName As String, strTableName As String, strFieldName As String, strWhere As String) As Long

eWhatHow : 어떤 것을 어떻게 처리할 지를 지정
strFileName : 사용되어질 파일 이름을 지정
strTableName : 데이터베이스의 입출력 테이블 이름을 지정
strFieldName : 데이터베이스의 입출력 필드 이름을 지정
strWhere : 데이터베이스에 입출력 레코드를 지정

enmWhatAndHow
WH_Binary2DB = 1 : 바이너리 파일을 데이터베이스에 저장
WH_DB2Binary = 2 : 데이터베이스의 내용을 바이너리 파일로 저장
WH_LongText2DB = 3 : 컨텍스트 파일을 데이터베이스에 저장
WH_DB2LongText = 4 : 데이터베이스의 내용을 컨텍스트 파일로 저장

반환형식 : Long형 ( -1이면 실패, 0이면 성공)

이렇게 mFileAndDB 메쏘드를 이용하면 손쉽게 BLOB 파일의 입출력을 처리할 수 있게 된다. <리스트 3>에서 저장 완료 후 ‘Picture1.Picture=LoadPicture(strFileName)’라고 사용한 것은 그림이 데이터베이스에는 저장됐지만 저장된 내용이 바로 화면에 보이는 것은 아니기 때문에 추가적으로 사용자에게 보여주기 위한 소스코드이다. 이제 저장된 이미지를 Picture 컨트롤에 보여주는 방법에 대해서 알아보자. 이미지를 보여주는 방법도 몇 가지가 있지만 필자는 Picture 컨트롤에 바인딩을 하는 방법을 사용한다.

<리스트 4> 레코드셋을 Picture 컨트롤에 표시하기

<리스트 4>에서와 같이 이미지 필드를 단순히 조회해서 Picture 컨트롤에 바인딩하는 것만으로 이미지가 표시되며 사용되었던 레코드셋은 바로 소멸시켜도 무관하다. <리스트 4>에서는 소스코드로 Picture 컨트롤에 바인딩을 하고 있으나 만약 폼에 데이터 컨트롤을 사용한다면 폼 디자인시에 바인딩을 할 수 있다. 지금까지 설명한 방법들을 사용하면 이미지를 쉽게 관리할 수 있을 것이라 생각한다.

데이터레이어와 데이터 컨트롤 사용하기
데이터레이어에서 서버의 데이터를 반환 받는 방법이 레코드셋을 반환 받지 않는 방법, 로컬 레코드셋으로 반환 받는 방법, 서버 레코드셋으로 반환받는 방법의 3가지라는 이야기를 지난 호에 했었다. 여기서 서버 레코드셋을 사용해야 하는 이유는 데이터 컨트롤에 바인딩을 하기 위해서이다. 데이터 컨트롤을 이용해 데이터를 표시하면 상당히 많은 양의 소스코드를 줄일 수 있는 장점이 있다.

<리스트 5> 거래처 전체정보 보기 프로시저

<리스트 5>는 사용자가 선택한 거래처의 모든 정보를 화면에 표시하는 프로시저인데 데이터 컨트롤과 바인딩이 되지 않는 shape 컨트롤을 제외하고 모든 컨트롤들이 데이터 컨트롤과 바인딩이 되어 있기 때문에 많은 양의 데이터라 하더라도 데이터를 표시하기 위한 별도의 소스코드가 포함되어 있지 않다.

이렇게 데이터를 조회하는 폼에서 소스코드를 단순화시키기 위해 데이터 컨트롤을 사용하는데, 이 데이터 컨트롤은 서버 레코드셋만을 바인딩할 수 있기 때문에 서버 레코드셋이 필요하게 된 것이다. 데이터 컨트롤을 사용해 데이터를 표시하면 데이터의 업데이트 시에도 효과적으로 소스를 작성할 수 있다.

<리스트 6> 거래처 전체정보 업데이트 프로시저

<리스트 6>은 각 컨트롤들의 데이터를 업데이트하기 위해 데이터레이어의 CField 객체에 입력하고 업데이트 쿼리를 실행시키는 프로시저이다. 하나의 폼에 많은 컨트롤들이 존재한다고 가정하고 각 컨트롤의 종류가 서로 다르며, 저장할 필드들의 이름이 모두 다르게 되면 업데이트 쿼리를 작성하는 소스가 무척 길어질 것이다.

하지만 <리스트 6>을 살펴보면 For Each~Next를 이용해 폼의 컨트롤들을 돌면서 우선 컨트롤의 이름으로 구분하고 다음에 DataField 프로퍼티의 값을 이용해 업데이트를 위해서 들어가야 할 정확한 위치에 입력해 주고 있다. 업데이트할 모든 데이터의 입력 작업이 끝나면 ‘거래처 전체정보 업데이트’란 쿼리를 실행해 한번에 처리한다. 이로써 거래처 위치관리 프로그램에서 데이터레이어를 사용한 부분은 모두 알아봤다.

XML & RSS

XML
1996년 W3C(World Wide Web Consortium)에서 제안했으며, 1997년부터 마이크로소프트와 넷스케이프 커뮤니케이션스가 XML(eXtensible Markup Language)을 지원하는 브라우저를 개발하고 있다. HTML과 XML은 같은 기술(SGML: 표준 마크업 언어)에서 나왔으며 HTML은 SGML의 일부만을 이용해 간단하고 쉽게 만들어진 반면, XML은 정보를 표현하기 위한 보편적인 방법으로 만들어졌다. XML은 HTML을 보완하기 위해 등장했고 표현방식과 데이터를 분리할 수 있으므로 프로그램에서 효과적인 처리가 가능해 전자상거래, 온라인 뱅킹 지원 분야 등에 적합하다.

RSS
RSS(Really Simple Sydication)는 뉴스, 블로그 등 자주 업데이트되는 성격의 사이트를 위한 XML 1.0 기반의 포맷으로 자료 교환을 위한 표준 규격이다. 현재 RSS 0.91, RSS 0.92, RSS 2.0의 규격이 사용되고 있다. 특히 국내의 많은 블로그 사이트들에서 XML-RSS 규격의 문서를 제공하고 있으며 이런 XML-RSS 문서를 구독하기 위한 전문 RSS 리더 프로그램도 많이 존재한다(참고 사이트 : http://blogs.law.harvard.edu/tech/rss)

XML과 RSS, 그리고 데이터레이어
이제부터는 XML-RSS에 대해 알아보자. XML-RSS는 XML로 작성된 RSS 규격의 문서를 의미한다.

<리스트 7> XML-RSS 문서 예

<리스트 7>이 XML-RSS 문서의 예로서 보기에는 복잡해 보이지만 상당히 규격화되어 있는 문서이다. 다만 국내의 모든 블로그 사이트들에서 완전히 동일한 형태의 문서를 제공하는 것이 아니기 때문에 RSS의 기본적인 형태에서 추가적인 여러 형태까지도 포함해줘야 RSS 리더기의 기능을 수행할 수 있는 프로그램을 만들 수 있다. 일단 이곳에서는 XML-RSS에 대해 자세히 다루지는 않고 데이터레이어에서 XML-RSS의 기능을 어떻게 사용하는지에 대해서만 설명하겠다. 더 많은 정보를 알고 싶은 사람들은 책을 구입해 공부하기를 바란다.

<그림 1> 데이터레이어에서 XML-RSS 문서를 처리하는 과정

<그림 1>은 데이터레이어에서 XML-RSS 문서를 ADO 레코드셋으로 변환하고 사용자가 원하는 정보를 제공하는 단계를 표현한 것이다. 웹 서버와의 통신은 비동기 방식이기 때문에 사용자에게 완료를 알려주는 방법으로 완료 이벤트를 발생시키고 있다. 그럼 실제 프로그램은 어떻게 작성되어야 하는지 알아보자.

데이터레이어의 이벤트를 사용하기 위해서는 폼 수준의 변수 선언시 WithEvents라는 예약어를 사용해 정의해야 한다.

◆ 선언 예) Dim WithEvents dlRSS as CDatalayer

그리고 초기화 프로시저에서 객체를 생성하고 사용할 수 있으며, 사용자가 데이터레이어에게 갱신을 요청하는 작업과 원하는 정보를 제공받는 부분은 아주 쉽게 만들어져 있다.

<리스트 8> 갱신 요청하기와 반환된 정보 조회 예

<리스트 8>은 데이터레이어에서 XML-RSS 문서의 반환을 요청하고 반환된 후에 어떻게 처리하는지를 간단하게 보여주는 예이다. 사용자가 특정 블로그에 XML-RSS 문서의 URL을 이용해서 XML-RSS 문서의 갱신을 요청할 때는 mExecuteRSSURL 메쏘드를 사용한다.

◆ mExecuteRSSURL의 사용방법
1. 설명 : mExecuteRSSURL - 입력된 URL에서 XML-RSS 문서의 반환을 요청
2. 형식 : mExecuteRSSURL(ByVal strRSSURL As String)
strRSSURL : XML-RSS문서가 존재하는 URL 값
3. 비고 : 이 메쏘드는 비동기 방식으로 결과의 반환 시점은 eCompleteLoadRSS 이벤트가 발생할 때이다.

웹 서버에서 XML-RSS 문서를 반환하면 데이터레이어가 필요한 처리를 하고 완료가 되면 사용자에게 eCompleteLoadRSS 이벤트를 발생시켜 정보를 조회할 수 있도록 해준다.

◆ eCompleteLoadRSS의 사용방법
1. 설명 : eCompleteLoadRSS - mExecuteRSSURL 메쏘드의 결과로 발생하는 이벤트로서 사용자가 입력한 URL에서 XML-RSS 문서에 대한 작업이 완료되면 발생함
2. 형식 : eCompleteLoadRSS(strRSSURL As String, lngError As Long)
strRSSURL : 이벤트를 발생시킨 URL
lngError : 에러 코드
1013 - 해당 URL에서 0개의 노드를 반환받았을 때이며 이는 사용자가 입력한 URL 주소가 XML-RSS의 주소가 아닐 수 있다.
1014 - 해당 URL을 요청한 후에 대기시간 초과 후에도 아무 것도 가져온 것이 없을 때이며 이는 서버측의 문제로 인해 지연됐을 경우 발생한다.

사용자는 데이터레이어로부터 eCompleteLoadRSS 이벤트를 받으면 이벤트 프로시저 내부에서 mGetRSS 메쏘드를 이용하거나 직접 접근해 반환된 정보를 조회할 수 있고 이를 프로그램에서 사용할 수 있다.

◆ mGetRSS의 사용방법
1. 설명 : mGetRSS : 사용자가 입력한 RSS URL에서 가져온 정보를 조회한다.
2. 형식 : mGetRSS(eWhatInfo As enmReturnRSSInfo) As Variant
enmReturnRSSInfo
RRI_XMLAttrib = 1 : XML 문서의 속성 값을 반환한다. 반환형식 : 문자열
RRI_RSSAttrib = 2 : RSS의 속성 값을 반환한다. 반환형식 : 문자열
RRI_RSTChannel = 3 : 채널의 정보를 반환한다. 반환형식 : 레코드셋
RRI_RSTElement = 4 : 채널의 아이템들을 반환한다. 반환형식 : 레코드셋
RRI_XMLDocument = 5 : XML-RSS 문서를 XMLDocument 객체로 반환한다. 반환형식 : XMLDocument 객체
RRI_RSSURL = 6 : 사용자가 입력한 URL을 반환한다. 반환형식 : 문자열
RRI_AllResponseHeader = 7 : 웹 서버로부터 반환된 헤더 문자열을 반환한다. 반환형식 : 문자열
3. 비고 : 사용자의 URL에서 가지고온 XML-RSS 문서의 정보는 CField 객체에 저장되어지고 있으므로 꼭 앞의 메쏘드를 사용해서 반환받을 필요는 없다.

데이터레이어가 많은 도움 됐길 바라며
지금까지 데이터레이어에서 BLOB 파일을 데이터베이스로 입출력하는 방법과 몇 가지 응용 방법, 그리고 XML-RSS 문서를 응용 프로그램에서 사용하는 방법을 설명했다. 이로써 데이터레이어를 이용해서 데이터베이스 응용 프로그램을 개발하는 방법을 모두 알아봤다.

처음에 말했듯이 데이터레이어가 기존 프로그램에서 발생할 수 있었던 여러 가지 문제를 해결하면서 좀 더 쉽게 개발할 수 있는 환경을 제공하는 라이브러리가 되어 많은 사람들에게 도움을 줄 수 있었으면 하는 바람이다. 필자는 데이터레이어를 사용해 꼬마 RSS 리더기를 만들었으며, 버전 0.9의 소스는 club.nate.com/kakisoft에 공개되어 있으니 참고해 더 좋은 RSS 리더 프로그램이 나오기를 바란다. @
데이터레이어는 비주얼 베이직을 이용해 데이터베이스 응용 프로그램을 만들 때 데이터의 관리를 쉽게 만들어 주는 액티브X 클래스 모듈이다. 사용자가 ADO(ActiveX Data Obejct)를 이용해 데이터를 조작할 때 일일이 설정하고 사용해야 하는 부분을 데이터레이어에 몇 가지 사항을 지정하면 그러한 처리를 대신 수행해 오류의 근본적인 원인을 줄여주는 것이 대표적인 특징이라 할 수 있다.

이번 호에서는 데이터레이어를 이용한 프로그램을 시작할 때 필수적으로 알고 있어야 하는 데이터레이어의 선언 방법, 기본적인 사용 방법, 쿼리를 이용해서 데이터의 입력, 출력, 조회 등의 처리를 어떻게 하는지를 설명할 것이다. 우선 데이터레이어를 적용하는데 있어 하나의 프로그램으로 등장하는 거래처 위치 관리 프로그램이 무엇인가부터 살펴보자.

거래처 위치 관리 프로그램이란?
거래처 위치 관리 프로그램은 다수의 거래처에 배송을 하는 회사에서 사용하면 유용한 프로그램이다. 일반적으로 거래처의 담당자만이 정확한 위치를 알고 있으나 부득이하게 다른 사람이 배송해야 하는 경우나 특정 지역의 거래처들의 위치를 보면서 배송 계획을 세우는 경우 등에 이용할 수 있다.

거래처 위치 관리 프로그램은 MS SQL 서버를 이용하도록 만들어져 있다. MS SQL 서버를 사용할 수 없는 경우에는 MSDE를 설치해 사용하면 된다. 필자는 프로그램을 개발할 때 전체적인 구성을 먼저 A3 용지에 그리고 대략적인 윤곽을 잡은 후 각 부분에 대해 다시 그림을 그려서 어느 정도 세분화가 되기 전까지는 코딩을 하지 않는다. 여기서도 프로그램을 이해하기 위해서 먼저 준비해야 할 전체적인 구성을 알아본 후 세부적으로 들어가 보자.

거래처 위치 관리 프로그램의 구성과 특징
프로그램의 전체 구성을 보면 맨 처음 데이터베이스에 로그인을 위한 로그인 폼이 표시되고, 로그인에 성공하면 메인 MDI 폼이 화면에 나타난다. 이후 메인 메뉴에 지역과 거래처가 나오고 지역을 누르면 지역 폼이, 거래처를 누르면 거래처 폼이 표시된다. 우선 각 구성요소의 특징을 살펴보자.

지역 폼은 범위가 넓은 지도를 이용해서 해당 지역에 어떤 거래처들이 있는지를 한눈에 파악하기 위한 용도이며, 거래처 폼은 특정 거래처를 찾아가기 위해 필요한 상세한 정보를 보기 위한 용도로 사용된다. 지역 폼은 해당 지역에 대한 정보를 입력·조회·삭제할 수 있어야 하며, 지역 명칭과 지역의 지도, 그리고 해당 지역에 어떤 거래처가 어디에 위치하는지를 표시하는 것이 목적이다. 그런데 어떤 지역에 어떤 거래처가 들어갈지는 알 수 없으므로 지역에 거래처를 연결시키는 것이 아니라 거래처에 지역을 연결시켜 주어야 한다.

거래처 폼에는 거래처의 기본 정보가 표시되며 많은 거래처를 효과적으로 찾기 위한 방법이 필요하다. 특히 거래처의 추가·삭제·수정도 포함되어야 한다. 거래처의 기본 정보는 거래처명, 별칭, 담당자명, 전화번호, 팩스번호, 주소, 지도, 찾아가기 포인트로 구성된다. 로그인 폼에는 서버의 이름, 사용자 아이디, 비밀번호를 입력하도록 구성되어 있다. 각 사용자 아이디마다 권한이 다르게 설정되어 있어서 일반 사용자가 함부로 수정하는 것을 방지한다(MSDE를 사용시 유저 아이디는 SetupMSDEforCustWhere.vbp 프로그램을 참고하고 이미 서버가 구축되어 있다면 데이터베이스를 연결 후 사용자 아이디를 추가하거나 권한을 변경해 사용하면 된다).

[그림 1] 거래처 위치 관리 프로그램의 구성

앞의 내용을 바탕으로 테이블을 설계하면, ‘지역 테이블 : 지역 ID, 지역명, 지역 지도’, ‘거래처 테이블 : 거래처 ID, 거래처명, 별칭, 담당자명, 전화번호, 팩스번호, 주소, 찾기 포인트 1~5까지의 사용 유무와 지도상의 위치 정보, 지역 ID, 지역 내에서의 위치 정보’, ‘거래처 지도 테이블 : 지도 ID, 거래처 지도, 거래처 ID’ 정도의 내용이 필요하다. 여기서 거래처 지도 테이블을 별도의 테이블로 구성한 이유는 여러 가지 형태를 만들기 위함이고 실제 서로 다른 성격의 데이터는 ‘지역’과 ‘거래처’ 두 가지로 볼 수 있다.

그러나 프로그램 전체에서 사용할 데이터까지 포함하면 세 가지의 데이터가 사용된다. CDatalayer 객체 하나에는 동일한 성격의 데이터를 모아서 사용하는 것이 좋으며, 내부적으로 유지하는 레코드 배열이 1개이므로 성격이 다른 레코드들을 여러 개 유지해야 하는 경우에는 CDatalayers 객체를 이용해서 CDatalayer 객체를 추가해 사용하면 된다.

우선 프로그램의 전체에서 사용할 데이터로는 거래처의 목록을 조회하는 쿼리와 데이터베이스 연결문자열을 저장하는 변수가 있다.

[리스트 1] 프로그램 전체에서 사용하는 내용들의 구성

[리스트 1]은 모듈, 로그인 폼, 메인 MDI 폼의 3곳에서 작성된 코드를 보여준다. 전역변수의 선언은 모듈에서 하고, 로그인 폼에서 객체를 생성, ‘연결문자열’이란 이름의 필드를 추가하고, 초기 값을 넣은 후 추가한 문자열을 dlPublic.pConnectionString에 넣고, 메인 MDI 폼에서 거래처 목록을 조회하는 쿼리를 전역 CDatalayer 객체에 추가한다(변수 선언과 사용에 대해 알고 있다면 꼭 이와 같은 방법을 사용하지 않아도 된다).

여기서 중요한 부분은 쿼리를 추가하면 CDatalayer 객체는 입력받은 쿼리를 분석해 해당 내용이 조회·삽입·수정·삭제 쿼리인지를 판단하고, 쿼리문에서 사용된 변수 이름이나 필드 이름을 이용해서 CField 객체를 생성하게 된다([그림 2] 참고).

[그림 2] dlPublic의 내부구조

이제 추가한 쿼리를 사용하는 방법에 대해 알아보자. ‘거래처목록’이란 쿼리에는 실행하기 전에 거래처 이름을 지정하도록 되어 있어 전체 목록을 조회하거나 일부 목록만을 조회할 수 있다([리스트 2] 참고).

[리스트 2] ‘거래처목록’ 쿼리를 실행하기

[리스트 2]에서 보듯이 동일한 쿼리를 서로 다른 폼에서 쉽게 사용하는 모습을 보여주고 있으며, 기존에 사용하던 방식과 비교해 보면 그 차이점을 알 수 있다. 또한 거래처 폼에서 사용한 방법을 보면 텍스트 박스에 사용자가 입력한 문자열이 존재하면 해당 문자열을 포함하는 거래처 목록을 반환하고, 입력된 문자열이 없으면 전체 거래처 목록을 반환하도록 ‘@Cust_VC’에 조건을 지정한 후 “거래처목록”이란 쿼리를 실행한다.

로컬 레코드셋은 데이터베이스 서버에서 레코드셋을 반환받은 후 로컬 컴퓨터에 저장하고 저장된 레코드셋을 다시 불러오는 과정을 거치게 된다. 일반적인 조회 쿼리의 결과로 반환된 레코드셋이 서버와 연결되어 있으면 서버의 부담을 가중시키므로 이와 같은 방법으로 처리해 서버의 부담을 최소화할 수 있다. 이 부분은 뒤에서 더 자세히 설명하도록 하겠다. 그럼 이제 지역 폼에서 사용된 소스 코드를 이용해 데이터레이어에 대해 살펴보자.

프로그램 소스를 작성하는 기본 방향
먼저 필자는 코딩을 할 때 몇 가지의 규칙을 가지고 있는데 그 중 한 가지는 컨트롤들의 이벤트 프로시저 내부에는 가급적 코딩을 하지 않는다는 것이다. 왜냐하면 첫째로 이벤트 프로시저 내부에 코딩한 내용을 다른 이벤트에서도 사용해야 할 경우가 발생했을 때 문제가 발생하기 때문이고, 둘째로 소스가 정렬되어 있는 것을 좋아하고 그래야 오류 수정을 하기 쉽기 때문이다. 이는 어떤 프로그램이든지 항상 레코드의 추가·삭제·수정·조회라는 사항은 필수적으로 따라 다니므로 이 부분의 소스를 정렬해 각 부분들의 처리를 한 눈에 파악하기 쉽도록 만들어 주면된다. 그럼 지역 폼의 소스 코드를 보면서 좀 더 깊이 있게 알아보자.

[리스트 3] 지역 폼에서 데이터레이어 사용을 위한 설정

[리스트 3]에서 지역 폼은 지역 데이터와 거래처 데이터라는 성격이 다른 두 개의 데이터를 필요로 하므로 CDatalayers 객체를 사용했다. 또한 폼 전체에서 사용하기 위해 ‘선택거래처코드’, ‘선택동그라미인덱스’, ‘동그라미총갯수’라는 이름의 CField 객체를 추가한다.

[리스트 4] 지역 테이블에 지역 레코드 추가

[리스트 4]는 지역 레코드 추가 쿼리를 ‘CDatalayer:지역’에 추가하는 코드로 IF문을 사용해 추가하려는 지역 이름이 존재하는 레코드가 있을 때는 추가하지 않고 -1을 반환하며, 이름이 없을 경우 레코드를 추가하고 추가한 레코드의 ID를 반환한다. 어떻게 보면 이런 쿼리는 저장 프로시저를 이용하는 것과 흡사하나 저장 프로시저를 이용해서 결과 값을 반환받기 위해서는 ADODB.Command 객체를 이용해야 하고 이로 인해 여러 저장 프로시저를 통합해서 사용하기가 어렵기 때문에 아주 복잡한 쿼리를 제외하고는 이와 같은 방법을 사용하는 것이 쉬운 방법이다.

쿼리에서 IF문을 사용할 경우 조건에 만족할 때 실행할 부분과 조건이 거짓일 때 실행할 부분을 모두 Begin~End 블럭으로 지정을 해줘야 한다. 이는 쿼리를 분석하는 과정에서 블럭에 대해서 인식해 쿼리를 분리하기 때문이다.

[그림 3] dlsArea의 내부구조

[그림 3]을 보면 CField 객체 세 개가 추가되어 있다. 그럼 이제 ‘지역추가’ 쿼리를 실행하는 방법을 보자.
[리스트 5]에서는 ‘지역추가’ 쿼리를 어떻게 사용하는지를 보여주고 있다. 지역 레코드를 추가하기 위해 ‘@Area_VC’에 사용자로부터 입력받은 지역 이름을 설정하고 mExecuteQuery 메쏘드로 ‘지역추가’ 쿼리를 실행하는데 이번에는 레코드셋을 반환받지 않는다. 레코드셋을 반환받지 않는 이유는 무엇이며, 결과를 어떻게 알 수 있을까?

[리스트 5] 지역추가 쿼리를 사용하는 방법

지난 호를 본 독자라면 알겠지만 기존 방법으로는 쿼리를 이용해서 데이터를 조회한다고 했을 때나 혹은 데이터 추가 쿼리를 전송 후 결과를 반환받을 때 반드시 레코드셋 형태이어야 했다. 하지만 데이터레이어를 이용하면 세 가지로 결과를 반환받을 수 있게 된다. 첫 번째는 레코드셋이 아닌 CField 객체로 받는 방법, 두 번째는 로컬 레코드셋 형태로 받는 방법, 세 번째가 기존에 사용하던 형태의 레코드셋이다.

[그림 4] 레코드셋을 반환하지 않는 쿼리의 처리

첫 번째 방법은 반환되는 필드 수가 적을 경우에 사용하면 좋다. 지금 같은 경우 반환 값은 ‘Result’ 하나뿐이므로 이 방법을 이용했다. 두 번째 방법은 반환되는 필드수가 많고 그리드 컨트롤과 같은 바인딩을 할 수 있는 컨트롤에 연결시키기 위해서 사용되고, 세 번째 방법은 데이터 컨트롤에 바인딩할 때 사용한다.

[그림 3]에서 ‘@Area_VC’는 추가할 지역 이름을 설정하는 곳이고, 추가 여부는 ‘Result’를 조회하면 알 수 있다. [그림 4]를 보면 처리과정이 나와 있다. [리스트 5]의 Select문에서 dlsArea(“지역”).pFields(“Result”).pValue의 값을 조회해서 레코드 추가의 성공 여부를 판단하고 있다. [그림 3]의 ‘@Result’는 쿼리 내부에서만 사용되므로 사용하지 않는다. 레코드를 추가하는 쿼리 작성과 실행 방법에 대해 알아보았다.

[리스트 6] 지역 테이블에서 지역 레코드 삭제

이번에는 레코드를 삭제하는 방법에 대해 설명하겠다. [리스트 4]와 [리스트 6]에 나오는 쿼리는 구성이 비슷하다. 하나의 IF문으로 조건에 만족할 때 수행하고 거짓일 때 수행하는 부분이 나누어지며, 조건은 ‘@Area_ID’의 값으로 레코드를 찾아보는 것이다. 그럼 이제는 dlsArea(“지역”)의 내부 구성이 어떻게 되리라는 것을 알 수 있을 것이라 생각된다.

그런데, 왜 Declare문 아래 Set문이 계속 들어갈까? 그 이유는 사용자가 입력한 값을 이용해서 쿼리를 재구성할 때 Set문을 바꾸어서 사용하기 때문인데, Declare문을 이용한 쿼리에서는 반드시 Declare문을 종료한 후 Set문을 이용해서 선언된 모든 변수에 아무 값이라도 넣어 주어야 한다. 쿼리를 실행한 후 pLastExecuteQuery 프로퍼티를 출력해보면 쉽게 알 수 있다.

또 다른 궁금증이 생기는 부분도 있을 것이다. 이미 dlsArea(“지역”)이란 CDatalayer 객체에는 ‘Result’란 CField 객체가 존재하는데 똑같은 이름이 들어가도 괜찮은가란 점이다. 결론은 ‘문제가 없다’이다. 왜냐하면 자신이 ‘지역추가’쿼리를 실행한 후에 ‘Result’를 조회하면 ‘지역추가’ 쿼리의 결과를 가지고 있고, ‘지역삭제’ 쿼리를 실행한 후에 ‘Result’를 조회하면 ‘지역삭제’ 쿼리의 결과를 가지기 때문으로, 즉 1개의 CField 객체를 여러 개의 쿼리에서 중첩해 사용할 수 있다. 단 쿼리를 사용하다 더 이상 필요가 없어서 제거하게 되면 해당 쿼리에서 사용하던 모든 CField 객체를 같이 제거하므로 제거시에는 주의해야 한다. 사용자가 마지막으로 실행한 쿼리의 이름은 pLastExecuteQueryName 프로퍼티를 조회하면 알 수 있다. 이번에는 수정 쿼리들에 대해 알아보자.

[리스트 7] 거래처 정보 수정

[리스트 7]은 ‘지역거래처’란 CDatalayer 객체에 ‘거래처정보수정’이란 쿼리를 추가하는 부분이다. 약간 복잡한 듯 보이지만 [리스트 4], [리스트 6]과 별반 다르지 않다.

[리스트 8] 거래처 정보 수정 쿼리 사용

[리스트 8]은 추가한 ‘거래처정보수정’ 쿼리를 실행하는 부분이다. 그런데 어딘가 약간 다르다고 생각할지도 모르겠다. dlsArea(“지역거래처”).pFields(“@Area_ID”).pValue라고 사용하는 것과 앞에서 사용한 dlsArea(“지역거래처”)(“@Area_ID”).pValue는 동일한 의미란 것과, 선택한 거래처에 여러 필드를 수정해야 하는 경우에도 충분히 사용할 수 있다는 것을 이야기하기 위한 소스이다. 이제 데이터레이어의 다른 기능을 활용하는 방법을 알아보도록 하자.

[리스트 9] 콤보 컨트롤에 리스트 만들기

[리스트 9]는 CRecordArray를 이용한 콤보 박스에 내용을 채우는 방법에 대해 보여주고 있다.

CRecordArray는 쿼리를 실행한 후 반환된 결과 레코드셋을 배열 형태로 저장하고 있는 객체이며, 사용자가 직접 접근할 수 없으나 CDatalayer에서 제공하는 CRecordArray 관련 프로퍼티와 메쏘드를 이용해 사용할 수 있다. 즉, 데이터베이스로부터 여러 레코드를 반환하는 쿼리를 실행시 레코드셋을 반환하지 않았다면 처음 레코드셋의 내용은 해당 CField 객체에 있겠지만 다음 레코드의 내용은 어떻게 조회할 수 있는가? 이 문제를 해결해 주는 것이 바로 CRecordArray 객체이다. CRecordArray 객체는 CData layer 객체 내부에 존재하면서 반환된 레코드셋의 모든 내용을 배열 형태로 보관하고 있으며, 마치 ADODB.Recordset을 사용하는 것과 비슷한 방법으로 조회할 수 있다.

[리스트 9]에서 사용된 CRecordArray 관련 프로퍼티와 메쏘드를 살펴보면 우선 pEOR이 있는데 pEOR은 배열의 마지막을 부울형으로 돌려주며, mMove는 배열에서의 현재 위치를 이동하는데 사용된다.

데이터레이어를 이용한 프로그래밍의 차이점
이번 강좌에서는 지역 폼의 소스 코드를 이용해서 데이터레이어의 기본인 쿼리 추가 방법, 쿼리를 추가한 후의 CDatalayer 객체 내부의 변화된 모습, 추가한 쿼리를 실행하는 방법, CRecordArray에 대해 알아보았다. 이제는 기존 프로그래밍 방식과 데이터레이어를 이용해 프로그래밍하는 것이 어떻게 다른지를 약간이나마 알 수 있는 기회가 되었을 것이다.

다음 강좌에서는 바이너리 파일의 입출력 방법에 대한 이해와 구현 방법, 데이터레이어에서 바이너리 파일을 다루는 방법, 데이터레이어를 응용해 데이터의 입출력 및 조회를 쉽게 하는 방법, XML-RSS 기능을 이용해 여러 블로그 게시판에서 제공하는 XML-RSS 파일을 가지고 오는 방법을 살펴 본다. @

* 이 기사는 ZDNet Korea의 자매지인 마이크로소프트웨어에 게재된 내용입니다.



바보들의 영문법 카페(클릭!!)

오늘의 메모....

시사평론-정론직필 다음 카페
http://cafe.daum.net/sisa-1

바보들의 영문법 다음 카페
http://cafe.daum.net/babo-edu/

티스토리 내 블로그
http://earthly.tistory.com/

내 블로그에 있는 모든 글들과 자료에 대한 펌과 링크는 무제한 허용됩니다.
(단, 내 블로그에 덧글쓰기가 차단된 자들에게는 펌, 트랙백, 핑백 등이 일체 허용되지 않음.)

그리고 내 블로그 최근글 목록을 제목별로 보시려면....
바로 아래에 있는 이전글 목록의 최근달을 클릭하시면 됩니다.
그러면 제목을 보고 편하게 글을 골라 보실 수 있습니다.

그리고 내 블로그내 글을 검색하시려면 아래 검색버튼을 이용하시면 됩니다.


가가챗창

flag_Visitors

free counters