2 Results for '리소스'

  1. 2008.10.24 리소스 종류와 상대 URI 평가 방법 정리 (5)
  2. 2008.03.31 리소스와 URI

실버라이트 2에서 상대 URI를 평가하는 기준은 아주 심플하게 말하자면,

“XAP파일이 호스팅되어 있는 웹 서버의 URL”이에요.

끝~~~~

 

 

 

 

이러면 해피하겠지만, 실버라이트는 각 리소스 종류에 따라 상대 URI를 평가하는 방법이 달라져요. 정확히 말하자면 어떤 상대 URI를 가진 리소스를 가져올 때에는 정해진 절차가 있다…가 되겠죠.

 

리소스의 종류

우선 실버라이트가 사용할 수 있는 리소스의 종류는 크게 다음과 같이 나눌 수 있어요.

  1. Resource
  2. Embedded Resource
  3. Content
  4. Site of Origin

Resource

Resource는 비주얼 스튜디오 IDE에서 Build Action 속성이 Resource로 설정된 프로젝트 아이템을 말해요.
Resource는 프로젝트가 컴파일 될 때 해당 프로젝트의 타겟 어셈블리에 포함되므로 별도로 배포할 필요가 없어지지만 대신 어셈블리의 용량이 그만큼 늘어나게 되겠죠. 따라서 아주 필수적인 요소만을 Resource로 설정해야 해요.

※ Build Action의 설정은 다음 그림과 같이 프로젝트 아이템을 선택하고 속성Properties 창에서 할 수 있습니다.


Embedded Resource

Embedded Resource는 Resource와 거의 동일한 속성을 갖지만 애플리케이션에서 접근하는 방법이 달라요. 실버라이트에서는 사용되지 않는다고 봐도 무방해요. 아니, 실버라이트 프로젝트에서는 쓰지 않기를 권장해요. 정말로 불편하기만 하니까요.

Content

Content는 비주얼 스튜디오 IDE에서 Build Action 속성이 Content로 설정된 프로젝트 아이템을 말하죠.
Content는 실버라이트 프로젝트가 컴파일 될 때 XAP 패키지 파일에 직접 포함이 되므로 역시 따로 배포할 필요가 없어지죠. 그러나 마찬가지로 XAP 패키지의 크기가 늘어나는 원인이 되므로 필수 요소만을 Content로 설정해야 해요.

Resource와 Embedded Resource와 Content가 비록 그 정의와 특성이 다르긴 하지만 하나의 프로젝트의 아이템이므로 같은 위치에 같은 파일 명으로는 단 하나의 종류만 존재할 수 있어요. 요컨대, MyImage.png라는 파일이 동시에 Resource와 Content의 형태로 존재할 수 없다는 거죠.

※단, 위의 가정은 어디까지나 비주얼 스튜디오 IDE를 사용할 경우를 말합니다. 기술적으로 MyImage.png는 Resource와 Content로 존재할 수 있지만 실제로 그렇게 하는 경우는 없다고 단언할 수 있을 만큼 없기 때문에 위와 같이 말 할 수 있습니다.

Site of Origin

이건 참 할 때마다 우리말로 옮기기가 애매한 건데요, 굳이 말하자면 ‘XAP파일을 호스트하는 서버의 위치’라고 할 수 있죠. 쉽게 얘기해서 실버라이트 패키지, XAP 파일이 올라갈 웹 서버에 있다는 것을 의미해요. Site of Origin 위치에 있는 리소스 파일은 당연하게도 실버라이트 패키지 내에 포함되지 않으므로 그 파일이 존재할 것이라고 확신할 수 없어요. 따라서 이 위치에 있는 리소스를 접근할 때에는 반드시 예외 처리가 필요하겠죠. 웹의 특성상 대부분의 이미지, 동영상, XML 등이 Site of Origin 리소스로 배치될 거에요.

 

URI 표현식

실버라이트는 어떤 리소스의 위치를 지정하는데 URI(Uniform Resource Identifyer)를 사용하죠. URI는 크게 상대 URI와 절대 URI로 구분할 수 있는데요, 절대 URI는 일반적인 URL을 지정하는 방법과 같다고 할 수 있으므로 상대 URI의 표현에 대해서 집중하도록 하죠. 상대 URI의 표현에는 몇 가지 규칙이 있어요.

