Developing Myself Everyday
이제부터는 우리가 지금까지 만들었던 서버와 Android간의 데이터 전달을 위한 Android 코드를 만들것이다.

 

 Android Studio의 코드를 작성하는데 생각보다 너무 많은 시간이 걸려서 이제 게시글을 작성한다. 우리가 할 것은 서버와 통신하기 위한 방법을 찾는 것이다. 서버와 통신할 수 있는 방법은 여러가지가 존재하는데 그 중 가장 많이 사용되고 가장 편리하게 사용할 수 있는 것이 바로 Retrofit이다. Retorfit에 대한 자세한 설명은 다음의 게시글을 참고하길 바란다.

 

 Retrofit Interface


Retrofit을 사용하기 위해서는 Retrofit 인터페이스를 정의해야 한다. 이를 기반으로 HTTP 요청 및 응답 처리를 자동으로 생성한다. 내가 작성한 인터페이스는 다음과 같다.

interface RetrofitSignIn {
    @FormUrlEncoded
    @POST("android_signin_php.php")
    @Headers(
        "accept: application/json",
        "content-type: application/x-www-form-urlencoded; charset=utf-8"
    )
    fun registerUser(
        @Field("username") username: String,
        @Field("userid") userid: String,
        @Field("userpassword") userpassword: String,
        @Field("userphone") userphone: String,
    ): Call<UserRegistrationResponse>
}

 이 인터페이스는 회원가입 기능을 구현하기 위해 필요한 정보를 서버에 요청하는 기능을 가진다.

 @FormUrlEncoded 어노테이션은 해당 메서드에서 Form URL Encoded 방식을 사용한다는 것이다. 이 방식은 key-value 쌍으로 이루어진 데이터를 요청 본문에 담아 보내는 방식이다. 이 방식을 사용하기 위해서는 요청 본문에 담는 방식을 Field로 사용해야 한다. 

 @Headers 어노테이션은 HTTP 헤더를 설정하는데 사용된다. 위 코드에서는 'accept' 헤더로 서버가 응답으로 보낼 수 있는 데이터 타입을 지정하고, 'content-type' 헤더를 통해 요청 본문의 데이터 타입을 지정한다.

 @Field 어노테이션은 정보를 key-value 쌍으로 욫어 본문에 담아서 보내고 있다.

 

 마지막으로 Call<UserRegistrationResponse>는 서버로부터 받아올 응답의 타입을 정의하는 타입이다.

data class UserRegistrationResponse(
    @SerializedName("status") val status: String,
    @SerializedName("message") val message: String
)

 서버로부터는 회원가입이 성공했는지를 확인하기 위한 상태와 원인을 담은 메시지가 들어있다.

 

 

 Retrofit


 다음은 Activity나 Fragment에서 서버와 통신하기 위한 코드를 작성하겠다. 아래에 보게 되면 getPesponseSignIn 함수에서는 OkHttpClient와 Retrofit 객체를 생성하고 Retrofit 객체에서 생성한 api를 통해 서버에 POST 요청을 보내게 된다. 

 이때 OkHttpClient는 네트워크의 상태를 출력하기 위한 객체를 생성한 것이다.  나도 처음 구현하는 부분이다보니 네트워크적인 부분에서 문제가 상당히 많았다. 하지만 로그에서는 Android에서 일어나는 일만 표시되었기에 OkHttpClient를 통해서 네트워크의 로그를 출력할 수 있었다. 

 

 다음으로 Retrofit.Builder()를 이용해 Retrofit 객체를 만든다. baseUrl() 메서드를 이용해 서버의 URL을 설정하고, addConverterFactory() 메서드를 이용해 Gson을 이용한 JSON 데이터 변환기를 추가한다. 이 과정을 거치게 되면 나중에 데이터를 받은 다음 JSON으로 파싱하는 과정이 필요없다.

private fun getResponseSignIn() {
        val loggingInterceptor = HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
        val client = OkHttpClient.Builder()
            .addInterceptor(loggingInterceptor)
            .connectTimeout(100, TimeUnit.SECONDS)
            .readTimeout(100, TimeUnit.SECONDS)
            .writeTimeout(100, TimeUnit.SECONDS)
            .build()

        val retrofit = Retrofit.Builder()
            .baseUrl("http://${IP_ADDRESS}/")
            .addConverterFactory(GsonConverterFactory.create(GsonBuilder().setLenient().create()))
            .client(client)
            .build()

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

        val call = api.registerUser(
            user.getName().toString(),
            user.getID().toString(),
            user.getPassword().toString(),
            user.getPhone().toString())

        call.enqueue(object : Callback<UserRegistrationResponse> {
            override fun onResponse(call: Call<UserRegistrationResponse>, response: Response<UserRegistrationResponse>) {
                if (response.isSuccessful && response.body() != null) {
                    try {
                        userRegistrationResponse(response.body()!!)
                    } catch (e: JSONException) {
                        signInView.onSignInError("응답 결과 파싱 중 오류가 발생했습니다.")
                    }
                }
            }

            override fun onFailure(call: Call<UserRegistrationResponse>, t: Throwable) {
                signInView.onSignInError("통신 실패")
                call.cancel()
            }
        })
    }

 

 

 

Response 처리


 다음은 서버로부터 받은 정보를 가지고 응답을 처리하는 부분이다. 나는 다음과 같이 작성했지만, 각자의 입맛에 맞춰서 회원가입 처리 이 후 로직을 정의하면 되겠다.

fun userRegistrationResponse(response: UserRegistrationResponse) {
        val message = response.message

        if (response.status == "true") {
            Log.d(TAG, "SignInViewModel - onResponse() called - response: $message")
            signInView.onSignInSuccess(message)
        }
        else {
            Log.d(TAG, "SignInViewModel - onResponse() called - response: $message")
            signInView.onSignInError(message)
        }
    }

 

 

 지금까지 AWS EC2에서 Ubuntu 서버를 할당받고 PuTTY를 이용해서 APM을 설치한 다음, MySQL Workbench로 데이터베이스 스키마를 만들고 VSCode를 통해 API를 만들었다. 이번 게시글에서 마지막으로 Android에서 서버에 연결하기 위한 코드를 작성하였다. 이 과정을 진행하는데 하루종일은 아니지만 많은 시간이 걸렸다. 처음 백엔드를 구축하는거였기 때문에 새로운 정보가 너무 많았고 한번에 안되는 것들이 상당히 많았다. 아직 해야할 일들이 많지만 이번 과정으로 얻은 지식을 활용할 수 있는 기회가 많다는 것이 긍정적인 부분이다. 

profile

Developing Myself Everyday

@배준형

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!