안드로이드 웹 브릿지 통신 & Clickable SVG

조관희·2024년 9월 4일
0
post-thumbnail

들어가기 앞서

디프만 15기 안드로이드팀에서 야구장 시야 서비스를 제공하는 SPOT 앱에서 야구장 구역을 클릭하고, 줌이 가능하도록 구현해야 했습니다. 네이티브에서 야구장 UI, 거기에다가 구역별로 클릭 이벤트 리스너를 다는 것을 구현하는 것은 복잡한 과정이였습니다.
디자이너의 요청은 아래의 야구장을 확대할 수 있어야 하며, 구역별로 클릭할 수 있는 클릭 리스너를 구현해야했습니다.

위 화면은 디자이너의 요청이였을 뿐 실제로 개발팀원들끼리 논의했을 때는 구현하기 어렵고, 레퍼런스가 없다면 디자인이 바뀌어야하지 않을까? 라는 논의를 했습니다.
하지만 유저에게 야구장 화면이 나오고, 줌인줌아웃하여 블럭들을 클릭할 수 있게 하는 것이 가장 좋을 것 같아 구현하기 위해 많은 레퍼런스를 찾아봤습니다.

실제로 이 화면을 구현하기 위해서 다양한 레퍼런스를 참조해봤습니다.

  • "자리어때" 서비스에서도 야구장 시야를 제공해줍니다. 야구장 화면은 구현되어있는데, 어떻게 그렸는 지 이해하기 위해서 개발자 도구를 열어서 확인해본 결과 SVG 이미지로 되어있었습니다.
  • "인터파크" 예매 서비스도 확인해보면서 좌석 예약 화면은 어떻게 그렸는 지 확인해봤는데, 이 부분은 HTML 태그를 사용해서 UI 를 그려놨습니다.

우선 위 레퍼런스를 참조하면서 네이티브 언어를 사용하는 모바일 환경 안드로이드에서는 UI 구현이 어려울 것 같다는 생각이 들었습니다. 위 레퍼런스는 웹으로 구현되어있었기 때문입니다.

저는 레퍼런스를 찾아보며, 아래와 같이 제 자신에게 질문하며 고민해봤습니다.

  • 웹 개발자는 위 UI를 요청받았을 때, 어떤 고민을 했으며 해결책은 어떤것일까?
  • 실제로 네이티브에서 구현될려면 어떻게 구현하지?
  • 레퍼런스에서 구현해놨는데, 진짜로 구현하지 못하는건가?

그래서 이 화면을 어떻게 구현해야할 줄 모르겠고, 집단 지성으로 해결해보자며 동아리 프론트엔드 톡방에 아래와 같이 구현가능성에 대해서 질문을 해봤습니다.

"저걸 어떻게 다 그리지?", "구현하기 어려울 것 같다" 등등 UI 를 직접 그리기에는 어려울 것 같다는 이야기를 해주었습니다.

하지만 어떤 분께서 Clickable svg map 키워드를 사용하면 구현할 수 있을 것 같다는 의견을 주셨습니다. 실제로 구글링을 해본 결과 다음과 같은 화면을 SVG 이미지로 대체해서 SVG 속성의 id를 설정한 뒤, javascript로 이벤트 로직을 구현하고 css로 스타일을 관리할 수 있었습니다.

또 하나의 문제는 그러면 네이티브 개발도 하면서 웹까지 구현해야하는가...?
구현 난이도와 공수까지 생각했을 때 일정 내에 할 수 없다는 생각이 들었습니다. 그래서 네이티브에서 Clickkable svg map 키워드를 사용한 레퍼런스가 없을 까 찾던 도중에...
IInteractive SVG image in Android app using Kotlin and JavaScript 아티클을 발견했습니다. 제가 찾던 녀석이였습니다. 해당 아티클의 예제 깃허브가 있어서 해당 깃허브 프로젝트를 살펴보았습니다.

직접 웹을 구현하지 않고, SVG 이미지 링크를 가져오고 HTML 코드는 문자열로 하드코딩하여 SVG 이미지 링크를 HTML 문자열에 직접 넣어주고 있었습니다.
그리고 웹뷰로 웹 링크를 load하는 것이 아닌 HTML 문자열을 인코딩하여 웹 링크와 같은 형식으로 loadDataWithBaseURL 함수를 사용하여 웹뷰를 사용할 수 있었습니다.
또한, 로직 구현을 하기 위한 js 코드는 안드로이드의 에셋으로 관리했습니다.

