티스토리 툴바



  

이벤트에 대해 알아보자.

 

이벤트는 이해하기 어렵지 않으니 Delegate에 대한 첫번째 발걸음으로 적합하다.

이벤트는 객체지향 프로그래밍의 가장 기본적인 설계 기법 중 하나라 할 수 있다.

객체지향 프로그래밍의 특징이 여러가지 있지만 그 중 하나가 재사용성이다.

재사용성과 이벤트가 무슨 관계가 있을까. 아래 마이클잭슨의 사례로 한번 생각해 보자.

 

 

마이클 잭슨 한국에 오다. 100여명의 스탭과 함께.

 

이제는 고인이 된 마이클 잭슨이 한국에 온 적이 있다. 그가 온다는 것만으로도 울트라 빅빅빅 이슈였지만, 함께 이슈가 되었던 건 100여명의 스탭과 함께 오기 때문에 모셔오는 비용이 어마어마하다는 거였다.

같이 오는 100여명의 스탭 중에는 헤어디자이너, 무대 감독, 음향 감독 뿐 아니라 전용 요리사들도 포함되어 있었다.

 

여기서 우리는 전용 요리사들에 주목해 보자.

물론 무대 준비를 때문에 예민해진 마이클 잭슨을 위해, 그의 입맛에 맞는 요리를 준비하는 요리사들은 어쩌면 필수일지 모른다. 하지만 이런 개인적인 감정 문제는 다 접어두고 큰 그림만 생각해 보자.

 

마이클 잭슨이 배가 고프면 밥만 제공해 주면 된다. 마이클 잭슨은 입맛이 까다롭지 않고 주는대로 먹는 착한 어른이니까.

그리고 총괄 스태프는 마이클 잭슨에게 요리사들을 전부 알려주고 배가 고프면 이 요리사들에게 얘기하라고 정해주고 자기는 싹 빠졌다.

 

이제 마이클 잭슨이 배가 고프면 아래의 프로세스를 따를 거다.

 

1. 마이클 잭슨이 배가 고프다.

2. 한식이 먹고 싶으면 한식 요리사를, 중식이 먹고 싶으면 중식 요리사를, 양식이 먹고 싶으면 양식 요리사를 찾는다.

3. 배가 고프니 밥달라고 얘기한다.

4. 요리사가 그 요구를 받아들인다.

5. 요리사가 요리를 준비하고 식사를 제공한다.

 

너무도 당연한 흐름이지만, 객체지향 프로그램을 설계하는 입장에서는 약간 문제가 있어 보인다.

객체지향 프로그래밍을 설계하는 입장에서 가장 문제가 되는  것은 “2번 요리사를 찾는다”이다.

 

만약 마이클 잭슨이 “나 배고파” 라고 총괄 스태프에서 얘기하면 총괄 스태프가 알아서 요리사를 찾아 음식을 제공해 주는 구조였다면 전용 요리사는 필요하지 않았을 거다.

 

문제가 되는 건 마이클 잭슨이 특정 요리사를 직접 찾았다는 거다.

 

위 문제에 대한 객체지향적인 해결 방안은 다음과 같다.

 

1. 마이클 잭슨이 배가 고프다.

2. 배가 고프다고 하늘에 대고 소리친다.

3. 총괄 스태프가 이 소리를 듣고 한식, 중식, 양식 요리사 들 중 한명을 배정해 음식을 만들어 달라고 요구한다.

4. 요리사가 그 요구를 받아들인다.

5. 요리사가 요리를 준비하고 식사를 제공한다.

 

둘의 차이를 명확히 알 수 있는가.

배고픈 당사자인 마이클 잭슨이 직접 요리사를 찾는지, 아니면 그냥 하늘에 대고 배고프다고 소리치면 총괄 스태프가 듣고 알아서 상황에 맞는 요리사를 찾아서 일을 시키는지가 가장 큰 차이이다.

 

