Android 쿠키 사용 방법 정리 - WebView CookieManager 예제까지

개요

안드로이드에서 쿠키를 다룰 때는 보통 두 가지 상황이 있다.

  1. WebView 안에서 웹 세션을 유지해야 하는 경우
  2. 앱의 HTTP 통신에서 쿠키를 직접 관리해야 하는 경우

실무에서는 대부분 첫 번째, 즉 WebView 쿠키 처리가 더 자주 문제를 만든다.
로그인 세션이 유지되지 않거나, 웹에서 발급한 쿠키를 앱이 미리 넣어줘야 하거나, 서드파티 쿠키 때문에 인증이 깨지는 경우가 대표적이다.

이 글에서는 다음 내용을 정리한다.

  • Android WebView 에서 쿠키를 사용하는 방법
  • CookieManager 로 쿠키를 설정, 조회, 삭제하는 방법
  • flush()CookieSyncManager 의 차이
  • 서드파티 쿠키와 파일 스킴 쿠키 주의사항
  • 앱 네트워크 통신에서의 쿠키 관리 기본 예시

Android 에서 쿠키를 다루는 핵심 클래스

안드로이드 공식 문서 기준으로 android.webkit.CookieManager 는 애플리케이션의 WebView 인스턴스가 사용하는 쿠키를 관리한다.

WebView 관련 쿠키는 보통 이 클래스로 다룬다.

val cookieManager = CookieManager.getInstance()

중요한 점은 이 클래스가 생성자 사용 대상이 아니라는 점이다.
공식 문서도 직접 생성하지 말고 getInstance() 로 singleton 을 가져오라고 안내한다.


가장 기본적인 설정

WebView 에서 쿠키를 정상적으로 쓰려면 보통 아래 설정부터 확인한다.

val webView: WebView = findViewById(R.id.webView)

webView.settings.javaScriptEnabled = true
webView.settings.domStorageEnabled = true

val cookieManager = CookieManager.getInstance()
cookieManager.setAcceptCookie(true)

setAcceptCookie(true)WebView 가 쿠키를 보내고 받을 수 있게 한다.
공식 문서 기준 기본값은 true 이지만, 명시적으로 써 두면 의도가 분명해진다.


WebView 에 쿠키를 직접 넣는 방법

앱에서 로그인 토큰이나 세션 쿠키를 먼저 알고 있고, 그 값을 WebView 에 주입하고 싶을 때가 있다.

예를 들어:

  • 앱 로그인 후 같은 세션으로 웹 페이지를 열고 싶을 때
  • SSO 연동 시 웹에 쿠키를 미리 넣어야 할 때
  • 특정 도메인에 세션 쿠키를 세팅한 뒤 loadUrl() 해야 할 때

이때는 setCookie() 를 사용한다.

val url = "https://example.com"
val cookieManager = CookieManager.getInstance()

cookieManager.setAcceptCookie(true)
cookieManager.setCookie(
url,
"accessToken=abc123; Path=/; Secure; SameSite=Lax"
)
cookieManager.flush()

webView.loadUrl(url)

여기서 중요한 포인트는 다음이다.

  • 쿠키는 대상 URL 기준으로 설정한다.
  • 보통 loadUrl() 전에 넣는 편이 안전하다.
  • 저장 내용을 디스크까지 반영하고 싶으면 flush() 를 호출한다.

즉 “쿠키 넣기 -> flush -> loadUrl” 순서를 기억해 두면 된다.


비동기 setCookie() 예제

API 21 이상에서는 callback 을 받는 setCookie() 도 사용할 수 있다.

val url = "https://example.com"
val cookieManager = CookieManager.getInstance()

cookieManager.setCookie(
url,
"sessionId=xyz789; Path=/; Secure; SameSite=None"
) { success ->
if (success) {
cookieManager.flush()
webView.loadUrl(url)
}
}

이 방식은 쿠키 설정 성공 여부를 확인하고 그 다음 동작을 이어가고 싶을 때 유용하다.

예를 들어:

  • 쿠키 주입이 끝난 뒤에만 페이지를 열고 싶을 때
  • 로그인 브릿지 흐름에서 순서를 보장하고 싶을 때

현재 쿠키 조회하기

특정 URL 에 어떤 쿠키가 들어 있는지 확인하고 싶다면 getCookie() 를 사용한다.

val cookies = CookieManager.getInstance().getCookie("https://example.com")
Log.d("COOKIE", cookies ?: "no cookies")

반환 값은 보통 HTTP Cookie 헤더 형태의 문자열이다.

