사용자 프로필 화면은 이름과 몇 가지 상태를 보여주는 단순한 화면처럼 보였다. 실제로는 기본 정보, 인증 상태, 설정, 이미지가 서로 다른 API와 캐시에서 왔다. 화면 하나가 열릴 때 여러 요청이 동시에 시작됐고 일부만 실패하면 로딩이 끝나지 않았다.
모든 데이터를 하나의 큰 응답처럼 기다리기보다 화면이 어떤 정보를 필수로 보고 어떤 정보는 나중에 채워도 되는지 나눴다.
화면 모델을 별도로 만들었다
각 API 응답을 UI 컴포넌트가 직접 읽으면 필드 이름과 실패 조건이 화면 전체에 퍼졌다. 프로필 화면에 필요한 의미만 모은 모델을 만들었다.
public record ProfileViewModel(
string DisplayName,
VerificationView Verification,
string Language,
ImageState Avatar);
누락된 선택 정보는 기본 표시로 바꿨지만, 사용자 자체를 식별하지 못한 경우는 프로필 화면을 열 수 없는 오류로 처리했다.
요청별 상태를 합쳤다
기본 정보는 성공하고 이미지가 실패했을 때 전체 화면을 오류로 바꾸지 않았다. 각 데이터의 로딩 상태를 보관하고 필수 데이터가 준비되면 화면을 먼저 열었다.
기본 정보 실패 -> 전체 재시도 화면
설정 실패 -> 로컬 기본값, 재동기화 표시
이미지 실패 -> 기본 아바타, 별도 재시도
사용자가 기다리는 시간을 줄이면서 실패 범위도 작게 만들 수 있었다.
캐시에는 소유자와 버전을 넣었다
프로필 이미지를 파일로 저장할 때 계정이 바뀌면 이전 이미지가 잠깐 보이지 않도록 사용자별 키를 사용했다. 서버가 새 이미지 버전을 알려주면 캐시를 무효화하고, 다운로드가 완료된 뒤 파일을 교체했다.
로그에는 이름이나 이미지 URL 대신 캐시 적중 여부와 버전만 남겼다. 화면 표시 데이터와 디버깅 데이터의 경계를 의식했다.
프로필을 편집한 직후에는 서버 저장 성공, 화면 모델 갱신, 캐시 무효화가 모두 이어지는지 확인했다. 성공 알림만 떴는데 뒤로 갔다 돌아오면 이전 값이 보이는 경로를 따로 시험했다.
화면 하나도 작은 통합 지점이었다
프로필 작업 전에는 화면 파일만 수정하면 될 거라 생각했다. 실제로는 여러 데이터 공급자의 속도와 실패를 조율하는 통합 지점이었다. 무엇을 기다리고 무엇을 대체할지를 정하는 일이 UI 코드보다 중요했다.
이후 복합 화면을 만들 때 API 목록부터 붙이지 않는다. 사용자에게 꼭 필요한 정보와 독립적으로 실패할 수 있는 영역을 먼저 나눈다. 데이터 경로를 화면 요구에 맞춰 정리하면 코드와 사용자 경험이 함께 단순해졌다.