Creative Commons License

Microsoft .NET

닷넷!시작하기
닷넷! Ver 2.0~
닷넷!스킬업
웹개발
윈폼개발
실용모듈개발
Tip & Tech
하루 한 문법

Microsoft .NET 개발자들을 위한 공간입니다. 기초강의에서 부터 고급 기술 정보 및 팁등을 다루도록 하겠습니다.

.

닷넷!스킬업

닷넷 기술을 조금 더 깊이 다루고자 합니다. 특정 주제를 정하지 않고 이슈 발생 시 마다 체계적으로 정리하여 공유하겠습니다. 이전 자료를 옮겨온 곳이기도 합니다.

리소스(Resource)

작성자 : 박종명
최초 작성일 : 2008-05-26 (월요일)
최종 수정일 : 2008-05-26 (월요일)
조회 수 : 4283

[1] 정의

- MSDN -
응용 프로그램과 함께 논리적으로 배포되는 실행 불가능한 데이터입니다. 응용 프로그램에서 오류 메시지로 표시되거나 사용자 인터페이스의 일부로 표시될 수 있습니다. 리소스는 문자열, 이미지, 지속된 개체 등을 포함하여 수많은
형식의 데이터를 포함할 수 있습니다

리소스란 어플리케이션에서 사용하는 일종의 자원인 셈이다. 그것은 텍스트타입일 수도 있고 바이너리 타입일 수도 있다. 예를 들어 닷넷컨트롤의 각종 설정값들(버턴의 Text,BackgroundImage 등)이 리소스가 된다.

아래 리소스를 사용하는 방법에 대해 다음과 같은 순으로 기술한다.
1. MANIFEST(매니페스트) 리소스 [타입을 가지지 않는 리소스]
2. .resources 리소스 [타입을 가지는 리소스] (Visual Studio의 리소스 관리 메커니즘)
3. 리소스의 지역화,국제화 (일종의 컨트롤속성의 국가별 설정(일종의 번역 같은..))

[2] 리소스 사용

2.1 메니페스트 리소스 (타입을 가지지 않는 리소스)
- 이미지 파일을 어셈블리(DLL,EXE)의 리소스로 포함하기 -
어플리케이션을 개발할 때 컨트롤에 사용될 이미지를 하드디스크의 물리적 주소에 의존하여 사용을 하면 어플리케이션 사용자(클라이언트)의 하드디스크의 동일한 경로,동일한 파일명이 항상 존재한다는 보장이 있거나, 매번 존재유무를 확인을 해야 하는 문제가 발생한다.

ex> button1.BackgroundImage = new Bitmap(@”C:\Temp\son.jpg”);

위처럼 코드에서 이미지를 지정하면 해당 디렉터리에 해당 이미지가 반드시 존재해야만 개발자가 의도한 응용프로그램이 될 것이다. 이 문제를 해결하기 위해서는 해당 이미지파일을 응용프로그램의 리소스로 포함시키면 된다

Demo>

* 이미지 파일을 리소스로써 추가하기

위와 같이 프로젝트 폴더 하위에 Resource 폴더를 만들고 (폴더명은 아무래도 상관없다) 이미지파일(son.jpb)을 프로젝트에 포함 하였다. son.jpg 파일속성에서 빌드작업 속성을 포함리소스(Embed)로 설정한다 이렇게 하면 포함한 이미지 파일은 어셈블리의 매니페스트(MANIFEST) 리소스 집합에 포함된다.

* 매니페스트 확인하기
ildasm.exe 사용하여 어셈블리를 확인해 보면 포함한 이미지파일이 어셈블리에 포함되었음을 알 수 있다.
리소스 명명 규칙 : 네임스페이스.폴더명.이미지파일명



* 포함한 리소스를 코드에서 사용하기
1.리소스로부터 이미지를 직접 불러오기 (Bitmap클래스는 리소스로부터 이미지를 직접 불러올 수 있다)
this.button1.BackgroundImage = new Bitmap(this.GetType(),"Resource.son.jpg");

2.어셈블리로부터 리소스를 바이트 형태의 스트림으로 불러오기
 this.button1.BackgroundImage = 
  
Image.FromStream(this.GetType().Assembly.GetManifestResourceStream(this.GetType(), "Resource.son.jpg") );

이때 주의해야 할 것은 리소스의 계층구조와 파일명(대소문자구분)을 정확히 지정해야 한다
 
