모든 브라우저에서 사용 가능한 CSS의 random() 함수 활용하기
요약
본 글은 웹 디자인에 무작위성(randomness)을 도입하여 예측 불가능한 사용자 경험(UX)을 구현하는 아이디어를 다룹니다. 특히, 2025년 말 Safari가 CSS `random()` 사양을 지원하며 이 기능을 선언적 방식으로 제공할 것이라는 내용을 중점적으로 설명합니다.
핵심 포인트
- CSS `random()` 함수는 웹페이지에 제어된 시각적 무작위성을 부여합니다.
- 이 기능은 JavaScript나 외부 프레임워크 의존도를 줄여 순수 CSS로 구현을 가능하게 합니다.
- Safari가 최초 지원 예정이나, Chrome과 Firefox 등 다른 브라우저의 적용 여부는 불확실합니다.
TV 쇼 The Good Place의 제작자가 도덕 철학에 관한 관련 서적을 집필했는데, 이 책에는 “운명의 장난 (The Luck of the Draw)”이라는 챕터가 포함되어 있습니다. 이 챕터는 능력주의 신화가 사람들을 자신의 삶에서 '운이 차지하는 역할을 과소평가하도록' 이끈다고 논합니다. 마치 신이 우주를 주사위 놀음으로 다루는 것처럼, 웹사이트 디자인이 통제된 혼돈을 받아들일 때 예술이 삶을 모방하는 방식에는 무언가 매혹적인 것이 있습니다. 생성형 UI(generative UI)와 같은 비결정론의 극단적인 버전이 예측 불가능한 UX에 도움이 되는 사용법인지에 대해서는 아직 의견이 분분합니다. 실제로, YouTube 댓글에서 Google이 검색에 GenUI를 사용할 예정이라는 것에 반응하는 것을 보면, 어쩌면 이 아이디어를 너무 잘못된 방향으로 끌고 가는 것 같습니다. 하지만 여전히 당신이 웹페이지에 접속할 때마다 미묘하게 변화하는 상태로 존재하는 페이지의 아이디어에는 무언가 매력이 있습니다. 마치 같은 강을 두 번 건널 수 없는 것처럼 말입니다.
무작위성(randomness)의 실제 사용 사례
저는 단기적이고 신규 프로젝트를 자주 수행하는 컨설턴트인데, 이를 통해 시대정신(zeitgeist)과 기업들이 미래라고 생각하는 트렌드를 엿볼 수 있습니다. 최근 저의 한 프로젝트에서 무작위성이라는 아이디어가 스며들었던 것은 우연이 아닙니다. 이는 사용자가 설정한 무작위 추첨을 실행할 때 흥분감을 주기 위해 색종이 조각(confetti)이 터지는 것으로 대표됩니다. 그리고 기업 세계의 많은 UI 기능처럼, 이 단순한 색종이 조각 아이디어조차도 클라이언트의 브랜드에 맞춰 모든 무작위 입자가 일치하도록 여러 차례 수정되었습니다.
실제로 요구사항이 너무 맞춤화되다 보니, 저희가 사용하던 JavaScript 플러그인을 버리고 자체적인 색종이 조각 구현을 하게 되었습니다! 이는 심지어 무작위 색종이 조각과 같은 재미있는 기능에서도 UX에서 혼돈(chaos)과 통제(control) 사이의 상충되는 필요성 간의 긴장감을 보여줍니다.
CSS를 벗어나지 않고도 표현 계층(presentation layer)에서 제어된 시각적 무작위성을 활용할 수 있다면 얼마나 좋을까요?
random()
함수가 나타납니다
예측 불가능한 사용자 경험을 구현하는 순간, CSS가 그 역할을 할 것이라는 점은 당연합니다. CSS 개발자들은 항상 일반적인 UI 패턴들을 선언적(declarative) CSS 표준으로 만들기 위해 노력해 왔습니다. 이러한 정신을 이어받아, 2025년 말 Safari는 “HTML과 CSS만으로 일반적인 사용 사례를 해결하고, 길을 개척하며, JavaScript나 타사 프레임워크의 필요성을 줄이는 것”에 중점을 둔 업데이트의 일환으로 CSS random() 사양을 지원하는 최초의 브라우저가 되었습니다.
그 이후로도 random()에 대한 멋진 데모와 토론이 계속해서 나오고 있습니다. 예를 들어, Schalk Neethling은 CSS random()이 악명 높은 컨페티(confetti) 효과를 세밀하게 제어할 수 있음을 보여주었고, Alvaro Montoro는 CSS가 이러한 작업에 가장 적합한 언어라는 강력한 주장을 펼쳤습니다. 그는 이 접근 방식이 “문제를 표현하고 해결하는 데 필요한 최소한의 기능을 가진 언어를 사용하여 문제를 해결하도록 장려하는” 최소 권력의 원칙(Rule of Least Power)과 일치한다고 지적합니다.
하지만 안 좋은 소식이 있습니다. Safari가 CSS random()을 도입한 지 반년이 지났지만, 다른 브라우저에 언제 적용될지에 대한 명확성이 없습니다. 글을 쓰는 시점에서 볼 때, Chrome과 Firefox 모두 이 기능을 개발하고 있다는 징후는 있지만, 심지어 브라우저 플래그(browser flag)를 통해서도 Apple 생태계 외부에서 사용할 수 있을지는 보장할 수 없습니다.
그래서 현재로서는 제가 작업하는 MacBook의 온라인 데모에서만 CSS random()을 시도해 볼 수 있고, 개인 프로젝트를 하는 PC에서는 할 수 없는 상황입니다. 직접 구현하고 싶은 유혹이 들지만, 구문(syntax)이 놀라울 정도로 복잡합니다. 이는 정교한 무작위 캐싱 및 키링 의미론(random caching and keying semantics), 그리고 기본값 및 간격 옵션들이 결합되어 있기 때문입니다. 설령 이 모든 세부 사항을 정확하게 처리할 수 있다고 해도, CSS random()은 “초기 탐색 단계”에 있으며 “주요 변경 사항이 예상되는” 편집자의 초안 사양(editor’s draft spec)의 일부입니다.
게다가, 제가 작성한 ::nth-letter 관련 CSS 폴리필(polyfill) 기사에서 파고든 바에 따르면,
CSS 폴리필의 전체적인 아이디어가 얼마나 복잡하고 까다로운지 알 수 있습니다.
이 모든 장애물들을 염두에 둔다면, 누군가가 CSS random()을 폴리필하려는 시도를 하려면 특별히 미친 사람일 정도여야 할 것입니다.
random()
CSS를 폴리필해 봅시다. 이 기능의 멋진 YouTube 데모를 본 댓글 작성자 중 한 명은 이것이 “오직 Safari에서만 작동하는 기능?!? 지구가 뒤집힌 건가요?”라고 감탄했습니다. 실제로 저는 Chrome에서 새로운 기능을 경험할 기회를 얻는 것에 더 익숙하기 때문에, 아이폰을 사용하는 친구들은 종종 제 실험을 실행할 수 없습니다.
하지만 random()의 경우, 우연에 기반한 기능이 우리 중 많은 사람이 사용할 수 없는 예상치 못한 장소에 나타났다는 것은 어둡고 시적인 일입니다. 사실 심지어 Safari 사용자들조차도 저의 css-random-polyfill 패키지로부터 이점을 얻을 수 있는데, 이는 Safari 업데이트가 OS에 연결되어 있어 모든 사람이 브라우저의 최신 버전으로 업그레이드할 수 없기 때문입니다. 게다가, Apple이 여러분이 그들의 것을 해킹하여 호환성을 개선하는 것을 얼마나 좋아하는지 우리는 알고 있습니다.
농담은 접어두고, Apple은 Safari를 구동하는 오픈 소스 WebKit 엔진의 모든 것에 대한 “해킹 가능성(hackability)”과 투명성에 대해 진지한 태도를 보이는 것 같으며, 제가 폴리필을 테스트하는 데 사용했던 대부분의 데모는 WebKit 블로그의 데모 포크(fork)이며, 이 데모에서 Apple Safari 팀은 CSS random()이 Safari 미리보기 버전(preview)에 있었을 때의 가능성을 보여주었습니다.
데모: 무작위 별장 (Random starfield)
여기는 Safari 팀 기사의 첫 번째 데모를 크로스 브라우저 버전으로 만든 것입니다. 이 데모는 무작위 간격으로 나타나고 사라지는 무작위 별들의 장입니다. 더 큰 네 꼭지점 모양의 별들은 모두 동일하게 무작위로 선택된 각도로 기울어져 있습니다. 모든 별들 주변에는 미묘하고 무작위한 색조의 그림자가 있습니다.
Safari 전용 원본을 Chrome과 Firefox에서 작동하는 버전으로 마이그레이션하려면, HTML을 수정하여 제 폴리필 스크립트를 참조하고 폴리필하려는 모든 요소에 randomized 마커 클래스를 추가해야 합니다.
...
CSS의 경우, 비표준 선택자(selector)인 :nth-letter 폴리필이 런타임에 유효한 CSS로 번역되어 과정에서 단점을 야기하는 것과는 달리 — 이번에는 새로운 선택자가 아닌 새로운 함수(function)를 지원해야 합니다. 놀랍게도 이 상황에서 사용할 수 있는 CSS는 기술적으로, CSS random()을 한 번도 들어본 적 없는 브라우저에서도 유효합니다.
왜 이것이 유효한지에 대한 내용은 나중에 다루겠지만, 일단은 무작위 값이 필요한 곳이라면 어디든 중간 사용자 정의 속성(intermediate custom property)에 저장해야 하며, 해당 속성 이름은 항상 --random 접두사로 시작한다는 규칙을 따라야 한다는 점만 알아주세요.
.star {
--random-star-size: random(1px, 7px, 1px);
background-color: white;
...
이 starfield 데모는 지원되는 random() 구문(syntax)의 몇 가지 다른 변형을 보여줍니다. 예를 들어, 단계 간격(step interval)을 지정하는 선택적 세 번째 인자(optional third argument)가 있는데, 이 경우 범위 내에서 정수 값만 무작위로 선택하는 데 사용됩니다:
--random-star-size: random(1px, 7px, 1px);
... 그리고 element-shared 기본값은 모든 네 방향 별을 동일하게 무작위로 선택된 각도로 기울이는 데 사용합니다.
.star.fourpointed {
--random-rotation: random(element-shared, -45deg, 45deg);
rotate: var(--random-rotation);
...
참고: 원래의 starfield 데모에서는 무작위 값 대부분이 인라인으로 사용되었는데, 이는 인정하건대 더 우아합니다. random()을 포함하는 사양(spec)은 이러한 종류의 함수가 calc()나 min()처럼 “속성 값의 어떤 부분에든 사용될 수 있음”을 명확히 합니다. 따라서 폴리필이 추가적인 의식과 규칙을 요구함으로써, 우리는 네이티브 random()으로 얻게 될 것의 일부(subset)만을 지원하고 있는 것입니다.
. 유리잔을 반만 채워진 것처럼 보기란 것은 CSS가 네이티브 구현과 호환된다는 의미입니다. 따라서 네이티브 지원이 기본 수준에 도달하면 폴리필(polyfill)의 스크립트 참조를 삭제할 수 있으며, 우리의 코드는 여전히 작동할 것입니다. 이는 Safari에서 네이티브 지원을 감지할 때 오늘날처럼 작동하는 방식과 같습니다. 이 경우 폴리필은 random() 호출을 전혀 처리하지 않고 Safari가 모든 작업을 수행하도록 내버려 둡니다. 이것은 제가 받아들일 수 있는 타협점이며, 특히 대안이 YouTube에서 Safari 전용 데모에 코를 박고
이 예제는 Safari 팀의 Tim Nguyen 님 자료입니다. 우연과 동시성의 주제를 이어가기 위해, 작년에 제가 Web Directions 2025에서 발표했을 때 Tim을 만난 좋은 행운에 대해 언급하겠습니다. 제 강연이 그의 강연 직후였는데, 이제 저는 그의 CSS random() 데모를 포크(fork)하여 크로스 브라우저 버전을 만들고 있으며, 그는 다시 한번 따라 하기 힘든 인물입니다.
이 예제에서 볼 수 있듯이, 바퀴의 최종 무작위 위치는 단계 간격 매개변수(step interval parameter)에 대해 최소값 및 최대값 매개변수에 사용되는 단위와 다른 단위를 사용합니다.
@keyframes spin {
from {
rotate: 0deg;
...
이러한 타입 혼합은 사양서(specs)에서 값들이 “동일한 데이터 타입으로 해석 가능해야 한다(resolvable to the same data type)”고 명시하고 있기 때문에 지원됩니다. 따라서 CSS calc()가 의미 있는 경우 다른 단위를 가진 값을 더하는 방식처럼, 우리는 turn과 deg와 같은 동일한 “전반적인 데이터 타입(overall data type)”에 속하는 단위들을 혼합할 수 있습니다. 이는 CSS 타입별 산술(typed arithmetic)을 사용하기 때문입니다.
참고: 이 데모가 폴리필(polyfill)로 작동하게 하려면, 저는 변수를 CSS 클래스 내에 정의해야 했습니다. 이 클래스는 폴리필이 처음 로드될 때 적용됩니다. 이는 체크박스 해킹(checkbox hack)을 기반으로 키프레임 애니메이션 내부에서 random() 함수를 사용했던 Tim의 원래 데모와 대조적입니다. 그 이유는 현재 폴리필은 페이지가 처음 로드될 때 요소에 적용되는 계산된 스타일(computed styles)만 처리하기 때문입니다. 모든 테스트가 이 구현으로 통과하므로, 저는 가장 간단하게 작동할 수 있는 것을 목표로 일단 그대로 두겠습니다. 폴리필이 계산된 스타일 및/또는 DOM의 동적 변경 사항에 반응하도록 만들 수 있는 방법들이 있습니다.
데모: 무작위 사각형
Chris Coyier는 자신의 요점을 전달하는 데 필요한 만큼 까다롭거나 단순한 코드를 작성하는 재주가 있으며, 그의 CodePen “CSS에서 매우 기본적인 random()”은 CSS random()의 가장 간단한 데모일 수 있습니다.
가능하며, 무작위로 배치된 무지개색 사각형 3개를 보여줍니다. 아래는 제가 만든 크로스 브라우저 버전으로, 커스텀 키를 사용하여 무작위 값 공유를 지원하는지 테스트하기 위해 사각형의 크기까지 무작위화하도록 수정했습니다.
각 사각형이 무작위 높이를 가지도록 하려면 다음 코드를 추가했습니다:
--random-height: random(--side, 40px, 100px);
--random-width: random(--side, 40px, 100px);
width: var(--random-height);
...
이는 올바른 구문이 지원됨을 재확인시켜 줍니다. 인정하건대, 커스텀 키는 중간 변수가 필요 없는 실제 네이티브 버전에서 더 유용할 것이며, 현재 우리는 중간 커스텀 속성을 사용하고 있기 때문에 --side라는 이름의 단일 커스텀 속성을 사용하여 height와 width 값 모두에 참조할 수 있었을 것입니다.
random-item
커스텀 CSS 함수를 사용하는 크로미움 전용 보너스 데모: 위 데모들 중 다수는 무작위 색상을 포함합니다. 이는 rgb()와 같은 CSS 색상 함수에 무작위 숫자 값을 전달하여 구현됩니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 CSS-Tricks의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기