React Canvas에서 Liquid Glass Lens 효과를 만들었습니다

발행: (2026년 4월 15일 PM 07:24 GMT+9)
6 분 소요
원문: Dev.to

Source: Dev.to

소개

최근 react-canvas에서 액체 유리 렌즈 후처리 효과를 구현했습니다. 목표는 세 가지였습니다:

  • 렌즈 중심에서 명확한 확대 느낌 제공
  • 가장자리 근처에 강한 유리‑같은 왜곡과 미세한 색분산 구현
  • 기존 CanvasKit 파이프라인을 완전히 재사용하여 두 번째 렌더링 스택을 없애기

GitHub 저장소:
Live demo:

렌더링 전략

가장 직관적인 방법인 별도의 캔버스나 WebGL 레이어를 추가하면 동기화 비용이 크게 증가합니다(스크롤, 줌, 카메라 상태를 일치시켜야 함). 또한 인터랙션 피킹 충돌이 발생할 수 있습니다.

대신 동일한 CanvasKit 파이프라인 내에서 전체 화면 후처리 방식을 선택했습니다:

  1. 전체 씬을 오프스크린 서피스로 렌더링합니다.
  2. 오프스크린 이미지에 SkSL RuntimeEffect를 적용합니다.
  3. 처리된 결과를 메인 캔버스에 한 번에 그립니다.

장점

  • 씬 로직을 완전히 재사용하므로 이중 렌더 트리가 필요 없습니다.
  • 효과 제어가 셰이더 코드와 유니폼에 집중됩니다.
  • 기존 렌더링 아키텍처와 높은 호환성을 유지합니다.

렌즈 구성 요소

현재 액체 유리 렌즈는 네 부분으로 구성됩니다:

  1. 중심 확대 – 렌즈 내부의 선명한 확대.
  2. 테두리 왜곡 – 외곽 링 근처에 집중된 왜곡.
  3. 색분산 (RGB 오프셋) – 가장자리에서 미세한 색 프린지를 추가해 유리 느낌을 강화.
  4. 테두리 하이라이트 + 그림자 – 렌즈에 물리적인 존재감을 부여.

핵심 최적화

중심은 왜곡 없이 확대되어야 하며, 왜곡은 외곽 약 20 % 영역에 집중되어야 합니다.

정규화된 반경 t를 도입하고 다음과 같이 사용합니다:

// GLSL / SkSL snippet
float rim = smoothstep(0.8, 1.0, t); // edge weight
// Near‑zero distortion weight at the center (t < 0.8)
// Gradually increasing distortion and dispersion as t → 1

이 접근법은 전체 영역을 흔들기보다 실제 렌즈의 가장자리 굴절을 모방합니다.

렌더링 루프

렌즈는 순수하게 유니폼에 의해 구동되는 후처리 효과입니다. 매 프레임마다 강제로 다시 그리면 간단하지만 불필요하게 비용이 많이 듭니다.

  • 포인터가 움직일 때 requestCanvasRepaint(canvas) 로 렌더링을 활성화합니다.
  • shouldContinueRepaint 은 렌즈가 목표 지점을 아직 따라가고 있을 때만 계속됩니다.
  • 렌즈가 정착하면 연속 재그리기가 자동으로 중단됩니다.

결과: 움직일 때는 부드러운 모션, 멈춰 있을 때는 불필요한 회전이 없습니다.

흔히 겪는 함정

  • 좌표 매핑: getBoundingClientRect() 와 백‑스토어 스케일을 이용해 포인터 좌표를 변환합니다.
  • 엣지 샘플링: 셰이더 UV 샘플링을 clamp(0..1) 로 제한해 검은 가장자리나 범위 초과 아티팩트를 방지합니다.

이러한 사소한 디테일이 최종 완성도에 직접적인 영향을 줍니다.

정리

  • 어디에 효과를 적용하지 않을지 결정하는 것이 무엇에 적용할지 결정하는 만큼 중요합니다.
  • 렌즈 효과에서는 안정적인 중심과 표현력 있는 가장자리가 전체 영역 왜곡보다 자연스럽습니다.
  • 아키텍처가 올바르게 잡히면(통합된 후처리 파이프라인) 반복적인 튜닝 비용이 크게 줄어듭니다.

Canvas/Skia 씬에서 유리, 깊이‑필드, 컬러‑그레이딩 효과를 만들고 있다면 “오프스크린 씬 + RuntimeEffect” 방식을 시작점으로 삼으세요. 향후 확장에도 훨씬 더 잘 스케일됩니다.

0 조회
Back to Blog

관련 글

더 보기 »