하이브리드 앱 개발의 핵심 기술
하이브리드 앱 개발에서 웹 기반 UI와 네이티브 기능의 통합은 중요한 과제입니다. 이 접근 방식은 앱 스토어 심사 없이 실시간 콘텐츠 업데이트가 가능하며, 특히 iOS의 장기간 심사 프로세스에 효과적인 솔루션을 제공합니다.
안드로이드 웹뷰 통합
자바스크립트-네이티브 상호작용 구현을 위한 안드로이드 구성:
네이티브 브릿지 액티비티
public class NativeBridgeActivity extends Activity {
private WebView webView;
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.main_layout);
webView = findViewById(R.id.webview);
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
// JS-네이티브 통신 인터페이스 등록
webView.addJavascriptInterface(new NativeHandler(this), "nativeBridge");
webView.loadUrl("file:///android_asset/ui.html");
}
// 자바스크립트 호출 메서드
private void executeJS(String script) {
webView.post(() -> webView.evaluateJavascript(script, null));
}
}
네이티브 기능 핸들러
public class NativeHandler {
private Context context;
public NativeHandler(Context ctx) { this.context = ctx; }
@JavascriptInterface
public void showToast(String text) {
Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
}
@JavascriptInterface
public void initiateCall(String number) {
Intent callIntent = new Intent(Intent.ACTION_CALL,
Uri.parse("tel:" + number));
context.startActivity(callIntent);
}
}
HTML/자바스크립트 클라이언트
<button onclick="invokeNative('showToast','Hello Android')">
토스트 표시
</button>
<script>
function invokeNative(action, param) {
if(window.nativeBridge) {
nativeBridge[action](param);
}
}
</script>
iOS 웹뷰 통합(Swift)
자바스크립트Core 프레임워크를 활용한 통신:
class ViewController: UIViewController, UIWebViewDelegate {
var webView: UIWebView!
var jsContext: JSContext?
override func viewDidLoad() {
super.viewDidLoad()
webView = UIWebView(frame: view.bounds)
webView.delegate = self
view.addSubview(webView)
if let url = Bundle.main.url(forResource: "interface",
withExtension: "html") {
webView.loadRequest(URLRequest(url: url))
}
}
func webViewDidFinishLoad(_ webView: UIWebView) {
jsContext = webView.value(forKeyPath:
"documentView.webView.mainFrame.javaScriptContext") as? JSContext
// 네이티브 함수 매핑
let nativeFunctions: @convention(block) () -> Void = { [weak self] in
let args = JSContext.currentArguments()
self?.handleNativeCall(method: args?[0].toString(),
data: args?[1].toString())
}
jsContext?.setObject(nativeFunctions, forKeyedSubscript: "nativeCall" as NSString)
}
private func handleNativeCall(method: String?, data: String?) {
switch method {
case "showAlert":
// 경고창 표시 로직
case "processData":
// 데이터 처리 로직
default: break
}
}
}
Swift-자바스크립트 상호작용 모델
class NativeInterface: NSObject {
weak var controller: UIViewController?
@objc func displayNotification(_ message: String) {
DispatchQueue.main.async {
let alert = UIAlertController(title: nil,
message: message,
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "확인", style: .default))
self.controller?.present(alert, animated: true)
}
}
@objc func fetchDeviceInfo() -> String {
return "Device: \(UIDevice.current.model)"
}
}