Android Daum 우편번호 서비스 API With FireBase Hosting

2024. 1. 4. 01:27·Android

🎉 개요

 프로젝트에서 Kakao MAP API를 사용하기 이전에 지도를 통해 위치 정보를 정확하게 보여주려면 위도와 경도가 필요합니다. 그러기 위해선 오타 등의 이유로 사용자에게 주소를 직접 입력 받는 것 보단 우편번호 API를 사용하는 방식이 더 안전할 것 이라고 생각해 사용하게 되었습니다.

🚨 Warning ! 

  • Node.js는 설치 되었단 가정하에 진행합니다
  • Window 환경에서 진행되었습니다.
  • 이 API는 JS만으로 제공되기 때문에 안드로이드에서 Retrofit 등을 사용해 직접 연동이 불가능합니다.
  • 이를 해결하기 위해 FireBase Host 서비스를 사용해 호스팅한 후 Web View를 통해 보여줄겁니다.
FireBase Hosting이란 ? 
정적 파일(HTML, CSS, JavaScript 등)을 호스팅하고 배포하는 서비스를 말합니다. 
파이어베이스 호스팅을 사용하면 사용자는 서버 셋업 및 유지 관리에 대해 걱정할 필요 없이 손쉽게 웹 앱을 배포할 수 있습니다. 

 

🎉 API 연동

https://console.firebase.google.com/

✅  파이어 베이스에 접속해 로그인 후 프로젝트를 생성해 줍니다.

✅ 왼쪽 메뉴에서 Hosting을 선택 해줍니다.

 

✅ CLI 설치 코드를 복사해줍니다

✅ 원하는 위치에 작업용 폴더를 하나 생성합니다.

✅ cmd창을 열고 해당 폴더 위치로 이동 후 CLI 코드를 입력해 설치합니다.

//폴더 이동 명령어
cd 
// CLI 설치
npm install -g firebase-tools

✅ 아래와 같이 설치가 완료 되었다면 아래와 같이 진행해줍니다.

$ firebase login // 새 창이 뜸
// init 을 입력하면 yes > Hosting : Configure files 
// for Firebase Hosting and (optionally) set up Github Action deploys 선택
$ firebase init

✅ public 폴더에 있는 index.html을 수정 후 deploy 합니다.

 firebase deploy
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<!-- HELLO DAUM! -->

<!-- iOS에서는 position:fixed 버그가 있음, 적용하는 사이트에 맞게 position:absolute 등을 이용하여 top,left값 조정 필요 -->
<div id="layer" style="display:block;position:fixed;overflow:hidden;z-index:1;-webkit-overflow-scrolling:touch;">

</div>


<script src="https://t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
<!-- <script src="http://dmaps.daum.net/map_js_init/postcode.v2.js"></script> -->
<script>


window.addEventListener("message", onReceivedPostMessage, false);

function onReceivedPostMessage(event){
    //..ex deconstruct event into action & params
    var action = event.data.action;
    var params = event.data.params;

    console.log("onReceivedPostMessage "+event);

}

function onReceivedActivityMessageViaJavascriptInterface(json){
     //..ex deconstruct data into action & params
     var data = JSON.parse(json);
     var action = data.action;
     var params = data.params;
       console.log("onReceivedActivityMessageViaJavascriptInterface "+event);
}


    // 우편번호 찾기 화면을 넣을 element
    var element_layer = document.getElementById('layer');

    function sample2_execDaumPostcode() {
        new daum.Postcode({
            oncomplete: function(data) {

              var fullRoadAddr = data.roadAddress ? data.roadAddress : data.autoRoadAddress;
              var extraRoadAddr = ''; // 도로명 조합형 주소 변수

              // 법정동명이 있을 경우 추가한다. (법정리는 제외)
              // 법정동의 경우 마지막 문자가 "동/로/가"로 끝난다.
              if(data.bname !== '' && /[동|로|가]$/g.test(data.bname)){
                  extraRoadAddr += data.bname;
              }

              // 건물명이 있고, 공동주택일 경우 추가한다.
              if(data.buildingName !== '' && data.apartment === 'Y'){
                 extraRoadAddr += (extraRoadAddr !== '' ? ', ' + data.buildingName : data.buildingName);
              }

              // 도로명, 지번 조합형 주소가 있을 경우, 괄호까지 추가한 최종 문자열을 만든다.
              if(extraRoadAddr !== ''){
                  fullRoadAddr += ' (' + extraRoadAddr + ')';
               }

               var jibunAddr = data.jibunAddress ? data.jibunAddress : data.autoJibunAddress;
            		window.Android.processDATA(fullRoadAddr); // data.zonecode + ", " +
                        },
                        width : '100%',
                        height : '100%'
                    }).embed(element_layer);

                    // iframe을 넣은 element를 보이게 한다.
                    element_layer.style.display = 'block';

                    // iframe을 넣은 element의 위치를 화면의 가운데로 이동시킨다.
                    initLayerPosition();


    }

    // 브라우저의 크기 변경에 따라 레이어를 가운데로 이동시키고자 하실때에는
    // resize이벤트나, orientationchange이벤트를 이용하여 값이 변경될때마다 아래 함수를 실행 시켜 주시거나,
    // 직접 element_layer의 top,left값을 수정해 주시면 됩니다.
    function initLayerPosition(){
        var width = (window.innerWidth || document.documentElement.clientWidth); //우편번호서비스가 들어갈 element의 width
        var height = (window.innerHeight || document.documentElement.clientHeight); //우편번호서비스가 들어갈 element의 height
        var borderWidth = 5; //샘플에서 사용하는 border의 두께

        // 위에서 선언한 값들을 실제 element에 넣는다.
        element_layer.style.width = width + 'px';
        element_layer.style.height = height + 'px';
        element_layer.style.border = borderWidth + 'px solid';
        // 실행되는 순간의 화면 너비와 높이 값을 가져와서 중앙에 뜰 수 있도록 위치를 계산한다.
        element_layer.style.left = (((window.innerWidth || document.documentElement.clientWidth) - width)/2 - borderWidth) + 'px';
        element_layer.style.top = (((window.innerHeight || document.documentElement.clientHeight) - height)/2 - borderWidth) + 'px';
    }

