본문 바로가기

IT 살이/04. 기술 - 프로그래밍

ClickOnce 어플리케이션의 파일 관리(Ⅲ) - 데이터 파일(i)

1.1 데이터 파일 관리

앞에서는 어플리케이션을 구성하는 파일중에서 데이터 파일을 제외한 일반 구성 파일들의 배포와 관리에 대해서 알아봤습니다. 이제부터는 “게시 상태”를 “데이터 파일”로 설정한 파일들의 배포와 관리에 대해서 알아봅니다.

ClickOnce 어플리케이션을 작성하다 보면 XML 파일 또는 MS 액세스 DB 파일(.mdb)같은 파일을 각 클라이언트로 배포할 필요도 생기게 됩니다. ClickOnce 어플리케이션이 클라이언트 머신에 설치되면 각 버전마다의 데이터 디렉토리(Data Directory)도 사용자 프로파일 디렉토리 하위에 함께 생성됩니다. 어플리케이션 구성 파일 속성 편집창에서 “데이터 파일”로 설정된 파일은 어플리케이션을 설치할 때 모두 데이터 디렉토리로 복사합니다. SQL Express 파일(.ldf, .mdf), Access 파일(.mdb), SQL Compact 파일(.sdf)그리고 XML 파일(.xml) 확장자를 갖는 파일은 Visual Studio는 기본적으로 데이터 파일로 설정합니다. 그러나 데이터 파일로 설정하는 것은 어떤 종류의 파일도 가능합니다.

1.1.1 데이터 파일 배포 결과

다음처럼 두개의 파일에 대해 “게시 상태” 속성을 “데이터 파일”로 설정했다고 해 보겠습니다. 각각의 파일은 “리소스\비트맵”과 “리소스\아이콘”의 하위 디렉토리에 포함되어 있습니다.

1234415029

그림  데이터 파일 설정

이렇게 설정된 어플리케이션을 클라이언트 머신에 설치하면 다음 그림처럼 계층 구조를 그대로 유지한채로 데이터 디렉토리 하위로 배포가 됩니다.

1104249060

그림  데이터 파일 계층 구조 배포

“데이터”로 설정하지 않은 파일은 어플리케이션 디렉토리(application directory)에 포함되는데 앞에서도 알아봤지만 완전 신뢰냐 부분 신뢰의 어플리케이션이냐에 따라서 동일한 API가 다른 값을 반환할 수도 있습니다. 그러나 데이터 디렉토리는 어플리케이션 전용 디렉토리로서 완전 신뢰든 부분 신뢰든 상관없이 프로그램상에서도 동일한 API를 사용해서 자유롭게 파일 관리를 할 수 있습니다.

1.1.2 데이터 파일 관리

앞에서 본 것처럼 데이터 파일도 계층구조를 그대로 유지하면서 클라이언트 머신에 설치되기 때문에, 파일에 접근하기 위해서 데이터 디렉토리를 기준으로 한 상대경로값을 이용하면 개발시의 코드를 그대로 유지해서 사용할 수 있습니다 : 데이터 디렉토리 + “\리소스\비트맵\Bitmap1.bmp”와 같은 형식이 됩니다. 이때 데이터 디렉토리 값을 구하기 위해서 ApplicationDeployment.DataDirectory 속성을 사용할 수 있습니다. DataDirectory 속성이야 말로 ClickOnce 어플리케이션에서의 데이터 파일 관리의 시작점입니다.

그러나 역시 이런 방법은 어플리케이션이 ClickOnce로 인스톨된 경우에는 이용할 수 있다는 것입니다. 어플리케이션을 개발할때는 이 형식을 그대로 사용할 수 없습니다. 개발때에는 우선 해당 파일을 빌드 출력 파일로 복사시켜야 하고 그 다음 다른 형식의 접근 경로가 필요합니다. 빌드시 해당 파일들을 출력 경로로 복사시켜주기 위해서는 파일들에 대한 “출력 디렉토리 복사”속성 값을 “항상 복사” 또는 “변경된 내용만 복사”로 선택해야 합니다. 이때 파일이 복사될때도 그 계층 구조는 프로젝트에서 구성한 그대로 유지됩니다.

