안드로이드 서버와 통신하는법 (API 사용)

쿼티·2023년 2월 27일
0

안드로이드 개발

목록 보기
2/2
post-thumbnail

총 6단계로 이루어지고 예제로 적용해보며 설명하겠습니다.

회원가입

1. 설정


1) build.gradle 파일에 implementation 추가

// build.gradle
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
implementation "com.squareup.retrofit2:adapter-rxjava2:2.9.0"

2) mainfest 파일에 인터넷 퍼미션 추가

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

3) Retrofit 객체 생성

  • Retofit 객체를 매번 생성하는 것이 번거로우니 따로 클래스를 만들어서 관리한다.
  • 처음에 한 번만 정의해놓고 언제든지 가져다 쓰면 된다.
  • BASE_URL에는 해당 서버의 url을 넣는다.
// NetworkModule.kt

package com.example.retrofitpractice
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

const val BASE_URL = "https://edu-api-test.softsquared.com"

fun getRetrofit(): Retrofit {
    val retrofit = Retrofit.Builder().baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create()).build()

    return retrofit
}

2.데이터 클래스 정의


1) Response(응답) 데이터 클래스 정의

  • 서버에서 보내는 값들이다.
// AuthResponse.kt

package com.example.retrofitpractice
import com.google.gson.annotations.SerializedName

data class AuthResponse (
    @SerializedName(value = "isSuccess") val isSuccess: Boolean,
    @SerializedName(value = "code") val code: Int,
    @SerializedName(value = "message") val message: String
)
// api 명세서 

{
	"isSuccess": true,
	"code": 1000,
	"message": "Successful!"
}

2) Request(요청) 데이터 클래스 정의

  • 클라가 서버로 보내는 값들이다.
  • request 가 없을 수도 있다.
// User.kt

package com.example.retrofitpractice
import com.google.gson.annotations.SerializedName

data class User (
    @SerializedName(value = "email") var email: String,
    @SerializedName(value = "password")var password: String,
    @SerializedName(value = "name")var name: String
)
// api 명세서 

{
	"email": "qwerty@gmail.con",
	"password": "qwertyaaa",
	"name": "쿼티"
}

3. Retrofit Interface


  • GET, POST, DELETE, PUT 등 쓰임에 맞게 작성한다.
  • 각 함수 안에는 @Query, @Path, @Body 등이 들어가거나, 아무것도 들어가지 않는다.
  • Call은 해당 api를 통해 들어오는 데이터를 받을 공간이라고 생각하면 되며, 앞서 만든 reponse data class을 call의 제네릭 타입으로 넣어주면 된다.
  • Body 매개변수로 들어가는 user는 request 보낼 때 data class 이다.
// AuthRetrofitInterface.kt

package com.example.retrofitpractice
import retrofit2.Call
import retrofit2.http.Body
import retrofit2.http.POST

interface AuthRetrofitInterFace {
    @POST("/users") // @Method(api address)
    fun signUp(@Body user:User): Call<AuthResponse>
}
// api 명세서

Method: POST
API Address: /users

4. View Interface


  • 이제 기본 세팅은 다 끝냈고, 사용만 하면 된다. 그런데..!!
  • 모듈화를 하기 위해서 Service에서는 retrofit 관련 처리를 하고, Activity에서는 UI 관련 처리를 해주도록 분리한다.
  • 이때, 데이터를 연결하기 위해 필요한 것이 View Interface다.
// SignUpView.kt

package com.example.retrofitpractice

interface SignUpView {
    fun onSignUpSuccess()
    fun onSignUpFailure()
}

5. Service


  • 1단계: View를 연결해준다.
  • 2단계: Retrofit 관련 작업을 해 줄 함수를 만든다.
// AuthService.kt

package com.example.retrofitpractice
import android.util.Log
import android.view.View
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

class AuthService {
		// 1단계
    private lateinit var signUpView: SignUpView

    fun setSignUpView(signUpView: SignUpView) {
        this.signUpView = signUpView
    }

		// 2단계
    fun signUp(user: User) {
        val authService = getRetrofit().create(AuthRetrofitInterFace::class.java)

        authService.signUp(user).enqueue(object: Callback<AuthResponse> {
            override fun onResponse(call: Call<AuthResponse>, response: Response<AuthResponse>) {
                Log.d("SIGNUP/SUCCESS", response.toString())
                val resp: AuthResponse = response.body()!!

                when(resp.code) {
                    1000 ->  signUpView.onSignUpSuccess()
                    else -> signUpView.onSignUpFailure()
                }
            }

            override fun onFailure(call: Call<AuthResponse>, t: Throwable) {
                Log.d("SIGNUP/FAILURE", t.message.toString())
            }
        })
    }
}

6. Activity


  • 1단계: View Interface를 상속받는다.
  • 2단계: 해당 Service를 호출해서 정의하고, setView 함수 호출로 연결해준다.
  • 3단계: overrideing 한 interface 함수를 통해 들어오는 Response를 가공해 화면해 보여준다. → Adapter 연결도 필요하다면 이 때 해주면 된다.
// MainActivity.kt

package com.example.retrofitpractice
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import com.example.retrofitpractice.databinding.ActivityMainBinding
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

// 1단계
class MainActivity : AppCompatActivity(), SignUpView {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.joinSubmitBtn.setOnClickListener {
            signUp()
        }
    }

    private fun getUser(): User {
        val email: String = binding.joinEmailEt.text.toString()
        val password: String = binding.joinPasswordEt.text.toString()
        val name: String = binding.joinNameEt.text.toString()

        return User(email, password, name)
    }

    private fun signUp() {
        if(binding.joinEmailEt.text.toString().isEmpty()) {
            Toast.makeText(this, "이메일 형식이 잘못되었습니다.", Toast.LENGTH_SHORT).show()
            return
        }

        if(binding.joinNameEt.text.toString().isEmpty()) {
            Toast.makeText(this, "이름 형식이 잘못되었습니다.", Toast.LENGTH_SHORT).show()
            return
        }

        if(binding.joinPasswordEt.text.toString() != binding.joinPasswordCheckEt.text.toString()) {
            Toast.makeText(this, "비밀번호가 일치하지 않습니다.", Toast.LENGTH_SHORT).show()
            return
        }

				// 2단계
        val authService = AuthService()
        authService.setSignUpView(this)
        authService.signUp(getUser())
    }
	
		// 1단계: 상속받은거 정의
    override fun onSignUpSuccess() {
        Toast.makeText(this, "회원가입에 성공했습니다", Toast.LENGTH_SHORT).show()
    }

    override fun onSignUpFailure() {
        TODO("Not yet implemented")
    }
}
profile
개발 기록

0개의 댓글