TDS 인터랙션 컴포넌트 / 2026.01 ~ 2026.04
ProgressiveBlur에 대한 고찰
TL;DR
ProgressiveBlur는 위치에 따라 blur 강도가 점진적으로 달라지는 효과예요. 시중에서는 backdrop-filter: blur(...)를 여러 레이어로 겹치고 linear-gradient로 블렌딩하는 방식을 많이 쓰지만, 저는 Figma의 ProgressiveBlur처럼 픽셀별 blur 값이 실제로 달라지도록 구현하려고 WebGL 기반 접근을 골랐어요.
문제 정의 Problem
Next Look & Feel 프로젝트의 일부로, Figma의 ProgressiveBlur 표현을 웹에서 구현해야 했어요. 비슷해 보이는 blur를 만드는 것보다, 진짜 ProgressiveBlur가 무엇인지 먼저 정의하는 게 중요했어요. 많은 웹 구현은 backdrop-filter 레이어를 여러 개 만들고 각 레이어를 gradient mask로 블렌딩해 점진적인 blur처럼 보이게 해요. 블렌딩 영역을 넓게 주면 어지간해서는 자연스러워 보이지만, Figma의 실제 ProgressiveBlur와 견주면 차이가 확연히 드러났죠.
접근 방식 Approach
기준으로 삼은 ProgressiveBlur는 여러 blur 레이어를 섞은 효과가 아니라, 픽셀 위치에 따라 blur radius가 실제로 달라지는 효과였어요. 앞서 말한 backdrop-filter 레이어 방식은 여러 blur 결과를 gradient mask로 섞는 구조라, 픽셀별 blur 값이 연속적으로 변하는 구조는 아니었죠. 그래서 ProgressiveBlur를 픽셀별 blur 값을 계산하는 문제로 다시 정의하고, shader에서 위치에 따라 blur 값을 계산할 수 있는 WebGL canvas 기반 접근을 검토했어요.
WebGL은 canvas 안에서 동작하기 때문에, canvas에서 렌더링하려면 이미지나 비디오처럼 텍스처로 올릴 수 있는 에셋이 필요해요. 이번 대상이 마침 이미지나 비디오처럼 texture로 올릴 수 있는 에셋 기반 표현이었던 덕분에, WebGL canvas와 shader를 활용할 수 있는 조건이 갖춰져 있었어요.
핵심 결정 Decision
backdrop-filter 레이어 방식 대신, 픽셀별 blur 값을 직접 계산할 수 있는 WebGL canvas 기반 구현을 골랐어요. CSS backdrop-filter 방식은 DOM 위에 바로 적용하기 쉽고 구현도 상대적으로 단순하지만, 정확한 ProgressiveBlur라기보다는 여러 blur 레이어를 gradient로 섞어 비슷하게 보이게 만드는 방식에 가까웠어요. 게다가 backdrop-filter는 이미 비싼 스타일 연산이라, 더 자연스러운 결과를 내려고 레이어 수를 늘리면 성능 비용도 같이 커지고요.
WebGL 방식은 canvas와 에셋이 필요하고 구현 난도도 훨씬 높아요. 대신 픽셀별로 blur 값을 계산하니까, Figma의 ProgressiveBlur에 더 가까운 연속적인 blur 변화를 만들 수 있었어요.
해결 결과 Result
shader가 픽셀별 blur 값을 직접 계산하니까, 레이어를 섞어 흉내 내던 방식과 달리 blur radius가 위치를 따라 연속적으로 변하는 결과를 얻었어요. ProgressiveBlur는 WebGL canvas와 shader 기반의 interaction 컴포넌트로 자리 잡았어요.
배운 점 Learning
이 작업을 하면서 canvas와 WebGL을 처음 본격적으로 다뤄봤어요. WebGL은 DOM에 직접 효과를 입히는 방식이 아니라 canvas 안에서 에셋을 텍스처로 올려 렌더링하는 방식이더라고요. 그래서 ProgressiveBlur 같은 효과를 웹에서 구현하려면, 이걸 DOM에 적용할지 에셋 기반 렌더링으로 다룰지부터 갈라야 한다는 걸 처음 체감했어요. 효과의 정의가 곧 렌더링 패러다임 선택으로 이어진다는 감각이 이번에 남았어요.