[안드로이드 - 코틀린] retrofit2 사용하기

2022. 11. 21. 21:21Android

앱으로 외부에 있는 데이터를 불러오기 위한 아주 기본적인 데이터 통신 라이브러리이다 많은 사람들이 많이 사용하고 앞으로도 많이 사용할 라이브러리이다 한 번에 이해해 잘 써보도록 하자

 

처음 retrofit2를 사용하면서 느낀 점은 어렵다 였다 처음으로 서버 데이터를 받아서 사용해보는 과정에 이해하지 않고 넘어가 고생한 부분과 힘들었던 부분을 풀어서 설명할 예정이다.

 

일단 설명하기전 기본적으로 알아야 되는 개념에 대해 알아보자

처음 나는 빠르게 통신 처리를 해야 되는 일이 있어 개념보다는 코드에 집중해 이때는 이거 저때는 이거 이런 식으로 외워서 들어가는 식으로 했다 ( + 기본적인 언어 개념도 부족했음 ) 하지만 기초적인 부분은 사용 가능해 통과할지언정 조금만 응용이 들어가는 순간 막혀 해결하는데 오래 걸리는 상황이 발생하였다.

 

1. GET,  POST

다른 것도 있지만 이것만 알아도 기본은 한다고 생각한다 

 

로그인을 이용한 레트로핏 설명 

 

인터페이스, 레트로핏, 데이터 클래스, 로그인 페이지

interface O2_Interface {

    @POST("api/user/login")
    fun login(
        @Body loginData: LoginData
    ) : Call<LoginDTO>
    
 }

 

현재 어플리케이션에서는 로그인을 할 때 POST를 이용했습니다 

Body안에는 데이터 형식(LoginData)에 맞춰 넣어준다

응답 결과는 LoginDTO에 반환받는다 

 

 

 

object Retrofit2 {

    private val retrofit = Retrofit.Builder()
        .baseUrl("서버 URL")
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    val api = retrofit.create(O2_Interface::class.java)

    // 다른 페이지에서 선언해 사용 초기화
    fun getInstance(): O2_Interface?{
        return api
    }
}

 

 

 

data class LoginDTO(

    @SerializedName("result")
    val result : LoginResult
)

data class LoginData(

    @SerializedName("id")
    val id : String,

    @SerializedName("pw")
    val pw : String,
)

data class LoginResult(
    @SerializedName("user_key")
    val user_key : Int?,

    @SerializedName("msg")
    val msg : String
)

 

LoginData는 Body안에 들어갈 값을 넣어주고 LoginDTO는 서버에서 받아온 응답 값이 들어간다

 

+ 다른 곳에서도 사용하는 user_key 값이 null인 경우가 있어 여기서 허용을 해줬지만 일반적인 로그인 반환 결과에서는 null 값이 생기면 안되기 때문에 null 허용을 하지 않고 다른 곳에서 사용할 때는 개별 데이터 클래스를 사용해서 사용하는 편이 더 좋을 것 같다. null 허용을 해줬기 때문에 하단 로그인 페이지에서 !!을 통해 not-null을 해줘야하는 일이 발생했다

 

 

class LoginActivity : AppCompatActivity() {

    val call by lazy { Retrofit2.getInstance() }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login_activty)

        val E_id : EditText = findViewById(R.id.login_id)
        val E_pw : EditText = findViewById(R.id.login_password)
        val loginB : Button = findViewById(R.id.login_button)

        // 유저키 유무 확인 -> 로그인 유지 위해 없으면 if 문 아니면 else 문 실행
        if (Loginkey.getUserKey(this@LoginActivity).isEmpty()) {
            Log.d("Login_key", "key_data 없음")

            loginB.setOnClickListener {
                // 로그인 아이디 패스워드 입력후 버튼 눌러서 전송
                val id = E_id.text.toString()
                val pw = E_pw.text.toString()
                Log.d("Login_Log", "$id + $pw")
                
                call?.login(LoginData(id, pw))?.enqueue(object : Callback<LoginDTO>{

                    override fun onResponse(call: Call<LoginDTO>, response: Response<LoginDTO>) {
                        if (response.isSuccessful) {
                            val result : LoginDTO? = response.body()

                            Log.d("Login_Log", "$result")
                            
                            Loginkey.setUserKey(this@LoginActivity, result!!.result.user_key!!.toInt())

                            Log.d("Login_key", "${result.result.user_key!!.toInt()}")

                            val intent = Intent(this@LoginActivity, MainActivity::class.java)
                            Toast.makeText(this@LoginActivity, "로그인 성공", Toast.LENGTH_LONG).show()
                            startActivity(intent)
                            finish()
                        }
                    }

                    override fun onFailure(call: Call<LoginDTO>, t: Throwable) {
                        Toast.makeText(this@LoginActivity, "로그인 실패", Toast.LENGTH_LONG).show()
                        Log.d("Login_Log", "${t.message}")
                    }

                })
            }

        } else {
            Log.d("Login_key", "응답 ${Loginkey.getUserKey(this@LoginActivity)}")

            val intent = Intent(this@LoginActivity, MainActivity::class.java)
            Toast.makeText(this@LoginActivity, "로그인 성공", Toast.LENGTH_LONG).show()
            startActivity(intent)
            finish()

        }

    }


}

 

LoginActivtiy는 크게 최초 로그인 창과 로그인 이후 디바이스 캐시에 저장된 값을 불러와 자동 로그인을 하는 방법으로 나뉜다

주석 순서대로 처음 화면에 들어오면 캐쉬에 로그인 키(key_data)를 확인하고 없다면 로그인 레트로핏을 이용해 로그인을 시도한다

로그인 성공을 한다면 캐쉬에 유저 정보가 저장되므로 다시 로그인 없이 로그인에 성공할 수 있다