본문 바로가기

.NET Framework/C# 2.0 Quick Look

[ConfigurationManager] 01:ConfigurationManager 소개

 회차
 01. ConfigurationManager - Overview of ConfigurationManager Class

 02. ConfigurationManager - Practical use of ConnectionString to encrypt

01| ConfigurationManager 소개
대부분의 어플리케이션들은 DB 연결 문자열부터 복잡한 설정 정보까지 여러 Configuration 정보를 필요로 합니다.  가끔 " 은성님은 Configuration 정보를 어떻게 관리 하시나요? " 라고 질문 하시는분이 계셔서 " Configuration 정보들은 어플리케이션의 요구사항에 따라 여러 방법으로 사용하고 있습니다 " 라고 답변을 드렸던 기억이 나네요. 그럼 일반적인 구성 정보들을 어떻게 관리를 할까요?

대부분의 개발자 분들은 다음과 같이 구성파일로 부터 어플리케이션을 개발 하지 않을까 생각이 듭니다.

Configuration 유형
 - xml files
 - windows ini files
 - database
 - code Embedded configuration
 - etc

위와 같은 방법으로 Configratuion 정보를 저장하며 관리를 하게 됩니다.
이번 포스팅을 통해 소개드릴 내용은 .NET 개발자라면 *.config라는 형식의 애플리케이션 구성 파일에 대해서 아시겠지만 .NET에 입문하시는 분 혹은 아직 모르시는 개발자분들을 위해 도움이 되고자 회차로 구성 해보았습니다.

아시는 개발자분들은 너무 서운해 하지 마세요^^ 그래서 팁에 대해서 소개드릴까 합니다.
3회차에 소개될
'  Practical use of ConnectionString to encrypt ' 포스팅의 주요 내용은
ConnectionString 정보를 암호화에 대해서 소개를 드릴 예정입니다.


머.. 뒷북이라면 당신은 대략 “지못미!!”

.NET에서는 *.config라는 형식의 애플리케이션 구성 파일(configuration file)을 둘 수 있다는 것은 대부분의 개발자분들이 알고 계시는 방법입니다. 예를 들어 애플리케이션이 winform1.exe이라는 화일명이라면 config 파일은 winform1.exe.config의 형태로 구성이 됩니다. ASP.NET 애플리케이션의 경우에는 예외적으로 web.config 라는 이름을 가지게 됩니다.

이러한 구성 정보를 관리를 하기 위한 이유는 Configuration 정보를 읽는 것 뿐만 아니라 쓰는 기능도 중요하게 고려해야 합니다. 만약 코드인 상태라면 그 설정 정보를 변경할때 재빌드를 해야한다는 단점이 있습니다.
설정파일과 프로그램 파일을 암호화 하지 않고 분리를 한다면 보안적 측면에서 위험하지 않을까요?

구성 정보는 읽기 읽고 쓰는 기능뿐만 아니라 보안 측면과 Integrity, 어플리케이션 성능에 대한 부분도 역시 고려되어야 합니다. 그러나 이러한 이슈에 너무 몰두하면 어플리케이션 개발 기능 자체가 늦어지거나 소홀 해지기 마련입니다.

runtime 1.x에서 지원이 되던 ConfigurationSettings클래스와 runtime 2.0이상 ConfigurationManager를 지원하는 두 클래스를 비교를 해보겠습니다.

우선 구성 파일 코드를 한번 보시죠^^

* [코드1-1] Runtime 1.x 구성파일 정보

<?xml version="1.0"?>
<configuration>
       <appSettings>
             <add key="Northwind" 
                     value="server=(local);database=northwind;Integrated Security=SSPI" />
         </appSettings>
         ...(중략)
</configuration>


* [코드1-2] Runtime 2.0 이상 구성 파일 정보

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
       <connectionStrings>
              <add name="Northwind"
                      connectionString="server=(local);database=northwind;Integrated Security=SSPI;" 
                      providerName="System.Data.SqlClient" />
       </connectionStrings>
</configuration>


코드 1-1의 경우 <appSettings>라는 섹션 내에 add 엘리먼트 타입으로 선언하게 되며 런타임 1.x 에서 사용값을 가져오기 위해서는 ConfigurationSettings.AppSettings나 AppSettingsReader 클래스를 사용 해야 했습니다.

* [코드2] Runtime 1.x 구성 정보 가져오기

string connectionString = ConfigurationSettings.AppSettings["Northwind"].Value;


DB만 읽는 문제라면 큰 문제점은 없었지만 여러 단점들이 존재를 하였습니다.

