Mobile : Android/Library

[Android Library] Retrofit2 #2 - HTTP Method

신숭이 2021. 9. 17. 16:37

[Android Library] Retrofit2 #2 - HTTP Method

 

 

Retrofit은 HTTP REST API통신에 사용하는 여러 종류의 요청 메서드를 사용할 수 있도록 돕는다.

 

Retrofit에서 구현 가능한 HTTP 요청 메소드는 GET, POST, PUT, DELETE, HEAD 이 5가지가 기본이며 어노테이션을 통해 이용가능하다.

 

참고로 메소드 Annotation은 대문자로 표기되며, 메소드와 함께 쓰이는 설정 어노테이션은 앞글자만 대문자료 표기된다.

(ex : @GET,   @Query )

 

 

Annotaion 요약

 

메소드 Annotation 종류 (서버의 파일(데이터)에 대한 CRUD 기준,  서버 DB에 대한 쿼리 기준)

 

주요 메소드

  • @GET : 바디 없이 URL에 모든 정보를 담아 요청한다. 서버에 데이터를 조회(Read, SELECT) 할 때 쓰며 @Query, @QueryMap 등의 Annotation과 함께 쓰인다. 
  • @POST : 바디에 정보를 담아 요청한다. 서버에 데이터를 생성(Create, INSERT)할 때 쓰며 @Body, @SerializedName , @Field, @FieldMap (@FormUrlEncoded 경우) 등의 Annotation과 함께 쓰인다.
  • @PUT : POST와 마찬가지 방식으로 요청하나, 서버에 데이터를 수정(Update, UPDATE) 할때 쓰인다. POST 와 다르게 수정할 데이터의 경로를 @Path로 명시해야한다.
  • @DELETE : 데이터를 제거(Delete, DELETE)할 때 쓰이며 제거할 경로를 @Path 로 명시한다. 반환 DTO는 없고 삭제시 응답 코드 200으로 응답한다.

기타 메소드

  • @HEAD : 헤더 정보를 조회한다.
  • @TRACE : 서버에 루프백 메시지 호출을 위한 테스트로 사용(클라이언트 서버 사이 프록시 서버에서 변경여부 확인시 사용)
  • @OPTIONS : 서버의 특정 URL에서 지원하는 메소드의 종류를 확인하는 용도, 요청 메소드 목록을 리턴하며 URL에 * 기입시 서버 전체의 메소드를 확인

 

URL 관련 어노테이션

  • @ Path : 경로를 설정할때 사용하는 Annotation

 

요청을 다른 데이터 방식으로 정의

 

요청 메소드 어노테이션 위에 추가로 명시

  • @FormUrlEncoded : form-encoeded 데이터로 정의한다. @Field Annotation을 통해 key-value 를 설정할 수 있다.
  • @Multipart : 주로 파일을 전송할때 사용한다.  @Part Annotation으로 객체를 직렬화할 수 있게 돕는다.

 

헤더 정의

  • @Headers : 메소드 어노테이션 상단에 정적헤더들을 정의할때 사용한다.
  • @Header : 함수 파라미터로 동적 헤더를 구성할때 사용한다.

 

 

 

GET Method

 

서버의 데이터를 조회할때 사용하며, URL에 모든 내용을 담아 보낸다. 기본적으로 아래와 같이 사용한다.

    @GET("/v2/local/search/keyword.json")           // /v2/local/search/keyword.{format}
    fun getKakaoAddress(
        @Header("Authorization") key:String,
        @Query("query") address:String
    ): Call<KakaoRoadApiData>

@Query Annotation의 쿼리에 따라 URL이 다음과 같이 구성된다. 참고로 URL은 255자로 길이제한이 있다.

 

https://dapi.kakao.co/v2/local/search/keyword.json?query=서초구

 

카카오 주소 조회 API는 사용 등록을 마친 개발자들에게 발급하는 key를 해더값으로 넣도록 문서에 명시되어있다. 따라서 동적헤더 @Header 를 이용하여 함수의 파라미터로 지정하도록 해봤다.

 

만약 여기서 정적 헤더 @Headers를 사용한다면, 아래와 같이 사용할 수 있겠다.

