플래시/플렉스 개발자라면 구글 크롬을 많이들 애용하실 겁니다. 그런데 어느날 갑자기 구글 크롬에 플래시 플레이어가 Release 버전이 깔려 있어 디버깅이 안되었습니다. 제가 맥 환경이라 플레이어는 오직 하나뿐이고 플래시는 브라우저 플러그인 아키텍쳐로 실행되기 때문에 사파리, 파폭은 잘 되는데 크롬만 Release로 돌아가는 것이 너무 이상했습니다.  그래서 플래시 플레이어를 지웠다 설치했다를 몇번을 반복해도 잘 안되길래 완전히 지우고 크롬을 실행해 봤습니다. 그랬더니 사파리, 파폭은 지워져서 실행이 안되는데 크롬에는 지워지지 않고 여전히 플래시 플레이어가 남아있었습니다. 

이를 해결하기 위해 구글 크롬 페이지에 가서 확인해 봤더니  5.0.360.4 부터는 플래시 플레이어가 크롬에 내장되어 나온답니다. 크롬을 쓰면 이제부터는 크롬의 플래시 플레이어가 항상 최신버전으로 유지되겠죠. 버전의 정확한 번호는 모르겠지만, 기존에는 단축 아이콘에 별도의 --enable-internal-flash 인수를 넣어야 했는데, 지금은 인수를 넣지 않아도 디폴트로 실행 되게 되어있더군요. 

구글 크롬에 플래시가 빌트인 된 부분에 대해 반감을 가지시는 분이 가끔 계실텐데, 이에대해 브라우저 플러그인 아키텍쳐로 구성되어있는 플래시 플레이어는 성능의 한계가 분명히 있고 브라우저의 자원을 사용하게 되어 이를 개선하기 위한 프로젝트의 첫 단계로써 지속적인 플래시 플레이어 관리가 초기 목표인 것으로 보아주시면 되겠습니다. 자세한건 구글 블로그의 포스트를 참고하시고... 

구글의 플래시 포함에 대한 입장:  http://googlekoreablog.blogspot.com/2010/04/blog-post_05.html
(사실 플래시의 2D 렌더링 퍼포먼스는 OS,브라우저마다 다릅니다. 그만큼 브라우저의 영향을 많이 받습니다. 심지어 플래시 플레이어 10의 텍스트 엔진이 맥의 사파리,크롬(웹킷) 에서는 아직 한글입력이 제대로 안됩니다. 그래서 맥에서 한글 테스트를 해보려면 파이어 폭스를 써야 합니다.)

그럼 이제 우리 개발자들은 크롬의 빌트인 플래시 플레이어가 아직은 필요가 없으니, 이걸 비 활성화 시켜보겠습니다. 
  1. 브라우저 주소창에 chrome://plugins 를 입력합니다.
  2. 플러그인 리스트가 나옵니다.
  3. 자세히 보시면 플래시 플레이어가 2개가 보일 것입니다.
  4. 이중에서 크롬이 설치된 폴더에 있는 플래시 플레이어를 disable 해 줍니다.
  5. naver나 daum에 들어가서 디버거로 실행 되고 있는지 확인해봅니다.

이걸로 삽질 하는 분이 한분이라도 없길 바라면서...

TRACKBACK ADDRESS : http://drumcap.com/trackback/82 관련글 쓰기

댓글을 달아 주세요

  1. hika 2010/06/28 15:44  댓글주소  수정/삭제  댓글쓰기

    큰 도움이 되었습니다!!!!

  2. jin_u 2010/07/04 02:53  댓글주소  수정/삭제  댓글쓰기

    호.. 좋은 정보! 내 것도 살펴보니...

    크롬플러스 (1.4.0.0), 크롬 버전 ver 5.0.375.38 인데, 아래와 같이 플래시보다 더 높은 걸 사용하고 있네?? Flash Player 업뎃 받아야 겠넹. ㅋ

    Shockwave Flash - 버전: 10,1,53,38
    설명: Shockwave Flash 10.1 r53
    위치: C:\Program Files\ChromePlus1.4.0.0\1.4.0.0\gcswf32.dll

    Shockwave Flash - 버전: 10,1,52,14
    설명: Shockwave Flash 10.1 r52
    위치: C:\WINDOWS\system32\Macromed\Flash\NPSWF32.dll

  3. 워니 2010/07/07 08:59  댓글주소  수정/삭제  댓글쓰기

    올레~!!!!! 이것 때문에 메인 브라우저를 다시 파폭으로 가야 하나 고민 중이였는데 한방에 해결 되었네요!!! 정말 좋은 정보 감사드립니다. 구글에서 영어로 검색하다 안되서 혹시나 하는 맘에 한글로 검색했더니 한방이네요~ ㅎㅎㅎ
    호~ 그나저나 위에 리플다신 분들이 다들 유명하신 분들~~ ^^

  4. krescendo 2010/07/31 04:07  댓글주소  수정/삭제  댓글쓰기

    감사합니다. 도움이 되었습니다.

  5. 지돌스타 2010/12/17 10:51  댓글주소  수정/삭제  댓글쓰기

    ㅎㅎ 너무 좋은데요^^

  6. nurv 2010/12/31 00:00  댓글주소  수정/삭제  댓글쓰기

    오래전에 크롬의 플래시플레이어가 제거가 안되서 왜 그런지 이유를 못찾다가 포기했었는데 우연찮게 오늘 그 이유를 알게되었네요. 좋은 정보 너~무 감사드립니다.

  7. BlogIcon outlet adidas 2013/04/07 23:59  댓글주소  수정/삭제  댓글쓰기

    기쁨을 나눌 때 약속을 하지말고, 슬플때 대답을 하지 말고 분노에서 결정을 하지 말라.

  8. BlogIcon christian louboutin discount 2013/04/08 22:17  댓글주소  수정/삭제  댓글쓰기

    당신이 슬퍼 느낄 때 고통, 무슨 내용을 보려면하는 것이 가장 좋습니다. 학습은 천하무적 할 것입니다.

