3 분 소요

Android WebView에 User-Agent 값 추가 또는 변경하기

Android 앱에서 WebView를 쓸 때 서버나 웹 페이지 쪽에서 앱 전용 요청을 구분해야 하는 경우가 있다. 이때 가장 간단하게 쓰는 방법 중 하나가 User-Agent 문자열을 조정하는 것이다.

실제로는 아래 같은 상황에서 자주 사용한다.

  • 앱 내 WebView 요청인지 일반 모바일 브라우저 요청인지 구분하고 싶을 때
  • 서버 로그에서 특정 앱 버전 트래픽을 식별하고 싶을 때
  • 웹 페이지에서 앱 전용 분기 처리를 하고 싶을 때
  • 외부 SDK나 사내 서버가 특정 UA 토큰을 요구할 때

이 글에서는 Jetpack Compose 환경에서 WebViewuserAgentString에 값을 추가하는 방법과, 기존 값을 완전히 교체하는 방법을 나눠서 정리한다.

기본 개념

WebView는 내부적으로 브라우저처럼 요청을 보낼 때 User-Agent 헤더를 사용한다. Android 기본 UA에는 보통 아래와 같은 정보가 포함된다.

  • Android 버전
  • 디바이스/빌드 정보
  • WebView / Chrome 엔진 버전
  • Safari 호환 문자열

이 기본 값을 유지한 채 뒤에 앱 식별 문자열만 붙이는 방식이 가장 무난하다.

예:

  • ... Mobile Safari/537.36 changok89

반대로 기존 값을 완전히 바꾸면 서버 호환성이나 사이트 렌더링에 영향이 생길 수 있으므로 목적이 분명할 때만 쓰는 편이 좋다.

1. 기존 User-Agent 뒤에 값 추가하기

가장 안전하고 실무적으로 추천되는 방법이다. 기존 UA를 유지하면서 뒤에 앱 식별용 토큰을 추가한다.

@Composable
fun MainContent() {
    Scaffold(
            content = { WebViewContent() }
    )
}

@Composable
fun WebViewContent(){

    val mUrl = "https://changok89.github.io"
    AndroidView(factory = {
        WebView(it).apply {
            layoutParams = ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT
            )
            webViewClient = WebViewClient()
            settings.userAgentString += " changok89"
            loadUrl(mUrl)
        }
    }, update = {
        it.loadUrl(mUrl)
    })
}

Image Alt userAgent1

이 방식이 좋은 이유

  • 기본 브라우저 호환성을 최대한 유지할 수 있다.
  • 서버에서 contains("changok89") 같은 식으로 앱 요청을 구분하기 쉽다.
  • 일부 사이트가 UA 구조를 기대하는 경우에도 깨질 가능성이 낮다.

추천 사용 예

  • 앱 이름 또는 서비스 이름 추가
  • 앱 버전 추가
  • 배포 채널 정보 추가

예를 들면 아래처럼 더 구체적으로 붙일 수도 있다.

settings.userAgentString += " changok89-app/1.0.0"

2. User-Agent 값을 완전히 변경하기

기존 UA를 버리고 원하는 문자열로 대체하는 방법도 가능하다.

@Composable
fun MainContent() {
    Scaffold(
            content = { WebViewContent() }
    )
}

@Composable
fun WebViewContent(){

    val mUrl = "https://changok89.github.io"
    AndroidView(factory = {
        WebView(it).apply {
            layoutParams = ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT
            )
            webViewClient = WebViewClient()
            settings.userAgentString = "changok89"
            loadUrl(mUrl)
        }
    }, update = {
        it.loadUrl(mUrl)
    })
}

Image Alt userAgent2

언제 이 방식을 쓰나

  • 서버가 완전히 고정된 커스텀 UA를 요구할 때
  • 내부 테스트 환경에서만 특정 UA만 허용할 때
  • 브라우저 호환성을 신경 쓰지 않는 사내 전용 페이지일 때

주의할 점

이 방식은 꽤 공격적이다. 너무 짧거나 비표준적인 UA를 넣으면 아래 문제가 생길 수 있다.

  • 일부 사이트가 모바일 브라우저로 인식하지 못함
  • 서버가 예상치 못한 클라이언트로 판단함
  • 웹 기능 분기가 깨질 수 있음
  • 디버깅 시 실제 Chrome/WebView 동작과 달라질 수 있음

그래서 외부 웹사이트를 로드하는 일반적인 앱에서는 기존 UA에 값을 덧붙이는 방식이 더 안전하다.

Compose에서 주의할 점

예제처럼 update 블록에서 매번 loadUrl()을 호출하면 recomposition에 따라 불필요한 재로드가 생길 수 있다. 실제 프로젝트에서는 다음을 고려하는 편이 좋다.

  • URL 변경 시점에만 로드하도록 제어
  • remember로 WebView 상태 관리
  • 뒤로가기/세션 상태를 별도로 관리

즉, 글의 핵심은 UA 설정 방식이고, 실제 운영 코드에서는 WebView 생명주기까지 같이 정리하는 것이 좋다.

서버에서 어떻게 활용할 수 있나

User-Agent에 앱 식별 문자열을 넣으면 서버나 로그 분석 도구에서 꽤 유용하게 쓸 수 있다.

예를 들어:

  • 앱 내 WebView 트래픽만 필터링
  • 특정 앱 버전 요청만 추적
  • A/B 테스트 또는 앱 전용 페이지 분기
  • 외부 브라우저와 앱 내 브라우저를 분리 분석

추천 패턴

대부분의 경우 아래 패턴이 가장 무난하다.

val defaultUA = settings.userAgentString
settings.userAgentString = "$defaultUA changok89-app/1.0.0"

이렇게 하면 기본 UA 구조를 유지하면서도 앱 식별이 가능하다.

확인 방법

설정 후에는 아래 중 하나로 실제 UA를 확인하면 된다.

  • 서버 로그 확인
  • requestbin 같은 테스트 엔드포인트 사용
  • JavaScript에서 navigator.userAgent 출력
  • 개발자 도구나 프록시 도구로 요청 헤더 확인

마무리

Android WebView에서 User-Agent를 조정하는 일 자체는 어렵지 않지만, 기존 값을 유지할지 완전히 바꿀지에 따라 안정성이 크게 달라진다.

내 기준으로는 이렇게 정리한다.

  • 외부 웹 호환성이 중요하다 → 기존 UA에 추가
  • 내부 시스템 전용이고 요구사항이 명확하다 → 완전 변경 가능

대부분의 앱에서는 “기본 UA + 앱 식별 토큰 추가”가 가장 실용적이다.

댓글남기기