Cheondi
개발 · Unity

로그아웃 이후 남은 알림

사용자 전환 뒤 이전 계정의 알림이 나타나는 문제를 구독과 캐시 생명주기로 추적한 기록입니다.

  • #unity
  • #notification
  • #lifecycle

로그아웃하고 다른 계정으로 들어갔는데 이전 계정에서 만든 알림이 다시 나타났다. 서버가 잘못 보낸 줄 알았지만 새 계정의 알림 API 응답에는 해당 항목이 없었다. 앱 안에 남아 있던 예약 작업과 로컬 캐시가 로그인 이후 다시 화면을 만들고 있었다.

로그아웃은 인증 정보만 지우는 작업이 아니었다. 사용자 세션 동안 시작한 일의 생명주기를 끝내야 했다.

알림 생성 경로의 전수 추적

알림은 서버 푸시, 주기 조회, 로컬 예약, 화면 복원 네 경로에서 생길 수 있었다. 어느 경로가 마지막으로 항목을 넣는지 출처를 표시해 확인했다.

public record AlarmItem(
    string LocalId,
    AlarmSource Source,
    string OwnerSession,
    DateTimeOffset TriggerAt);

실제 로그에는 내용 전문이나 사용자 식별값 대신 세션별 임시 ID와 출처만 남겼다.

구독 해제 이후의 알림 정리

로그아웃 때 이벤트 구독을 끊어도 이미 예약된 코루틴과 비동기 작업이 나중에 완료될 수 있었다. 세션 취소 토큰을 전달하고 결과 적용 전에 현재 세션과 같은지 확인했다.

sessionCancellation.Cancel();
alarmPoller.Stop();
localScheduler.ClearForSession(sessionKey);
alarmStore.RemoveUserScopedItems();

다음 로그인에서는 새 토큰과 새 저장소 범위로 시작했다.

유지 알림과 삭제 알림의 구분

앱 업데이트처럼 계정과 무관한 시스템 알림은 로그아웃 뒤에도 유지할 수 있었다. 계좌 상태나 거래 관련 알림은 사용자 범위라 반드시 정리해야 했다. 전부 지우거나 전부 남기지 않고 소유 범위를 데이터에 포함했다.

로그아웃, 세션 만료, 다른 계정 로그인, 앱 강제 종료 후 재실행을 각각 확인했다. 종료 경로가 달라도 사용자별 항목이 넘어가지 않아야 했다.

비동기 작업의 종료 규칙

알림 기능을 만들 때 어떻게 받는지에 집중했지 언제 중단되는지는 뒤늦게 봤다. 오래 실행되는 작업은 화면이 닫히는 것, 로그아웃하는 것, 앱이 종료되는 것을 구분해야 했다.

이 문제 이후 백그라운드 작업과 캐시를 추가할 때 소유 세션과 정리 시점을 함께 정한다. 이전 사용자 흔적이 남지 않는 것은 기능 정확성과 개인정보 보호 모두에 필요한 조건이었다.

추가 구현 기준

작업 당시에는 눈앞의 오류를 먼저 고쳤지만, 이후 기술 문서와 맞춰 보며 확인 순서를 조금 더 구체화했다.

OWASP ASVS와 API Security 기준을 따라 다시 보면 화면에서 숨겼다는 사실은 권한 검사가 아니다. 계좌나 사용자 식별자를 클라이언트가 보내더라도 서버는 인증 주체가 그 객체에 접근할 수 있는지 매 요청에서 확인해야 한다.

클라이언트의 역할은 권한을 결정하는 것이 아니라 잘못된 조작을 줄이고, 거부 응답을 이전 데이터와 섞지 않으며, 민감한 정보를 로그나 저장소에 남기지 않는 데 가깝다.

다음에 로그아웃 이후 남은 알림 같은 문제를 보면 아래 순서부터 확인하려고 한다.

  • 익명·인증 중·인증됨·만료 상태
  • 재시도 가능한 오류와 사용자 입력 필요 오류
  • 토큰 폐기와 화면 초기화 순서
  • 동시에 도착한 만료 응답의 단일 처리

식별자 형식을 어렵게 만들거나 메뉴를 감추는 방법은 서버의 객체 수준 권한 검사를 대체하지 못한다.

공식 참고 자료