프로그래머의 일상: 다시 ActionScript 삽질

사실 이건 ActionScript 2.0 이라서 하는 삽질이지만.

예전에 했던 작업을 동면에서 깨워, 다시 진행해야하는 상황이 되었다(이미 2.x주 전의 얘기). 그래서 요즘 C++ + ActionScript(2.0; Flash 8) 으로 작업하고 있는데, 나는 플래시 저작툴 라이센스가 하나도 없어서 MotionTwin 의 툴셋을 쓰고 있다. 덤으로 ASUnit 2.5 도 다시 끄집어 내서 사용 중.

예전에 Flex 로 액션스크립트 테스트를 한다는 글을 읽고, 다음에 이 쪽을 또하면 이용해보자란 생각을 했었다. 그렇지만 여전히 ActionScript 2.0 (≠Flex SDK)라서, 이걸 사용하는건 불가능.

일단 현재 테스트하는 환경/상태는 다음과 같다.

  • 수 개의 .as 파일에 대해, 이 파일 중 변경 사항이 있으면[1] , msbuild 를 실행시켜서 .swf 를 빌드해낸다.
  • msbuild는 .swf를 빌드하고, 이걸 특정 디렉토리로 복사한다.
  • python으로 작성한 웹 서버는 특정 디렉토리에 있는 파일들을 서비스하게 동작.
  • 웹 페이지 하나에 .swf 들을 embed 로 연결하고, 이 페이지에 http meta tag 중 refresh 태그를 이용해서 30초마다 다시 실행

그리고 조그맣게 띄워놓은 웹 브라우져로 실행 결과를 지켜보고 있다. 그러니까 아직 CI 툴에 붙일 수 없는 상태(=커맨드라인 실행이 불가능한 수준).

이에 대한 앞으로의 개선책(?)은 아래 정도. 처음 두 개는 @oscarplex 님의 조언을 듣고 정리한 것.

  • 테스트 결과를 받는 (python) 웹 서버를 하나 짜고, 이 서버가 정해진 형태로 유닛테스트 이름과, 결과를 받아서 (xml) 파일로 내보내는 방법
  • (웹브라우져에서) 출력하는 부분을 API hooking해서 내보내는 방법
  • 웹브라우져에서 드래그&복사는 되는걸로 봐서, 이걸 어떻게 자동화해버리는 방법

사실 1이 간단해보이는데(AS 2.0 통신용의 각종 모듈은 다 짜놨으니), 이거 다음주에 전달해주고나면 끝날지도 모르는데?[2]

고향에 놋북 들고왔으면 후다닥 짜버리면 땡인데 안들고왔으니 Orz.

ps. 사실 시간이 한 4주쯤 여유가 있으면 Python으로 ActionScript 코드 토해내게 짜버리고 싶다(…).

  1. 사실 파일 변경 시간(mtime)이 정해진 몇 개의 .swf 보다 최신인 파일이 있다면 []
  2. 하지만 난 2 년 쯤 전에도 이 생각을 했지 []

Adobe FlashSocketPolicyDaemon (python) 코드의 버그

예~~~~전에 작성한 ActionScript 코드 및 이것과 통신하는 C++ 서버 코드가 있는데, 이걸 다시 창고(…)에서 꺼낼 일이 생겼다. 전부 다시 빌드하고 – 그동안 라이브러리는 업데이트 되었는데, 이 녀석은 손 안 대서 수정할 게 좀 있더라 – 테스트 코드를 돌리기 위해서 python 서버들을 띄우고, C++ 서버를 띄우고, 테스트 클라이언트(.swf)를 연결했다.

그런데 소켓 정책 파일(flash socket policy file)을 얻어오지 못하는 게 아닌가?[1]

한참 고민하고 + 코드 리뷰하고 나서야 문제를 파악했는데, 내 C++ 코드나, ActionScript 적응단 문제가 아니라 Adobe 에서 제공하는 flashsocketpolicyd 의 python 구현체 일부에 문제가 있는 코드가 있었다.

