안드로이드 Resources, Assets, R 클래스에 대해 간단히 알아봅니다.

1. Resources

  • 리소스는 애플리케이션이 필요로 하는 코드 이외의 자원
  • 이미지, 오디오, 비디오, 텍스트 문자열, 레이아웃, 테마 등
  • 리소스는 res/ 폴더에 위치시킴
  • 리소스 파일명은 소문자, 숫자, 마침표(.), 언더바(_)로만 구성
  • 리소스는 빌드타임에 안드로이드 빌드시스템에 의해 감지되며, 각 리소스는 고유의 ID를 부여받음
  • 안드로이드는 리소스ID를 포함하는 R 클래스를 생성해줌(aapt)
  • 리소스는 Resources 인스턴스를 통해 액세스됨
  • 리소스는 빌드시 컴파일되어 애플리케이션 바이너리에 포함됨


2. Assets

  • Resources와 비슷하나 자주 사용되지 않음
  • assets/ 폴더에 위치함
  • 어떤 종류의 파일이든 가능
  • 컴파일되지 않고 원시형태 그대로(raw) 패키징됨
  • 바이트스트림(InputStream) 형식으로 읽기 가능
  • 파일시스템의 파일처럼 다루어짐(리소스ID 없음)
  • AssetManager를 이용


* 파일 시스템처럼 다루어진다는 의미
 - 파일목록을 구할 수 있고 순회할수 있고 원하는 파일을 찾을 수 있다(listed, iterated, discovered)

* 하위 디렉토리 구조
 - Assets 디렉토리(assets/)는 하위 디렉토리 구조(hierachy)를 유지할 수 있다.
 - Resources 디렉토리(res/)는 하위 디렉토리 구조를 가질 수 없다(R 클래스에 나타나지 않게됨)
 
* res/raw/ 폴더와 assets/ 폴더의 차이점
 - 리소스ID가 있는가 없는가
 - Resources를 이용하는가 AssetManager를 이용하는가
 - 그 외 큰 차이없는 듯

3. R 클래스
안드로이드는 애플리케이션 소스코드에서 리소스 ID를 쉽게 참조할 수 있게 aapt(android asset packaging tool)를 이용하여 R클래스를 자동으로 만들어서 제공합니다.

 

R 클래스의 구조는 다음과 같습니다.

참고로 framework-res.apk에 포함된 시스템 리소스들의 ID는 android.R 클래스에 정의되어 있습니다.

신고
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 에코지오

댓글을 달아 주세요

  1. BlogIcon javalove 2011.08.05 10:24 신고  댓글주소  수정/삭제  댓글쓰기

    알기쉽게 잘 정리해주셔서 감사합니다.

    링크로 제 블로그에 넣었습니다~ ^^

  2. 자바및안드로이드처음 2011.09.14 22:02 신고  댓글주소  수정/삭제  댓글쓰기

    대단히 잘봤습니다. 무척이나 정리가 잘 되어있군요^^

리소스 설정치환은 리소스 필터링과 리소스 교체로 나눌 수 있습니다. 이 중에서 리소스 필터링은 원본 리소스 파일을 타겟으로 복사하면서 파일 내의 특정 부분을 다른 문자열로 치환하는 방법입니다. Ant, Maven, Buildr에서 이것을 어떻게 처리하는지 살펴봅니다.

1. Ant는 copy 타스크 내부에서 filter 요소를 사용하여 리소스 필터링을 지원합니다. 보통 @토큰@ 형식으로 표현된 내용이 다른 값으로 치환됩니다.

<copy file="${build.dir}/version.txt" toFile="${dist.dir}/version.txt">
  <filterset>
    <filter token="DATE" value="${TODAY}"/>
    <filtersfile file="${user.dir}/dist.properties"/> <!-- 이름/값 쌍을 프로퍼티 파일로 제공 -->
  </filterset>
</copy>

2. Maven에서는 process-resources 단계(또는 'resources:resources' 골)에서 보통 ${프로퍼티} 형식의 문자열이 실제 그 프로퍼티 값으로 바뀝니다.

