일요일 새벽에 갑자기 원격 포트가 접속이 안된다고 IDC에서 문자가 왔었습니다. 이게 무슨 일일까요...


그래서홈페이지를 들어가보니 뭐 접속이 되는데, DB데이터를 불러오는 곳에서 오류메세지가 나더라구요. 


뭐 내용은 아래와 같았습니다.


Error Code: 145. Table 'scheme.table_name' is marked as crashed and should be repaired



음.. 에러를 보아하니 꼭 테이블이 깨진 것 같단 생각이 들었습니다. 일단 테이블은 MyISAM이었습니다. 갑자기 3년 전에 InnoDB로 된 거대 테이블 하나가 깨졌을 때의 안 좋은 기억이 스믈스믈 떠오르면서 그 때에 MyISAM은 복구가 굉장히 간편하다라는 검색 내용이 생각나서 좀 검색을 해봤습니다.


http://dev.mysql.com/doc/refman/5.0/en/myisam-repair.html


다음과 같은 답변이 있더군요. 뭐 간략히 요약하자면..


콘솔창이나 workbench나 phpMyAdmin 등 SQL을 실행할 수 있는 무언가를 능력껏 구동하여,


repair table 'scheme.table_name' 을 실행하면 자동적으로 고쳐진다고 합니다. 만약 그게 안된다면 위의 링크를 참조하여 고치면 되는 것 같네요.


원격 접속 안되지, phpmyadmin 안되지, 결국은 IDC에 전화해서 원격 콘솔 열어달라고해서 했습니다 -_-


보통 이 문제는 서버가 강제적으로 종료되었을 때 나타나는데, 어제 저희 홈페이지 서버가 강제로 전원이 나갔었어서 그 문자메세지가 최초로 도착한 것 같습니다.


공격이라도 받았을까봐, 원격 콘솔 열어서 RDC 포트 바꾸고 이리저리 수선을 떨었었는데..


뭐 결론은 파워서플라이 불량이었습니다. 이것부터 어제밤에 문제 생기고 계속적으로 문제가 생겨서 문자오고 메일오고 핸드폰 그래서 하루종일 징징거리고, 어제밤부터오늘 아침부터 저녁까지 수선떤걸 생각하면, 아오... 


근데 뭐 기계가 망가진게 사람의 뜻이겠습니까. 


뭐 그렇습니다. :) 


Posted by TY
,

 근간 거의 하지도 않았으며 머릿속에 지우개가 있는지 아무 것도 기억나지 않는 iOS앱을 수정해서 올려야 하느라 제대로 삽질을 했다. 코딩이 문제가 아니라 업로드를 할 줄을 몰랐던 것. 내가 아는 것은 오직 99$ 였던가, 이것이 필요하단 것 밖에 없었고 욕 밖에 안했었다. 개발자의 푼돈을 뜯어먹는 돈에 눈먼 애플같으니.. 라고 맨날 비난만 했던 것.


그래서 수 많은 삽질을 한 후에 오늘 큰 결실을 얻었다. 즉 업로드에 성공했다는 것.


나의 경우는 기존에 다른 사람이 사용하던 인증서를 받아야했다. 그래서 아무생각없이 받아서 다 키체인에 등록하니 안되었던 것 같다.(이런 멍청한..)


* 아래의 글은 전혀 전문적인 지식이 없이 구글링과 통밥으로 때려맞춰서 한 것이므로 트러블 슈팅에 도움이 되고자 쓴 글이지 누군가를 가르치기 위한 글이 아님을 알립니다. 혹시 문제 사항이나 자세한 사항을 알려주실 분의 덧글은 언제나 환영합니다 :)


기억나는 대로 쭈욱 적어보겠다.


기존에 알아야 할 사항.


1. 애플에서 말하는 키체인(Keychain)은 아래에서 관리한다.

 - 유틸리티 -> 키체인 접근


