Skip to main content

WebXR 개발 시 꼭 주의할 것들

WebXR에서 가장 자주 생기는 오해는 이것입니다. "일단 실행되면 성공한 것 아닌가요?"

아쉽게도 그렇지 않습니다. 일반 웹 페이지는 조금 느려도 참고 볼 수 있지만, XR은 다릅니다. 프레임이 흔들리거나 입력이 어색하면 사용자는 바로 불편함을 느낍니다. VR에서는 멀미가 나고, AR에서는 물체가 덜컹거리거나 실제 공간과 어긋나 보일 수 있습니다. 그래서 WebXR 개발에서는 작동 여부보다 사용자가 편안하게 느끼는지가 더 중요합니다.

특히 WebXR은 브라우저, 운영체제, 헤드셋, 휴대폰, 컨트롤러, 카메라 권한, 공간 추적 기능이 한꺼번에 얽혀 움직입니다. 즉, 한 군데만 잘 만들어서는 부족합니다. 성능, 입력, 보안, 권한, 세션 종료 처리까지 모두 함께 챙겨야 비로소 "잘 만든 XR"에 가까워집니다.

이번 장에서는 초보자가 실전에서 가장 자주 부딪히는 문제를 성능, 멀미, 입력 차이, 호환성, 세션 관리라는 다섯 축으로 정리해 보겠습니다. 앞 장들에서 예제를 따라 하며 "일단 돌아가게" 만드는 감각을 익혔다면, 이제는 "사람이 써도 괜찮은 경험"으로 다듬는 감각을 익힐 차례입니다.

가장 먼저 챙길 것: 안정적인 프레임 유지

XR에서 성능 문제는 단순한 숫자 문제가 아닙니다. 곧바로 사용자 경험 문제로 이어집니다. MDN은 WebXR에서 렌더링 루프를 단순하게 유지하고, 불필요한 그리기를 줄이며, 메모리 할당을 반복하지 않는 식으로 프레임 유지에 신경 써야 한다고 설명합니다.1 PlayCanvas 문서도 XR에서는 특히 높고 일관된 프레임레이트가 중요하다고 강조합니다. VR은 양쪽 눈에 장면을 렌더링해야 하므로 일반 3D보다 더 비싸고, AR은 여기에 월드 트래킹 비용까지 더해질 수 있습니다.2

쉽게 말해, 데스크톱 화면에서 잘 돌아가던 3D 장면이 XR에 들어가면 갑자기 무거워지는 일이 흔합니다. 한 장면을 한 번 그리던 습관으로 만들었는데, XR에서는 두 눈용 뷰와 센서 처리까지 감당해야 하기 때문입니다.

초보자가 특히 자주 놓치는 병목은 다음과 같습니다.

  • 드로우 콜 증가: 오브젝트가 지나치게 많거나 재질이 잘게 나뉘면 GPU에 그리기 명령을 너무 많이 보냅니다.23

  • 오버드로우: 보이지 않는 픽셀을 여러 번 덧그리면 모바일 XR 기기에서 성능이 급격히 떨어집니다.23

  • 실시간 조명과 그림자 남용: 보기에는 멋지지만 프레임을 크게 잡아먹습니다.2

  • 매 프레임 객체 생성: 벡터, 행렬, 배열을 계속 새로 만들면 가비지 컬렉션이 끼어들어 화면이 순간적으로 끊길 수 있습니다.12

여기서 중요한 감각은 "멋진 효과를 추가할 때마다 사용자의 머리에 부담이 간다"는 점입니다. XR에서는 화려함보다 안정감이 먼저입니다.

성능 최적화는 나중이 아니라 처음부터 해야 한다

성능은 마지막 주에 한꺼번에 고치는 항목이 아닙니다. Meta의 WebXR 성능 가이드는 하드웨어 특성을 이해하고, 도구로 측정하고, 최적화 결과를 검증하는 식의 체계적인 접근을 권장합니다.4 Toji의 최적화 글도 먼저 실제 기기에서 프로파일링해서 병목이 어디인지 확인해야 한다고 말합니다.3

즉, "느린 것 같으니 모델을 줄여 보자"처럼 감으로 접근하면 금방 한계가 옵니다. CPU가 문제인지, GPU가 문제인지부터 구분해야 합니다. 예를 들어 장면은 단순한데 자바스크립트 계산이 많아 느릴 수도 있고, 반대로 코드 자체는 단순하지만 반투명 오브젝트와 고해상도 텍스처 때문에 GPU가 버거울 수도 있습니다.