class policy_server(object):
  def __init__(self, port, path):
    self.port = port
    self.path = path
    self.policy = self.read_policy(path)
    self.log(‘Listening on port %d\n % port)
    try:
      self.sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
    except AttributeError, socket.error:
      # AttributeError catches Python built without IPv6
      # socket.error catches OS with IPv6 disabled
      self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

IPv6 (AF_INT6) 로 소켓을 열어보고, 안되면 IPv4 (AF_INET) 로 소켓을 여는 구현인데, 문제는 Windows 나  일부 UNIX 구현체 들 중 일부는, IPv6 소켓이 IPv6 스택만 지원하는 형태로 여는 게 기본 값이라는 것. 덕분에 IPv4 스택을 이용하는 클라이언트 프로그램(=flash player) 랑 통신 못하는 것. 야 임마 ㅠㅠ

이게 예전에는 잘 되었던 이유는, WinSock을 사용하는 경우, 듀얼 스택 자체를 XP/2003 서버까지 지원하지 않았고 예전에는 Windows Server 2003(x64) 에서 작업했기 때문. 덕분에 try 에서 항상 예외가 나서 IPv4 소켓을 생성했기에 잘 돌았지만, Vista x64를 쓰는 지금에 와서 빵 터진 듯 Orz

듀얼 스택 지원 부분을 저렇게 안일하게 구현하면 안되지. 아무리 reference code 수준이 될까 말까한 거라곤 해도 이건 좀 아니지 않나?

  1. 게다가 예전에도 언급했지만, 소켓 정책 서버에서 파일을 못 가져오면, 처음 붙는 소켓에 또 요청을 날리기에 C++ 서버는 예상치 못한 XML 요청을 받게 된다. =_= []

CI에 ActionScript Unit test 포함하기

Google Testing Blog에도 자주 글을 쓰고 있는, 구글 안에서 자동화된 테스팅 쪽에서 일하는 Miško Hevery의 글: CI 빌드에서 어떻게 Flex Unittest를 하는가

 

내용은 간단(?)하다. Adobe AIR 라는 플래쉬 플레이어가 있다(이쪽에 친숙한 사람들이라면 다들 알듯). 이걸 써서 CI(continuous integration) 툴 쪽에서 빌드할 때, 

  • Flash(actionscript) 혹은 flex 응용(이 경우엔 UnitTest)을 만들어내고(adobe air용으로)
  • 이 UnitTest를 실행하고 실패한 테스트 갯수를 세서 CI 툴에 반환하고(프로그램 종료 코드로),
  • 덤으로 XML 파일로 테스트 리포트도 보내버리기

라는 것. 사실 첫번째는 별거 아니고(CI 쪽 툴 좀 만져봤으면 뻔하고+ 자동화된 빌드야 뭐…), 두번째랑 세번째는 Adobe Flash Player의 기본적인 특성, 즉 안-_-전-_-한 샌드박스 위에서 동작하기 때문에 손댈 수 있는게 거의 없다는 점을 피할 수 있어서 가능한 것. Adobe AIR는 샌드박스 위에서 도는게 아니기 때문에, 파일도 쓸 수 있고(=즉 XML 출력도 되고)해서 문제를 피해간다는 것.

 

저 글을 읽고나니, 이젠 나랑 (아마도) 관련없는 프로젝트지만 예전에 ASUnit 이란 ActionScript 용 유닛 테스트 쓰던 기억이 나서 끄적끄적.

 

+ 생각없이 또 읽다보니, Adobe AIR엔 WebKit[1] 이 포함되어 있어서 JavaScript 쪽의 UnitTest도 CI에 합칠 수 있다고 한다. 이건 내 쪽에선 관심이 적은 동네지만 누군가는 관심을 가질듯도 :P

  1. Apple의 Safari, 구글의  Chrome 웹브라우져에서 사용되는 렌더링 엔진 []

C/C++ on Adobe Flash

via DDJAdobe Alchemy