2. 기존에 있던 개발자용 인증서 때문에 안되는 것 같으면 일단 다 지운다.

 - 기존에 있는 apple관련 인증서를 모두 지운다. 아이디/비밀번호는 안지워도 된다. 이것을 지우는 것은 라이온 기준으로 유틸리티 -> 키체인 접근 -> 인증서 이다. (개인인증서 아님)


3. Apple Developer 에 로그인한다. - 그 후 member center에서 iOS provisioning portal을 들어간다.


4.좌측에 Certificates 를 접근, 하단에 


*If you do not have the WWDR intermediate certificate installed, click here to download now.


를 눌러서 다운로드 한다. 


는.... 여기서부터 귀찮으니


http://beta.smoon.kr/20


이 블로그의 글을 참조해서 한다.


* 아 참고로 등록된 인증서가 있다면 Revoke를 누르고 다른 페이지를 왔다갔다하면 위와 같은 모습이 된다. 근데 기존에 그 인증서 쓰던 사람은 못쓰게 되는거 다 아시져? :)


5. 인증서를 다 등록했으면 이제 Provisioning 에서 자신이 등록한 앱이 있다면 invalid되어있는 것을 다 edit를 해서 valid하게 만들어줘야한다. develop탭만 하지 말고 distribution탭도 할 것.


6. 그리고 엑스코드를 키고 핸드폰을 꽃으면 뜨는게 있었는데(기억이 잘 안남)어쨌든 거기서 refresh를 해서 현재 provisioning상황을 받아와야한다.


7. 그리고 archiving을 하면 되는데...


application executable is missing a required architecture armv6


이런 개같은 에러가 보일 수 있다.

그러면 프로젝트와 타겟 프로파일에서 Architectrue가 보통 Armv7(Standard)인지 Standard(Armv7)인가로 되어있는데, 그거를 편집하면 뭔가 모를 환경변수가 적혀있지만 그냥 지워버리고 armv6을 추가하고 armv7을 추가하면 된다. 

그리고 다시 컴파일을 하면...


이런 개븅신같은 에러도 보였었다.

이럴 때에는 해당 파일(png)가 interlace가 걸려있는지 확인해주고, 에러난 파일을 포토샵으로 열어줘서 Not interlaced로 저장해주고, Clean을 하고 다시 archiving한다. 클린 꼭 해줘야 한다. 안하면 계속 에러남.

이 과정을 몇 번 반복하다보면 archiving에 성공한다.

그러면 그 다음에 Organizer(xcode 메뉴에서 window-organizer) 를 실행하면 앱에서 컴파일할 때 에러(빨간 세모 안에 하얀 느낌표)만 없으면 업로드 되는 것 같다.

어쨌든 이 수많은 삽질을 통해서 나는 앱을 업로드에 성공하는 감격을 누렸다.

이 글을 쓴 이유는 다음에도 뻔히 이와 같은 삽질을 할 것 같기 때문이었다. 안 까먹으려면 어디다 써놔야 한다. 늙었나... 주말에는 소닉3 하다가 토할뻔했는데...

모두 행복하시길.

Posted by TY
,

우선 DISTINCT에 대해서 설명을 하자면 중복된 결과를 제거하고 하나만 원하고자할 때 쓰이는 문법이다.


예를 들어서  DB에


a, a, a, b, b, c 


과 같이 존재할 경우에는


a,b,c만 나오게 된다. -.,- 흔히 COUNT와 엮어서 특정 사용자가 어떤 행동을 했는지 뽑아달라고 할 때 많이 썼던 것 같다.


최근에 약 50만건의 DB에서 중복되지 않게 email들을 뽑아달라는 요청이 왔었다. 


그래서 아무 생각없이. 'DISTINCT를 쓰면 되겠구나'라고 생각을 했는데, 음... 결론적으로 말하자면 결과가 별로 좋진 않았다.


테이블을 간략화하자면 다음과 같다.


idx / int / NOT NULL, PK, AUTO_INCREMENT, INDEX

