BLOG main image
분류 전체보기 (92)
Cocoa Touch (11)
Cocoa (10)
Objective-C (13)
Swift (6)
Development (11)
Tools (11)
Books (7)
etc (21)
Application release (1)
Document Project (1)
106,256 Visitors up to today!
Today 14 hit, Yesterday 5 hit
daisy rss
tistory 티스토리 가입하기!
'Objective-C'에 해당되는 글 9건
2015. 7. 1. 13:57

평소에 ARC를 별로 쓰지 않다가 샘플 프로젝트를 ARC로 하고 있는데 재미있는 내용이 보입니다.

performSelector: 메소드에 관한 것인데, MRR의 경우 performSelector의 사용에 있어서 아무런 문제가 없습니다.

하지만 ARC의 경우 warning을 내는 경우가 발생하네요. 아래와 같이 static한 selector를 사용하는 경우는 문제가 되지 않습니다.


[object performSelector:@selector(myMessage)];


하지만 이렇게 사용해서는 selector를 제대로 쓰는 거라 보기는 좀...

만일 SEL에 담긴 임의의 selector를 사용하게되면 “PerformSelector may cause a leak because its selector is unknown”이라고 메시지가 뜹니다.

아래와 같이 코딩을 하면 그런 문제가 생기지요.


[object performSelector:mySelector];


이유는 return type 때문입니다. return type이 객체인지, primitive type인지 autorelease를 해줘야 하는지 retain된 상태인지 컴파일러가 나는 모르겠다는거군요.

뭐 MRR의 경우 컴파일러가 몰라도 개발자가 알아서 할것이기 때문에 굳이 이런 warning을 낼 필요가 없었던 것이지요.


하지만 급기야 swift에 가서는 performSelector 자체를 없애버렸습니다(이전 글에서 썼듯이)!!


여기서 조금 중요한 개념적인 문제를 한번 짚고 넘어가 보죠.

OOP란게 뭔가 잔득 복잡한 이야기 같지만, OOP에서 가장 중요한 키워드만 뽑아보라면 저는 단연코 “객체”, “관계”, “메시지”라고 이야기 하고 싶습니다. “클래스”, “맴버 함수”, “상속” 따위가 아니라는 말이지요.


Objective-C의 performSelector는 다른 언어와 Objective-C가 구별되는 가장 중요한 차이 중 하나인 “메시지”를 대표하는 기능입니다.

Objective-C의 경우 객체만 추상화 되는 것이 아니라 메시지도 추상화 되기 때문에 이 기능을 잘 이용하면 매우 간결하고 아름다운 코드를 만들어 낼 수 있습니다. 그런데 애플은 결국 서서히 메시지의 추상화를 제거해버리는 쪽으로 방향을 잡았군요.

아주 로레벨인 메모리 관리를 하는 방법을 컴파일러가 알아내기 힘들다는 이유로 하이레벨의 중요한 개념 하나를 날려버렸군요. 쩝...


결국 Swift의 경우 메시지 전달은 매우 명시적고 해당 클래스에 강하게 묶여있습니다. 우리는 이것을 맴버 함수 호출이라고하지요.

반면 Objective-C의 경우 메시지 전달과 메소드 호출은  완전 다른 이야기입니다. 어떤 객체에든 메시지를 보내는 것이 자유이고 메시지를 받은 객체는 그 메시지에 대해 어떤 메소드를 이용해서 반응할지 동적으로 결정할 수 있습니다.


여러분은 어느 쪽에 손을 들어주실 것인가요?



Name
Password
Homepage
Secret
2014. 4. 14. 23:03


Objective-C가 계속 발전하면서 오랫동안 Objective-C를 개발하던 사람들에게는 눈에 거슬리는 문법이 하나 있는데 이름 하여 property dot notation이다.

주변에 꽤 오래된 (10년 정도) Objective-C 개발자들(그래 봐야 몇 안되지만)에게 물어보면 대체로 property dot notation에 대해서 부정적이었다.

그들의 생각을 속속들이 모두 들어보지 않았기 때문에 모두들 어떠한 이유로 그런 생각을 가지고 있는지는 모르겠지만 내가 주장하는 큰 이유는 아래와 같다.


1. dot notation을 사용하는 property는 마치 public 변수와 같은 느낌을 준다.

당연히 public 변수는 아니지만 그런 느낌으로 사용되는 것은 부정할 수 없으리라 생각한다. OOP에서 그런것이 그렇게 남발되어서는 안된다고 생각한다. 모든 죄악의 근본이다.


2. message sending syntax의 일관성을 해친다.

뭐 반드시 코드가 일관성을 가져야 하는가에 대해서 강하게 주장하지는 못하겠지만 깔끔하게 정리된 느낌을 주지 못하는 것은 사실이다.


3. Law of Demeter를 너무 쉽게 어기게 만든다.

C++이나 Java같은 언어에서도 메시지 체인은 피해야 할 코딩 습관인데 Objective-C에서도 너무 쉽게 메시지 체인을 만들어 버리게 한다. 물론 dot notation이 아니라도 메시지 체인을 만들 수 있지만 아무래도 매우 번거롭고 보기만 해도 위압적이다. 그러므로 잘 안하게 된다.


