내역 항목을 누르면 작은 차트가 열렸다. 두 번째부터는 잘 열리는데 앱을 실행한 뒤 처음 누를 때만 로딩에서 멈추는 경우가 있었다. 한 번 닫았다 다시 열면 정상이라 데이터 자체가 틀린 것 같지는 않았다.
처음에는 첫 요청이 느린 문제로 생각했다. 요청 로그에는 정상 응답이 남아 있었다. 응답은 왔지만 차트를 그릴 컴포넌트가 아직 초기화되지 않은 시점에 데이터가 적용되고 있었다.
준비 완료가 하나가 아니었다
차트를 보여 주려면 적어도 세 가지가 준비돼야 했다.
- 패널과 그래프 컴포넌트 생성
- 선택 항목 정보 확정
- 차트 데이터 응답 완료
각각 비동기로 움직이는데 마지막으로 끝난 작업이 누구인지에 따라 그리기 함수가 호출되지 않았다.
void TryRender()
{
if (!viewReady || !selectionReady || chartData == null)
return;
RenderChart(chartData);
HideLoading();
}
각 준비 단계가 끝날 때 TryRender()를 부르면 완료 순서와 관계없이 모든 조건이 갖춰진 순간 한 번 그릴 수 있었다.
로딩을 끄는 책임이 흩어져 있었다
성공 콜백에서는 로딩을 끄지만, 빈 데이터나 화면이 먼저 닫힌 경우에는 그대로 남았다. 로딩 표시를 켠 코드와 끄는 코드가 멀리 떨어져 있어 빠진 경로를 찾기 어려웠다.
그래서 Loading, Ready, Empty, Failed 상태에 따라 한 함수가 표시를 결정하도록 모았다. 무조건 HideLoading()을 추가하는 것보다 어떤 상태로 끝났는지를 명확히 하는 편이 이후 오류도 줄였다.
첫 실행만 다른 이유를 찾았다
두 번째부터 잘 되는 건 이미 생성된 리소스와 캐시 덕분이었다. 첫 실행은 폰트, 프리팹과 데이터 준비가 모두 겹쳤다. 두 번째 성공을 정상 증거로 보면 초기화 문제를 놓치기 쉬웠다.
테스트할 때 캐시와 화면 인스턴스를 완전히 초기화하고 첫 진입을 반복했다. 네트워크 지연도 넣어 준비 순서를 바꿔 봤다. 순서가 바뀌어도 결과가 같아야 초기화 흐름이 안정적이라고 볼 수 있었다.
로딩 화면은 상태를 드러내는 장치였다
예전에는 로딩 이미지를 요청 전후에 켜고 끄는 장식으로 생각했다. 이번 문제를 겪으며 로딩도 화면 상태의 결과라는 걸 알았다. 무엇을 기다리는지 정의하지 않으면 영원히 돌거나 너무 일찍 사라진다.
미니차트가 처음에만 멈춘 문제를 고치며 초기화 순서, 여러 준비 조건과 로딩 책임을 같이 보게 됐다. 이후 “두 번째에는 돼요”라는 증상이 나오면 캐시보다 먼저 첫 생명주기의 순서를 의심한다.