[VB.NET] 차근차근 크롬 브라우저 만들기 - 5. 자바스크립트와 통신

2023. 2. 10. 09:00VB.NET/Chrome Browser

[VB.NET] 차근차근 크롬 브라우저 만들기 - 4. 자바스크립트와 통신

지난번 강좌도 그렇고 이게 말로 설명하기가 참 난해하다. 자바스크립트와 통신을 한다? 뭘 위해서? 그러니 하나의 상황을 만들어서 생각해보자. 현재 브라우저가 티스토리에 로그인이 됐는지 여부를 확인해야 하는 상황이 생겼다고 생각해보자. 

로그인 여부 확인에는 간단히 두가지 방법중 하나로 확인이 가능하다. 지난 강좌에서 클릭했던 "시작하기" 버튼이 있으면 로그인 안된거고, 없으면 로그인이 된거다. 혹은, 티스토리 화면 우상단에 로그인한 사용자의 로고이미지가 있고 이걸 클릭해서 div 팝업 맨밑에 "로그아웃" 링크의 유무로 확인해도 된다.

여기서는 두번째 방법을 사용할 예정인데, 이 버튼을 클릭해서 실제 로그아웃 하는건 이전 강좌를 참고해서 자바스크립트를 실행하면 되겠고, 이번 강좌에서는 자바스크립트로 로그인 여부를 확인해서 그 결과를 내 프로젝트에서 받아야 한다. 이렇게 현재 페이지의 상태를 알아내서 적절한 로직을 태우기 위해 반드시 자바스크립트와의 통신이 필요하다.

예를들어, 로그인이 안되어 있으면 로그인을 하도록 분기하고, 되어있으면 글쓰기를 하거나 덧글쓰기를 하도록 분기하면 되는것이다.

각설하고 이제 해당 소스를 구현해보자. 크롬에서 요소검사를 해보면 로그아웃 태그는 <button class="btn_logout">로그아웃</button> 이렇게 되어있다. 페이지내에서 이걸 찾아내서 있으면 로그인이 되어있는 것이고, 없으면 안되어 있는 것이다.

우선 간략히 클래스를 하나 만들자. 기능확인용이니 정말 간략하게 만들자. 클래스명은 ClassJavaScript라고 지정한다. 그전에 프로젝트 전체 모듈에서 사용하도록 ScriptValue 변수를 선언하자. 임의의 모듈을 하나 만들어서 Public으로 선언하면 된다.

Public ScriptValue As String = ""

그다음 만든 클래스다.

Public Class ClassJavaScript
    Public Sub setValue(pValue As String)
        ScriptValue = pValue
    End Sub
End Class

자바스크립트에서 이 클래스의 setValue를 실행해서 ScriptValue라는 전역변수에 자바스크립트의 결과값이 저장되는 구조다. 전역변수를 사용하지 않고, 클래스 멤버변수로 사용해도 되고, 그런식의 변형은 스스로 능력껏 사용하면 되겠다. 여기서는 설명의 편의성을 위해 전역변수로 사용했다.

그다음 Form_Load 이벤트의 Me.Controls.Add(BrowserMain) 바로 위에 아래 소스를 추가하자.

BrowserMain.JavascriptObjectRepository.Settings.LegacyBindingEnabled = True
BrowserMain.JavascriptObjectRepository.Register("bound", New ClassJavaScript(), False, BindingOptions.DefaultBinder)

이런 기능까지도 ChromiumWebBrowser에서 지원해준다. 이 두줄의 의미는 자바스크립트에서 호출했을때 ClassJavaScript 클래스의 함수를 bound라는 이름으로 접근하도록 설정하는 것이다.

디자인모드에서 툴바에 Name - ButtonCheck, Text - &Check, DisplayStyle - Text로 버튼을 하나 추가하고, Timer1으로 타이머도 추가하자. Async 방식으로 값을 받아오기 때문에 동일함수 내에서는 원하는 값을 받지 못하니, 타이머로 한템포 쉬어서 호출한 함수를 빠져나와야 값을 받아올 수 있다.