실전에서는 다음 순서로 접근하면 좋습니다.

  • 실제 목표 기기에서 먼저 돌려 봅니다.

  • 브라우저 개발자 도구나 엔진 프로파일러로 프레임 시간을 확인합니다.23

  • CPU 병목인지 GPU 병목인지 나눠 봅니다.

  • 원인을 하나씩 줄인 뒤 다시 측정합니다.

이 과정을 거치지 않으면, 열심히 최적화했는데 정작 느린 이유는 그대로 남아 있는 경우가 많습니다.

모델과 텍스처는 "예쁜 파일"이 아니라 "빠른 자산"이어야 한다

XR 프로젝트가 느린 가장 흔한 원인 중 하나는 코드가 아니라 에셋입니다. 특히 인터넷에서 받은 멋진 3D 모델은 데스크톱 미리보기에서는 그럴듯해 보여도 모바일 AR/VR 기기에서는 너무 무거운 경우가 많습니다. Toji는 WebXR에서 장면 최적화의 핵심 중 하나로 드로우 콜 감소, 불필요한 복잡도 제거, 모바일 기기 기준 테스트를 강조합니다.3

초보자는 "폴리곤 수만 낮으면 괜찮겠지"라고 생각하기 쉽지만, 실제로는 재질 수, 메시 분할, 텍스처 해상도, 투명 재질, 애니메이션, 물리 계산이 함께 영향을 줍니다.

에셋을 다룰 때는 다음 원칙을 기억해 두면 좋습니다.

  • 가까이서만 볼 물체가 아니면 디테일을 과하게 넣지 않습니다.

  • 멀리 있는 물체는 더 단순한 모델로 바꾸는 LOD를 고려합니다.5

  • 텍스처 해상도는 필요한 만큼만 씁니다.

  • 투명 재질은 꼭 필요한 곳에만 사용합니다.

  • 정적 오브젝트는 가능하면 병합하거나 배치해 드로우 콜을 줄입니다.23

한마디로 말하면, WebXR에서 좋은 에셋은 "고급스러운 에셋"이 아니라 "기기에서 부드럽게 보이는 에셋"입니다.

해상도 욕심은 멀미로 돌아올 수 있다

XR에서는 화면이 선명할수록 좋아 보이지만, 해상도를 무작정 높이면 프레임이 떨어집니다. XR은 두 눈을 위한 렌더링이 필요하기 때문에 일반 3D보다 해상도 비용이 훨씬 크게 느껴집니다. WebXR의 XRWebGLLayer는 framebufferScaleFactor로 프레임버퍼 크기를 조절할 수 있고,6 react-three/xr 문서도 프레임버퍼 스케일과 포비에이션(foveation)을 GPU 성능 최적화 수단으로 소개합니다.7

포비에이션은 화면 중심부는 선명하게, 주변부는 상대적으로 낮은 해상도로 렌더링해 성능을 확보하는 방법입니다. 말하자면 사용자가 잘 보는 곳에 힘을 몰아주는 방식입니다. 최적화가 충분한데도 GPU가 버겁다면 이런 옵션을 검토할 수 있습니다.7

다만 초보자라면 먼저 더 기본적인 것부터 줄이는 편이 안전합니다. 무거운 셰이더, 큰 텍스처, 많은 반투명 오브젝트, 실시간 그림자 같은 항목을 정리한 뒤에 해상도 조정을 마지막 카드로 꺼내는 것이 좋습니다.

멀미를 유발하는 요소는 기능보다 더 치명적이다

WebXR에서 나쁜 UX는 대개 두 가지 얼굴을 가지고 있습니다. 하나는 느림이고, 다른 하나는 어색한 움직임입니다.

VR에서 특히 조심해야 할 것은 사용자의 몸이 느끼는 방향과 화면이 움직이는 방향이 어긋나는 순간입니다. 예를 들어 사용자가 가만히 있는데 카메라가 갑자기 미끄러지듯 이동하거나, 머리를 돌렸는데 화면이 늦게 따라오거나, 조작에 따라 가속이 너무 급격하게 붙으면 멀미가 쉽게 생깁니다. 프레임 저하도 여기에 기름을 붓습니다.

