retrofit을 테스트해보기 위해 아래 블로그를 참고했다
모델 클래스 선언
DataModels.kt에 선언
package com.asiae.retrofit2test
data class HTTP_GET_Model(
var something: String? = null,
var users: ArrayList<UserModel>? = null
)
data class UserModel(
var idx: Int? = null,
var id: String? = null,
var nick: String? = null
)
data class PostModel(
var id: String? = null,
var pwd: String? = null,
var nick: String? = null
)
data class PostResult(
var result: String? = null
)
APIS 라는 인터페이스를 만드는 과정에서 @Headers가 잘 이해되지 않았다.
깡샘 안드로이드 책에서는 @Headers가 서버 요청에서 헤더값을 조정하고 싶을 때 사용하는 것이라고 되어있었는데
헤더의 개념이 무엇인지 잘 이해되지 않았다.
헤더의 개념을 구글링해보다가 헤더를 알기 위해서는 HTTP의 기본 구조부터 알고 있어야 하는 것 같아 아래의 블로그를 참고했다
(Computer Science > --Network 카테고리의 내용들을 처음부터 찬찬히 살펴봄)
위의 블로그를 통해 헤더에 대한 기본 개념을 좀 잡은 상태에서 아까 봤던 코드에 대한 설명을 gpt를 통해 살펴봤다
서비스 인터페이스 정의
@POST("/users")
@Headers("accept: application/json", // 클라이언트가 서버로부터 JSON 형식의 응답을 기대
"content-type: application/json") // 요청의 본문(content)이 JSON 형식
fun post_users(
@Body jsonparams: PostModel
): Call<PostResult>
- @POST("/users") : POST 메서드를 사용해 지정된 엔드포인트인 "/user"로 요청을 보냄
- @Headers("accept: application/json", "content-type: application/json") : POST 요청에 대한 헤더를 설정
- "accept: application/json" : 클라이언트가 JSON 형식의 응답을 기대한다
- "content-type: application/json" : 요청의 본문이 JSON 형식
- fun post_users(@Body jsonparams: PostModel) : Call<PostResult> : 이 메서드는 POST 요청을 수행하는데 사용되며, 'jsonparams'를 요청의 본문으로 보냄
- PostModel : 요청 본문의 구조를 정의하는 모델 클래스
- Call<PostResult> : 서버로부터 예상되는 응답의 형태를 정의하는 Retrofit의 'Call' 객체
위 코드는 안드로이드 앱에서 Retrofit을 사용해 "/users" 엔드포인트로 JSON 형식의 데이터를 POST 요청하고, 서버로부터 'PostResult' 객체를 받아올 때 사용
@GET("/users")
@Headers("accept: application/json",
"content-type: application/json"
)
fun get_users(
): Call<HTTP_GET_Model>
위의 코드는 이전에 봤던 코드와 비슷하지만 다르다.
위 코드는 Retrofit을 사용하여 GET 요청을 보내고 "/user" 엔드포인트로부터 JSON 형식의 데이터를 받아오기 위한 것이다
- @GET("/users") : GET 메서드를 사용해 "/user" 엔드포인트로 요청을 보냄
- @Headers("accept: application/json", "content-type: application/json") :요청에 대한 헤더를 설정
- "accept: application/json" : 클라이언트가 JSON 형식의 응답을 기대한다
- "content-type: application/json" : 요청의 본문이 JSON 형식
하지만 GET 요청은 일반적으로 본문이 없으므로 "content-type" 헤더는 보통 사용되지 않음
- fun post_users() : Call<HTTP_GET_Model> : 이 메서드는 GET 요청을 수행하고, 서버로부터 받은 응답을 'HTTP_GET_Model' 객체로 변환해 반환
- HTTP_GET_Model : 서버에서 받아온 JSON 응답을 파싱하여 해당 데이터를 포함하는 데이터 클래스
따라서 이 코드는 "/user" 엔드포인트로 GET 요청을 수행하고, 서버로부터 JSON 형식의 응답을 'HTTP_GET_Model' 객체로 변환해 받아옴
Retrofit 객체 생성
companion object {
private const val BASE_URL = "http://234.234.234.33:7712" // 주소
fun create() : APIS {
val gson: Gson = GsonBuilder().setLenient().create();
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
.create(APIS::class.java)
}
}
- companion object : 이 블록은 클래스의 인스턴스 없이 클래스에 속한 메서드와 변수를 사용할 수 있게 해주는 Kotlin의 기능. 이 경우에는 'create()' 메서드를 정의하여 Retrofit 인스턴스를 만듦
- private const val BASE_URL : 기본 URL 주소를 저장하는 상수. 이 URL은 앱이 통신할 서버의 기본 주소를 나타냄
- fun create() : APIS : Retrofit 인스턴스를 생성하여 반환하는 함수. 이 함수는 Retrofit.Builder를 사용해 Retrofit 객체를 만들고, 해당 Retrofit 객체를 통해 서비스 인터페이스(APIS)를 생성해 반환
- val gson: Gson = GsonBuilder().setLenient().create() : Gson을 커스터마이징하여 JSON 파싱을 유연하게 처리하도록 하는 부분. setLenient()은 JSON 파싱에서 유연성을 확보하기 위한 설정
- Retrofit.Builder() : Retrofit 객체를 생성하는데 사용됨. 기본 URL, 컨버터 팩토리(Gson), 그리고 기타 설정을 여기에 추가 가능
- addConverterFactory(GsonConverterFactory.create(gson)) : Retrofit이 서버 응답을 파싱하는데 사용할 Gson 인스턴스 설정
- .create(APIS::class.java) : 마지막으로, Retrofit 객체를 생성하고 'APIS' 인터페이스를 구현한 서비스 생성. 이 서비스를 통해 앱은 서버로부터 데이터를 받거나 보낼 수 있음
GET 요청 버튼 구현
MainActivity.kt에 구현된 GET요청 버튼 클릭하는 부분이다.
아래 코드는 안드로이드 앱에서 'GET요청' 버튼을 클릭할 때 Retrofit을 사용해 서버로부터 데이터를 가져오는 예시
클릭 이벤트가 발생하면 api.get_users()를 호출해 서버로부터 데이터를 가져오고, 이를 처리하기 위해 Retrofit의 enqueue 메서드 사용
// get 요청 버튼 클릭
binding.getbutton.setOnClickListener {
api.get_users().enqueue(object : Callback<HTTP_GET_Model> {
override fun onResponse(call: Call<HTTP_GET_Model>,
response: Response<HTTP_GET_Model>) {
Log.d("log",response.toString())
Log.d("log", response.body().toString())
if(!response.body().toString().isEmpty())
binding.text.setText(response.body().toString());
}
override fun onFailure(call: Call<HTTP_GET_Model>, t: Throwable) {
// 실패
Log.d("log",t.message.toString())
Log.d("log","fail")
}
})
}
enqueue() 함수를 호출하면 비로소 통신이 수행됨
그리고 enqueue() 함수의 매개변수로 지정한 Callback 객체의 onResponse(), onFailure() 함수가 자동으로 호출됨
- 통신 성공 : onResponse() 함수 호출
- 통신 실패 : onFailure() 함수 호출
통신에 성공하면 서버에서 넘어온 데이터가 onResponse() 의 매개변수인 Response 객체로 전달되며 이 데이터를 response.body() 함수로 얻을 수 있음
위 코드를 보면 Response<HTTP_GET_Model>로 선언했으므로 response.body() 함수가 반환하는 값은 HTTP_GET_Model 객체
즉, 제네릭으로 선언한 클래스의 객체에 담아서 전달해줌
POST 요청 버튼 구현
MainActivity.kt에 구현된 POST요청 버튼 클릭하는 부분이다.
아래 코드는 안드로이드 앱에서 'POST버튼'을 클릭할 때 Retrofit을 사용해 서버로 데이터를 전송하는 예시를 보여줌
클릭 이벤트가 발생하면 'PostModel' 객체를 생성하여 사용자가 입력한 데이터를 담음
그런 다음, 'api.post_users(data)'를 호출하여 서버로 데이터 전송
//post요청 버튼 클릭
binding.postbutton.setOnClickListener {
val data = PostModel(
binding.idedt.text.toString(),
binding.pwdedt.text.toString(),
binding.nickedt.text.toString())
api.post_users(data).enqueue(object: Callback<PostResult>{
override fun onResponse(call: Call<PostResult>, response: Response<PostResult>) {
Log.d("log", response.toString())
Log.d("log", response.body().toString())
if(!response.body().toString().isEmpty())
binding.text.setText(response.body().toString())
}
override fun onFailure(call: Call<PostResult>, t: Throwable) {
Log.d("log", t.message.toString())
Log.d("log", "fail")
}
})
}
enqueue() 함수를 호출하면 비로소 통신이 수행됨
그리고 enqueue() 함수의 매개변수로 지정한 Callback 객체의 onResponse(), onFailure() 함수가 자동으로 호출됨
- 통신 성공 : onResponse() 함수 호출
- 통신 실패 : onFailure() 함수 호출
통신에 성공하면 서버에서 넘어온 데이터가 onResponse() 의 매개변수인 Response 객체로 전달되며 이 데이터를 response.body() 함수로 얻을 수 있음
위 코드를 보면 Response<PostResult>로 선언했으므로 response.body() 함수가 반환하는 값은 PostResult 객체
즉, 제네릭으로 선언한 클래스의 객체에 담아서 전달해줌
AVD 애뮬레이터 실행 결과
초기 화면
코드를 다 작성하고 애뮬레이터를 실행했는데 get요청 버튼 post요청 버튼이 모두 동작하지 않았다. 초기값이라고 적힌 부분이 바뀌어야 하는데 그대로였다.
baseUrl의 문제 같긴한데 결국 해결하지는 못했다...
logCat을 확인해보니
Failed to connect to /234.234.234.33:7712
라고 떴다
baseUrl의 문제가 맞는 것 같다 하지만 해결하지 못했다...
완성 github는 retrofitTest폴더 안에 있다