결국 1, 3번은 1번이 원인이고 3번이 결과인 셈인것 같다. 여튼 이 주장의 근거로 삼기에 강력한 순으로 따지자면 3, 1, 2쯤 될것 같기도 하고 보는 이에 따라 1, 3, 2쯤 될것 같기도 하고…


이쯤되면 이런 주장이 나올법하다.

“결국 문법은 문법일 뿐 그렇게 사용하지 않으면 괜찮지 않은가? []을 사용하는 메시지 전달 방식도 결국 하기에 따라 동일하지 않은가?”


뭐 맞는 말이다. 하지만 좀 많이 어거지로 같다붙이자면 언어는 사고를 지배한다(사피어-워프 가설. 이런데 갖다 붙이기엔 좀…).

프로그래밍도 근본적으로 언어를 이용하여 컴퓨터의 동작을 기술한다는 점에서 언어를 사용하는 것과 동일 선상에 놓고 볼 수 있을것 같은데 프로그래밍에 사용하는 언어, 그리고 그 언어를 사용하는 습관이 전체적인 애플리케이션의 구조와 동작 방식에 영향을 준다고 생각한다.

즉, 메시지 체인을 만들기 쉬운 문법을 제공하면 그만큼 메시지 체인을 만들 확률이 높아질 수 밖에 없다고 생각한다. 마치 public변수 처럼 사용하기 쉬운 문법을 제공하면 그렇게 코딩하게 된다.


그래서 결론은… 조금 귀찮더라도 dot notation을 사용하지 않고 한번 작업을 해보라고 권해보고 싶다.

어떻게 될것 같냐고?


조금 더 귀찮지만 훨씬 괜찮은 코드가 되어 있을 것이라 생각한다.


Name
Password
Homepage
Secret
2013. 6. 19. 23:20

ARC(Automatic Reference Counting)이 소개된지도 시간이 꽤 지난 것 같은데 나는 여전히 이놈이 적응되지 않는다. 아니 적응하고 싶지 않다가 정확한 표현인지도 모르겠다.

Objective-C의 retain/release 룰은 매우 심플하고 간단한데 왜 굳이 그것을 복잡한 룰로 한꺼풀 더 씌워서 ARC라는 놈을 만들었는지 모르겠다.

아직도 많은, 특히나 오래된 Objective-C 개발자들은 ARC를 그다지 선호하지 않는 편으로 판단된다. 애플은 열심히 밀고 있지만...


그러면 애플은 왜 ARC를 이렇게까지 밀고 있을까? 대충 우스개로 짐작해보면 다음과 같은 이유가 있을 수 있겠다.


1. Clang으로 뭔가를 계속 개선하고 있다는 것을 보여주고 싶다.

2. C를 제대로 모르는 상태에서 Objective-C를 개발하기 시작하는 개발자들이 alloc/free에 대한 개념이 없다. 그래서 수많은 leak과 double free를 만들어내고 앱의 퀄리티를 낮추기 때문에 그들을 일일이 교육시키느니 그냥 툴로 커버하는게 낫다고 판단했다.


정말 그럴지도 모르겠다는 생각이 든다. 옆에서 지켜보던 모 프로젝트는 Objective-C 초보가 코드를 작성해서 도저히 벗어날 수 없는 메모리 문제에 봉착했었다. (leak, double free, retain cycle...) 하지만 그 모든 문제를 ARC가 한방에 해결해줬다. 그래 적어도 앱이 죽지는 않았다.

개발을 하면서 자신이 사용하고 있는 언어의 정확한 동작원리도 이해하지 않고 사용하겠다는건 도대체 무슨 용기인지 모르겠다.


어쨌건, 애플이 ARC를 홍보할 때 사용하는 수많은 말들이 있지만 사실 별로 와닫지 않고 단순한 언어와 룰을 복잡하게만 만들었다는 생각이 드는건 나의 편협한 생각탓일지도 모른다. 하지만 어쩌겠나... 그나마 유일하게 쓸만하다고 느끼는 경우는 부주의한 코드 작성으로 retain cycle이 걸릴 확률이 조금 줄어든다는 정도인데...

대신 alloc / free 시점의 정확한 컨트롤, 메모리 사용에 대한 명쾌함이 사라진다고 생각하면 "글쎄요?"이다. 공짜로 그게 다 주어진다고 해도 더 낫다고 확신이 서지 않는데... 뭐 또 봐야 할 건 이렇게도 많고 기존 코드와 호환도 안되고... 에라잇!


최건우 | 2013.06.21 01:19 | PERMALINK | EDIT/DEL | REPLY
Objective-C를 꽤 오래 해온 개발자입니다. 저는 ARC가 나온 이후로 ARC를 이용하지 않는 프로젝트는 손도대지 않고있습니다. 왜 그 편하고 최적화도 공짜로 해주며 개발자가 실수할 염려도 줄여주는 도구를 안쓰는지 이해가 되지 않는다고 생각하는데 이에 대해서는 어떻게 생각하시나요
maccrazy | 2013.06.21 11:21 신고 | PERMALINK | EDIT/DEL
안녕하세요. 댓글을 남겨주셔서 감사합니다.
뭐, ARC를 바라보는 시각의 차이야 개발자 마다 있는 것은 당연한데요, 제 경우는 오히려 불편했다는 말씀을 드리는 것입니다.