마이클 잭슨의 입장에서는 배가 고프면 말할 수 있는 상대가 특정의 몇몇 요리사들 뿐이기 때문에 배가 고플 때를 대비해서 그 요리사들을 데려올 수 밖에 없었던 거다.

배가 고프다고 다른 사람들한테는 얘기할 수 없고 꼭 그 요리사들한테만 얘기하도록 정해져 있기 때문에 그 요리사들을 데려와야만 한다.

 

이걸 좀더 확대하면, 헤어를 위해 전용 헤어 디자이너, 전용 의상 담당, 구두, 악세사리, 무대, 음향, 기타 등등 마이클 잭슨이 직접 다 찾아서 얘기해야 하기 때문에 마이클 잭슨 한명만 오면 그 모든 스태프들이 다 딸려와야 한다.

그중 한명이라도 없으면 마이클 잭슨은 제대로 된 공연을 할 수 없다.

 

헤어를 다듬어야하면 하늘에 대고 “나 머리 좀 잘라줘~” 라고 소리치면 총괄 스태프가 이걸 듣고 알아서 한국에서 잘 나가는 헤어 디자이너를 섭외해 머리를 잘라주는 구조였다면 굳이 전용 헤어 디자이너를 미국에서 여기까지 데려오느라 큰 돈을 쓰지 않아도 되었을 거다.

이런 식으로 전부 확대하면 100여명의 스태프가 아니라 1-2명의 총괄 스태프 등 핵심 스태프 몇 명만 같이 왔어도 되었을지 모른다. 그럼 돈도 무지 절약했을텐데.

 

 

그런데 우리 프로그래머들도 이렇게 돈을 무지 쓰는 일을 하고 있다.

 

프로그래머라면 대부분 어떤 프로젝트에서 클래스 하나를 만들어 놓고 와~ 잘 만들었다~ 혼자 감탄하면서 다른 프로젝트할 때도 가져다 쓰기 위해 다른 프로젝트에 던져 놓았더니, 그 클래스 안에서 다른 클래스나 파일들을 요구해서 하나씩 복사해 넣다가 결국은 프로젝트 전체를 다 복사해 넣어야 하는 상황이 발생해서 포기한 경험이 있을거다. ㅋ.

 

바로 마이클 잭슨과 같은 경우다.

 

한 클래스에서 다른 클래스를 사용하도록 프로그래밍 하는 경우가 바로 그런 경우다.

물론 대부분 한 클래스에서 다른 클래스를 사용하도록 설계하지만, 어떤 클래스들은 내부적으로 아무런 클래스도 사용하지 않도록 설계되어야 한다.

그래야 다른 프로젝트에서 사용할 때 아무런 문제없이 사용할 수 있다.

이래야 객체지향 프로그래밍의 특징 중 하나인 “재사용성”을 높일 수 있다.

 

예를 들어 질량 계산을 담당하는 클래스라면 그 클래스의 헤더파일과 구현 파일들만으로 (상속을 받았다면 그 상위 클래스들까지 포함) 모든 기능을 제공해야 한다는 거다.

다른 클래스를 가져다 쓰기 시작하면 그 클래스가 또 다른 클래스를 필요로 하고 그 또 다른 클래스는 또또 다른 클래스를.. 또또또 다른 클래스를… 이래서는 재사용성이 보장되지 않는다.

 

이렇게 클래스의 헤더 파일과 구현파일만으로 하나의 기능이 완벽하게 보장되면 재사용성이 보장될 수 있다.

 

그런데 이렇게 다른 클래스를 쓰지 않기 위한 또 하나의 조건이 있다.

 

바로 마이클 잭슨처럼 배고프면 배고프다고 외치는 매커니즘으로 구현되어야 한다는 거다.

배고프다고 특정 요리사에게 얘기한다면, 이거이 바로 클래스 안에서 다른 클래스를 쓰는 거다.

재사용성이 보장되기 위해선 나 외에 다른 클래스는 아예 알아서도 안된다.

