사전 웹뷰
개념

웹뷰

gabury1고친 사람 github-actions[bot]

웹뷰는 앱이 자기 화면 안에 웹 페이지를 띄우게 해 주는 부품입니다. 페이지를 그리는 일은 브라우저에서 떼어 온 부분이 맡습니다. 사용자는 앱을 떠나지 않고 웹 페이지를 봅니다. 그 대신 페이지가 앱의 손 안에 놓입니다.

쉽고 빠른 이해

웹뷰는 앱 화면 안에 웹 페이지 한 칸을 끼워 넣는 부품입니다. 쇼핑 앱에서 고객 센터를 누르면 앱을 떠나지 않고 웹 페이지가 뜨는 것이 대개 웹뷰입니다.

이게 없으면 웹에 이미 있는 화면을 보여 줄 때마다 사용자를 앱 밖의 브라우저로 내보내야 합니다. 아니면 같은 화면을 앱에서 새로 만들어야 합니다.

  1. 앱이 화면에 웹뷰 한 칸을 놓고 주소를 넘깁니다
  2. 웹뷰가 그 주소의 페이지를 받아 칸 안에 그립니다
  3. 필요하면 앱과 페이지가 서로 함수를 불러 값을 주고받습니다

대가는 페이지가 앱의 손 안에 있다는 것입니다. 앱은 그 안에서 치는 글자와 로그인 값을 엿볼 수 있습니다. 주소창이 없어서 사용자는 어느 사이트인지 확인할 수 없습니다. 그래서 다른 서비스의 로그인 화면은 웹뷰로 띄우지 않습니다.

상세

건물주는 건물 안 어디에 얼마나 큰 매장을 낼지 정합니다. 매장 안은 세입자가 꾸밉니다. 그래도 건물주는 마스터키를 쥐고 있어서 언제든 매장 안에 들어갈 수 있습니다.

웹뷰는 앱 화면에 들인 그 매장입니다. 칸의 위치와 크기는 앱이 정합니다. 칸 안은 웹 서버가 보낸 페이지가 채웁니다. 그리고 앱은 마스터키를 쥔 건물주처럼 페이지 안까지 손을 넣을 수 있습니다.

웹뷰는 앱 안에 박혀서 앱의 통제 아래 웹 페이지를 그리는 화면 부품입니다. 쇼핑 앱에서 고객 센터를 누르면 위아래 막대는 남습니다. 가운데에만 고객 센터 웹 페이지가 뜹니다. 그 가운데 칸이 웹뷰입니다.

앱 화면을 이루는 한 칸

앱 화면 하나를 펼쳐 놓고 웹뷰가 그 안의 어디에 들어가는지 봅니다.

앱 화면은 뷰 여러 개를 쌓아 만듭니다. 뷰는 화면에서 네모난 한 칸을 차지하는 부품입니다. 그 칸 안은 뷰가 그립니다. 버튼 하나, 글상자 하나, 사진 한 장이 각각 뷰입니다.

사용자가 기기에 설치해서 쓰는 앱을 네이티브 앱이라고 부릅니다. 브라우저 안에서만 도는 웹 앱과 가르는 이름입니다. 네이티브 앱의 뷰는 대개 운영체제가 기본으로 주는 도구로 그립니다. 그렇게 그린 뷰를 네이티브 뷰라고 부릅니다.

웹뷰도 뷰 가운데 하나입니다. 다른 점은 칸 안을 앱 코드가 아니라 웹 페이지가 채운다는 것입니다. 앱은 웹뷰에 주소 하나를 넘깁니다. 웹뷰는 그 주소의 페이지를 받아 와 칸 안에 그립니다. 한 앱이 웹뷰를 여럿 둘 수도 있습니다.

flowchart TD
    subgraph 앱화면["앱 화면"]
        T["상단 바 · 네이티브 뷰"]
        W["웹뷰 · 웹 페이지가 채운다"]
        B["하단 탭 · 네이티브 뷰"]
        T ~~~ W ~~~ B
    end
    W -- 페이지를 받아 온다 --> S["웹 서버"]

