본문 바로가기
웹 프론트엔드/HTML | CSS | JS

모바일 웹 : Device Orientation Event란? ( feat: IOS 13+ 이상에서 Device Orientation Event 권한 얻어오기 )

by 번데기 개발자 2022. 10. 12.
반응형

개요

 

Device Orientation 는 모바일 웹에서 기기의 위치나 회전에 대한 값을 얻어올수 있는 이벤트입니다.

 

보통 모바일웹에서 360도 파노라마 이미지를 보여주거나 Aframe과 같은 3D 프레임워크를 웹에서 사용할때 내부적으로 DeviceOrientation 이벤트가 사용되는 것을 알수 있습니다.

 

오늘은 모바일 웹에서 DeviceOrientationEvent 이벤트를 요청하는 방법에 대해 알아보겠습니다.

 

 

 

DeviceOrientation 이란?

 

Device Orientation은 중력을 기준으로 기기의 물리적 방향의 변화(event)를 뜻합니다.

 

즉, Device Orientation은 모바일 웹에서 디바이스의 물리적 방향의 변화를 감지하기 위해 사용됩니다.

 

해당 이벤트를 이용하면 모바일 디바이스를 회전시켰을때 이벤트를 감지하여 적절히 화면을 변화시킬수 있습니다.

 

Device Orientation 의 값을 얻기 위한 이벤트로는 2가지가 있는데요,

 

하나는 DeviceOrentationEvent와 다른 하나는 DeviceMotionEvent 입니다.

 

 

DeviceOrientationEvent

 

DeviceOrientationEvent는 이벤트는 기기 내 가속도센서(Accelerometer sensor) 또는 자이로센서(Gyro sensor) 이용하여 기기의 방향 변화를 감지합니다.

 

값의 종류로는 아래와 같은 값들이 있습니다.

 

  • DeviceOrientationEvent.absolute (IOS Safari X)
  • DeviceOrientationEvent.alpha
  • DeviceOrientationEvent.beta
  • DeviceOrientationEvent.gamma

 

// 기기의 방향 변화를 감지하는 이벤트 리스너
window.addEventListener("deviceorientation", handleOrientation, true);

// 기기의 방향 변화가 감지될 때 실행할 함수
function handleOrientation(event) {
  var absolute = event.absolute;  // 지구좌표계를 사용하는 지에 대한 boolean
  var alpha    = event.alpha;  // z축(0 ~ 360도)
  var beta     = event.beta;  // x축 (-180 ~ 180도)
  var gamma    = event.gamma;  // y축 (-90도 ~ 90도)

  // Do stuff with the new orientation data
}

 

참고 : https://developer.mozilla.org/en-US/docs/Web/API/DeviceOrientationEvent

 

DeviceMotionEvent

 

DeviceMotionEvent는 기기내 가속도센서(Accelerometer sensor) 또는 자이로센서(Gyro sensor) 이용하여 가속도의 변화를 감지합니다.

 

값의 종류로는 아래와 같은 값들이 있습니다.

 

  • DeviceMotionEvent.acceleration
  • DeviceMotionEvent.accelerationIncludingGravity
  • DeviceMotionEvent.rotationRate
  • DeviceMotionEvent.interval
  • DeviceOrientationEvent.absolute

 

window.addEventListener("devicemotion", handleMotion, true);

function(event) handleMotion{
    let acc = event.acceleration.x;  // x 또는 y 또는 z축에 대한 가속도 (단위는 m/s²)
    let aig = event.accelerationIncludingGravity.x;  // x, y, z축에 대한 중력가속도 (단위는 m/s²)
    let rr = event.rotationRate  // 기기 방향 변화에 대한 비율 (초당 각도)
    let interval = event.interval  // 시간 텀을 나타내는 number (milliseconds)
}

 

참고 : https://developer.mozilla.org/en-US/docs/Web/API/DeviceMotionEvent

 

 

Device Orientation 센서 권한 획득

 

Device Orientation 센서 권한 획득에 대해서는 보통 window.addEventListener를 통해 deviceorientation, devicemotion 이벤트를 등록하게 되면 해당 권한을 자동으로 얻어옵니다. 

 

즉 권한에 대한 Trigger가 addEventListener를 통한 이벤트 등록입니다.

 

 

Device Orientation 센서 권한 획득 (  IOS 13+ 이상의 Safari 브라우저 )

 

대부분은 addEventListener를 통해 권한과 센서 데이터를 얻어와서 원하시는 작업을 진행하시면 되는데요, 

 

하지만 특이하게 IOS Safari 13+ 베타버전 이후의 Safari 브라우저에서 권한을 얻어오는 방식이 조금 달라졌습니다.

 

( 보안때문에 그러는것 같은데.. Safari는 항상 뭔가 개발자를 불편하게 하는 것 같습니다... )

 

