| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
- gradle jdk
- JCF
- rememberupdatedstate
- 선언형ui
- bottomscaffold
- clean coder
- android
- NavHost
- remembercoroutinescope
- 명령형 ui
- mutableStateOf
- derivedstateof
- 선언형 ui
- apollo3
- 자바
- genarics
- compose
- producestate
- State
- ktor-auth
- 안드로이드
- 양과 늑대
- mutablestate
- snapshotflow
- 무선 페어링
- 2022 KAKAO BLIND RECRUITMENT
- 2989번
- Java
- 명령형ui
- 2022 kakao blind
- Today
- Total
버미
[안드로이드] 웹뷰와 커스텀 탭 본문
웹뷰와 커스텀 탭 모두 웹 페이지의 내용을 보여주는 컴포넌트다. 이 글을 통해 웹뷰를 상기해보고 커스텀 탭이 어떻게 차이가 있는지 알아보자.
웹뷰
웹뷰는 안드로이드에서 지원하는 컴포넌트로, 앱 내부에 웹 브라우저를 내장하여 웹 페이지를 렌더링하는 컴포넌트이다.
즉, 앱 안에 브라우저를 직접 구현하는 방식이다.
WebView의 핵심은 “렌더링”과 “제어”를 분리해서 이해하는 것이다. HTML을 파싱하고 DOM을 구성하며, 레이아웃을 계산하고 화면에 그리는 작업은 모두 Chromium 기반의 웹 엔진이 담당한다. 하지만 그 엔진은 앱 프로세스 안에서 동작하며, 앱은 WebView API를 통해 이 엔진을 제어할 수 있다. 즉, 렌더링 자체는 엔진이 수행하지만, 어떤 페이지를 로드할지, 어떤 JavaScript를 실행할지, 어떤 이벤트를 가로챌지는 전부 앱이 결정한다.
이 구조 덕분에 WebView에서는 일반 브라우저에서는 불가능한 수준의 제어가 가능하다. 예를 들어 evaluateJavascript()를 사용하면 웹 페이지 내부의 DOM에 접근해 데이터를 가져올 수 있다. 또한 JavaScript 인터페이스를 통해 웹과 네이티브 간 양방향 통신도 구현할 수 있다. 이처럼 WebView는 단순히 웹 페이지를 보여주는 것을 넘어, 웹을 앱의 일부처럼 동작하게 만드는 강력한 도구다.
하지만 이러한 강력함은 동시에 책임을 의미한다. WebView는 앱 내부에서 실행되기 때문에 보안과 안정성을 개발자가 직접 관리해야 한다. 외부에서 로드한 HTML에 대한 검증 없이 JavaScript 인터페이스를 열어두면 XSS와 같은 취약점이 발생할 수 있고, 잘못된 설정은 사용자 데이터 유출로 이어질 수 있다. 또한 웹 렌더링을 앱 내부에서 수행하기 때문에 성능에 대한 고려도 필요하다.
결국 WebView는 “브라우저를 여는 기술”이 아니라, 브라우저 엔진을 앱 안에 두고 직접 웹을 렌더링하고 제어하는 환경이다. 웹과 네이티브의 경계를 허물고 하나의 사용자 경험으로 통합할 수 있다는 점에서 매우 유용하지만, 그만큼 구조를 정확히 이해하고 사용하는 것이 중요하다.
한 줄로 정리하면 다음과 같다.
WebView는 브라우저를 실행하는 것이 아니라, 브라우저 엔진을 앱 내부에서 사용해 웹을 직접 제어하는 기술이다.
특징
- HTML, CSS, JavaScript 를 직접 렌더링 가능
- JavaScript 인터페이스를 통해, 안드로이드 ↔ 웹 양방향 통신 가능
장점
- 완전 제어가 가능해서 높은 자유도
- 앱 상태와 강하게 연동 가능
단점
- 앱 내부에서 렌더링이 되기 때문에, 성능 부담
- XSS, JS Injection 등 보안 취약점 존재
커스텀 탭
크롬과 같은 외부 브라우저를 앱 위에서 실행하는 방식이다.
즉, 브라우저를 직접 구현하는 것이 아닌, 빌려서 사용하는 방식이다.
안드로이드에서 웹 페이지를 열 때 흔히 “브라우저를 빌려쓴다”는 표현을 사용한다. 특히 Custom Tabs를 설명할 때 자주 등장하는 말인데, 이 표현은 방향은 맞지만 정확한 구조를 이해하지 않으면 쉽게 오해로 이어진다.
우선 중요한 전제부터 짚고 가야 한다. 안드로이드에서 브라우저는 단순히 “항상 백그라운드에서 실행되고 있는 존재”가 아니다. Chrome이든 Samsung Internet이든 브라우저 앱은 단지 설치된 애플리케이션일 뿐이며, 사용하지 않으면 프로세스가 아예 존재하지 않을 수도 있다. 즉, “기본 브라우저가 있으니 항상 프로세스도 떠 있다”는 생각은 틀린 가정이다. 안드로이드는 필요할 때만 프로세스를 생성하고, 필요 없으면 종료하는 구조이기 때문이다.
그렇다면 Custom Tabs에서 말하는 “브라우저를 빌려쓴다”는 것은 무엇을 의미할까? 핵심은 브라우저의 내부 인스턴스에 직접 접근하는 것이 아니라, 브라우저 앱과 IPC(Inter-Process Communication), 정확히는 Binder를 통해 협업하는 구조라는 점이다. Custom Tabs를 사용할 때 앱은 브라우저 프로세스 내부 객체를 직접 제어하는 것이 아니라, 브라우저가 제공하는 CustomTabsService에 바인딩하여 세션을 생성하고, 필요한 기능을 요청한다. 이후 실제 웹 콘텐츠는 브라우저 쪽 Activity가 실행되어 렌더링을 담당한다.
동작 흐름을 보면 더 명확하다. 앱에서 CustomTabsIntent.launchUrl()을 호출하면, 시스템은 Custom Tabs를 지원하는 브라우저를 찾는다. 이때 브라우저 프로세스가 이미 실행 중이라면 그대로 재사용하고, 실행 중이 아니라면 OS가 새로 프로세스를 생성한다. 이후 (선택적으로) bindCustomTabsService()를 통해 브라우저의 서비스에 연결할 수 있는데, 이 단계는 필수가 아니라 성능 최적화를 위한 선택 사항이다. 여기서 warmup()이나 세션 생성, URL prefetch 같은 작업을 통해 페이지 로딩 속도를 개선할 수 있다. 마지막으로 브라우저의 Activity가 foreground로 올라오며 실제 화면이 표시된다.
여기서 중요한 포인트는 Custom Tabs가 “앱 내부에 웹을 렌더링하는 방식”이 아니라는 것이다. 즉, WebView처럼 앱 프로세스 안에서 웹을 그리는 것이 아니라, 브라우저 프로세스가 별도로 존재하고 그 Activity가 화면에 표시되는 구조다. 다만 툴바 색상 커스터마이징, 애니메이션, 뒤로가기 동작 등으로 인해 사용자 입장에서는 마치 앱 내부 화면처럼 자연스럽게 이어지는 경험을 제공한다.
또 하나 중요한 점은 모든 브라우저가 Custom Tabs를 지원하는 것은 아니라는 것이다. 따라서 실제 구현에서는 CustomTabsClient.getPackageName() 등을 통해 지원 브라우저를 먼저 탐색하고, 없는 경우에는 ACTION_VIEW로 fallback하는 구조를 사용한다. 이 fallback은 “같은 방식으로 동작한다”는 의미가 아니라, 단순히 “어쨌든 URL은 열리게 한다”는 의미에 가깝다. 즉, Custom Tabs가 제공하는 최적화된 UX와 성능은 포기하고 기본 브라우저 실행으로 대체하는 것이다.
정리하면 Custom Tabs는 단순히 브라우저를 여는 기술이 아니라, 브라우저 앱의 기능을 IPC 기반으로 재사용하면서도 앱과 자연스럽게 이어지는 사용자 경험을 제공하는 방식이다. 브라우저 프로세스는 항상 존재하는 것이 아니라 필요할 때 생성되며, 서비스 바인딩은 성능 최적화를 위한 선택적 단계다. 그리고 최종적으로 화면을 그리는 주체는 여전히 브라우저라는 점을 이해하는 것이 가장 중요하다.
한 줄로 정리하면 다음과 같다.
Custom Tabs는 브라우저를 “내 앱 안에 띄우는 기술”이 아니라, 브라우저와 협업하여 “브라우저가 그린 화면을 앱처럼 보이게 사용하는 기술”이다.
특징
- 크롬(or 기본) 브라우저 엔진 사용
- 쿠키 및 로그인 상태 자동 공유
- 주소창 및 보안 UI 제공
장점
- 이미 실행 중인 브라우저를 활용하여 빠른 성능
- 크롬 정책을 적용하여 높은 보안
단점
- HTML/DOM 제어 불가능
- JavaScript 주입 불가
- 앱과의 직접적인 데이터 연결 어려움
Reference
'안드로이드' 카테고리의 다른 글
| [안드로이드] MVI에서 Event 처리: Channel vs SharedFlow (0) | 2025.12.22 |
|---|---|
| [안드로이드] JDK, JRE, JVM 그리고 Gradle JDK (0) | 2025.10.09 |
| [안드로이드] 안드로이드 스튜디오 무선 연결이 안될 때 (0) | 2025.10.02 |
| [안드로이드] Gson과 kotlinx.serialization 차이 (0) | 2025.09.23 |
| [안드로이드] Gradle 이란 (0) | 2025.09.16 |