PWA에서 상세 화면을 연 뒤 기기 뒤로가기를 누르면 목록으로 돌아가지 않고 앱 창이 닫혔다. 앱 내부에서는 화면을 바꿨지만 브라우저 히스토리에는 시작 페이지 한 개만 있었기 때문이다. Unity의 화면 스택과 브라우저의 방문 기록이 서로 다른 상태를 가지고 있었다.
뒤로가기는 단순 버튼 이벤트가 아니라 두 내비게이션 시스템을 맞추는 작업이었다.
내부 이동을 히스토리에 반영했다
화면을 열 때 공개 가능한 경로와 최소 상태를 pushState로 추가했다.
function openRoute(route) {
history.pushState({ route }, '', `/app/${route}`);
unityInstance.SendMessage('Navigator', 'Open', route);
}
window.addEventListener('popstate', event => {
const route = event.state?.route ?? 'home';
unityInstance.SendMessage('Navigator', 'Restore', route);
});
계정 정보나 민감한 화면 데이터를 URL과 history state에 넣지 않았다.
팝업과 화면 이동의 우선순위를 정했다
팝업이 열려 있을 때 뒤로가기는 팝업을 닫고, 입력 중이면 취소 확인을 보여주고, 그다음 화면 스택을 이동하게 했다. 모든 뒤로가기를 브라우저에 넘기면 사용 중인 상태를 잃을 수 있었다.
열린 팝업 있음 -> 팝업 닫기
저장 안 된 입력 -> 확인
내부 이전 화면 -> history.back()
시작 화면 -> 앱 종료 가능
같은 이벤트를 두 번 처리하지 않도록 현재 전환 중 상태도 확인했다.
새로고침으로 직접 경로에 들어와도 복원했다
히스토리만 추가하면 /app/profile에서 새로고침할 때 서버가 404를 반환할 수 있었다. 배포 서버는 앱 셸로 fallback하고, 시작 코드가 URL을 읽어 접근 가능한 화면으로 복원했다.
세션이 없거나 권한이 바뀌면 요청한 화면 대신 로그인 또는 기본 화면으로 보냈다.
내비게이션도 플랫폼 계약이었다
Unity 안에서 화면 전환이 됐으니 이동 기능이 끝난 줄 알았다. PWA에서는 브라우저와 OS가 뒤로가기의 의미를 이미 가지고 있었다. 앱이 그 규칙에 참여하지 않으면 사용자가 예상한 동작과 달라졌다.
이 작업 뒤 웹 화면 경로를 단순 표시 상태로 보지 않는다. URL, 히스토리, 앱 스택, 인증 상태가 같은 이동을 설명하도록 맞춘다. 뒤로가기 하나가 플랫폼다운 동작의 중요성을 보여줬다.