프리티월드(freetyworld)
시각장애인·저시력·어르신을 위한 날씨 앱을 만들고 있습니다. 장애인자립생활센터에서 일했던 경험이 계기였습니다.
설계에서 제일 크게 바꾼 건 숫자를 지운 것입니다.
보통 날씨 앱은 "23°C, 습도 60%, 강수확률 30%"를 보여줍니다. 눈으로 훑으면 빠르지만, 스크린리더로 들으면 숫자의 나열입니다. 듣는 사람은 그걸 조합해서 "그래서 뭘 입지"를 스스로 계산해야 합니다.
그래서 문장으로 바꿨습니다. "어제보다 조금 쌀쌀해요. 얇은 겉옷 하나면 좋아요." 정보량은 줄었지만 한 번 듣고 판단할 수 있습니다.
레이아웃도 보는 순서가 아니라 낭독 순서를 기준으로 짰습니다. 화면은 한 장, 스크롤 없이. 스크린리더가 위에서 아래로 훑을 때 중요한 것이 먼저 나오도록 DOM 순서를 잡고, 시각적 배치를 거기 맞췄습니다. 보통은 반대로 하죠.
폰트는 한국장애인개발원의 KoddiUD 온고딕을 씁니다. 저시력 사용자를 위해 설계된 서체이고 공공누리로 열려 있습니다. CDN을 쓰지 않고 로컬에 번들했습니다.
이렇게 공들여놓고, 정작 고대비 코드는 죽어 있었습니다.
새 버튼을 하나 넣고 실기기 검증을 돌리다가 시스템 설정에서 고대비 텍스트를 켰습니다. 화면이 안 바뀌더군요.
matchMedia('(prefers-contrast: more)').matches
// false
설정은 분명히 켜져 있었습니다(high_text_contrast_enabled=1). 그런데 매칭이 안 됩니다.
이 앱에는 @media (prefers-contrast: more) 블록이 두 버전 전부터 들어 있었습니다. 테두리를 진하게, 대비를 높이는 코드였습니다. 한 번도 실행된 적이 없었습니다.
"WebView가 미디어쿼리를 무시하는 것 아닌가"를 먼저 의심했는데 아니었습니다. 같은 기기·같은 WebView에서 prefers-reduced-motion: reduce는 정상 매칭됩니다. 미디어쿼리 자체가 죽은 게 아니라 prefers-contrast만 안 옵니다.
검증 환경: Galaxy S21+ / Android 15(SDK 35) / WebView 151.0.7922.199.
추정은 이렇습니다. Android의 "고대비 텍스트"는 OS의 전역 대비 설정이 아니라 접근성 서비스가 텍스트 렌더링 단계에 개입하는 기능입니다. 브라우저에 사용자 선호로 전달되는 신호가 아닙니다. 데스크톱 OS의 대비 설정과 이름만 비슷하고 계층이 다릅니다. 확인된 건 아니라 추정으로 남겨둡니다.
얻은 교훈은 미디어쿼리 얘기가 아닙니다.
이 블록은 문법이 맞았고, 빌드도 성공했고, 리뷰도 통과했습니다. 자동화 테스트도 못 잡습니다 — 테스트 하네스는 CSS 미디어쿼리를 평가하지 않으니까요. 실기기에서 설정을 켜보기 전까지 아무도 죽은 줄 몰랐습니다.
접근성 코드는 "짰다"가 아니라 "켜고 봤다"여야 합니다. 지금은 그 기준으로 나머지도 다시 훑고 있습니다.
대체 감지 수단은 아직 못 찾았습니다. 아시는 분 계시면 알려주세요.
앱: Play 스토어
소개: ryumarl.com/moduweather/
모두날씨(Moduweather)
숫자 대신 문장으로 날씨를 알려주는 배리어프리 날씨 앱입니다. 스크린리더 낭독 순서를 기준으로 화면을 설계했고, 시스템 글자 크기를 최대로 키워도 레이아웃이 무너지지 않습니다.