email / varchar(100) / NOT NULL

name / varchar(30) / NOT NULL


동일한 사용자는 여러개의 name(많은 사람은 400개 정도 --;)를 가질 수 있고, 이것을 DISTINCT로 거르자는게 내 생각이었다.


그래서 아무 생각없이


SELECT DISTINCT email FROM table;


로 끝내려고 했는데, 음 캐릭터 이름도 나와야할 것 같아서 캐릭터 이름을 그냥 나중에 뒤로 추가했다.


SELECT DISTINCT email, name FROM table;


그랬더니 왠지 모르게 결과가 많이 늘었지만 (그 당시에는 인지하지 못했다) 무시하고 지나갔는데 오늘 생각해보니 이런 이유였던 것 같다.


 SELECT DISTINCT email, name FROM table 에서


DISTINCT는 (email, name) 짝을 하나의 결과물로 묶고 저 두개가 같은 결과들만 쳐낸 것이 아닐까 --; 그럼에도 불구하고 결과가 약 17만건이 줄었던 것이 여전히 충격적이다.


그래서 다음과 같은 경우에는 이제 아래와 같은 방법을 사용하면 될 것 같다...;;


SELECT email, name FROM table WHERE idx in (SELECT DISTINCT email FROM table) ORDER BY idx DESC


만약 저렇게 한다면 최신 캐릭터명으로 이메일들이 1개씩만 나오지 않을까 생각한다 -_-;


mysql만 쓴지 벌써 5년짼데 아직도 이딴 삽질을 하는거 보면 맨날 헛공부를 하는 것 같다.



Posted by TY
,

 예전에 개발을 할 때 flash를 개발할 때 arguments같은 기능이 있지 않을까 해서 많이 찾아 헤매었던 기억이 있다. 왜 찾았었냐하면 특정 폰트에 이펙트를 입힌 swf를 많이 그려줘야 하는데 하나하나 만들기 도저히 귀찮아서 못하겠던 것. 그래서 나는 결국 글자를 동적으로 바꿀 수 있는 방법을 구상했고, 그래서 찾아 낸 방법은 FlashVars였다. 


 FlashVars는 Flash에 특정 인자를 전달하여, 로딩할 때 구동되게 하는 방식이다. 상당힌 간결하게 이용이 가능한데, flash에서는 어떻게 받아왔었는지 기억조차 나지 않지만 어쨌든 쉽게 받아왔었다.


 그래서 Flex(Flash Builder)에서 이용하려고 하는데 기억이 안나서 잠시 기억 좀 더듬고 인터넷좀 찾아서 기억해냈다. 하하.


* 보고 따라하실 분들은 맨 아래부터 보시면 되겠다. 위에부터 따라하면 패망함.


우선 FlashVars를 이용하려면 플래시를 불러오는 HTML파일을 수정할 필요가 있다. 기본적으로 Flex를 컴파일하면 생성되는 파일인 Project명.html을 열어보면 아래 두 개의 부분을 주의깊게 봐주자.




우선 첫 번째 소스코드이다. JS에서 swf를 불러오는 것을 생성해주는 부분이다. 여기서 원래 일반 소스에는 


var flashvars = {};

var params = {};


와 같은 방식으로 되어있다. 그러나 flashvars에 새 내용을 추가하고 싶다면 저 두 줄 사이에  


flashvars.변수명 = 값 


으로 작성할 수 있다(물론 꼭 두 번째 줄이어야하는 것은 아니고 swfobject.embedSWF 전에만 하면 될 것 같지만 저게 더 예쁠 것 같다)


예를 들자면


var flashvars = {};

flashvars.id = 3;

var params = {};


으로 하면 된다.




그리고 또 다음 소스에도 비슷한 방향으로 변경해주어야 한다.


원래는 param에 


<param name="FlashVars" value="name=idiot!" />


