필자는 처음 아이폰이 발표되었을 때 상당한 충격을 받았습니다. 그리고 아이폰을 통해서 그동안 모르고 지냈던 새로운 세계를 발견하게 되었습니다. 아이폰 SDK로 애플리케이션을 개발하고, 앱 스토어를 통해서 제품을 판매하는 여러가지 과정을 경험하면서 앱스토어가 가지고 올 새로운 변화에 주목하게 되었습니다. 애플은 완전히 새로운 생태계(Ecosystem)인 앱스토어를 성공적으로 만들어냈습니다. 앱스토어를 통해서 개발자는 자기가 개발한 애플리케이션을 손쉽게 세상에 내 놓을 수 있게 되었습니다. 어제 개발한 애플리케이션이 내일이면 미국, 멕시코, 유럽 등 세계 모든 곳으로 퍼져 나갑니다. 지금껏 가지지 못한 배포의 자유를 얻게 된 것입니다.
필자는 이 책에서 아이폰 애플리케이션을 개발하기 위한 모든 내용을 설명할 것입니다. 그리고 모든 내용을 아이폰 SDK 3.0을 기준으로 작성했습니다. 이 책의 목적은 독자가 아이폰 애플리케이션을 쉽게 개발하고 세상에 내 놓을 수 있도록 하는 것입니다.
읽기 쉽고 재미있는 책을 만들기 위해서 그림과 삽화를 최대한 넣으려고 노력했습니다. 또한 모든 주제에 대해 예제를 이용해서 직접 개발할 수 있도록 했습니다. 예제는 (특별한 언급이 없는 한) 모두 필자가 개발하고 실제 장비에서 테스트를 진행한 것입니다. 특히 푸시 통보 서비스(Push Notification)를 제공하는 서버 구현 방법을 윈도우와 리눅스 플랫폼에 대해서도 설명했습니다. 그리고 스토어 킷을 통해서 직접 제품을 등록하고 판매할 수 있도록 한 지하철 노선도 예제도 자랑할 만한 예제 입니다. 그 외에도 인터넷 라디오, 게임킷을 활용한 예제, 멀티 터치와 OpenGL 예제 등 재미있는 예제가 많습니다.
이 책이 아이폰 애플리케이션을 개발하고자 하는 독자들에게 좋은 출발점이 될 수 있다면 더 이상 바랄것이 없을 것입니다.
감사의 글
먼저 책의 출판을 결정해 주신 인사이트 출판사의 한기성 사장님에게 감사 드립니다. 그리고 정말 놀라운 꼼꼼함으로 이 책의 수많은 오류를 잡아주신 김승호 편집자님에게 감사의 마음을 전합니다. 아직 이 책에 오류가 남아있다면 모두 필자의 탓입니다.
책의 4장을 리뷰해 주신 이창희(http://www.cocoadev.co.kr/)님, 3장과 13장을 리뷰해 주신 박종암(http://jongampark.wordpress.com/)님에게 감사의 마음을 전합니다.
7장의 MD2 예제의 주요 클래스를 구현하고 이 책에서 사용할 수 있도록 허락해 준 제임스 휘(James Hui)에게 감사의 마음을 전합니다. 그리고 8장의 스트림 예제에서 사용된 클래스를 작성해서 이 책에서 사용할 수 있도록 허락해 준 맷 갤래거(Matt Gallagher)에게도 감사의 말을 전합니다.
마지막으로 언제나 옆에서 든든한 지원군이 되어준 아내와 곧 태어날 딸에게도 사랑을 전합니다.
2009.7.18
강덕진
목차는 다음과 같습니다.
1장 안녕! 아이폰!
1.1 아이폰의 등장
1.2 아이폰/ 아이팟 터치 모델
1.3 아이폰 OS 3.0의 새로운 기능
1.4 이 책이 다루는 내용
1.5 새로운 도전
2장. 설치 및 개발 환경 구축
2.1. 개발에 필요한 시스템
2.1.1. 개발에 필요한 시스템 사양
2.2. 아이폰 SDK 설치
2.2.1 아이폰 SDK 설치하기
2.3. Xcode
2.3.1. 프로젝트 템플릿
2.3.2 Xcode 화면 구성
2.4 인터페이스 빌더
2.4.1 인스펙터
2.4.2 라이브러리
2.4.3 문서 창
2.4.4 연결 패널
2.5 도움말 접근하기
2.5.1. 조사 도우미
2.5.2. 도움말 창
2.5.3 고급 검색
2.5.4. 편집기의 문자열을 도움말 창에서 바로 검색하기
2.5.5 도움말 문서의 형태
2.6 아이폰 레퍼런스 프로젝트
2.6.1 프로젝트 생성
2.6.2 인터페이스 빌더로 화면 디자인하기
2.6.3 코드 입력하기
2.7. 아이폰 시뮬레이터
2.7.1 터치 조작
2.7.2 리셋하기
2.8 정리
2.8.1 참고 사이트
3장 동작 환경 이해하기
3.1 아이폰 동작 환경
3.2 애플리케이션 번들
3.3 Info.pList 파일
3.4 애플리케이션 델리게이트
3.5 핵심 디자인 패턴
3.5.1 델리게이트(delegate)
3.5.2 데이터 소스(Data Sources)
3.5.3 타깃-액션 (Target-Action)
3.5.4 통보(Notification)
3.5.5 키-값 감시(Key-Value Observing)
3.6 아이폰 링크
3.6.1 메일
3.6.2 전화 걸기
3.6.3 문자(SMS) 보내기
3.6.4 지도 보기
3.6.5 아이튠스
3.6.6 유튜브(U-Tube) 연결하기
3.7 커스텀 URL 스키마 만들기
3.8 정리
4장 화면을 이루는 기본 : 뷰
4.1 UIWindow
4.2 UIView와 UIViewController
4.3 뷰를 직접 만들어 보자
4.3.1 이미지 준비
4.3.2 코드 작성
4.3.3 직접 만든 뷰를 화면에 추가하기
4.4 UI 브로슈어 프로젝트
4.5 이미지 뷰(UIImageView)
4.5.1 인터페이스 빌더를 이용한 화면 디자인
4.5.2 코드 작성
4.5.3 이미지 선택하기
4.5.4 애니메이션 설정
4.6 웹 뷰(UIWebView)
4.6.1 디자인하기
4.6.2 코드 작성하기
4.6.3 PDF를 보여주자
4.7 텍스트 입력과 키보드
4.7.1 화면 구성
4.7.2 코드 작성
4.7.3 키보드 숨기기 팁
4.7.4 키보드 관련 통보(Notification) 이용하기
4.8 피커 뷰
4.8.1 코드 분석
4.8.2 슬롯머신 게임 만들어 보기
4.8.3 XIB에 객체 추가하기
4.8.4 로직 구현
4.9 알림, 경고창
4.9.1 인터페이스 빌더에서 클래스 내보내기
4.9.2 병합하기
4.9.3 UIAlertView 코드 작성
4.9.4 UIActionSheet 코드작성
4.10 스크롤 뷰
4.10.1 스크롤, 확대, 축소 구현하기
4.10.2 스크롤에 따른 지도확장
4.10.3 확대에 따른 지도 재설정
4.10.4 자바스크립트에서 Objective-C 객체에 이벤트 보내기
4.11 맵 뷰(MKMapView)
4.11.1 화면 디자인
4.11.2 코드 작성
4.11.3 직접 표시 추가하기
4.11.4 표시 직접 구현하기
4.12 정리
5장 뷰를 담는 그릇 : 뷰 컨트롤러
5.1 회전에 대비하기
5.1.1 자동 회전(AutoRotate)
5.1.2 자동 크기 조절
5.1.3 자동 크기조절의 한계
5.2 테이블 뷰와 테이블 뷰 컨트롤러
5.2.1 데이터 소스
5.2.2 인덱스 이용하기
5.2.3 셀을 직접 꾸미기
5.2.4 검색 기능 넣기
5.2.5 테이블 뷰 정리
5.3 내비게이션 컨트롤러
5.3.1 내비게이션 컨트롤러 생성하기
5.3.2 내비게이션 아이템 설정
5.3.3 편집 / 완료
5.3.4 테이블 뷰의 항목 이동
5.4 탭 바 컨트롤러
5.4.1. 구현하기
5.4.2 탭 바 아이콘
5.4.3 배지(Badge)
5.5 이미지 피커
5.6 이메일 뷰 컨트롤러
5.7 정리
6장. 이벤트 처리
6.1 UIResponder와 응답 체인
6.1.1 기본 메서드
6.1.2 아이폰 OS 3.0에 추가된 메서드
6.1.3 UIResponder 체인 메서드
6.1.4 이벤트 흐름
6.2 멀티 터치 동작 원리
6.2.1 첫 번째 손가락
6.2.2 손가락 움직이기
6.2.3 멀티 터치
6.2.4 손 때기
6.3 멀티 터치 구현하기
6.4 두드림(tap)
6.5 닦아내기(Swipe)와 집기(Pinch)
6.5.1 닦아내기
6.5.2 집기(Pinch) 동작
6.6 흔들기와 실행 취소, 실행 복귀
6.6.1 NSUndoManager
6.7 베껴두기와 붙이기
6.8 정리하기
7장. 그래픽과 애니메이션
7.1 쿼츠(Quartz)
7.1.1 직선 그리기
7.1.2 사각형
7.1.3 다각형 그리기
7.1.4 이미지/비트맵 그리기
7.1.5 PDF 그리기
7.1.6 그래디언트 (Gradient)
7.1.7 글꼴 (Font)
7.1.8 베지어(Bezier) 곡선
7.1.9 쿼츠 정리
7.2 코어 애니메이션
7.2.1 속성 변화 애니메이션
7.2.2 고급 속성 변화 애니메이션
7.2.3 전환 효과 (Transition)
7.3 UIView 애니메이션
7.4 OpenGL
7.4.1 프로젝트 생성
7.4.2 MD2 모델 뷰어
7.4.3 OpenGL 정리
7.5 정리
8장. 동영상과 사운드
8.1. 오디오 형식
8.2 오디오 재생
8.2.1 짧은 효과음과 진동
8.2.2 일반 오디오 재생하기
8.2.3 AVAudioPlayer로 재생하기
8.3 오디오 큐 서비스
8.3.1 녹음하기
8.3.2 녹음 시간 표시하기
8.3.3 재생하기
8.3.4 UI 업데이트를 위한 콜백
8.4 오디오 세션
8.4.1 AVAudioSession
8.5 네트워크 오디오 스트림
8.6. 동영상 재생
8.7 아이튠스 라이브러리 접근하기
8.8 정리
9장. 아이폰 자원 활용
9.1 장치 정보 얻기
9.2 가속도계 이용하기
9.3 주소록 프레임워크
9.3.1 검색하기
9.3.2 수정하기
9.3.3 주소록 UI (AddressbookUI)
9.4 파일에 저장하기
9.4.1 접근할 수 있는 디렉터리
9.4.2 프로퍼티 리스트
9.4.3 고급 프로퍼티 리스트
9.4.4 아카이브 (Archive)
9.5 SQLite
9.5.1 데이터베이스 열기
9.5.2 쿼리 하기
9.5.3 데이터 변경하기
9.5.4 데이터베이스 닫기
9.6 코어 데이터
9.6.1 관리 객체 컨텍스트 생성하기
9.6.2 관리 객체 컨텍스트에 객체 가져오기
9.6.3 관리 객체 추가, 삭제
9.6.4 저장소에 기록하기
9.6.5 코어 데이터 정리
9.7 코어 로케이션
9.8 정리하기
10장. 네트워크 프로그래밍
10.1 푸시 통보 서비스 (Push Notification Service)
10.1.1 인증서 준비하기
10.1.2 OpenSSL
10.1.3 프로바이더 구현
10.1.4 메시지 구조
10.1.5 애플리케이션 구현
10.1.6 피드백
10.2 피어 투 피어 연결
10.2.1 예제 프로젝트 생성
10.2.2 델리게이트
10.3 음성 대화 추가하기
10.3.1 오디오 세션 설정하기
10.3.2 GKVoiceChatClient 프로토콜 구현
10.3.3 받은 데이터 알려주기
10.3.4 client 연결
10.3.5 대화 시작
10.4 정리
11장 설정 번들(Settings.bundle)
11.1 설정 애플리케이션이 설정 번들을 찾는 방법
11.2 예제 작성
11.3 설정 번들 파일 디자인하기
11.3.1 문자열 입력 추가하기
11.3.2 참, 거짓 스위치
11.3.3 다중 값 선택
11.3.4 슬라이더 추가하기
11.3.5 자식 항목 추가하기
11.4 새로운 파일을 설정 번들에 추가하기
11.5 지역화
11.6 애플리케이션에서 설정 값 접근하기
11.7 정리
12장 디버깅 가이드
12.1 Xcode로 디버깅하기
12.1.1 Xcode 화면 구조 설정하기
12.1.2 브레이크 포인트 설정하기
12.1.3 코드 실행하기
12.1.4 Objective-C 메서드에 브레이크 걸기
12.1.5 브레이크 포인트를 소리로 알려주기
12.1.6 브레이크 포인트에 동작 지정하기
12.2.7 와치 포인트 설정하기
12.2.8 메모리 덤프하기
12.2.9 디버깅 중이 아닌 애플리케이션의 NSLog 보기
12.3 인스투르먼츠(Instruments)
12.3.1 Leaks (메모리 누수 감지하기)
12.3.2 OpenGL ES 성능 확인
12.3.3 Activity Monitor
12.3.4 정리
12.4 Clang 정적 분석기
12.4.1 프로젝트 설정하기
12.4.2 설치하기
12.4.3 분석 진행
12.5 정리하기
13장 프로그래밍 기법과 팁
13.1 통보 (Notification)
13.1.1 통보 큐
13.2 프로퍼티와 접근자(Accessor)
13.2.1 synthesize 팁
13.2.2 프로퍼티 선언
13.2.3 메모리 해제
13.3 키-값 코딩 (Key-Value Coding)
13.3.1 예외 상황
13.4 키-값 감시 (Key-Value Observing)
13.4.1 수동으로 알리기
13.5 객체를 비교하는 방법
13.6 문자열 다루기
13.6.1 C 문자열로 초기화하기
13.6.2 문자열을 형식 문자로 구성하기
13.7 타이머 (NSTimer)
13.7.1 지정한 시간에 타이머 시작하기
13.8 스레드 기초
13.8.1 스레드 생성하기
13.8.2 스레드 메서드 구현하기
13.8.3 런 루프
13.8.4 스레드의 대안
13.9 메모리 관리
13.9.1 규칙1
13.9.2 규칙2
13.9.3 규칙3
13.9.4 규칙4
13.9.5 규칙5
13.9.6 규칙6
13.9.7 규칙7
13.10 빌드 시에 시뮬레이터와 실제 장치 구분하기
13.11 빌드 시에 SDK 버전 구분하기
13.12 무료 버전 타깃 구성하기
13.13 정리
15장 배포와 스토어 킷
15.1 개발을 위한 준비
15.1.1 개발 인증서 발급
15.1.2 개발 장비 등록
15.1.3 애플리케이션 ID (AppID) 만들기
15.1.4 프로비전 만들기 (Provisioning)
15.1.5 프로젝트 설정
15.2 배포 준비
15.2.1 배포 인증서
15.2.2 배포 프로비전
15.2.3 프로젝트 설정
15.2.4 AdHoc 프로젝트 설정
15.2.5 빌드 및 배포
15.2.6 Ad hoc 배포 사용하기
15.3 애플리케이션 내 판매 (In-App Purchase)
15.3.1 스토어 킷을 위한 사전 준비
15.3.2 스토어 킷의 클래스
15.3.3 상품 정보 얻기
15.3.4 구매하기
15.3.5 과거에 구매한 내역
15.4 정리
15.4.1 마치며
얼마 전까지만 해도 개발자 세상에서 아이폰 프로그래밍은 빠뜨릴 수 없는 이야깃거리였고, 조금 차분해지긴 했지만 여전히 많은 분들이 아이폰 프로그래밍에 관심을 가지고 계시리라 생각합니다. 특히, 지난 6월 애플에서 아이폰 SDK 3.0을 소개했을 때는, '바로 이거다!' 싶은 새롭고 재미있는 기능들이 여럿 소개되었는데요. 백그라운드 프로세스의 효과를 얻을 수 있는 '푸시 통보 서비스(push notification service)' 아이폰끼리 연결할..
많은 개발자들이 Objective-C 의 메모리 관리를 어렵게 느낀다. Objective-C 에서 객체는 참조 카운터를 이용해서 관리되기 때문에, 참조 카운터를 증가 시키고 감소하는 작업이 프로그래머의 몫이 된다. 여기서 혼돈이 오는 것이다. 참조 카운터를 증가시키는 함수는 retain 이다. 반대로 참조 카운터를 감소시키는 함수는 release와 autorelease 이다. 하지만 문제는 이미 만들어진 객체의 메서드가 내부에서 retain 을 몇번 부르는지를 별도로 알아낼 방법이 없다는 것이다. 다음을 보자.
이 코드에서 UIImageView 는 retain 내부에서 한번 호출해서 객체를 반환해 준다. 그렇기 때문에 우리는 더이상 필요하지 않을때,
[imgView release];
를 호출해야 한다. 하지만 다음을 보자.
NSString* output = [NSString stringWithFormat:@”My name : %@”, name];
이 코드는 NSString의 stringWithFormat 클래스 메서드를 이용해서 객체를 생성하는 코드이다. 이 녀석은 retain 이 아닌 autorelease 를 호출해서 객체를 반환한다. 이렇게 어떤 메서드는 객체를 retain 해서 반환하고, 또 어떤 객체는 autorelease 로 반환하기 때문에 혼돈이 온다.
참조 카운트를 관리하는 함수는 다음과 같다.
• retain
- 참조 카운트를 1 증가 시킨다.
• release
- 참조 카운트를 1 감소시킨다. 참조 카운트가 0이 되면 메모리가 해제된다.
• autorelease
- 객체를 오토릴리즈 풀에 등록한다. 나중에 오토릴리즈 풀이 제거될때 release 를 호출해 준다.
객체의 참조를 관리하는 것은 위 3개의 메서드가 전부이지만, 문제는 클래스 내부 구현에서 위 함수들을 호출하는 지를 모른다는 점이다. 하지만 법칙이 있다. 애플이 작성한 모든 클래스는 정해진 규칙을 철저하게 따르기 때문에 이 법칙들만 알아두면 더 이상 햇갈릴 일이 없다.
* 규칙1 : alloc, copy, new를 이름에 포함하는 메서드는 retain 된 객체를 반환한다.
alloc, copy, new 가 메서드 이름에 포함되어 있다면, 그 때 반환되는 객체는 retain 되어 있다. 그래서 반드시 release 를 직접 호출해야 한다.
코드 1행의 imageNamed 메서드 처럼 클래스 메서드를 이용해서 객체를 생성하는 경우 그 객체는 autorelease 가 호출된 객체이다. 그렇기 때문에 별도로 release 를 호출하지 않아도 오토릴리즈 풀이 자동으로 release 를 호출해 준다. 하지만 이 객체에 retain 을 호출 했다면 호출한 만큼의 release 를 호출 해야한다.
* 규칙4: 포함 객체는 추가된 객체를 retain 하고, 항목을 제거할 때 release 한다.
NSArray,NSDictionay 등의 포함 객체는 항목으로 추가되는 객체에 대해서 retain 을 한번 호출한다. 그리고 객체가 포함객체에서 제거될때 release 를 호출해 준다.
13.9.5 규칙5: retain 속성을 갖는 접근자
프로퍼티를 구성할때 @property (retain) ... 과 같이 retain 속성을 지정하면 이 프로퍼티에 객체를 설정하면 retain 메서드를 호출한다.
01: myImage = [[UIImage alloc] init]; // myImage 에 retain –> 1
02: self.userImage = myImage; // myImage 에 retain –> 2
03: [myImage release]; // myImage 에 release –> 1
04: // ...
05: self.userImage = myImage2; // 예전 myImage 에 release -> 0 해제
이와 같이 객체를 설정하는 접근자는 일반적으로 그 객체에 대해서 retain 을 호출한다. 그리고 만약 다른 객체를 재설정하면, 예전 객체에 release 를 호출한다. 위 예제의 3행에서 release 를 호출한 이유를 이해할 것이다.
내가 만든 앱이 각 나라별로 과연 몇등이나 하고 있을까 ?
간단하게 확인할 수 있는 툴이있다.
사실, 이 툴을 개발한 개발자는 이 툴을 아이폰 버젼으로 판매하려고 했는데 애플에서 리젝을 먹었다고 한다.
맥 데스크탑으로는 공짜로 프로그램을 공개하고 있어서 한번 다운로드 받아서 실행시켜 보았다.
놀랍게 치킨푸쉬가 100위 안에 드는 나라가 있었다.. 싱가포르에서는 27위다.. 물론 Board 게임 카테고리에서만 해당한다. 그리고 슬픈 소식은 Free 버젼만 그렇다는 것이다. 유료버젼은 ?? 볼 용기가 안났다. (내 투자금 ㅠㅠ)
인터페이스는 아주 직관적이고, 검색한 결과를 히스토리로 저장해 놓을 수 있기 때문에 나라별 순위 흐름을 파악하는데 아주 좋을 것이다.
짧은 느낌을 추가하자면,
"애플의 앱스토어.. 정말 전세계를 상대로 하는구나.. 정말 가본적도 없는 나라사람들이 내 어플리케이션을 받고 사용한다는게 무척 떨리고 기분 좋다. 이게 앱스토어의 힘, 오픈의 힘이구나.."
자신의 앱을 등록한 분들은 아래 링크에서 프로그램을 받아서 실행해 보기 바란다.. *링크*
만약 애플이 리젝을 하지 않았다면 정말 대박이 났을 어플리케이션이다. 개발자의 블로그에 가면, 앱스토어를 통해서 구입할 수는 없지만 소스를 따로 돈을 받고 판매하는것 같다. 아무래도 정상적인 방법으로 AppStore의 DB에 접근하는 것이 아니라서 리젝을 먹은것 같은데, 정확히는 보지않았다.
애플의 앱스토어가 현재의 모바일 기기에 머물러 있을 이유는 별로 없다. 10인치 아이팟 루머에서도 연상할 수 있듯이, 모바일 기기는 점점 더 커지고 있다. 물론 들고다닐 수 있을 정도까지만 커지겠지만, 점점 더 사용하기 편리해 지는 것은 맞다.
10인치나 7인치 정도는 사용자가 큰 무리없이 컴퓨팅을 할 수 도 있는 크기라고 볼 수 있다. 3.5인치와는 완전히 다르다. 현재 컴퓨팅 시장에서 넷북이나 모바일PMP가 대세이듯 멀지않은 미래는 적당히 큰 크기의 헨드핼드 시스템이 보편화 될 것이다. 그리고 넘처나는 기기는 여러가지 응용 사례를 파생시켜 실제로 우리가 생각하는 말 그대로의 유비쿼터스를 만들것 같다.
그렇다면 다시 앱스토어를 생각해 보자. 앱 스토어의 어플리케이션은 기존의 번들시장과 기존의 소프트웨어 유통을 대체해 내갈 수 있을 것이다. 개발자는 자신의 소프트웨어를 앱스토어를 통해서 판매하는데, 그 대상은 일반 데스크톱 어플리케이션 까지 확장할 수 있는 것이다. 그렇게 되면 데스크톱이든 모바일이든 자신이 사용하는 OS의 앱스토어에서 소프트웨어를 검색하고 구입할 수 있을 것이다.
현재 아이폰의 AppStore 가 (독점적으로) 오직 하나의 경로로 어플리케이션을 배포할 수 있는 이유는 닫혀 있기 때문이다. 아이폰의 파일 시스템은 공식적으로는 닫혀있다. 어플리케이션들은 철저히 샌드박싱되어 있다. 하지만 PC와 MAC은 충분히 열려있고, 사용자는 너무나 쉽게 소프트웨어를 복제할 수 있다. 이 부분이 데스크톱 앱스토어의 가장 큰 문제가 될 수 있다. 하지만 궁극적으로 우리는 앱스토어라는 진보의 단맛을 보았기 때문에, 데스크톱에서의 앱스토어는 충분히 가능하고, 설명한 문제들은 해결책이 나올 것이라고 생각된다.
상상만 해도 멋지다. 물론 개발자이기 때문에 그럴 수도 있지만..
"앗 워드프로세서가 필요해 어떤걸 사지.. 앱스토어에 가보자.. 음 이게 평가가 제일 좋구나.. 이걸 다운로드 받자. 음 9.99불이라 괜찮네!!!"
개발자 프로그램에 등록했기 때문에, iPhoneSDK 3.0을 받을 수 있다. 그래서 SDK도 3.0을 설치했다.
이렇게 했을때, 3.0 에서만 지원하는 기능을 사용했을 경우 2.2 에서는 컴파일 에러가 나게 된다.
이것을 막기 위해서 현재 빌드하고 있는 타깃의 iPhone OS 의 버젼을 판단할 수 있는 다음 매크로가 유용하게 사용될 것이라고 생각했다.
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_3_0 // 3.0 에서가 가능한 코드 작성 #endif
하지만 재미있는 것은, 기존의 2.0 SDK에는 __IPHONE_3_0 이라는 녀석의 define 조차 없다는 것이다.
그래서 위의 매크로만으로는 문제를 해결해 주지 못한다. 해결하기 위해서는 #ifndef 도 추가해 주자.
더 좋은 방법이 있을 것같은데, 혹시 아이디어가 있으시면 알려주시길...
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_3_0 #ifdef __IPHONE_3_0 // 3.0 에서가 가능한 코드 작성 #endif /*#ifdef __IPHONE_3_0 */
#endif
이 포스트는 필자가 마이크로소프트웨어 2009년 4월호 특집기사에서 아이폰 SDK 3.0 에 대해서 간략히 소개한 부분을 발췌한 것이다.
지난 3월 말에 아이폰 3.0에 대한 발표가 있었다. 정식 공개는 아니고, 개발자들에게만 베타 버젼이 공개되었다. 하지만 애플 스스로가 광고하듯이 아주 많은 기능 개선이 있었다. 그 중에서 의미있는 몇 가지를 살펴보도록 하자.
1. 애플리케이션 내에서 컨텐츠 판매 (In-app-purchase)
- 어플리케이션 내부에서 컨텐츠를 판매할 수 있게 되었다. 예를들어 e-book 또는 잡지 어플리케이션을 생각해 보자. 고객이 새로나온 최신호 잡지를 잡지 어플리케이션 내부에서 바로 구입해서 볼 수 있고, 또 헤리포터 e-book 어플리케이션이라면 새로운 시리즈가 나왔을때 e어플리케이션 안에서 구매할 수 있게 되는 것이다. 다른 활용 방안으로는 게임의 경우 확장판이나 추가 스테이지 또는 아이템을 구매할 수 있거나 하는 식이다. 하지만 무료 어플리케이션내에서는 컨텐츠 판매가 불가능 하다는 제한점이 있다. “공짜 프로그램은 그냥 공짜로 두자.” 는 철학을 유지하고 있다.
2. Peer to Peer
주변의 아이폰 또는 아이팟 터치를 검색해서 Peer to peer 통신이 가능하도록 해 준다. 블루투스 네트워크를 이용해서 주변에 있는 Peer를 검색해서 같이 게임에 참여할 수 있도록 기반 API가 새롭게 추가되었다. 제공되는 API를 통해서 개발자는 Pairing 등의 하위 레벨에 대한 부분은 생각하지 않아도 된다.
3. 악세서리 접근
아이팟을 위한 악세서리와 통신할 수 있다. 발표 동영상에서 든 한 가지 예는 병원에서 사용되는 혈압계인데, 협압계를 아이폰에 연결하고, 측정된 혈압을 아이폰 Application 에서 읽어서 표시할 수 있는 것이다.
<그림> 혈압계 악세서리와 아이폰 어플리케이션
4. 푸쉬 통보 서비스 (Push notification service)
백그라운드 프로세스는 여전히 지원하지 않는다. 하지만 푸쉬 통보 서비스를 통해서 어플리케이션을 대신해서 Push notification server 가 필요한 이벤트를 중계하고 아이폰 OS 에서 자체적으로 Push 서버와 통신해서 해당 어플리케이션에 알려주는 방식이다. 이제 메신저 등의 어플리케이션도 개발이 가능해 지게 되었다. 또한 온라인 게임에서 친구가 게임을 하지 않고 있더라고 그 친구를 초대하는 등의 기능이 구현 가능해 졌다.
5. 아이팟 라이브러리 접근
드디어 어플리케이션에서도 아이팟의 음악과 비디오에 접근할 수 있게 되었다.
6. Copy & Paste
- 사용자의 불만이 가장 많았던 부분이었는데 드디어 추가되었다. 입력한 내용이나 웹 페이지에서 필요한 부분을 복사해서 편지나 메모장에 붙여넣기 하는 작업은 아주 빈번하게 사용지만 그동안 지원되지 않았었다.
물론 기대는 컸지만, 현실은 냉혹했다. ㅠㅠ
하지만 좀더 많은 사람들이 썼으면 하는 마음에서 프리버젼을 배포해야 겠다고 생각했다. 그래서 Xcode 의 프로젝트 에서 어떻게 쉽게 Lite 버젼을 위한 타깃을 자동으로 만들고, 하나의 프로젝트를 그대로 유지할 지 생각해 봤다.
기존의 많은 개발툴과 방식은 같다. 일단 내가 사용한 방법은, Target 을 하나 추가하는 것이다.
AAA 라는 기존의 타깃에서 AAA Lite 라는 타깃을 추가하는 것이다.
위의 경우 aurioTouch 라는 타깃 하나만 있다. 여기서 다음 메뉴에서 Add Target ... 을 통해서 타깃을 추가하도록 하자.
선택하면 창이 하나 뜨는데 Application 타깃이므로 Application을 선택하고 이름을 입력하도록 하자.
타깃이 추가되었기 때문에, 이제 타깃에 해당하는 프리프로세서를 이용해서 코드 상에서 일반 버전과 프리 버전간의 차이를 만들어 나가면 된다. 프리프로세서를 추가하는 방법은,
슈퍼몽키볼은 아이폰SDK가 최초 공개될 때 같이 소개되었던 세가의 게임이다. 실제로 앱스토어가 처음 오픈했을 때도 가장 많은 인기와 관심을 받았던 게임이기도 하다. 이번에 샌프란시스코에서 열린 게임개발자회의 (Game Developers Conference 2009)의 모바일 세션에서 세가의 프로듀서인 이단 에인혼(Ethan Einhorn)와 Other Ocean의 크리스 샤플리(Chris Sharpley)가 밝힌 10가지 교훈을 소개한다. 아이폰 게임을 개발함에 있어서 도움이 될 만한 코멘트일 것이다. (급하게 Rough한 번역임을 이해해 주기 바란다. ^^; )
* 세가(Sega)의 교훈
1. 사용자의 피드백에 귀기울여라.
2. 가격 전쟁에 편승하지 말자.
3. "라이트" 버전의 장단점을 고려할것. 자신이 개발한 게임의 조작법이나 방식이 새로운 형태일 경우에는 시험판을 제공해서 쉽게 익숙해질 기회를 주는 것은 좋은 경우라고 볼 수 있지만, 그렇지 않고 직관적인 게임들의 경우에는 이 라이트 버전이 정식판의 판매와 경쟁하게 되는 경우가 생길 수 있다.
4. 많은 사용자들이 그 게임을 처음 접하는 것이기 때문에, 적절한 브랜드를 갖거나, 새로운 사용자에게도 완벽하게 접근가능하도록 해야 한다.
5. 아이폰의 경우 사용자 리뷰가 절대적이다. 유명 리뷰사이트의 리뷰는 거의 무의미할 정도다. 사용자들은 사용자리뷰에 대해서 개발자가 세심하게 대응하는지 유심히 살펴본다.
6. 너무 어렵게 만들지 말것. 쉽게 만들려고 노력했지만 많은 사용자들이 어렵다고 호소했다. 게임을 끝까지 깰 수 있는 가능성을 보여줘야 한다.
7. 그 장치에 맞게 개발하자. 애플이 슈퍼몽키볼에 관심을 보인것은 아이폰이라는 장치의 가속도계에 잘 어울리는 제품이었기 때문이다.
8. 10초안에 사용자를 사로잡아야 한다. 일반 게임기 게임들의 경우는 5분이나 10분이 주어진다면 아이폰은 10초다. 사용자들은 바로 다운받고, 바로 플래이하지만, 또 관심을 돌릴만한 다른 무료 게임들도 넘쳐난다.
9. 간단하게! 몽키볼의 Wii 버젼은 아이폰 버전보다 더 복잡하다.
10. 플레이하는 환경을 고려할 것. 처음 몽키볼을 런칭했을때 사용자들이 10 스테이지까지 모두 마쳐야 게임을 저장할 수 있도록 하는 실수를 저질렀다. 하지만 아이폰은 언제든 전화가 올 수 있다. 언제든 게임이 종료될 수 있다는 이야기..
* Other Ocean의 교훈
1. 되도록 한 팀으로 모여서 작업하자. "우리의 경우 아침 9시에 레벨을 하나 만들기 시작해서, 10시나 10시 30분에 마무리 했다. 그러면 항상 작업할 준비가 되어있는 두명의 테스터가 점심시간까지 새로운 레벨에 대해서 피드백을 줬다. 이런 식으로 3개월간의 반복된 작업으로 작업을 했는데, 이는 한팀으로 모여서 하지 않았다면 불가능 한 것이다."
2. 디바이스의 한계 까지 최대한 활용하자. 캐쥬얼 게임을 만든다고 해서, 사람들이 기존에 이미 익숙했던 높은 게임 품질에 대한 기대를 안할 꺼라고 생각하지 말자. 장치가 제공하는 만큼 최대한의 퀄러티를 추구할것.
3. 하드코어 게임을 일반사용자에게 내놓은 것을 너무 쉽게 생각하지 말자. 일반 사용자를 위해서 추가적으로 내용을 더해야 할 필요도 있는데, 많은 개발자들이 이 부분을 생각하지 못한다.
4. 기획자와 개발자간의 효과적인 커뮤니케이션
5. 처음엔 간단하게 시작해서 거기에 살을 붙여 개선해 나가자. 심플한 디자인으로 접근하는 방식 때문에 수백개의 전채적인 디자인을 쉽게 관리할 수 있었다.
6. 빡빡한 개발일정에 대응하기. 중요한 것부터 먼저 개발하자. 실제 사용자가 필요로 할 기능들 부터 구현한다.
7. 새로운 기회는 그에 상응하는 위험이 따른다. 1년전만해도 세상에 앱스토어라는 것은 없었다. 우리가 작업을 시작한 것은 위험을 감수하는 것이었지만, 기금 우리는 기회를 잡은 샘이다.
8. 경험있는 소수정예의 팀이 더 기민하다. 오션팀이 실제로는 더 많은 개발자를 확충하려고도 했지만, 작고 기민한 팀으로 남기로 결정했다. 만약 팀에 더 많은 사람을 끌어 들였다면, 개발이 더 느려졌을 것이다.
9. 라이선스가 걸린 지적저작물에 대해서 열린 태도를 유지할것.
10. 그 제품을 이해하는 팀을 선택할 것. Other Ocean의 팀은 모두 애플과 슈퍼 몽키볼의 팬들이었다.
1. Listening to feedback. "Getting that user feedback is tremendous," Sharpley said.
2. Don't play price wars. "We resisted the temptation to drop the price
prematurely," the producer recalled. Eventually, during the holiday
season, since the company had not yet dropped its price, when it
finally did exercise that option, it made much more of a splash than it
did for the companies that dropped down to $1 soon after launch.
3. Consider the pros and cons of "lite" versions. If you have a new
unusual IP, or a gameplay mechanic that cannot be easily explained via
the app store, it may be worth developing a trial version of your game,
Sharpley said, but if the game can be communicated easily, you risk
cannibalizing your own sales with a lite version.
4. Many users will be new to the property. Though Monkey Ball
is an established console series, that matters little on a new
platform, Sharpley said -- it helps to have a brand, but it still must
be completely approachable to new players.
5. User reviews are king on iPhone. Gameranking and Metacritic are
nearly meaningless on iPhone games, Sharpley warned -- user reviews are
the bottom line, and users will closely watch whether the publisher
pays attention to complaints in the user reviews.
6. Don't make it too hard. "For many, it was still too hard," Sharpley
said, even though the team intended to make a casual game. "Getting to
the end of a game should be foolproof."
7. Build to the device. "The reason we were able to get Apple so
interested in this brand is because it played so well to this device"
with its accelerometers, Sharpley explained.
8. Make suer consumers "get it" in 10 seconds. In console games, "you
have five or ten minutes" to hook the player -- but "with the iPhone
audience, you want to make sure your app grabs them right away." After
all, they can always move onto a free game whenever they choose.
9. Keep things simple. On the Wii, Monkey Ball became more complex than previous iterations -- but on the iPhone, the decision to go in the opposite direction paid off.
10. Consider the play environment. "We made a critical mistake at
launch by requiring players to complete 10 levels before they saved,"
Einhorn remembered -- the iPhone play environment was ill-suited to
that mechanism, which was later altered.
10 Lessons Learned -- Other Ocean
1. Use an internal studio if possible. "We found ourselves in a
situation where we started to build a level at 9 in the morning, and it
might be finished by 10 or 10:30, and we had two testers full-time
ready to give us feedback by lunchtime," Sharpley explained -- the
three-month dev cycle would have been impossible without all in-house
developers.
2. Stretch a new device to its limits. "Just because it's aimed at the
casual market, doesn't mean they're not deserving of the production
values that everyone else is accustomed to," the developer said.
3. Don't underestimate the challenge of bringing a hardcore game to
casual. Paradoxically, sometimes new content must be added to make a
game suitable for casual players -- many developers do not expect this.
4. Communicate efficiently between publisher and developer. Other
Ocean, Sega of America, and Sega of Japan were spread across three time
zones -- and so tight communication was necessary to keep the project
from going off the rails.
5. Start simple and add refinement. When it comes to level design,
Other Ocean's approach of simple design sheets paid off by keeping the
hundreds of total designs manageable.
6. Aggressive deadlines focus development. "In some ways, the tight
deadline allowed us to focus on what somebody wants when they buy a
game like this," Sharpley said. "We only focused on the important
features."
7. New opportunities can be risky. "It's hard to imagine, but a year
ago there was no App Store...and it was quite a risky venture for Other
Ocean to take this on -- but by taking that risk, we've now opened
ourselves to all sorts of other opportunities."
8. A small experienced team can be more agile. Other Ocean actually had
the opportunity to expand its team, but elected to stay small and
agile. "In hindsight, if we'd added more people to the project, we
probably would have slowed down production," Sharpley reflected.
9. Be open to licensed IP. Some developers disdain licensed IP,
Sharpley said, but working with less risky licenses raises a studio's
profile and allows it, over time, the security to develop original
games.
10. Use a team that understands the brand. Other Ocean's employees were already fans of Apple and Super Monkey Ball
-- which made all the difference when communicating with the people in
charge of the platform and property. "We were all on the same page,"
said Sharpley.