Android

[Android] - @JavascriptInterface에 대해서

dev_SiWoo 2025. 11. 4. 16:04

@JavascriptInterface란 무엇인가?

간단하게 정리하자면, WebView에서 JavaScript와 Java를 연결하는 다리(Bridge) 라고 생각하면 쉽다.

 

이 때 안드로이드환경에서 개발을 하다 보면, WebView 안에서
HTML, CSS, JavaScript로 구성된 웹 페이지를 띄워야하는 상황에서  단순히 웹을 보여주는 것만으로는 부족할 때가 있는데예를 들어 웹 화면에서 버튼을 누르면, 앱의 특정 기능(예: 카메라 실행, 로그인 토큰 전달 등)을 실행해야하는 상황이 그렇다.

 

이때 필요한 게 바로 @JavascriptInterface 

 

@JavascriptInterface는
WebView에서 실행되는 자바스크립트 코드가 Java 메서드를 호출할 수 있도록 허용하는 어노테이션이다.

 

 

WebView는 원래 앱 내부에서 HTML 페이지를 렌더링하는 View이다.
여기에 JavaScript가 포함되어 있다면, 앱 안의 Java 코드와 소통할 수 있어야 한다.

이 때, 그 역할을 담당하는 구조는 아래와 같다.

 

JavaScript  ⇄  WebView  ⇄  Java

 

이때 JavaScript → Java 방향의 호출을 허용하려면,
Java 메서드 위에 반드시 @JavascriptInterface를 붙여야 한다.

# 예제 코드

1. Java Code

public class WebAppInterface {
    @android.webkit.JavascriptInterface
    public boolean isDevMode() {
        return CommonStr.DEV_MODE;
    }
}

 

2. WebView설정

WebView webView = findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new WebAppInterface(), "Android");

 

3. JavaScript 코드 

let isDev = Android.isDevMode();
alert("현재 개발모드 여부: " + isDev);

 

 

 

# @JavascriptInterface의 등장 배경

안드로이드 4.2(API 17) 이전에는
JavascriptInterface()로 연결된 객체의 모든 public 메서드가 자바스크립트에서 호출 가능했었다.

 

즉, 악성 웹페이지가 앱 내부 함수를 마음대로 호출할 수 있는 보안 취약점이 존재했다. 😨

그래서 4.2 버전부터는 **명시적으로 허용된 메서드(@JavascriptInterface 붙은 메서드)**만 호출할 수 있도록 정책이 바뀌었다.

 

 

⚠️ 안드로이드 4.2 이전의 동작 방식 (보안 취약 버전)

1. java

public class InsecureInterface {
    public void showToast(String msg) {
        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
    }

    public void deleteAllFiles() {
        File dir = new File("/sdcard/");
        for (File file : dir.listFiles()) {
            file.delete();
        }
    }

    public String getDeviceInfo() {
        return Build.MODEL + " / " + Build.VERSION.SDK_INT;
    }
}

 

webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new InsecureInterface(), "Android");

 

 

2. Javascript

<html>
<body>
  <script>
    // 모든 public 메서드에 접근 가능했던 시절 😨
    Android.showToast("안드로이드에서 호출됨!");

    // 심지어 이런 것도 가능했음!
    Android.deleteAllFiles();

    // 기기 정보 수집도 가능
    alert(Android.getDeviceInfo());
  </script>
</body>
</html>