예:

sessionId=abc123; accessToken=token-value

디버깅할 때는 편리하지만, 운영 로그에 민감한 쿠키 값을 그대로 남기지 않도록 주의해야 한다.


쿠키 삭제하기

로그아웃 처리나 세션 초기화가 필요하면 쿠키 삭제가 필요하다.

모든 쿠키 삭제

공식 문서 기준 removeAllCookie() 는 deprecated 이고, API 21 이상에서는 removeAllCookies() 를 사용해야 한다.

val cookieManager = CookieManager.getInstance()

cookieManager.removeAllCookies { removed ->
if (removed) {
cookieManager.flush()
}
}

이 메서드는 비동기다.
즉 삭제 직후 바로 다음 작업을 하면 타이밍 이슈가 생길 수 있으므로 callback 이후에 후속 처리를 하는 편이 좋다.

세션 쿠키만 삭제

세션 쿠키만 지우고 싶다면:

CookieManager.getInstance().removeSessionCookies { removed ->
if (removed) {
CookieManager.getInstance().flush()
}
}

로그아웃 시 영속 쿠키까지 모두 지울지, 세션 쿠키만 지울지는 서비스 정책에 따라 다르다.


flush() 는 왜 필요한가

공식 문서 기준 flush() 는 현재 getCookie() API 로 접근 가능한 쿠키를 영구 저장소에 기록하도록 보장한다.

CookieManager.getInstance().flush()

즉 메모리에만 반영된 쿠키를 디스크에도 반영하고 싶을 때 호출하는 메서드라고 이해하면 된다.

다음 상황에서 특히 자주 쓴다.

  • 앱이 종료되기 전에 쿠키를 저장하고 싶을 때
  • 쿠키를 세팅한 직후 안정적으로 반영하고 싶을 때
  • 로그아웃 후 삭제 상태를 확실히 반영하고 싶을 때

CookieSyncManager 는 더 이상 쓰지 않는다

예전 안드로이드 예제에는 CookieSyncManager 코드가 많이 나온다.
하지만 공식 문서 기준 이 클래스는 API 21 에서 deprecated 되었고, 이제는 WebView 가 쿠키를 자동으로 sync 한다.

즉 예전 방식:

// 더 이상 권장되지 않음
CookieSyncManager.createInstance(context)
CookieSyncManager.getInstance().startSync()
CookieSyncManager.getInstance().sync()

대신 지금은:

CookieManager.getInstance().flush()

를 쓰는 것이 맞다.


서드파티 쿠키 허용

공식 문서 기준 setAcceptThirdPartyCookies()WebView 별 정책이다.
즉 앱 전체 공통 설정이 아니라, 각 WebView 인스턴스마다 따로 적용할 수 있다.

val cookieManager = CookieManager.getInstance()
cookieManager.setAcceptThirdPartyCookies(webView, true)

이 설정이 필요한 대표적인 경우는 다음과 같다.

  • 외부 인증 페이지를 iframe 으로 여는 경우
  • 결제/SSO/광고 연동처럼 다른 도메인의 쿠키가 필요한 경우
  • 웹 로그인은 되는데 특정 인증 흐름만 WebView 에서 실패하는 경우

공식 문서에 따르면:

  • 앱이 KITKAT 이하를 target 하면 기본적으로 허용
  • 앱이 LOLLIPOP 이상을 target 하면 기본적으로 비허용

즉 최신 앱에서는 필요한 경우 명시적으로 켜줘야 할 수 있다.


파일 스킴 쿠키는 피하는 편이 좋다

공식 문서 기준 setAcceptFileSchemeCookies() 는 API 30 에서 deprecated 되었고, 보안상 안전하지 않다고 안내한다.

이유는 file:// URL 이 쿠키를 공유하면서 의도하지 않은 노출이 생길 수 있기 때문이다.

즉 이런 방식:

// 권장되지 않음
CookieManager.setAcceptFileSchemeCookies(true)

보다는 공식 문서가 권장하는 androidx.webkit.WebViewAssetLoader 방식으로 http(s) 모델에 맞춰 로컬 리소스를 제공하는 편이 좋다.


실전 예제 1: 앱 로그인 후 WebView 에 세션 전달

앱에서 이미 로그인되어 있고, 같은 세션으로 웹 페이지를 열고 싶은 경우의 대표 예제다.

class HybridActivity : AppCompatActivity() {
private lateinit var webView: WebView

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_hybrid)

webView = findViewById(R.id.webView)

webView.settings.apply {
javaScriptEnabled = true
domStorageEnabled = true
}

