안녕하세요. 어제에 이어 두 번째 포스팅이네요.

제가 요즘 하고 있는 프로젝트는 '하이브리드앱' 제작 관련 프로젝트입니다.

왠지 하이브리드 하니깐 예전에 무한도전에서 하하가 맡았던 캐릭터가 떠오르기도 하고, 승용차가 떠오르기도 하는데요,

제가 만드는 하이브리드앱은 웹페이지을 앱에 담는것을 기본으로 하되, 웹페이지에서 지원하지 않는 기능들을 Native앱에서 구현하는 형태입니다.

 

이렇게 이야기 하면 감이 안 오실 것 같아서요, 프로젝트 산출물인 앱의 모습을 아래 보여드립니다.

 

<프로젝트의 산출물 중 하나인 뽐뿌 앱 : 윈도우8 앱 다운로드 링크 >

 

네, 기본적으로 화면의 대부분을 차지하는 웹페이지 부분은 Webview라는 컨트롤을 통해 주소만 입력하면 위와 같이 나타나게 됩니다.

상단에는 여러 버튼이 있는 것을 보실 수가 있는데요, 이는 Webview가 아니라 Native App에서 직접 만들어야 하고 버튼을 눌렀을 때의 동작도 지정 해 줘야합니다.

( 버튼을 만드는 방법은 저희팀의 에반젤리스트이신 황리건 차장님이 만들어 놓으신 좋은 강좌가 있어서 참고하시면 좋을 것 같습니다. )

 

가령 'Back' 버튼을 눌렀을 때는 Webview에 나타난 웹페이지가 이전페이지로 이동을 해야겠지요.

미리 공개된 Windows 8.1에서는 Webview control도 그 기능이 좋아져서 Goback() 이라는 메소드가 생겼습니다.

그래서 myWebview.Goback(); 이런식으로 활용하실 수도 있어요. 하지만 Windows 8에서는 다른방법을 사용해야 합니다.

이에 대해서 참 고민+검색+삽질이 많았었는데요, 두 가지 방법으로 해결 할 수 있습니다.

 

첫 번째 방법은 Webview의 InvokeScript 라는 함수를 이용하는 방법입니다.

코드를 공개 드리자면,

        //버튼 클릭시 발생하는 이벤트 핸들러
        private void BackButton_Click_1(object sender, Windows.UI.Xaml.RoutedEventArgs e) 
        {
            WebView.InvokeScript("eval"new[] { "history.go(-1)" });
        }

위 코드는 history.go(-1) 이라는 자바스크립트 명령을 실행하는 코드입니다. 제 프로젝트는 C# / XAML로 되어있는데 자바스크립트를 실행한다는게 재미 있네요.

앞으로 가고 싶은 경우에는  -1을 +1로 바꾸면 아주 잘 됩니다.

 

두 번째 방법은 스택을 활용하여 자체적인 웹브라우징 History를 앱에서 관리하는 방법입니다.

위와 같이 하면 되지 왜 그런 듣기만 해도 싫은 선택을 했냐... 라고 물으실 수 있겠네요...

이유는 첫 번째 방법이 대부분 사이트에서는 잘 되지만 모든 사이트에서 동작하는건 아니기 때문입니다.  ( 실례로 HTML5로 쓰여진 웹페이지로 해보니 동작하지 않더라구요. )

 

구현 방법입니다. 가장 먼저 스택을 두개 만듭니다. 이 스택에는 웹페이지의 URL이 들어갈 것입니다.

private Stack<Uri> backStack = new Stack<Uri>();
private Stack<Uri> forwardStack = new Stack<Uri>();
 

스택에 저장을 하려면 현재 웹페이지의 URL을 알아낼 수 있어야겠지요? 웹 브라우저 처럼 상단에 주소가 나오면 참 좋을 텐데 Webview는 그렇지가 않습니다.

어떻게 하냐면, Webview의 페이지가 모두 로드 되었을 때 발생하는 이벤트를 아래와 같이 XAML에서 만들 수가 있습니다.

<WebView x:Name="WebView" LoadCompleted="WebViewOnLoadCompleted"/>
 

이벤트 만들기 버튼을 누르면 cs파일에 아래와 같은 코드가 생기겠지요. 

private void WebViewOnLoadCompleted(object sender, NavigationEventArgs navigationEventArgs)

{

   backStack.Push(navigationEventArgs.Uri);

}

 

<수정 내용 시작>

 

아시리라 생각되서 생략했습니다만, 좀 더 친절한 포스팅이 되기 위해 적습니다.

위의 WebViewOnLoadCompleted 이벤트는 웹뷰가 모두 로드 되었을 때 발생하는 이벤트를 받아서 동작해야 합니다.

따라서 메인 페이지 어딘가에 아래와 같은 코드를 추가해 주시면 되겠습니다.

WebView.LoadCompleted += WebViewOnLoadCompleted;
 

<수정내용 끝>

 

매개변수로 잡혀 있는 navigationEventArgs가 여러정보를 담고 있는데요, navigationEventArgs.Uri 가 현재 Webview의 URL을 담고 있어서 이를 back 스택에 Push해 둡니다.

웹페이지가 바뀔 때 마다 URL을 저장했으니 이제 뒤로 버튼과 앞으로 버튼을 눌렀을 때의 코드를 보겠습니다.

 

        private void BackButton_Click_1(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
             forwardStack.Push(backStack.Pop());
             WebView.Navigate(backStack.Pop());
        }

현재의 URL은 forward 스택에 넣어두고 그 전의 URL로 이동을 하면 이전 페이지로 이동하는 것이 됩니다.

스택이 비어있을 때는 Pop을 하면 에러가 나므로 버튼을 비활성화 해주는 것이 좋습니다.

 

  private void ForwardButton_Click_1(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            WebView.Navigate(forwardStack.Pop());
        }

 앞으로 버튼을 눌렀을 때는 forward 스택에서 Top 노드를 제거를 해주면서 해당 URL로 이동하면 됩니다.

 

간단할 수 있는 내용인데요 포스팅으로 설명하자니 쉽지가 않네요 (손에 땀이...)

꾸준히 블로깅을 해오신 분들이 벌써 존경스러워 지고 있습니다. :)

 

재밌는 개발 + 삽질이야기가 되었는지 잘 모르겠네요.

혹 문의사항이 있다면 댓글로 남겨 주시면 감사하겠습니다.