위아래 막대는 앱이 직접 그립니다. 가운데 칸만 웹 서버에서 받아 온 페이지입니다. 사용자 눈에는 한 화면이지만 만든 쪽은 둘입니다.

브라우저에서 덜어 낸 것

같은 페이지를 브라우저로 볼 때와 견주면 웹뷰에 무엇이 들어 있고 무엇이 없는지 드러납니다.

웹 페이지는 세 가지 언어로 적힙니다. HTML(HyperText Markup Language)은 문서의 구조를 적습니다. CSS(Cascading Style Sheets)는 모양을 적습니다. 자바스크립트는 동작을 적습니다.

이 셋을 읽어 화면으로 그려 내는 부분을 렌더링 엔진이라고 합니다. 웹뷰는 브라우저의 화면 부품을 앱 안에 들인 것이라 이 엔진도 함께 들어 있습니다. 그래서 같은 페이지가 브라우저에서와 거의 같게 보입니다.

빠진 것은 브라우저를 둘러싼 껍데기입니다. 아래 표가 둘을 견줍니다.

브라우저 웹뷰
페이지를 그리는 엔진 ✓ ✓
자바스크립트 실행 ✓ ✓
주소창 ✓ ✗
안전한 연결임을 확인했다는 표시 ✓ ✗
뒤로 가기 · 새로 고침 단추 ✓ ✗
탭 · 북마크 ✓ ✗

껍데기가 없으니 뒤로 가기 같은 조작도 앱이 직접 만들어 붙입니다. 대신 앱은 그 칸을 자기 화면의 일부처럼 꾸밀 수 있습니다. 사용자는 웹 페이지를 보고 있다는 것을 알아채지 못하기도 합니다.

앱과 페이지를 잇는 통로

웹뷰 안의 페이지와 앱 코드는 서로를 부를 수 있습니다. 그 길을 아래에서 봅니다.

웹뷰를 띄운 앱은 페이지 안을 읽고 고칠 수 있습니다. 앱은 이 힘으로 앱 코드와 페이지 코드 사이에 통로를 놓습니다. 앱은 자기 함수에 이름을 붙여 페이지의 자바스크립트에 내놓습니다. 페이지는 그 이름으로 앱 함수를 부릅니다. 페이지는 이 통로로 앱 쪽 기능에 닿습니다.

이런 통로를 흔히 자바스크립트 브리지라고 부릅니다.

반대 방향도 됩니다. 앱은 페이지에 자바스크립트를 넣어 실행합니다. 페이지 안의 값을 읽거나 바꿀 수도 있습니다.

flowchart TD
    subgraph 앱["앱 코드"]
        A["앱"]
        F["이름을 붙여 페이지에 내놓은 앱 함수"]
        N["앱 쪽 기능"]
    end
    subgraph 뷰["웹뷰 안의 웹 페이지"]
        JS["페이지의 자바스크립트"]
    end
    JS -- 이름으로 부른다 --> F
    F --> N
    A -- 스크립트를 넣어 실행한다 · 값을 읽고 바꾼다 --> JS

화살표 셋 가운데 위로 올라가는 하나만 페이지가 시작하는 길입니다. 나머지 둘은 앱이 페이지 쪽으로 뻗는 길입니다. 통로를 놓는 코드 한 벌은 「예시」 절에 있습니다.

웹뷰끼리 다른 세 성질

모든 웹뷰가 같은 힘을 갖지는 않습니다. 웹뷰 부품들이 무엇에서 서로 다른지 셋을 아래에 모았습니다.

셋째 성질에 나오는 낱말 둘을 먼저 풉니다. 쿠키는 웹사이트가 브라우저 쪽에 맡겨 두는 작은 값입니다. 로그인 상태를 흔히 여기에 담습니다. 캐시는 한 번 받아 온 페이지 조각을 다시 쓰려고 남겨 둔 사본입니다.