참고> 어셈블리의 메니페스트 리소스를 모두 볼려면…
System.Reflection.Assembly asm = this.GetType().Assembly;
foreach(string resourceName in asm.GetManifestResourceNames()){
    MessageBox.Show(resourceName);
}


*
타입을 가지지 않는 리소스
우리가 방금 추가한 son.jpg 파일은 분명 이미지 파일이다. 하지만 매니페스트 리소스에는 파일의 확장자에 대한 어떤 정보도 포함하지 않는다. son.jpg 파일의 확장자를 이미지 확장자가 아닌 다른 확장자로 바꾸어도 위의 예제는 정확히 동작한다. Bitmap, Image 클래스에서 이미지변환 가능유무를 판단한다.


2.2 .resources 리소스 (타입을 가지는 리소스)
닷넷컨트롤의 각종 속성관리를 위한 리소스로써 텍스트 포맷,바이너리 포맷 두가지 포맷이 제공된다

Demo>

* 새로운 리소스파일 만들기

리소스를 추가한뒤 리소스편집기에서 아래와 같이 Name(mkex) 이라는 string 타입의  항목 을 추가하였다.

이 리소스 파일을 xml 은 아래와 같이 생성되었다 
<data name="Name"> 
           <value>mkex</value> 
</data>


* 리소스 파일 사용하기 (문자열) 
System.Reflection.Assembly asm = this.GetType().Assembly; 
System.Resources.ResourceManager rm =
                            new System.Resources.ResourceManager("Resource_Demo.Resource1",asm ); 
 string name = rm.GetString("Name"); 
MessageBox.Show(name); //결과는 mkex

* 리소스 파일 사용하기 (바이너리)
이번에는 문자열이 아닌 이미지 파일을 리소스 파일에 추가해 보자

System.Reflection.Assembly asm = this.GetType().Assembly;
System.Resources.ResourceManager rm = 
                            new System.Resources.ResourceManager("Resource_Demo.Resource1",asm );
string name = rm.GetString("Name");
MessageBox.Show(name);
this.button1.BackgroundImage = (System.Drawing.Image) rm.GetObject("Image");

문자열이 아닌 이미지타입의 리소스를 추가하기 위해서는 위에서와 같이 이미지 파일의 바이너리코드를 직접 만들어 줘야 한다. Visual Studio 에서는 이미지타입의 리소스를 자동으로 추가해주는 편집기능을 제공하지 않는다.
또한 디자인타임에서 확인할 수도 없다(위의 코드는 런타임에서 확인 가능하다)
이렇듯 바이너리타입의 리소스를 리소스편집기에서 편집,사용하는데는 한계가 있다.


2.3 디자이너 리소스
위의 리소스관리 메커니즘은 Visual Studio의 폼리소스 관리 메커니즘과 거의 유사하다. 또한 윈폼 디자이너는 커스텀 폼이나 컴포넌트 타입에 포함된 개체를 리소스 데이터에 연결시키기 위한 여러 기능을 제공한다



위 그림은 Visual Studio에서 버턴의 백그라운드 이미지를 디자인타임에 설정한 화면이다

1) Visual Studio
가 자동으로 생성한 코드
자동으로 생성되는
InitializeComponent() 메서드에 아래와 같은 코드가 있을 것이다
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Form1));
this.button2.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("button2.BackgroundImage")));

디자이너에서 설정한 이미지리소스는 디자인타임에 바로 연결되어 개발자에게 보여진다

2) 버턴이 있는 폼의 리소스 파일내용


3) ResourceManager를 사용한 동적 이미지 변경
System.Resources.ResourceManager resources =new  System.Resources.ResourceManager(typeof(Form1));

//button2의 배경이미지를 button1의 배경이미지로 설정하기
this.button1.BackgroundImage =
                                      ((System.Drawing.Image)(resources.GetObject("button2.BackgroundImage")));

4) 매니페스트에서 컨트롤의 리소스 확인하기
Visual Studio 를 사용해서 위와 같이 이미지파일을 설정해도 어셈블리의 리소스로써 포함되는 것은 차이가 없다.
단지, 아래에 보는 바와 같이 Form1 의 리소스 정보에 폼하위 컨트롤들의 리소스정보가 있다는 것을 제외하곤..




[3] 리소스의 지역화
지금까지 우리는 닷넷 컴포넌트의 리소스를 ResourceManager 클래스로 핸들링 하는 것을 알아 보았다.
System.Resources.ResourceManager 클래스는 이외에도 컴포넌트의 리소스를  지역화 해주는 유용한 기능을 또한 포함하고 있다. ResourceManager 객체는 여러 문화권의 리소스 중 어떤 리소스를 탐색할지를 현재 쓰레드의  CurrentUICulture 속성을 참고하여 내부적으로 결정한다.
  
