Skip to Content
DecisionsADR-0005: eziok App2App은 userAgent와 deviceBrowser를 함께 보내야 켜진다

ADR-0005: eziok App2App은 userAgent와 deviceBrowser를 함께 보내야 켜진다

  • Status: Accepted
  • Date: 2026-08-31
  • 관련: HMH-8978, PR #5799 · ADR-0004의 근거를 정정함
  • 배선: apps/app/src/features/eziok/useEziokAuth.ts (resolveDeviceBrowser)

Context

ADR-0004에서 SIV WebView에 applicationNameForUserAgent="MobileApp"을 넣어 App2App으로 전환했습니다. 그 문서는 “검토한 대안”에서 deviceBrowser 파라미터 변경을 **“UA가 진짜 스위치이므로 효과가 없다”**며 의도적으로 제외했습니다.

프로덕션이 이 판단을 부정했습니다. OTA 배포 후에도 여전히 PUSH로 동작했습니다(인증사업자 앱이 즉시 뜨지 않고 푸시 알림이 옴).

계측으로 좁힌 결과:

확인결과
WebView UA (프로덕션 iPhone, OTA 직후)... Mobile/15E148 MobileAppUA는 정상, OTA·prop 모두 적용됨
siv_native_external_app_open (3시간)0건 — 딥링크 분기가 한 번도 실행되지 않음 = 표준창이 dream-eziok URL을 뱉지 않음
우리가 보내던 deviceBrowser'MB' (native는 redirect 모드)

UA는 필요조건이었지 충분조건이 아니었습니다.

원인은 표준창 가이드 2.6의 자동승격 서술 범위입니다. 가이드는 두 군데 모두 WB만 언급합니다.

WB(Web Browser) 설정시에도 MWV Flag로 자동변환되어 PUSH가 가지 않고…” “웹스크립트에 WB 플래그로 설정되어도 MWV Flag로 자동변환”

MB(모바일웹)에 대한 언급은 없습니다. native 경로는 redirect 모드라 MB를 보내고 있었고, 자동승격 규칙에 걸리지 않았습니다. ADR-0004의 근거는 “WB는 자동승격된다”는 서술만 보고 MB도 그럴 것이라고 일반화한 것이 오류였습니다.

검토한 대안

대안채택 안 한 이유
모든 경로에서 무조건 MWV 전송App2App이 배선되지 않은 구 WebView 셸·일반 브라우저까지 의미가 틀린 값을 받는다. 가이드상 그 경우 WB로 자동강등되어 동작은 같지만, 틀린 값을 보내지 않는 편이 낫다
MBWB로만 변경 (자동승격에 기대기)WB는 “그렇게 설정해도 승격된다”는 폴백 서술이다. 가이드 표에서 APP 직접호출 방식의 값은 MWV이므로 의도를 그대로 표현하는 값을 쓴다
native 셸에서 web에 플래그를 주입웹·native 양쪽에 배선이 생긴다. UA는 이미 native가 붙이고 web이 읽을 수 있으므로 단일 신호원으로 충분하다

Decision

deviceBrowser를 UA에서 파생시킨다. navigator.userAgentMobileApp 표식이 있을 때만 'MWV'를 보내고, 없으면 기존값(redirect=MB, callback=WB)을 유지합니다.

// apps/app/src/features/eziok/useEziokAuth.ts export function resolveDeviceBrowser( userAgent: string | undefined, mode: 'redirect' | 'callback', ): EziokDeviceBrowser { if (userAgent?.includes('MobileApp')) return 'MWV'; return mode === 'redirect' ? 'MB' : 'WB'; }
  • UA가 단일 신호원입니다. native 셸이 UA에 표식을 붙이고, web이 그것을 읽어 플래그를 정합니다. 두 값이 어긋날 수 없습니다
  • 순수 함수로 추출해 단위 테스트를 붙였습니다 — 이 판정은 프로덕션에서만 드러나는 종류의 버그였고, 실제로 그렇게 새어 나갔습니다
  • siv_auth_start 로그에 deviceBrowser를 실어 “App2App으로 요청했는데 PUSH가 왔다”를 구분할 수 있게 했습니다

Consequences

좋아지는 것

  • App2App이 실제로 켜집니다 (ADR-0004가 의도했던 상태에 비로소 도달)
  • App2App이 배선되지 않은 구 WebView 셸·일반 브라우저는 기존 동작 그대로입니다 (UA에 표식이 없으므로)
  • 요청 시점의 deviceBrowser가 로그에 남아, 다음에 같은 증상이 나면 3시간이 아니라 즉시 구분됩니다

감수하는 것

  • web이 native의 UA 규약에 의존합니다. MobileApp 문자열이 두 레이어(native 셸의 applicationNameForUserAgent, web의 resolveDeviceBrowser)에 각각 상수로 존재합니다. 한쪽만 바꾸면 조용히 PUSH로 돌아갑니다
  • 가이드에 명시되지 않은 동작(MB는 자동승격 대상이 아님)에 대한 추론에 기대고 있습니다. 벤더가 이를 바꾸면 다시 깨질 수 있습니다

이 결정을 다시 열어야 할 때

  • 이 변경 후에도 hadEziokPrefixtrue로 찍히지 않을 때 → 원인은 플래그가 아니다. 다음 후보는 이용기관 단위 App2App 등록(카카오 APP 이용상품 K1120, 네이버 callback URL)이며 드림시큐리티 문의 건으로 넘어간다
  • 벤더가 가이드 2.6의 자동승격 규칙이나 deviceBrowser 값 체계를 변경할 때

ADR-0004에서 배울 것

ADR-0004는 가이드에 없는 것을 있는 것처럼 일반화했습니다. “WB는 자동승격된다”에서 “플래그는 무의미하다”로 건너뛴 것이 오류였고, 그 결과 대안 하나를 검증 없이 제외했습니다.

교훈은 “더 조사했어야 한다”가 아닙니다 — 결정 문서에 근거를 적어 뒀기 때문에 3시간 만에 어디가 틀렸는지 짚을 수 있었다는 점입니다. 근거 없이 “App2App으로 간다”만 남겼다면 PUSH로 도는 원인을 UA·OTA·표준창 어디서부터 뒤져야 할지 몰랐을 것입니다.

Last updated on