성질 묻는 것
화면을 꾸미는 폭 앱이 웹뷰의 화면을 마음대로 꾸미나, 웹뷰가 정해 둔 화면을 조금만 손대나
페이지에 닿는 힘 앱이 웹뷰 안의 페이지를 읽고 고칠 수 있나
상태 나눔 웹뷰가 쿠키와 캐시를 기기 브라우저와 나누나, 따로 떨어져 있나

앞의 정의, 곧 앱의 통제 아래 페이지를 그리는 부품은 세 성질이 모두 앱 쪽으로 기운 웹뷰입니다. 앱이 화면을 다 꾸미고 페이지에 닿습니다. 상태는 기기 브라우저와 따로 둡니다.

세 성질이 모두 반대로 기운 부품도 있습니다. 그 부품까지 웹뷰라고 부르느냐는 「이견」 절이 다룹니다.

배경

네이티브 앱은 화면을 앱 코드로 그립니다. 그런데 앱이 보여 줘야 할 화면 가운데에는 이미 웹에 있는 것이 많습니다. 광고와 결제 화면이 그렇습니다. 이용 약관이나 고객 센터 같은 웹 페이지도 그렇습니다.

이런 화면을 보이는 길은 둘이었습니다. 하나는 사용자를 앱 밖 브라우저로 내보내는 것입니다. 다른 하나는 같은 화면을 앱 코드로 다시 만드는 것입니다. 다시 만든 화면은 고칠 때마다 앱의 새 판을 내야 합니다. 운영체제마다 앱을 따로 짜면 그 수만큼 또 만듭니다.

그래서 앱 화면의 한 칸에 웹 기술로 만든 화면을 바로 그리는 부품이 필요했습니다. 이 부품으로 앱은 광고나 결제처럼 웹에 이미 갖춰진 기능을 앱 안에서 다시 씁니다. 한 번 만든 웹 화면을 여러 운영체제에서 함께 쓸 수도 있습니다. 화면 대부분을 웹 기술로 짓고 네이티브 앱으로 배포한 앱을 하이브리드 앱이라고 부릅니다.

예시

성격이 다른 실물 넷을 봅니다. 웹뷰가 서버에 보내는 값 한 줄, 안드로이드에서 페이지가 앱 함수를 부르는 코드, iOS 에서 페이지가 앱에 메시지를 보내는 호출, 그리고 플랫폼마다 붙은 웹뷰 부품의 이름입니다.

안드로이드 WebView 의 사용자 에이전트 문자열

요청을 보내는 프로그램을 사용자 에이전트라고 합니다. 사용자 에이전트 문자열은 그 프로그램이 자기를 소개하는 한 줄입니다. HTTP(HyperText Transfer Protocol) 요청의 User-Agent 헤더에 실려 서버로 갑니다.

안드로이드 17 부터 안드로이드 WebView 의 기본 사용자 에이전트 문자열이 짧게 줄어듭니다. 줄인 기본 문자열은 아래와 같습니다.

