본문 바로가기

Local Oriented/jQuery

고정 width 를 가진 웹페이지, meta viewport 로 모바일 기기별 해상도에 자동 맞추기

요즘 반응형웹이다 적응형웹이다 이슈가 장난 아니네요.

그러나, 둘다 모바일에 최적화 되어 있다고 할 수는 없어요.

요즘 나오는 모바일 기기는 PC 해상도를 상회하지만, 화면폭은 클 수가 없다는 겁니다.. ㅠ.

이럴 바에는 차라리 viewport 를 이용하는 것이 나아 보입니다.

물론, www 용과 mobile 용 웹페이지 2개를 운영해야 하겠지만서도요..

암튼, 어떤 방법이든 장단점이 있으니까요.

 

여기에서는 모바일 홈페이지가 고정폭으로 적용된 웹사이트에서..

어떻게 하면, 해상도가 서로 다른 모바일 디바이스에서 모두 한 방에 정상적으로 보이게 하느냐에 대해 다뤄봅니다.

 

초창기 스마트폰 해상도가, 320 인 시절이 있었지요.

이때 개발된 홈페이지들은 화면폭이 640 pixel 로 세팅되어 있어요.

320 해상도에는 viewport 의 scale 을 0.5 로 해서 기기에 맞춰주는 방식이었습니다.

 

window.screen.width, $(document).width(), 세로모드, 가로모드 등등등등..

별별 내용을 다 해 봤는데.. 기기마다 모두 달라서요.. 포기.

그런데, width=device-width 라는거요.. 이게 어떻게 보면 함정입니다.

모바일 기기가 제공하는 해상도를 모두 수용하라는 거거든요.

그러니까, 가로폭이 일정한 웹페이지에서 매번 scale 을 계산해야 하잖아요.

그런데, width 에 웹페이지 가로폭 수치를 넣어주면 얘기가 달라집니다. 이것이 이번 글의 핵심입니다.

반응형이나 적응형이 아닌 고정폭 웹페이지들의 모바일 거듭나기 주제이기도 합니다. ^^v

 

예를들면, 640 픽셀로 화면을 구성했던 초기 웹페이지의 경우..

viewport 에 width=640 으로 하면, 모바일 기기의 해상도나 화면 사이즈에 상관없이 화면에 꽉차게 웹페이지들이 나오게 됩니다.

놀랍죠..? 아래와 같이 한 번 해 보세요.

<meta name="viewport" content="width=640">

이렇게 해 놓으니까, iOS 나 Android 모두 웹브라우저에서 제대로 작동하네요.

기기를 가로로 누이면 width 값이 바뀌니까, 화면 사이즈에 맞게 웹페이지가 자동으로 확대됩니다.

다시, 기기를 세로로 세우면 줄어든 width 값에 맞게 화면이 자동으로 줄어들어요.. 빙고.

 

걱정인 것은, MS 에서 만든 모바일 기기에서 어떻게 작동할지 모르겠다는 거죠..

제발 MS 야 이번엔 제대로 만들어 다오.. ㅠ.

 

그리고, 화면 확대는 수용해 주어야 겠네요, 아래와 같이.

user-scalable 은 default 가 no 이기 때문에 손으로 확대나 축소를 할 수 없어서,

세로 모드에서는 정상 화면, 가로 모드에선 확대 화면 이렇게 되었겠지만..

user-scalable 을 yes 로 하면 세로 모드나 가로 모드 둘다 사용자가 확대와 축소를 할 수 있지요.

<meta name="viewport" content="width=640, user-scalable=yes">

 

그리고 첨언을 한다면..

user-scalable=yes 인 경우에만 initial-scale, minimum-scale, maximum-scale 등이 작동합니다.

user-scalable=no 인 상태에서 각종 -scale 값을 조정해 봐야 소용 없어요.. ㅋㅋ

 

그런데, 문제도 있어요.. 입력창이 있는 경우, 웹브라우저가 자동으로 확대를 하는데 다시 축소를 해 주지는 않아요.

