모바일 로그인 입력을 손본 뒤 Android 기기에서만 커서가 사라지는 문제가 남았다. 입력창을 처음 누르면 잘 보이는데 비밀번호 보기 버튼을 누르거나 앱을 잠깐 내렸다 돌아오면 커서는 없고 키보드만 열렸다. 에디터에서 같은 순서를 반복해도 재현되지 않아 코드보다 기기 문제처럼 느껴졌다.
그래도 “Android에서 이상하다”로 두면 고칠 수 없었다. 포커스가 사라지는 정확한 순서를 만들고, 화면 생명주기와 입력 필드 상태를 같이 기록했다.
재현 순서를 먼저 고정했다
처음에는 커서가 가끔 사라진다고만 적었다. 동작을 나누자 특정 조건이 보였다.
1. 로그인 화면 진입
2. 비밀번호 입력 필드 선택
3. 비밀번호 표시 토글
4. 앱을 백그라운드로 이동
5. 다시 돌아와 입력 필드 선택
단순 탭에서는 괜찮았고 입력 필드의 타입이 바뀌거나 포커스가 복구되는 과정에서 주로 발생했다. 재현 절차가 생기니 로그를 어디에 넣을지도 정할 수 있었다.
입력 타입 변경은 필드를 다시 만들기도 했다
비밀번호 표시를 바꾸려고 contentType을 수정한 뒤 텍스트를 다시 설정하는 코드가 있었다. 이 과정에서 캐럿 위치와 활성 상태가 초기화됐다. 현재 선택 범위를 보존하고 타입 변경 뒤 다시 활성화했다.
int caret = passwordField.caretPosition;
passwordField.contentType = showPassword
? TMP_InputField.ContentType.Standard
: TMP_InputField.ContentType.Password;
passwordField.ForceLabelUpdate();
passwordField.caretPosition = Mathf.Min(caret, passwordField.text.Length);
passwordField.ActivateInputField();
실제 기기에서는 같은 프레임에 키보드 상태도 바뀌어 다음 프레임에 활성화하는 처리가 필요했다.
앱 복귀와 화면 활성화를 구분했다
OnEnable은 화면 오브젝트가 켜질 때 호출되고, OnApplicationFocus는 앱이 포커스를 되찾을 때 호출된다. 두 곳에서 모두 무조건 첫 필드를 선택하니 사용자가 입력하던 필드와 충돌했다. 마지막으로 활성화된 필드를 기억하고 앱 복귀 시점에는 사용자가 입력 중이었을 때만 복원했다.
로그에는 비밀번호 값 같은 민감한 내용 대신 필드 이름, 선택 여부, 앱 포커스, 키보드 활성 여부만 남겼다. 기기 로그에서도 필요한 문맥은 충분했다.
플랫폼 차이는 마지막 단계가 아니었다
이 작업 전에는 에디터에서 기능이 되면 대부분 끝났다고 생각했다. 하지만 입력은 OS 키보드와 Unity 이벤트가 만나는 경계였다. 에디터 테스트는 로직을 확인했고, 실제 기기 테스트는 생명주기와 플랫폼 동작을 확인했다.
커서 하나를 고치면서 재현 절차, 안전한 로그, 앱 포커스까지 보게 됐다. 이후 모바일 문제를 만날 때는 플랫폼 이름으로 뭉뚱그리지 않고 어떤 생명주기와 외부 시스템이 끼어드는지부터 찾게 됐다.