Android/StoreInfo

<강의> 안드로이드 앱 개발 심화 - Retrofit

re트 2024. 1. 25. 13:04
728x90

1. Retrofit이란?

Square Inc.에서 개발한 안드로이드 및 자바를 위한 타입-세이프한 HTTP 클라이언트 라이브러리

 

2. Retrofit의 목적

REST API의 HTTP 요청을 자바, 코틀린의 인터페이스로 변환하는 것

 

3. Retrofit의 장점

1) 좋은 성능

-  OkHttp보다 3배 빠르다고 함

- 내부적으로 OkHttp 라이브러리를 사용하여 안정적인 통신을 함

- 인터셉터를 사용하여 요청/응답 프로세스를 확장하거나 수정할 수 있음

2) 좋은 가독성

- 복잡한 HTTP API 요청을 쉽고 간결하게 만들 수 있음

- 간단한 어노테이션을 통해 요청 메서드와 URL을 정의할 수 있음

3) 간단한 구현

- 다양한 데이터 타입에 대한 데이터 변환 컨버터 제공

- 비동기 프로그래밍 라이브러리와 연동 가능

 

4. Retrofit의 3가지 요소

1) 서버와 통신할 때 사용할 HTTP 메서드를 정의한 인터페이스

2) Retrofit 클라이언트 객체를 생성하는 오브젝트 클래스(싱글턴)

3) 서버로부터 넘어오는 Json 데이터를 담을 데이터 클래스

 

5. Retrofit 사용방법

1) 인터넷 접근 권한 설정

 <uses-permission android:name="android.permission.INTERNET"/>

 

2) Gradle에 Retrofit 관련 라이브러리 추가

- Gson은 Google에서 제공하는 오픈소스 라이브러리

- Gson 컨버터를 사용하면 프로그래밍 언어 객체를 JSON 데이터로, JSON 데이터를 프로그래밍 언어 객체로 변환하는 직렬화, 역직렬화를 간단하게 해줌

- OkHttp의 인터셉터를 사용하면 http 통신 로그를 기록할 수 있음

// build.gradle.kts (Module :app)
implementation("com.squareup.retrofit2:retrofit:2.9.0") // Retrofit
implementation("com.squareup.retrofit2:converter-gson:2.9.0") // gson 컨버터
implementation("com.squareup.okhttp3:logging-interceptor:4.8.0") // okhttp 인터셉터

 

3) 데이터 클래스 정의

- 받을 데이터 그대로 데이터 클래스 구조를 만듬

- 데이터 클래스에서 사용하는 변수 이름이 JSON 데이터에서 넘어오는 이름과 다르다면 @SerializedName 어노테이션을 쓰면 됨(같을 때 써도 상관없음)

data class SearchResponse(
    @SerializedName("documents")
    val documents: MutableList<Document>?,
    @SerializedName("meta")
    val metaData: MetaData?
)

data class MetaData(
    ...
)

data class Document(
    ...
)

 

4) API 인터페이스 정의

- 서버와 통신할 때 사용할 HTTP 메소드들을 어노테이션으로 적고 그 아래에 함수를 만들어 들어갈 값과 반환값을 설정

- 어노테이션에는 @GET, @POST, @PUT, @DELETE가 들어갈 수 있음

- 어노테이션 뒤에는 상대 URL을 소괄호 안에 문자열로 적으면 됨

- 헤더가 따로 필요하다면 @Headers 어노테이션을 사용하면 됨

- 함수는 비동기적으로 받아올 거라면 suspend를 붙여 코루틴 안에서 작동하도록 해야함

- 함수의 파라미터로 일일히 API 요청 파라미터를 적을수도 있지만 HashMap을 통해서 한꺼번에 넘길 수도 있음

- 반환값은 가장 상위의 데이터 클래스를 적으면 됨(Response로 감싸거나 Call로도 감쌀 수 있는 거 같은데 그렇게 안 해도 잘 받아오고 사용할 수 있더라)

interface NetworkInterface {
    @Headers("$헤더내용")
    @GET("$상대 URL")
    suspend fun searchImage(@QueryMap param: HashMap<String, String>) : SearchResponse
}

 

5) Retrofit 클라이언트 객체 생성

- 애플리케이션 내에서 하나만 있으면 되므로 싱글턴으로 구현

- 데이터를 받아올 베이스 URL을 상수로 선언

- Retrofit.Builder()를 사용하여 Retrofit 클라이언트 객체 생성

- 거기에 필요한 속성 설정하고 마지막에 build()로 마무리

- 만들어진 객체를 가지고 API 인터페이스 객체를 만들 수 있음

- API 인터페이스 객체를 통해 정의된 API 요청을 사용 가능

object NetworkClient {
    private const val BASE_URL = "https://dapi.kakao.com/"

    ...

    private val searchRetrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .client(createOkHttpClient()) // <- OkHttp 인터셉트 세팅한 부분
        .build()

    val searchNetwork: NetworkInterface = searchRetrofit.create(NetworkInterface::class.java)
}

 

6) 응답처리

- 동기식 요청과 비동기식 요청이 있는데 코루틴을 사용하여 비동기 요청을 함

  > 동기식 요청 : 현재 스레드에서 실행되며, 응답이 올 때까지 다음 코드의 실행이 중단

  > 비동기식 요청 : 다른 스레드에서 실행되며, 응답이 올 때까지 메인 스레드의 코드 실행 중단 없음

- 먼저 서버로 보낼 파라미터를 세팅하고 코루틴 안에서 HTTP 메소드를 보내면 값이 옴

communicationNetwork(setUpSearchParameter(binding.etMainSearch.text.toString()))

private fun communicationNetwork(param: HashMap<String, String>) = lifecycleScope.launch {
    val responseData = NetworkClient.searchNetwork.searchImage(param)
    
    ...
}
반응형