그냥 “나 배고파요~”라고 외치기만 해야 한다.

 

똑같은 쇠구슬 하나를 놓고 은하계의 각 행성마다 다르게 나타나는 질량을 계산하는 클래스에서 중력가속도가 필요하다면 중력가속도를 알려주는 클래스를 이용할 게 아니라,

“XX 행성의 중력가속도를 알려줘요~” 라고 소리치기만 해야 한다는 거다.

실제로 아이폰용 프로그램 개발의 많은 부분이 이런 식으로 이루어지고 있다.

 

이렇게 소리지르고 난리를 치면 담당하는 누군가가 듣고 그 값을 알려준다.

여기서 중요한 건, 질량을 계산하는 클래스는 그 담당자가 누구인지는 전혀 모르고, 그게 누구이건 아무런 상관이 없다는 거다.

기억하자. 우리의 “재사용용성이 보장되는” 클래스는 자기 자신 외에는 아무도 모르고 있어야 한다.

소리만 칠 줄 알아야 한다.

 

버튼의 경우를 보자.

우리는 버튼에게 색상, 크기, label 등을 정해준다.

내가 버튼에게 명령을 내리는거다.

그런데 버튼이 눌려진 처리를 해야 한다면?

 

 

많은 사람들이 위와 같은 그림을 그려놓고 이벤트를 설명하지만, 위 그림은 틀렸다.

 

버튼은 아무런 클래스도 모르는 “재사용성이 뛰어난” 클래스이기 때문에 form에게 자기 버튼이 눌렸음을 알려주지 못한다.

다만 “나 눌렸어요~” 하고 소리치는 것밖에 할 수가 없다. 다른 아무런 클래스도 알지 못하니까 .

그냥 소리만 치는거다.

 

모든 건 form이 다 알아서 한다.

form에서 버튼 클래스를 하나 사용하면서 이 버튼이 “나 눌렸어요~” 라고 소리치면 어떻게 처리할지를 정해놓는거다.

그러면서 계속 버튼 클래스에 귀를 기울이고 있다. “나 눌렸어요~”라고 소리치는지 안치는지 듣고 있는거다.

 

이거 큰 차이다. 버튼 클래스가 form에게 알려주는지, 아님 그냥 소리만 치고 마는거지.

듣는 사람이 없으면 그냥 소리는 공허하게 흩어지고 만다. (실제로 이런 경우는 많다.)

 

자, 이런 게 이벤트다.

한 놈은 소리만 치고, 다른 놈은 소리치는지 듣고 있다가 불편한 거 해결해 주고.

 

뭐라고 소리지를지 미리 약속을 정해놓은 게 protocol이고 이런 체계가 Delegate다.

 

이제 계속 연재를 통해 프로토콜과 Delegate의 동작 방법에 대해 설명하겠다.

 

이 글이 도움이 되셨다면 아래 손꼬락을 꼬옥 눌러주세요. 큰 힘이 됩니다. 그리고 댓글도 남겨주시면 더더욱 크~ㄴ 힘이 됩니다. ^^;






  

iOS에서 Object-C를 이용해 아이폰/아이패드 개발을 할 때 절대 빼 놓을 수 없는 필수 요소가 Delegate이다.

이게 없으면 개발을 할 수가 없을 정도인데, 블로그에서 delegate에 대해 찾아보면 이에 대한 정보가 정말 빈약하다.

그래서 이 연재를 만들기로 했다.

 

Delegate에 대해 이해하려면 꽤 많은 걸 알아야 한다.

 

우선 interface나 abstract class 에 대해 알아야 한다. 자바, C#, 델파이, C++, Action Script에서는 interface나 abstract class 라고 부르지만, Objective-C에서는 protocol이라고 부른다.

 

그리고 callback 에 대해서도 이해해야 한다.