예제를 들기 위해 실버라이트 애플리케이션이 http://hugeflow.com/Silverlight/Test.xap에서 다운로드 되었다고 가정합니다.

상대 URI는 Site of Origin 즉, 웹 사이트가 아닌 Resource또는 Content를 우선적으로 가리킵니다.

단, 적용 방식은 살짝 특이한데 이 부분은 아래에 설명합니다.

 

상대 URI의 절대적 기준은 XAP 파일의 현재 위치가 됩니다.

ex) /Image.png => http://hugeflow.com/Silverlight/Image.png

 

상대 경로는 '/'로 시작하는 것과 그렇지 않은 것이 동일한 위치를 가리킵니다.

ex) Image.png  => http://hugeflow.com/Silverlight/Image.png

ex) /Image.png => http://hugeflow.com/Silverlight/Image.png

 

..표현식으로 상위 경로를 지정할 수 없으며 이 표현은 무시됩니다.

ex) ../../Image.png => http://hugeflow.com/Silverlight/Image.png

 

Resource는 명시적으로 리소스가 포함된 어셈블리를 지정할 수 있습니다.

ex) /MyAssembly;component/Image.png => MyAssembly안에 있는 Image.png 리소스를 가리킴

 

동작 테스트

이외에도 다른 규칙들도 있지만 실제 사용에서 가장 중요한 내용은 이 정도라고 봐요. 자, 지금껏 말만 많이 했는데 역시 실제 동작 코드를 봐야 쉽게 이해가 가겠죠? 다음 이미지는 각 경로에 따라 로드되는 리소스의 종류를 표현하고 있는데요, 일단 보죠.


코드도 함께 곁들이는 건 어떨까요? :)

 

이 프로젝트는 다음과 같은 구조를 가지고 있어요.

 
 - 크게 세개의 프로젝트

ImageLibrary
실버라이트 라이브러리

UriRuleTest
ImageLibrary를 참조하는 실버라이트 애플리케이션 프로젝트

UriRuleTest.Web
UriRuleTest 실버라이트 애플리케이션을 호스팅하는 웹 서비스


- 실버라이트 애플리케이션 프로젝트와 웹 프로젝트는 각각 동일한 위치에 같은 파일 명으로 이미지 리소스 파일 존재

- 각 리소스가 포함된 위치는 색상으로 구분
(파랑 ; 실버라이트 애플리케이션
빨강 ; 실버라이트 라이브러리
녹색 ; Site of Origin 웹 프로젝트)

- 상대 URI로는 실버라이트가 호스팅되는 위치 바깥의 경로를 접근할 수 없다는 것을 보여주기 위해 웹 프로젝트에는 또다른 위치에 리소스들을 포함
(Web/Images 폴더)


결과를 보면 직관적으로 어떤 식으로 리소스가 로딩 되는지를 확인할 수 있을 거에요. 하나하나 설명하는 것 보다는 특이한 몇 가지 결과만 얘기해 보도록 하죠.

  • '/'로 시작하지 않는 리소스의 경우 Resource를 먼저 검색하고 만약 Resource가 없을 경우 Site of Origin을 시도합니다. 즉 두 파일이 모두 존재할 경우 항상 Resource가 선택됩니다. 또한 이 경우 Content에 대해서는 시도하지 않습니다.
  • '/'으로 시작하는 리소스의 경우 Content를 먼저 검색하고 만약 Content가 없을 경우 Site of Origin을 시도합니다. 즉 두 파일이 모두 존재 할 경우 항상 Content가 선택됩니다. 또한 이 경우 Resource에 대해서는 시도하지 않습니다.
  • Site of Origin의 경우 '/'의 유무는 영향을 주지 않습니다.
  • 위와 같은 특징이 혼란을 줄 가능성이 있으므로 Resource는 반드시 다음과 같이 명시적인 리소스 경로를 사용하는 것이 좋습니다. 이렇게 하면 참조하고 있는 다른 어셈블리의 리소스도 가져올 수 있습니다. 
    /UriRuleTest;component/Images/Resource.png
  • Embedded Resource는 오직 코드를 통해 특별한 방법으로만 접근이 가능합니다. 사실 Embedded Resource를 쓸 이유가 없습니다.
  • 다른 라이브러리 어셈블리에 있는 Content는 가져올 수 있는 방법이 없습니다. 이 파일은 사실상 컴파일시 버려집니다.
  • 웹 서버에서 XAP 파일이 있는 경로를 벗어난 위치에 있는 리소스를 접근하기 위해서는 절대 URI를 사용하는 방법 밖에 없습니다. 사용법은 코드를 참고하세요.
  • ../../../../… 와 같이 ..를 아무리 많이 중첩하더라도 결코 XAP 파일의 위치에서 벗어날 수 없으며 해당 표현은 무시됩니다.

