고래를 찾는데 고양이가 나타났다 · 고래 1만 마리와 키보드 한 개 · 이론
초록불이 켜졌는데 화면은 왜 불편할까
한 줄 요약
타입 검사, React DOM 동작 검사, 실제 브라우저 검사는 서로 다른 질문에 답한다. 검사 결과를 말할 때는 무엇을 관찰했는지까지 함께 설명한다.
왜 이게 필요했나
고래 검색이 끝까지 유지되고 모든 상태 검사가 통과했다. 그런데 휴대전화에서는 검색 단추가 화면 밖에 있고, 키보드로 입력 중 응답이 오면 초점이 결과 영역으로 이동한다. 구현자는 테스트가 초록불이라고 말하고 사용자는 여전히 쓸 수 없다고 말한다. 둘 중 하나가 거짓말하는 것이 아니라 서로 다른 대상을 보고 있는 경우다.
이번 과정은 검사의 범위를 분리한다. 학생 소스는 타입 검사 뒤 실제 React로 DOM 환경에 렌더링하여 요청 전후 상태를 읽는다. DOM 환경은 브라우저의 일부 API를 구현하지만 글자 배치나 실제 페인트 비용을 재현하는 레이아웃 엔진은 아니다. 화면 너비나 성능을 그 결과만으로 판정하면 근거 없는 확신이 된다.
어떻게 동작하나
검사할 동작을 작은 사건으로 나누자. 컴포넌트를 렌더링하고, 검색을 제출하고, 지정한 응답을 완료시키고, React 업데이트가 반영된 뒤 DOM을 읽는다. React의 비동기 act는 그 경계를 다룰 때 쓰는 도구다. 임의로 3초를 자는 방식은 빠른 컴퓨터에서 시간만 낭비하고 느린 환경에서는 여전히 먼저 읽을 수 있다.
| 검사 층 | 확인할 예 | 이것만으로 알 수 없는 것 |
| --- | --- | --- |
| TypeScript | 상태별 필수 데이터와 타입 | 실제 응답 도착 순서 |
| React+DOM | 역순 응답 뒤 결과, effect 정리 | 픽셀 배치와 페인트 비용 |
| 실제 브라우저 | 키보드 경로, 좁은 화면, 렌더 기록 | 모든 보조기술의 사용성 |
| 사용자 관찰 | 지시문을 이해하고 과제를 마치는지 | 다른 모든 사용자의 경험 |
접근성에서는 입력의 이름, 실제 form 제출, 결과 변경 안내, 초점 유지가 연결된다. 새 결과를 알리는 것과 결과로 초점을 강제로 옮기는 것은 다르다. 사용자가 검색어를 계속 고치는 중이라면 현재 입력 위치를 보존하면서 변경을 전달해야 한다. 자동 검사 통과를 스크린리더 사용성 인증으로 표현하지 않는다.
성능도 시간을 나눠 본다. 요청을 보내고 응답을 받기까지의 대기와, 결과를 React로 계산하고 화면에 그리는 비용은 다르다. 네트워크 대기만 긴데 memo를 붙여도 응답은 빨리 오지 않는다. 이미 결과가 도착했는데 1만 행을 한꺼번에 표시하는 비용이 크다면 네트워크 재시도로 해결되지 않는다.
React Profiler의 렌더 시간과 브라우저의 레이아웃·페인트·네트워크 기록을 같은 숫자로 취급하지 말자. 측정 전에 데이터 수, 개발/운영 빌드, 기기, 반복 횟수를 기록한다. 한 번의 좋은 숫자보다 같은 조건의 여러 관찰이 유용하다. 이 단계에서는 목표 숫자를 맞추기 위해 관찰값을 지어내지 않는다.
관찰 기록을 남기는 방법
좋은 기록은 결과 숫자만 적은 표보다 재현 조건을 먼저 알려 준다. 다음 양식에 실제로 한 일만 채워 보자. 아직 실행하지 않은 항목은 빈칸을 그럴듯한 값으로 채우지 말고 미확인으로 남긴다.
| 항목 | 기록할 내용 |
| --- | --- |
| 대상 | 소스 버전, 수정한 함수, 빌드 종류 |
| 환경 | 브라우저 버전, 화면 너비, 기기 조건 |
| 입력 | 데이터 개수, 검색어, 제출·응답 순서 |
| 기대 | 마지막에 남아야 할 결과와 초점 위치 |
| 관찰 | 실제 결과, 오류, 렌더 또는 네트워크 기록 |
| 남은 범위 | 다른 화면·보조기술·실제 서비스 연결 |
예를 들어 고래 다음 고양이를 배달했다는 기록만으로는 충분하지 않다. 요청은 어떤 순서로 보냈는지, 취소를 무시하는 모드였는지, 최신 결과를 확인한 뒤 과거 응답을 배달했는지가 있어야 한다. 이런 조건이 빠지면 동료는 같은 코드를 받아도 문제를 재현하지 못한다.
성능 개선 전후에도 한 번에 한 조건만 바꾸는 편이 해석하기 쉽다. 표시 행 수와 네트워크 지연과 빌드 종류를 동시에 바꾸면 어느 변경이 효과를 냈는지 알기 어렵다. 표시 개수를 줄였다면 총 결과 수와 현재 표시 수를 사용자에게 알려 자료를 잃었다고 오해하지 않게 해야 한다. 빠르게 보이기 위해 결과를 조용히 버리는 것은 성능 개선과 다른 제품 변경이다.
현장에서 만나는 모습
고객에게 장애 수정 결과를 설명할 때도 같은 원칙이 적용된다. “테스트 통과” 대신 “역순 성공·실패와 해제 취소는 재현해 확인했고, 모바일 실제 세션은 아직 확인하지 않았다”고 말하면 다음 검토 대상이 분명해진다. 확인하지 않은 범위를 드러내는 것이 검사의 신뢰를 높인다.
채점 도구도 검증 대상이다. 정답 외에 무조건 success를 반환하는 코드, 중간에 exit하는 코드, 끝나지 않는 코드를 넣어 본다. 종료 코드 0이나 stdout의 PASS 문구만 믿으면 학생 코드가 검사를 우연히 건너뛰어도 통과할 수 있다. 채점 결과가 끝까지 수집되었는지와 학생 원본이 바뀌지 않았는지도 확인한다.
직접 확인할 것
DOM 검사와 실제 브라우저 관찰을 별도로 기록한다. 어떤 검사가 어떤 결함을 잡았는지 표로 정리하고, 아직 관찰하지 않은 범위를 남긴다. 긴 목록의 실측은 실제 브라우저에서 하고, DOM 모형에서 얻은 시간을 대신 제출하지 않는다.
도구의 범위는 [React act](https://react.dev/reference/react/act), [React Profiler](https://react.dev/reference/react/Profiler), [jsdom 안내](https://github.com/jsdom/jsdom)를 참고한다.