1. 편리함 : 메모리 관리에 대해서 투명하게 확인이 되지 않는게 전 오히려 더 불편했습니다. 마치 Java를 볼때의 그런 불편함이랄까요? 가베지 콜랙팅이 언제 일어날지 확인도 안될때의 그런 느낌 말입니다. 단지 retain/release pair를 맞추는 수준의 생각을 덜어줄 수 있는건 편하다고 느껴지지는 않았습니다.

2. 최적화 : 몇몇 부분에서 ARC가 최적화를 해주는게 맞기는 하지만, 대부분의 정말 최적화가 필요한 부분은 결국 사람이 일일이 확인해봐야 합니다. 즉, ARC가 해주는 최적화가 크게 와닫지 않습니다.

3. 실수에 대한 우려 : 실수는 ARC를 쓰나 안쓰나 동일하게 발생하고요, 실수를 줄이기 위해서는 unit test나 analysis, profiling같은 유용한 방법이 많습니다. 아, 메모리에 관한 실수라면 그건 실수가 아니라 잘 모르고 있는 것일 확률이 훨씬 높다고 생각됩니다.

본문에서도 썼듯이, ARC 자체가 나쁘다고 생각하지는 않습니다. 다만 ARC가 추가되면서 언어 자체의 룰이 오히려 더 복잡해졌고요, ARC를 쓰더라도 결국 ARC가 어떻게 동작하는지 제대로 알지 못하면 전혀 종잡을 수 없는 실수를 만들 수도 있다고 생각합니다. 즉, retain/release 개념만 알면 될 것을 ARC까지 알아야 하는 상황이 된거고요. 뭐, 애플은 그냥 믿고 ARC를 써라고하는데... :)

사실 그것보다 더 중요한 문제는, 개발자들이 원리를 이해하고 공부하는 습관을 가지지 않고 가시적인 편리함, 성과에만 치중하게 되는 경향을 가지게 만든다는거죠. 메모리 관리에 무엇인가 문제가 생겼다면 왜 그런 일이 벌어졌는지 확인해보지 않고 툴이 알아서 모든 뒷정리를 해줄거라 믿고 그냥 날림 코딩을 하게 되는거죠.

저도 Objective-C를 지금 10년 넘게 주 언어로 사용하고 있고 제 주변에 그런 분이 몇분 계신데 하나같이 하시는 말씀들이 "ARC 좋은건 알겠는데 나한테는 별로 유용하지 않다."입니다. 왜 그런걸까요? :)
박종암 | 2013.06.21 14:42 | PERMALINK | EDIT/DEL | REPLY
웬지 Like 버튼이나 Favorite 버튼이 아쉬워지는군요. :)
maccrazy | 2013.06.21 14:55 신고 | PERMALINK | EDIT/DEL
그래도 언젠가는 ARC로 넘어가야 하나 그러고 있습니다. 마음에 들지는 않지만 뭐 어쩌겠습니까? (그래도 최대한 버틸때까지 버텨볼렵니다. ;) )
박종암 | 2013.11.01 17:19 | PERMALINK | EDIT/DEL | REPLY
누가 잘 정리했군요. ARC가 어떤 점이 안 좋은지.
http://pivotallabs.com/why-not-to-use-arc/
maccrazy | 2013.11.02 01:00 신고 | PERMALINK | EDIT/DEL
와닫는 문장이... 쉬운건 더 쉽게 어려운건 더 어렵게.. ㅋㅋ
요즘 프로젝트 하나를 시험삼아 ARC로 해보고 있는데... 글쎄요... 별로 좋을게 없다는 생각을 더욱 굳히게 만들고 있네요.
Name
Password
Homepage
Secret
2010. 5. 12. 11:56

쓸일이 있을것 같아서 간단하게 한번 만들어봤는데... 쓸일이 없을듯 하기도 하고...



#define CROSS_PRODUCT(sPt1, sPt2)   (sPt1.x * sPt2.y - sPt1.y * sPt2.x)



- (BOOL)isCross:(MyLine *)aLine

{

    NSPoint sL1S = [self pt1];

    NSPoint sL1E = [self pt2];

    NSPoint sL2S = [aLine pt1];

    NSPoint sL2E = [aLine pt2];

    NSPoint sV  = NSMakePoint(sL2S.x - sL1S.x, sL2S.y - sL1S.y);

    NSPoint sV1 = NSMakePoint(sL1E.x - sL1S.x, sL1E.y - sL1S.y);

    NSPoint sV2 = NSMakePoint(sL2E.x - sL2S.x, sL2E.y - sL2S.y);

    

    CGFloat sCrossV1V2 = CROSS_PRODUCT(sV1, sV2);

    if (sCrossV1V2 == 0)

    {

        return YES;

    }

    

    CGFloat sCrossVV1 = CROSS_PRODUCT(sV, sV1);

    CGFloat sCrossVV2 = CROSS_PRODUCT(sV, sV2);

    CGFloat sT1       = sCrossVV2 / sCrossV1V2;

    CGFloat sT2       = sCrossVV1 / sCrossV1V2;

    

    if (0.0 <= sT1 && sT1 <= 1.0)

    {

        return YES;

    }

    if (0.0 <= sT2 && sT2 <= 1.0)

    {

        return YES;

    }

    

    return NO;

}



