Coors To Address - Picplz/picplz-aos GitHub Wiki

์นด์นด์˜ค ์ฃผ์†Œ ๊ฒ€์ƒ‰ REST API ์ด์šฉ

์ง€๋„์˜ ์ค‘์•™ ์ขŒํ‘œ๋ฅผ ํƒ์ƒ‰ํ•ด์„œ ํ•ด๋‹น ์ขŒํ‘œ์˜ ์ฃผ์†Œ๋ฅผ rest api๋ฅผ ์ด์šฉํ•ด์„œ ๊ตฌํ•˜๋Š” ๋™์ž‘

API ๊ฐ€์ด๋“œ

API ๊ด€๋ จ Model ์ •์˜

image

๊ณต์‹ ์š”์ฒญ ํ˜•์‹์— ๋งž์ถฐ data class๋กœ ์ •์˜

data class KaKaoAddressRequest(
    val x: String,
    val y: String
)

๊ณต์‹ response ํ˜•์‹์— ๋งž์ถฐ ์ค‘์ฒฉ data class๋กœ ์ •์˜

image

data class KaKaoAddressResponse(
    val meta: Meta,
    val documents: List<Document>
) {
    data class Meta(
        val total_count: Int
    )

    data class Document(
        val address: Address,
        val road_address: RoadAddress?
    )

    data class Address(
        val address_name: String,
        val region_1depth_name: String,
        val region_2depth_name: String,
        val region_3depth_name: String,
        val mountain_yn: String,
        val main_address_no: String,
        val sub_address_no: String
    )

    data class RoadAddress(
        val address_name: String,
        val region_1depth_name: String,
        val region_2depth_name: String,
        val region_3depth_name: String,
        val road_name: String,
        val underground_yn: String,
        val main_building_no: String,
        val sub_building_no: String,
        val building_name: String,
        val zone_no: String
    )
}

data class์˜ ์ค‘์ฒฉ ํด๋ž˜์Šค

data class์˜ ์ค‘์ฒฉ ํด๋ž˜์Šค๋Š” json์˜ ๊ณ„์ธต๊ตฌ์กฐ๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ ์ข‹๋‹ค

  • ์ด๋•Œ json ํ˜•์‹๊ณผ kotlin์˜ ๊ฐ์ฒด์™€์˜ ์ง๋ ฌํ™”/์—ญ์ง๋ ฌํ™”๋Š” retrofit์„ ํ†ตํ•ด ์ด๋ค„์ง„๋‹ค

ServiceํŒŒ์ผ์—์„œ ์—”๋“œํฌ์ธํŠธ๋ณ„ ์š”์ฒญ interface ์ •์˜

package com.hm.picplz.data.service

import com.hm.picplz.data.model.KaKaoAddressResponse
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Query

interface KakaoMapService {
    @GET("v2/local/geo/coord2address.json")
    suspend fun getAddressFromCoordsService(
        @Header("Authorization") authorization: String,
        @Query("x") x: String,
        @Query("y") y: String
    ): KaKaoAddressResponse
}

retrofit

HTTP Method ๋ฐ ์—”๋“œํฌ์ธํŠธ ์ง€์ • : ์–ด๋…ธํ…Œ์ด์…˜(@)์„ ์ด์šฉ ํŒŒ๋ผ๋ฏธํ„ฐ ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ๊ฐ๊ฐ @Header, @Query, @Path, Body ์ •์˜ ๊ฐ€๋Šฅ

//์˜ˆ์‹œ
interface ApiService {
    @GET("users")
    suspend fun getUser(
        @Header("Authorization") token: String,    // ํ—ค๋” ํŒŒ๋ผ๋ฏธํ„ฐ
        @Query("name") name: String,              // URL ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ (?name=๊ฐ’)
        @Path("id") id: String,                   // URL ๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ
        @Body userInfo: UserInfo                  // ์š”์ฒญ ๋ฐ”๋””
    )
}
// ์นด์นด์˜ค ์ขŒํ‘œ ๊ฒ€์ƒ‰ api
interface KakaoMapService {
    @GET("v2/local/geo/coord2address.json")
    suspend fun getAddressFromCoordsService(
        @Header("Authorization") authorization: String,
        @Query("x") x: String,
        @Query("y") y: String
    ): KaKaoAddressResponse
}

ํ—ค๋” ๋ฐ ์ฟผ๋ฆฌ ์ž…๋ ฅ interface๋ฅผ ์ •์˜ํ•ด์ค๋‹ˆ๋‹ค

api ํ˜ธ์ถœ