val url = "https://example.com"
val sessionId = "my-session-id"

val cookieManager = CookieManager.getInstance()
cookieManager.setAcceptCookie(true)
cookieManager.setAcceptThirdPartyCookies(webView, true)

cookieManager.setCookie(
url,
"SESSION=$sessionId; Path=/; Secure; HttpOnly; SameSite=Lax"
) { success ->
if (success) {
cookieManager.flush()
webView.loadUrl(url)
}
}
}
}

이 패턴은 “로그인 API 는 앱이 호출하고, 화면은 WebView 로 보여주는” 하이브리드 앱에서 자주 사용된다.


실전 예제 2: 로그아웃 시 쿠키 초기화

fun logout(webView: WebView) {
val cookieManager = CookieManager.getInstance()

cookieManager.removeAllCookies {
cookieManager.flush()

webView.clearHistory()
webView.clearCache(true)
webView.loadUrl("https://example.com/login")
}
}

쿠키만 지우고 끝내지 말고, 상황에 따라:

  • WebView cache
  • history
  • local storage 처리 여부

도 함께 검토해야 한다.
서비스에 따라 “로그아웃했는데 뒤로 가기로 이전 세션 화면이 보이는” 문제가 여기서 발생하기도 한다.


실전 예제 3: 앱 HTTP 통신에서 쿠키 사용

WebView 말고 앱의 HTTP 통신에서 쿠키를 다루고 싶다면 java.net.CookieManager 를 사용할 수 있다.
안드로이드 공식 문서 기준 이 클래스는 CookieHandler 의 구현체이며, HttpURLConnection 과 함께 사용할 수 있다.

val cookieManager = java.net.CookieManager()
java.net.CookieHandler.setDefault(cookieManager)

간단한 예시는 다음과 같다.

val cookieManager = java.net.CookieManager()
java.net.CookieHandler.setDefault(cookieManager)

val url = java.net.URL("https://example.com/login")
val connection = url.openConnection() as java.net.HttpURLConnection

connection.requestMethod = "GET"
connection.connect()

val responseCode = connection.responseCode
println("responseCode = $responseCode")

이 경우 서버가 Set-Cookie 를 내려주면 CookieManagerCookieStore 에 저장된다.

val store = cookieManager.cookieStore
for (cookie in store.cookies) {
println("${cookie.name}=${cookie.value}")
}

다만 여기서 중요한 점은:

  • android.webkit.CookieManagerWebView
  • java.net.CookieManager 는 앱 HTTP 통신용

이라는 것이다.

즉 둘은 같은 이름이지만 역할이 다르다.
앱 구조에 따라 두 영역을 별도로 맞춰줘야 할 수도 있다.

이 구분은 공식 문서의 클래스 역할 설명을 바탕으로 한 해석이다.


쿠키가 잘 안 먹을 때 점검할 것

실무에서 자주 보는 문제는 대부분 아래 항목에 걸린다.

  • setCookie()loadUrl() 뒤에 호출하고 있는지
  • flush() 를 안 해서 반영 타이밍이 꼬였는지
  • 도메인/경로가 실제 요청 URL 과 안 맞는지
  • Secure 쿠키인데 https 가 아닌 URL 을 쓰는지
  • 서드파티 쿠키가 필요한데 setAcceptThirdPartyCookies() 를 안 켰는지
  • 로그아웃 시 쿠키만 지우고 캐시/히스토리를 안 지웠는지
  • 옛날 예제처럼 CookieSyncManager 를 아직 쓰고 있는지

특히 “앱에서는 쿠키 넣었다고 생각하는데 웹은 로그인 안 됨” 문제는 대부분 도메인, 경로, 시점 문제다.


정리

안드로이드에서 쿠키를 사용할 때 핵심은 WebView 쿠키와 앱 HTTP 쿠키를 구분해서 이해하는 것이다.

  • WebView 쿠키는 android.webkit.CookieManager
  • 앱 HTTP 쿠키는 java.net.CookieManager
  • WebView 에 쿠키를 넣을 때는 보통 setCookie -> flush -> loadUrl
  • 서드파티 쿠키가 필요한 흐름은 별도 허용 여부 확인
  • CookieSyncManager 는 더 이상 쓰지 않고 flush() 사용

하이브리드 앱이나 인증 연동이 있는 프로젝트라면 쿠키 처리는 거의 필수로 만나게 된다.
처음부터 도메인, 타이밍, 삭제 정책까지 함께 정리해 두면 디버깅 시간을 크게 줄일 수 있다.


참고

Share