FileCube 버전 0.0.4 (커스텀 레코드셋으로 구현한 정렬 기능)

등록일시: 2003-09-15 12:28,  수정일시: 2018-04-07 23:30
조회수: 16,448
본문은 최초 작성 이후, 약 21년 이상 지난 문서입니다. 일부 내용은 최근의 현실과 맞지 않거나 동떨어져 있을 수 있으며 문서 내용에 오류가 존재할 수도 있습니다. 또한 본문을 작성하던 당시 필자의 의견과 현재의 의견에 많은 차이가 존재할 수도 있습니다. 이 점, 참고하시기 바랍니다.

목차

FileCube 버전 0.0.4 개요

이미 FileCube 버전 0.0.6a가 공개된 지금 뒤늦게 버전 0.0.4에 대한 문서를 제공하는 것이 다소 어색하기는 하지만, 반드시 한 번은 소개하고 싶은 내용이 있어서 본문을 준비하게 됐다. 바로 커스텀 레코드셋에 관한 내용이 그것으로, 그 강력함은 간단히 말로 설명할 수 없을 정도다. 비록 본문에서는 FileCube에 사용된 커스텀 레코드셋의 간단한 활용 사례를 소개하는데 그치겠지만 한 번쯤 관심을 갖고 커스텀 레코드셋에 관해서 자세히 알아보는 기회를 갖기를 강력하게 권장한다.

먼저 FileCube 버전 0.0.4와 버전 0.0.3의 차이점을 간단하게 살펴본 뒤에 커스텀 레코드셋에 관한 나머지 내용들을 살펴보도록 하자. 이 두 버전간의 차이점이라고는 본문의 주제인 커스텀 레코드셋으로 구현된 정렬 기능이 추가됐다는 점 외에는 없다. 따라서, 이 정렬 기능과 관련된 내용 외에는 설치 방법과 기술적인 구현 방법까지도 완전히 동일하므로, 이와 관련된 여러 가지 제반 사항들에 대해서는 FileCube 버전 0.0.3에 관해서 설명하고 있는 필자의 기존 글을 참고하기 바란다.

본 사이트에서 현재 서비스 중인 FileCube의 버전이 다름아닌 버전 0.0.4인데, 개인적인 홈페이지 관리 정책에 따라 파일 업로드 등의 기능들을 그리 필요로 하지 않기 때문에 굳이 버전 0.0.6a로 업그레이드하지 않고 있다. 단지 파일 다운로드 기능만 제공해주기 위해서라면 굳이 버전 0.0.6a를 설치할 필요는 없다. 일반적인 상업용 프로그램들처럼 버전 업그레이드에 구애받을 필요는 없는 것이다.

FileCube_ASP_0.0.4.zip (48k)

아래의 FileCube 0.0.4 살펴보기 링크나 좌측 메뉴의 FileCube 링크를 클릭해보면 현재 서비스 중인 FileCube 0.0.4 버전을 살펴볼 수 있으며, 참고로 최신 버전인 FileCube 버전 0.0.6a의 테스트용 미리보기 페이지는 여기에서 접근 가능하다. 그러나, 버전 0.0.6a 미리보기 페이지는 전적으로 테스트만을 위한 것으로 관리상의 이유로 종종 모든 데이터를 초기화하는 경우가 있으므로 이 곳에 중요한 파일을 올려놓는 일은 없기를 바란다.

노트: 본 사이트가 ASP.NET MVC 기반으로 이행된 2013년 말 이후부터 더 이상 ASP 기반의 FileCube는 서비스되지 않고 있으므로 유의하기 바란다. FileCube 역시 ASP.NET MVC 기반으로 이행 중인 상태로 소스 공개 여부는 아직 확정되지 않았다. 참고로, ASP 기반의 마지막 FileCube 버전은 0.0.7 Prepare SP1이며 여기에서 다운로드 가능하다.

FileCube 버전 0.0.4 적용 기술

커스텀 레코드셋으로 구현한 정렬 기능

프로그래밍 작업을 하다보면 데이터 집합을 화면에 표시하기 전에, 먼저 정렬 작업을 수행해야 하는 경우를 상당히 자주 접하게 된다. 그러나, 사실 ASP 프로그래밍 작업의 대부분이 데이터베이스로부터 필요한 데이터를 조회하는 경우이므로, SQL 문을 적절히 사용해서 손쉽게 해결이 가능하고, 따라서 평소에 정렬에 관해서는 그다지 신경 쓰지 않는 것이 보통이다.