사실 이 정책이 Beta2때 바뀌었다가 RC0이후로 다시 위와 같이 돌아왔죠. 실버라이트 애플리케이션의 의미상 위의 정책이 올바르다고 생각해요. 실버라이트 애플리케이션이 웹 서버의 루트 경로나 상대 경로를 가정하고 동작하는 것은 좋지 않은 판단일테니까요.

어쨌든 이젠 헤깔리지 마시고 그냥 위의 표를 참고하세요^^

저작자 표시 동일 조건 변경 허락
신고
Posted by gongdo

오랫만이네요. 이건 이주일 전부터 써야지하고 생각했던건데 너무 오랫동안 묵혀뒀어요.
실버라이트 2에서 가장 많이 달라진 것중 하나는 바로 프로젝트에서의 리소스 파일의 관리와 URI 접근 규칙이죠.

※이 글에서 사용된 내용을 포함하는 샘플프로젝트는 다음의 파일을 다운로드 하세요.

SilverlightResourceFiles.zip

실버라이트 리소스와 URI 테스트 프로젝트


리소스 파일이란 공통으로 사용되는 XAML, XML, 이미지, 동영상, 음악 등 컴파일되지 않는 모든 '비실행(non-executable)' 파일을 말해요. 실버라이트 애플리케이션이 이러한 리소스 파일을 요청할 때에는 URI(Uniform Resource Identifier)라고 하는 형식으로 리소스 파일의 위치를 식별하게 되죠.

실버라이트에서 다루는 리소스 파일은 크게 다음과 같은 네가지로 분류할 수 있어요. 자세한 설명은 각 토픽에서 다루도록 하죠.

  • 리소스(Resource)
  • 컨텐트(Content)
  • Site of origin
  • 절대 URI
※노트
이 글에서 모든 비실행 데이터 파일을 의미하는 리소스 파일과 리소스 파일의 종류를 말하는 리소스를 일반적인 폰트와 이탤릭체로 구분합니다. 이 둘의 의미를 혼동하지 않도록 주의하여 읽어주세요.

이 글에서는 실버라이트에서의 리소스 파일의 종류와 정의 그리고 각각의 URI를 표현하는 방법에 대해 설명합니다. 가능하다면 MSDN의 Resource Files도 함께 참고하세요. 사실 이 글의 핵심은 MSDN의 글과 일치하고 약간의 설명만 추가한거에요.

리소스 파일

리소스 파일은 애플리케이션 어셈블리나 라이브러리 어셈블리에 포함(embedded)되는 비실행 데이터 파일을 말해요. 리소스 파일은 어셈블리에 포함되기 때문에 반드시 프로젝트에 포함되어야 하며 비주얼 스튜디오에서는 다음과 같이 프로젝트에 추가된 파일의 Build Action을 Resource로 설정하여 해당 파일을 리소스 파일로 지정할 수 있어요.

비주얼 스튜디오는 비실행 파일이 추가될 경우  기본적으로 Build Action을 Resource로 설정하게 되죠. 만약 해당 파일이 어셈블리에 포함되는게 아니라 다음에 설명할 다른 리소스 형식으로 설정하고 싶다면 반드시 Build Action을 수정해야 해요.

이렇게 리소스로 추가된 리소스 파일은 어셈블리 내에 포함되므로 같은 어셈블리 내에 있는 코드에서는 별다른 접근자 없이 곧바로 리소스 파일의 상대 URI(relative URI)를 사용하여 접근할 수 있어요. 예를 들어 위의 그림처럼 EmbeddedInApplicationAssembly.png 파일이 프로젝트의 루트에 들어있다면 이 그림 파일을 보여주기 위한 Image 오브젝트는 XAML과 코드 비하인드에서 각각 다음과 같이 표현할 수 있죠.