KakaoMapSourceํŒŒ์ผ์—์„œ retrofit ์„ค์ • ๋ฐ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ์„ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค

private val retrofit: Retrofit = Retrofit.Builder()
    .baseUrl("https://dapi.kakao.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .build()

.baseUrl : api์˜ base url์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค .addConverterFactory(GsonConverterFactory.create()) JSON ๋ณ€ํ™˜๊ธฐ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค

์ธ์Šคํ„ด์Šค ์ƒ์„ฑ

private val kakaoMapService: KakaoMapService = retrofit.create(KakaoMapService::class.java)

์ •์˜ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๊ณผ ์„ค์ •์— ๋งž์ถฐ์„œ retrofit์ด api๋ฅผ ์š”์ฒญํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„

api ํ˜ธ์ถœ

๊ตฌํ˜„์ฒด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ runCatching๋ฐฉ์‹์œผ๋กœ api๋ฅผ ํ˜ธ์ถœ

suspend fun getAddressFromCoords(request: KaKaoAddressRequest): Result<KaKaoAddressResponse> =
    runCatching {
        kakaoMapService.getAddressFromCoordsService(
            authorization = "KakaoAK ${BuildConfig.KAKAO_REST_API_KEY}",
            x = request.x,
            y = request.y
        )
    }

runCatching

์ฝ”ํ‹€๋ฆฐ์˜ ์˜ˆ์™ธ์ฒ˜๋ฆฌ ๋ฐฉ์‹์œผ๋กœ .onSuccess์™€ .onFailure๋กœ ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// try-catch ๋ฐฉ์‹
try {
    // ์—๋Ÿฌ ๋ฐœ์ƒ ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ
} catch (e: Exception) {
    // ์—๋Ÿฌ ์ฒ˜๋ฆฌ
}

// runCatching ๋ฐฉ์‹
runCatching {
    // ์—๋Ÿฌ ๋ฐœ์ƒ ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ
}.onSuccess { result ->
    // ์„ฑ๊ณต ์ฒ˜๋ฆฌ
}.onFailure { exception ->
    // ์—๋Ÿฌ ์ฒ˜๋ฆฌ
}
runCatching {
    // ์œ„ํ—˜ํ•œ ์ž‘์—…
}.onSuccess { response ->
    // ์„ฑ๊ณต ์‹œ ์ฒ˜๋ฆฌ
}.onFailure { exception ->
    // ์‹คํŒจ ์‹œ ์ฒ˜๋ฆฌ
}.map { response ->
    // ์„ฑ๊ณต ๊ฒฐ๊ณผ๋ฅผ ๋ณ€ํ™˜
}.mapCatching { response ->
    // ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ณ€ํ™˜
}.recover { exception ->
    // ์‹คํŒจ๋ฅผ ๋ณต๊ตฌ
}.recoverCatching { exception ->
    // ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ณต๊ตฌ
}.getOrNull()      // null ๋˜๋Š” ๊ฒฐ๊ณผ
    .getOrDefault(defaultValue)  // ๊ธฐ๋ณธ๊ฐ’ ๋˜๋Š” ๊ฒฐ๊ณผ
    .getOrElse { exception ->    // ์ง์ ‘ ์ฒ˜๋ฆฌ
        // ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋กœ์ง
    }

์œ„์™€ ๊ฐ™์ด ๋‹ค์–‘ํ•œ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

intent๋กœ api ํ˜ธ์ถœ ๋ฐ address state ์„ค์ •

fun handleIntent(intent: SearchPhotographerIntent) {
    when (intent) {
        is SearchPhotographerIntent.SetAddress -> {
            _state.update { it.copy(address = intent.address) }
        }
        is SearchPhotographerIntent.GetAddress -> {
            viewModelScope.launch {
                kakaoSource.getAddressFromCoords(KaKaoAddressRequest(intent.Coords.longitude.toString(), intent.Coords.latitude.toString()))
                    .onSuccess { response ->
                        val twoDepthRegion = response.documents.firstOrNull()?.address?.region_2depth_name ?: ""
                        val threeDepthRegion = response.documents.firstOrNull()?.address?.region_3depth_name ?: ""
                        val address = "$twoDepthRegion $threeDepthRegion"
                        handleIntent(SearchPhotographerIntent.SetAddress(address))
                    }
                    .onFailure { error ->
                        Log.e("kakaoMapAddressSearch", "์ขŒํ‘œ ๊ฒ€์ƒ‰ ์‹คํŒจ : ", error)
                    }
            }
        }
        ...
    }
}
โš ๏ธ **GitHub.com Fallback** โš ๏ธ