이 행은 아예 존재하지도 않는다. 그러므로 새롭게 추가하여 value에 key=value쌍으로 추가해주면 된다. 중복적으로 추가해주고 싶을 경우 get request를 설정하듯 key1=value1&key2=value2 와 같은 방식으로 설정할 수 있다.


그리고 소스코드를 수정한다. 




root.loaderInfo.parameters.변수명 으로 접근을 하면 된다.


그러면 성공적으로 이용할 수 있다.



Posted by TY
,



sourcetree 는 MacOSX에서 사용가능한 SVN, Git, Mercurial 소스코드관리프로그램이다. 인터페이스가 상당히 간단한 것 같다.


그 동안 Mac용의 SVN 프로그램 등을 내가 유료 빼곤 못 찾았던 것 같은데 이렇게 있으니 정말 좋은 것 같다.


한 번 써본결과 꽤 괜찮은 것 같다! 강추! :)


Github와 Bitbucket같은 사이트와도 손쉽게 연동이 된다(아이디와 패스워드만 치면 연동이 된다 ^^)


다운로드는 아래의 주소에서 받을 수 있다.


http://www.sourcetreeapp.com/

'study > apple' 카테고리의 다른 글

iOS (apple) 앱 업로드(배포) 하기  (0) 2012.07.16
맥OSX에서 XCode를 설치 및 실행해보자!  (1) 2011.01.10
Posted by TY
,

무비클립 내부에 무비클립이 있을 경우 정지와 재생이 뜻대로 되지 않는다. 이를 해결하기 위해 재귀 함수를 간단히 만들어보았다. 재귀로 하지 않는 방법이 있다면 좋겠지만 그런 방법은 잘 생각이 나지 않는다. 음... 


Posted by TY
,

어젠가 그젠가 Deepcopy에 대한 글을 올린 적이 있다. 테스트도 해봤고 해서 너무 잘 되길래 쓰려고 했더니... 어머나.. Movieclip은 안되더라-_-;


 그래서 도움을 구하여보니, export for ActionScript 를 한 다음 new를 해주면 된다 하더라. 여러가지 삽질을 했는데 안되서 다시 질문을 했더니, 친절하게도 예제를 만들어주더라(이 자리를 빌어서 도움을 주신 전수열님께 감사드립니다.)


 아래와 같은 방식으로 처리했다.



1. 만들어진 무비클립(library에 있는 것)의 property에서 Export for ActionScript를 체크해준다.


2. 화면 상의 심볼에 이름을 정해준다.



그리고 소스코드에서 다음과 같이 이용한다.


* 참고로 나는 BulkLoader를 이용한다. MIT LICENSE만세!




public class Test extends Sprite

{

var loader:BulkLoader;

var a:MovieClip;

var b:MovieClip;

public function Test()

{

loader = new BulkLoader("test");

loader.add("duck.swf");

loader.addEventListener(BulkProgressEvent.COMPLETE,onCompleteHandler);

loader.start();

}

public function onCompleteHandler(e:BulkProgressEvent):void

{

a = new(loader.getMovieClip("duck.swf").deco.constructor)();

b = new(loader.getMovieClip("duck.swf").deco.constructor)();

a.x = 100;

a.y = 100;

b.x = 300;

b.y = 300;

addChild(a);

addChild(b);

}

}





그러면 아래와 같은 화면을 얻을 수 있게 된다.




해결이 되서 너무 기분이 좋다!




Posted by TY
,

