이 블로그를 종료합니다.

분류없음 2012.11.16 00:03
개인적으로 인터넷의 무효한 링크를 굉장히 싫어하기때문에
거의 사용하지 않는 블로그였지만, 내 블로그를 통해 조금이라도 도움이 될사람이 있다면
기꺼히 그리고 서비스가 죽지않은한 영원히 남겨둘 생각이었다.

하지만 최근에 비공개된 글이 타 검색사이트에 공개가 되어있다는 것을 알고는
다음에 항의했지만, 지금까지 2주째 답장이 없기때문에 , 나로서는 더이상 이 블로그를
유지하는것은 무의하다고 판단하게 되었다.

내 블로그를 보는 몇명 안되는 유저들을 위해 마지막 인사를 남긴다.
 
さようなら


p.s 새로운 대안 블로그가 생기면 이 블로그의 모든 글은 삭제될 예정입니다. 
Trackback 0 : Comment 0

Coredata Background 처리에 관하여

Project 2012.10.17 22:43

격주 릴리즈의 바쁜 스케쥴안에서 시간을 쪼개 코어 데이터 처리 로직을 백그라운드에서 처리하려는 작업을 조금씩 진행시켜 이번버젼에야 겨우 적용할수 있었다. 여기에 약 6개월간에 걸쳐 내가 겪은 시행착오에 관한 기록을 남긴다.

1. 기존설계의 문제점

  모든 처리를 MainThread에서 하도록 구현되어있었기 때문에 화면이 멈추는 경우가 자주 있었다.
Main Thread에서 처리하지 않으면 안되었던 이유는 UI의 변경은 반드시 Main Thread에서 하지 않으면 안되기때문이다.


모든 작업을 main Thread에서 처리하더라도 발생하는 한가지 이슈가 있었는데,

비동기 리퀘스트(Asynchronous Request)와 Block을 이용할때 request시에 취득한 NSManagedObject는 respoonse때에 다시 사용할경우 문제가 생길 가능성이 있다.

ex)

a. Request - A 유저 데이터를 이용하여 request를 보냄
b. A 유저데이터가 삭제됨
c. Response - A 유저 데이터를 그대로 이용하여 작업 하지만 이미 삭제되어있기때문에 fault된상태이기때문에
crash 를 유발할수있다.

이때문에 response블록에서는 사용될 데이터는 moc로부터 새로 취득하여 사용하지 않으면 안되었었다.



2. 개선 - 2개의 NSManagedObjectContext

 기동시에 데이터를 정기적으로 체크하지 않으면 안되는 로직이 있어서 해당 작업을 배치로 묶어서 백그라운드에서 처
리하도록 수정하였다.
 수정방법은 배치에 사용될 NSManagedObjectContext(이하 MOC)는 직접 DB(persistent)로부터 취득하여 생성하여
main thread사용중인 moc에 영향이 가지않도록 하였다.

 이 작업을 진행하며 발견된 이슈가 있는데

- Fetch Result Controller(이하 FRC)의 델리게이션은 Main Thread에서 일어나야한다(UI)
FRC델리게이션으로인해 table view의 갱신이 일어나게되고 이 작업은 항상 main thread에서 실행되어야만 하는 문제가 있었다.

하지만 데이터의 저장타이밍(moc save)에 FRC에 대한 델리게이션이 일어나기때문에 save타이밍에
직접 merge를 구현하여 main thread에서 실행되도록 수정하였다.

save시에 notification(NSManagedObjectContextDidSaveNotification)을 observer하여
MainThread에서 noti데이터로부터 main context에 merge하도록 수정하였다

....

            [[NSNotificationCenter defaultCenter] addObserver:moc selector:@selector(merge:) name:NSManagedObjectContextDidSaveNotification object:moc];
....

- (void)merge:(NSNotification *)notification