Name
Password
Homepage
Secret
2009. 4. 6. 23:43

요즘 짬내서 읽고 있는 책은 Dreaming in code입니다. 몇몇 반가운 이름들이 거론되곤 하는데 Objective-C를 쓰는 사람이라면 누구나 알법한 브래드 콕스에 대한 이야기가 있기에 소개합니다.

브래드 콕스의 생각을 읽으면 Objective-C의 설계 철학을 조금이라도 더 이해 할 수 있지 않을까요?


인용시작 :

1980년대에 브래드 콕스라는 컴퓨터 공학자는 재사용 가능한 파트를 결합해서 프로그램을 개발하기 위해 엄청난 노력을 쏟아부었다. 그는 C언어를 확장해서 Objective-C라는 새로운 언어를 고안했으며, 이를 통해 재사용 가능한 소프트웨어 객체를 개발하는 것을 좀더 편리하게 만들고자 했다. 하지만 이 시도가 무위에 그치자, 그는 이 문제를 기술적인 관점 대신 경제적인 관점에서 접근하기 시작했다. 1990년에 콕스는 프로그래머들이 재사용가능한 작은 컴포넌트를 개발해 다른 개발자들에게 판매할 수 있게 하는 새로운 접근 방식을 고안해냈다.

콕스에 따르면 프로그래머들은 여전히 움막을 짓는 방식으로 소프트웨어를 개발하고 있었다. 그는 '혼자서 공예품을 만드는 가내수공업 방식'에서 벗어나 '제조업 공장을 세우는 기업형 방식'을 추구해야 한다고 주장했다. 오늘날의 소프트웨어 개발자는 볼트와 너트 하나하나를 깎아 총을 만드는 식민지 시대의 대장장이와 비슷하다. 소프트웨어 산업은 '대장장이가 쇳대를 깎듯이 소프트웨어 컴포넌트 하나하나를 수작업으로 깎아내는 단계'에서 산업 혁명과 같은 과정을 거쳐 '안정적이고 신뢰할 수 있으며 명세가 정확한 표준 부품을 시장으로부터 공급받을 수 있는 단계'로 도약하지 못했다. 컴퓨터 하드웨어 산업은 관련 기술의 엄청난 복잡성에도 불구하고 소프트웨어 산업이 흉내 내지 못하는 성공적인 도약을 이뤄냈다. 십자드라이버만 사용할 줄 안다면, 컴퓨터 하드웨어에 대한 전문 지식 없이도 그래픽 카드 정도는 누구나 바꿔 낄 수 있다. 이와 비슷하게 그래픽 카드 제조사들 역시 카드에 들어가는 칩 등의 부품을 시장에서 구입해서 실제로 그런 칩들이 어떻게 동작하는지를 모르고도 얼마든지 그래픽 카드를 만들어낸다. 소프트웨어 또한 이렇게 만들어낼 수는 없을까?

콕스는 이를 시도했다. 그는 스탭스톤이란 회사를 설립해 C언어를 위한 소프트웨어 컴포넌트를 제공하고자 했다. 하지만 일부 작은 성과에도 불구하고, 이러한 접근 방법은 결국 성공하지 못했다. 그는 나중에 다음과 같이 썼다. "실제로 시도해본 결과, 쓸모있고, 재사용에 성공적이며, 프로그래머들이 쉽게 이해해 활용할 수 있고, 지속적으로 쏟아져 나오는 하드웨어 플랫폼에 쉽게 이식되며, 기능 업데이트가 기존 코드와 충돌이 나지 않은 컴포넌트를 개발해서, 모든 것을 자체적으로 개발하려는 문화를 가진 시장에서 판매하는 것은 불가능할 정도로 어려운 일이었다."

인터넷의 등장은 콕스로 하여금 이 문제에 다시 한번 도전하게 만들었다. 콕스는 1995년 자신의 저서인 'Superdistribution'에서 인터넷을 이용해 새로운 소프트웨어 컴포넌트 시장을 구축하는 계획을 제안했다. 그는 오늘날의 컴퓨터 환경에서 코드가 복사되는 것을 추적하는 일은 불가능에 가깝지만, 그 코드가 실제로 실행되는지를 추적하는 일은 충분히 가능하다고 지적했다. 따라서 소프트웨어는 무료로 배포하되, 사용 횟수와 시간에 따라 과금을 하는 방법이 어떻겠냐고 콕스는 제안했다. 새로운 이메일 프로그램을 개발하는 프로그래머라고 가정해보자. 나는 개발 과정에서 다른 프로그래머가 개발한 스팸 필터 모듈을 찾아내서 사용하기로 결정한다. 사용자는 소프트웨어를 무료로 다운로드 받을 수 있지만, 매달 사용료를 지불해야 한다. 사용료의 일부는 스팸 필터를 개발한 프로그래머에게 지급된다.