입력창에 포커스가 될 때, user-scalable=yes 이면 화면이 확대되는데.. 포커스가 해제될 때 자동으로 축소되지 않아서 문제가 된다면..

기본 화면은 user-scalable=no 로 가고, 확대가 필요한 곳만 yes 로 가든지..

아니면 반대로 기본은 확대 가능하게 하고, 입력이 필요한 곳에서만 확대 못하게 하든지..

 

 

 

--------------------------------------------------------

그런데..

하이브리드로 제작된 안드로이드 어플(어플 개발업체가 잘못해서 발생한 것일수도.. 아니면 불운인 건가..?)의 경우..

상기 meta 태그(width=640)가 적용되지 않을수가 있네요.. 그러나 iOS 쪽 어플은 정상 작동하네요.. ㅋㅋ

(2023년 현재 이런 이슈는 더이상 발생하지 않는 것으로 보아 보완이 된듯..)

자바스크립트에서 안드로이드 기기와 안드로이드용 어플인 경우,

화면 사이즈를 구해서 640(웹사이트가 640 픽셀 가로폭인 경우) 으로 나눈 값으로 initial-scale 을 조정하면 됩니다.

그런데, 이리저리 해 보니.. 1000 픽셀이 넘으면 이 값을 4 로 더 나누고, 그 미만이면 2 로 더 나눠야 하더라구요.

루나나 갤럭시 노트4 등과 같이 세로 모드에서 width 가 1000 픽셀이 넘어가는 경우 제대로 작동하게 됩니다.

어플마다 달라지려나..? 아무튼, 테스트 하면서 세팅해야 하겠어요.

잊지 말아야 할 것은, user-scalable=no 이면 각종 scale 수치가 적용되지 않기 때문에,

user-scalable=yes 로 해야 하구요..

기본이 화면 확대/축소가 없는 경우라면 initial-scale, minimum-scale, maximum-scale 값들을 모두 동일하게 주는 겁니다.

기본이 확되/축소가 가능하게 하는 경우라면 각 scale 값들을 배율에 맞게 세팅하면 되구요.

이 때, 자바스크립트에 화면 사이즈 기준으로 작성한 비율을 사용하는 겁니다.

initial-scale=1, minimum-scale=0.5, maximum-scale=3 이라고 하면,

width 에 적용된 device-width 를 1로 보고 세팅하기 때문에 웹페이지가 화면에 꽉차게 나오지 않게 되겠죠.

그리고, 아래 코드는 viewport 메타 태그를 찾아서 넣는 것이기 때문에 html head 부분에 viewport 메타 태그가 이미 있어요 하고요.

head 와 자바스크립트에서 세팅하는 값이 서로 다르면 화면이 확대나 축소되었다가 꽉 차게 바뀌니까..

처음 화면이 열릴 때는 확대되었다가 조금 지나서 다시 화면에 맞춰서 줄어드는 현상을 없애려면..

처음 해당 페이지가 열릴 때 쿠키에 값을 넣고, 이후 .jsp 가 로딩될 때 쿠키값을 읽어서 적용하면 됩니다.

 

대충 아래와 같은 코드 정도.. 이건, iOS 쪽은 할 필요 없고, 안드로이드도 웹브라우저에서는 적용할 필요가 없어요.

문제가 된 안드로이드용 어플에서만 $(document).width() 를 사용하기도 하는데, 약간 다른 듯..

var w = Number(window.orientation == 0 ? screen.width : screen.height); // orientation 이 0 이면 세로 모드, 아니면 가로 모드

var dpr = window.devicePixelRatio; // 픽셀비를 별도 계산해야 할 수도 있으니까 참고

//w = w * dpr; // 필요시에만.. iOS 에서도 이걸 해야 하는데, 안드로이드 어플은 신기하게도 할 필요가 없네요. 기기마다 다른지도..

if(w>1000) is = parseInt(w /640 /4 *10) /10; // 10 배로 하여 int 형으로 변환하고 다시 10 로 나누면 소숫점 1째 자리까지 나옵니다.

else is = parseInt(w /640 /2 *10) /10;