농담이 아니라, Adobe Flash Player 위에서 (물론 정확히는 Adobe VM 이지만) C/C++ 로 작성된 코드가 동작하게 하는 툴인 Alchemy 가 release preview로 나왔다. DDJ에 나온 내용을 따오자면,

Alchemy, which can be downloaded here is primarily intended to be used with C/C++ libraries that have few operating system dependencies. Targeting computation-intensive use cases, such as audio/video transcoding, data manipulation, XML parsing, cryptographic functions or physics simulation, performance can be considerably faster than ActionScript 3.0 and anywhere from 2-10x slower than native C/C++ code. Alchemy is not intended for general development of SWF applications using C/C++.

C/C++ 코드를 ActionScript 3.0 기반의 바이트 코드(?)로 컴파일 해주며, 계산량이 많은 응용 — video/audio 라거나 — 등에 사용할 목적인듯하다. 당연히 Flash Player의 샌드박스를 따라가며 + native C/C++ 보다 느리다. 그렇지만 현재 엄청난 양이 존재하는 C/C++ 코드 베이스를 쓸 수 있다는 점에서는 상당히 고무적이다. (특히 계산량이 많은 쪽은 죄다)

Flash/ActionScript 의 속도 혹은 JS 틱한 semanitc에 괴로워했던 사람들(rein 본인이라거나)에겐 꽤나 희소식인듯 싶다.

각설하고, Alchemy를 다운로드해서 열어보니 linux 기준으로는 대략,

  • 일련의 라이브러리와
  • 일련의 C/C++ 헤더와
  • Flash 라이브러리
  • GCC toolchain을 Alchemy의 그걸로 적당히 치환하는 유틸들

을 가지고 있다.

다만 ActionScript 3.0이기도 하고, 사실상 현재로썬 experimental/unstable한 영역이라 Flash Player 10 / Adobe Air 1.5 에서만 구동 가능하다. 그리고 GCC 툴체인을 쓰기 때문에 linux/MacOSX에서는 그냥 되지만 Win32 환경에서는 cygwin이 필요하긴하다(…).

Flash Socket Policy 설정

Adobe Flash의 소켓 정책(socket flash or flash policy or cross-domain (socket) policy)은 Flash Player 의 소켓 연결과 관련된 보안 정책을 처리하는 방법을 기술한다. 특히 이종 도메인간의 연결은 이 것 없인 불가능하다.

이런걸 기술하는 파일의 정식 명칭은 corss-domain policy file 이며, 여러개의 도메인에 걸쳐 데이터를 가져올 수 있게[1]어떤 의미론 통신할 수 있게 — 해주는 기능을 한다.
물론 이 기능 때문에, 예전에 Flash 소켓 정책이 돌아가는 구조를 몰랐을 때 삽질했던 적이 있다

Terminology

즉 web.upnl.org 에 서비스되고 있는 플래쉬 파일이 app1.upnl.org에 접속하려는 경우 web.upnl.org 가 현재 도메인(source domain)이 되며, 이 서버에서 다운로드 받은 some.swf 파일이 접근하는 (데이터/응용서버) app1.upnl.org 가 remote domain이 된다. 

이 때 some.swf 파일을 app1.upnl.org 에 도메인간 정책 파일을 요구하고, 이 파일이

“web.upnl.org”로 부터의 접속을 나의 이런이런 포트로 허용한다

같은 형식인 경우에만 Flash Player가 실제로 접속을 허가한다.

 

Historical notes

Flash 9의 일정 버젼까지는 http://app1.upnl.org/crossdomain.xml 처럼 루트 디렉토리의 crossdomain.xml 파일로 지정되는 파일에 정의되었다. 그리고 1024번 보다 상위 포트로는 (즉 non-priviliged ports로는) 접속이 가능했었다. 그러나 이게 9.0.124.0 이후로 변경됨 (모든 포트에 정책 파일이 필요)

그리고 현재(Flash 9)엔 IANA와의 협의에 의해 843 번 포트를 사용하기 시작하였다.

 