</script>

</body>
</html>

🎉 Android Setting

✅ Web View를 띄워줄 Activity를 만들어 줍니다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

✅ Activity 코드를 작성합니다.

      webView.loadUrl( ) 의 파라미터는 개인 FireBase Host Domain을 입력합니다.

class AddressActivity : AppCompatActivity() {
    private lateinit var binding: ActivityAddressBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityAddressBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val webView = binding.webView
        webView.settings.javaScriptEnabled = true
        webView.addJavascriptInterface(BridgeInterface(), "Android")

        webView.webViewClient = object: WebViewClient(){
            //2. 페이지가 로드 되었을 때
            override fun onPageFinished(view: WebView?, url: String?) {
                super.onPageFinished(view, url)
                // android->javascript
                webView.loadUrl("javascript:sample2_execDaumPostcode();")
            }
        }
        //1.
        // 최초 웹뷰 로드
        webView.loadUrl(개인 Host Domain)

    }

    inner class BridgeInterface{
        @JavascriptInterface
        fun processDATA(data: String){
            // 카카오 주소 검색 API 결과를 브릿지 경로를 통해 전달 받는다(from Javascript)
            val intent = Intent()
            intent.putExtra("data", data)
            setResult(ADDR_RESULT, intent)
            finish()
        }
    }


}

 

✅ 위 Activity 호출할 Activity나 Fragment를 생성합니다. 저는 Fragment에서 실행했습니다.

btnAddr.setOnClickListener {
    val intent = Intent(requireContext(), AddressActivity::class.java)
    launcher.launch(intent)
}
val launcher = registerForActivityResult(
    // AddrActivity 로부터 결과값을 전달 받음
    ActivityResultContracts.StartActivityForResult()){ result ->
    if (result.data != null){
        when(result.resultCode){
            // ADDR_RESULT : 1001
            ADDR_RESULT -> {
                val data = result.data!!.getStringExtra("data")
                binding.addrEdit.setText(data)
            }          
     }
}

 

'Android' 카테고리의 다른 글

[Android] Jetpack WorkManager  (0) 2024.01.07
[Android]Android Memory Process  (1) 2024.01.07
Android Base64 Decoding  (0) 2024.01.03
Anroid Jetpack [ ViewBinding ]  (0) 2024.01.02
Android LayoutInflater  (1) 2023.12.26
'Android' 카테고리의 다른 글
  • [Android] Jetpack WorkManager
  • [Android]Android Memory Process
  • Android Base64 Decoding
  • Anroid Jetpack [ ViewBinding ]
빨주노초잠만보
빨주노초잠만보
  • 빨주노초잠만보
    과거의 나를 통해 미래의 나를 성장시키자
    빨주노초잠만보
  • 전체
    오늘
    어제
    • 분류 전체보기 (94)
      • TEKHIT ANDROID SCHOOL (4)
      • Android Architecture (7)
      • Android (40)
      • PROJECT (5)
      • KOTLIN (10)
        • 코루틴의 정석 (3)
      • BACK END (12)
      • CS (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    STATEFLOW
    kotlin interface abstract 차이
    value class
    interface vs abstract
    리사이클러뷰 풀
    saeled class enum class 차이
    kotlin abstract class
    flow
    Repository Pattern
    Room
    kotlin array
    orbit
    ThrottleFirst
    kotlin interface vs abstract
    sealed class
    의존성 주입
    kotlin interface
    Clean Architecture
    코틀린 코루틴의 정석
    android Room
    DI
    Livedata
    DataSource
    callbackflow
    android clean architecture
    sealed class vs enum class
    Throttle
    repository
    kotlin 타입 소거
    MVI
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
빨주노초잠만보
Android Daum 우편번호 서비스 API With FireBase Hosting
상단으로

티스토리툴바