<resources>
 <resource>
  <directory>src</directory>
  <filtering>true</filtering>
  <excludes>
   <exclude>**/*.java</exclude>
  </excludes>
 </resource>
</resources>

프로퍼티는 여러방식으로 제공됩니다. (1) 메이븐 실행시 -D를 통해서 제공 (2) properties 엘리먼트에 기술 (3) 프로퍼티 파일을 지정 (4) 시스템 프로퍼티. 프로퍼티 파일 형태로 이름/값 쌍을 제공하는 경우 아래처럼 build 밑에 filters 엘리먼트에 파일의 위치를 기술하면 됩니다.

<build>
  <defaultGoal>install</defaultGoal>
  <directory>${basedir}/target</directory>
  <finalName>${artifactId}-${version}</finalName>
  <filters>
     <filter>filters/filter1.properties</filter>
  </filters>
  ...
</build>


3. Buildr의 리소스 필터링은 메이븐과 유사합니다. Buildr에서는 resources 타스크를 통해 리소스의 내용을 필터링합니다. 기본적으로 src/main/resources 디렉토리의 리소스 파일들을 target/resources 디렉토리로 복사하면서 필터링을 수행합니다.

resources.from _('src/etc') # 원본 리소스 파일 디렉토리 변경
resources.include '*.html' # 포함할 파일 패턴
resources.exclude 'scratch/*' # 제외할 파일 패턴

resources
.filter.using 'version'=>'experimental''copyright'=>'Acme Inc (C) 2007' # 치환될 내용 매핑

위의 예제에서 리소스 파일내의 ${copyright} 부분은 'Acme Inc (C) 2007'로 바뀌게 됩니다. 이러한 이름/값 매핑은 당연히 외부 파일 형태로도 제공할 수 있습니다만, Buildr에서는 프로퍼티 형식이 아니라 buildr 파일과 동일한 위치에 있는 profiles.yaml 파일을 사용합니다. profiles.yaml 파일은 서로다른 환경에서 서로다른 설정을 가져가기 위한 것인데요(메이븐의 그것과 똑같은 개념입니다), 여기에 filter 엘리먼트를 추가하면 됩니다.

filter: &alpha1
  version: experimental
  copyright: Acme Inc (C) 2007
 
development:
  filter: *alpha1
test:
  filter: *alpha1

resources 타스크는 compile 타스크 실행시 자동으로 함께 수행됩니다. 아래처럼하면 단독으로 실행됩니다.

buildr 프로젝트이름:resources

그런데 이 리소스 필터링 기능이 resources 타스크가 실행될 때뿐 아니라 빌드의 다른 곳에서도 필요한 경우가 있습니다. 이때는 resources 타스크가 내부적으로 이용하고 있는 filter를 사용하면 됩니다.

filter('src/specs').into('target/specs').
  using('version'=>version, 'created'=>Time.now).run
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'Build&Deploy > Buildr' 카테고리의 다른 글

Buildr : 타스크 의존 관계  (0) 2008.12.11
Buildr : 리소스 교체  (3) 2008.12.09
Buildr : 리소스 필터링  (0) 2008.12.09
Buildr : 파일집합 복사하기  (0) 2008.12.05
Buildr : 파일 집합 선택  (0) 2008.12.01
Buildr : 의존성(dependencies) 설정하기  (4) 2008.11.19
Posted by 에코지오

댓글을 달아 주세요

이전 글에서 리소스 설정치환 방법에 대해 얘기했습니다. 그럼 메이븐 환경에서 리소스 설정치환 작업은 어떤 phase에서, 어떤 리소스를 대상으로 이루어져야 할까요?

1. 클래스패스에 포함되는 리소스

(1) 리소스 필터링 방식
메이븐이 process-resource 단계에서 타겟 디렉토리로 복사된 리소스를 대상으로 필터링을 해줍니다. 이때 원본 리소스는 변경이 없습니다. 그러니까 /src/jdbc.properties 파일에 password=${jdbc.password} 처럼값을 설정해놓으면 /target/classes/jdbc.properties 파일에는 그 부분이 password=my_password 식으로 바뀌어 있다는 말입니다.

(2) 리소스 교체 방식
타겟 디렉토리에 복사된 리소스 파일에 대해서 교체 처리해줍니다. 어차피 process-resource 단계에서는 resources:resources 골이 가장 먼저 실행되기 때문에 교체 작업(ant의 copy 타스크 이용)은 그냥 process-resources 단계에 바인딩하면 됩니다. 역시 원본 리소스 파일은 변경이 없습니다. 예를 들어 /src 밑의 jdbc.properties와 jdbc.properties.dev가 /target/classes 밑에 복사된 후 /target/classes/jdbc.properties.dev 파일이 /target/classes/jdbc.properties 파일을 덮어쓰게 됩니다.

 

2. WEB-INF 밑에 있는 리소스(web.xml, struts-config.xml, applicationContext.xml 등등)

WEB-INF 밑의 리소스에 대한 설정치환은 좀 지저분합니다. 
메이븐은 package 단계에서 war:war를 실행하는데, war:war는 무조건 war:exploded 를 먼저 실행하고 나서 exploded된 웹어플리케이션을 war 파일로 묶어냅니다. 우리가 원하는 것은 exploded 된 웹어플리케이션의 리소스 파일에 대해 리소스설정치환 작업을 하고나서 war 파일로 패키징하는 것인데, 중간에 끼어들 여지가 원천 봉쇄된 것입니다.

뭐 package 단계나 war:war를 실행하지 않으면 되긴합니다. war:exploded를 명시적으로 실행한 뒤에 설정치환을 하면 됩니다. 그런데 설정치환하는 execution을 어느 phase에 바인딩하는게 좋을지... 하여간 원본 리소스 파일을 건드리지 않은 상태로 리소스 치환을 하려니 지저분해지는군요.

만약 원본 리소스를 건드려도 무방하다면 package 전 단계(prepare-package 단계는 maven 2.1부터 지원하기 때문에 2.1 이전 버전이라면 process-resources 단계가 괜찮을까요)에서 원본 리소스를 대상으로 설정치환 작업을 처리하면 됩니다. 
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 에코지오

댓글을 달아 주세요

우리가 개발하는 어플리케이션은 최종 사용자에게 서비스되기 전에 여러 장소를 거칩니다.

개발자 로컬PC -> (소스저장소) -> 빌드서버(CI서버) -> 개발서버 -> 테스트서버 -> 스테이징서버 -> 운영서버

불행히도 이렇게 거쳐가는 서버에 따라서 환경/정책이 조금씩 다르기 때문에 우리는 개발소스에 포함된 설정값을 다르게 가져가야 합니다. 예전에는 소스가 서버 사이를 옮겨갈 때마다 수작업으로(vi 에디터로) 설정값을 매번 편집을 해주거나, 설정값을 포함한 파일을 빼고(!) 소스를 옮기기도 했습니다. 여러분은 어떤 방법으로 설정값을 다르게 세팅하셨습나요?

여기, 좀더 우아한 방법이 있습니다.

아, 그보다 먼저 설정값을 포함하는 파일을 보통 뭐라고 부르나요? 설정파일 ? 리소스 파일?  뭐라고 부르든 리소스는 주로 xml, properties 로 작성을 하죠. 레일스에서는 yml인가 이런것도 있더군요. 암튼.

그리고 로컬,개발,운영 등 서버의 환경차이에 따라 리소스 파일을 변환하여 개발소스에 포함된 설정을 달리하는 일을 뭐라고 부르나요? 환경맞춤작업? 리소스변환리소스 설정치환? 이런 거에 대한 공식적인 용어를 들은 바가 없어서 일단은 제목에 리소스 설정치환이라고 임의대로 용어를 지었습니다. 혹시 널리 사용되는 용어를 아시는 분은 알려주세요. 언뜻 profile, portable이란 단어가 떠오르기는 합니다만....

아래는 제가 알고 있는 리소스 설정치환 방법 2가지입니다.(리소스 필터링, 리소스 교체 역시 모두 제가 임의로 만든 용어입니다. 더 나은 용어가 있으면 알려주세요.)

1. 리소스 필터링(filtering)
-빌드시에 설정 파일의 내용을 수정하는 방법
-설정값을 하드코딩하지 않고 정해진 형식의 변수로써 설정. 예를 들어 ${jdbc.password}.
-빌드 실행시 설정 파일 내의 변수는 환경에 적합한 설정값으로 치환됨
-환경별 설정값은 빌드스크립트에 보관됨(메이븐의 경우 프로파일 엘리먼트에)

2. 리소스 교체(replacing)
-빌드시에 기준(로컬) 설정 파일을 다른 파일로 교체하는 방법
-설정 파일을 환경별로 분리하여 관리
  (1)환경별로 별도 디렉토리를 만들어 기준 파일과 동일한 파일명으로 관리.
      예를 들어 /web/WEB-INF/web.xml 이 로컬PC용 설정파일이면,
      개발서버용 web.xml은 /conf/dev/web.xml에 두고 관리.
  (2)기준 설정파일과 동일한 경로에, 다른 파일명으로 관리.
      예를 들어 개발서버용 web.xml을 /web/WEB-INF/web.xml.dev 라는 이름으로 관리.
-빌드실행시 환경에 맞는 파일을 골라서 (1)빌드디렉토리로 이동하거나 (2)파일명을 변경하여 기준 설정 파일을 덮어씀

1번 리소스 필터링의 경우 메이븐에서는 Profile 기능과 Resource Filtering 기능을 이용하면 되고, 2번 리소스 교체의 경우 메이븐에서는 Profile 기능과 Ant의 copy 타스크 조합으로 처리할 수 있습니다. 아래는 메이븐에서 2번을 처리한 예제입니다.

... ...
<plugin>
 <artifactId>maven-antrun-plugin</artifactId>
 <executions>
  <execution>
   <id>resource-changing</id>
   <phase>process-resources</phase>
   <goals><goal>run</goal></goals>
   <configuration> <tasks>
          <copy todir="${project.build.outputDirectory}"
                    overwrite="true" preservelastmodified="true" verbose="true">
               <fileset dir="${project.build.outputDirectory}"
                          includes="**/${conf.replace.pattern}" />
                   <mapper type="glob" from="${conf.replace.pattern}" to="*" />
          </copy>
    </tasks></configuration>
  </execution>
...... .......
..... ........
 <profiles>
  <profile>
   <id>env-dev</id>
   <activation>
    <property><name>env</name><value>dev</value></property>
   </activation>
   <properties>
    <conf.replace.pattern>*.dev</conf.replace.pattern>
   </properties>
  </profile>
  <profile>
   <id>env-prod</id>
   <activation>
    <property><name>env</name><value>prod</value></property>
   </activation>
   <properties>
    <conf.replace.pattern>*.prod</conf.replace.pattern>
   </properties>
  </profile>
 </profiles>
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 에코지오

댓글을 달아 주세요



티스토리 툴바