그러나, 어떤 상황에서는 SQL 문을 이용할 수도 없고, 그렇다고 달리 특별한 방법을 찾을 수도 없는 경우가 종종 있는데, FileCube 같은 경우가 그 대표적인 사례라고 말할 수 있다. 본문을 읽고 계시는 분들은 대부분 FileCube의 구조에 대해서 잘 알고 계시겠지만, FileCube는 지정된 폴더 하위에 존재하는 모든 하위 폴더들의 구조와 각각의 폴더에 위치한 파일들의 정보를 읽어서 윈도우즈 파일 탐색기와 비슷한 구조로 웹 브라우저에 출력해준다. 이 얘기가 잘 이해되지 않는 분들은 일반적인 윈도우즈 파일 탐색기의 모습을 떠올려보거나 본 사이트에서 서비스되고 있는 FileCube를 직접 살펴보기 바란다. 이처럼 FileCube는 폴더들의 구조를 트리 형태로 보여주는 좌측 패널과, 그 좌측 패널에서 사용자가 선택한 폴더의 하위 폴더들과 파일들의 목록을 보여주는 우측 패널, 이렇게 두 가지 부분으로 구성되는데, 우측 패널의 경우 FileSystemObject 개체를 사용해서 얻은 하위 폴더들과 파일들의 목록을 어떻게 정렬할 것인지가 문제가 된다.

일단 하위 폴더들의 목록을 얻어오는 작업은 전혀 문제가 되지 않는다. 그러나, FileSystemObject 개체는 정렬을 지원하지 않으므로 ASP 개발자가 직접 정렬 작업을 처리하는 코드를 작성해야 한다. 파일들의 정보를 조회하는 작업 역시 마찮가지다. 즉, 정보 자체를 조회하는 작업은 전혀 문제가 되지 않지만, 조회한 정보들을 정렬하는 기능이 FileSystemObject 개체에서 지원되지 않기 때문에 모든 것을 개발자가 직접 처리해야만 한다.

그리고, 한 가지 더 중요한 문제는 이런 상황에서 ASP 프로그래머가 처리해야만 하는 작업은 단순히 하나의 항목에 대해서만 정렬을 하면 끝나는 것이 아니라, 데이터 집합 전체에 대해서 한 번에 모든 정렬이 이뤄져야만 한다는 점이다. 즉, 파일들의 정보 집합을 예로 들어보면 파일명 하나만 정렬을 하면 끝나는 것이 아니라, 파일 크기, 파일 종류, 바뀐 날짜 등도 같이 연계되어 정렬돼야만 한다. 다시 말해서, 한 항목을 기준으로 정렬을 하면 연계된 다른 항목들도 그 기준에 의해서 동일하게 정렬되어야 하는 것이다.

이런 경우, 어떤 방법을 사용해서 정렬을 구현하는 것이 가장 효과적일까? 이런 상황에서 필자가 개인적으로 강력하게 추천하는 방법이 바로 커스텀 레코드셋을 사용하는 방법이다. 물론, 일반적인 배열에 각각의 항목들을 담아서, 또는 Dictionary 개체 등을 사용해서 ASP 프로그래머가 직접 정렬 처리 코드를 작성할 수도 있을 것이다. 그러나, 조금만 생각해보면 이런 방법들은 몇 가지 심각한 문제점을 갖고 있다는 것을 쉽게 깨달을 수 있다.

먼저, 코드 자체가 어려워질 뿐더러 차후에 유지보수가 상당히 힘들어진다. 즉, 새로운 컬럼이 추가되거나 기존 컬럼이 제거되는 경우 프로그래머가 일일이 코드를 수정해야만 하는데, 일반적으로 성능뿐만 아니라 유지보수의 용이성이나 코드의 간결성 또는 추후에 이뤄질 인수인계 등의 문제들을 고려해야만 하는 ASP 프로그래밍 환경에서는 결코 바람직한 일이 아니다. 무엇보다도 쉽고 강력한 방법이 있는데 굳이 어려운 방법을 사용하는 것은 학습을 위해서가 아니라면 실제 기업 환경에서는 그다지 의미를 찾을 수 없는 일인 것이다.

