📱 모바일 앱 연동 — 완전 분석

웹 페이지가 네이티브 앱(Android/iOS)과 어떻게 통신하는지, 앱 브릿지와 딥링크 시스템을 분석합니다.

🌉 callAppBridge() — 웹과 앱을 잇는 다리

이 함수는 웹 페이지(WebView) 안에서 네이티브 앱 기능을 호출할 때 사용됩니다. JavaScript에서 Android/iOS 네이티브 코드를 직접 호출하는 마법 같은 함수예요.

function callAppBridge(action, data) {
    // action에 따라 분기 처리
    switch (action) {
        case 'camera':
            // 명함 사진 촬영 → 네이티브 카메라 앱 실행
            if (isAndroidApp()) {
                window.Android.callCamera();
            } else if (isIOSApp()) {
                window.webkit.messageHandlers.callCamera.postMessage(data);
            }
            break;

        case 'gallery':
            // 갤러리에서 명함 이미지 선택
            if (isAndroidApp()) {
                window.Android.openGallery();
            } else if (isIOSApp()) {
                window.webkit.messageHandlers.openGallery.postMessage(data);
            }
            break;

        case 'share':
            // 카카오톡/인스타 등 외부 공유
            if (isAndroidApp()) {
                window.Android.shareContent(JSON.stringify(data));
            } else if (isIOSApp()) {
                window.webkit.messageHandlers.shareContent.postMessage(data);
            }
            break;

        case 'phone_call':
            // 전화 걸기
            if (isAndroidApp()) {
                window.Android.makePhoneCall(data.number);
            } else if (isIOSApp()) {
                window.webkit.messageHandlers.makePhoneCall.postMessage(data);
            }
            break;

        case 'map':
            // 지도 앱 열기
            if (isAndroidApp()) {
                window.Android.openMap(data.address);
            } else if (isIOSApp()) {
                window.webkit.messageHandlers.openMap.postMessage(data);
            }
            break;
    }
}

🔍 앱 환경 감지 — 웹인가 앱인가?

// 1. UserAgent 기반 감지
function isAndroidApp() {
    var ua = navigator.userAgent.toLowerCase();
    return ua.indexOf('[앱식별자]') > -1;
}

function isIOSApp() {
    var ua = navigator.userAgent.toLowerCase();
    return ua.indexOf('[앱식별자-iOS]') > -1;
}

function isApp() {
    return isAndroidApp() || isIOSApp();
}

// 2. URL 스킴 기반 감지
function isAppInstalled() {
    // Android: intent:// 스킴 시도
    // iOS: [앱스킴]:// 스킴 시도
    // → 타이머로 실패 감지 (일정 시간 내 반응 없으면 미설치)
}

// 3. 감지 결과에 따른 분기
if (isApp()) {
    // 앱 내부 WebView → callAppBridge() 사용
    // UI 요소 중 일부 숨김 (앱 설치 버튼 등)
    $('.app-only').show();
    $('.web-only').hide();
} else {
    // 일반 브라우저 → 웹 전용 UI 표시
    $('.app-only').hide();
    $('.web-only').show();
}

웹에서 앱을 열거나, 앱이 설치되어 있지 않으면 Play Store로 보내는 시스템입니다.

// === goOnlyOneApp() 함수 분석 ===
function goOnlyOneApp() {
    // 1. Android인지 확인
    if (!isAndroidApp()) {
        // 2. 일반 브라우저에서 앱 실행 시도
        var now = new Date().getTime();

        // 3. 커스텀 URL 스킴으로 앱 열기 시도
        //    [앱스킴]://open?url=... 형태
        location.href = "[앱스킴]://open?url=" +
            encodeURIComponent(window.location.href);

        // 4. 2초 후에도 페이지에 남아있으면
        //    → 앱이 설치되지 않은 것!
        setTimeout(function() {
            if (new Date().getTime() - now < 2200) {
                // 5. Play Store로 이동
                location.href =
                    "[PlayStore앱URL]";
            }
        }, 2000);
    }
}

// === goIamHome() 함수 ===
function goIamHome() {
    // Android 앱 환경이면 AppScript로 /m 페이지 이동
    if (isAndroidApp()) {
        // WebView에서 JavaScript 인터페이스로 이동
        window.AppScript.movePage('[앱내부경로]');
    } else {
        // 일반 웹 → 직접 /m 페이지로 이동
        location.href = '[웹홈URL]';
    }
}
⚠️ 딥링크의 마법 같은 트릭