실제로 동작할 때의 접속 순서

  1. some.swf 파일이 로드되면, 843 번 포트로 <policy-file-request/>\0 라는 메시지를 보낸다.[2] 이게 실패하거나, 성공했는데도 site-control이 all인 경우, 다음으로 간다.
  2. Security.loadPolicyFile() 명령이 들어있고, 이게 어떤 검사할 위치를 주는 경우 그 파일을 가져온다. 다만 1이 실패한 경우에만임에 주의
  3. 접속한 소켓에, 접속한 순간에 <policy-file-request>\0 를 전송하고 응답을 기다린다. 첫 응답은 text/xml 의 정책 파일이어야 함.  

 

Terminology에 따른 설정

일단 3을 막아야 서버는 독립적으로 짤 수 있다. 즉 XML Socket을 일반적인 TCP 소켓처럼 쓰는 걸 짜야했던 내 경우엔 정말 그렇게 해야한다. 물론 XML 기반의 처리라면 그냥 받아서 처리해도 편하겠지만.

다음은 위의 용어 설명에서 썼던 관계에서 정의될 만한 것.

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd">

<cross-domain-policy>
    <site-control permitted-cross-domain-policies="master-only"/>
    <allow-access-from domain='web.upnl.org' to-ports="4000,4001,4002,4020-4060"/>
</cross-domain-policy>

같은 식으로 하면 web.upnl.org 에서 다운로드된 some.swf 가 app1.upnl.org 의 4000~4002, 4020~4060에 접속할 수 있게 된다.

저기서 도메인을 앗싸리(…) *.upnl.org 같은 꼴을 할 수도 있지만, 그건 비권고 사항 중 하나. * 도 가능하지만 그건 정말(…).  ((사실상 한단계 걸러줄 수 있는걸 뚫어놓은 결과니 + 나중에 처리는 해야겠지만 개발단계라면 모를까 굳이 막을 수 있는걸 안 막을 이유는 없는듯.))

물론 이 policy file이 서비스되어야 하는 위치는 app1.upnl.org 라는 사실엔 두말할 여지가 없는듯… [3]

덤으로 소켓이 HTTPS 일지 여부(SSL사용)도 지정할 수 있지만 내가 신경쓸 범위가 아닌 (개발이 아닌 publish-issue) 거라 그냥 생략.

site-control

site-control 은 플래쉬 정책 파일이 허용되는 위치 — 즉 casecade되어 허용될지/말지 등등 — 에 관한 사항을 설명한다

allowed-access-from

개인적으로 헷갈리는 태그 명인데 -_-; “저기서 언급된 도메인에서 다운로드된 플래쉬 파일을 저 파일이 있는 서버의 특정 포트에 접근하게 해준다” 는 의미다.

즉 저 위에선, web.upnl.org 에서 온 파일이면 to-ports 밑에 언급된 포트로 접근가능하다는 의미. [4]

그림으로 따지면 adobe.com에서 가져온 다음 그림의 프로세스를 따라간다고 생각하면 쉽다.

 


이 이미지의 저작권은 Adobe Systems Inc.에 있습니다.

 

Reference

  1. 예를 들어 예전에 포스팅했던 UNIQLO의 광고 같은 경우 전체 데이터를 다 가지고 있는 건 좀 말이 안된다. 네트웍 대역폭을 잡아먹긴 하겠지만, 일종의 플레이어가 다운로드 되고, 그 플레이어가 해당 플래쉬 파일이 있던 서버가 아닌 다른 서버에 접속해서, 스트리밍 동영상을 가져오는게 말이 될 것이다. []
  2. XMLSocket의 관례인지 뒤에 NULL이 붙는다. 위에서 나오는 <policy-file-request/>\0 는 일단 문서에 따르면, 더 늘어나거나 줄지 않는다. 다만 이걸 수정해서 보내게 만들 수도 없다 :P []
  3. 방법이야 위에서 쓴 843 포트에 XMLHTTPRequest를 처리한다거나, 소켓의 첫 응답을 처리한다거나… []
  4. 물론 이 포트는 app1.upnl.org에 열린다 []