콕스는 이런 소프트웨어 배포 방식을 통해 신뢰할 수 있는 소프트웨어 컴포넌트들이 거래될 수 있는 시장을 만들어낼 수 있다고 생각했다. 하지만 그의 아이디어는 이번에도 성공하지 못했다. 오늘날의 웹 기반 소프트웨어 서비스는 사용자가 소프트웨어를 다운로드 받아 설치해 사용하는 방식이 아니라 웹 브라우저를 통해 제공돼 무료로 또는 싼 값에 사용하는 모델을 따르고 있다. 이러한 방식이 콕스가 상상했던 '슈퍼배포' 방식과 비용 과금 등에 있어 가장 비슷한 모델이다. 또한 프로그래머들은 비용을 지불해야 하는 소프트웨어 컴포넌트를 사용하는 대신 완전히 무료로 개방된 오픈소스 소프트웨어 컴포넌트를 사용하는 쪽을 선호하게 됐다. 현재 버지니아 주에서 컨설턴트로 활동하고 있는 콕스는 자신도 매일같이 오픈소스 소프트웨어를 사용하고 있고 스스로를 리눅스 해커라고 여기지만, 오픈소스가 소프트웨어 재사용성 문제에 대한 현실적인 해답은 아니라고 말한다. "오픈소스는 돈보다 명성으로 인해 동기부여를 받는 이들에게는 하나의 경제모델을 제시하고 있습니다. 하지만 대부분의 사람들은 어떻게 대출금을 갚을 것인지에 더 동기부여가 되기 마련이죠. 저는 재사용성 문제를 해결하기 위해 이들 다수를 움직이는데 관심이 더 많습니다."

인용 끝:


일단, 제 경우는 이 글을 읽었을 때 딱 와닫는 단어가 두개 있었습니다. "재사용성", "현실적인"이 그것인데요, 이것이야 말로 Objective-C를 잘 설명하는 단어인듯 합니다. 브래드 콕스가 이상을 추구한다기 보다 상당히 현실적인 사고방식을 가졌기에 지금의 Objective-C같은 모양이 나오지 않았나 합니다. 만일 이상주의자였다면 Smalltalk같은 녀석이 나왔을지도 모르겠습니다.



Name
Password
Homepage
Secret
2009. 4. 5. 19:26


Objective-C는 C/C++에 비해서 매우 동적인 언어에 속하는 편입니다. 동적인 속성은 속도를 희생해서 얻은 것이기도 합니다. 덕분에 Objective-C가 비교적 느린 언어라는 비판을 받기도 합니다. 하지만, 다른 부분이 너무 매력적이어서 그런 약간의 손해를 보고도  포기 할 수 없는 것을 어찌할까요.

그래서, 가끔 속도에 밀접한 코드를 작성할 때, 부분적으로 C/C++로 작성하기도 합니다. C/C++로 작성된 함수들은 Objective-C의 메소드 콜에 비해서 비교적 빠릅니다. Objective-C의 메소드 디스패치 프로세스에 대해서 잘 알면 좋을텐데 그 주제는 다음에 다뤄야 할것 같고, 일단 오늘의 주제인 메소드 콜 속도 향상을 위한 이야기를 계속 해볼께요.

특정한 루프 안에서 반복적으로 메소드를 계속 호출 할 때, 메소드 디스패치 프로세스를 타는 것은 참 비효율적일 수도 있습니다. 특히 요즘 같이 CPU 속도가 나날이 빨리지는 시대에 Mac OS X와 같은 데스크탑에서는 별로 의미가 없을지도 모릅니다만, iPhone의 경우라면 또 이야기가 달라질듯 합니다. 어떤 때는 물에 빠진 사람이 지푸라기라도 잡는 심정으로 메소드 콜 옵티마이징을 해야 할 경우가 생길지도 모르겠네요. (사실 이정도까지 가는 경우는 자주 보지는 못한듯 합니다만...)

여튼, 굳이 이 주제에 대해서 이야기를 하는 것은, 첫째, 옵티마이징 여지를 찾아보는 것과 동시에, 둘째, Objective-C의 안쪽을 조금 더 들여다보고 이해 할 수 있지 않을까 해서입니다.

여기서 질문 하나, C/C++을 같이 쓰는 방법으로 속도향상을 노릴 수 있지 않나요? 예, 실제로 그렇게 많이 쓰기도 하지만 단점이 있습니다. 아무래도 Objective-C객체의 데이터와 C/C++ 함수의 코드가 따로 분리되어서 처리되기 때문에 모양이 별로 좋지 않아집니다. 비용이 C함수 호출하는 것과 거의 비슷한데 Objective-C 고유의 객체지향 속성을 버리지 않아도 된다면 차라리 이쪽을 선택하는 것이 낫지 않을까요?


이 테스트를 위해서 간단한 샘플 코드를 하나 작성했습니다.


- (NSInteger)accumulate:(NSInteger)aValue

{

    mSum += aValue;

    return mSum;

}


실제 수행을 위한 메소드는 위와 같습니다. 옵티마아징을 할 때도 이 코드는 수정하지 않겠습니다. (mSum은 맴버 변수입니다.)


NSInteger i;

for (i = 0; i < 100000; i++)

{

    [self accumulate:i];

    [self accumulate:i];

    [self accumulate:i];

    [self accumulate:i];

    [self accumulate:i];

    [self accumulate:i];

}


