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)
105,875 Visitors up to today!
Today 1 hit, Yesterday 3 hit
daisy rss
tistory 티스토리 가입하기!
'Objective-C'에 해당되는 글 13건
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. 11. 2. 01:11

ARC로 개인 프로젝트를 하나 해보고 있는데... 그러면서 가진 ARC에 대한 소감은 한마디로...


"쉬운 건 더욱 쉽게, 어려운 건 더욱 어렵게"이다. 아래 종암님이 댓글로 알려준 블로그 주인장도 비슷한 말을 한 것 같은데... 딱 그 말이 가장 적합한 것 같다.


애플이 ARC를 만든 게 결국 새로 유입된 개발자들이 Objective-C를 제대로 못 써서 계속 메모리 관련 문제를 일으키니 결국 앱스토어 앱들의 전체 퀄리티 향상을 위해서 만든 건데... 까보면 까볼수록 점점 애플 말이 믿기  힘들어진다.


성능이 더 좋다고 하지만 전혀 체감되지 않고 몇몇 테스트 결과는 되레 느리고, 개발자의 실수를 줄여서 퀄리티를 높인다고 하는데 가만히 보면 쉽게 찾을 버그를 더욱 깊은 곳으로 숨겨버리는 역할을 하는 것 같기도 하고... 


결국, 고만고만한 개발자 동원해서 대충 후다닥 빨리 만들 거면 ARC를 쓰는 게 나을 수도 있고, 베테랑 개발자를 동원해서 퀄리티 높은 코드를 만들려면 MRC(이건 또 무슨 용어...)를 쓰는 게 맞을 듯(후훗. 이런 위험한 발언을...)


이런 생각하는 것 보면 나도 참 이제는 올드한 개발자 측에 들어가나보다.


PS. ARC에 대한 내가 아는 에피소드 중 하나가 회사에서 추진하는 프로젝트에서 MRC로 작업하다가 수많은 크래시와 메모리 문제가 발생해 퀄리티에 문제가 생겼는데 프로젝트 자체를 ARC로 바꿔서 해결되었다고 한다. 와우! 개발자 실력을 늘려서 해결하지 않고 간단하게 툴로 해결했다! 하지만 크래시 하는 버그를 메모리 릭 버그로 다 바꿔놓은 게 아닌가 하는 의심이 드는 이유는 뭘까?

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
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
2009. 4. 1. 16:12
메소드 안에서 자신의 selector는 _cmd를 이용해서 알 수 있다.
사실 언제쓸까 싶었다. 예전에 봤었는데 워낙 안쓰다보니 그런게 있나 조차 까먹었었다. (어렴풋이 그런게 있었던것 같은데 수준..)
그러다가 오늘 드디어 쓸 일이 생겼다. :)
다른 메소드를 호출하면서 나중에 '나 다시 불러줘~'의 용도로 사용해봤다.
괜찮네...

박종암 | 2009.04.03 00:33 | PERMALINK | EDIT/DEL | REPLY
어떻게 그 용도로 썼나요? 다른 메소드 호출하면서, 그 메소드의 패러미터에 그 selector를 전달해 줬나요?
코드 샘플, 코드 샘플!!!
maccrazy | 2009.04.03 07:44 신고 | PERMALINK | EDIT/DEL
어떤 메소드를 호출했는데 그 메소드가 어떤 특정한 조건이 되었을때 자기를 다시 불러줘야 했어요. 근데 불러줘야 할 메소드가 고정된게 아니라 뭐가 될지 모르는 상황이었죠. 그래서 파라메터로 SEL을 주고 _cmd를 넘겨줬어요. 필요하면 다시 불러달라고.. ㅎㅎ
박종암 | 2009.04.04 11:17 | PERMALINK | EDIT/DEL | REPLY
음.. 그렇게 하셨군요.
참.. 그런데 Obj-C/Cocoa를 MFC처럼 쓴 거.. 정말 상상이 안되는데요? 어떻게 그럴 수가 있죠? 저는 암만 상상해도 그게 안되는데.. 한번 구경하고 싶네요.
maccrazy | 2009.04.04 14:24 신고 | PERMALINK | EDIT/DEL
NSString *szTemp = [[NSString alloc] initWith....

간단한 예이지만 이런 스타일이죠. ㅎㅎ sz... 이건 뭐 Obj-C 코딩 컨벤션을 모르는게 문제가 아니고 헝가리안 코딩 컨벤션도 제대로 이해 못하고 쓰고 있었다는 이야기죠.
나머지는 나중에 하나씩.. :)
Name
Password
Homepage
Secret
2008. 11. 26. 16:52
Objective-C 2.0에 "@package" 이런 놈이 추가 되었다.
뭔가 했는데 아주 나쁜 놈이다. 이제 프래임웍 안을 휘젓고 다니지 말라는 거군.
그럴거면 필요한 옵션기능 좀 제대로 할 수 있게 해주던가...
간단히 말하면 프래임웍 안에서는 @public으로 프래임웍 밖에서는 @private로... 서브클래싱 해도 맴버 변수 맘대로 가지고 놀기 힘들겠구나... 쩝...

