CareMatch에는 사용자가 화면의 글자 크기를 키울 수 있는 접근성 토글 기능이 있습니다. 요양보호사·구직자 등 시니어 사용자 비중이 높은 서비스 특성상, 처음부터 넣어둔 기능입니다.
그런데 오늘 이 토글을 켜고 화면을 살펴보다가 두 가지 문제를 발견했습니다.
96px, 104px처럼 고정 px 값으로 박혀 있었습니다. 글자 크기가 커져도 컬럼 폭은 그대로였기 때문에 "급여", "근무 시간대" 같은 텍스트가 줄바꿈되며 테이블 밖으로 삐져나왔습니다.w-[120px] 같은 고정 폭이라 아이콘+텍스트가 버튼 밖으로 튀어나왔고, 메인 화면 "최신 인재정보" 카드의 갱신일 항목은 truncate 처리가 빠져 있어 날짜가 카드 밖으로 넘쳤습니다.원인은 하나로 요약됩니다. 글자 크기 토글은 rem 기반으로 동작하는데, 레이아웃 폭은 px로 고정되어 있었다는 것. 텍스트만 커지고 그릇은 그대로였으니 당연히 넘칠 수밖에 없었습니다. 수정은 단순했습니다 — 96px → 6rem, 120px → 7.5rem처럼 동일한 크기의 rem 값으로 바꿔서 글자 크기와 컨테이너 폭이 함께 비례하도록 했고, 누락된 truncate를 자격증 항목과 동일하게 추가했습니다.
수정 자체는 30분도 안 걸렸습니다. 하지만 이 버그가 알려주는 건 더 근본적인 질문입니다.
"우리 프로젝트에
px로 폭이 고정된 곳이 이 세 군데뿐일까?"
정확히 말하면 아닙니다. 이번에 고친 건 우연히 눈에 띈 곳이었을 뿐, 같은 패턴(고정 px 폭 + rem 기반 폰트 스케일 조합)이 코드베이스 다른 곳에도 얼마든지 숨어 있을 수 있습니다. 즉 이번 커밋 두 개는 "증상 치료"였고, "이 클래스의 버그가 왜 계속 나오는가"라는 원인은 아직 손대지 않은 상태입니다.
프로젝트를 처음 만들 때는 기능을 붙이는 속도가 우선이라 이런 디테일이 뒤로 밀리기 쉽습니다. 하지만 데모/발표가 끝나고 "완성"이라는 딱지가 붙은 뒤에야 비로소 이런 것들을 정리할 여유가 생기는 경우가 많습니다. 그래서 이번 경험을 계기로, 프로젝트 완성 이후에 보완하면 좋을 주제들을 정리해봤습니다.
grep -rn "w-\[.*px\]" 같은 검색으로 프로젝트 전체에서 고정 px 폭을 쓰는 곳을 찾아, 폰트 스케일과 함께 늘어나야 하는 요소(버튼, 테이블 컬럼, 카드 내부 요소)를 전부 rem 단위로 통일하는 작업이 필요합니다. 더 나아가서는 Tailwind 설정에 spacing/width 커스텀 토큰을 rem 기준으로 정의해서, 애초에 px 하드코딩이 불가능하게 만드는 규칙(예: ESLint 커스텀 룰, 코드리뷰 체크리스트)을 두는 것도 고려할 만합니다.
이번 버그는 사람이 눈으로 토글을 켜보다가 발견했습니다. 시각적 회귀 테스트(Playwright + 스크린샷 비교, 또는 Storybook의 접근성 애드온)를 붙여서, 글자 크기를 키운 상태의 주요 화면(홈, 검색 결과, 상세 카드)을 자동으로 스냅샷 비교하면 이런 문제를 배포 전에 잡을 수 있습니다.
truncate 남용 여부 재검토이번엔 갱신일에 truncate를 "추가"해서 고쳤지만, 사실 truncate는 정보를 잘라서 안 보이게 하는 임시방편에 가깝습니다. 글자 크기를 키우는 사용자는 애초에 "더 잘 보고 싶은" 사용자인데, 정작 중요한 정보(날짜, 급여 등)가 말줄임표로 잘려버리면 목적에 어긋납니다. 완성 후에는 truncate 대신 flex-wrap이나 카드 레이아웃 자체를 세로로 풀어주는 방식처럼, 글자가 커져도 정보 손실 없이 자연스럽게 줄바꿈되는 패턴으로 바꾸는 걸 검토할 가치가 있습니다.
글자 크기 확대는 CareMatch에서 부가 기능이 아니라, 실제 사용자층(시니어 구직자)을 위한 핵심 접근성 기능입니다. 그런데 지금까지는 새 컴포넌트를 만들 때 "기본 크기에서 예쁜가"만 확인하고, "글자 크기를 최대로 키워도 안 깨지는가"는 체크리스트에 없었습니다. PR 템플릿이나 코드리뷰 체크리스트에 "폰트 스케일 확대 상태에서 확인했는가" 항목을 넣는 것만으로도 이런 류의 버그 재발을 줄일 수 있습니다.
글자 크기 확대는 시작일 뿐입니다. 명도 대비(다크모드/고대비 모드), 클릭 영역 크기(버튼이 손가락 터치에 충분히 큰가), 스크린리더 대응(aria-label이 실제로 의미 있게 채워져 있는가) 등도 완성 이후 순차적으로 점검할 만한 주제입니다.
기능이 다 완성되고 나면 "이제 끝났다"는 안도감이 들지만, 사실 진짜 사용자가 실제 기기·실제 설정으로 서비스를 켰을 때 드러나는 문제는 그때부터 시작입니다. 오늘의 버그 두 개는 작았지만, "완성"이라는 것이 기능 목록을 다 채우는 것이 아니라 그 기능이 다양한 사용자 조건에서도 일관되게 동작하는 것을 뜻한다는 걸 다시 한번 확인시켜 준 하루였습니다.