[TIL-230622] Retrofit 알아보기

반응형

안녕하세요
역시나 처음 그 기세(?)는 어디가고 작성일의 텀이 길어지고 있네요

하루에 한번이 안되면 이틀에 한번, 한줄이라도 작성해서 무언가 남기는 하루가 되어야 겠습니다.
오늘 작성해 볼 내용은 Retrofit 입니다.


Retrofit이란?

Retrofit 은 서버 <-> 안드로이드 간 REST API 수행을 돕는 라이브러리입니다.

간단하게 장점을 설명하자면,

 

1. 구현이 간단하다

  • 코드량이 비교적 적어 빠르게 구현이 가능하다
  • 이 부분은 또다른 Library인 Volley와 비교를 해야하는데, 실제 사용해보진 않아서 확실하진 않다.

 

2. 가독성

  • Annotation을 활용하여 HTTP Method 코드 작성으로 코드가 읽기 쉽다.

 

3. 성능

 

  • AsyncTask는 Deprecated 되었음
  • 위와 같이, Volley와 비교 시에도 속도 만큼은 제일 좋으니 많이 사용되어진다.
  • 단, Volley 와 Retrofit이 지원하는 추가 기능이 다르기 때문에, 현재 개발 상황에 맞게 라이브러리를 선택해야 할 것이다.

Retrofit의 주요 기능

 

1.  Type Safe

  • 타입을 판별할 수 있어 Runtime 오류가 발생하지 않는다는 의미
  • 이러한 특징으로, 서버에서 전달받은 데이터를 Android에서 필요한 타입으로 변환하여 사용이 가능하다.

2.  Synchronous vs Asynchronous

  • Call 객체를 생성하여 동기/비동기 방식을 선택할 수 있습니다.
  • 각 인스턴스는 한번만 사용할 수 있지만, clone() 으로 새로 생성할 수 있습니다.
  • Android에서 콜백은 메인 스레드에서 실행되고, JVM위에서 콜백은 HTTP 요청한 동일 스레드에서 실행됩니다.

3.  Converters

  • Retrofit을 이용하여 서버에서 전달받은 값을 역직렬화할 수 있습니다.
    * 역직렬화(deserialize) : 특정 포맷 상태의 데이터를 다시 객체로 변환
  • Retrofit은 역직렬화에 여러 라이브러리를 지원합니다. (Gson, Moshi 등)
  • Retrofit이 지원하지 않는 형식 (YAML, txt 등)도 Custom Converter 기능을 활용하여 직접 코드 작성할 수 있습니다.

예제 작성

Retrofit을 기존 개발하고 있는 앱에 적용해보기로 하겠습니다.

1. Dependancy 작성

  • app모듈의 build.gradle에 아래와 같이 선언합니다.
  • Moshi 부분은 Json 형식의 데이터를 받아 역직렬화 하기위해 선언합니다.
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-moshi:2.9.0'
implementation 'com.squareup.moshi:moshi-kotlin:1.9.3'

 

2. 전달받을 Data class 선언

  • 서버에서 전달받은 값을 바로 객체로 만들기 위한 Data class를 선언
  • 변수 앞에 annotation은 서버에서 전달되는 Json 키 값과 내가 선언할 변수명이 다를 때,  선언해주는 것이 필요합니다.

data class ShopData(
    @Json(name = "번호") val num: Int? = 0,
    @Json(name ="상호") val shopName: String? = "",
    @Json(name = "도로명주소") val roadAddress: String? = "",
    @Json(name = "지번주소") val lotAddress: String? = ""
)

 

3. API Interface 선언

  • 어떤 방식으로 요청할 지에 대한 annotation 및 Base Url 이후의 Context Url 을 작성한다.
  • 메소드 파라미터에 @Query annotation을 추가하여, 해당 key값에 파라미터임을 선언한다.
interface ShopService {
    @GET(CONTEXT)
    fun getShopList(
        @Query("page") page: Int,
        @Query("perPage") perPage: Int,
        @Query("returnType") returnType: String = "",
        @Query("serviceKey") serviceKey: String = Api.API_KEY
    ): Call<ShopDataResponse>
}

 

4. Retrofit Instance

  • Converter로 사용할 Moshi 객체를 선언합니다. (Kotlin <-> Json)
  • Converter 객체를 추가하고, Base Url을 선언하여 retrofit 객체를 생성합니다.
  • interface를 선언한 클래스를 파라미터로 retrofit.create를 호출하여, API Endpoint를 구현한 객체를 생성합니다.
private val moshi = Moshi.Builder()
        .add(KotlinJsonAdapterFactory())
        .build()

private val retrofit = Retrofit.Builder()
        .addConverterFactory(MoshiConverterFactory.create(moshi))
        .baseUrl(BASE_URL)
        .build()

val retrofitService: ShopService by lazy {
        retrofit.create(ShopService::class.java)
}

 

5. API 호출

  • 4번에서 생성한 retrofitService 객체를 이용하여 getShopList 메소드를 호출합니다.
  • 호출 후 동기/비동기 여부에 따라 Call.excute()/Call.enqueue () 메소드를 호출합니다.
val service = Api.retrofitService.getShopList(page, perPage)
        service.enqueue(object: Callback<ShopDataResponse> {
            override fun onResponse(
                call: Call<ShopDataResponse>,
                response: Response<ShopDataResponse>
            ) {
                if(response.isSuccessful){
                    Log.d("shop", "success : ${_shopResponse.value}")
                } else {
                    Log.d("error", "error : ${response.errorBody()}")
                }
            }

            override fun onFailure(call: Call<ShopDataResponse>, t: Throwable) {
                Log.d("error", "${t.printStackTrace()}")
            }
        })

 

결과

위의 예제에 사용된 API 호출 후 정상 전달된 값을 확인할 수 있었습니다.

 


 

이번에는 Retrofit 사용법에 대해 알아보았습니다

잘못된 내용이 있다면 댓글 부탁드리고, 내용이 좋았다면 공감, 구독 부탁드려요!

반응형