그런 다음 코드상에서는 ApplicationDeployment 클래스의 IsNetworkDeployed 속성을 이용해서 현재 어플리케이션이 ClickOnce로 배포된 어플리케이션인지 아니면 개발시 디버그 모드에서 실행하는지를 구분합니다. 만약 ClickOnce로 배포된 어플리케이션의 경우라면 앞에서처럼 데이터 디렉토리를 이용한 경로를 이용하고 그렇지 않다면 데이터 디렉토리 대신에 어플리케이션 디렉토리를 이용해서 경로를 구성합니다.

코드  데이터 파일 접근 경로 결정

private void Form1_Load(object sender, EventArgs e)

{

string dataPath = string.Empty;

// ClickOnce로 배포된 어플리케이션인지 확인합니다.

if (ApplicationDeployment.IsNetworkDeployed)

{

// 데이터 디렉토리 조회

dataPath = ApplicationDeployment.CurrentDeployment.DataDirectory;

}

else

{

// 어플리케이션 디렉토리 조회

dataPath = AppDomain.CurrentDomain.BaseDirectory;

}

// 데이터 파일에 대한 전체 경로

dataPath = Path.Combine(dataPath, @"리소스\비트맵\Bitmap1.bmp");

// 파일을 Bitmap으로 읽어오기

Bitmap b = new Bitmap(dataPath);

pictureBox1.Image = b;

}

파일에 대한 경로가 완전히 구성되면, FileStream 또는 앞의 코드처럼Bitmap 클래스를 이용해서 저장된 파일을 읽어와서 원하는대로 이용하면 됩니다.

데이터 디렉토리를 이용해서 ClickOnce 어플리케이션에서 데이터 파일을 읽고 쓰기 위해서는 어플리케이션에 파일 시스템에 대한 읽기, 쓰기 권한이 있어야 합니다. 만약 완전 신뢰의 어플리케이션으로 배포한 경우는 자동으로 이런 권한을 갖게 됩니다.

1.1.3 데이터 파일의 업데이트 과정

데이터 파일(“게시 상태”를 “데이터 파일”로 설정한 파일)은 그 파일에 대한 업데이트 과정이 일반 어플리케이션 구성 파일과는 조금 다릅니다. 이해를 돕기 위해서 앞에서 설명한 일반 어플리케이션 업데이트 과정을 간략히 요약해보도록 하겠습니다.

ClickOnce 어플리케이션이 클라이언트에 설치되어 있는 상태에서 새로운 업데이트 버전이 다운로드하게 되면 일단 새로운 버전의 파일들이 캐싱될 폴더가 생성됩니다. 서버측에 업데이트된 버전의 파일과 클라이언트에 캐싱되어 있는 이전 버전의 파일들이 비교됩니다. 그래서 변경되거나 새로 추가된 파일만 새로운 버전의 폴더로 다운로드받습니다. 그리고 나서 변경되지 않은 파일은 이전 버전의 폴더에서 새로운 버전의 폴더로 로컬 복사가 일어납니다. 그러나 만약 클라이언트측의 이전 버전에 캐싱되어 있는 파일중에서 변경된 파일이 있다면 로컬 복사가 일어나는 것이 아니라 해당 파일은 서버측에서 다운로드받게 됩니다. 이것은 일반 어플리케이션 파일은 클라이언트측에서 변경되면 외부로부터의 강제 수정이 이뤄졌다는 것으로 보는 것입니다.

조금만 생각해 보면 데이터 파일은 일반 어플리케이션 파일과는 업데이트 과정이 다를 것이라고 예상할 수 있습니다. 데이터 파일은 당연히 클라이언트측에서 수정될 일이 많을 것이기 때문에 변경되었다고 해서 서버측 버전을 다시 다운로드해서 덮어써 버리면 안될 것이기 때문입니다. 정확히 어떤 상황인지를 알아봅니다.