{

......

    dispatch_async(dispatch_get_main_queue(), ^{

        [mainManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];

    });

....



3. 개선 - 2개의 Context 그리고 GCD QUEUE

모든 데이터의 처리는 아래의 2개의 context를 이용하여 데이터를 처리하기로 결정하엿다.

a. Read 및 UI용 Main Context
FRC에 설정되거나, viewDidLoad시에 사용될 데이터을 위해서만 사용된다.
이 MOC에대한 수정 및 Save는 금지된다.

b. 데이터 수정용 private context
수정이 필요한 NSManagedObject들은 이 MOC로부터 취득한다.
UI에서는 절대 사용하지 않도록한다.

위의 콘텍스트를 두가지로 나눈이유는 merge conflict 머지경합을 방지하기 위해서이고
기본 비지니스로직의 처리는 private MOC의 performBlock 안에서 하도록 강제한다.

만약 로직에 UI변경이 필요하다면 

dispatch_sync(dispatch_get_main_queue(), ^{ UI 변경 });

을 이용하여 처리하도록 한다.

 이렇게 함으로서 자연적으로 처리가 비동기, 백그라운드에서 실행하게 되며 기본적으로 UI작업과 독립적으로 이루어지기 때문에 앱이 멈추는 경우는 거의 사라졌다.

이 작업을 진행하면서 발견한 몇가지 이슈가 있는데 

-  MOC의 생성과 사용은 항상 같은 Thread이어야만 한다.
GCD queue를 이용해 block을 dispatch 했을경우, block내의 moc가 다른 thread에서 실행될경우에 데이터가 엉키거나 크래쉬되는 문제가 있었다.

 쉽게설명하면 
GCD Private Queue

BLOCK 1
{
   MOC A를 생성
} Thread A에서 실행

BLOCK 2
{
  MOC A를 가지고 작업
} Thead B에서 실행

Private Queue이기때문에 기본 시리얼하게 실행되겠지만 , moc가 생성된 thread가 아닐경우 문제가 생길 가능성이 있다.


- IOS4의 MOC에는 perform block이 존재하지 않는다.

IOS5에서 추가된 기능중하나는 GCD Queue를 이용한 core data 처리관련 기능들이 추가되었다는것이다.
NSManagedObjectContext 를 생성할때 ConcurrencyType를 지정할수가 있다.

NSPrivateQueueConcurrencyType
 이 타입으로 생성한 MOC는 performBlock을통해 실행되어 사용된다면 특별히 신경쓰지 않아도 thread safe가 보장된다.

NSMainQueueConcurrencyType
 performBlock내의 처리로직들은 항상 main thread에서 실행된다.



IOS5에서는 private context를 NSPrivateQueueConcurrencyType으로 생성하여 block내에서 실행한다면 쉽게 백그라운트 처리가 가능해졌다.

하지만 문제는 IOS4 , IOS4를 위해서 직접performBlock을 구현하고 private thread를 생성하여 해당 block의 실행을
동일한 thread로 강제하였다.

ex

        privateQueueContextThread_ = [NSThread newDefaultModeRunLoopThread];

        [privateQueueContextThread_ performBlockAndWait:^{

            privateQueueContext_ = [[NSManagedObjectContext alloc] init];

        }];



직접 prvateQueueContext의 초기화를 privateQueueContextThread에서 실행하고

    @autoreleasepool {

        if (NO == [NSManagedObjectContext instancesRespondToSelector:@selector(performBlock:)]) {

            __unsafe_unretained Class mocClass = [NSManagedObjectContext class];

            IMP performBlockIMP = class_getMethodImplementation(mocClass, @selector(iOS4PerformBlock:));

            IMP performBlockAndWaitIMP = class_getMethodImplementation(mocClass, @selector(iOS4PerformBlockAndWait:));

            

            class_addMethod([NSManagedObjectContext class], @selector(performBlock:), performBlockIMP, "v@:@?");

            class_addMethod([NSManagedObjectContext class], @selector(performBlockAndWait:), performBlockAndWaitIMP, "v@:@?");

        }

    }

performBlock을  구현하였다.

- (void)iOS4PerformBlock:(dispatch_block_t)block
{
  [privateQueueContextThread performBlock:block]


이로서 ios4,ios5에서도 동일한 코드로서 백그라운드 처리가 가능하게되었다.

4. Etc 몇가지 팁

- 비동기로 처리시 UI작업에서 사용하기전에 삭제된 NSManagedObject가 아닌지 체크하여라

- (BOOL)wasDeleted

{

    id myObject = [self.managedObjectContext existingObjectWithID:[self objectID] error:NULL];

    return myObject == nil;

}


위의 함수를 NSManagedObject의 category로 등록하여 , 사용전에 wasDeleted로 체크한다면
릴리즈 데이터의 엑세스로인한 crash이슈는 막을수 있을것이다. 



- Core data에서 sqlite 의 데이터중 name값이 NULL값을 찾고싶을때?

[NSPredicate predicateWithFormat:@"name = NULL"]


5. 마지막으로

 사실 위의 코드로 실제 백그라운드를 바로 구현하기는 어렵겠지만, 문제의 원인과 수정에 대한 방향은
잡을수 있으리라 생각된다.


p.s 이 슬라이드에서 내가 한 방법과 완전히 같은 방식으로 멀티쓰레드 코어데이터를 구현했다. (11월10일)
http://www.slideshare.net/Inferis/adventures-in-multithreaded-core-data


Trackback 0 : Comment 0

PHP 단상

Project 2012.04.15 23:30

PHP: 잘못된 디자인의 프랙탈 


PHP를 정말로 증오하는 분이 쓴 글을 국내의 블로거가 번역한글인데 , 최근에 읽은 블로그 중 가장 재미있어서 나도 PHP의 단상을 몇가지 적어본다.

 먼저 나또한 위의 글을 전적으로 동의한다. PHP개발을 하며 나타나는 알수없는 버그들등에 고생을 한 경험이 있어서 PHP가 얼마나 거지같은지 깊이 공감을 한다.
 하지만 왜 언어 랭킹을 보면 항상 저자가 좋아하는 Python보다 높은 순위에 있으며 , 그 인기가 10년가까이 지속되고 있는지 생각해볼필요는 있을것같다.

1. PHP는 왜 그렇게 많이 쓰이는가?

- 먼저 PHP는 환경설정이 정말 간단하다.
윈도우라면 XAMP , 맥이라면 MAMP , 리눅스라면 LAMP 로 검색해서 나오는 패키지를 인스톨하면 끝이다.
다른 환경설정 필요없이 그냥 설치하고 htdocs에 php를 넣어두기만 하면 끝이다.
물론 실제 서비스때는 apache,php설정등을 바꿔줘야하지만 다른 언어에서 그것에 비하면 정말 생각할것이 없다.

- 빠른 개발속도
당신이 프레임워크를 이용하든, 그냥 통짜 php로 개발을 하든 무엇을 이용하든 익숙한 개발방법이 있다면 하나의 화면을 구현하는데 정말 별로 시간이 걸리지 않는다. 내 경험상 자바로 개발할때보다 4배이상은 빠르게 개발할수 있다고 말할수 있다.

- 낮은 학습곡선
PHP는 정말 누구나(개나소나) 쉽게 배울수 있다.
귀찮은 부분은 다빼버린 언어 설계때문에 (그로인해 심각한 결함들도 있지만) 그냥 생각한대로
쓰면 왠만하면 결과가 나온다.
또 PHP프레임워크는 배우기가 정말 쉽기 때문에 다른언어의 프레임워크보다 쉽게 이용할수가 있다.
(어려우면 안쓴다)

- 풍부한 라이브러리
게시판,블로그,홈쇼핑등의 많은 레퍼런스및 오픈소스가 있으며 필요한 함수나 소스코드는 검색만 하면 나올정도로
도처에 널려있다.(C&P가 많아서 문제,중복되는 기능의 함수가 많아서 문제이긴 하지만)

2. 그리고 현실적인 이유들

- 개발자를 구하기 쉽다.
학습곡선이 낮은만큼 PHP개발자는 도처에 널려있다.
컴퓨터 전공이 아닌 많은사람들이 웹페이지를 만드려고 처음 개발을 시작해서 접하는것이 html 다음이 php이기에
정말 많은 사람들이 php를 알고있다.(커뮤니티의 수준이 낮다고 하는것도 비슷한것이 원인)

- 대부분의 웹사이트들은 규모가 작다
대부분의 웹사이트들은 우리가 생각하는만큼 많은 유저를 대상으로 만들지 않아도 된다.
게다가 개발에 들어가는 돈과 시간도 일주일,100만원수준의 사이트가 대부분.
홈쇼핑에 무회원 계좌이체, 수동결제확인이면 회원관리에 그렇게 보안을 신경쓰지 않아도 되는 경우도 많다.

- 유지보수비용이 상대적으로 적다.
위의 경우와 낮은 학습곡선을 생각한다면 , 대부분의 작은 사이트에서 php소스코드를  수정하는일은 그리 전문적은 지식을 갖지않은 사람도 조금만 공부한다면 할수 있다. (신기능 개발은 무리일지 몰라도)


- 대부분의 PHP개발자는 PHP만 하지 않는다.
PHP만 알아서 먹고살수 있느냐 한다면 대부분의 경우 아니라고 말할수 있다.(JAVA라면 가능)
보통 php개발자는 mysql도 알아야하고 Javascript도 알아야하고, html도알아야하고 css도알아야하고 상황에따라 디자인도해야하는 경우도 많이 있다.이런상황에서 다른언어를 써보라고? 아마 납기 못맞추고 야근하기 쉽상일듯.


3. 결론

내 생각은 앞으로도 PHP의 인기는 계속될것이다. IT업계에서 누구나 항상 좋은 조건의 좋은환경에서 개발할수 있는 것이 아니기 때문에 , 위의 막장처럼 보이는 환경에서 많은사람이 일할것이고 그들은 PHP를 선택해 개발할경우가 많을것으로 보이기 때문이다. (적어도 python보다는)
 
물론 주력언어로 PHP를 쓴다고 한다면 도시락 싸들고 말릴것이다.
PHP를 깊게 파려고하는 당신 왜 이 단순한 언어를 더 공부하려고 하나요?



 
 

Trackback 0 : Comment 0