[Android] Retrofit2 사용법

강승구·2022년 12월 23일
0

Retrofit은 안드로이드와 서버간의 REST API 통신을 도와주는 라이브러리로, okHTTP에 기반을 두고 있다.
안드로이드에서 API서버와 통신하기 위한 방법으로 HttpUrlConnection, Volley, OkHttp, Retrofit2 등이 존재한다. 그중에서 Retrofit2는 높은 성능과 가독성으로 현재 가장 인기가 많은 통신 라이브러리 중 하나이다.

Retrofit의 장점

1. 높은 성능

HTTP 통신을 지원하는 다른 라이브러리들과 비교했을 때 높은 성능을 보여준다.
img

2. 뛰어난 가독성

Annotation으로 HTTP 메소드를 정의함으로서 코드의 구현이 쉬워지며 개발자들은 행위를 손쉽게 알아볼 수 있게 되어 직관적으로 코드를 설계할 수 있게 된다.

3. 쉬운 유지보수

Retrofit은 서버 연동 시 주로 주고받는 데이터인 JSON, XML을 자동을 파싱해주는 Converter 연동을 지원해주기 때문에 개발자 입장에서는 유지보수가 매우 편리하다.


사용법

1. dependency 추가

implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.6.0'

2. internet permission 부여

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

3. Retrofit Builder 생성

Retrofit Builder는 Retrofit 인스턴스를 만들기 위한 구성 요소들을 설정할 수 있는 객체로, API 통신을 위해 기본 설정을 수행하는 역할을 한다.

Retrofit Builder에는 주로 다음과 같은 요소들을 설정한다.

3-1. Base URL 설정
Base URL은 API 서버의 기본 주소를 설정하는 것입니다.
API 요청 시, 엔드포인트 URL은 baseUrl에 상대 경로가 붙어서 만들어진다.

Retrofit.Builder()
    .baseUrl("https://api.example.com/")  // API 서버의 기본 주소
    .build()

3-2. Converter 설정 (addConverterFactory)
Converter는 서버에서 받은 응답 데이터를 특정 형식으로 변환해주는 역할을 한다. 보통 REST API는 JSON 데이터를 반환하므로, JSON 데이터를 객체로 변환해주는 GsonConverterFactory나, Moshi 등을 추가할 수 있다.


3-3. HTTP Client 설정 (client)
Retrofit은 내부적으로 OkHttp를 사용하여 HTTP 요청을 처리한다. OkHttp는 네트워크 타임아웃, 인터셉터 추가 등을 설정할 수 있으며, 이를 통해 네트워크 요청을 세밀하게 제어할 수 있다.

val okHttpClient = OkHttpClient.Builder()
    .connectTimeout(30, TimeUnit.SECONDS)
    .readTimeout(30, TimeUnit.SECONDS)
    .addInterceptor(LoggingInterceptor())  // 요청/응답 로그를 기록하는 인터셉터
    .build()

Retrofit.Builder()
    .client(okHttpClient)  // 커스텀 OkHttp 클라이언트 추가
    .build()

이때 Retrofit Builder는 object 키워드를 이용하여 싱글톤으로 생성해주어야한다.
Retrofit 인스턴스는 서버와 통신할 때 사용하는 HTTP 클라이언트, 직렬화 방식, 베이스 URL 등의 설정을 포함하고 있기 때문에 이러한 설정이 앱 전역에서 일관되게 유지되어야 안정적인 네트워크 통신을 보장할 수 있다.

만약 여러 개의 Retrofit 인스턴스를 생성하게 된다면, 설정이 일관되지 않거나 예기치 않은 동작이 발생할 수 있다.

또한 Retrofit은 내부적으로 OkHttp 클라이언트를 포함하고, 여러 설정이 적용되어 있기 때문에 무거운 객체에 속하는 편이다. 따라서 매번 새롭게 인스턴스를 생성할 경우, 리소스를 불필요하게 소비하게 되며, 앱 성능에 악영향을 줄 수 있다.

import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

object RetrofitBuilder{
    var api: RetrofitService
    init {
        val retrofit = Retrofit.Builder()
            .baseUrl("https://api.github.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        api = retrofit.create(RetrofitService::class.java)
    }
}

3. DTO 클래스 생성

Data Transfer Object의 약자로 JSON Object 파싱을 위해 사용하는 클래스이다.
DTO는 서버로부터 받은 JSON 데이터를 자바나 코틀린 객체로 변환하기 위해 사용되며, 반대로 서버로 데이터를 보낼 때도 DTO 객체를 JSON 형식으로 변환하여 전달할 수 있다.

import com.google.gson.annotations.SerializedName

data class UserInfo(
    @SerializedName("login")
    val id: String,
    val name: String,
    val created_at: String,
    val updated_at: String,
    val followers: Int,
    val following: Int
)

4. API 인터페이스 생성

import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Path

interface RetrofitService{
    @GET("users/{userId}")
    fun getUserInfo(@Path("userId") userId: String): Call<UserInfo>
}

5. 요청 보내기

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response


class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val button: Button = findViewById(R.id.button)
        var inputId: EditText = findViewById(R.id.input_id)
        var name: TextView = findViewById(R.id.name_text)
        var followers: TextView = findViewById(R.id.followers_text)
        var following: TextView = findViewById(R.id.following_text)
        var createDate: TextView = findViewById(R.id.createDate_text)
        var updateDate : TextView = findViewById(R.id.updateDate_text)

        button.setOnClickListener {
            var userId: String = inputId.text.toString()
            RetrofitBuilder.api.getUserInfo(userId).enqueue(object : Callback<UserInfo> {
                override fun onResponse(call: Call<UserInfo>, response: Response<UserInfo>) {
                    var userInfo = response.body()
                    if (userInfo != null){
                        name.text = "이름 : ${userInfo.name}"
                        following.text = "Following : ${userInfo.following.toString()}"
                        followers.text = "Followers : ${userInfo.followers.toString()}"
                        createDate.text = "계정 만든 날짜 : ${textSlicing(userInfo.created_at)}"
                        updateDate.text = "최근 업데이트한 날짜 : ${textSlicing(userInfo.updated_at)}"
                    }else{
                        Toast.makeText(this@MainActivity, "ID 오류", Toast.LENGTH_LONG).show()
                    }
                }

                override fun onFailure(call: Call<UserInfo>, t: Throwable) {
                    Toast.makeText(this@MainActivity, "fail", Toast.LENGTH_LONG).show()
                }
            })
        }
    }

    fun textSlicing(text: String): String = (text.replace("Z", " ")).replace("T", " ")
}

전체 코드

https://github.com/kang9366/Android_Study/tree/main/AndroidEssential_Retrofit

profile
강승구

0개의 댓글

관련 채용 정보