. 프로젝트 레코드

비슷비슷한 여러 종류의 프로그램을 분석해보면 모든 면에서 다 좋은 프로그램은 무척 드물고 각각 장단점을 가지고 있다. 편집기들도 어떤 기능은 아주 기본적인 수준이거나 아니면 상대적으로 떨어지는 기능이 있는 반면 다른 편집기와 확실하게 구분되는 자기만의 장기를 하나씩은 가지고 있다. 솔직히 당근의 모든 기능은 대체로 기본 이상의 성능을 제공하지 못하고 겨우 기능을 제공하는 정도에만 그치고 있지만 그래도 다른 편집기에 비해 상대적으로 강한 기능이 하나 있는데 바로 여기서 만들 프로젝트 기능이다.

프로젝트란 간단히 말해 관련 있는 파일들의 집합이라고 할 수 있다. 웹 사이트를 하나 만들고 있다면 수많은 HTML 파일과 DB 스크립트, ASP PHP 스크립트, 작업 계획서 등이 여러 폴더에 흩어져 존재하게 되는데 이런 파일들의 목록을 프로젝트로 작성해놓으면 파일을 관리하기가 한결 편리해진다. 비주얼 스튜디오의 솔루션(6.0에서는 워크 스페이스)이 프로젝트의 대표적인 예인데 하나의 모듈을 만드는데 필요한 CPP, H, RC, 각종 리소스들을 하나의 이름으로 묶어 놓아 관리하기 편리하다.

프로젝트 파일은 소속 파일의 목록을 가지는 정보 파일이며 프로젝트에 대한 정보 및 소속 파일의 이름과 경로가 저장된다. 비주얼 스튜디오의 sln 파일(6.0에서는 dsw파일)이 프로젝트 파일의 예이다. 당근의 프로젝트 파일은 확장자 DGP(DanGeun Project)를 가진다. 단순히 소속 파일의 정보가 나열되어 있는 간단한 구조가 아니며 프로젝트 내에서 나름대로의 계층을 구성하는데 우선 그 포맷부터 설계해보자. 프로젝트는 하나의 헤더와 복수 개의 레코드로 구성되는데 일단 다음 두 구조체를 Dangeun.cpp에 선언하자.

 

enum {DGP_SUB=1, DGP_FILE, DGP_FOLDER};

 

struct ProjectHeader

{

     TCHAR Text[64];

     int Ver;

     TCHAR Name[32];

     TCHAR Desc[128];

     BOOL bAbsolute;

};

 

struct ProjectRecord

{

     int Parent;

     BYTE Type;

     TCHAR Path[400];

};

 

ProjectHeader에는 프로젝트 전반에 걸친 간단한 정보가 들어가며 프로젝트 하나당 하나씩의 헤더를 가진다. Text는 프로젝트 파일임을 알리는 안내문을 넣는데 이는 다른 텍스트 편집기로 프로젝트 파일을 열었을 때 어떤 종류의 파일인지 알리기 위해 필요하다. 프로젝트 파일은 이진 포맷으로 되어 있으므로 앞쪽에 별도의 설명 텍스트를 작성하였다.

Ver은 프로젝트 파일의 버전이며 100으로 초기화된다. 이 버전은 프로젝트 파일의 구조를 설명하기 위해 붙이는 것이므로 당근의 버전과는 굳이 일치시킬 필요가 없다. 당근이 1.2 1.5로 업그레이드되더라도 프로젝트의 포맷이 바뀌지 않으면 이 버전은 여전히 1.0으로 유지된다. 만약 당근 2.0에서 프로젝트 기능이 보강되어 포맷이 바뀐다면 그때 프로젝트 파일의 버전이 올라갈 것이며 이 포맷은 당근 1.0에서 읽지 못할 것이다. 하위 호환성을 유지하지 못할 정도로 포맷이 바뀔 때 하위 버전에서 에러 처리를 제대로 하기 위해 버전 정보가 반드시 필요하다.