이쪽은 반복해서 특정 메소드를 호출하는 코드입니다. 예~ 인정합니다. 테스트 목적에 맞춰서 조금 무리하게(?) 코드를 끼워 맞췄습니다. 즉, 굳이 다른 부분에 CPU를 안쓰게하고 accumulate를 호출하는데 CPU를 많이 쓰게 유도했습니다. 60만번 호출이라면 엄청 많은 편에 속할듯 합니다. 일반적인 경우에서 이만큼 호출 하는 경우가 잘 있나 싶을 정도입니다. (이미지 프로세싱을 할때면 또 모르겠네요.) 60만번을 메소드 디스패치 프로세스를 탈 이유는 없어보입니다. (하지만 테스트를 하면서 하나 놀란 것이 메소드 디스패치 프로세스를 60만번 타는 속도가 생각보다 매우 빨랐다는 겁니다. ^^ ) 제 기계에서 (2.0GHz G5 X 2, 그래봐야 하나 밖에 안 썼겠지만...) 0.032초 걸렸네요. 이거 뭐, 거의 무시해도 되지 않나 싶은데... 여튼, 그래도 칼을 뽑았으니 옵티마이징 하면 어떻게 되나 한번 봅시다.


    NSInteger i;


    typedef void (*FuncPtr)(id, SEL, int);

    SEL sel = @selector(accumulate:);

    FuncPtr func = (FuncPtr)[self methodForSelector:sel];

    

    for (i = 0; i < 100000; i++)

        func(self, sel, i);

        func(self, sel, i);

        func(self, sel, i);

        func(self, sel, i);

        func(self, sel, i);

        func(self, sel, i);

    }


먼저, 간단하게 설명하지만 다음과 같은 단계를 거칩니다.


1. 호출하고자 하는 메소드의 셀렉터를 구합니다.

2. methodForSelector 메소드(클래스 오브젝트만 안다면 instanceMethodForSelector 메소드)를 이용해서  함수의 포인터를 얻습니다.

3. 함수를 호출합니다. 첫번째 파라메터는 리시버, 두번째 파라메터는 셀렉터, 그리고 변수들이 들어갑니다.


이렇게 작동시켜서 얻은 소요시간은 0.018초, 비율로 보면 상당히 줄었으나 만일 호출되는 메소드가 복잡해지고(그쪽이 CPU를 사용하는 비중이 늘어나고) 메소드 디스패치 프로세스를 이용하는 횟수가 줄어든다면(디스패치가 사용하는 CPU시간이 줄어들면) 전체적으로 봤을때 의미있는 성능향상을 보기는 쉽지 않을듯 합니다. 아이폰에서 아주 속도에 민감한 경우, 의미있는 결과를 얻을 수 있을지는 모르겠습니다. :)


Name
Password
Homepage
Secret
2008. 11. 18. 15:47
예전에 써둔 Objective-C언어에 대한 문서에서 polymorphism과 dynamic binding 부분만 따로 정리했다.
원문은 예전에 마소에 연재되었었고 osxdev를 통해서 게시되었고 인터넷 여기저기 펌질 당한.. ㅡ.ㅡ;; 글이다. 오래되기도 했고 다시 손봐야 할 것 같아서 조금씩 정리 해보도록 하겠다.

Objective-C 언어가 대부분의 개발자들에게 익숙하지 않은 언어인데다 개발자들의 입장에서 보면 특히 polymorphism과 dynamic binding은 기존에 익숙한 언어인 C++와 비교해 조금은 다른 형태를 가져 다른 해석을 할 필요가 있다. 비록 Objective-C에서 이 두 부분이 차지하는 비중이 매우 크고 다른 언어와 확연한 차별성을 보여주는 부분이기에 확실한 이해가 필요하다.
하지만 기존의 많은 Objective-C 해설서가 이 부분에 대해서 크게 할애하고 있지 않고 개발자들도 심각하게 받아들이지 않는 다는 점은 다소 의외이다.
여기서는 Objective-C 언어의 모든 범위를 살펴보기 보다 이 두 부분에 집중해서 설명하도록 하겠다.

Polymorphism
Polymorphism에 대해 이야기 하기 전에 기존의 C++같은 언어에서의 polymorphism을 생각하고 Objective-C의 polymorphism을 보면 더 헷갈리기 때문에 C++의 경우에 대해서는 잠시 잊어 두도록 하자. Objective-C의 polymorphism은 단지 Objective-C의 polymorphism이다. 이게 무슨 polymorphism이냐고 따지지 말자. 같은 단어를 두고 조금은 다른 해석을 하고 있다는 것을 고려해서 보도록 하면 좋을 것 같다. 그리고 Objective-C가 “method”와 “message”를 엄밀하게 말하면 구분 짓는다는 사실에 염두하고 보기 바란다.
A라는 객체와 B라는 객체가 있다고 가정하자. 이 객체들이 setOrigin이라는 동일한 message를 받는다면 어떻게 될까? 만일 A와 B가 같은 클래스로부터 인스턴스화 되었다면 같은 동작을 하겠지만 만일 다른 클래스로부터 인스턴스화 되어 나온 객체라면 다른 동작을 보인다. 이것이 “message의 polymorphism”이다.
이렇게 동일한 message가 각각의 객체에서 다르게 해석되기 때문에 개발자들이 얻을 수 있는 장점은 message의 이름을 정하는데 상당히 여유로울 수 있고 공동개발을 할 때도 message의 혼동을 줄일 수 있다.
message를 보내는 일련의 작업이 특정 객체의 맴버 함수를 바로 호출하는 C++의 방식과 많이 다르다는 것을 주목해보기 바란다.