Callback은 단순해서 좀 이해하기 쉬운데, 보통은 A 클래스에서 B 클래스의 메소드를 호출하는 식으로 이용하는 관계에서 그 반대인 B 클래스에서 A 클래스로 호출하는 것을 Callback라고 부른다. 예를 들어 우리는 보통 “Button” 에게 색과, 위치, 표시될 label 등을 설정해 주는 식으로 우리가 Button에게 call을 하는데, button이 눌리는 일이 발생하면 반대로 button이 우리에게 “나 눌려졌어요~” 하고 알려주는 것과 같은 거다. Win 32 프로그래밍을 할 때는 이걸 이벤트라 부르고, iOS의 Objective-C에서는 이런 처리를 Delegate라고 하는 것만 다르다고 하면 되겠다. 

C/C++에서는 이걸 함수 포인터를 이용해서 처리하고, 델파이에서는 이벤트로 처리한다. (이 방면에서는 델파이가 제일 나은 방법을 제공하는 듯 하다.) 자바는 interface / abstract class에 의해 처리하고, C#은 Objective-C와 같은 Delegate라는 이름으로 처리하는데 이름만 다르지 실제 처리하는 밑으로 내려가면 결국은 다 같은 놈들이다.

 

이런 것들을 다 이해해야 Delegate의 동작 원리에 대해 제대로 알 수 있다.

동작 원리를 제대로 밝힌 글들은 없어 내가 한번 써보려 한다.

이 글이 도움이 되셨다면 아래 손꼬락을 꼬옥 눌러주세요. 큰 힘이 됩니다. 그리고 댓글도 남겨주시면 더더욱 크~ㄴ 힘이 됩니다. ^^;






  

이 간단한 걸 기억 못해서 어제 종일 끙끙댔다.

그래서 기록을 남겨본다

 

XCode는 C++ 과 Objective-C 를 동시에 쓸 수 있.. 쓸 수 있을수도 있도록 지원하고 있다.

그래서 나는 중요한 클래스는 그냥  C++ 로 만들고 UI와 관련된 부분만 Objective-C 로 만들려고 생각하고 있다.

 

그런데, 오랜만에 해보니 이게 잘 안되는거다. 블로그 검색해도 잘 나오질 않고.

 

방법은 간단하다.

1. C++클래스를 사용하는 Objective-C 파일의 확장자를 .m 에서 .mm 으로 바꿔준다. .cpp 확장자를 .mm으로 바꾸는 게 아니라, .m 파일의 확장자를 .mm으로 바꾸는거다.

 

이렇게만 해도 되는데, 만약 이래도 안되면,

 

2. .cpp 파일의 속성을 아래와 같이,

"Objective-C++ source" 로 바꿔준다.

스크린샷 2011 10 20 오후 2 57 46 1

 

사실 이게 XCode 3.2때는 꼭 해줘야 했었는데, 이번 4.2에서는 굳이 안해줘도 처음부터 잘 된거 같다. (사실 이것저것 세팅을 건드려서 확실치는 않음. 여튼 안되면 이걸 보자.)

 

그리고 어떤 분이 이렇게 Objective-C에서 C++을 사용하면 생성자와 소멸자가 호출이 안된다는 소문을 내셨는데,

실제 테스트해본 결과 XCode 3.x대와 4.2 모두 C++ 클래스의 생성자와 소멸자가 제대로 호출되는 걸 확인했다.

 

TestUnit에서도 C++ 클래스 잘 인식되고(당연하지만 ㅋ) 넘 기쁘다. 이제 코딩만 남았다. 코딩만.. 남았네.

 

 

이 글이 도움이 되셨다면 아래 손꼬락을 꼬옥 눌러주세요. 큰 힘이 됩니다. 그리고 댓글도 남겨주시면 더더욱 크~ㄴ 힘이 되겠습니다. ^^;






  

오늘 그렇잖아도 시간도 별로 없었는데, 짬날때마다 이것 때문에 삽질 좀 했슴미다.

너무나도 단순한 문제인데 컴파일이 안되어 이거이  XCode 4.2의 버그라고 생각했는데, 역시나 제 잘못이었슴미다.

 