* 아래 내용은 지돌스타님의 ActionScript 3.0 Prototype 디자인 패턴(http://starpl.com/jidolstar/10052497) 내용을 참고하여 작성된 글입니다. 이해하기 쉽고, 요점만을 알기 위해 작성한 글이라고 생각하시면 되며 깊은 이해를 위해 위의 링크를 타고 이동해서 읽어주시면 감사하겠습니다.


 사실 이 내용은 3일밤낮을 머리싸매고 고민하며 온갖 방법들을 이용해서 Deep copy를 시도하다가 모르겠어서 맘먹고 구글링을 한 3시간 해서 찾아낸 결과이다. 정말 힘들었다. ㅠㅠ


 학생들을 가르치다보면 벽에 부딪히는 부분이 가끔 있다. Call by value Call by reference 차이를 이해를 한다는 것이었다. C언어를 가르칠 포인터를 설명하며 알려주면 쉽게 이해하는 부분이었지만, 요즘 대부분은 모바일의 여파 때문인지 JAVA 먼저 배우는 같다.( 안드로이드 때문 --;) 그래서 들에게 설명할 머릿속에는 포인터로 이해되어있는 내용을 포인터란 단어를 꺼내지 않고 설명하는 것은 상당히 곤란한 일이었다. 그래서 언제나 예시로 배열을 하나 생성해서 대입을 해주고 값을 바꿔서 ' 신기하지? 단순 자료형이 아닌 경우는 주소를 참조하게 되는거야'라고 하며 배열 모양의 메모리에 주소들을 붙이고 주소값을 넣는다며 배열 객체 자체를 출력하며 알려주었던 기억이 난다.


 요즘 대부분의 언어는 객체간의 대입 기호(=) reference형으로 연산을 한다. 그건 어떻게 보면 엄청 좋은 것이지만, 어떤 면으로는 엄청 짜증날 때가 있는데 동일한 객체를 복사해야 때이다.물론 클래스의 원형을 갖고 new 이용하면 되겠지만 비용 소모적인 문제도 있으나 결정적으로 MovieClip 받아왔을 new로 상속받는 방법은 굉장히 까다로우며 후임자가 봤을 경우 몹시 화가날 경우가 있다고 생각했다. 경우에 따라 매번 새롭게 할당받을 수 있으나 그 경우는 트래픽 문제 상 게임엔 적합하지 않다고 생각하여, 리소스로 넘어오는 swf파일에 최대한 추가 작업을 하지 않고 받아오는 방법에 대해서 생각해보아서 다음과 같은 물음에 도달했다.


 "shallow copy가 아닌 deep copy를 as3에서 사용할 수는 없나?"


 예전 as2 시절에는 duplicateMovieClip이라는 함수가 있었다고 하지만 지금은 존재하지 않으며, 인터넷 검색결과 대부분 ByteArray로 파일을 재 할당하여 대입하는 것을 알 수 있었다.


소스는 다음과 같이 구성되어있다.


public function createClone(source:*):*

{

var clone:ByteArray;

clone = new ByteArray();

clone.writeObject(source);

clone.position = 0;

return (clone.readObject());

}


위와 같은 방식으로 구성하면 되는데 위의 방법에 문제가 있다.


그래서 아래와 같은 방식을 이용한다고 한다. 대부분의 외국사이트들도 아래와 같은 방식을 채택하고 있다. 사용자정의 클래스를 복사하려면 이 방법이 더 좋은 것 같다. 


public function createClone(source: *):*

{

var className:String = getQualifiedclassName(source);


try

{

getClassByAlias(className);

}

catch(e:ReferenceError)

{

registerClassAlias(className, getDefinitionByName(className) as Class);

}


var clone:ByteArray;

clone = new ByteArray();

clone.writeObject(source);

clone.position = 0;

return clone.readObject();

}


결론은 MovieClip을 DeepCopy를 하기 위해선 위와 같은 함수를 추가해서 풀어야 한다는 말이다.


도움을 준 이근배(터칭시그널) 님과 전수열(Joyfl) 님에게 감사드립니다.


Posted by TY
,

BulkLoaderdㅔ는 크게 2개의 이벤트로 나눌 수 있따


BulkProgressEvent에서


PROGRESS와 COMPLETE이다.


PROGRESS는 데이터를 로딩할 때 계속 호출되는 이벤트이고, COMPLETE는 모든 데이터를 불러왔을 때 호출되는 이벤트이다.


progress는 로딩의 진행상황 같은걸 알 때 쓰이는데, 사실 나는 이게 로딩화면 말고 과연 쓰이는 곳이 있을까 의문이다 ( --;) 하지만 있음으로 해서 매우 훌륭한 이벤트임은 틀림없다.


한 클래스에서 좀 로더를 여러개 쓰기 싫어서 몇 가지 삽질을 했고 내린 결론이다.


1. 


알다시피 이벤트 기반의 프로그램은 (이게 시분할을 해서 돌아가는건지 모르겠지만) 리스너를 마구 건들면 안되는데 weakreference 로 참조하여 둘 다 호출을 하면 중복호출이 혹시 안되지 않을까 했다.


결론: 둘다 된다. GC에서 reference로 체크를 안해서 빨리 날릴 뿐이지 뭐 별다를 건 없었다. 역시 add를 해줬으면 remove를 해줘야한다.


2. 

그 다음엔 리스너를 add한 후 start하고 리스너를 remove 한 다음에 다른 리스너를 애드를 하면 어떻게 될까?


이벤트 기반이라 로딩은 따로 돌아가고 프로그램은 계속 다음 라인으로 넘어간다. 즉 로딩하기 전에  remove를 하면 어떻게 될까?


결론: ㅎㅎㅎ역시 ㅎㅎㅎ 안됨 ㅎㅎㅎ 




최종도출결론: 그래서 리스너를 두 개로 나누었습니다.


진작에 나눌것을.


...하아...



Posted by TY
,

다들 몸은 건강하신가요. 감기 조심하세요. 감기 1주일 째 빌빌거리고 있습니다.


최근에 깨달은 몇 가지 사항입니다. 기초적인 것이 많을 수도 있습니다.


1. toString() 메서드는 override가 가능하나 override를 작성하지 않는다.

 저는 해당 오브젝트에 대한 내용을 얻어올 때 Object객체에서 getObject()함수를 호출해서 toString()으로 받게 됩니다.


이러면 보통 아래와 같은 형식으로 출력이 되죠.


[object BitmapData]


하지만 저는 각각의 경우를 분할하기 위해서 toString()메서드를 override할 수 있지 않을까 생각했습니다. 


그래서 public override function toString()


와 같은 방식으로 작성을 했는데, 에러가 나더라구요. 그래서 override를 뺐더니 잘 작동을 합니다. 


그래서 위와 같은 방식으로 구분을 할 수 있지 않을까 생각하네요.


2. Dictionary 자료형에서 foreach나 for문을 이용한 iterator 이용

dictionary에서 iterator를 돌리려고 할 때 난감한 경우가 많았던 것 같습니다. 

그래서 조금 뒤져보니 다음과 같은 내용이 나오더라구요.


for(var key:String in dict) {


}


위와 같은 방식을 이용했을 때에 dictionary의 key들을 순서대로 얻어옵니다(제 생각에는 등록된 것의 역순으로 나오는 듯 하더군요.. 아니면 제가 쓰는게 stack형식으로 구현이 되는걸지도^^;;)


value는 다음과 같은 방식으로 얻어올 수 있습니다.


for each(var value:Object in dict)

{


}


저러면 Object만 얻어올 수 있습니다. 만약 두 개를 섞고 싶다면


for(var key:String in dict) {

if(dict.hasOwnPriority(key))

{

value = dict[key];

}

}


와 같은 방식으로 얻어올 수 있습니다.


3.  BulkLoader에서 id로 줘봤자 해당 id로 얻어오는 것은 힘들다

넘어온 Event객체나, loader를 뒤져도 해당 id로 iterate 하는 것은 힘듭니다. 그래서 주소에 충분한 구분자를 둬서 구분해야 합니다.


4. Flash Builder에서 Static Value의 값을 얻어올 수 없다.

 예를 들어서

 ResourceManager라는 클래스를 만들고 모든 변수를 static하게 관리한다고 하면, 디버거에서 Expression에서 얻어올 수 없습니다. 일일히 trace로 찍어야 합니다 --;



Posted by TY
,