ASUnit 사용기

이름만으로도 반쯤 알 수 있는 프레임웍 — ActionScript (2.0, 3.0 모두 지원) 기반의 xUnit 류의 유닛테스트 프레임웍이다.

몇 일간 써본걸 토대로 간략히 장단점을 논하자면.

장점

xUnit 류의 인터페이스라는 것. 덕분에 xUnit 계통을 다른 언어에서 써본 사람이라면 일단 한 번만 전체 구성이 나오면, 별 어려움없이 바로 사용할 수 있다. setUp(), test테스트이름(), tearDown() 으로 이어지는 테스트 준비, 개별 테스트, 테스트 뒷처리의 형태는 일단 익숙하고 / 바로 사용할 수 있어서 상당한 장점이라고 생각한다.[1]

ActionScript 에서 간략한 수준의(…) reflection을 사용할 수 있기 때문에, 그걸 이용해서 test???() 인 함수들은 전부 실행되서 C++ 에서처럼 복잡하게 (내부적으로) 테스트들을 등록시키는 수고는 던다.

Adobe의 Flash 제작툴이나 Flex Builder와도 연동이 가능하며, 현재 사용 중인 ActionScript 컴파일러인 mtasc 에서도 무난히 동작한다. 그리고 나름대로(?) xUnit의 상징인 녹색바도 볼 수 있다(?).

단점

ActionScript 자체의 단점과 맞닿아있는 부분인데, 파일 수가 너무 많다 — 그것도 사용자가 간섭해서 만들어줘야하는 것들이 Orz.

ActionScript의 대전제(?)인 클래스당 파일 하나라는 것 덕분에 최소한 이런 수의 파일들이 생긴다.

  • TestRunner.as — 테스트를 실행해주는 스크립트. 이 녀석이 main() 역할을 한다
  • AllTest.as — 모든 테스트 케이스가 든 파일들을 열거하기 위한 녀석. 일종의 suite 느낌?
  • Test???.as — 특정 클래스를 테스트하기 위한 파일
  • 실제 클래스 — 작성할 클래스 파일.

이런 식으로 실제 클래스 / Test 클래스 쌍이 심각하게(…) 증가하게 되고, 이걸 AllTest.as 에 반영해야하는 것도 정적으로 적어줘야하는 것도 좀 스트레스. 그리고 ActionScript 최대의 문제인 (Flex 3은 모르겠고) 커맨드라인 자동화가 불가능한 것 — 결국엔 웹 브라우져 refresh 로 실행해야한다는 것.[2]

커맨드라인 인자를 받거나 할 수 없기 때문에 특정 suite이나 test-case 만 실행한다거나하는 일은 꿈에도 못 꾸고, 자동화된 테스트 리포트도 넣을 수 없다. 그래도 이런 거라도 있는게 어디야 Orz

  1. 뭐 이건 xUnit Test Framework 자체가 갖는 장점 []
  2. 다만 이 부분은 Projector 라고 부르는 exe를 자동으로 만들어낼 수 있으면 그걸 이용해서 강제로 success/fail 에 해당하는 report를 만들어낼 수도 있을 것 같다. 보안 설정도 무시할 수 있는 것 같고 []

회고: 프로젝트 A

근 5주..이젠 6주가 되어가나 동안 처음 3.5주는 그 일에만, 나머지 2 정도는 그 일과 다른 일을 진행하면서 수행한 프로젝트가 하나 있다. 편의상 프로젝트 A라고 부르자 — 사실 공식 명칭이 없거나 내가 모르거나.

평소에 프로그래밍할 때 C++/python/lua 정도를 쓰고 설정 같은 걸 lua/xml로 빼는 형식으로 주로 작업했었는데 이번에 해야했던 일은 서버는 (native) C++로, 클라이언트는 ActionScript 2.0으로 동작하는 녀석을 수정하는 일이었다.