초보자가 자주 만드는 위험한 패턴은 이렇습니다.

  • 스틱 입력으로 카메라를 너무 빠르게 이동시키는 경우

  • 이유 없이 자동 회전, 자동 이동을 넣는 경우

  • 머리 추적과 별개로 카메라 위치를 강제로 덮어쓰는 경우

  • 순간이동 대신 부드러운 이동만 제공하는 경우

  • 화면 흔들림 효과를 멋으로 넣는 경우

WebXR에서는 "게임처럼 역동적이면 좋다"보다 "머리가 편안한가"를 먼저 물어야 합니다. 이동 방식은 가능하면 예측 가능해야 하고, 시야 변화는 최소화해야 하며, 사용자가 직접 통제하고 있다는 느낌을 줘야 합니다.

입력 방식은 하나가 아니다

웹 개발에 익숙한 사람은 클릭이나 터치만 생각하기 쉽습니다. 하지만 WebXR의 입력은 훨씬 다양합니다. MDN은 WebXR 입력을 타기팅과 액션으로 나누고, 입력 장치도 화면 터치, 모션 컨트롤러, 손 추적, 시선 기반 입력 등으로 달라질 수 있다고 설명합니다.8 또한 XRInputSource는 targetRayMode, gripSpace, profiles 같은 정보를 통해 입력 장치의 성격을 알려 줍니다.86

여기서 정말 중요한 사실은 입력이 기기마다 다르게 들어온다는 점입니다.

  • 어떤 기기는 컨트롤러가 있고, 어떤 기기는 손 추적만 있습니다.

  • 어떤 환경은 시선 기반 선택이 중심이고, 어떤 환경은 화면 탭이 중심입니다.8

  • targetRayMode는 gaze, tracked-pointer, screen처럼 서로 다른 방식을 가질 수 있습니다.86

따라서 입력 로직을 한 가지 방식에만 맞춰 만들면 금방 벽에 부딪힙니다. 예를 들어 "트리거를 눌러 선택"만 가정하면 모바일 AR에서는 어색해지고, "화면 탭"만 가정하면 VR 컨트롤러 환경에서는 UX가 빈약해집니다.

좋은 시작점은 다음과 같습니다.

  • 기본 상호작용은 가능한 한 단순하게 만듭니다.

  • 선택 방식은 한 가지에만 의존하지 말고 대안을 둡니다.

  • 컨트롤러 모델이 꼭 같을 것이라 기대하지 않습니다.

  • 입력 소스가 바뀌거나 추가될 수 있다는 전제로 코드를 짭니다.

WebXR Input Profiles 프로젝트도 서로 다른 하드웨어 입력 프로필을 표준적으로 다루기 위한 자료와 자산을 제공합니다.9 즉, 입력은 "내가 가진 기기에서만 되는 방식"이 아니라 "여러 장치에서도 무너지지 않는 방식"으로 설계해야 합니다.

디바이스 호환성은 생각보다 더 복잡하다

WebXR은 한 번 만들면 어디서나 똑같이 동작할 것처럼 보이지만, 실제로는 그렇지 않습니다. MDN은 WebXR이 아직 제한적으로 지원되는 기술이며, 운영 환경별 호환성을 주의 깊게 확인하라고 안내합니다.10 Can I use에서도 브라우저별 지원 차이를 확인할 수 있습니다.11

게다가 "WebXR 지원"이라는 한 줄만으로는 부족합니다. 실제로는 다음이 다 다릅니다.

  • 브라우저가 immersive VR을 지원하는지

  • immersive AR을 지원하는지

  • hand input, hit test, plane detection 같은 기능이 되는지

  • 특정 권한이 필요한지

  • 프레임레이트나 렌더링 옵션을 얼마나 허용하는지

그래서 시작 전에 navigator.xr 존재 여부만 보는 것은 너무 얕은 검사입니다. MDN은 원하는 세션 모드가 가능한지 isSessionSupported()로 확인하는 방식을 제안합니다.12

실전에서는 "지원 여부 확인 → 기능별 분기 → 대체 UX 제공"의 흐름이 필요합니다. 예를 들어 immersive AR이 안 되면 3D 미리보기 모드로 내려가고, 컨트롤러가 없으면 gaze나 화면 탭 입력으로 바꾸는 식입니다. 잘 만든 WebXR 앱은 실패하지 않는 앱이 아니라, 실패했을 때도 부드럽게 대처하는 앱입니다.

HTTPS와 권한 요청은 기능이 아니라 입장권이다

