Skip to content

Latest commit

Β 

History

History
232 lines (140 loc) Β· 7.68 KB

retrofit.md

File metadata and controls

232 lines (140 loc) Β· 7.68 KB

Retrofit

Present time : 2018-07-06 Fri


Last Updated :



0. 곡식 λ¬Έμ„œ

0-1. 곡식 λ¬Έμ„œ

0-2. κ°€μ΄λ“œ

  • ​


1. μ†Œκ°œ

  • Retrofit은 HTTP APIλ₯Ό μžλ°” μΈν„°νŽ˜μ΄μŠ€ ν˜•νƒœλ‘œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • Java 7 이상, Android 2.3 μ΄μƒμ—μ„œλ§Œ μ‚¬μš©κ°€λŠ₯ν•©λ‹ˆλ‹€.

HTTP μš”μ²­μ€ μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜μ—¬ λͺ…μ‹œν•©λ‹ˆλ‹€.

  • URL νŒŒλΌλ―Έν„° μΉ˜ν™˜κ³Ό 쿼리 νŒŒλΌλ―Έν„°κ°€ μ§€μ›λ©λ‹ˆλ‹€.
  • 객체λ₯Ό μš”μ²­ body둜 λ³€ν™˜ν•©λ‹ˆλ‹€. (예: JSON, protocol buffers)
  • λ©€ν‹°νŒŒνŠΈ μš”μ²­ body와 파일 μ—…λ‘œλ“œκ°€ κ°€λŠ₯ν•©λ‹ˆλ‹€.


2. API μ •μ˜

μΈν„°νŽ˜μ΄μŠ€μ˜ μ–΄λ…Έν…Œμ΄μ…˜κ³Ό λ©”μ†Œλ“œ λ§€κ°œλ³€μˆ˜λ“€μ€ μš”μ²­μ„ μ–΄λ–»κ²Œ 닀룰지 μ§€μ‹œν•©λ‹ˆλ‹€.

2-1. μš”μ²­ λ©”μ†Œλ“œ

λͺ¨λ“  λ©”μ†Œλ“œλ“€μ€ λ°˜λ“œμ‹œ μƒλŒ€ URLκ³Ό μš”μ²­ λ©”μ†Œλ“œλ₯Ό λͺ…μ‹œν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜μ„ 가지고 μžˆμ–΄μ•Όν•©λ‹ˆλ‹€. 기본으둜 μ œκ³΅ν•˜λŠ” μš”μ²­ λ©”μ†Œλ“œ μ–΄λ…Έν…Œμ΄μ…˜μ€ λ‹€μŒκ³Ό 같이 5κ°œκ°€ μžˆμŠ΅λ‹ˆλ‹€ : GET, POST, PUT, DELETE, HEAD.


정적 쿼리 인자λ₯Ό URL에 λͺ…μ‹œν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

@GET("/users/list?sort=desc")

2-2. URL 닀루기

μš”μ²­ URL은 λ™μ μœΌλ‘œ λΆ€λΆ„ μΉ˜ν™˜ κ°€λŠ₯ν•˜λ©°, μ΄λŠ” λ©”μ†Œλ“œ λ§€κ°œλ³€μˆ˜λ‘œ 변경이 κ°€λŠ₯ν•©λ‹ˆλ‹€. λΆ€λΆ„ μΉ˜ν™˜μ€ 영문/숫자둜 이루어진 λ¬Έμžμ—΄μ„ { 와 } 둜 감싸 μ •μ˜ν•΄μ€λ‹ˆλ‹€. λ°˜λ“œμ‹œ 이에 λŒ€μ‘ν•˜λŠ” @Path λ₯Ό λ©”μ†Œλ“œ λ§€κ°œλ³€μˆ˜μ— λͺ…μ‹œν•΄μ€˜μ•Όν•©λ‹ˆλ‹€.