Dynamic Binding
그렇다면 함수의 호출과 message의 전달이 어떤 점에서 다르다는 것인가?
함수의 호출은 함수와 그 매개변수들이 컴파일 된 코드에 완전히 바인딩되어 버린다. 그렇지만 message와 message를 받는 객체(receiver)는 그렇지 않고 실행시간에 message를 보내기 전까지 전혀 바인딩되지 않는다. 어떤 method를 실행할건지는 실행시간에 message를 받으면서 결정 나며 컴파일 할 때는 알 수 없다.
Polymorphism을 설명할 때 설명했듯이 message에 대해서 실행되는 method는 receiver에 의해 결정 나게 되는데 다른 receiver라면 다른 method가 실행되는 것이다.
컴파일러가 message에 대해서 정확한 method구현을 찾게 하기 위해서 오브젝트가 무슨 클래스에서 유래했는지 알아야 한다. Objective-C에서는 이런 정보가 소스코드에서 파악이 불가능하며 receiver가 message를 받은 시점에서 알 수 있다.
이것이 Objective-C에서 구현된 dynamic binding이다. 앞서 설명한 polymorphism과 함께 생각해보면 이해가 쉬울 것이다.
message가 보내지면 런타임 messaging루틴은 receiver의 method 리스트에서 message와 같은 것이 있는지 확인해서 그 method를 호출하고 receiver의 인스턴스 변수들의 포인터를 넘긴다.
message 안에 있는 method 이름은 실제 실행될 method를 찾는데 사용되어서 “selector”라고 부른다.
이런 dynamic binding은 polymorphism과 함께 유연함과 힘을 제공한다.
예를 들어 워드프로세서를 한번 생각해 보자. 화면에 선택된 영역이 있다. 이 선택된 영역은 텍스트 일 수도 있고, 레스터 이미지 일 수도 있고 벡터 이미지 일 수도 있다. 아니면 복합적인 형태의 표 이거나 다른 형태의 데이터의 표현일 수 도 있다. dynamic binding이 지원되지 않는 언어라면 이런 경우 메뉴에서 Copy를 선택하면 어떤 동작을 해야 할까?
먼저 선택된 것이 무엇 인지부터 판단해야 하는데 이는 결과적으로 코드를 복잡하게 한다.
반대로 dynamic binding과 polymorphism을 이용한 Objective-C의 경우 선택된 객체가 copy method를 구현하고 있다면 그 객체가 무엇인지 신경 쓰지 않고 단지 copy message만 보내면 된다. 당연히 특정 객체가 특정 method를 구현하고 있는지 런타임 시에 확인 할 수 있는 방법도 제공한다.
얼핏 보면 이게 차이가 얼마나 날까 싶지만 많은 차이가 난다.

이상 간단하게 Objective-C에서의 polymorphism과 dynamic binding에 대해서 살펴 보았다.
C++과는 다르게 Objective-C에서의 polymorphism은 각 객체들이 동일 message에 어떻게 해석할지 객체마다 달라진다는 것이고 이것은 dynamic binding과 밀접한 연관성을 지니고 있다.
객체 method의 기본 작동 방식이 다른 만큼 실제 그 언어를 이용한 프로그램의 설계도 달라지게 된다. 기존의 C++에서의 습관을 그대로 가지고 Objective-C를 바라보게 되면 Objective-C를 제대로 사용하는 것이라 할 수 없다.
Name
Password
Homepage
Secret
2008. 11. 5. 23:45
아이폰 덕분인지 코코아, Objective-C 개발 저변이 확대되고 있다는 생각이 많이 든다.
대부분의 신규 Objective-C 개발자들이 C++이나 Java 개발을 하던 사람들인데 가끔 코드를 보면 예전 스타일을 고수하는 것을 볼 수 있다. 그래, 솔직히 고백하건데 나도 처음에는 그렇게 쓴 적이 있었다.
로마에 가면 로마법을 따르라고 했던가 Cocoa/Objective-C 세상에서는 그 룰을 따라주는게 좋을 것 같다.
많은 부분에 대해서 이야기 할 내용이 있지만 이번에는 "get"으로 시작하는 메소드에 대해서 이야기 해보고자 한다. 일반적으로 set, get으로 시작하는 메소드를 accessor라고 하고 보편적인 다른 언어에서는 set은 맴버 변수에 값을 넣을 때, get은 반대로 값을 가지고 올 때 사용한다. Set, Get 처럼 대문자로 시작하는 경우는 있을 지언정 대부분이 이렇게 사용했을 것이다.
사실 여기에도 의문이 조금 있다. get이라는 단어 자체가 너무 의미가 포괄적이지 않나 하는 것이 내 생각인데 변수의 값을 복사해서 받는다는 말인지 포인터만 가져오겠다는 것인지, 다른 어느 곳에서 부터 받아오겠다는 건지...
뭐, 이런 의미에 대한 이야기는 나중에 기회가 되면 다시 이야기 하기로 하고 Objective-C에서는 어떻게 쓰나 알아보자.
Objective-C의 경우 set은 "set"으로 명시하지만 get은 기본적으로 맴버 변수 이름을 그대로 사용한다.
만일 맴버 변수 이름이 frame이면 get메소드 이름도 frame이 되는 것이다. 만일 변수 이름이 _frame이면 역시 frame, mFrame이라도 역시 frame이 되는 것이다.
변수에 사용된 프리픽스를 제외한 단어가 메소드 이름으로 사용된다. 이 규칙은 단순하지만 꽤 중요한데 Key-Value Coding에서 진 면목을 드러낸다.(이에 대해서는 차차...)
그렇다면 언제 "get"을 사용하는가? 아래의 경우를 보자