그리고, ASP 프로그래머에게 있어서 레코드셋보다 더 친숙한 개체는 좀처럼 찾아보기 힘들다는 사실도 커스텀 레코드셋의 사용을 권하는 가장 큰 이유 중 하나다. 직업적인 ASP 프로그래머분들 가운데 ADO 레코드셋을 다룰 수 없는 분을 과연 얼마나 찾을수 있을지 의문이다.

커스텀 레코드셋에 관한 추천 도서: 커스텀 레코드셋뿐만 아니라 ADO에 관해서 더 자세히 알고 싶은 분들께는 정보문화사에서 출판된 빨간색 표지로 유명한 Worx사의 Professional ADO 2.5 RDS Programming with ASP 3.0의 일독을 권한다. 감히 단언컨데 아직까지 이 책을 읽어보지 않은 분이시라면 이 책을 다 읽고나면 ADO를 바라보는 시각 자체가 틀려질 것이다.

비록 출판된지 조금 시간이 지나서 ADO 2.5 버전에 대해서 다루고 있기는 하지만, ADO의 보다 깊은 개념을 파악하기에 전혀 부족함이 없고, 국내에서 원서와 번역본 모두 쉽게 구할 수 있다. 어떤 형태로든지 ADO와의 관계를 벗어날 수 없는 ASP 프로그래머라면 반드시 한 번은 읽어봐야 할 서적이다.

커스텀 레코드셋을 가장 쉽게 이해하는 방법 중 하나는 커스텀 레코드셋을 초강력 배열이라고 생각하는 것이다. 즉, 다양한 메서드가 지원되는 강력한 2차원 배열 정도로 생각하면 된다. 이를테면, C/C++의 배열은 그야말로 순수한 배열로 더 이상 부가적인 기능이 지원되고 말고를 생각할 여지 자체가 없는 반면, 커스텀 레코드셋은 ASP 프로그래머에게는 너무나 익숙한 BOF나 EOF 등의 기초적인 프로퍼티부터 다양한 메서드들, 가령 MoveFirst() 메서드나 MoveLast() 메서드 또는 MoveNext() 메서드 등의 무수히 많은 유용한 메서드들이 지원되는 2차원 배열인 셈이다.

또한, 레코드셋의 내용을 배열로 리턴해주는 GetRows() 메서드나 스트링으로 리턴해주는 GetString() 메서드, 그리고 Stream이나 XML 파일 등으로 저장하는 기능을 지원해주는 Save() 메서드 등의 존재를 머리 속에 떠올려보면 이것이 얼마나 강력한 장점인지 쉽게 깨달을 수 있을 것이다. 단적으로 말해서 본문에서 살펴보려는 정렬 기능조차도 Sort 프로퍼티를 통해서 아주 간단하게 해결된다. 그러면, 먼저 커스텀 레코드셋을 어떻게 만드는지부터 알아보도록 하겠다. 참고로 지금부터 제시되는 코드들은 모두 FileCube에서 실제로 사용되고 있는 코드들이다.

커스텀 레코드셋 개체가 만들어지는 과정은 일반적인 경우와 크게 다르지 않다. 다만, Open() 메서드를 사용해서 SQL 쿼리나 저장 프로시저를 호출하는 등의 경우에는 리턴되는 데이터의 구조와 형식에 맞게 자동으로 레코드셋의 필드 갯수와 데이터 형식 등이 설정되고 데이터까지 입력된 뒤에 레코드셋 개체가 리턴되는 반면, 커스텀 레코드셋에서는 이 모든 과정을 ASP 프로그래머가 수작업으로 처리해줘야 한다는 점이 다를 뿐이다. 먼저 다음 코드와 같이 언제나처럼 레코드셋 개체를 생성한다.

  Set objRecorset = Server.CreateObject("ADODB.RecordSet")

레코드셋 개체를 생성하는 방법에는 특별한 점이 없다. 그러나, 그 다음 과정부터 뭔가 조금씩 달라지기 시작한다. 먼저, CursorLocation 프로퍼티의 값을 3(adUseClient)으로, 즉 클라이언트측 커서로 설정해준다.

  objRecorset.CursorLocation = 3