[XAML]
<Image Source="EmbeddedInApplicationAssembly.png" />

[C#]
Image img1 = new Image();
img1.Source = new BitmapImage(new Uri("EmbeddedInApplicationAssembly.png", UriKind.Relative));

한가지 주의할 점은 리소스 파일은 상대 URI로 표현되므로 만약 이 리소스 파일을 요청하는 코드의 위치가 리소스 파일의 위치와 다를 경우 제일 앞에 슬래시로 시작하는 정확한 상대경로를 적어주는 것이 좋죠. 또 한가지 잊지 말아야 할 것은 실버라이트의 URI 표현에는 상위 경로를 의미하는 '../'이나 현재 경로를 의미하는 './'을 사용할 수 없다는 점이에요. 다음은 슬래시로 시작하는 정확한 상대경로로 URI를 표현하는 방법을 보여줘요.

[XAML]
<Image Source="/EmbeddedInApplicationAssembly.png" />

[C#]
Image img1 = new Image();
img1.Source = new BitmapImage(new Uri("/EmbeddedInApplicationAssembly.png", UriKind.Relative));

여러가지 면을 고려할 때 리소스 파일은 리소스를 관리하기 위한 하나의 폴더에 저장하고 리소스 파일의 URI를 지정할 때에는 반드시 슬래시로 시작하는 정확한 상대경로로 표현하는 것이 실수를 줄일 수 있는 가장 좋은 방법이라고 할 수 있어요.

※노트
현재, MSDN에는 앞에서와 같이 /로 시작하는 리소스 파일에 대한 상대 URI를 지정할 수 있다고 나와있으나 실제로 코드를 만들어보면 런타임 예외를 유발하죠. 앞의 설명에서 '../'이나 ./'을 사용할 수 없다는 것도 맞고 정확한 표현을 위해서 완전한 상대 URI를 써야한다는 설명도 맞지만 불행히도(?) /로 시작하는 단순한 형태의 상대 URI를 리소스 파일에 사용할 수 없으므로 다음에서 설명하는 명시적인 방법을 통한 상대 URI를 사용할 것을 권장합니다.

리소스 파일의 또 한가지 특징은 해당 리소스가 다른 어셈블리에 있어도 그것을 참조할 수 있다는 점인데요, 예를 들어 다음과 같이 다른 프로젝트(즉, 다른 라이브러리 어셈블리)에 있는 리소스가 있다고 생각해 보죠.

이렇게 다른 어셈블리에 있는 리소스 파일은 다음과 같이 요청할 수 있어요.

[XAML]
<Image Source="/SilverlightResourceLibrary;component/EmbeddedInLibraryAssembly.png" />

[C#]
Image img1 = new Image();
img1.Source = new BitmapImage(new Uri("/SilverlightResourceLibrary;component/EmbeddedInLibraryAssembly.png", UriKind.Relative));

/SilverlightResourceLibrary;component/ 부분은 어셈블리의 위치를 명시적으로 표시하는 방법인데요, 위와 같이 다른 어셈블리를 표현할 수도 있지만 자기 자신의 어셈블리를 명시적으로 표현할 수도 있죠. 예를 들어 같은 어셈블리에 있더라도 명시적으로 정확히 리소스 파일을 가져오기 위해 /SilverlightResourceFiles;component/...와 같이 표현할 수 있어요.

앞에서 설명한 것처럼 리소스 파일은 어셈블리에 포함되는데요, 이 사실은 .NET Reflector와 같은 어셈블리 해커를 통해 쉽게 확인할 수 있어요.


컨텐트 파일

컨텐트 파일은 배포되는 패키지에 포함되는(in-package) 비실행 데이터 파일을 말해요. 즉,  XAP 패키지 파일(.XAP)내에 파일의 형태로 포함되는 형태의 리소스를 말하죠. 컨텐트 파일은 비주얼 스튜디오에서 다음과 같이 Build Action을 Content로 설정하여 지정할 수 있어요.

컨텐트 파일도 패키지 내에 포함되기 위해 반드시 프로젝트에 추가되어 있어야 하며 따라서 항상 그 파일이 존재한다고 가정할 수 있어요. 또한 패키지를 기준으로 항상 어셈블리와 같은 경로에 있기 때문에 단순히 상대 URI만으로 해당 리소스를 요청할 수 있죠. 다음은 XAML과 C# 코드로 컨텐트 파일을 요청하는 Image 오브젝트를 보여줘요.

[XAML]
<Image Source="/IncludedInApplicationPackage.png" />

[C#]
Image img1 = new Image();
img1.Source = new BitmapImage(new Uri("/IncludedInApplicationPackage.png", UriKind.Relative));

잊지 마세요, 컨텐트 파일은 코드가 들어있는 어셈블리가 위치한 경로와 컨텐트 파일의 경로가 서로 다를 수 있기 때문에 반드시 위와 같이 슬래시로 시작하는 정확한 상대 URI로 표현해야 해요.

컨텐트 파일은 다음과 같이 애플리케이션 패키지(.XAP)를 압축해제 해 보면 확인할 수 있어요.


Site of Origin

Site of Origin은 딱히 한글로 번역할만한 단어를 찾지 못했는데요, 풀어서 얘기하자면 실버라이트 애플리케이션 패키지를 다운로드한 원래 사이트(같은 도메인에 있는 서버)를 말해요. 즉, Site of Origin 파일은 원래 사이트에 있는 비실행 데이터 파일을 말하죠. Site of Origin 파일은 다음과 같이 비주얼 스튜디오에서 Build Action을 None으로 설정하면 돼요.

또한 Copy to Output Directory 속성을 Copy Always로 설정하면 출력 경로에 해당 파일을 항상 복사하게 되므로 배포가 조금 더 용이해지죠.

※노트
하지만 위와 같이 Copy Always를 설정하더라도 실버라이트와 연결된 웹 사이트나 웹 애플리케이션 프로젝트의 출력 경로에는 해당 파일이 복사되지 않으므로 반드시 다음과 같이 Site of Origin 파일들을 실제 웹 프로젝트의 출력 경로에 복사해줘야 합니다. 이 기능은 다음 베타때 꼭 지원을 해줬으면 하네요.

중요한 것은 Site of Origin 파일은 어셈블리나 패키지에 포함되지 않고 필요할 때마다 다운로드(On-Demand)되므로 실제로 서버에 파일이 존재하지 않을 가능성이 있다는 점이에요. 따라서 Site of Origin 파일을 사용하는 코드는 적절한 이벤트 핸들링을 통해 로드에 실패했을 때 처리를 수행해야 하죠. 그러나 이 글에서는 논의의 범위를 벗어나므로 에러를 처리하는 방법에 대해서는 소개하지 않고 다음에 추가로 포스팅하도록 하죠. Site of Origin 파일은 XAML과 C# 코드에서 다음과 같이 표현할 수 있어요.

[XAML]
<Image Source="/OnDemandAtSiteOfOrigin.png" />

[C#]
Image img1 = new Image();
img1.Source = new BitmapImage(new Uri("/OnDemandAtSiteOfOrigin.png", UriKind.Relative));

한 가지 주의할 점은 Site of Origin에서의 '/'는 일반적인 웹과는 달리 웹 사이트의 루트 경로를 나타내지 않는다는 점이에요. 실버라이트 애플리케이션은 실버라이트 패키지가 배포되는 경로를 기준으로 완전히 독립적으로 작동하며 따라서 '/'는 실버라이트 패키지 즉, XAP파일이 있는 경로를 의미하게 돼요. 또한 앞에서 설명한 것처럼 '../'을 사용할 수 없기 때문에 실버라이트 애플리케이션이 상대 경로를 통해 웹 서버의 다른 리소스를 접근하는 것은 금지되게 되죠.


리소스(or 컨텐트) vs Site of Origin

Application Development Overview에서 다뤘듯이, 애플리케이션 패키지는 가능한 그 크기를 줄이는 것이 빠른 응답을 하는 애플리케이션을 만드는 가장 기본적인 방법이죠. 즉, 애플리케이션 패키지에 포함되는 리소스 파일과 컨텐트 파일은 그 성격과 크기, 종류에 따라 신중하게 선택하는게 좋아요. 각 파일의 선택은 대체로 다음과 같은 기준으로 정할 수 있을 거에요.

  • 리소스 파일
    모든 애플리케이션에 공통적으로 적용될 어셈블리에 포함되는 사용자 컨트롤 등의 표현에 없어서는 안될 에셋(Asset)성격의 이미지, XAML, 효과음 등의 작은 파일
  • 컨텐트 파일
    애플리케이션 마다 다르게 사용될 수도 있는 종류의 스킨, 설정 등의 작은 파일
  • Site of Origin 파일
    애플리케이션의 외형적인 이미지, XAML, 동영상, 음악 등 애플리케이션을 표현하기 위해 필요한 모든 종류의 파일

상대 URI로 표현되는 리소스들은 경우에 따라 애매하게 될 수 있어요. 예를 들어,

"RelativeURIResource.png"

이것만으로는 해당 파일이 리소스인지 Site of Origin인지 구분할 수 없겠죠. 또한,

"/RelativeURIResource.png"

이 경우는 해당 파일이 컨텐트인지 Site of Origin인지를 구분할 수가 없어요.
이런 경우 실버라이트 런타임은 다음의 과정을 통해 파일을 찾게 돼요.

  1. 만약 URI가 /어셈블리이름;component/ 처럼 명시적으로 지정된 경우 해당 어셈블리에서 리소스 파일을 확인하고 없을 경우 이미지 로드 실패
  2. 만약 제일 앞에 /가 없다면 가장 먼저 어셈블리에 해당 리소스 파일이 있는지 확인
  3. 다음으로 패키지가 위치한 Site of Origin에서 해당 파일을 요청하고 존재하지 않을 경우 이미지 로드 실패
  4. 만약 제일 앞에 /가 있다면 가장 먼저 Site of Origin에서 해당 파일을 요청
  5. 다음으로 XAP 패키지에서 컨텐트 파일을 확인하고 없을 경우 이미지 로드 실패
※노트
앞에서 설명한 것처럼 현재 실버라이트의 URI 표현은 뭔가 MSDN과 맞지 않는 부분이 있고 따라서 위의 검색 순서는 다음 베타 버전에서 변경될 가능성이 있으니 주의하세요.

절대 URI

절대 URI는 일종의 Site of Origin이지만 의미상 같은 도메인의 서버 뿐만 아니라 다른 도메인(크로스 도메인)의 리소스도 요청할 수 있다는 점에서 따로 분리했어요. 앞에서 살펴본 세가지 경우와는 달리 절대 URI는 말 그대로 지정된 절대적인 경로에서만 파일을 요청하게 되죠. 또한 절대 URI로 설정할 경우 요청하는 리소스의 종류에 따라 크로스 도메인을 사용할 수 있다는 점에서 앞의 세가지 경우와 다르다고 볼 수 있어요.

절대 URI는 다음과 같은 구성 요소로 이루어져 있죠.

  • 스키마
  • 호스트
  • 포트 번호
  • 경로

예를 들어 gongdosoft.com이라는 웹 서버에 있는 ghost.png라는 파일은 http://gongdosoft.com:80/ghost.png로 표현할 수 있고 각각,

http:// gongdosoft.com :80 /ghost.png
스키마 호스트 포트 번호 경로

로 구분할 수 있죠. 대체로 http-80과 같이 잘 알려진 스키마와 포트는 생략되는게 일반적이에요.

만약 스키마, 호스트, 포트 번호가 실버라이트 패키지의 위치와 다를 경우 접근 정책에 따라 제한을 받을 수 있으며 여기에 관해서는 URL Access Policy를 참고하세요.

절대 URI를 가진 리소스를 요청하는 방법은 다음과 같아요.

[XAML]
<Image Source="http://shiverlight.net/Images/AbsoluteURI.png" />

[C#]
Image img1 = new Image();
img1.Source = new BitmapImage(new Urihttp://shiverlight.net/Images/AbsoluteURI.png", UriKind.Absolute));

절대 URI도 Site of Origin과 같이 필요할 때 요청하는 리소스이기 때문에 리소스를 요청하는 시점에는 존재하지 않거나 요청에 실패하는 경우가 있을 수 있겠죠. 따라서 반드시 로드 실패에 대한 이벤트를 처리해야 한다는 것을 잊지 마세요.


참고


신고
Posted by gongdo


티스토리 툴바