LCDS나 BlazeDS는 플렉스와 서버와의 통신을 도와주는 미들웨어 입니다. 여기서 서버 설정에 대한 부분은 인터넷에 널려있으니 넘어가고, 플렉스에서의 설정에 대해서만 이야기 해 보도록 하겠습니다.
플렉스 프로젝트를 만들면 RemoteObject 등을 사용하여 통신하기 위해 아래와 같이 프로젝트 생성 위자드에서 설정을 하는 과정을 거칩니다. 

그러면 빌더는 다음과 같은 프로젝트 설정 정보들을 화면에 보여주면서 LCDS/BlazeDS 등의 서버 기술을 사용할 수 있게 도와 줍니다.

 

차례대로 설명하면, 서버 탭에 생긴 정보들은 빌더에서 사용하는 정보로써, 이 정보를 참고하여 플래시 빌더4의 서비스 생성 위자드, 컴파일, 실행 등을 매끄럽게 할 수 있습니다. 
컴파일러 탭의 Additional Compiler Arguments 항목에 –services 에 LCDS/BlazeDS의 서비스 xml 이 지정되어 있는 것을 보실 수 있습니다. 이것은 컴파일 시에 해당 서비스 xml 정보를 플래시 안에 넣기 위함이며, 컴파일러가 알아서 해 줍니다. 공동 작업 시에는 이 services 컴파일러 아규먼트가 달라서 개발자마다 이 정보를 변경해 줘야 했습니다.

여기서 고민이 생겼습니다.
개발자마다 파일은 같지만 위치가 다르다고 해서 설정을 바꾸는 수고를 매번 해야할까? 라고 말이죠. 이것으로 쏠쏠하게 세팅할 때마다 불려 다니곤 했습니다.

해결책1. RemoteObject에 endpoint 속성을 매번 넣어주기

사실 RemoteObject 클래스에는 endpoint 라는 속성이 있는데, 여기에 해당 서비스의 endpoint 를 아래와 같이 지정해 주시면 됩니다. 다만, RemoteObject 선언할 때 매번 설정해 줘야겠죠


해결책2. 직접 services-config.xml 정보를 넣어주기.

위와 같이 일일이 설정하는 것은 답이 아니라 생각해서 컴파일러 아규먼트에 촛점을 맞춰 해결책을 강구해 봤습니다. 이 아규먼트가 들어감으로 해서 어떤 일이 생기는지 분석해 보면 자연스레 해결될 것이니까요. 그래서 컴파일러 아규먼트에 -keep을 추가해서 mxml에서 생성되는 as 클래스들을 찾아 하나하나 자세히 분석해 보았습니다. 그랬더니 의외의 결과가 나왔는데, 컴파일러는 –services 아규먼트를 지정하면 부가 코드를 여럿 생성하지만 가장 중요한 부분이 지정한 xml을 읽어와 mx.messaging.config.ServerConfig 클래스의 스태틱인 xml속성에 넣어주는 것 밖에 없었습니다.

궁금하시면 컴파일러 아규먼트 –services 를 지정하셨다면 아래와 같이 해 보세요. services-config.xml 설정 정보가 쫙 펼쳐져 보일 것입니다.

trace(ServerConfig.xml.toXMLString());

결론은 간단합니다. 글을 장황하게는 썼지만 그냥 다음과 같은 간단한 클래스를 만들어 mxml코드에 넣어주기만 하면 됩니다. 초기화 시에 서비스를 다녀와야 할 일이 있다면 as 코드에 직접 설정정보를 예제와 같이 넣으시고요. 아니라면 xml를 읽어온 이후에 서버의 타이밍에 따라 다르지만 대체로 applicationComplete 이벤트 디스패치 된 이후에 세팅완료 됩니다. RemoteObject 에서 endpoint를 찾을 수 있습니다.