@Headers({"Authorization : KakaoAK 6ca4c5e2bbfa6aaaaadd93a7ae68fca37fd"})
@GET("/v2/local/search/keyword.json")           // /v2/local/search/keyword.{format}
fun getKakaoAddress(
     @Query("query") address:String
): Call<KakaoRoadApiData>

 

다른 예시로 헤더에 여러가지를 명시해야할 필요가 있을땐 아래와 같이 쓴다. 아래는 Java의 예시이다.

@Headers({
    "Accept: application/vnd.github.v3.full+json",
    "User-Agent: Retrofit-Sample-App"
})
@GET("/users/{username}")
fun getUser(@Path("username") username:String): Call<User>

위에서 @Path를 이용해 동적으로 경로를 지정하는 방식도 볼 수 있다.

 

만약 쿼리를 여러개 한번에 지정하고 싶다면, @QueryMap 과 Map 객체를 파라미터로 삼으면 된다.

@GET("/group/{id}/users")
fun groupList(@Path("id") groupId:Int, @QueryMap options:Map<String, String>):Call<List<User>>

 

 

 

POST Method

 

 

보통 데이터를 서버에 생성(추가)할 때 사용한다. 

POST 는 바디를 정의할 수 있고 GET에 비해 훨씬 많은 데이터를 담을 수 있다. 

@POST("/users/new")
fun createUser(@Body user:User): Call<User>

바디에 들어갈 객체는 @SerializedName Annotation을 이용하여 직렬화한다. Java Object를 통째로 직렬화하여 전송.

data class User {
    @SerializedName("user_id") val userId: Int?,
    @SerializedName("user_name") val userName: String?,
    @SerializedName("user_email") val userEmail: String?,
    @SerializedName("user_age") val userAge: String?,
    @SerializedName("user_uid") val userUid: String?
}

 

 

 

만약 메소드를 form-encoded 데이터 방식(키-값으로 URL 방식)으로 정의하고자 한다면 , 메소드 상단에 @FormUrlEncoeded 를 명시하고 @Field Annotaion으로 매개변수를 정의해야한다.

 

@FormUrlEncoded
@POST("/user/edit")
fun updateUser(@Field("first_name") first:String, @Field("last_name") last:String) : Call<User>

 

key-value 값을 여러개를 한번에 정의하고자 한다면 @FieldMap Annotaion으로 매개변수를 정의하면 된다. 여기서도 Map 객체를 인자로 전달하도록 정의한다.

 

@FormUrlEncoded
@POST("posts")
fun createUser(
	@FieldMap userData:Map<String, String>
) :Call<PostResult>

 

 

 

PUT Method

 

 

주로 서버 내의 데이터를 수정할때 사용한다. POST 와 매우 용법이 유사하며, 수정할 대상의 경로를 지정하는 내용만 추가하면 된다.

@PUT("users/{id}")
fun putUser(
	@Path("id") id:String,
	@Body user:User
):Call<Result>

 

 

DELETE Method

 

 

서버 내의 데이터를 지울때 사용하며, 경로를 지정한다.

@DELETE("users/{id}")
fun deletePost(@Path("id") id:String): Call<Void>

 

 

 

 

부록 : 파일업로드 @Multipart

 

 

예전에 Java로 액셀파일을 서버로 업로드하는 방법을 공유하고자 한다. Kotlin으로 변환하는건 어렵지 않을 것이다.

 

우선 @Multipart Annotation을 명기하고, 매개변수로 MultipartBody.port 객체로 @Part Annotation과 함께 정의한다.

@Multipart
@POST("/upload")
Call<Result> callDataUpload(@Part MultipartBody.Part File);

 

함수를 호출하는 시점에서는 다음과 같이 파일을 불러온 후, Multipart.Part 객체로 변환한다.

File xlsFile = new File(mRndTestActivity.getExternalFilesDir(null),tx_filename.getText().toString());

RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"),xlsFile);
MultipartBody.Part body = MultipartBody.Part.createFormData("data",xlsFile.getName(),requestFile);

callDataUpload(body).enqueue(Call<Result> call, Response<Result> response) {

... 콜백 정의

}

 

 

 

 

 

참조

http://devflow.github.io/retrofit-kr/

 

Retrofit - 한글 문서

A type-safe HTTP client for Android and Java

devflow.github.io