Cheondi
개발 · API

중복 로그인은 서버 문제일까 화면 문제일까

중복 로그인 알림을 따라가며 서버 세션과 클라이언트 화면의 책임을 나눈 기록입니다.

  • #session
  • #api
  • #login

다른 기기에서 같은 계정으로 로그인했을 때 기존 앱에 중복 로그인 알림이 나타나는 기능을 봤다. 알림이 늦게 뜨거나, 확인 버튼을 누른 뒤 로그인 화면으로 가지 않고 다시 연결되는 경우가 있었다. 처음에는 서버가 세션을 잘못 끊는 문제인지 클라이언트 화면 전환 문제인지 구분하기 어려웠다.

로그인을 허용하고 기존 세션을 만료시키는 판단은 서버에 있었고, 그 사실을 사용자에게 안전하게 보여주는 책임은 클라이언트에 있었다.

서버 이벤트와 화면 행동을 분리했다

클라이언트가 받은 이벤트를 바로 팝업 코드에 연결하지 않고 세션 상태로 변환했다.

void OnSessionRevoked(SessionEvent message)
{
    session.MarkRevoked(message.Reason);
    connection.StopReconnect();
    navigator.ShowSessionEnded();
}

팝업이 닫혀 있거나 다른 화면 위에 있어도 세션 상태 자체는 만료된 채 유지됐다. 화면이 다시 열릴 때도 유효하지 않은 세션으로 요청하지 않았다.

재연결이 만료를 되돌리면 안 됐다

네트워크가 끊기면 자동 재연결하는 코드가 중복 로그인으로 연결이 닫힌 경우에도 실행됐다. 종료 원인을 구분하지 않으니 새 연결이 생겼다가 다시 거절되는 반복이 발생했다.

일시적 네트워크 종료 -> 세션 유지, 제한된 재연결
서버의 세션 만료    -> 재연결 중단, 로그인 화면
사용자 로그아웃      -> 로컬 정보 정리, 재연결 금지

연결 상태와 인증 상태를 하나의 bool로 다루지 않는 게 중요했다.

이벤트가 중복돼도 결과는 한 번이어야 했다

서버 알림과 다음 API의 인증 실패가 거의 동시에 도착할 수 있었다. 둘 다 세션 종료 화면을 열면 팝업이 두 개 생겼다. 세션 상태 전이를 멱등하게 만들어 이미 만료 처리됐다면 같은 결과를 다시 실행하지 않았다.

사용자에게는 내부 오류 코드 대신 다른 곳에서 로그인되어 세션이 종료됐다는 다음 행동을 설명했다. 계정이나 접속 위치 같은 정보는 필요한 범위 이상 표시하지 않았다.

경계를 알면 확인할 증거가 달라졌다

서버가 만료 이벤트를 보냈는지, 클라이언트가 받았는지, 재연결을 중단했는지, 화면이 전환됐는지를 따로 확인했다. 한 단계의 성공으로 전체가 정상이라고 결론 내리지 않았다.

중복 로그인 문제를 통해 서버 문제와 화면 문제 사이에 세션 상태라는 경계가 있다는 걸 배웠다. 이후 인증 오류를 보면 팝업 문구만 고치지 않고 누가 상태를 결정하고 다음 요청을 누가 막는지까지 따라가게 됐다.