var ms = parseInt(is *3 *10) /10; // 자바스크립트에 버그가 있나 봐요.. 그래서 보정하기 위해 이렇게 코드가 복잡해짐

setCookie('s_is',is,4380); // 쿠키에 세팅하면 .jsp 로딩시 쿠키값을 읽어서 바로 적용할 수 있으니까,  

setCookie('s_ms',ms,4380); // setCookie() 함수는 내가 만든 사용자 정의 함수에요. ^^; 아무거나 쿠키값 저장하는 걸 사용하면 됩니다.

$(document.getElementsByName('viewport')).attr('content',
'minimum-scale='+is+', initial-scale='+is+', maximum-scale='+is+', width=device-width, user-scalable=yes');

 

 

 

--------------------------------------------------------

그러고 보니.. 또 문제가 있네요.

www.opensymphony.com 의 sitemesh 로 웹사이트가 구현된 경우..

그리고, 안드로이드 어플(이건, 어플 개발업체가 잘못해서 발생한 것일수도..)에..

특정 안드로이드 기기의 조합에서는 상기와 같이 하면 대략 난감해져요. 화면이 처음 로딩될 때 확대되더라구요.

이것도 물론.. iOS 쪽에선 웹브라우저나 하이브리드로 만든 어플에서는 정상 작동하고,

Android 쪽에선 웹브라우저나 하이브리드로 만든 어플도 대부분의 모바일 기기에선 정상 작동합니다.

일부(?) 모바일 기기에서 오동작 하는거죠.

 

이유는 sitemesh 에서 html 태그와 meta 태그들을 사용했는데,

사용자 PC 에 다운로드 하여 sitemesh 를 렌더링 한 다음에, 다시 본문을 렌더링 해서 붙이는가 봐요.

본문이 들어가면서 다시 viewport 가 흔들리니까 처음 로딩된 결과가 확대되어 버리네요.

sitemesh 의 meta viewport 에 적용한 값이 반영되지 않아요.

그리고, html head 부분에 적용된 viewport 세팅과 동일하게 자바스크립트에서 재세팅 하는 경우..

동일한 내용을 왜 반영하라고 하냐면서 적용해 주지 않으니까.. scale 값을 바꾸어야 합니다.

기존 값에 0.00001 과 같이 거의 흔적도 없는 수치를 더해주면,

수치가 바뀌긴 하니까 의도되지 않은 확대/축소 현상이 발생하지 않아요.

갤럭시 윈이나, 갤럭시 S3 등이 이런 경우에 해당합니다. ㅠ.

 

 

 

다시 정리를 하자면..

1. iOS 웹브라우저, Android 웹브라우저, iOS 하이브리드 어플 등을 위해서, 아래와 같이 세팅 (기본 세팅)

   width=640, user-scalable=no

2. Android 하이브리드 어플만을 위해서, 아래와 같이 세팅 (오류가 나는 어플이라면 이렇구요..)

   자바스크립트에서 screen.width 추출해서 640 과 화면 사이즈에 맞게 2나 4로 나누고 소수 첫째 자리까지 각 scale 에 세팅

   자바스크립트에선 쿠키에 값을 담고, 다음번 화면 로딩시 .jsp 가 쿠키값을 읽어와서 세팅

   initial-scale, minimum-scale, maximum-scale 수치를 모두 동일하게 하고, width=device-widh, user-scalable=yes

3. 상기 1은 쿠키값이 없고 상기 2는 쿠키값이 있어요.

   .jsp 로딩시 자바스크립트가 아니라 .jsp 에서 쿠키값을 읽어서,

   값이 없으면 상기 1 을 기본 세팅으로, 값이 있으면 상기 2 를 .jsp 에서 최초 viewport 세팅시 처리

4. sitemesh 와 일부 안드로이드 기기를 위해서, 아래와 같이 세팅

   sitemesh 로 세팅되는 부분과 아닌 부분이 모바일 기기에 다운로드 된 다음에 기기에 따라 두 번 세팅되기 때문에,

   $(document).ready() 에 각 scale 값을 모두 동일하게 하되, maximum-scale 만 0.00001 값을 기존값에 추가하여 적용