@GET("/group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);

이외에도 쿼리 λ§€κ°œλ³€μˆ˜λ„ λͺ…μ‹œ κ°€λŠ₯ν•©λ‹ˆλ‹€. @Query와 @QueryMap을 μ΄μš©ν•˜λ©΄ λ©λ‹ˆλ‹€.


2-3. μš”μ²­ λ³Έλ¬Έ

HTTP μš”μ²­ 본문에 객체λ₯Ό @Body μ–΄λ…Έν…Œμ΄μ…˜μ„ 톡해 λͺ…μ‹œκ°€ κ°€λŠ₯ν•©λ‹ˆλ‹€.

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

μ΄λŸ¬ν•œ 객체듀은 Retrofit μΈμŠ€ν„΄μŠ€μ— μΆ”κ°€λœ 컨버터에 따라 λ³€ν™˜λ©λ‹ˆλ‹€. λ§Œμ•½ ν•΄λ‹Ή νƒ€μž…μ— λ§žλŠ” 컨버터가 μΆ”κ°€λ˜μ–΄μžˆμ§€ μ•Šλ‹€λ©΄, RequestBody 만 μ‚¬μš©ν•˜μ‹€ 수 μžˆμŠ΅λ‹ˆλ‹€.


FORM-ENCODEDκ³Ό MULTIPART

λ©”μ†Œλ“œλŠ” form-encoded 데이터와 multipart 데이터 λ°©μ‹μœΌλ‘œ μ •μ˜ κ°€λŠ₯ν•©λ‹ˆλ‹€.


@FormUrlEncoded μ–΄λ…Έν…Œμ΄μ…˜μ„ λ©”μ†Œλ“œμ— λͺ…μ‹œν•˜λ©΄ form-encoded λ°μ΄ν„°λ‘œ 전솑 λ©λ‹ˆλ‹€. 각 key-value pair의 keyλŠ” μ–΄λ…Έν…Œμ΄μ…˜ 값에, valueλŠ” 객체λ₯Ό μ§€μ‹œν•˜λŠ” @Field μ–΄λ…Έν…Œμ΄μ…˜μœΌλ‘œ λ§€κ°œλ³€μˆ˜μ— λͺ…μ‹œν•˜μ‹œλ©΄ λ©λ‹ˆλ‹€.

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

Multipart μš”μ²­μ€ @Multipart μ–΄λ…Έν…Œμ΄μ…˜μ„ λ©”μ†Œλ“œμ— λͺ…μ‹œν•˜μ‹œλ©΄ λ©λ‹ˆλ‹€. 각 νŒŒνŠΈλ“€μ€ @Part μ–΄λ…Έν…Œμ΄μ…˜μœΌλ‘œ λͺ…μ‹œν•©λ‹ˆλ‹€.

@Multipart
@PUT("/user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);

Multipart의 partλŠ” Retrofit 의 μ»¨λ²„ν„°λ‚˜, RequestBody λ₯Ό ν†΅ν•˜μ—¬ 직렬화(serialization) κ°€λŠ₯ν•œ 객체λ₯Ό μ‚¬μš©ν•˜μ‹€ 수 μžˆμŠ΅λ‹ˆλ‹€.


2-4. 헀더 닀루기

2-4-1. 정적 헀더

정적 헀더듀은 @Headers μ–΄λ…Έν…Œμ΄μ…˜μ„ 톡해 λͺ…μ‹œν•  수 μžˆμŠ΅λ‹ˆλ‹€.

@Headers("Cache-Control: max-age=640000")
@GET("/widget/list")
Call<List<Widget>> widgetList();
@Headers({
    "Accept: application/vnd.github.v3.full+json",
    "User-Agent: Retrofit-Sample-App"
})
@GET("/users/{username}")
Call<User> getUser(@Path("username") String username);

2-4-2. 동적 헀더

동적인 ν—€λ”λŠ” @Header μ–΄λ…Έν…Œμ΄μ…˜μ„ 톡해 λͺ…μ‹œ κ°€λŠ₯ν•©λ‹ˆλ‹€. λ°˜λ“œμ‹œ 이에 λŒ€μ‘ν•˜λŠ” @Header μ–΄λ…Έν…Œμ΄μ…˜μ„ λ§€κ°œλ³€μˆ˜μ— λͺ…μ‹œν•΄μ•Όν•©λ‹ˆλ‹€. λ§Œμ•½ 값이 null이라면 ν•΄λ‹Ή ν—€λ”λŠ” μΆ”κ°€λ˜μ§€μ•ŠμŠ΅λ‹ˆλ‹€. μ•„λ‹ˆλΌλ©΄, λ§€κ°œλ³€μˆ˜ 객체의 toString λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜μ—¬ λ°˜ν™˜λœ 값을 ν—€λ”μ˜ κ°’μœΌλ‘œ μΆ”κ°€ν•©λ‹ˆλ‹€.

@GET("/user")
Call<User> getUser(@Header("Authorization") String authorization)

2-5. 동기 VS. 비동기

Call μΈμŠ€ν„΄μŠ€λŠ” 동기 ν˜Ήμ€ λΉ„λ™κΈ°λ‘œ μš”μ²­ 싀행이 κ°€λŠ₯ν•©λ‹ˆλ‹€. 각 μΈμŠ€ν„΄μŠ€λ“€μ€ 동기 ν˜Ήμ€ 비동기쀑 ν•œκ°€μ§€ λ°©μ‹λ§Œ μ‚¬μš©κ°€λŠ₯ν•©λ‹ˆλ‹€, ν•˜μ§€λ§Œ clone() λ©”μ†Œλ“œλ₯Ό 톡해 μƒˆ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜μ‹œλ©΄ 이전과 λ‹€λ₯Έ 방식을 μ‚¬μš© κ°€λŠ₯ν•©λ‹ˆλ‹€.

μ•ˆλ“œλ‘œμ΄λ“œμ—μ„œμ˜ μ½œλ°±λ“€μ€ 메인 μŠ€λ ˆλ“œμ—μ„œ μ‹€ν–‰λ©λ‹ˆλ‹€. JVMμ—μ„œλŠ”, HTTP μš”μ²­μ„ ν˜ΈμΆœν•œ μŠ€λ ˆλ“œμ™€ λ™μΌν•œ μŠ€λ ˆλ“œμ—μ„œ μ½œλ°±λ“€μ΄ μ‹€ν–‰λ©λ‹ˆλ‹€.


μš°μ„  자주 μ‚¬μš© 될 λ²•ν•œ 비동기식 λ°©μ‹μ˜ 톡신은 μœ„μ—μ„œ 이미 μ‚¬μš©ν•΄ λ³Έ enqueue() methodλ₯Ό μ΄μš©ν•˜λŠ” 것 μž…λ‹ˆλ‹€.

κ·Έλ ‡λ‹€λ©΄ λ°˜λŒ€λ‘œ 동기식 λ°©μ‹μ˜ 톡신을 ν•˜λ €λ©΄ μ–΄λ–»κ²Œ ν•΄μ•Όν• κΉŒμš”?

μƒμ„±λœ ν΄λΌμ΄μ–ΈνŠΈ 객체가 μ œκ³΅ν•˜κ³  μžˆλŠ” execute() methodλ₯Ό enqueue() method λŒ€μ‹  μ΄μš©ν•˜λ©΄ λ©λ‹ˆλ‹€.



3. Retrofit μ„€μ •

3-1. 컨버터

기본적으둜, Retrofit은 HTTP μš”μ²­ 본문을 OkHttp의 ResponseBody ν˜•μ‹κ³Ό @Body 에 μ΄μš©ν•˜λŠ” RequestBody νƒ€μž…λ§Œ 역직렬화(deserialization) ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

컨버터듀은 μ΄μ™Έμ˜ ν˜•μ‹λ“€μ„ λ³€ν™˜ν•΄μ£ΌλŠ” 역할을 ν•©λ‹ˆλ‹€. μ•„λž˜μ— 많이 μ‚¬μš©ν•˜κ³  νŽΈλ¦¬ν•œ 컨버터 6개의 λΌμ΄λΈŒλŸ¬λ¦¬λ“€μ„ μ‚¬μš©ν•˜μ‹€ 수 μžˆμŠ΅λ‹ˆλ‹€.

  • Gson: com.squareup.retrofit:converter-gson
  • Jackson: com.squareup.retrofit:converter-jackson
  • Moshi: com.squareup.retrofit:converter-moshi
  • Protobuf: com.squareup.retrofit:converter-protobuf
  • Wire: com.squareup.retrofit:converter-wire
  • Simple XML: com.squareup.retrofit:converter-simplexml

μ˜ˆμ‹œ

Gson을 μ‚¬μš©ν•˜λŠ” GitHubService μΈν„°νŽ˜μ΄μŠ€κ°€ Gson을 역직렬화가 κ°€λŠ₯ν•˜κ²Œ GsonConverterFactory 클래슀λ₯Ό 톡해 컨버터λ₯Ό μΆ”κ°€ν•˜λŠ” μ˜ˆμ œμž…λ‹ˆλ‹€.

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

GitHubService service = retrofit.create(GitHubService.class);

addConverterFactory() methodλ₯Ό 톡신이 μ™„λ£Œλœ ν›„, μ–΄λ–€ Converterλ₯Ό μ΄μš©ν•˜μ—¬ 데이터λ₯Ό νŒŒμ‹±ν•  것인지에 λŒ€ν•œ μ„€μ •μž…λ‹ˆλ‹€.


μ£Όμ˜ν•  점!

κ³΅μ‹λ¬Έμ„œμƒμ—λŠ” baseURL()에 μ„€μ •λœ μ„œλ²„ URL에 /κ°€ μ—†μŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ μ‹€μ§ˆμ μœΌλ‘œ μ—¬λŸ¬κ°€μ§€ 톡신을 ν•˜λ©΄μ„œ λ‘œκΉ…μ„ 해보면 baseURL()에 /κ°€ 없을 경우, μš”μ²­ λ˜μ–΄μ•Ό ν•  URL의 일뢀가 μž˜λ €λ‚˜κ°€λŠ” ν˜„μƒμ΄ λ°œμƒν•˜μ—¬ 잘λͺ»λœ 경둜둜 μš”μ²­ν•˜λŠ” ν˜„μƒμ΄ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

κ·ΈλŸ¬λ‹ˆ κΌ­ baseURL()에 μ„€μ •λ˜λŠ” URL의 λ§ˆμ§€λ§‰ κ²½λ‘œμ—λŠ” /λ₯Ό ν•¨κ»˜ 포함해 주도둝 ν•΄μ•Όν•©λ‹ˆλ‹€!


3-2. μ‚¬μš©μžμ •μ˜ 컨버터

λ§Œμ•½ API와 ν†΅μ‹ ν•˜λŠ”λ° Retrofit이 μ§€μ›ν•˜μ§€ μ•ŠλŠ” ν˜•μ‹(e.g. YAML, txt, custom format) μ΄κ±°λ‚˜ ν˜„μž¬ μ‚¬μš©κ°€λŠ₯ν•œ ν˜•μ‹μ΄μ§€λ§Œ λ‹€λ₯Έ 라이브러리λ₯Ό 톡해 κ΅¬ν˜„ν•˜μ‹œκΈΈ μ›ν•˜μ‹ λ‹€λ©΄, μ‰½κ²Œ λ‚˜λ§Œμ˜ 컨버터λ₯Ό λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€. Converter.Factory λ₯Ό μƒμ†ν•˜μ—¬ λ§Œλ“œμ‹œκ³ , 이λ₯Ό Retrofit 객체λ₯Ό λ§Œλ“œμ‹€λ•Œ μΆ”κ°€ν•˜μ‹œλ©΄λ©λ‹ˆλ‹€.


Proguard

λ§Œμ•½ ν”„λ‘œμ νŠΈκ°€ Proguardλ₯Ό μ‚¬μš©ν•˜μ‹œλ©΄ μ•„λž˜ λ‚΄μš©μ„ 섀정에 μΆ”κ°€ν•˜μ‹­μ‹œμ˜€.

-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions