달력

5

« 2024/5 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
2011. 5. 18. 15:40

SWF 파일 사이즈의 축소 Enjoy/FLEX2011. 5. 18. 15:40


출처 : http://loudon23.blog.me/30034697717


 <?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
    <mx:Button label="버튼"/>
</mx:Application>

 

위의 코드를 실행 해 보면 용량이 243,860 bytes 이다. 

웹서비스에 올리기에는 단지 버튼 하나 들어갔을 뿐인데 용량이 꽤 크다;;

 

그래서 최적화 해보려고 정보를 찾아 봤다.

 

Flex 3 Help 내용을 보니

(http://livedocs.adobe.com/flex/3/html/performance_06.html#208825)

  1. 바이트 코드 옵티마이져 사용
  2. 디버그의 무효화
  3. strict 모드사용
  4. 링커의존 확인
  5. 사용하지 않는 클래스의 초기화의 방지
  6. 어셋의 외부화
  7. 매입 폰트에 대한 문자범위의 사용

이러한 방법이 있다고 한다.

 

그래서 하나씩 테스트 해보면서 용량 비교를 해봤다.

 

1. 바이트 코드의 옵티마이져 사용

바이트 코드 옵티마이져는  "플렉스 최적화 응용 프로그램의 합병과 구멍을 바이트 코드를 사용하여 swf 파일을 최적화합니다. 바이트 코드에서 중복을 제거 지침을 구멍을 최적화합니다.(The bytecode optimizer can reduce the size of the Flex application's SWF file by using bytecode merging and peephole optimization. Peephole optimization removes redundant instructions from the bytecode.)"  라고 하는데.. 뭔말인지 모르겠음;;;

 

사용방법 :

 mxmlc -optimize=true MyApp.mxml

 

용량비교

  • -optimize=true : 243,860 bytes 
  • -optimize=false : 284,336 bytes
    사용 한것과 안한 것의 차이가 40,000 bytes(약 15%) 정도 난다.

참고

  optimize 옵션은 기본값이 true 상태임. 구지 mxmlc 에서 설정 할 필요 없다는 말;;

 

 

 

2. 디버그의 무효화

VC++ app들을 보면 릴리즈버전과 디버그 버전을 만들수 있듯, swf도 마찮가지다. 릴리즈 버전으로 제작을 하면 용량이 줄어 든다.

 

사용방법 :

 mxmlc -debug=true MyApp.mxml

 

용량비교 :

  • -debug=true : 243,860  bytes (디버그 버전)
  • -debug=false : 150,645  bytes (릴리즈 버전)
    디버그 버전을 포함하면 93,215 bytes (약 40%) 정도 늘어난다.

참고

debug 옵션의 기본값은 mxmlc 컴파일러는 false, compc 컴파일러는 true 이다.

flex 빌더의 경우 기본값이 true이다.

 

* mxmlc(어플리케이션 컴파일러) - ActionScript 및 MXML 등의 원시 파일로부터 SWF만들 때 사용

* compc(컴퍼넌트 컴파일러) -  컴퍼넌트 원시 파일, 이미지, 스타일 시트등의 어셋 파일로부터 SWC 파일을 생성하는 경우에 사용

 

 

3. strict 모드 사용

strict 컴파일러 옵션을 true로 설정하면, 컴파일러는 import 된 패키지들이 사용되고 있는지를 검증합니다. import한 클래스가 사용되지 않는 경우에 컴파일러는 에러를 보고합니다.  그리고 컴파일시 타입의 체크도 실시합니다.

 

사용방법 :

 mxmlc -strict=true MyApp.mxml

 

용량비교 :

  • -strict=true : 243,860 bytes
  • -strict=false : 245,777  bytes
    strict 모드 사용 안한것에 비해 사용 한것이 1,917 bytes (약 1%)가 줄어든다.

 

4. 링커의존 확인

swf파일 사이즈를 축소하는 방법을 찾아 내려면 swf 파일에서 쓰이고 있는 actionscript 클래스의 리스트들을 확인 합니다. 확인 후에 원인이되는 링커의존관계를 끊고, 새로운 코드를 작성 합니다.

 

사용방법 :

 mxmlc -link-report 리포트파일명 MyApp.mxml

 

이 옵션을 실행하면 '리포트파일명'으로 된 파일이 하나 생성된다.  해당 파일을 열어보면 swf 파일 내에서 쓰이고 있는 actionscript 클래스 리스트들을 확인 할 수 있고. 해당 클래스들의 의존관계를 볼 수 있다.

 

like-report 파일 내용

<script name="C:\flex3sdk\frameworks\libs\framework.swc(mx/skins/ProgrammaticSkin)" mod="1141055632000" size="5807">
    <def id="mx.skins:ProgrammaticSkin"/>
    <pre id="mx.core:IFlexDisplayObject"/>
    <pre id="mx.styles:IStyleable"/>
    <pre id="mx.managers:ILayoutClient"/>
    <pre id="flash.display:Shape"/>
    <dep id="String"/>
    <dep id="flash.geom:Matrix"/>
    <dep id="mx.core:mx_internal"/>
    <dep id="uint"/>
    <dep id="mx.core:UIComponent"/>
    <dep id="int"/>
    <dep id="Math"/>
    <dep id="Object"/>
    <dep id="Array"/>
    <dep id="mx.core:IStyleClient"/>
    <dep id="Boolean"/>
    <dep id="Number"/>
    <dep id="flash.display:Graphics"/>
</script>

 

link-report 파일 내의 태그 설명

  • 태그명 - <script>
  • 설명 -  어플리케이션의 SWF 파일 작성에 사용되는 컴파일 단위명을 나타냅니다.컴파일 단위는 클래스, 함수, 이름 공간등의 일반 정의를 1 개이상 포함합니다.
    name 속성에는 스크립트의 격납원이 표시됩니다. 원시 파일 또는 SWC 파일(frameworks.swc 등)로 나타납니다.
    커멘드 라인으로 keep-generated=true 와 설정하면, 생성된 폴더의 모든 클래스가 이 파일의 스크립트로서 리스트 됩니다.
    size 속성에는 클래스의 사이즈가 바이트 단위로 나타납니다.
    mod 속성은 스크립트가 작성되었을 때의 타임 스탬프를 나타냅니다.
  • 태그명 - <def>
  • 설명 - 스크립트, 클래스, 함수 네임스페이스 등의 이름을 정의 합니다 
  • 태그명 - <pre>
  • 설명 - 현재의 정의를 링크 하기 전에 SWF 파일에 링크 할 필요가 있는 정의를 나타냅니다. 이 태그는 전제 조건을 의미합니다.
    클래스 정의의 경우, 이 태그는, 직접적인 부모클래스(flash.events:Event 등) 및 그 클래스를 구현하는 모든 인터페이스(mx.core:IFlexDisplayObject,mx.managers:ILayoutClient 등)을 나타냅니다.
  • 태그명 - <dep>
  • 설명 - 이 정의가 의존하고 있는 그 외의 정의를 나타냅니다(String,_ScrollBarStyle,mx.core:IChildList 등).
    이것은, 현재의 스크립트가 필요로 하는 정의에의 참조입니다. 
    다른 정의에 의존하고 있지 않는 스크립트 정의도 존재하므로 <script> 태그에 <dep> 자식 태그가 없는 것도 있습니다.
  • 태그명 - <ext>
  • 설명 - 링크 되지 않았던 어셋에 대한 의존을 나타냅니다.
    external-library-path,externs, 또는 load-externs 컴파일러 옵션을 사용해 어셋을 SWF 파일에 추가하면 이러한 의존관계(dependencies)가 링크 리포트에 표시됩니다.

 

5. 사용하지 않는 클래스의 초기화 방지

쉽게 말하자면 쓰지 않는 컨트롤을 swf에 로드 하지 마라는 말입니다.

아래의 예는 어플리케이션 전체에서 DataGrid 컨트롤이 없어도 DataGrid을 강제적으로 swf 파일에 포함하고 있습니다.

 <?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
 <mx:Script>
  <![CDATA[
   import mx.controls.DataGrid;  // 쓰지 않는데 import 되어 있음
  ]]>
 </mx:Script>
 <mx:Button label="버튼"/> 
</mx:Application>

 

용량비교 :

이것은 strict 모드로 하고 있으면 용량 비교가 되지 않는다. 이유는 위에 있는 strict를 보면 쓰이지 않는것은 애초에 포함을 안시키기 때문이다. 그래서 strict 모드를 끄고 테스트 하였다.

  • 쓰지 않는 DataGrid 임포트 전 - 245,768  bytes
  • 쓰지 않는 DataGrid 임포트 후 - 245,775  bytes 
    별차이를 모르겠음;; 테스트 잘못했는가??

 

6. 어셋의 외부화

Flex 어플리케이션으로 사용되는 외부화의 방법은 여러가지가 있습니다. 예를 들면, 다음과 같은 방법이 있습니다.

  • 모듈을 사용한다
  • 실행시 스타일 시트를 사용한다
  • 런타임 공유 라이브러리(RSL)을 사용한다
  • 어셋을 임베드 하지 않고 실행시에 로드한다

swf내에서 비트맵 이미지를 많이 포함 하고 있으면 당연히 용량이 커진다. 용량을 줄이기 위해서 실행시에 로드하도록 만들어야 한다. 

 <?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
   <!--

        <mx:Image source="http://imgnews.naver.com/image/001/2008/08/13/PYH2008081400270005100_P2.jpg" />

    -->
   <mx:Image source="@Embed(source='../assets/PYH2008081400270005100_P2.jpg')"/> 
</mx:Application>

 

이 코드에 보면 위에 꺼는 외부에서 불러오는것이고 아래 것은 swf에 임베드 하는것이다.

 

용량비교 :

  • 이미지 파일의 크기 - 31,648  bytes
  • 실행시 로드 - 252,853  bytes
  • 어셋 매입 - 285,559  bytes 
    어셋 매입에 비해 실행시 로드가 32,706 bytes(약 10%) 줄었다.

 

7.  매입 폰트에 대한 문자 범위의 사용

매입 폰트의 쓰이는 글자 범위를 지정하여 폰트 사이즈를 작게 하는 방법이다.

문자 범위는 flex-config.xml 또는 각 MXML 파일의 font-face 선언으로 설정 할 수 있다.

문자범위는 유니코드 값을 사용하고 개별 문자 또는 문자 범위를 지정가능하다.

 

지정방법 :

  css를 통한 방법

 @font-face {
    src:url("../assets/MyriadWebPro.ttf");
    fontFamily: myFontFamily;
    unicodeRange:
        U+0041-U+005A, /* Upper-Case [A..Z] */
        U+0061-U+007A, /* Lower-Case a-z */
        U+0030-U+0039, /* Numbers [0..9] */
        U+002E-U+002E; /* Period [.] */
}

 

 flex-config.xml 파일을 통한 방법

 <language-range>
    <lang>Latin I</lang>
    <range>U+0020,U+00A1-U+00FF,U+2000-U+206F,U+20A0-U+20CF,U+2100-U+2183</range>
</language-range>

 

 

용량비교 :

다음의 코드를 통해서 용량 비교를 테스트 했다.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
 <mx:Style>
  @font-face {
   src:url("../assets/tunga.ttf");
   fontFamily: tunga;   
   unicodeRange:
          U+0030-U+0039, /* Numbers [0..9] */
  }
 </mx:Style>
 <mx:Label text="1234567890" fontFamily="tunga" />
</mx:Application>

 

문자범위 지정 전 - 267,509  bytes

문자범위 지정 후 - 248,529  bytes

지정 전 보다 지정 한 후가 18,980 bytes (약 8%)정도 용량이 줄었다.

 

 

 

 

 

여러가지 방법이 있지만 이중에서 내가 느끼기엔 가장 효율이 좋은것은 어셋의 외부화이다. 그중에서도 특히 어셋의 외부화 - 런타임 공유 라이브러리(RSL)을 사용하는 것이다.  

RSL는 공통으로 쓰는 공유 라이브러리를 런타임때 호출 하는 방식이다. 윈도우에서 따지자면 공유 DLL 같은 방식이다. 

이것을 swf에 적용 한다면, FLEX에서 쓰는 Framework를 외부 파일로 빼내서 런타임때 불러서 쓰는 것이다.  뭐... 다르게 말하자면 .net framework 처럼 쓴다고 할까나?? (맞는 비유일까;;;)

:
Posted by 라면스프