티스토리 뷰

웹 개발을 하다 보면 내 컴퓨터에선 멀쩡한데, 특정 사용자의 컴퓨터에서만 이미지가 아예 렌더링되지 않는 현상을 마주하곤 합니다.
실제 경험 중 React + WebView2(EXE) 환경에서 발생한 이미지 증발 사건이 있는데 이를 통해, GPU 합성(Compositing)레이아웃 타이밍 문제를 파헤쳐 봅니다.

해당 문제는 React 환경에서 발생하는 것이 아닌, css 페인팅 및 합성 과정에서 발생하는 문제입니다.

용어 정리

우선 문제를 정의 전에 알아두고 가면 좋을 용어들을 정리합니다. 아래 용어를 달달 외울필요는 없지만, 아 이런게 있구나 정도만 알면 될 듯 합니다.

1. Stacking Context (쌓임 맥락)

정의: HTML 요소들이 사용자 눈에 보이는 '앞-뒤 순서(Z축)'를 결정하는 가상의 그룹입니다.

  • 비유: 포토샵의 '레이어 그룹(Group)'과 같습니다.
  • 특징: 특정 속성(opacity, transform, z-index, overflow: hidden 등)을 주면 브라우저는 새로운 그룹을 만듭니다. 이 그룹 안에 갇힌 자식들은 부모라는 '그룹' 안에서만 순서를 바꿀 수 있고, 부모를 넘어서 앞으로 나올 수 없습니다.
  • 이번 이슈와의 연관: 부모가 overflow: hidden으로 새로운 맥락을 만들면서, 자식(SVG)을 관리하는 '기준점'이 생성된 것입니다.

2. Composited Layer (합성 레이어)

정의: 성능 최적화를 위해 브라우저가 일반적인 문서 흐름(2D)에서 떼어내어 GPU 메모리에 직접 올린 독립된 레이어입니다.

  • 비유: 투명한 '아크릴판'입니다.
  • 특징: absolute, transform, will-change 등이 적용된 요소는 브라우저가 "이건 따로 관리하는 게 빠르겠다"라고 판단하여 별도의 아크릴판에 그려버립니다.
  • 이번 이슈와의 연관: absolute로 띄운 SVG가 바로 이 '독립된 아크릴판'이 되어 공중에 붕 떠 있는 상태가 된 것입니다.

3. Layer Promotion (레이어 격상)

정의: 일반 요소가 CPU가 그리는 방식에서 벗어나 GPU가 관리하는 '합성 레이어'로 승격되는 과정을 말합니다.

  • 발생 조건: 3D 변환(translateZ), 애니메이션, 혹은 복잡한 absolute 배치가 있을 때 브라우저가 판단하여 격상시킵니다.
  • 문제점: 격상된 레이어는 성능은 좋지만, 부모(일반 레이어)와의 물리적 거리가 생기기 때문에 둘을 합치는 연산이 추가로 필요합니다.

4. GPU Compositing (GPU 합성)

정의: 쪼개진 여러 개의 레이어(아크릴판)들을 순서에 맞게 겹쳐서 하나의 최종 화면으로 만드는 작업입니다.

  • 역할: 이 단계에서 GPU는 부모 레이어의 overflow: hidden 경계선을 계산해서, 그 밖에 삐져나온 자식 레이어 부분을 잘라냅니다(Clipping).
  • 이번 이슈의 핵심: 특정 PC의 GPU 드라이버가 "2D 종이(부모)의 구멍에 맞춰 3D 아크릴판(자식)을 자르는 계산"에 실패하여 이미지를 투명하게 날려버린 단계입니다.

5. Rasterization (래스터화)

정의: 벡터 데이터(SVG의 점과 선)를 브라우저가 실제 화면에 뿌릴 수 있는 픽셀(점) 데이터로 변환하는 과정입니다.

  • 참고: 메모리가 부족하거나 GPU 가속에 문제가 생기면, 이 래스터화 과정이 생략되거나 오류가 나면서 이미지가 깨지거나 안 보일 수 있습니다.

그렇다면 어떤 구조였는가?

<div style="position: relative; overflow: hidden; height: auto;">
  <div style="position: absolute; top: 0; left: 0;">
    <svg>...</svg>
  </div>
</div>

 

 

 

위 구조를 가지고 아래와 같은 이슈가 발생합니다.

 

Layer 1 (부모): overflow: hidden으로 인해 새로운 Stacking Context 형성. 일반적인 2D 렌더링 층에 머무름.

Layer 2 (자식): absolute + SVG 조합. 브라우저가 성능을 위해 이를 GPU 합성 레이어(Composited Layer)로 격상시켜 공중에 띄움 (3D 아크릴판 상태).

The Conflict (합성 단계): GPU는 Layer 1(부모)의 경계선에 맞춰 Layer 2(자식)를 잘라내야 함.

- 특정 저사양 GPU/구형 드라이버는 이 "2D-3D 교차 클리핑" 연산을 수행하다가 오류(Artifact) 발생.

- 결과: 계산에 실패한 GPU는 안전을 위해 자식 레이어를 투명(Transparent) 처리함.


왜 "하필" 그 컴퓨터에서만 발생할까?

사용자의 RAM이 16GB로 충분하더라도 문제는 발생할 수 있습니다. 이는 하드웨어 용량보다는 '환경의 조합' 문제이기 때문입니다.

  1. GPU 드라이버 버전: 최신 WebView2 엔진을 쓰더라도, 실제 그림을 그리는 GPU 드라이버가 구형이면 브라우저의 최신 합성 명령을 이해하지 못합니다.
  2. 하드웨어 가속(Hardware Acceleration): 하드웨어 가속이 켜져 있으면 GPU가 무리하게 계산을 시도하다 오류가 나고, 꺼져 있으면 CPU가 처리하느라 속도가 느려집니다.
  3. 내장 그래픽의 한계: 인텔 내장 그래픽(iGPU)은 VRAM을 시스템 RAM과 공유합니다. 다른 프로그램이 메모리를 많이 점유하면 GPU가 쓸 여유 공간이 줄어들어 복잡한 레이어 합성(Compositing)을 가장 먼저 포기하게 됩니다.

그렇다면 어떻게 해결해야 하는가?

이런 문제는 논리적인 문제보다는 보통 브라우저, 하드웨어간의 통신 문제로 인한 오류가 더 많습니다.

그렇기 때문에 명시적으로 동기화를 해준다거나, 렌더링 범위를 한정적으로 가져가면 됩니다.

.parent {
  transform: translateZ(0); /* 부모도 3D 레이어로 격상 */
  overflow: hidden;
}

.parent {
  contain: paint; /* 이 영역 밖은 절대 안 그리니 안심하고 계산해! */
}

 

이러한 문제는 많이 만나볼 수 없는 문제이고 보통 엔진 업데이트를 진행하면 자동으로 해결되는 경우가 많아 참고 바랍니다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/03   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함