<예>
NSValue의 - (void)getValue:(void *)buffer
NSData의 - (void)getBytes:(void *)buffer
NSString의 - (void)getCharacters:(unichar *)buffer
등등

자, 보면 알겠지만 값을 복사해서 돌려주는 포인터를 받아올 때 사용한다. 만일 이런 용도 이외에 get을 사용한다면 다른 협업하는 개발자에게 혼란을 주는 행동을 하게 되는 것이다.
박종암 | 2008.11.06 18:14 | PERMALINK | EDIT/DEL | REPLY
이거 예전에 쓰셨던 내용이죠? 이글루스에서 본거 같은데...
get과 set을 쓰는 것은 getter/setter라는 용어를 그대로 반영한거 같습니다.
요새 다른 사람들의 코드를 손보느라고 시간을 많이 쓰는데, 제가 발견한 문제가 바로 이 글과 관련이 많습니다. method의 이름으로 도대체 뭘하는 것인지 알아먹기가 힘들다는 것입니다. 결과적으로 data encapsulation/hiding이 되지를 않습니다. 클래스의 내부 구조를 모르고도 가져다 쓸 수있다가 OOP의 장점 중 하나인데, 이게 되지를 않으니..
maccrazy | 2008.11.06 18:35 신고 | PERMALINK | EDIT/DEL
예전에 쓴 내용은 아닌데요. 예전 회사에서 이 문제로 한참을 시끄럽게 토론했던 기억이 나서 한번 써봤습니다.
뭐, get도 나쁘진 않지만... 글쎄요... 자주 혼란스러운 경우게 생기더군요.
Name
Password
Homepage
Secret
2008. 9. 18. 10:09
Objective-C를 사용하다 보면 nil을 많이 사용하게 된다. nil이 "0" 즉, NULL이란 사실은 다 아는 사실이고 그렇다면 Nil은 무었일까?

이렇게 define 되어있다.
뭐.. 같은거네... 하지만 설명에는 이렇게 되어있다.

nil : Defines the id of a null instance.
Nil : Defines the id of a null class.

null instance라는 말은 익숙할텐데 null class라는 말은 왠지 익숙치 않을듯 하다.
Objective-C는 런타임 상에서 클래스도 "클래스 오브젝트"로 일종의 오브젝트라는 생각을 하면 null class라는 말이 이해하기 쉬울듯 하다. 뭐, 어차피 같은 값으로 define 되어있으니까 nil을 쓰나 Nil을 쓰나 그게 그거이긴 하지만...
박종암 | 2008.09.18 11:06 | PERMALINK | EDIT/DEL | REPLY
우연인데, 얼마전에 Apple의 Objective-C mailing list에 이것때문에 길게 토의가 진행된 적이 있어요.
nil, Nil, NULL, (void *)0 등의 차이가 뭐냐.. 뭐 그랬던거 같은데, 사람들이 이런 저런 이유로 이게 옳다 저게 옳다했었죠. 헤더에서 nil은 (void *)0이래나 하면서 그냥 NULL (0)하곤 다르다 어쩌고 이랬는데요..
지금 헤더를 보니 다 그냥 0이네요. 사실 (void *)0이라고 해도, automatic casting이 되니까, 별 의미 없죠.
제가 보기엔 이건 그냥 coding convention인거 같습니다.
Data Structure 책을 보면 (한국에서 교과서로 제일 많이 쓰는), pointer variable에 대해선 nil을 쓰더군요. ToolBox에서 nil을 보아온 저는 어라? 이거 익숙한데 했죠. 어디서 nil이란 말이 나왔는지는 여전히 모르지만.. 그래서 보면 보통 포인터 변수나 객체는 nil을 써서, 아 이놈이 포인터나 객체.. 즉 어쨌거나 포인터다라는 것을 알게 해주고 NULL이라고 하면 아 스칼라 변수구나 하고 알수있게 해주는거죠.
Nil은... 사실 전혀 쓰지 않아 생소하네요. 있었는지도 몰랐어요.
Jenix | 2008.09.24 13:23 | PERMALINK | EDIT/DEL | REPLY
헛.. Nil 이 있는줄은 이 글 보고 알았어요.
인스턴스랑 클래스를 구분지어 둔거군요. 또 하나 배우고 갑니다 :)
Name
Password
Homepage
Secret
prev"" #1 next