몰입형 전체 화면 웹사이트와 애플리케이션을 쉽게 만들 수 있지만 웹상의 다른 기술과 마찬가지로 이를 실행하는 방법은 여러 가지가 있습니다. 전체 화면을 실행하는 '설치된 웹 앱' 환경을 지원하는 브라우저가 늘어나고 있는 요즘에는 이 점이 특히 중요합니다.
앱 또는 사이트를 전체 화면으로 구현
사용자 또는 개발자가 웹 앱 전체 화면을 구현하는 방법은 여러 가지가 있습니다.
- 사용자 동작에 응답하여 브라우저에 전체 화면 요청
- 홈 화면에 앱 설치
- 주소 표시줄을 자동으로 숨겨서 가상으로 전체 화면 구성
사용자 동작에 응답하여 브라우저에 전체 화면 요청
플랫폼은 동일하지 않습니다. iOS Safari에는 전체 화면 API가 없지만 Android의 Chrome, Firefox, IE 11 이상에는 있습니다. 빌드하는 대부분의 애플리케이션은 전체 화면 사양에서 제공하는 JS API와 CSS 선택기를 함께 사용합니다. 전체 화면 환경을 빌드할 때 주의해야 할 주요 JS API는 다음과 같습니다.
element.requestFullscreen()
: (현재 Chrome, Firefox, IE에서 프리픽스됨) 전체 화면 모드에서 요소를 표시합니다.document.exitFullscreen()
: (현재 Chrome, Firefox 및 IE에서 프리픽스됨. Firefox는cancelFullScreen()
사용) 전체 화면 모드를 취소합니다.document.fullscreenElement
: (현재 Chrome, Firefox, IE에서 프리픽스됨) 전체 화면 모드인 요소가 있으면 true를 반환합니다.
앱이 전체 화면이 되면 브라우저의 UI 컨트롤을 더 이상 사용할 수 없게 됩니다. 이로 인해 사용자가 여러분의 환경과 상호작용하는 방식이 변경됩니다. 앞으로, 뒤로 등과 같은 표준 탐색 컨트롤이 없고 탈출 수단인 새로고침 버튼도 없습니다. 이 시나리오를 수용하는 것이 중요합니다. 몇 가지 CSS 선택기를 사용하여 브라우저가 전체 화면 모드로 진입할 때 사이트 스타일과 표현을 변경할 수 있습니다.
<button id="goFS">Go fullscreen</button>
<script>
var goFS = document.getElementById('goFS');
goFS.addEventListener(
'click',
function () {
document.body.requestFullscreen();
},
false,
);
</script>
위의 예시는 공급업체 접두사 사용과 관련된 모든 복잡한 내용을 감추었기 때문에 다소 부자연스럽습니다.
실제 코드는 훨씬 더 복잡합니다. 전체 화면 전환에 사용할 수 있는 매우 유용한 스크립트를 Mozilla에서 만들었습니다. 보다시피 공급업체 프리픽스 상황에서는 지정된 API에 비해 코드가 복잡하고 느려집니다. 아래와 같이 코드를 단순화하더라도 여전히 복잡합니다.
function toggleFullScreen() {
var doc = window.document;
var docEl = doc.documentElement;
var requestFullScreen =
docEl.requestFullscreen ||
docEl.mozRequestFullScreen ||
docEl.webkitRequestFullScreen ||
docEl.msRequestFullscreen;
var cancelFullScreen =
doc.exitFullscreen ||
doc.mozCancelFullScreen ||
doc.webkitExitFullscreen ||
doc.msExitFullscreen;
if (
!doc.fullscreenElement &&
!doc.mozFullScreenElement &&
!doc.webkitFullscreenElement &&
!doc.msFullscreenElement
) {
requestFullScreen.call(docEl);
} else {
cancelFullScreen.call(doc);
}
}
우리 웹 개발자들은 복잡한 것을 싫어합니다. 사용할 만한 멋진 고수준 추상 API는 Sindre Sorhus의 Screenfull.js 모듈입니다. 이 모듈은 약간 차이가 있는 JS API와 공급업체 접두사를 하나의 일관된 API로 통합합니다.
Fullscreen API 팁
문서를 전체 화면으로 구현
본문 요소를 전체 화면으로 구현하는 것이 당연하다고 생각할 수 있지만, WebKit 또는 Blink 기반 렌더링 엔진을 사용하는 경우 본문 너비가 촤대한 작은 크기로 줄어들고 그 안에 모든 콘텐츠가 들어가는 이상한 현상을 보게 될 것입니다. (Mozilla Gecko는 괜찮습니다.)
이 문제를 해결하려면 본문 요소 대신 문서 요소를 사용해야 합니다.
document.documentElement.requestFullscreen();
동영상 요소를 전체 화면으로 구현
동영상 요소를 전체 화면으로 구현하는 과정은 다른 요소를 전체 화면으로 구현하는 방법과 정확히 같습니다. 동영상 요소에서 requestFullscreen
메서드를 호출합니다.
<video id="videoElement"></video>
<button id="goFS">Go Fullscreen</button>
<script>
var goFS = document.getElementById('goFS');
goFS.addEventListener(
'click',
function () {
var videoElement = document.getElementById('videoElement');
videoElement.requestFullscreen();
},
false,
);
</script>
<video>
요소에 컨트롤 속성이 정의되지 않았다면 전체 화면일 때 사용자가 동영상을 제어할 방법이 없습니다. 이를 위한 권장 방법은 동영상을 래핑하는 기본 컨테이너와 사용자에게 표시할 컨트롤을 갖는 것입니다.
<div id="container">
<video></video>
<div>
<button>Play</button>
<button>Stop</button>
<button id="goFS">Go fullscreen</button>
</div>
</div>
<script>
var goFS = document.getElementById('goFS');
goFS.addEventListener(
'click',
function () {
var container = document.getElementById('container');
container.requestFullscreen();
},
false,
);
</script>
이렇게 하면 컨테이너 객체를 CSS 의사 선택기와 결합할 수 있기 때문에 유연성이 높아집니다 (예: 'goFS' 버튼 숨기기).
<style>
#goFS:-webkit-full-screen #goFS {
display: none;
}
#goFS:-moz-full-screen #goFS {
display: none;
}
#goFS:-ms-fullscreen #goFS {
display: none;
}
#goFS:fullscreen #goFS {
display: none;
}
</style>
이러한 패턴을 사용하면 전체 화면이 실행되는 시기를 감지하고 사용자 인터페이스를 적절히 수정할 수 있습니다. 예를 들어 다음과 같은 방법을 사용합니다.
- 시작 페이지로 돌아가는 링크 제공
- 대화상자를 닫거나 되돌아가는 메커니즘 제공
홈 화면에서 페이지 전체 화면 시작
사용자가 웹페이지로 이동할 때 전체 화면 웹페이지를 실행할 수는 없습니다. 브라우저 공급업체는 모든 페이지 로드 시 전체 화면 환경이 큰 불편을 끼친다는 사실을 잘 알고 있으므로 전체 화면으로 전환하려면 사용자 동작이 필요합니다. 공급업체는 사용자가 앱을 '설치'하도록 허용하며, 설치 작업은 사용자가 플랫폼에서 앱으로 실행하려는 것임을 운영체제에 알리는 신호입니다.
주요 모바일 플랫폼에서는 다음과 같이 메타 태그나 매니페스트 파일을 사용한 구현이 매우 쉽습니다.
iOS
iPhone이 출시된 이후로 사용자는 웹 앱을 홈 화면에 설치하고 전체 화면 웹 앱으로 실행할 수 있게 되었습니다.
<meta name="apple-mobile-web-app-capable" content="yes" />
content가 yes로 설정되어 있으면 웹 애플리케이션이 전체 화면 모드에서 실행됩니다. 그렇지 않으면 이 모드에서 실행되지 않습니다. 기본 동작은 Safari를 사용하여 웹 콘텐츠를 표시하는 것입니다. window.navigator.standalone 읽기 전용 부울 자바스크립트 속성을 사용하면 웹페이지가 전체 화면으로 표시되는지 확인할 수 있습니다.
Apple
Android용 Chrome
최근 Chrome팀은 사용자가 홈 화면에 앱을 추가하면 페이지를 전체 화면으로 실행하라고 브라우저에 알리는 기능을 구현했습니다. 이는 iOS Safari 모델과 유사합니다.
<meta name="mobile-web-app-capable" content="yes" />
애플리케이션 바로가기 아이콘을 기기의 홈 화면에 추가하고 Android용 Chrome의 'Add to Home screen'(홈 화면에 추가) 메뉴 항목을 사용하여 앱을 전체 화면 '앱 모드'로 실행하도록 웹 앱을 설정할 수 있습니다.
Chrome
이보다 더 좋은 방법은 웹 앱 매니페스트를 사용하는 것입니다.
웹 앱 매니페스트 (Chrome, Opera, Firefox, Samsung)
웹 애플리케이션 매니페스트는 사용자가 앱을 볼 것으로 예상되는 영역 (예: 모바일 홈 화면)에 앱을 표시하는 방식을 개발자가 제어하고, 사용자가 실행할 수 있는 항목을 지시하고, 더 중요한 것은 사용자가 앱을 실행하는 방식을 지시할 수 있는 단순한 JSON 파일입니다. 미래에 매니페스트는 앱에 대한 더 세밀한 제어 기능을 제공할 것이지만, 현재로서는 앱 실행 방식에만 집중합니다. 특히 다음에 주의해야 합니다.
- 브라우저에 매니페스트 정보 전달
- 실행 방법 설명
매니페스트를 생성하고 사이트에 호스팅한 후에는 다음과 같이 앱을 포함하는 모든 페이지에 링크 태그를 추가하는 작업만 수행하면 됩니다.
<link rel="manifest" href="/manifest.json" />
Chrome은 Android용 버전 38 (2014년 10월)부터 매니페스트를 지원했으며, 이를 통해 웹 앱이 홈 화면에 설치될 때 표시되는 방식 (short_name
, name
, icons
속성 사용)과 사용자가 실행 아이콘을 클릭할 때 실행되는 방식 (start_url
, display
, orientation
사용)을 제어할 수 있습니다.
다음은 예시 매니페스트입니다. 이 예시는 매니페스트에 포함할 수 있는 모든 것을 보여주지는 않습니다.
{
"short_name": "Kinlan's Amaze App",
"name": "Kinlan's Amazing Application ++",
"icons": [
{
"src": "launcher-icon-4x.png",
"sizes": "192x192",
"type": "image/png"
}
],
"start_url": "/index.html",
"display": "standalone",
"orientation": "landscape"
}
이 기능은 완전히 점진적이며, 이 기능을 지원하는 브라우저 사용자를 위해 더욱 개선되고 통합된 환경을 개발할 수 있습니다.
사용자가 사이트나 앱을 홈 화면에 추가하는 것은 앱처럼 취급하겠다는 사용자의 의도를 나타냅니다. 즉, 사용자를 제품 방문 페이지가 아니라 앱의 기능으로 안내하는 것을 목표로 삼아야 합니다. 예를 들어 사용자가 앱에 로그인해야 한다면 이 페이지를 시작 페이지로 삼는 것이 좋습니다.
유틸리티 앱
대부분의 유틸리티 앱은 이 기능을 바로 활용할 수 있습니다. 이러한 앱은 모바일 플랫폼의 다른 모든 앱과 마찬가지로 독립적으로 실행되기를 바랄 것입니다. 앱을 독립적으로 실행하려면 다음 내용을 웹 앱 매니페스트에 추가하세요.
"display": "standalone"
게임
대부분의 게임도 매니페스트를 바로 활용할 수 있습니다. 대다수 게임은 전체 화면으로 실행하고 특정 방향을 강제로 지정하고자 할 것입니다.
수직 스크롤러를 개발하거나 Flappy Birds와 같은 게임을 개발 중이라면 게임을 항상 세로 모드로 유지시켜야 합니다.
"display": "fullscreen",
"orientation": "portrait"
반면 퍼즐 게임이나 X-Com과 같은 게임을 개발 중이라면 게임을 항상 가로 방향으로 사용하기를 원할 것입니다.
"display": "fullscreen",
"orientation": "landscape"
뉴스 사이트
대부분의 경우 뉴스 사이트는 순수한 콘텐츠 기반 환경입니다. 대부분의 개발자는 뉴스 사이트에 매니페스트를 추가하려고 생각하지 않습니다. 매니페스트를 사용하면 실행할 페이지 (뉴스 사이트의 1면)와 실행 방법 (전체 화면 또는 일반 브라우저 탭)을 정의할 수 있습니다.
선택은 여러분 자신에 달려 있습니다. 또한 여러분이 생각하는 사용자가 원하는 액세스 방식에도 영향을 받습니다. 여러분의 사이트가 다른 사이트와 같은 모든 브라우저 chrome 요소를 갖도록 하려면 디스플레이를 browser
로 설정하면 됩니다.
"display": "browser"
여러분의 뉴스 사이트에 뉴스 중심적인 앱 느낌을 주기 위해 앱처럼 취급하고 UI에서 모든 웹과 유사한 chrome을 제거하고 싶다면 디스플레이를 standalone
로 설정하세요.
"display": "standalone"
주소 표시줄을 자동으로 숨겨서 가상으로 전체 화면 구성
다음과 같이 주소 표시줄을 자동으로 숨겨서 '가짜 전체 화면'을 만들 수 있습니다.
window.scrollTo(0, 1);
방법은 상당히 간단합니다. 페이지가 로드되고 브라우저 메뉴에게 사라지라고 지시합니다. 안타깝게도 이 방법은 표준이 아니고 지원되지 않는 곳도 많습니다. 여러 가지 문제도 해결해야 합니다.
예를 들어 사용자가 페이지로 돌아가면 브라우저가 해당 페이지의 위치를 복구하는 경우가 많습니다. window.scrollTo
를 사용하면 이 설정이 재정의되므로 사용자에게 불편을 끼칩니다. 이 문제를 해결하려면 localStorage에 마지막 위치를 저장하고 돌발 상황을 처리해야 합니다 (예: 사용자가 여러 창에서 페이지를 열었을 경우).
UX 가이드라인
전체 화면을 사용하는 사이트를 구축하고 있을 경우 사용자가 좋아하는 서비스를 구현하려면 알아두어야 할 잠재적 사용자 환경 변경 사항이 여러 가지 있습니다.
내비게이션 컨트롤에 의존하지 마세요.
iOS에는 하드웨어 뒤로 버튼이나 새로고침 동작이 없습니다. 그러므로 사용자가 갇히지 않고 앱을 탐색할 수 있게 해야 합니다.
모든 주요 플랫폼에서 전체 화면 모드로 실행되는지 설치 모드로 실행되는지 쉽게 탐지할 수 있어야 합니다.
iOS
iOS에서는 navigator.standalone
부울을 사용하여 사용자가 홈 화면에서 실행했는지 알 수 있습니다.
if (navigator.standalone == true) {
// My app is installed and therefore fullscreen
}
웹 앱 매니페스트 (Chrome, Opera, Samsung)
설치된 앱으로 실행하면 Chrome은 실제 전체 화면 환경으로 실행되지 않으므로 document.fullscreenElement
는 null을 반환하고 CSS 선택기가 작동하지 않습니다.
사용자가 사이트에서 동작을 통해 전체 화면을 요청하면 표준 Fullscreen API를 사용할 수 있습니다. 예를 들어, 다음과 같이 전체 화면 상태에 반응하도록 UI를 변경할 수 있는 CSS 의사 선택기 등이 있습니다.
selector:-webkit-full-screen {
display: block; // displays the element only when in fullscreen
}
selector {
display: none; // hides the element when not in fullscreen mode
}
사용자가 홈 화면에서 사이트를 실행하면 display-mode
미디어 쿼리가 웹 앱 매니페스트에 정의된 내용으로 설정됩니다. 순수 전체 화면의 경우 다음과 같습니다.
@media (display-mode: fullscreen) {
}
사용자가 독립형 모드로 애플리케이션을 실행하면 display-mode
미디어 쿼리는 standalone
이 됩니다.
@media (display-mode: standalone) {
}
Firefox
사용자가 사이트를 통해 전체 화면을 요청하거나 전체 화면 모드에서 앱을 실행하면 표준 Fullscreen API를 사용할 수 있습니다. 예를 들어, 다음과 같이 전체 화면 상태에 반응하도록 UI를 변경할 수 있는 CSS 의사 선택기 등이 있습니다.
selector:-moz-full-screen {
display: block; // hides the element when not in fullscreen mode
}
selector {
display: none; // hides the element when not in fullscreen mode
}
Internet Explorer
IE에서 CSS 의사 클래스에 하이픈이 들어가지 않는 것을 제외하면 Chrome 및 Firefox와 유사하게 동작합니다.
selector:-ms-fullscreen {
display: block;
}
selector {
display: none; // hides the element when not in fullscreen mode
}
사양
사양의 철자는 IE가 사용하는 구문과 일치합니다.
selector:fullscreen {
display: block;
}
selector {
display: none; // hides the element when not in fullscreen mode
}
사용자를 전체 화면에 고정
Fullscreen API는 때로 세심한 주의가 필요합니다. 브라우저 공급업체는 사용자를 전체 화면 페이지에 가두고 싶어 하지 않으므로 최대한 빨리 전체 화면에서 벗어나는 메커니즘을 개발했습니다. 즉, 여러 페이지에 걸친 전체 화면 웹사이트를 빌드할 수 없다는 뜻입니다.
window.location = "http://example.com"
를 사용하여 URL을 자동 변경하면 전체 화면에서 빠져나옵니다.- 사용자가 페이지 안의 외부 링크를 클릭해도 전체 화면이 종료됩니다.
navigator.pushState
API를 통해 URL을 변경해도 전체 화면 환경에서 빠져나옵니다.
사용자를 전체 화면에 고정하고 싶다면 두 가지 옵션이 있습니다.
- 설치 가능한 웹 앱 메커니즘을 사용하여 전체 화면을 실행합니다.
- # 프래그먼트를 사용하여 UI와 앱 상태를 관리합니다.
# 문법을 사용하여 URL을 업데이트하고 (window.location = "#somestate") window.onhashchange
이벤트를 리슨하면 브라우저 자체의 기록 스택을 사용하여 애플리케이션 상태의 변경사항을 관리하거나 사용자가 하드웨어 뒤로 버튼을 사용하도록 허용하거나 다음과 같이 history API를 사용하여 간단한 프로그래매틱 뒤로 버튼 환경을 제공할 수 있습니다.
window.history.go(-1);
전체 화면으로 이동 시 사용자에게 선택권 부여
사용자가 가장 크게 짜증을 느끼는 순간은 웹사이트가 예상치 못한 동작을 하는 때입니다. 사용자가 여러분의 사이트로 이동할 때 속임수로 전체 화면으로 안내하려고 하지 마세요.
첫 번째 터치 이벤트에 개입해서 requestFullscreen()
을 호출하지 마세요.
- 짜증이 납니다.
- 나중에 언젠가 브라우저에서 앱을 전체 화면으로 바꿀지 묻는 메시지를 사용자에게 표시할 수도 있습니다.
앱을 전체 화면으로 실행하고 싶다면 각 플랫폼의 설치 경험을 활용해 보세요.
앱을 홈 화면에 설치하라는 스팸을 사용자에게 보내지 마세요
설치된 앱 메커니즘을 통해 전체 화면 환경을 제공하고 싶다면 사용자를 배려하세요.
- 신중하게 행동해야 합니다. 배너나 바닥글을 사용하여 앱을 설치할 수 있다고 사용자에게 알리세요.
- 사용자가 프롬프트를 닫으면 다시 표시하지 마세요.
- 사용자가 처음 방문했을 때는 여러분의 서비스에 만족하지 않는다면 앱을 설치하려고 할 가능성이 낮습니다. 사이트에서 긍정적인 상호작용을 한 후에 사용자에게 설치 메시지를 보여주세요.
- 사용자가 여러분의 사이트를 정기적으로 방문하고 앱을 설치하지 않는다면 향후 앱을 설치할 가능성이 낮습니다. 계속 스팸을 보내지 마세요.
결론
완벽히 표준화되어 구현된 API가 있는 것은 아니지만 이 문서에 나온 지침을 활용하면 클라이언트와 관계없이 사용자의 화면 전체를 활용하는 환경을 쉽게 빌드할 수 있습니다.