이제는 웹뷰와 통신해야합니다.

브릿지 통신

브릿지 통신은 @JavascriptInterface 어노테이션을 사용해서 웹의 Javscript 와 안드로이드 네이티브 언어와 통신할 수 있는 방법입니다.

@JavascriptInterface

브릿지 통신의 흐름도는 아래의 사진과 같습니다.

안드로이드 브릿지 코드는 아래와 같습니다. 데이터를 받아올 때 아래코드를 사용합니다.

class AndroidBridge(
    private val callback: (sectionId: String) -> Unit
) {
    companion object {
        const val JAVASCRIPT_OBJ = "javascript_obj"
        const val INJECT_STADIUM_BLOCK_NUMBER =
            "javascript: window.androidObj.getStadiumBlockNumber = function(sectionId) { $JAVASCRIPT_OBJ.getStadiumBlockNumber(sectionId) }"
    }

    @JavascriptInterface
    fun getStadiumBlockNumber(sectionId: String) {
        callback(sectionId)
    }
}

javscript 코드에서 네이티브로 보낼 때는 아래와 같이 코드를 작성합니다.

window.androidObj = function AndroidClass() {};

function getStadiumBlockNumber(sectionId) {
    window.androidObj.getStadiumBlockNumber(sectionId)
}

이러한 방식으로 웹뷰에서 안드로이드 네이티브와 웹 JS는 브릿지를 두어서 통신할 수 있습니다.
JS 코드에서 SVG 이미지의 데이터를 파싱하여 적절하게 CSS 스타일을 건들이면 야구장 화면에 대한 이벤트를 구현해볼 수 있을 것 같습니다.

SVG 의 속성 ID 를 가져와라

피그마를 이용해서 SVG를 추출할 수 있습니다.
또한, 피그마를 사용하다보면 도형, 프레임 등 피그마 요소들의 이름을 지어줄 수 있습니다. 그리고 추출 시, id를 추출하겠다고 설정하면 SVG의 각 요소들의 id 속성이 부여되는 것을 알 수 있습니다.

레이어에 아래와 같이 이름을 부여할 수 있습니다. (한글로 설정하면 SVG 속성 id가 깨질 수 있으니 사용하지 말아주세요.)

추출 시, 아래 사진처럼 include "id" attribute 라는 목록을 체크해서 추출하면 id 속성이 들어와 있는 것을 확인할 수 있습니다.

실제로 어떻게 확인하는가? SVG 이미지를 URL로 만들어봐야 합니다.
SVG Share 웹 사이트에서 간단하게 SVG 이미지를 URL로 만들어볼 수 있습니다. 이렇게 URL 을 만들고 개발자 도구를 열어서 속성이 잘 들어왔는 지 확인합니다.

아래 사진을 확인해보면, 요소(태그)별로 id 속성이 부여된 것을 알 수 있습니다.

그렇다는 것은 id를 적절하게 사용해서 Javascript 로직을 작성하고 css 스타일을 부여한다면? 다양한 처리가 가능할 것 같습니다.
딱 기다려라... 야구장 화면...

실제 구현화면

위 문제들을 하나하나 해결하면서 안드로이드가 아닌 아래와 같이 다른 곳(피그마, 웹, SVG 등)에 대한 이해가 필요했었습니다.

배움의 끝은 없고, 이를 통해 하나를 또 알아가는 것 같아 흥미로운 과정이였습니다.

그렇게 결국 태어났습니다. 저의 야구장 화면이...
아래는 디자이너의 요청에 맞게 최종 구현한 화면입니다.

해당 서비스는 디프만 15기 6팀이 진행했으며, 다양한 정보를 확인해보고 싶으시다면, 아래의 링크들을 확인해주세요!
안드로이드 개발자 깃허브 보러가기!
"SPOT! - 내가 만들어가는 야구장 시야 서비스" 플레이스토어에서 다운받기

profile
Allright!

0개의 댓글

관련 채용 정보