내게 주어진 수정범위는 서버 전체 — 인터페이스와 동작 구조만 유지하는 범위에서 — 그리고 클라이언트가 통신에 사용하는 일부 코드였다. 그리고 주어진 자료는 프로토콜 문서와 서버 코드, 클라이언트의…껍데기쯤 되는 소켓 통신 부분[1]

팀에서 간단한 회의를 거친 결과 서버의 전면 개보수 + 클라이언트 소켓 부분을 서버에 맞게 수정하되 프로토콜은 유지한다라는 것. 그리고 이 프로젝트는 나 혼자 진행하게 되었다. 여튼 내가 생각하기에 내 문제였던 녀석들을 요약해보고자 한다.

의사 소통 문제

프로젝트 진행 초기에 내가 내렸던 의사 결정 중에 하나가 일종의 primary key비슷한 역할을 하는 변수의 타입을 변경한 것 이었는데 — 나는 원래 프로젝트 팀에서 내린 결정이 일종의 defect라고 생각했다 — 이게 기존 legacy 코드[2] 랑 문제가 생겨서 내 작업을 일정 부분 수정해야 했다.

아무래도 이런건 내가 의사소통을 잘못했다고 밖엔…

이종 언어 문제

처음 겪었던 문제, 그리고 끝까지 발목을 잡았던 문제는 익숙하지 않은 언어 — ActionScript 2.0 — 에서 불거져나온 이것 저것들이었다. 내가 홍민희 님의 블로그에서 “워드의 메타프로그래밍” 이란 글 — 불편한 언어를 사용할 때 그냥 사용하는게 아니라 자신에게 편의를 줄 수 있게 언어에 추가로 빌딩블럭을 쌓아 “중력을 줄여가는/언어의 장애를 줄이는” 프로그래밍을 하자는 것 — 을 일찍 볼 수 있다거나, 혹은 애자일 블로그 내용을 기억하고 있었다면[3] 참 좋았을텐데 불행히도 그렇게 일이 돌아가진 않았고, 전에 언급했던 것 처럼 C++에서 모든 프로젝트를 최대한 진행시키고, 해당 코드 베이스를 ActionScript에 반복하는 작업을 했다.

지금 다시 하라고 하면 ActionScript 코드에 더 많은 계층을 추가하지 않을까 싶다. 현재는 패킷을 받고, 이에 대한 이벤트를 전달하고, 패킷을 해석하는 계층만 있다 — 즉 프로토콜을 받아서 처리하는 콜백을 부르는 정도까지의 추상화.

테스트 케이스들도 C++쪽에 집중되어 있고… ActionScript 쪽의 제대로된 테스트 케이스도 오늘의 ASUnit 쪽으로 코드 테스트를 옮김으로써 제대로 작성된듯하다…

테스트 주도 개발

TDD(테스트 주도 개발;Test Driven Development)를 시작한건 작년 말 / 올해 초 정돈데 일단 C++ 쪽 코드 작성에서는 제대로 효과를 발휘한듯 하다. 개략적으로 defect를 찾고나서 이를 코드 베이스에 테스트 케이스로 반영하고 / 수정하고 / 다시 커밋하는데 평균적으로 1일 이하의 시간이 걸린 것 같다. 손으로 테스트 하지 않는데에서 상당히 빠른 코딩/컴파일/테스트/리포트 주기를 겪게 된 것도 같고. 다만 ActionScript 쪽의 TDD는 좀 야매였다고 생각해야한다 — .fla 파일에 assert 비슷한 함수를 만들고 그 함수에서 실패할 때마다 특정 메시지 형태로 찍게 하는 수준이었다. 지금이야 ASUnit으로 옮겨서 그런데로 볼만한 수준으로는 자동화 된 듯 하다.

UTF-8 문제