WebXR은 보안 맥락에서만 동작합니다. MDN은 WebXR이 secure context, 즉 HTTPS 환경에서만 제공되며, 안전하지 않은 문서에서는 navigator.xr 자체가 없을 수 있다고 설명합니다.1012 개발 단계에서는 localhost가 허용되지만, 배포 환경에서는 HTTPS가 사실상 필수입니다.12

또 하나 자주 놓치는 점은 세션 요청 타이밍입니다. requestSession()은 아무 때나 부르면 안 되고, 보통 사용자의 클릭 같은 사용자 제스처 안에서 호출해야 합니다.12 사용자가 아무 행동도 하지 않았는데 갑자기 XR 진입을 시도하면 브라우저가 막을 수 있습니다.

iframe 안에서 WebXR을 띄우는 경우에는 allow="xr-spatial-tracking" 같은 설정도 필요할 수 있습니다.13 이 조건을 모르고 "왜 내 코드는 기기에서만 실패하지?" 하고 한참 헤매는 경우가 많습니다.

권한 요청도 UX입니다. AR에서는 카메라, 공간 추적, 추가 기능 권한이 얽힐 수 있고, 사용자는 갑작스러운 권한 팝업에 쉽게 경계합니다. 따라서 권한이 왜 필요한지 먼저 설명하고, 거부되었을 때는 대체 화면이나 안내 문구를 제공하는 편이 훨씬 좋습니다.

세션 시작보다 세션 종료가 더 중요할 때가 있다

많은 초보자가 세션 진입에는 신경을 쓰지만, 세션을 끝낼 때는 대충 넘어갑니다. 그런데 WebXR에서는 종료 처리가 엉성하면 재진입 시 상태가 꼬이기 쉽습니다. MDN은 세션을 깔끔하게 닫으려면 session.end()를 호출해야 한다고 설명합니다.12

문제는 여기서 끝이 아니라는 점입니다. XR 세션이 끝났다고 해서 장면 상태, 앵커, 히트 테스트 결과, 선택 상태, 이벤트 리스너, 임시 메시는 자동으로 모두 정리되는 것은 아닙니다. 실제로 pmndrs/xr 이슈에서는 AR 세션 종료 후 재입장했을 때 이전 배치 상태가 남거나 검은 화면, 추적 이상이 생기는 사례가 보고되었습니다.15

이런 문제를 막으려면 세션 종료 시 다음을 함께 정리해야 합니다.

  • XR 세션 객체와 관련 이벤트 리스너

  • 배치된 오브젝트, 앵커, 히트 테스트 상태

  • 입력 상태와 선택 상태

  • 임시 메시, 텍스처, 지오메트리 캐시

  • 프레임 루프에서만 쓰던 참조값

즉, 종료 처리는 "XR 모드만 빠져나오기"가 아니라 "다음 입장을 위한 초기화"까지 포함해야 합니다. 세션이 새로 시작될 때는 정말 새로 시작되는 느낌이어야 합니다.

메모리와 가비지 컬렉션은 조용히 프레임을 망친다

XR에서 가장 얄미로운 문제 중 하나는 눈에 잘 안 보이는 성능 저하입니다. 화면은 멀쩡한데 가끔씩 툭 끊기고, 사용자는 이유를 설명하기 어려운 불편함을 느낍니다. 이런 현상은 자바스크립트의 메모리 할당과 가비지 컬렉션에서 오는 경우가 많습니다.

MDN은 렌더링 루프 안에서 매 프레임 벡터, 행렬, 배열 같은 객체를 새로 만들지 말고, 재사용 가능한 객체를 미리 준비해 두라고 권장합니다.1 PlayCanvas 문서도 같은 이유로 런타임 할당을 최소화하고 벡터 등을 재사용하라고 조언합니다.2

이 원칙은 간단합니다. 프레임 루프는 계산만 하고, 생성은 가급적 바깥에서 하자는 것입니다. 특히 충돌 검사, 레이캐스팅, 포즈 계산, 행렬 업데이트가 많은 XR에서는 이 차이가 꽤 크게 느껴집니다.

AR은 보이는 것보다 추적이 더 어렵다

AR은 VR보다 쉽다고 생각하는 경우가 있는데, 실제로는 다른 종류의 어려움이 있습니다. PlayCanvas는 AR에서 월드 트래킹 자체가 큰 성능 비용을 가질 수 있다고 설명합니다.2 Android XR 개발 문서도 WebXR 앱이 깊이 정보, 손 입력, 권한 같은 기기 특성을 고려해야 한다고 안내합니다.16