오늘 따라 애플이 사람을 계속 열 받게 만든다.
littlehj | 2008.11.27 16:11 신고 | PERMALINK | EDIT/DEL | REPLY
또 하나의 나쁜 놈을 알게 됐넹? ㅋㅋ
근디 요즘 뭐하냐? 아이챗에서도 통 안보이고...
maccrazy | 2008.11.28 09:44 신고 | PERMALINK | EDIT/DEL
빡세게 일 하지요. ㅡ.ㅡ;; 메신저는... 회사에서... 흑...
정승욱 | 2008.11.27 20:07 | PERMALINK | EDIT/DEL | REPLY
지금 회사에서도 썸네일 뷰 만들줄이야.. 아고고.. 저를 스크롤해주세요
maccrazy | 2008.11.28 09:45 신고 | PERMALINK | EDIT/DEL
ㅋㅋㅋ 인생이라 생각하세요. :)
아이폰용 썸네일 뷰면.. 너무 작지 않나요?
레이어와 스크롤 뷰 적절히 이용하면 뭐... 어렵지 않을듯 한데요..
littlehj | 2008.11.30 19:07 신고 | PERMALINK | EDIT/DEL | REPLY
ㅎㅎㅎ....올초도 썸네일뷰 올말도 썸네일 뷰~ 승욱이 팔자는?
박종암 | 2008.12.06 13:56 | PERMALINK | EDIT/DEL | REPLY
Java의 냄새가....
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
2008. 8. 26. 12:23
Objective-C 2.0에 추가된 기능 중 가장 큰 것이 Garbage Collector(GC)가 아닐까 하는데 사실 나도 retain/release가 손에 익어서 그런지, GC가 못 미더워서 그런지, 그것도 아니면 호환성 때문인지 아직은 사용하지 않고 있는 기능 중 하나이다.
Objective-C 2.0의 GC는 몇개의 구분된 generation을 기준으로 reclaim을 하는데 이는 대부분의 객체는 임시로 생겼다가 바로 사라진다는 사실을 기반으로 하고 있다. 뭐, 맞는 말이다. 즉, 그렇기 때문에 임시 객체의 소멸은 매우 빠르게 진행되겠지만 오래된 객체의 경우 그 반대일 수도 있다는 이야기가 되는것 같기도 하고... 아직 확인 해보지는 못했다. 이것을 설명할 때 사용되는 용어 중 하나가 "Write-Barriers"이다. 쓰기 울타리? 무슨 말이지?
앞서 이야기 했듯이 GC가 메모리를 몇개의 generation으로 나누어 관리한다. 만일 새로 생성된 객체가 오래된 객체의 영역으로 저장되면 write-barrier는 그것을 표시해두는 역할을 한다. 가비지 컬렉팅이 요구될 때 이미 표시된 객체들이 계속 사용되는지 확인하고 보다 오래된 영역으로 옮기고 사용되지 않는 새 객체들은 모두 제거 된다.
이때 실제 동작되는 모양을 들여다 보면 대입연산자들이 objc_assignIvar나 objc_assignGloabl같은 helper function으로 대체되어서 작동된다. 즉, 약간의 오버헤드가 걸리는데 애플은 이 함수들이 매우 빠르다고 주장하고 있다. :)
밀리네스 | 2008.08.26 12:59 | PERMALINK | EDIT/DEL | REPLY
애플도 자바 vm을 만드니까 자바에서 그동안 발전되어온 gc 코드를 가져다 쓰면 되지 않을까 싶네요.
뭐 썬이 주장하기로는 jvm에 사용되는 jit나 gc는 예술의 경지에 이르렀다고 하고, 실제로 성능도 상당히 나오는 편이니까요. ^^
박종암 | 2009.05.06 01:23 | PERMALINK | EDIT/DEL | REPLY
Garbage Collector는 아니지만, autorelease pool이 관리되는 것도 다르네요?
Tiger에서 버그가 있어서, 디버깅을 해 봤는데, 하나를 그냥 stringWithFormat과 같은 함수로 생성된 NSString객체를 그냥 한 클래스의 내부 변수에 할당을 한게 있는데, 그 클래스의 인스턴스가 release가 되지 않았는데도 Tiger에선 release되더군요. Leopard에선 아무런 문제가 없는데 말이죠. Tiger에서 쓰던 obj-c RunTime이 클래스의 유효성 유무와 상관없이 release를 시킨다는건데..

아.. 은근스레 Tiger하고 Leopard하고 다른게 꽤 있어서, 다 관리하는게 좀 복잡하네요. :)
Name
Password
Homepage
Secret
prev"" #1 #2 next