본문 바로가기

Programming

PhoneGap의 모든것 - Plugin 개발 (3)


 


 최근엔 "하이브리드 앱"이라는 용어가 마케팅으로 사용될 정도로 PhoneGap에 대한 관심이 많습니다. 하지만 아래와 같은 장점을 가지고 있지만 단점도 가지고 있습니다.


장점

- 기존 Javascript 코드를 부분적으로 재사용 가능

- 하나의 웹 코드 (HTML, CSS, Javascript)를 작성하면 부분적으로 여러 플랫폼(iOS, Android, Window Phone, Black berry, webOS, smybian, bada) 재사용 가능 


단점

- 웹베이스로 코드가 동작 되기 떄문에 비교적(Native App과 비교하면) 느리다.

- PhoneGap API들은 가장 기본이 되는 것만 제공해 준다. (PhoneGap API 참고 : http://docs.phonegap.com/en/1.7.0/index.html)

- Native 고유의 기능을 사용해야만 구현 할 수 있는 기능들이 있다 (예) Android의 Background Service


이러한 장.단점들을 가지고 있지만 단점들을 보면 정말 부족해 보입니다. 이 단점을 어느 정도 극복 하기 위한 방법이 각 플랫폼 별로 Plugin을 개발해서 사용하는 것 입니다.


PhoneGap Plugin

Plugin을 만든다는 것은 Native 코드를 이용해서 필요한 기능들 만들어서 사용한다는 것 입니다. iOS의 경우에는 Objective-C로 Android는 Java로 기존 Native에서 동작하는 코드를 PhoneGap Plugin 형식에 맞게 제공하여 PhoneGap을 이용한 앱에서 이를 사용할 수 있도록 합니다.


무엇을 할 수 있는가?

많은 연산을 필요로 하는 작업은 Native에서 처리 (더 빠르다?)

- PhoneGap API에 없는 기능들을 추가해서 사용 (Android의 Background service, 바이너리 이미지를 PhotoLibrary에 저장)

- Native 언어적으로 복잡한 비지니스 로직을 처리 하는 방법이 있을 경우 플러그인으로 만들어서 사용




개발 방법

PhoneGap Plugin은 Javascript코드와 Native코드 쌍으로 이루어져 있습니다. 여러 플랫폼에 대응하는 Plugin기능을 만드려면 플랫폼 마다 구현해 줘야 합니다. Javascript는 기본 인터페이스를 만들어 놓고 세부적인 내용은 플랫폼 별로 다르게 작성 되야 합니다.


PhoneGap 1.5 부터 Apache Cordova로 이름이 바뀌면서 덩달아 Namespace도 모두 바뀌었습니다. 아래 내용은 PhoneGap 1.5 이후 버전에 맞게 작성 되었습니다.


iOS (wiki : http://goo.gl/fNC4c)

예제 코드는 Javascript에서 Plugin으로 Hellow World 문자열을 전달하여 전달된 문자열이 Hellow World가 맞다면 성공, 아니면 실패를 반환하는 코드 입니다. 원본 코드는 위의 wiki에서 확인 가능 합니다.


1.  사용할 Objective-C 코드 작성

(코드 출처 :  http://goo.gl/fNC4c)

#import <Foundation/Foundation.h>
#import <Cordova/CDVPlugin.h>
   
 
// CDVPlugin을 상속
@interface MyClass : CDVPlugin {
      
      // 호출된 Javascript를 참조 하는 ID
      NSString* callbackID; 
 }
 
@property (nonatomic, copy) NSString* callbackID;
 
// Instance Method 
- (void) print:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
  
@end


#import "MyClass.h"
       
 @implementation MyClass
 
 @synthesize callbackID;
 
 -(void)print:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options 
 {
           // arguments에 제일 마지막에 있는 값이 callbackID이다.
           self.callbackID = [arguments pop];
 
           // Javascript로 부터 전달된 값을 저장
           NSString *stringObtainedFromJavascript = [arguments objectAtIndex:0];                
 
           // Javsacript로 확인된 메세지를 보내기 위해 Objective-C에서 값 생성
           NSMutableString *stringToReturn = [NSMutableString stringWithString: @"StringReceived:"];
 
           // 전달된 값과 생성된 값을 합침
           [stringToReturn appendString: stringObtainedFromJavascript];
            
           // Javascript에 전달할 결과 값을 생성 CDVPluginResult 로 생성 해야만 한다. 전달하는 문자열은 UTF-8로 인코딩
           CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
                  messageAsString: [stringToReturn stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
 
           // Javascript로 부터 전달된 값이 HellowWorld이면 성공 Callback 실행, 실패면 실패 Callback 실행
           if ([stringObtainedFromJavascript isEqualToString:@"HelloWorld"] == YES)
           {
                  // Call the javascript success function
                  [self writeJavascript: [pluginResult toSuccessCallbackString:self.callbackID]];
           else
           {   
                  // Call the javascript error function
                  [self writeJavascript: [pluginResult toErrorCallbackString:self.callbackID]];
           }
  }
  @end


2. 위에서 작성된 Plugin 코드를 실행할 Javascript 클래스 생성 및 실행 예제


var MyPlugin = {
     nativeFunction: function(types, success, fail) {
          return Cordova.exec(success, fail, "MyPlugin""print", types);
     }
};
 
MyPlugin.nativeFunction(
      ["HelloWorld"],
      function(result) {
           alert("Success: \r\n"+result);     
      },
      function(error) {
           alert("Error: \r\n"+error);     
      }
); 



3. 위의 코드들이 제대로 동작하게 할 설정  


Cordova.plist



<plist version="1.0">

     <dict>
          ...
          <key>Plugins</key>
          <dict>
               ...

               <key>MyPlugin</key>

               <string>MyClass</string>
               ...
          </dict>
          ...
     </dict>
</plist>





다른 플랫폼에 대한 Plugin 개발 방법은 여기서(http://goo.gl/O6XHI) 확인 가능 합니다


결론


PhoneGap은 모바일 개발 인력이 부족한 환경에서 빠른 시간 안에 더 많은 플랫폼을 대응할 수 있다는 장점을 가지고 있습니다. 하지만 이러한 생산성은 모든 플랫폼에 적용되는 것이 아닙니다. 지극히 한정적인 서비스에서 그리고 웹기반으로 서비스를 구축했을때 장점을 가진 환경에서만 위의 장점을 누릴수 있습니다. 많은 서비스들이 하이브리드 앱으로 서비스를 시작했다가 결국에는 Native 로 다시 만드는 사례가 많아 지고 있는 이유는, 하이브리드 앱 개발이나 HTML5 라는 용어가 단순히 유행 처럼 서비스에 적용하는 사례들이 많아 지고 있기 때문이 아닐까 생각해 봅니다.


저도 PhoneGap에 대해 공부 하고 있는 상태지만, 서비스에 해당 기술을 도입함에 앞서서 앞으로 만드려고 하는 서비스가 퍼포먼스를 중시하는 서비스 인지, 아니면 특별한 기능이 있는데 이를 하이브리드 앱으로 개발해도 가능 할지에 대해 반드시 확인하고 적용해 보는게 좋습니다. 

제대로된 선행 조사와 서비스에 대한 이해가 있는 상태에서 PhoneGap을 선택했을때는 더할나위 없이 빠른 퍼포먼스를 낼 수도 있는 플랫폼이지만 그게 아니라면 빠른 생산성은 커녕 유지 보수 하는데 더 많은 시간과 인력이 필요하게 될거라 생각 합니다.


PhoneGap의 모든것이라는 제목으로 3개의 포스팅을 하였는데요. 모든것을 다룬것 같진 않네요. 처음 시작하기에 앞서 한번 훑어 보면 좋은 글이라고 봐주셨으면 합니다.


제가 언급한 내용중 잘못된 내용이 있으면 바로 잡아 주세요.