Demo>>

1. 폼의 Localizable 속성을 true 로 설정한다
이렇게 하면 폼의 리소스파일(Form1.resx) 는 자동으로 폼의 지역화를 위한 엔트리를 생성하며 생성된 각 엔트리는
InitializeComponent() 에서 각 컨트롤과 매핑시킬 것이다 (각 파일을 직접 확인 해 보길 바람, 그림생략)

2. 폼의 Language 속성을 특정 문화권으로 설정한다
영어(영국)과 독일어를 설정한 상태이다. Language를 계속 변경하면 지역화 관련 리소스파일이 계속 추가됨을 알 수 있다. 어플리케이션 bin>Debug폴더에는 방금 설정한 문화권 de,en-GB와 영어중립국가(en) 이라는 폴더가 자동으로 생성되었으며 각 폴더하위에는 네임스페이스.resources.dll 라는 이름의 리소스어셈블리 파일이 생성되었음을 확인할 수 있다.

* 리소스의 탐색과정  
1. 특정국가와 특정언어에 대한 사항 탐색 
2. 중립국가와 특정언어에 대한 사항 탐색
3. 주 어셈블리에 포함되는 리소스 탐색
   (영어(미국) 과 같이 특정국가를 설정하면 그 언어의 중립국가(en)이 자동으로추가된다.
   독일어의 경우에도 독일어(오스트리아)를 선택했으면 독일어에 대한 중립국가(de) 가 자동 추가되었을 것이다)

위의 예에서 만일 영어(영국)에서 이 어플리케이션을 실행한다면 en-GB/네임스페이스.resources.dll 검사  -> (만일 찾을 수 없다면) en/네임스페이스.resources.dll 검사 -> (만일 찾을 수 없다면) 네임스페이스.exe 검사(Form1.resx가 된다) 의 순으로 리소스 탐색이 일어날 것이다

3. 버턴의 Text를 국제화 시키기
버턴의 텍스트 속성을 폼의 Language별로 다르게 설정한다(아래의 설정을 따라 하기 바란다)
1. 폼의 Language를 독일어로 설정한 뒤 버턴의 Text를 하늘(독일어)
2. 폼의 Language를 영어(영국)으로 설정한 뒤 버턴의 Text를 하늘(영국)
3. 폼의 Language를 영어로 설정한 뒤 버턴의 Text를 하늘(영어)
4. 폼의 Language를 기본값으로 설정한 뒤 버턴의 Text를 하늘(기본값)

이렇게 하면 각 리소스파일마다 버턴의 Text를 다르게 설정할 수 있으며 런타임에 컴퓨터의 국가정보를 바탕으로 해당 리소스파일의 정보가 위에서 언급한 탐색과정을 거쳐 사용되어진다(각 설정파일을 하나씩 지워나가며 탐색과정을 확인해 보길 바란다) 즉, 나라별로 번역본이 설정된 셈이다

4. 국제화된 버턴의 텍스트 확인하기
테스트를 하기 위해서는 해당 머신의 국가정보를 변경하거나 응용프로그램의 현재 국가정보를 변경해야 테스트를 할 수 있다. 여기에서는 현재 응용프로그램의 국가정보를 변경해서 테스트를 해보겠다
응용프로그램의 Main 메서드에 아래와 같이 특정 국가를 지정하자.    

static void Main() { 
    System.Threading.Thread.CurrentThread.CurrentUICulture =  new System.Globalization.CultureInfo("en-GB"); 
    Application.Run(new Form1());
}

응용프로그램이 실행되기 전에 쓰레드의 국가를 영어(영국)으로 변경했다.
(ResourceManager 이 현재 쓰레드의 CurrentUICulture 정보를 기반으로 어떤 문화권을 탐색할지 결정한다)
응용프로그램을 실행해보면 하늘(영국)이 나올 것이다.

리소스 탐색과정의 확인을 위해 하늘 (영국) 리소스 파일을 삭제한 후 다시 시도해 보자.
(결과 : 하늘(영어) 가 나올 것이다)

∵Commented by 미지수 at 2008-10-30 오후 4:30:01  
엠켁스님 잘 봤습니다. 덕분에 폼에 사운드 추가 성공! ^ㅡ^
이름
비밀번호
홈페이지
TX <- 왼쪽의 문자를 오른쪽 박스에 똑같이 입력해 주세요