1
0
forked from baron/baron-sso
Files
baron-sso/docs/trouble-shooting/issue-277-null-check-dashboard-routing.md

4.1 KiB

Issue #277/#302 트러블슈팅 기록: 로그인 후 공백 화면 + 새로고침 시 signin 회귀

기준 시점

  • 2026-02-23 KST
  • 재현 환경: https://sss.hmac.kr (WASM 배포)

증상

  • 로그인 직후 URL은 /{locale} 또는 /{locale}/dashboard로 보이지만 화면이 렌더링되지 않음
  • 이후 새로고침하면 /{locale}/signin으로 되돌아감
  • 콘솔/백엔드 수집 로그:
    • Null check operator used on a null value
    • wasm-function[765] 포함 스택 반복

스택 매핑 결과 (source-map + no-strip-wasm)

  • 매핑 커맨드:
    • python3 scripts/map_wasm_stack.py --wasm userfront/build/web/main.dart.wasm --sourcemap userfront/build/web/main.dart.wasm.map --frame ...
  • 핵심 프레임:
    • wasm-function[765] -> _TypeError._throwNullCheckErrorWithCurrentStack
    • 상위 프레임 -> Flutter NavigatorState.didUpdateWidget/_updatePages 경로
  • 결론:
    • 단일 위젯 null 접근보다, 라우트 갱신 타이밍/중복 네비게이션 경쟁에서 Navigator 내부에서 터지는 양상

지금까지 시행착오와 실패 내역

  1. LocaleGate, LanguageSelectorEasyLocalization.of(context) null 방어만 적용
  • 결과: 동일 예외 재발
  • 이유: 루트 원인은 로케일 위젯 단일 null 접근이 아니라 네비게이션 경쟁 구간
  1. /ko 루트에서 signin 강제 리다이렉트만 강화
  • 결과: 최초 진입은 일부 개선됐지만 로그인 직후/새로고침 회귀 지속
  • 이유: 로그인 성공 경로가 루트(/{locale})와 엮이면서 라우트 재평가가 중첩
  1. 로그인 화면에서 AuthNotifier.notify() + context.go(...) 동시 수행
  • 결과: 간헐적 경쟁 상태 유발 가능성 확인
  • 조치: 로컬 네비게이션 1회 가드 도입(_goLocalizedHomeOnce)
  1. cookie 세션 승격이 토큰 저장 이후 덮어쓰는 경합
  • 결과: 일부 흐름에서 저장 상태 불안정 가능성
  • 조치: cookie_session_policy 추가, 토큰 존재 시 불필요한 cookie 승격 차단
  1. /:locale 엔트리가 redirect 없이 매칭되는 구조
  • 결과: /ko 직접 진입 시 페이지 스택 재계산 과정에서 NavigatorState.didUpdateWidget/_updatePages 경로 null check 재발
  • 이유: /ko는 실질 화면이 아닌 분기 지점인데, 명시적 redirect 경로가 없으면 라우트 갱신 타이밍 경쟁에 취약
  • 조치: /:locale를 redirect 전용 엔트리로 확정(비로그인 /{locale}/signin, 로그인 /{locale}/dashboard)

최종 반영 방향 (이번 패치)

  1. 로그인 성공 기본 경로를 명시적으로 /{locale}/dashboard로 고정
  • buildLocalizedHomePath() 반환값을 /{locale}/dashboard로 변경
  • /:locale 엔트리는 /:locale/dashboard로 redirect 전용 처리
  1. 라우터/화면 역할 분리
  • 보호 경로 검사는 router redirect에서 수행
  • 대시보드는 필요 시 cookie 세션 복구를 1회 시도 후 signin 이동
  1. 중복 네비게이션 억제
  • 로그인 성공 시 내부 이동은 1회만 수행

검증

  • 추가 테스트:
    • userfront/test/login_navigation_race_test.dart
    • userfront/test/cookie_session_policy_test.dart
    • userfront/test/router_redirect_widget_test.dart (/{locale} 직접 진입 시 signin/dashboard 분기 검증)
  • 갱신 테스트:
    • userfront/test/locale_utils_test.dart (home path /{locale}/dashboard 기준)
  • 실행:
    • flutter test
    • flutter test --platform chrome test/router_redirect_widget_test.dart test/login_navigation_race_test.dart test/cookie_session_policy_test.dart

남은 리스크

  • 실제 브라우저 저장소 정책(localStorage 차단/쿠키 정책)에 따라 세션 판정이 달라질 수 있음
  • 운영 검증 시 네트워크/스토리지 상태를 함께 수집해야 원인 분리 가능

운영 확인 체크리스트

  1. 비로그인으로 /{locale} 접속 시 즉시 /{locale}/signin 이동
  2. 로그인 성공 시 /{locale}/dashboard 진입
  3. /{locale}/dashboard에서 새로고침 후 세션 유지 (동일 브라우저)
  4. 실패 시 RECOVERY_NAV_NULL_CHECK와 wasm frame 동시 수집