웹 미리보기 환경에서 로그인 폼을 열면 입력하지 않은 계정이 채워지는 일이 있었다. 화면의 placeholder처럼 보이다가 필드를 누르면 실제 값이 됐고, 앱 코드의 상태에는 빈 문자열이 남아 있었다. 버튼은 비활성인데 화면에는 값이 보이는 이상한 상태였다.
브라우저 자동 완성은 사용자의 편의를 위한 기능이지만 Unity나 웹 앱의 입력 이벤트와 같은 시점에 움직이지 않았다. 화면에 보이는 DOM 값과 앱이 기억한 값이 어긋났다.
자동 완성을 무조건 막는 게 답은 아니었다
처음에는 모든 입력에 autocomplete="off"를 붙이고 싶었다. 브라우저가 이를 항상 따르는 것도 아니었고, 정상 로그인에서는 비밀번호 관리자의 도움을 막을 수 있었다. 미리보기용 임시 로그인과 실제 사용자 로그인의 정책을 구분했다.
<input name="preview-user" autocomplete="username" />
<input name="preview-password" type="password"
autocomplete="current-password" />
실제 필드의 의미와 안정적인 이름을 알려주는 편이 임의 이름으로 속이는 것보다 예측 가능했다.
DOM 값과 앱 상태를 동기화했다
Unity WebGL 입력을 HTML 요소와 연결하는 구간에서 input, change 이벤트뿐 아니라 화면이 활성화된 직후 실제 DOM 값을 읽었다. 자동 완성으로 값이 들어왔지만 이벤트가 오지 않은 경우를 보완했다.
const value = input.value;
unityInstance.SendMessage('LoginBridge', 'OnUserChanged', value);
비밀번호 값은 로그에 남기지 않았고, 메시지 전달 시점과 값의 존재 여부만 확인했다.
테스트 프로필도 실제 조건에 가까워야 했다
새 브라우저 프로필에서는 문제가 없고 이미 로그인 기록이 있는 프로필에서만 재현됐다. 저장된 자동 완성, 비밀번호 관리자, 새로고침, 뒤로 가기 같은 조건을 테스트 목록에 넣었다.
자동 로그인 정보와 브라우저 자동 완성 정보가 각각 어디서 지워지는지도 구분했다. 앱 로그아웃으로 브라우저가 기억한 계정까지 지울 수는 없었다.
웹에서는 브라우저도 상태의 주체였다
Unity 화면만 보던 때에는 입력 값의 주인이 앱이라고 생각했다. WebGL에서는 브라우저가 접근성, 자동 완성, 키보드 동작에 관여했다. 이를 방해할 대상으로만 보면 사용자 경험이 나빠졌다.
이 문제를 통해 웹 기능은 렌더링된 화면과 앱 코드 사이만 보는 것으로 부족하다는 걸 배웠다. 브라우저가 제공하는 기능을 인정하고 두 상태를 명시적으로 동기화해야 했다.