검색창에 글자를 입력하면 결과 목록이 바뀝니다. 간단해 보이지만 입력 사건, 네트워크 요청, 데이터 상태, 화면 배치가 서로 다른 시점에 진행됩니다. 웹과 모바일 UI는 플랫폼 API가 달라도 이 관계를 명확히 해야 한다는 공통점이 있습니다.
데이터 상태와 화면 표현
검색어 ab를 입력한 직후의 화면은 query=ab, phase=loading, items=[]일 수 있고, 성공 뒤에는 phase=ready, 실패 뒤에는 phase=error가 됩니다. 이처럼 데이터와 진행 상태를 함께 모델링하면 빈 결과와 아직 결과가 없는 상태를 같은 화면으로 잘못 표현하는 문제를 피할 수 있습니다.
서버에서 받은 목록과 화면에 그린 목록은 같은 것이 아닙니다. 클라이언트는 로딩 중인지, 결과가 비었는지, 오류인지 같은 상태를 함께 관리합니다. ‘빈 배열’ 하나로 로딩 중과 결과 없음과 실패를 모두 표현하면 사용자는 무슨 일이 일어났는지 알 수 없습니다.
화면은 현재 상태의 표현입니다. 상태를 바꾼 뒤 어떤 UI 요소를 갱신할지는 DOM 조작, 선언형 렌더링, 네이티브 뷰 갱신 등 플랫폼과 프레임워크에 따라 다릅니다. 프레임워크가 있어도 상태의 의미와 실패 정책을 대신 정해 주지는 않습니다.
배치와 그리기
레이아웃 문제를 진단할 때는 먼저 논리 트리의 크기 계산, 그 결과로 정해진 위치, 실제 픽셀에 그려진 결과를 분리해 캡처합니다. 이미지의 intrinsic size를 모르는 동안 placeholder 높이를 확보하지 않으면 데이터는 맞아도 배치가 바뀌며, 이는 렌더링 오류와 비동기 데이터 오류가 서로 다른 문제임을 보여 줍니다.
웹에서는 HTML의 구조와 CSS의 스타일로 요소의 크기·위치를 계산하고, 그릴 내용을 만든 뒤 화면에 표시합니다. 네이티브 UI도 뷰 계층과 제약·좌표를 사용해 배치를 결정합니다. 논리적인 너비 값과 실제 화면의 픽셀, 부모 기준 위치와 자기 내부 좌표는 구별해야 합니다.
이미지가 늦게 도착했을 때 높이가 0에서 300으로 바뀌면 아래 콘텐츠가 밀릴 수 있습니다. 미리 비율이나 크기로 자리를 확보하면 이런 이동을 줄일 수 있습니다. 화면이 빨리 나타나는 것과 이후에도 안정적으로 배치되는 것은 다른 품질입니다.
그림을 글로 읽기
- 입력 이벤트 · 검색어
- 요청 · 검색어·요청 번호
- 현재 결과·로딩·오류 상태
- 화면 배치·표시
- 입력 이벤트 · 검색어 → 요청 · 검색어·요청 번호: 조회 시작
- 요청 · 검색어·요청 번호 → 현재 결과·로딩·오류 상태: 현재 요청 결과만 적용
- 현재 결과·로딩·오류 상태 → 화면 배치·표시: 상태 표현
이벤트와 비동기 결과
재현 입력을 a 시작 → ab 시작 → ab 응답 → a 응답으로 고정하면 마지막 도착 응답을 적용하는 코드의 오류가 드러납니다. 요청 번호 2만 현재 번호로 인정하거나, 화면의 현재 query와 응답 query가 같을 때만 상태를 갱신하면 예측 결과는 ab 목록 유지입니다. 취소는 네트워크 작업 중단의 힌트이고 적용 권한 철회와는 별도입니다.
사용자가 a를 검색한 뒤 곧바로 ab를 검색했다고 해 보겠습니다. ab 응답이 먼저 도착하고 a 응답이 나중에 오면, 단순히 마지막 응답을 표시하는 코드는 옛 결과로 돌아갑니다. 현재 요청 번호나 검색어와 응답의 문맥을 대조해야 합니다.
취소는 불필요한 작업을 줄이는 데 도움이 되지만 이미 큐에 들어온 콜백까지 모두 사라진다고 가정할 수 없습니다. 화면이 닫힌 뒤 결과가 도착할 수도 있습니다. 작업 취소와 현재 화면에 결과를 적용할 조건을 함께 관리해야 합니다.
화면 수명과 자원 수명
자동완성은 화면이 닫히면 취소할 수 있지만, 여러 화면이 함께 보는 다운로드는 화면 하나의 종료와 무관하게 서비스가 소유할 수 있습니다. 따라서 리스너·타이머·구독·작업마다 owner와 해제 시점을 표로 정하면 메모리 누수와 너무 이른 취소를 동시에 진단할 수 있습니다.
화면이 사라졌다는 것과 화면 객체가 메모리에서 해제됐다는 것은 다릅니다. 화면을 나중에 다시 보여 주려고 보관하거나, 등록한 콜백이 화면을 계속 참조할 수 있습니다. 이벤트 리스너, 알림 구독, 타이머와 네트워크 작업의 소유자를 정해야 하는 이유입니다.
여러 화면이 공유하는 다운로드라면 화면 하나가 닫혀도 서비스가 계속 소유할 수 있습니다. 반면 그 화면만을 위한 검색 자동완성은 더 필요 없을 수 있습니다. 모든 비동기 작업을 화면 수명에 붙이거나 모두 독립 실행으로 분리하는 대신 목적에 맞춰 선택합니다.
사용자 입력과 접근성
실습에서는 키보드로 검색 입력, 결과 선택, 오류 수정까지 수행하고 포커스가 어디에 있는지 확인합니다. 시각적으로 같은 div라도 이름·role·상태·키보드 동작이 없으면 보조 기술과 비포인터 사용자는 다른 인터페이스를 받으므로, 접근성은 색상 보정이 아니라 입력 계약의 일부입니다.
버튼처럼 그린 div에는 네이티브 버튼의 키보드 동작과 포커스 의미가 자동으로 생기지 않습니다. 색과 위치뿐 아니라 요소의 이름·역할·상태를 제공해야 마우스 없이도 사용할 수 있습니다. 오류도 빨간 테두리만으로 전달하지 않고 어떤 입력을 고쳐야 하는지 설명해야 합니다.
웹과 iOS의 이벤트 전파·뷰 수명·접근성 API는 서로 다릅니다. 공통 원리는 이해하되 구체적인 호출 순서와 지원 조건은 플랫폼 문서로 내려가 확인합니다.
세부 학습 경로
웹은 브라우저 탐색, 레이아웃, 이벤트 위임으로 이어집니다. iOS는 화면 수명, 좌표계, ARC에서 실제 플랫폼 규칙을 살펴볼 수 있습니다.