
크롬에서 멀쩡하던 레이아웃이 사파리에서 완전히 무너진 경험, 혹시 있으신가요? 저도 블로그를 몇 달째 크롬으로만 테스트하다가 아이폰을 쓰는 친구한테 "네 블로그 레이아웃 다 깨졌어"라는 말을 들었습니다. 그때 처음으로 브라우저 호환성이 이론이 아닌 현실 문제라는 걸 제대로 실감했습니다. 이미 몇 달 동안 방문자들이 깨진 화면을 보고 있었을 거라는 생각에 식은땀이 났습니다.
렌더링 엔진이 다르면 CSS가 다르게 보인다
브라우저 호환성 문제가 왜 생기는지 한 번이라도 궁금하셨던 분이라면, 렌더링 엔진 차이부터 이해하면 훨씬 빠릅니다. 렌더링 엔진이란 HTML, CSS, JavaScript 코드를 읽어 실제 화면으로 그려내는 핵심 소프트웨어를 말합니다. 크롬과 엣지는 Blink 엔진을, 사파리는 WebKit 엔진을, 파이어폭스는 Gecko 엔진을 씁니다. 같은 CSS 코드를 각 엔진이 조금씩 다르게 해석하기 때문에, 한 브라우저에서 완벽하게 보여도 다른 브라우저에서는 전혀 다른 결과가 나올 수 있습니다.
특히 사파리가 문제가 되는 이유는 국내 아이폰 사용자 전원이 사파리를 기본 브라우저로 쓴다는 점입니다. 안드로이드와 달리 iOS에서는 다른 브라우저 앱을 써도 내부 렌더링은 WebKit 기반으로 동작합니다. 즉, iOS 환경에서는 사파리 호환성 문제를 피할 방법이 사실상 없습니다. 크롬을 쓰더라도 iOS에 깔린 크롬은 결국 WebKit으로 렌더링됩니다. 이 사실을 모르고 "iPhone에서 크롬으로 확인했는데 괜찮아요"라고 말하는 경우가 종종 있는데, 그게 왜 의미 없는지를 이해하면 테스트 방식 자체가 달라집니다.
직접 겪은 사례가 딱 두 가지였습니다. 하나는 flex gap이었고, 다른 하나는 position: sticky였습니다. flex gap이란 Flexbox 레이아웃에서 자식 요소 사이의 간격을 한 줄로 지정하는 CSS 속성입니다. 구버전 사파리는 이 속성을 지원하지 않아서, 요소들이 간격 없이 다닥다닥 붙어버렸습니다. margin으로 대체하고 나서야 해결됐는데, 이걸 모르고 몇 주를 그냥 배포했던 게 지금도 아찔합니다. position: sticky도 비슷한 케이스입니다. 이 속성은 스크롤 위치에 따라 요소가 뷰포트에 고정되는 방식인데, 사파리에서는 반드시 -webkit-sticky를 함께 병기해야 작동합니다. 벤더 프리픽스(-webkit-)란 각 브라우저 엔진이 실험적으로 먼저 지원하던 시절에 붙이던 제조사 식별 접두어를 말합니다. 최신 CSS 속성은 대부분 프리픽스 없이도 작동하지만, position: sticky나 background-clip: text 같은 일부 속성은 지금도 -webkit- 없이는 사파리에서 제대로 작동하지 않을 수 있습니다.
날짜 파싱 문제도 있습니다. JavaScript에서 "2024-01-01" 형식의 날짜 문자열을 Date 객체로 변환하면 크롬에서는 문제없이 작동하지만 사파리에서는 Invalid Date, 즉 날짜 인식 실패가 발생합니다. "2024/01/01" 형식으로 바꾸는 것만으로 해결되는데, 이걸 모르면 날짜 관련 기능이 사파리에서만 조용히 망가집니다. 에러 메시지조차 안 뜨고 그냥 빈 값이 출력되는 방식이라 한참을 헤맸습니다. 조용히 망가지는 버그가 가장 찾기 어렵습니다.
사파리에서 자주 깨지는 패턴은 다음과 같습니다. flex gap은 구버전에서 미지원으로 margin으로 대체해야 하고, position: sticky는 -webkit-sticky 병기가 필요합니다. "2024-01-01" 형식의 날짜 파싱은 Invalid Date가 발생하므로 슬래시 형식으로 변경해야 하고, background-clip: text는 -webkit-background-clip: text 병행이 필요합니다.
크로스브라우저 테스트 도구, 실제로 어떻게 쓰는가
이론은 알겠는데, 그래서 실제로 어떻게 테스트하면 되냐는 질문이 자연스럽게 따라옵니다. 크로스브라우저 테스트란 하나의 웹페이지가 여러 브라우저와 기기에서 동일하게 보이는지 확인하는 작업을 말합니다.
Can I Use(caniuse.com)는 CSS나 HTML5 속성이 각 브라우저에서 지원되는지 한눈에 확인하는 사이트입니다. CSS 속성을 새로 쓸 때 반드시 이 사이트를 먼저 확인하는 습관이 생겼습니다. flex gap이 사파리 구버전에서 빨간색으로 표시되는 걸 직접 보고 나서부터입니다. 검색 한 번이 몇 시간의 디버깅을 막아줍니다.
Chrome DevTools Device Mode는 크롬 개발자 도구 안에서 스마트폰 화면 크기를 에뮬레이션할 수 있는 기능입니다. 어느 정도의 반응형 레이아웃 확인은 가능하지만, 실제 iOS 사파리와 완전히 동일하진 않습니다. 이 도구에서 괜찮아 보여도 실제 아이폰에서 깨지는 경우가 있었습니다. 에뮬레이션은 참고용이고, 실제 기기 테스트를 대체하지는 못합니다.
Firefox Developer Edition은 파이어폭스 전용 개발자 도구가 탑재된 버전입니다. BrowserStack은 실제 기기와 브라우저 환경을 원격으로 테스트할 수 있는 서비스로, 유료지만 무료 체험이 가능하고 실제 iOS 사파리 환경을 직접 확인할 수 있다는 점에서 가장 정확한 도구입니다. 아이폰이 없어도 iOS 사파리 테스트가 가능하다는 게 가장 큰 장점입니다.
Normalize.css란 각 브라우저가 기본으로 적용하는 스타일을 표준에 맞게 통일시켜주는 CSS 파일입니다. 완전 초기화를 목표로 하는 CSS Reset과 달리, Normalize.css는 브라우저 기본 스타일을 무력화하는 대신 일관된 기준으로 정렬하는 방식입니다. 블로그에서 CSS Reset을 쓰면 티스토리나 워드프레스 스킨이 제공하는 기본 스타일까지 다 날아갈 수 있어서, Normalize.css가 훨씬 안전한 선택입니다.
일반적으로 Autoprefixer를 소개하면서 PostCSS 설정까지 해야 한다고 하는 경우가 많은데, 티스토리나 워드프레스처럼 직접 CSS를 수정하는 환경에서는 빌드 도구 기반 설명이 현실적으로 맞지 않습니다. 벤더 프리픽스는 대부분의 경우 직접 코드에 한 줄 추가하는 것으로 충분하고, 빌드 환경 없이 운영하는 블로그라면 Can I Use에서 확인 후 필요한 프리픽스만 수동으로 넣는 방식이 오히려 더 명확합니다. 도구가 복잡할수록 시작을 미루게 됩니다.
브라우저 호환성 문제는 한 번에 다 해결하기보다 배포 전 체크리스트를 만들어두고 습관적으로 돌리는 게 결국 가장 확실한 방법입니다. 크롬, 사파리, 엣지, 파이어폭스를 직접 확인하고, iOS 사파리와 안드로이드 크롬에서의 모바일 화면도 반드시 보는 것, Can I Use에서 새 CSS 속성을 쓸 때마다 지원 현황을 먼저 확인하는 것. 이 세 가지만 지켜도 대부분의 크로스브라우저 문제는 사전에 잡을 수 있습니다.
참고