AR에서는 다음과 같은 문제가 자주 발생합니다.

  • 평면 인식이 늦거나 흔들립니다.

  • 조명이 바뀌면 물체가 부자연스러워 보입니다.

  • 실제 공간과 가상 물체의 크기 감각이 어긋납니다.

  • 사용자가 너무 빠르게 움직이면 추적이 불안정해집니다.

그래서 AR에서는 "처음부터 모든 기능을 다 켜는 것"보다 핵심 상호작용 하나를 안정적으로 만드는 편이 낫습니다. 히트 테스트, 앵커, 깊이 센싱, 손 추적을 한꺼번에 넣으면 멋져 보일 수는 있지만, 성능과 디버깅 난도가 급격히 올라갑니다.

에뮬레이터는 연습장이지, 시험장이 아니다

데스크톱 개발 단계에서는 WebXR 에뮬레이터와 폴리필이 큰 도움이 됩니다. 하지만 MDN은 에뮬레이터나 폴리필 환경이 실제 하드웨어 테스트를 대신할 수 없다고 분명히 말합니다.12 실제 기기에서는 센서 정확도, 컨트롤러 반응, 카메라 권한, 추적 안정성, 렌더링 성능이 전부 다르게 나타날 수 있기 때문입니다.

즉, 에뮬레이터에서 잘 되는 것은 "시작할 자격"일 뿐, "배포해도 좋다"는 의미는 아닙니다. WebXR은 반드시 목표 기기에서 직접 확인해야 합니다.

출시 전에 반드시 확인할 실전 체크포인트

마지막으로, WebXR 프로젝트를 공개하기 전에는 아래 항목을 꼭 직접 확인해 보길 권합니다.

  • HTTPS 환경에서 정상 진입하는가1012

  • isSessionSupported()로 모드별 지원 여부를 확인하는가12

  • 세션 진입이 사용자 제스처 안에서 호출되는가12

  • 프레임 저하 없이 안정적으로 유지되는가124

  • 모델, 텍스처, 조명, 그림자가 목표 기기 기준으로 가벼운가235

  • 컨트롤러, 터치, 시선 등 입력 차이를 고려했는가89

  • AR/VR 미지원 환경에서 대체 화면을 제공하는가1011

  • 세션 종료 후 재진입 시 상태가 깨끗하게 초기화되는가1215

  • 권한 거부 시 사용자에게 이해 가능한 안내를 제공하는가1216

이 체크리스트를 통과하지 못했다면, 기능을 더 추가하기보다 먼저 다듬는 편이 좋습니다. XR에서는 작은 불편 하나가 전체 인상을 무너뜨리기 때문입니다.

결국 중요한 것은 "배려된 경험"이다

WebXR 개발은 단순히 3D를 브라우저에 띄우는 일이 아닙니다. 사용자의 머리 움직임, 손 입력, 기기 성능, 브라우저 정책, 권한 시스템, 실제 공간까지 함께 다루는 작업입니다. 그래서 좋은 WebXR 개발자는 기능을 많이 넣는 사람이 아니라, 사용자가 헷갈리지 않고 불편하지 않게 경험하도록 만드는 사람에 가깝습니다.

성능을 챙기고, 멀미를 줄이고, 입력 차이를 받아들이고, 지원하지 않는 환경에는 대안을 제공하고, 세션 종료까지 깔끔하게 처리하는 것. 이 모든 것이 모여서 "작동하는 WebXR"이 아니라 "잘 작동하는 WebXR"이 됩니다.

다음 장에서는 이런 원칙들이 실제 서비스나 데모에서 어떻게 살아났는지, 잘 만든 WebXR 사례를 통해 더 구체적으로 살펴보겠습니다.

참고

1MDN WebXR performance guide

2PlayCanvas Optimizing WebXR applications

3Toji.dev WebXR Scene Optimization

4Meta WebXR Performance Optimization

5Mastering WebXR Development

6WebXR Device API specification summary

7pmndrs xr Performance

8MDN Inputs and input sources

9WebXR Input Profiles

10MDN WebXR Device API

11Can I use WebXR

12MDN Starting up and shutting down a WebXR session

13Immersive Web Developer Home

15pmndrs xr issue 490

16Android Developers Develop for the web on Android XR

책 목록

초보자도 쉽게 하는 WebXR 개발: A-Frame부터 Three.js·Babylon.js·React-XR까지 차근차근 배우는 실전 입문

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기