그 이유는 어찌보면 매우 당연한데 커스텀 레코드셋은 데이터를 데이터베이스로부터 가져오는 것이 아니라 수작업으로 채워주는 것이므로 연결할 데이터베이스 서버가 없기 때문이다. 따라서, 서버 측 커서를 사용하고 싶어도 제공되는 서버가 없으므로 불가능하고 클라이언트 측 커서를 사용할 수 밖에 없는 것이다.

이제 작업할 대상 레코드셋이 준비되었다. 그런데, 알고 있는 것처럼 아직까지 이 레코드셋에는 필드가 하나도 준비되지 않은 상태다. 다시 말해서 완벽하게 텅빈 상태나 마찬가진데 이는 비단 데이터뿐만 아니라 필드가 몇 개나 있는지, 각각의 필드는 어떤 데이터 형을 사용하는지, 문자열 형식인 경우 그 길이는 얼마나 되는지 등과 같은 아주 기본적인 정보까지도 일체 설정되지 않은 상태인 것이다. 따라서, 다음 과정은 당연히 이런 정보들을 설정해주는 작업이 된다.

  With objRecorset
      .Fields.Append "rsName",     200, 256   '** Folder 나 File 의 이름
      .Fields.Append "rsSize",     200, 24    '** Folder 나 File 의 형식화된 크기
      .Fields.Append "rsRealSize", 3,   4     '** Folder 나 File 의 크기
      .Fields.Append "rsType",     200, 256   '** Folder 나 File 의 종류
      .Fields.Append "rsDate",     200, 256   '** Folder 나 File 의 최종 편집 일자
      .Fields.Append "rsPath",     200, 1024  '** Folder 나 File 의 경로
      .Fields.Append "rsCase",     200, 8     '** Folder / File 구분값 설정
      .Fields.Append "rsExtn",     200, 32    '** Folder 나 File 의 형식화된 종류
      .Open
  End With

레코드셋에서 사용되는 모든 필드들의 정보는 Field 개체의 컬렉션인 Fields 컬렉션에 저장되며, 이 레코드셋의 Fields 컬렉션은 텅 비어있는 상태이다. 따라서, 이 컬렉션에 사용하고자 하는 필드들의 정보를 채워줘야 한다. 가령, 위의 코드에서 볼 수 있듯이 FileCube에서는 모두 8개의 필드를 설정해서 사용하고 있음을 알 수 있다. 각각의 필드 정보는 Fields 컬렉션에서 제공되는 Append() 메서드로 추가할 수 있으며 이 메서드는 다음과 같은 형식을 가지고 있다. (ADO 2.8 기준)

  objFields.Append 필드명, 데이터형, 데이터 크기, 필드 속성, 기본값

여기서 첫 번째 인자는 추가하려는 필드의 필드명으로 일반적으로 데이터베이스에 테이블을 만들 때 사용하는 컬럼명과 같은 요령으로 설정하면 된다. 두 번째 인자는 해당 필드의 데이터형으로 MS SQL Server에서 사용하는 데이터형과 같은 데이터형이 아니므로 혹시 오해하지 않도록 한다. 이 샘플 코드에서는 한 개의 정수형 필드(3, adInteger)와 일곱 개의 가변 길이 문자열형 필드(200, adVarChar)가 설정되고 있음을 알 수 있다. 이 두 번째 인자에 사용할 수 있는 모든 열거형 상수들의 목록은 MSDN이나 다음 페이지 링크를 참고하기 바란다.

다음으로 세 번째 인자는 필드의 길이를 뜻하며 해당 필드의 사용 목적에 따라 적절한 값을 설정해주면 되는데, 생략도 가능하고 생략한 경우에는 두 번째 인자에서 설정된 테이터형에 의해서 기본값이 결정된다. 네 번째 인자는 해당 필드에 널(NULL) 값을 허용할 것인지 말 것인지 등을 의미하는 필드의 속성을 설정하는데 사용되고, 역시 생략 가능하며 이 인자도 생략한 경우 그 기본값이 두 번째 인자에서 설정된 테이터형에 의해서 결정된다. 이 네 번째 인자에 사용할 수 있는 모든 열거형 상수들의 목록은 역시 MSDN이나 다음 페이지 링크를 참고하면 된다.

