개요
Three.js를 이용해 웹에서 3D Scene을 구현할 때는 브라우저의 크기 변화나 디스플레이 환경에 따라 다양한 문제가 발생할 수 있습니다. 본 문서에서는 창 리사이징 시 발생하는 화면 찌그러짐과 여백 문제, 그리고 전체화면(Fullscreen) 모드 구현에 대한 해결 방법을 다루겠습니다.
- Resizing
Three.js로 만든 3D Scene을 웹을 렌더링하면, 브라우저 창 크기를 조절할 때 그림이 찌그러지거나, 모서리에 하얀 여백이 생기는 현상이 발생할 수 있습니다.
기존 sizes를 800x600 에서 window.inner 변수를 이용해 실제 뷰 포트를 조정해줍니다.
현재 해당 이미지에서 하얀 여백이 모서리 부분에 액자처럼 생긴 것을 확인할 수 있습니다. 이러한 부분을 css 추가를 통해 수정할 수 있도록 해주겠습니다.
- CSS
먼저 style.css파일을 생성해주고 index.html 에서 .css파일을 불러옵니다.
이후 .css 파일을 작성합니다.
margin, padding을 0으로 설정하여 기본적으로 생기는 브라우저의 공백을 제거해줍니다. html, body에 overflow: hidden을 적용하면 화면 조작 중 스크롤이 생기는 걸 방지할 수 있습니다. webgl 클래스에 position: fixed, top: 0, left: 0, outline: none을 적용하면 화면 전체를 꽉 채우는 형태로 렌더링 할 수 있으며, 마찬가지로 canvas에 display: block을 설정하면 기본적으로 생기는 줄바꿈 여백도 제거됩니다.
이렇게 공백 없는 Scene이 렌더링되는 것을 볼 수 있습니다.
- Resizing 대응(Javascript)
.css 설정을 마쳤다면, 이제 .js에서 창 크기 변화에 대응하여 3D Scene도 동적으로 반응하도록 만들어야 합니다. 아래는 일반적으로 많이 사용하는 방식으로 sizes 객체를 통해 브라우저의 크기를 감지하고, 카메라의 비율(aspect)만 조정해주는 코드입니다.
하지만 이 코드만으로는 리사이징이 완전히 적용되지 않습니다. 창 크기를 줄이면 하얀 여백이 생기거나, 화면 일부가 잘리는 현상, 혹은 큐브가 찌그러져 보이는 문제가 발생하죠.
- 문제가 발생하는 이유
위 코드는 단지 카메라의 비율(aspect) 값만 바꿨을 뿐, 투영 행렬(Projection Matrix) 이나 캔버스 크기(Renderer 크기) 는 갱신하지 않았기 때문입니다. 해결 방법은 간단합니다. camera 안에 있는 투영행렬 업데이트 함수를 호출하고 renderer를 리사이징하면 완료됩니다.
위 그림은 위아래로 리사이징해도 잘 따라오는 예시입니다.
(GIF 프레임 때문에 조금 어색해 보일수도 있습니다.
이제 브라우저 창을 위아래, 좌우로 줄이거나 늘려도 3D Scene이 자동으로 맞춰지면서, 화면이 찌그러지거나 하얀 여백이 생기지 않습니다!
- 픽셀 비율 처리
마지막으로 현재 콘솔에 window.devicePixelRatio를 선언한다면 기본적인 PC에서는 1이 나오고 레티나 디스플레이나 고해상도 화면에서는 2, 3 또는 더 큰 값이 나오죠.
픽셀 비율이 높을수록 선명해지지만, 그 만큼 GPU 리소스를 더 많이 소모합니다. 그래서 보통 2로 제한하는 것이 성능과 화질 사이의 균형을 맞추는 좋은 선택입니다.
resize event는 디스플레이거 변경되거나 브라우저 확대/축소 등의 특수한 상황에서 호출되므로, 이 시점에 setPixelRatio를 설정해주는 것이 가장 적절합니다.
// 일반적으로 1이지만, 고해상도 디스플레이에서는 2 또는 3일 수 있습니다.
// 픽셀 비율이 너무 높으면 성능 저하가 발생하므로,
// 최대값을 2로 제한하여 적절한 품질과 성능을 유지합니다.
Math.min()을 설정해서 최대 픽셀 비율을 2로 고정하고, 너무 고해상도에서 프레임 드랍이 발생하지 않도록 방지합니다.
- Fullscreen
Fullscreen은 웹 또는 모바일 환경에서 더블 클릭이나 버튼 클릭을 통해 화면 전체를 채우는 기능입니다. 다음은 해당 기능을 구현하는 코드이며, 브라우저 호환성을 최대한 고려한 예시입니다.
기본적으로 canvas.requestFullscreen, canvas.exitFullscreen을 사용하면 되지만, 브라우저 마다 사용하는 API가 다르기 때문에 아래처럼 구분이 필요합니다 :
- fullscreentElement: 표준 (크롬, 파폭, 엣지 최신)
- webkitFullscreenElement: 사파리
- mozFullScreentElement: Firefox(구버전)
- msFullscreentElement: IE/Edge 구버전
이처럼 다양한 브라우저 기능을 모두 대응할 수 있도록 조건문을 구성한 것입니다.
- 최신 브라우저만 고려한다면?
최신 환경에서는 아래 코드만으로도 충분합니다:
canvas.requestFullscreen();
하지만 Safari, 일부 기업용 환경, 구형 브라우저까지 고려한다면 위에서 작성한 다양한 fallback이 포함된 코드를 사용하는 것이 더 안정적입니다.
결론
이번 작업을 통해 화면 크기 변경, 고해상도 디스플레이, 다양한 브라우저 환경에서도 문제 없이 동작하는 안정적인 3D Scene을 만들 수 있게 되었습니다. 기본적인 대응만으로도 사용자 경험이 크게 개선된다는 점을 확인할 수 있었습니다.
'Three.js > Intro' 카테고리의 다른 글
[threejs-journey 1-9] Debug UI (0) | 2025.06.22 |
---|---|
[threejs-journey 1-8] Geometries (0) | 2025.06.16 |
[threejs-journey 1-6] Control (0) | 2025.06.10 |
[threejs-journey 1-6] Camera (3) | 2025.06.10 |
[threejs-journey 1-5] Animation (0) | 2025.06.03 |