ConfigurationSettings와 ConfigurationManager클래스의 차이
 1. runtime 1.x에서는 코드[1-2]runtime2.0 구성처럼 관련된 속성들을 묶어서 처리하기 위해 section
    handler를 작성하고  <configSections/sectionGroup> 내부에 등록을 해야하는 번거로움
 2. runtime 1.x에서 configuration 파일에 대해 접근을 제공하는 클래스들은 모두 읽기 전용이였으며 
     config 파일의 내용을 프로그래밍적으로 변경을 할 수가 없어 당시 개발자분들은 XMLDocument에 관련
     된 클래스를 사용하여 직접적으로 xml을 처리하거나 register, ini 형태로 처리를 해야 했었습니다.
 3. WebForm인 ASP.NET과 WinForm인 윈도우 어플리케이션에서도 확연한 차이가 존재를 하였습니다.
     ASP.NET의 경우 configuration 내용이 변경이되면 구동되고 있는 프로젝트가 restart를 하게 되지만
     반면에 Winform의 경우 즉시 변경을 할수가 없었습니다. 2번 항목에서 소개드린것처럼 제공하는 클래스
     들은 모두 읽기 전용만 가능 했기 때문에 configuration 정보를 반영하기위해서 어플리케이션을 restart
     하기엔 번그러웠습니다. 이를 해결하기 위해서 file, register, database에 접근하여 새롭게 읽어 온다는
     건 성능 상 바람직하지 못합니다.
  

그렇다면 NET 2.0부터는 어떻게 달라 졌나요?
configuration 파일에 appSettings 및 connectionString과 같은 섹션을 추가하게 되었고 runtime1.0에서 사용던 ConfigurationSettings 클래스 대신 ConfigurationManager을 사용을 권장하고 있습니다.
ConfigurationManager도 또한 읽기 전용 작업으로 수행을 하고 구성의 캐시된 단일 인스턴스를 사용하며 다중 스레드를 인식합니다. 무엇보다 config 파일을 좀더 자유롭게 다루기 위해 ConfigurationManager 클래스가 탄생 하였고 하위 구성파일도 호환을 위해서 유지 됩니다.

ConfigurationManager의 특징
 1. AppSetting 및 ConnectionStrings 속성을 통해 <appSettings>,<connectionStrings>의 섹션을 바로
    접근을 할 수 있습니다. [아래 코드3 참조]
 2. 구성 파일의 섹션을 액세스 하기 위해서 GetSection() 메소드를 호출 합니다. 또한 다른 컴퓨터에 대한 
     모든 수준의 구성 설정을 로컬 또는 원격으로 읽고 쓸수 있으며 제공되는 메서드는 읽기 또는 쓰기 작업
     을 수행하고 파일이 쓰여질 때마다 구성 데이터를 만듭니다.
 3. 다양한 구성 작업을 지원합니다.(MSDN Library를 참조하세요)
     SectionInformation, PropertyInformation, PropertyInformationCollection, ElementInformation,
     ContextInformation, ConfigurationSectionGroup, ConfigurationSectionGroupCollection
 4. RefreshSection메소드(코드4 참조)를 사용하여 해당 섹션만을 파일에서 다시 읽어오도록 할 수
     있습니다. 뿐만 아니라 configuration 파일의 내용을 업데이트 할 수 있습니다.
     즉, configuration 정보들은 읽기 전용이므로 add 속성으로 쓰기를 할수가 없습니다.
     다만 (코드5 참조) 수정이 되는 요소들은 xxx.config 나 web.config가 아닌 machine.config이며 수정
     대상의 구분이 필요하지요. ConfigurationManager클래스에서는 machine.config을 수정할 수 있도
     록  OpenXXXXConfiguration(OpenExeConfiguration, OpenMachineConfiguration, 
     OpenMappedExeConfiguration, OpenMappedMachineConfiguration) 메소드들을 제공합니다.

* [코드3] Runtime 2.0 구성 정보 가져오기

* connectionStrings 세션의 경우
string connectionStr = ConfigurationManager.ConnectionString["Northwind"].ConnectionString
string connectionStr2 = ConfigurationManager.ConnectionString["Northwind"].ToString()

* appSettings 세션의 경우

string connectionStr3 = ConfigurationSettings.AppSettings["Northwind"].Value;


* [코드4] RefreshSection 메소드를 이용한 appSettings 세션의 다시 읽기

ConfigurationManager.RefreshSection("appSettings");


* [코드5] Config 정보 변경 및 RefreshSection를 이용한 세션 다시 읽기

using System.Configuration.Configuration;

string conStr = "server=(local);database=northwind;Integrated Security=SSPI;";
Configuration config = 
             ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
//ConnectionString Add
config.ConnectionStrings.ConnectionStrings.Add(new ConnectionStringSettings("conStr", conStr));
// Save the configuration file.
config.Save(ConfigurationSaveMode.Modified);
// Force a reload of the changed section.
ConfigurationManager.RefreshSection("connectionStrings");


위 코드는 .config 파일의 connectionStrings 섹션 내에 "conStr" 요소가 존재한다면 Connection String 값을 업데이터를 하게 되고 그렇지 않으면 새롭게 요소를 만들어 추가하게 되고 Save 메소드를 통해 변경 사항을 저장한뒤 RefreshSection을 호출을 하게 되어 connectionStrings 섹션에 한해서 변경된 내용을 새롭게 읽어 오게 됩니다.

포스팅을 마치며...


이번 포스팅는 ConfigurationManager 클래스 소개에 대해서 알아 보았습니다. ^^
너무 뒷북치는 내용과 지루 하지 않으셨는지 모르겠습니다ㅜ_ㅜ
좀더 유용한 예제로 소개 드려서 도움이 되었어야했는데.. 아쉽네요 ^^;  

아무쪼록 항상 즐거운 하루 되세요 ^^

정은성 드림