진짜 간단한, Apple에서 제공한 tutorial을 따라하는 중이었는데,

 

#import <Cocoa/Cocoa.h>

 

@interface HelloView : NSView

{

NSString * m_pstrText; // 여기서 보여줄 문자열

}

 

-(void) test;

 

@end

 

위와 같은 클래스를 정의해 놓고, 외부에서 test() 메소드를 호출하겠다고만 하면

 

"AutoreleasePool count reference issue" 라고 시작하는, 암튼 저런 함수가 없다 라는 말도 안되는 컴파일 에러 메시지가 나온다.

 

clean을 아무리 하고 껐다켰다를 반복해도 마찬가지였다.

그래서 이름만 다르게 하고 똑같은 기능을 하는 새로운 클래스를 만들어서 테스트해보니

당연히 잘 된다. 잘 되야 하니까.

 

도대체 왜 안될까를 고민면서 잘되는 파일과 잘 안되는 파일의 속성을 비교해 보았다.

 

이런 저런 속성들을 찾아보다 드뎌 그 문제를 확인했다.

 

XcodeLocation

 

처음 봤을 때, 다른 점은 파란색으로 표시한 "Relative to Project" 부분이었다.

 

Location의 위치가 다른 파일들은 모두 "Relative to Group" 이었는데, 문제가 되는 그 클래스의 파일 2개만 "Relative To Project"였다.

그래서 그 클래스를 위한 2개의 파일을 그냥 다른 조치없이 Location을 "Relative to Group"으로만 바꿔줘 봤다.

 

그래도 여전히 마찬가지로 똑같은 에러가 났다.

 

또 뭐가 문젠가 봤더니 다른 파일들은 모두 다 같은 폴더 안에 있는데, 그 2개의 파일만 다른 위치에 있었다.

그래서 모두 같은 폴더 안에 들어가도록 맞춰줬다.

 

다행히도 XCode는 파일을 우클릭하면 Finder에서 보여주는 기능을 제공한다.

그래서 쉽게 파일의 위치를 조정할 수 있었고, 위 그림에서 빨간색 버튼을 클릭하면 해당 파일의 위치를 다시 잡아줄 수 있다.

 

이런 식으로 파일 위치를 잡아줬더니 문제가 모두 해결되었다.

아마도 XCode에 캐시가 있었던 게 아닌가 싶다.

그래도 Clean을 했는데도 계속 캐시를 쓰면서 에러가 발생한 건 큰 문제다.

 

이렇게 해 놓으니 다시 원래의 상태로 돌려놔도 컴파일 에러가 발생하지 않는다.

 

도대체 왜 이러는지 많이 궁금했는데, 이제 원인도 파악하고 문제도 해결되어 넘 개운하다. 하하.

이 맛에 파고드는거지 모.

 

 

이 글이 도움이 되셨다면 아래 손꼬락을 꼬옥 눌러주세요. 큰 힘이 됩니다. 그리고 댓글도 남겨주시면 더더욱 크~ㄴ 힘이 되겠습니다. ^^;






  
오랜만에 프로그래밍 관련 글을 쓰는군요. 

자바의 Object 나 iOS의 id에 대해 궁금해 하시는 분이 계셔서 글을 쓰게 되었습니다. ^^;

자바의 Object에 대해 먼저 설명하겠습니다.


Object는 클래스다.  

자바의 Object는 클래스입니다.

자바에는 무수히 많은 클래스가 있습니다. 거의 모든 걸 다 클래스로 만들어 놓았죠. 그래서 자바를 만든 제임스 고슬링의 별명이 "Every thing is classes" 라고 합니다. 이 말은 굳이 클래스로 만들지 않아도 될 것을 클래스로 다 만들어서 속도저하를 일으키고 있다는 걸 빗대고 있는 거라 생각되네요.

암튼. 자바에 무수히 많은 클래스가 있는데, 그 클래스들마다 공통으로, 반드시, 꼭 구현되어야  하는 기능들이 있습니다.