Mozilla/5.0 (Linux; Android 10; K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/125.0.0.0 Mobile Safari/537.36

판 번호의 잔 숫자가 0.0.0 으로 줄어 있습니다. 괄호 안의 wv 가 웹뷰라는 표시입니다. 사이트는 이 표시를 찾아 요청이 웹뷰에서 왔는지 가를 수 있습니다. 앱이 setUserAgentString() 으로 자기 문자열을 정했다면 이 방법은 통하지 않습니다.

이 문자열은 앱이 바꿔 적을 수 있는 값입니다. 그래서 권한을 가르는 근거로는 쓸 수 없습니다.

안드로이드 WebView 의 호출 한 벌

앱이 자기 함수를 페이지에 내놓는 코드와 페이지의 단추가 그 함수를 부르는 코드를 나란히 봅니다. 결과는 화면 아래에 잠깐 떴다 사라지는 짧은 알림 하나입니다. 안드로이드는 이 알림을 토스트라고 부릅니다.

앱 쪽 코드는 코틀린입니다.

Kotlin
class WebAppInterface(private val mContext: Context) {
    /** Show a toast from the web page. */
    @JavascriptInterface
    fun showToast(toast: String) {
        Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show()
    }
}

val webView: WebView = findViewById(R.id.webview)
webView.addJavascriptInterface(WebAppInterface(this), "Android")

addJavascriptInterface 는 객체 하나와 이름 하나를 받습니다. 위 코드는 WebAppInterface 객체를 Android 라는 이름으로 웹뷰 안의 자바스크립트에 내놓습니다.

페이지에 내놓을 메서드에는 @JavascriptInterface 를 붙입니다. 그 메서드는 public 으로 둡니다. targetSdkVersion 은 앱을 어느 안드로이드 판에 맞춰 만들었는지 적어 두는 값입니다. 이 값을 17 이상으로 두면 이 표시가 없는 메서드는 페이지에서 부를 수 없습니다.

페이지 쪽 코드는 아래와 같습니다.

HTML
<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />
<script type="text/javascript">
    function showAndroidToast(toast) {
        Android.showToast(toast);
    }
</script>

페이지는 Android 를 따로 만들지 않습니다. 웹뷰가 알아서 페이지에 넣어 줍니다. 단추를 누르면 아래 순서로 흐릅니다.

sequenceDiagram
    participant 사용자
    participant 페이지 as 웹 페이지
    participant 웹뷰 as WebView
    participant 앱 as WebAppInterface
    앱->>웹뷰: addJavascriptInterface 로 Android 라는 이름을 단다
    웹뷰->>페이지: Android 를 페이지에 넣어 준다
    사용자->>페이지: Say hello 단추를 누른다
    페이지->>앱: Android.showToast('Hello Android!')
    앱->>사용자: 토스트를 띄운다

페이지의 자바스크립트 한 줄이 앱의 코틀린 메서드를 부른 것입니다. 「상세」에서 본 통로의 실물이 이 호출입니다.

iOS 웹뷰의 메시지 핸들러

iOS(아이폰의 운영체제)의 웹뷰 부품은 WKWebView 입니다. 여기서는 부르는 방향이 반대입니다. 안드로이드는 앱이 객체를 내놓고 페이지가 그 객체의 메서드를 부릅니다. iOS 는 페이지가 앱에 메시지를 보냅니다.

앱은 먼저 메시지 핸들러를 심어 둡니다. 메시지 핸들러는 페이지가 보낸 메시지를 받는 앱 쪽 코드입니다. 핸들러를 심는 곳은 WKUserContentController 객체이고, 심을 때 이름을 함께 붙입니다. 심는 메서드는 add(_:name:) 입니다.

페이지는 그 이름으로 아래 함수를 불러 핸들러에 값을 보냅니다.

JavaScript
window.webkit.messageHandlers.<messageHandlerName>.postMessage(<messageBody>)

WKWebView 를 담은 애플 프레임워크의 이름이 WebKit 입니다. 메시지가 오면 WebKit 이 핸들러의 userContentController(_:didReceive:) 메서드를 부릅니다. 앱은 그 메서드 안에 응답을 적습니다. 페이지가 함수에 실어 보낸 값은 앱 쪽 타입으로 꾸려져 그 메서드에 닿습니다.

플랫폼마다 붙은 부품 이름

웹뷰는 한 제품의 이름이 아니라 부품의 종류를 가리키는 말입니다. 운영체제마다 자기 웹뷰 부품을 줍니다. 아래 표는 앱이 페이지 안에 닿을 수 있는 부품만 모았습니다. 표에 나오는 API(Application Programming Interface)는 프로그램이 다른 프로그램의 기능을 불러 쓰는 통로입니다.

부품 플랫폼 견주는 브라우저 · 엔진
Android WebView 안드로이드 대체로 Chrome 과 같은 기능을 냅니다. 일부 웹 API 는 안 됩니다
Tencent X5 안드로이드 Tencent 가 따로 만든 웹뷰입니다
WebView2 윈도우 Microsoft Edge 를 렌더링 엔진으로 씁니다. Evergreen 배포를 고르면 갱신이 꾸준히 들어오는 Chromium 판에 기댑니다
WKWebView iOS 대체로 Safari 와 같은 기능을 냅니다. 일부 웹 API 는 안 됩니다. iOS 8 부터 예전 부품 UIWebView 를 대신합니다
ArkWeb OpenHarmony · HarmonyOS 이 플랫폼의 기본 웹뷰입니다

이 목록이 웹뷰 부품 전부는 아닙니다. 부품 이름은 달라도 하는 일은 같습니다. 앱 화면에 칸 하나를 내고 그 안에 웹 페이지를 그립니다.

대가

웹뷰를 고르면 앱이 페이지를 통제하게 됩니다. 그 맞바꿈으로 누가 무엇을 잃는지를 다섯 갈래로 봅니다. 사용자의 확인 수단, 페이지에 치는 비밀번호, 앱의 권한, 로그인 상태, 페이지가 기대는 웹 기능입니다.

사이트를 확인할 수 없는 사용자

웹뷰에는 브라우저의 주소창이 없습니다. 안전한 연결임을 확인했다는 표시도 없습니다. 사용자는 지금 비밀번호를 치는 페이지가 진짜 그 사이트인지 알 수 없습니다.

진짜 사이트라 해도 문제가 남습니다. 사이트를 먼저 확인하지 않고 비밀번호를 쳐도 괜찮다고 사용자를 길들입니다.

앱 손에 들어가는 입력과 쿠키

웹뷰를 띄운 앱은 그 웹뷰의 쿠키 저장소에 닿을 수 있습니다. 페이지 내용을 들여다보거나 고칠 수도 있습니다. 웹뷰로 띄운 흔한 로그인 화면에서 앱은 이런 일을 할 수 있습니다.

  • 로그인 칸에 치는 글자를 하나하나 기록해 아이디와 비밀번호를 가로챕니다
  • 폼을 저절로 제출해 사용자의 동의를 건너뜁니다
  • 세션 쿠키를 복사해 그 사용자인 것처럼 요청을 보냅니다

페이지에 닿는 웹뷰의 강한 기능은 브라우저가 페이지에 걸어 두는 보통의 보안 제한을 거치지 않습니다. 이 기능은 사용자 추적이나 피싱 같은 악의적인 목적에도 쓰일 수 있습니다. 피싱은 진짜처럼 꾸민 화면으로 비밀번호 같은 값을 빼내는 공격입니다.

이 위험이 몰리는 화면이 다른 서비스 계정으로 로그인하는 화면입니다. 새로 받은 앱에서 이미 쓰던 포털 계정으로 로그인하는 장면을 떠올려 봅시다. 이 화면이 웹뷰라면 앱은 포털 비밀번호를 읽을 수 있습니다. 앱에게 필요한 것은 포털이 내준 권한 하나입니다. 그런데 앱은 사용자의 비밀번호까지 쥐게 됩니다.

OAuth 2.0(Open Authorization)은 이런 로그인을 위한 규약입니다. 사용자는 비밀번호를 앱에 넘기지 않습니다. 포털의 로그인 화면에서 로그인한 뒤 동의 화면을 봅니다. 동의 화면은 앱이 가져갈 정보를 보여 주고 사용자에게 허락을 받는 화면입니다.

이 로그인과 허락을 맡는 포털 쪽 서버를 인가 서버라고 합니다. 앱이 그 서버에 보내 허락을 구하는 요청을 인가 요청이라고 합니다.

네이티브 앱은 인가 요청을 웹뷰로 해서는 안 됩니다(MUST NOT). 인가 서버는 웹뷰에서 온 인가 요청을 알아보고 막는 조치를 할 수 있습니다(MAY). 괄호 안의 두 낱말은 표준 문서가 지킬 강도를 적는 표시입니다. MUST NOT 은 어기면 안 된다는 뜻이고 MAY 는 해도 된다는 뜻입니다.

인가 서버와 같은 회사가 만든 믿을 만한 앱이라도 웹뷰는 문제를 남깁니다. 앱이 필요한 것보다 강한 자격 증명을 쥐게 됩니다. 꼭 필요한 권한만 쥐라는 최소 권한 원칙을 어기는 것입니다. 그만큼 공격받을 수 있는 면이 넓어질 수 있습니다.

구글은 이 조치를 자기 인가 서버에 걸었습니다. 2021년 6월에 웹뷰에서 오는 구글 OAuth 요청을 금지하는 정책을 알렸습니다. 2021년 9월 30일부터는 모든 웹뷰를 막는다고 밝혔습니다.

앱 권한을 내주는 통로

「상세」에서 본 통로는 거꾸로 앱의 약점이 됩니다. 안드로이드 WebView 에서 addJavascriptInterface 로 통로를 열면 페이지의 자바스크립트가 앱을 조종할 수 있습니다.

웹뷰 안의 HTML 일부라도 모르는 사람이 만든 것이면 위험합니다. 공격자는 앱 코드를 실행하는 HTML 을 넣을 수 있습니다. 공격자가 고른 다른 코드까지 실행될 수도 있습니다.

그래서 웹뷰에 뜨는 HTML 과 자바스크립트를 전부 직접 쓴 것이 아니면 이 통로를 열지 않습니다. 사용자가 웹뷰 안에서 남의 페이지로 옮겨 가지 못하게 합니다. 바깥 링크는 기기의 기본 브라우저가 열게 둡니다.

주소를 눌렀을 때 사용자의 브라우저가 여는 것이 기본 동작입니다. 위 경고는 앱이 페이지 이동을 직접 맡아 다룰 때 주로 걸립니다.

브라우저와 끊기는 로그인 상태

웹뷰는 로그인 상태를 기기 브라우저나 다른 앱과 나누지 않습니다. 사용자가 브라우저에서 로그인해 두었어도 웹뷰에서는 로그인 안 된 상태로 보입니다. 인가 요청마다 사용자가 다시 로그인해야 합니다. 이것은 흔히 사용자 경험을 떨어뜨린다고 여겨집니다.

브라우저 쪽에서도 데이터를 내주지 않습니다. 안드로이드의 기본 브라우저 앱은 보안상의 이유로 자기 앱 데이터를 다른 앱과 나누지 않습니다. 웹뷰의 격리된 저장 환경은 사용자를 평소 쓰던 싱글 사인온에서도 끊어 놓습니다. 싱글 사인온은 한 번 로그인으로 여러 서비스에 들어가는 방식입니다.

인앱 브라우저 탭은 사정이 다릅니다. 인앱 브라우저 탭은 앱 안에 뜨지만 브라우저가 직접 그리는 창입니다. 브라우저의 보안 성질과 로그인 상태를 온전히 지닙니다.

flowchart TD
    subgraph 브라우저["기기 브라우저"]
        BS["브라우저의 쿠키 저장소 · 로그인 상태"]
    end
    subgraph 앱["앱"]
        WV["웹뷰"]
        TAB["인앱 브라우저 탭"]
    end
    WV --> WS["웹뷰 몫의 쿠키 저장소 · 로그인 안 된 상태"]
    TAB --> BS

그림의 두 화살표가 이 소절의 요점입니다. 웹뷰는 따로 떨어진 저장소를 봅니다. 인앱 브라우저 탭은 브라우저의 저장소를 봅니다. 앱에 이미 로그인한 사용자를 웹뷰 안의 페이지에서도 같은 사람으로 이으려면 그 상태를 넘겨주는 일을 앱이 따로 맡아야 합니다.

웹뷰마다 다른 웹 기능

웹뷰는 대체로 짝이 되는 브라우저와 같은 기능을 냅니다. 그래도 일부 웹 API 는 빠져 있습니다.

웹뷰끼리도 동작이 서로 다릅니다. 그러면 페이지를 만드는 쪽은 웹뷰를 따로 가려 맞춰야 합니다. 웹이 여러 환경에서 같게 돌아간다는 성질이 그만큼 깎입니다.

웹뷰로 띄울 화면과 브라우저로 넘길 화면

위 대가를 화면 종류별로 모으면 아래와 같습니다. 가르는 기준은 둘입니다. 페이지를 앱을 만든 쪽이 전부 썼나, 그리고 앱이 엿보면 안 되는 화면인가입니다.

화면 여는 곳 까닭
앱 안에서 자주 바뀌는 콘텐츠 웹뷰 앱 화면을 새 판으로 내지 않고 웹 쪽에서 고친다
HTML 과 자바스크립트를 전부 직접 쓴 페이지 웹뷰 통로를 열어도 모르는 코드가 없다
다른 서비스의 로그인 · 동의 기본 브라우저 · 인앱 브라우저 탭 앱이 입력과 쿠키를 쥐면 안 된다
모르는 바깥 링크 기본 브라우저 사용자가 사이트를 확인해야 하고 통로가 새면 안 된다

이견

인앱 브라우저 탭을 웹뷰라고 부르느냐가 출처마다 다릅니다. 인앱 브라우저 탭은 「대가」 절에서 본, 앱 안에 뜨지만 브라우저가 그리는 창입니다. 안드로이드의 Custom Tabs 와 iOS 의 SFSafariViewController 가 이 부류에 듭니다.

IETF(Internet Engineering Task Force, 인터넷 표준을 만드는 단체)가 낸 RFC 8252 「OAuth 2.0 for Native Apps」(2017)는 둘을 따로 정의합니다. RFC(Request for Comments)는 이 단체가 내는 문서 번호 체계입니다.

  • 웹뷰는 「앱에 박혀 앱의 통제 아래 웹 페이지를 그리는 브라우저 UI(User Interface, 사용자 화면) 부품」입니다
  • 인앱 브라우저 탭은 「앱 안에 뜨지만 브라우저의 보안 성질과 로그인 상태를 온전히 지닌, 프로그램으로 띄운 브라우저」입니다

같은 RFC 는 앱이 쿠키 저장소와 페이지 내용에 닿느냐로 사용자 에이전트도 둘로 가릅니다. 앱이 닿는 쪽은 임베디드 사용자 에이전트, 못 닿는 쪽은 외부 사용자 에이전트입니다. RFC 8252 에서 인앱 브라우저 탭은 웹뷰가 아닙니다.

W3C(World Wide Web Consortium, 웹 표준 단체)의 WebView 커뮤니티 그룹은 문서 「WebView: Usage Scenarios and Challenges」에서 웹뷰를 두 갈래로 나눕니다.

갈래 꾸미는 폭 페이지에 닿나 브라우저와 상태를 나누나
브라우저형 웹뷰(Browser-like WebView) 대개 좁다 대개 못 닿는다 대개 나눈다
완전한 웹뷰(Fully-fledged WebView) 넓다 닿는다 안 나눈다

이 문서는 Custom Tabs 와 SFSafariViewController 를 「브라우저형 웹뷰를 여는 API」로 적습니다. 커뮤니티 그룹 문서에서 인앱 브라우저 탭은 웹뷰의 한 갈래입니다.

같은 W3C 안에서도 선이 다릅니다. 2022년 W3C 블로그 글 「Making WebViews work for the Web」은 Android WebView · UIWebView · WKWebView · WebView2 를 웹뷰라는 이름 아래 묶습니다. 그리고 그 넷을 앱 안에서 웹 콘텐츠를 그리는 다른 방법들과 한자리에 놓고 견줍니다. 다른 방법으로 적힌 것은 안드로이드의 Custom Tab · Trusted Web Activity 와 iOS 의 SFView · ASWebAuth 입니다. 네 이름은 모두 그 플랫폼이 웹뷰와 따로 내놓은 부품이고, 이 글에서 그것들은 웹뷰 묶음 밖에 섭니다.

그리고 커뮤니티 그룹은 2025년 말 정리 글에서 정의 자체가 아직 서지 않았다고 적었습니다. 웹뷰가 무엇이고 브라우저나 다른 사용자 에이전트와 어떻게 이어지는지 딱 맞아떨어지는 정의가 나온 적이 없다는 것입니다. 정의를 두고 논의는 했지만 합의에는 이르지 못했습니다. 웹뷰는 쓰임에 따라 사용자 에이전트일 때도 있고 아닐 때도 있다고도 적었습니다.

누가 인앱 브라우저 탭을 어떻게 두나
RFC 8252 웹뷰와 따로 정의한다
W3C WebView 커뮤니티 그룹 문서 브라우저형 웹뷰로 웹뷰에 넣는다
W3C 블로그 글(2022) 웹뷰와 가르는 「다른 방법」 쪽에 둔다
W3C WebView 커뮤니티 그룹 정리 글(2025) 웹뷰의 정의를 아직 합의하지 못했다고 적는다

관련 항목

웹뷰가 속하는 상위 분류

뷰 · UI 컴포넌트 · 사용자 에이전트 · 임베디드 사용자 에이전트 · 임베디드 브라우저 · 모바일 개발

웹뷰 안에서 페이지를 그리는 구성 요소

렌더링 엔진 · 자바스크립트 엔진 · HTML · CSS · 자바스크립트 · DOM

웹뷰를 구현한 플랫폼 부품

Android WebView · WKWebView · UIWebView · WebView2 · ArkWeb · Tencent X5

웹뷰 부품이 짝으로 삼는 브라우저와 엔진

Chromium · WebKit · Microsoft Edge · Chrome · Safari

웹뷰를 대신할 수 있는 다른 수단

브라우저 · 외부 사용자 에이전트 · 인앱 브라우저 탭 · Custom Tabs · SFSafariViewController · Trusted Web Activity · ASWebAuthenticationSession · 네이티브 앱 · 프로그레시브 웹 앱

웹뷰로 화면을 짓는 앱 구조와 프레임워크

하이브리드 앱 · 인앱 브라우저 · 미니앱 · 슈퍼앱 · 크로스플랫폼 프레임워크 · Apache Cordova · Capacitor · Ionic

앱과 페이지가 값을 주고받는 통로

자바스크립트 브리지 · postMessage · WKScriptMessageHandler · URL 스킴 · 딥 링크

웹뷰를 노리는 보안 공격

클릭재킹 · 피싱 · 교차 사이트 스크립팅 · 세션 하이재킹 · 자격 증명 탈취 · 중간자 공격

웹뷰 로그인을 막는 인가 규약과 원칙

OAuth 2.0 · OAuth 2.0 for Native Apps · 인가 서버 · PKCE · 소셜 로그인 · OpenID Connect · 싱글 사인온 · 최소 권한 원칙

서버가 웹뷰 요청을 알아보는 단서

사용자 에이전트 문자열 · User-Agent 헤더 · User-Agent Client Hints · 쿠키 · 세션 쿠키 · 액세스 토큰 · HTTP 헤더

웹뷰를 정의하는 표준 단체와 문서

IETF · W3C · RFC 8252 · RFC

다른 이름: WebView · web view · 웹 뷰 · web-view