1.0.0.0버전의 어플리케이션과 함께 게시되는 데이터 파일 MyData.xml의 “게시 상태”를 “데이터 파일”로 설정했다고 가정해 보겠습니다. 이 XML 파일은 클라이언트로 배포되면 데이터 디렉토리로 저장되고 사용자가 어플리케이션을 통해서 로딩해서 편집 작업을 한 후 다시 데이터 디렉토리로 저장하는 파일입니다.

그런 다음 어느 순간 어플리케이션의 버그를 수정하기 위해서 새로운 업데이트 버전 2.0.0.0의 어플리케이션을 게시합니다. 그러나 이 버전에 포함된 XML 파일의 데이터는 여전히 변경되지 않은 최초 파일입니다.

클라이언트로 업데이트 버전의 어플리케이션이 다운로드되면 사용자가 수정한 MyData.xml 파일은 일반 어플리케이션 파일처럼 새로운 버전 2.0.0.0의 데이터 디렉토리로 복사됩니다. 그런 다음 서버측의 MyData.xml 파일은 다운로드되지 않습니다. 이제 사용자가 버전 2.0.0.0을 시작하면 1.0.0.0에서 작업했던 수정된 데이터가 보이게 됩니다.

이처럼 서버측의 데이터 파일이 수정되지 않은 한 업데이트가 일어날때마다 클라이언트의 데이터 파일은 새로운 버전의 데이터 디렉토리로 복사되어서 사용자로 하여금 연속적인 작업을 할 수 있게 됩니다.

그러나 서버측에 게시된 데이터 파일도 변경되면 어떻게 될까요? 예를 들어 XML 파일의 스키마를 약간 변경하거나 초기 데이터를 변경할 수도 있을 것입니다. 이런 경우 게시자가 의도적으로 서버측 파일을 변경하였으므로 서버측 버전을 새로운 버전의 데이터 디렉토리로 복사해야 할까요? 아니면 클라이언트에서 사용자가 작업을 내용을 보존하기위해서 클라이언트측의 이전 데이터 파일을 새로운 폴더로 복사해야 할까요?

클라이언트측의 버전 1.0.0.0의 데이터 디렉토리에 사용자가 수정한 데이터 파일 MyData.xml 파일이 있고, 서버측에는 새로운 버전 2.0.0.0의 어플리케이션에 수정된 MyData.xml이 “데이터 파일”로 포함되어 있다고 해 보겠습니다. 업데이트 버전의 어플리케이션이 클라이언트로 다운로드되면 다음과 같은 일이 일어납니다.

1. 이전 버전 1.0.0.0의 데이터 디렉토리에 있는 수정된 MyData.xml 파일은 새로운 버전 2.0.0.0의 데이터 디렉토리 하위에 있는 \.pre 폴더로 복사가 됩니다.

2. 버전 2.0.0.0에 있던 데이터 파일 MyData.xml 파일은 새로운 데이터 디렉토리로 다운로드됩니다.

1078602263

그림 데이터 파일 업데이트 과정

어플리케이션에서 특별한 조치를 취하지 않으면 버전 2.0.0.0에서는 이전 버전의 데이터 파일을 무시하고 새롭게 다운로드 한 2.0.0.0의 데이터 파일을 사용하게 됩니다.

이전 버전의 폴더 \.pre에 있는 데이터 파일도 코드상에서 접근할 수 있습니다. 따라서 이전 버전의 데이터 파일에 담긴 데이터를 계속해서 유지하고 싶다면 이런 식의 업데이트가 일어나는 경우에 실행될 수 있는 데이터 병합 프로그램 코드를 작성해야 합니다.

만약 .\pre 폴더에 있는 이전 버전의 데이터를 새로운 버전의 데이터 파일과 적절히 병합하지 않은 상태에서 또 다른 업데이트가 일어난다면 \.pre에 있는 데이터 파일은 사실상 유실된 데이터라 할 수 있습니다. 따라서 새로운 버전의 어플리케이션이 실행되자마자 데이터 병합을 하지 않으면 사용자가 편집한 데이터는 영원히 잃게 된다고 생각해야 합니다.