이종 언어 개발 쪽이랑 겹치는 문젠데, ActionScript 2.0에선 문자열의 bytes 길이[4] 를 바로 얻지 못하고, 그것 때문에 패킷 생성에 오류가 생기는걸 생각하지 못해서 문제가 생겼다. 사실 이건 ActionScript쪽에서 테스트를 제대로 했으면 괜찮았을텐데, C++ 쪽 테스트에서 잘 되는 것만 믿고, 그걸 포팅한 AS 2.0 코드를 제대로 된 테스트 케이스 확보도 없이 넘어간게 크나큰 패인. 덕분에 어제 오늘은 회사에서 일해야 했다…

여튼 요약.

  1. 의사 소통이 가장 중요 — 의사 소통하기 쉬운 환경 / 코드베이스도 필요
  2. 프로젝트에서 쓰는 언어의 중력을 줄여라 — 프로젝트에서 쓰는 언어가 맘에 안들면, 자신에게 우호적인 환경으로 바꿀 수 있도록 하자
  3. TDD에 맞는 툴을 우선 확보하자 — mtasc와 ASUnit을 일찍 알았으면 C++에서 테스트하려던 욕구가 줄었을 텐데

다음 프로젝트 회고는 언제하게 될까 -_-a

  1. 이게 만악의 근원이었던 것 같은 기분도 들지만 []
  2. 문제는 나는 이 코드를 받지도 못했단 말이다 Orz 클라이언트 코드 중 극히 일부(껍데기?)만 받았으니… []
  3. 저 글을 읽었을 당시엔 별 감흥이 없었는데… 지금은 뼈에 사묻힘(?) []
  4. 문자 수 길이랑 대비되는 개념. 예를 들어 “한글”이란 단어는 문자 수 길이로는 2지만, UHC(cp949 or euc-kr)에선 바이트 길이로 4, UTF-8에서는 바이트 길이로 6이다. 즉 의미론적인 길이가 문자수 길이고, 바이트 길이는 메모리에서 표현되는 길이 []

ActionScript: Shock and awe

C…더 이상 이 주제로 글을 쓰고 있지만 아마도, 그리고 기원하건데 마지막 글일 듯.

지역 변수의 스코프 문제

지역 변수의 선언이 유효한 범위(local variable scope) 가 굉장히 괴악하다. 다음은 너무나도 적절한 mtasc.com에서 제시하는 예제.

function f() {
	var x = 1;
	if( true ) {
		var x = "hello";
		// ...
	}
	trace(x+1);
}

trace 의 결과가[1] 좀 충격적이다. 일반적인 프로그래밍 언어[2] 에 익숙한 사람이라면 출력되는 결과를 “2” 라고 생각할 것이다.

하지만 결과는 hello1

생각없이 짜다 또 한 방 먹었고 Orz

문자열의 길이

문자열의 길이는 보통 두 가지 의미를 갖는다.

  • (의미 단위인) 글자 단위의 길이
  • (저수준 단위인) 메모리 상의 bytes 길이

저수준 메모리 접근이 가능하거나, 해당 추상화가 존재하는 어느 정도 성숙된 언어들 — 예를 들어 C 와 그 자손들 혹은 최근의 일부 VM 언어들(C#/Java), 혹은 python이나 PHP 같은 언어들 — 에서는 저 두 가지를 구하는 방법이 모두 존재한다.

하지만 기대를 저버리지 않고 ActionScript 에는 메모리 상의 bytes길이를 인코딩에 맞게 구하는 방법이 없다. 정말 소켓 연결해서 쓰기가 !@#$%^&* 스럽다.

UTF-8 문자의 bytes 길이 경계에 해당하는 0x7F, 0x07FF 랑 비교해서 1~3 byte(s) 로 쪼개지게해서 일일이 길이를 구하고 직렬화하게 수정해야했다 Orz[3]

  1. trace는 Debugger를 통해서만 출력이 이루어지는 함수 []
  2. C나 C++, Java, C# 같은 스코프 룰이 있는 대부분의 언어 []
  3. 어차피 이 녀석도 BMP에 있는 유니코드 밖에 지원 안하는 걸로 보인다. 유니코드 표현 형식이 ‘\unnnn’ (nnnn = 숫자) 형태인데, 네 자리만 된다면 딱 BMP만 표현되지… []