Safari에서는 IOS Safari 13+ 베타 버전 이후에 requestPermission() 이라는 콜백함수를 추가하였는데요, 기존 방식과는 다르게 requestPermission()을 통해 DeviceMotion 권한을 얻어온뒤 addEventListener만 등록하여야 모션 센서의 데이터를 얻어올수 있습니다. 

 

IOS 13버전 requestPermission

 

RequestPermission으로 권한 얻어오기 코드 실습 (  IOS 13+ 이상의 Safari 브라우저 )

 

DeivceMotionEvent 요청 

/** Safari가 13+ 버전 이상인지 체크 **/
const isSafariOver13 = window.DeviceOrientationEvent !== undefined &&  typeof window.DeviceOrientationEvent.requestPermission === 'function'

const requestPermissionSafari = () => {
  if (isSafariOver13) {
    window.DeviceMotionEvent.requestPermission()
      .then((state) => {
        if (state === 'granted') {
          /** 모션 이벤트 권한 허용을 눌렀을때 **/
          window.addEventListener('devicemotion', () => {});
        } else if (state === 'denied'){
          /** 모션 이벤트 권한 취소를 눌렀을때 **/
          /** Safari 브라우저를 종료하고 다시 접속하도록 유도하는 UX 화면 필요 **/
        }
      })
      .catch(e => {
        console.error(e)
      })
  } else {
    window.addEventListener('devicemotion', () => {});
  }
})

 

DeviceOrientation 요청

/** Safari가 13+ 버전 이상인지 체크 **/
const isSafariOver13 = window.DeviceOrientationEvent !== undefined &&  typeof window.DeviceOrientationEvent.requestPermission === 'function'

const requestPermissionSafari = () => {
  if (isSafariOver13) {
    window.DeviceOrientationEvent.requestPermission()
      .then((state) => {
        if (state === 'granted') {
          /** Orientation 이벤트 권한 허용을 눌렀을때 **/
          window.addEventListener('deviceorientation', () => {});
        } else if (state === 'denied'){
          /** Orientation 이벤트 권한 취소를 눌렀을때 **/
          /** Safari 브라우저를 종료하고 다시 접속하도록 유도하는 UX 화면 필요 **/
        }
      })
      .catch(e => {
        console.error(e)
      })
  } else {
    window.addEventListener('deviceorientation', () => {});
  }
})

 

 

RequestPermission으로 권한 얻어올 때, 대화상자(prompt)를 유저가 닫았을때 예외처리

 

 

 

위 부분에서 하나 주의깊게 알아둬야될 내용은 만약 Safari 브라우저에서 사용자가 모션 센서 권한에 대한 대화상자(prompt)에서 취소 버튼을 눌렀을 때, 다시 권한에 대한 대화상자를 얻어올 방법이 없다는 점입니다.

 

유일한 방법은 Safari 브라우저를 껐다 켜거나 또는 Safari 브라우저의 현재 열려있는 Tab을 껐다 켜는 방법입니다.

 

대화상자를 유저가 닫았을때 해결법

 

How do I get DeviceOrientationEvent and DeviceMotionEvent to work on Safari?

I'm trying to implement DeviceOrientationEvent and DeviceMotionEvent on my website for a 3D effect. However, the console doesn't log any info and apparently iOS 13 requires a user set permission to...

stackoverflow.com

 

 

해당 문제점 때문에 추가적으로 유저가 dialog의 취소(dinied)버튼을 눌렀을때 브라우저를 껐다가 다시 접속하도록 유도하는 UX상의 화면구성이 필요합니다.

 

이를 잘 해결한 업체로 예를 들면 8thwall이라는 WebAR 서비스 회사가 있는데, 기본 브라우저가 제공해주는 Prompt 앞단에 Custom Modal를 하나 더 두어서 유저가 대화상자를 닫았을때 문제를 해결하였습니다.

 

해당 회사는 유저가 모션 센서의 취소버튼을 눌렀을때 아래와 같은 화면을 유저에게 보여줍니다.

 

8thwall 모션센서 처리

 

마무리

 

간단하게 DeviceMotion 에 대해 정리하려고 했던 글이, Safari 13+ 베타버전 이후에 추가된 권한 획득에 대해서도 다루려다보니 글이 엄청 길어진것 같습니다.

 

하지만 정리해놓고 보니 나중에 까먹었을때도 금방 찾아서 기억할수 있어서 좋을 것 같습니다. 헤헤

 

웹 개발은 재밌긴 하지만, 크로스 브라우징 이슈나 이러한 Safari 의 강력한 보안정책이 업데이트 될때마다 대응하는게 무척 까다로운것 같습니다.

 

앞으로도 여러 자주 쓰이는 이벤트나 새롭게 추가된 JS 문법들에 대해 포스팅할 예정입니다.

 

감사합니다.

 

 

참고

 

 
반응형