2초 타이머가 핵심이에요! location.href로 앱 스킴을 호출하면: 1. 앱이 설치되어 있다면 → 앱이 열리고, 타이머는 앱으로 이동하면서 중단됨 2. 앱이 없으면 → 아무 일도 안 일어나고, 2초 후 Play Store로 이동! 이게 바로 "Fallback URL" 패턴이에요. 초등학생도 이해할 수 있죠?

📸 카메라 연동 — 명함 사진 촬영

// === app_camera_paper() 함수 ===
function app_camera_paper() {
    if (isApp()) {
        // 앱 환경 → 네이티브 카메라 호출
        callAppBridge('camera', {
            type: 'paper_card',     // 어떤 용도의 촬영인지
            quality: 0.8,           // 이미지 품질 80%
            maxWidth: 1200,         // 최대 너비 1200px
            callback: 'onCameraResult'  // 결과 콜백 함수명
        });
    } else {
        // 웹 환경 → 파일 업로드 input 표시
        $('#paper_card_upload').click();
    }
}

// === 네이티브 카메라 결과 콜백 ===
function onCameraResult(imageData) {
    // imageData = base64 인코딩된 이미지 또는 파일 경로
    $('#paper_card_img').attr('src', imageData);
    $('#paper_card_url').val(imageData);

    // OCR 처리를 위해 서버로 전송
    $.ajax({
        url: "[OCR서버URL]/[이미지처리]",
        type: "POST",
        data: { image: imageData },
        success: function(ocrResult) {
            // OCR 결과로 폼 자동 채우기
            fillCardForm(ocrResult);
        }
    });
}

📞 전화 상태 & GPS 연동

// === recvPhoneStatus() — 전화 상태 수신 ===
function recvPhoneStatus(status) {
    // status: "IDLE" | "RINGING" | "OFFHOOK"
    // 앱에서 전화 상태가 바뀔 때마다 WebView로 알려줌

    switch (status) {
        case "RINGING":
            // 전화 오는 중 → 자동 저장, 입력 중단 알림
            autoSave();
            showToast("전화가 와서 임시 저장했어요!");
            break;
        case "OFFHOOK":
            // 통화 중 → 페이지 잠금
            lockPage();
            break;
        case "IDLE":
            // 통화 끝 → 잠금 해제
            unlockPage();
            break;
    }
}

// === recvPhonePos() — GPS 위치 수신 ===
function recvPhonePos(lat, lng) {
    // 현재 위치를 받아서 주소 검색에 활용
    $('#current_lat').val(lat);
    $('#current_lng').val(lng);

    // 지도 API로 역지오코딩 (위도/경도 → 주소)
    reverseGeocode(lat, lng, function(address) {
        $('#paper_address').val(address);
    });
}

🎓 초등학생도 따라하는 모바일 분석법

1
크롬 Device Mode 켜기
F12 → 좌측 상단 "Toggle device toolbar" (Ctrl+Shift+M)
2
모바일 기기 선택
상단 드롭다운에서 "Galaxy S20" 또는 "iPhone 12" 선택
3
UserAgent 확인
Console에서 navigator.userAgent 입력 → 모바일 UA 확인
4
앱 환경 시뮬레이션
Console에서 isApp = function(){ return true; } 로 강제 설정
5
callAppBridge 추적
var orig = callAppBridge; callAppBridge = function(a,d){ console.log(a,d); orig(a,d); }
💡 WebView 디버깅 꿀팁

실제 안드로이드 앱의 WebView를 디버깅하려면:

  1. 안드로이드 폰을 USB로 연결
  2. 폰에서 "개발자 옵션" → "USB 디버깅" 활성화
  3. PC 크롬에서 chrome://inspect 입력
  4. 연결된 기기의 WebView 목록에서 "inspect" 클릭
  5. PC에서 폰의 WebView 콘솔/네트워크/요소 검사 가능!

📱 모바일 관련 주요 상수

항목
Android 패키지명[앱패키지명]
커스텀 URL 스킴[앱스킴]://
Play Store 링크[PlayStore앱URL]
웹 홈 URL[웹홈URL]
Android WebView JS 인터페이스[JS인터페이스1], [JS인터페이스2]
iOS WebView 메시지 핸들러[iOS메시지핸들러]