마지막으로 다섯 번째 인자는 해당 필드의 기본값을 설정하는데 사용되며 생략되는 경우 널(NULL) 값이 입력된다. 따라서, 이 샘플 코드에서 가장 첫 번째로 추가된 필드의 경우, 필드명이 rsName이고 가변 길이 문자열형 필드며, 그 길이는 256이라는 사실을 파악할 수 있다.

이런 요령으로 필요한 필드들을 모두 설정했으면 Open() 메서드를 호출해서 레코드셋을 사용 가능한 상태로 활성화시킨다. 이 과정까지 끝내고 나면 이제 이 레코드셋은 마치 일반적인 SQL 쿼리나 저장 프로시저를 사용해서 얻어냈으나 조건을 만족하는 데이터가 하나도 존재하지 않는 레코드셋과 거의 마찬가지인 상태가 된다. 즉, 현재 입력된 데이터가 하나도 없으므로 BOF면서 EOF인 상태가 되는 것이다.

이제 다음으로 수행해야할 작업은 당연하게도 데이터를 채워 넣는 것이다. 데이터를 채워 넣는 작업은 이미 대부분의 ASP 프로그래머들이 익히 알고 있는 AddNew() 메서드와 Update() 메서드를 이용하면 간단하게 해결된다. 다음은 FileCube에서 해당 작업을 처리하기 위한 코드로 폴더의 정보를 입력하는 부분이다.

  '************************************************************
  '* 하위 폴더들의 정보를 얻고 사용자 정의 레코드셋에 추가한다.
  '************************************************************
  
  Set objSubFolders = objFolder.SubFolders
  With objRecorset
  For Each objTempFolder In objSubFolders
      .AddNew
      .Fields("rsName")     = objTempFolder.Name
      .Fields("rsSize")     = objFileCubeUtil.CalcSize(CSng(objTempFolder.Size))
      .Fields("rsRealSize") = objTempFolder.Size
      .Fields("rsType")     = "파일 폴더"
      .Fields("rsDate")     = CStr(objTempFolder.DateLastModified)
      .Fields("rsPath")     = objTempFolder.Path
      .Fields("rsCase")     = "FOLDER"
      .Fields("rsExtn")     = ""
      .Update
  Next
  End With
  Set objSubFolders = Nothing

먼저 AddNew() 메서드를 호출해서 빈 레코드를 하나 추가한다. 그런 다음에 각각의 필드에 알맞은 값들을 넣어주면 되는데, 이 예제 코드를 살펴보면 폴더명, 폴더 크기, 마지막으로 수정한 날짜, 경로 등의 정보가 저장되는 것을 알 수 있다. 필요한 정보를 입력했으면 Update() 메서드를 호출해서 변경된 사항을 반영한다. 이런 방법을 반복해서 필요한 정보를 입력하고 나면 이제 모든 준비가 끝난 셈이다.

단순히 SQL 문이나 저장 프로시저를 호출해서 데이터를 얻어왔던 기존의 방법에 비하면, 복잡하고 번거러우며 어려워 보이기까지 하는 과정을 거친 후에야 비로소 쓸만한 데이터를 얻은 셈이다. 그렇다면 이제 이런 수고에 대한 보상을 얻을 시간이 됐다. 현재 우리의 관심 사항인 데이터 집합의 정렬 작업이 얼마나 간단하게 처리되는지 다음 코드를 살펴보기 바란다.

  objRecordset.Sort = "rsCase DESC, rsName ASC"

단지 이 한 줄로 모든 정렬 작업이 끝난다. 지금까지 정렬 작업에 대해서 고민해왔던 것이 허탈할 정도로 간단하게 모든 작업이 끝난 것이다. 이 샘플 코드에서는 먼저 rsCase 필드에 대해서 역방향으로 정렬을 한 후, rsName 필드에 대해서 정방향으로 정렬하고 있다. 만약, 정렬 작업을 취소하고 싶다면 Sort 프로퍼티에 공백 문자열을 설정하면 간단하게 처리된다.

이제 남은 일이라고는 MoveFirst() 메서드나 MoveNext() 메서드 등을 적당하게 호출하면서 필요한 데이터를 호출해주는 일 뿐이다. 참고로 이 Sort 프로퍼티를 설정한다고 해서 실제로 데이터 자체가 이동하는 것은 아니고, 단지 데이터에 대한 접근만 정렬된 순서대로 이뤄지는 것 뿐이다.