5. 기본은 확대 불가하게 하고, 필요시 확대 가능하게 하기 위해서 아래와 같이 세팅

   상기 1에 대해서 기본 세팅값을 불러오고 user-scalable=yes 로만 변경,

   상기 2와 3에 대해서 기본 세팅값을 불러오고 maximum-scale 수치만 변경

 

 

 

-------------------------------------------------

오, 이런 된장.. 그러나.. 문제가 있네요.

어떤 분이 안드로이드 기기의 Naver 어플에서는 화면이 확대되어 뜬다고, 매번 화면을 줄이는 것이 힘들다 하시네요.

역시나, 애플 기기에서는 Naver 어플에서도 상기 1번으로 정상 작동.. 과연 안드로이드는 iOS 의 짝퉁..?

이것저것 확인해 보니.. OS 버전에 따라 설치되는 Naver 어플 버전이 따로 있는 것인지 의심이 드네요.

userAgent 를 찍어 보면..

모바일 기기 안드로이드 OS 버전이 4.1.2 일 때 구글 플레이에서 설치되는 Naver 버전은 AppleWebKit/534.30,

OS 가 4.4.2 인 경우에는 구글 플레이서 Naver 를 검색해서 설치했을 때 applewebkit/537.36 이네요.

결국 534.30 applewebkit 에 문제가 있다는 이야기.. ㅋㅋ

상기 문제가 되었던 어플도 534.30 버전으로 찍히네요. 이거 말고도 문제가 있는 버전이 여럿 있을듯..

단종된 iOS 5.x 대의 AppleWebKit 버전도, 문제가 되는 534.30 보다는 높은 것을 알 수 있었어요.

그런데, 진짜 웃기죠..? Naver 어플이고 둘다 최종 버전이라 찍히는데, useragent 를 찍어보면 OS 버전에 따라 applewebkit 버전이 달라요.

혹시나, AppleWebKit 이라는 useragent 가 찍히는 정보를 OS 에서 가져오기 때문인지도..

웹뷰를 구현하는 엔진을 OS 에서 API 로 제공하는 것으로 보이네요..

 

iOS 쪽도 마찬가지.. 예전에 모 어플을 개발하다 스토어에는 올렸는데 sale 상태가 아닌 걸로 세팅했거든요.

그런데, 그 다음에 새로운 버전을 개발해서 올렸더니..

iOS 버전이 낮은 기기에서는 예전에 개발하다 망친 어플, 지금은 sale 상태가 분명히 아님에도 그걸 설치하더라구요.

애플 앱스토어랑 구글 플레이랑, 그리고 OS 나 그 버전 별로 각각의 특색이 있네요.

 

 

--------------------------------------------------------------

갤럭시 S1 은 AppleWebKit 533.1 인데.. 여기서도 화면이 최초 로딩시 확대되네요.

그러면, AppleWebKit/533.1 과 AppleWebKit/534.30 이렇게 2 종에 대한 조치를 해 주면 되겠네요.

위에서 설명했던 그 어플도 534.30 으로 찍히는 걸로 보이구요.

그런데, 또 웃기는 것은 롤리팝으로 올린 넥서스7 에서는 문제가 되었던 어플도 534.30 으로는 찍히지 않아요.

그런데도 화면이 확대되죠. 결국.. 문제가 있는 어플과, 533.1, 534.30 AppleWebKit 버전 등 이렇게 3개만 예외처리를 하면 되는 거네요.

앞으로 더 발견되면 이곳에 추가하겠습니다.. ^^;

외주로 개발된 어플이든, Naver 나 Daum 검색앱이든 어떤 브라우저든.. 암튼, WebView 를 사용하는 프로그램이..

Web Redering 엔진을 OS 에서 가져오느냐 자체적으로 구현하느냐, 뭐 어떤 조합으로든 서로 영향을 주는 아주아주 복잡한 관계.

이것이 Android 의 현실이에요. iOS 는 애플 맘대로 한 번에 확 바꿀 수 있지만, Android 는 구글의 손을 얼만큼은 떠나 있다는거..

 

 

.Fine.