이제 준비는 끝났다. 로그아웃 버튼 유무를 확인해서 어떻게 프로젝트에 값을 전달하는지 아래 ButtonCheck_Click 이벤트와 Timer1_Tick 이벤트의 소스를 확인하자.

Private Sub ButtonCheck_Click(sender As Object, e As EventArgs) Handles ButtonCheck.Click

    ScriptValue = ""

    Dim script = "var btntag = document.getElementsByTagName('button');"
    script &= "var result = 'false';"
    script &= "for (var i = 0; i < btntag.length; i++)"
    script &= "{"
    script &= "  if (btntag.item(i).className == 'btn_logout')"
    script &= "  {"
    script &= "     result = 'true';"
    script &= "     break;"
    script &= "  }"
    script &= "}; bound.setValue(result);"

    BrowserMain.ExecuteScriptAsync(script)

    Timer1.Interval = 100 : Timer1.Enabled = True

End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick

    Timer1.Interval = 100 : Timer1.Enabled = False

    If ScriptValue = "" Then
        Timer1.Enabled = True : Exit Sub
    End If

    If ScriptValue = "true" Then
        MsgBox("로그인 상태!!!")
    Else
        MsgBox("로그아웃 상태!!!")
    End If

End Sub

소스를 위와같이 만든 후 실행해서 Check 버튼 클릭, 직접 로그인해서 Check 버튼을 다시한번 클릭해보자. 각각 로그인과 로그아웃상태로 나와야 성공

로그아웃&nbsp;상태
로그인 상태

제대로 실행됐나 확인하자. 이제 소스 분석을 차근차근 해보자.

ButtonCheck_Click 함수내에 있는 자바스크립트인 아래 줄에 집중하자.

bound.setValue(result);

이 한줄에 이번 강좌의 모든 내용이 다 들어있다. 여기서 호출한 bound가 저 위에 Form_Load에서 추가한 BrowserMain.JavascriptObjectRepository.Register 함수의 첫번째 파라미터와 동일해야 한다. 즉, 꼭 "bound"라고 쓸 필요는 없고 두개가 동일한 값이면 정상 동작하게 된다.

그리고, 자바스크립트에서 호출한 bound는 우리 프로젝트 내에 있는 ClassJavaScript와 매칭된다. 그래서 이 클래스 내에 있는 setValue라는 함수를 호출하게 되며, 이 함수로 인해 ScriptValue라는 전역변수에 자바스크립트의 "result" 값을 넣어주게 되는 것이다.

이렇게 생성한 자바스크립트를 ChromiumWebBrowser의 ExecuteScriptAsync 함수를 이용해서 페이지에 삽입한 후 결과를 받을 타이머를 켜주면 ButtonCheck_Click 이벤트의 내용은 끝난다.

그다음 타이머 이벤트를 보자. 체크버튼 이벤트에서 초기화한 ScriptValue 라는 전역변수의 값이 변경될때까지 대기한다. 물론 여기에서 대략 3초정도 시간을 정해서 해당시간까지 값이 변하지 않으면 응답을 못받았으니 다른 오류처리를 해줘야 하지만, 이 예제에 해당 내용은 없으니 직접 구현해보자.

그 다음은 ScriptValue의 결과에 따라 로그인 여부의 확인이 가능해진다.

지난강좌를 통해 자바스크립트를 실행하는 방법을 익혔고, 이번 강좌를 통해 자바스크립트에서 값을 받아오는 방법을 익혔으니 이정도 지식만 확실히 내걸로 만들어 놓으면 웬만한 자동프로그램 매크로는 어렵지 않게 만들 수 있을 것이다. 다음강좌에서는 ChromiumWebBrowser를 이용해서 웹페이지 소스를 받아오는 방법에 대해 알아보자.

반응형