Name은 프로젝트의 이름인데 기억하기 쉬운 임의의 이름을 붙일 수 있다. 이 이름은 프로젝트간의 구분을 위해 사용되며 프로젝트를 대표하는 이름이 된다. Desc는 단순한 설명에 불과하며 별다른 기능은 없다. 마지막 멤버인 bAbsolute는 다소 설명이 필요한데 소속 파일의 경로를 어떻게 기억할 것인가를 지정하는 프로젝트 옵션값이다. 이 값이 TRUE이면 소속 파일의 경로를 절대경로로 저장하고 FALSE이면 가능한 한 프로젝트 파일의 위치를 기준으로 한 상대경로로 저장한다.

절대경로로 저장시 프로젝트 파일을 어디로 옮기든지 소속 파일을 계속 참조할 수 있다. 반면 소속 파일의 위치가 바뀌면 프로젝트가 기억하고 있는 절대경로로는 더 이상 파일을 참조할 수 없게 된다. 상대경로로 저장시 프로젝트와 그 하위 폴더의 파일들이 같이 움직여도 참조 가능하다는 장점이 있는 반면 모든 파일의 경로가 프로젝트 파일이 있는 위치를 기준으로 하므로 프로젝트 파일만 단독으로 움직일 수 없다는 단점이 있다.

한 프로젝트를 구성하는 파일들은 보통 하나의 프로젝트 루트 아래에 모여 있는 경우가 많고 소속 파일들의 상대적인 위치가 변하는 경우는 거의 없다. 반면 프로젝트 루트 폴더를 통째로 다른 위치로 옮기는 경우는 종종 있다. 그래서 여러 모로 볼 때 상대경로로 저장하는 것이 유리하며 bAbsolute 옵션의 디폴트값은 FALSE이다.

ProjectRecord 구조체는 소속 파일 하나의 정보를 가진다. 프로젝트내의 소속 파일들은 파일 시스템처럼 계층 관계를 이룰 수 있는데 하위 묶음을 만들고 이 묶음안에 관련된 파일을 둘 수 있다. 하위 묶음이라는 개념은 파일 시스템의 폴더와 동일한 개념이며 하위 묶음 안에 파일이나 또 다른 하위 묶음이 포함될 수 있다. 계층의 깊이에는 제한이 없으므로 하위 묶음을 무한대까지 만들 수 있다.

Parent는 이런 계층 구조에서 레코드의 위치를 지정하는데 -1이면 루트 바로 아래에 있는 것이고 0이상이면 이 번호가 가리키는 레코드의 하위 묶음에 소속된다. Type은 레코드의 종류를 나타내는데 1이면 하위 묶음, 2이면 파일, 3이면 폴더 링크이다. 마지막 멤버인 Path는 소속 파일의 경로인데 FTP, HTTP 파일도 포함될 수 있으므로 길이를 좀 길게 잡았다. 프로젝트 레코드의 예를 들어 보자.

나의 텍스트라는 프로젝트에 여섯 개의 레코드가 있는데 두 개의 하위 묶음과 세 개의 파일이 포함되어 있다. 할일 목록.txt는 루트 바로 아래에 있는 파일이므로 Parent -1이며 Type 2이다. 편지일기는 루트 바로 아래의 하위 묶음이므로 Parent -1이고 Type 1이다. 개똥이에게.txt 1번 하위 묶음인 편지에 소속되어 있으므로 Parent 1번을 가리키고 있다. 이런 식으로 레코드 배열로 입체적인 트리를 표현하는데 이 기법은 데이터 베이스에서도 흔히 사용되는 방법이다.

폴더 링크라는 개념은 윈도우즈의 바로가기(ShortCut) 개념과 유사하다. 프로젝트는 폴더의 경로에 대한 정보만 가지고 있으며 이 폴더를 열면 실제 파일 시스템의 폴더에서 파일과 서브폴더의 목록을 가져온다. 프로젝트를 구성하는 요소들이 한 폴더에 있다면 폴더의 파일들을 프로젝트에 포함시키는 것보다는 폴더의 링크를 포함시키는 것이 더 좋다.