LcdsServiceInitializer.as
package
{
	import mx.core.IMXMLObject;
	import mx.core.mx_internal;
	import mx.messaging.config.ServerConfig;
	import mx.rpc.AsyncToken;
	import mx.rpc.Responder;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.HTTPService;

	use namespace mx_internal;

	/**
	 * LCDS , BlazeDS의 Services Config를 컴파일러에서 세팅하지 않고 
	 * 동적으로 세팅하게 해 주는 초기화 클래스
	 *  
	 * @author Yun Dosun
	 */
	public class LcdsServiceInitializer implements IMXMLObject
	{
		//-----------------------------------------------------------
		//
		// Constants
		// 
		//-----------------------------------------------------------
		private static const DEFAULT_XML_LOCATION:String = "config/services-config.xml";
		private static const DEFAULT_SERVICES:XML = 
				
					
						
							
						
					
				
				
					
						
							
						
					
				
				
				
				
					
						
						
							true
							4
						
					
					
						
						
						
					
					
						
						
						
					
				
			;


		/**
		 * IMXMLObject 를 구현한 클래스 (MXML에서 세팅한 속성값 적용을 위한 목적)
		 * @param document
		 * @param id
		 */
		public function initialized(document:Object, id:String):void
		{
			this.document = document;
			this.id = id;

			setROService();
		}

		/**
		 * configPath 설정파일 경로에서 잘 찾아오면 그 값으로, 
		 * 설정파일이 없으면 기본 설정정보로 셋  
		 */
		private function setROService():void
		{
			var service:HTTPService = new HTTPService();
			service.url = configPath;
			service.resultFormat = "e4x";

			var resultFunc:Function = function(event:ResultEvent):void
				{
					var xml:XML = event.result as XML;
					ServerConfig.xml = xml;
				}

			var faultFunc:Function = function(event:FaultEvent):void
				{
					ServerConfig.xml = DEFAULT_SERVICES;
				}

			var responder:Responder = new Responder(resultFunc, faultFunc);

			var token:AsyncToken = service.send();
			token.addResponder(responder);
		}

		//--------------------------------------------------------
		//
		// Variables
		// 
		//--------------------------------------------------------

		mx_internal var document:Object;
		mx_internal var id:String;

		/**
		 * services-config.xml(플렉스용) 파일의 경로
		 * @return 
		 */
		public function get configPath():String
		{
			var ret:String = _configPath;

			if (!_configPath)
			{
				ret = DEFAULT_XML_LOCATION;
			}

			return ret;
		}
		private var _configPath:String;

		/**
		 * services-config.xml(플렉스용) 파일의 경로
		 * @param value
		 */
		public function set configPath(value:String):void
		{
			if (_configPath == value)
			{
				return;
			}
			_configPath = value;
			
			setROService();
		}
		
		/**
		 * 현재 어플리케이션에 설정 되어있는 services-config 정보
		 * @return 
		 */
		public function get serverConfigXml():XML
		{
			return ServerConfig.xml;
		}
	}
}
main.mxml


	
		<![CDATA[
			import mx.rpc.CallResponder;
			import mx.rpc.events.FaultEvent;
			import mx.rpc.events.ResultEvent;

			import volcano.uxsb.platform.utils.RemoteObjectHelper;

			private var cr:CallResponder;

			protected function datagrid1_clickHandler(event:MouseEvent):void
			{
				cr.token=RemoteObjectHelper.sendRemote(new Object, "getData111", "drumcap");
				cr.addEventListener(ResultEvent.RESULT, onResultEventHandler);
			}

			private function onResultEventHandler(event:ResultEvent):void
			{
				trace("result===", event.result);
			}
		]]>
	

	
	

	


TRACKBACK ADDRESS : http://drumcap.com/trackback/81 관련글 쓰기

댓글을 달아 주세요

  1. hika 2010/06/23 00:15  댓글주소  수정/삭제  댓글쓰기

    와 오랜만에 포스팅. 역시 모임에서 한마디 건내드린게 효과가 있었던건가요 ^^

    • BlogIcon 드럼캡 2010/06/24 11:57  댓글주소  수정/삭제

      ^^ 저는 블로그에 글을 올리기가 트위터만큼 편하게 쓰지는 못하겠어요. 블로그를 편하게 만들어 볼까도 고민중이구요. 제가 사진과 음악에도 관심이 많거든요. 기록이 휘발성이 아닌 블로그가 더 좋은것 같기도 하고요 ^^

  2. 지돌스타 2011/08/18 17:13  댓글주소  수정/삭제  댓글쓰기

    와~ 이런 글을 이제야 보다니 ^^