자동차를 예를 들어 보죠. 자동차는 반드시 가고, 서고, 방향 바꾸고. 이렇게 3가지 기능이 반드시 구현되어 있어야 합니다. 

자동차라는 게 종류도 많고 가격도 천차만별에 모양 색깔 기능.. 다 다른데, 반드시, 꼭 구현되어야  하는 기능들이 있습니다.
 




이런 식인거죠.

모든 자동차들은 가다, 서다, 방향기능을 꼭 가지고 있어야 합니다.

마찬가지로 자바의 클래스들도 꼭  가지고 있어야 하는 기능들이 있습니다.





그 클래스가 생성되고, 소멸되는 기능들, 그리고 그 클래스의 이름.. 기타 등등 모든 클래스들이 자바 클래스로서 갖추어야 할 기본 덕목들.. 아니 기본 기능들과 속성들이 있습니다.

이런 기능들을과 속성들을 학점 클래스 만들 때마다 구현해 주고, 학생 클래스 만들 때마다 다 구현해 줘야 할까요?
어떤 사람은 클래스의 이름을 위해 name 이라는 변수로 만들고, 어떤 사람은 _name, 어떤 사람은 Name, 어떤 사람은 m_classname.. 기타 등등.

사람마다 다 틀리게 만들어서 무지막지 혼란스러울 겁니다.

그래서 클래스 하나를 딱 정해놓고 기본적으로 필요한 기능과 속성들을 정리했죠.

그것이 바로 당신이 알고 싶어하는 바로 그 Object 클래스인 겁니다.


모든 자바 클래스는 Object 클래스를 상속받습니다. 

굳이 명시 안해도 이미 Object 클래스를 상속받았다고 간주됩니다.



Object는 최상위 클래스다. 그래서 대표성을 지닌다.
 


그런데, 이 Object 클래스에 한가지 더 재밌는게 있슴미다.

모든 클래스는 Object 클래스를 상속받는다고 했습니다.

그럼 여기에 이런 관계가 성립합니다.

학생 클래스는 Object 클래스다. (O)
Object 클래스는 학생 클래스다. (X)

잘 이해가 안되죠. 이 말은, 

한국사람은 사람이다. (O)
사람은 한국사람이다. (X)

이 관계와 같습니다.

[하위 클래스]는 [상위클래스]다. 는 성립하지만, 그 반대는 성립하지 않습니다.

만약 프로그래밍할 떄 저 반대가 성립하는 것처럼 프로그래밍하면(실제로 이렇게 하는 사람 있음. 형변화에 엄격하지 않은 Object Pascal에서 이렇게 하는게 가능함. ㅋ. 결과가 골때림. 그 자리에서 에러가 안나고 다른 자리에서 에러가 나기 떄문에 이거 일주일짜리 디버깅 꺼리임) 프로그램이 불규칙하게 죽는 현상이 발생할 수 있습니다. 

그래서 이게 가능합니다.

Object obj = 학생클래스 인스턴스;

반대는 성립하지 않습니다.  

이렇게 Object 클래스는 모든 클래스의 최상위 클래스로 대표성을 가지기 떄문에

Object 클래스의 인스턴스는 모든 클래스의 인스턴스를 받을 수 있습니다. 

Object obj = 학생클래스 인스턴스; (O)
Object obj = 교수클래스 인스턴스; (O)
Object obj = 학점클래스 인스턴스; (O)



그럼 iOS의  id는?

iOS의 id는 약간 개념이 다릅니다. 클래스가 아닌거죠.

그냥 변수입니다. 

C를 하셨던 분들은 다 아실만한 void * 인 겁니다.

그냥 포인터를 받는 변수입니다. 좀 길게 말하면 클래스 인스턴스의 주소를 저장하는 변수인거죠.

이 글이 마음에 드시면 아래 손꼬락을 꼬옥 눌러주세요. ^^