๊นจ์•Œ ๊ฐœ๋… ๐Ÿ“‘/Android

[Android] Retrofit - ๊ธฐ์ดˆ

interfacer_han 2024. 5. 29. 13:48

#1 ์ด์ „ ๊ธ€

 

[Android] Retrofit - ๋ฐฐ๊ฒฝ๊ณผ ๊ตฌ์กฐ

#1 Restrofit์˜ ๋ฐฐ๊ฒฝ#1-1 REST API REST API (REpresentational State Transfer Application Programming Interface)#1 ๋ฌด์—‡(What)์— ๋Œ€ํ•œ API์ธ๊ฐ€?#1-1 ๊ฐœ์š”REST(REpresentational State Transfer) ๋˜๋Š” RESTful API๋Š” ์„œ๋ฒ„์˜ ์ž์›(Resource)์„ ๋‘๊ณ 

kenel.tistory.com

์ด์ „ ๊ธ€์—์„œ Retrofit์˜ ๋ฐฐ๊ฒฝ๊ณผ ๊ตฌ์กฐ๋ฅผ ์‚ดํŽด๋ดค๋‹ค. ์ด๋ฒˆ์—” ์‹ค์ œ Retrofit์„ ์‚ฌ์šฉํ•œ ์•ฑ์„ ๋งŒ๋“ค์–ด๋ณธ๋‹ค.
 

#2 ํ†ต์‹ ํ•  ์„œ๋ฒ„

 

JSONPlaceholder - Free Fake REST API

{JSON} Placeholder Free fake and reliable API for testing and prototyping. Powered by JSON Server + LowDB. Serving ~3 billion requests each month.

jsonplaceholder.typicode.com

์œ„ ์‚ฌ์ดํŠธ๋Š” ์•ฑ ํ”„๋กœํ† ํƒ€์ดํ•‘์ด๋‚˜ ๊ณต๋ถ€๋ฅผ ํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์ œ๊ณตํ•˜๋Š” ๋ชฉ์ ์œผ๋กœ, JSON ํ˜•์‹์œผ๋กœ ๋œ ์ž์›(Resource)์„ ์ œ๊ณตํ•œ๋‹ค. ๋ณธ ๊ฒŒ์‹œ๊ธ€์—์„œ๋Š” ์ด URL์˜ ๋ฐ์ดํ„ฐ๋ฅผ GETํ•˜๋Š” ๊ฑธ ๋ชฉํ‘œ๋กœ ์‚ผ๋Š”๋‹ค.
 

#3 Retrofit ์‚ฌ์šฉ์„ ์œ„ํ•œ ํ™˜๊ฒฝ ์„ค์ •

#3-1 AndroidManifest.xml์—์„œ ๊ถŒํ•œ ํ—ˆ์šฉ

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

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

    <application
        ...
    </application>

</manifest>

์ธํ„ฐ๋„ท, ๋„คํŠธ์›Œํฌ ์ƒํƒœ, ์™€์ดํŒŒ์ด ์ƒํƒœ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์„ ๋„ฃ๋Š”๋‹ค.
 

#3-2 Retrofit ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€ (๋ชจ๋“ˆ ์ˆ˜์ค€ build.gradle)

plugins {
    ...
}

android {
    ...
}

dependencies {

    ...

    // Retrofit
    val retrofitVersion = "2.9.0"
    implementation("com.squareup.retrofit2:retrofit:$retrofitVersion")
    implementation("com.squareup.retrofit2:converter-gson:$retrofitVersion")
}

Retrofit ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ชจ๋“ˆ ์ˆ˜์ค€ build.gradle์— ์ถ”๊ฐ€ํ•œ๋‹ค. ์—ฌ๊ธฐ(๊ณต์‹ ์‚ฌ์ดํŠธ)์—์„œ Retrofit ์‚ฌ์šฉ์„ ์œ„ํ•ด ์ถ”๊ฐ€ํ•ด์•ผํ•˜๋Š” dependencies ๋ชฉ๋ก์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. GSON Converter ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ์ถ”๊ฐ€ํ•œ๋‹ค. ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” JSON์„ Kotlin์˜ ๋ฐ์ดํ„ฐ ํ˜•์‹์œผ๋กœ ํŒŒ์‹ฑํ•˜๋Š” ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
 
๋งŒ์•ฝ, ์„œ๋ฒ„๊ฐ€ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ณด๋‚ด๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ JSON ํ˜•์‹์ด ์•„๋‹ˆ๋ผ XML์ด๋ผ๋ฉด, ์œ„ ๊ณต์‹ ๋ฌธ์„œ์˜ ์„ค๋ช…๋Œ€๋กœ GSON ๋Œ€์‹  Simple XML Converter ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ๋œ๋‹ค.
 

#3-3 Coroutine, LiveData ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€  (๋ชจ๋“ˆ ์ˆ˜์ค€ build.gradle)

plugins {
    ...
}

android {
    ...
}

dependencies {

    ...

    // Retrofit
    ...

    // Coroutines
    val coroutinesVersion = "1.6.4"
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion")

    // ViewModel, LiveData
    val lifecycleVersion = "2.5.1"
    implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycleVersion")
}

์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›๋Š” ์ž‘์—…์„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ์—์„œ ์ง„ํ–‰ํ•  ๊ฒƒ์ด๋ฏ€๋กœ, ์ฝ”๋ฃจํ‹ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ฐ›์•„์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•œ ViewModel ๋ฐ LiveData ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ์ถ”๊ฐ€ํ•œ๋‹ค.
 
๋งˆ์ง€๋ง‰์œผ๋กœ, ์•ˆ๋“œ๋กœ์ด๋“œ ์ŠคํŠœ๋””์˜ค ์ƒ๋‹จ์— ๋œจ๋Š” 'Sync Now' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•œ๋‹ค.
 

#4 Data Class ๋งŒ๋“ค๊ธฐ

#4-1 AlbumsItem.kt

package com.example.retrofitbasics


import com.google.gson.annotations.SerializedName

data class AlbumsItem(
    @SerializedName("userId")
    val userId: Int,

    @SerializedName("id")
    val id: Int,

    @SerializedName("title")
    val title: String,
)

/*
{
    "userId": 1,
    "id": 1,
    "title": "Album Title"
}

โ†‘ ์ด ํด๋ž˜์Šค๋Š” ์œ„์™€ ๊ฐ™์€ JSON ๋ฐ์ดํ„ฐ๋ฅผ, ์•„๋ž˜์™€ ๊ฐ™์€ Kotlin ๊ฐ์ฒด๋กœ ๋ฐ”๊พผ๋‹ค. โ†“

val myAlbum = AlbumsItem(id = 1, title = "Album Title", userId = 1)
*/

GSON ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์–ด๋…ธํ…Œ์ด์…˜์ธ @SerializedName()์„ ํ™œ์šฉํ•ด, GSON ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์„œ๋ฒ„๊ฐ€ ๋ณด๋‚ด์ค€ JSON์„ ํŒŒ์‹ฑํ•  ๋•Œ ์ฐธ์กฐํ•  Key ์ •๋ณด๋ฅผ ๋„ฃ๋Š”๋‹ค.
 

#4-2 Albums.kt

// package com.example.retrofitbasics


class Albums : ArrayList<AlbumsItem>()

AlbumsItem๋ฅผ ArrayList์— ๋„ฃ์€ ๊ฐ์ฒด๋‹ค. ์ด๋ ‡๊ฒŒ ๊ตณ์ด ๋‚˜๋ˆ„๋Š” ์ด์œ ๋Š”, ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์•„์˜ฌ JSON ์•„์ดํ…œ ํ•˜๋‚˜์— @SerializedName()๊ฐ€ ์“ฐ์ธ #4-1์˜ data class ํ•˜๋‚˜๊ฐ€ ๋งค์นญ๋˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ, ์ฆ‰ JSON ๊ฐ์ฒด ํ•˜๋‚˜์™€ ์ฝ”ํ‹€๋ฆฐ ๊ฐ์ฒด๊ฐ€ 1๋Œ€1๋กœ ๋งค์นญ๋˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์ง๊ด€์ ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. #4-1๊ณผ #4-2๋ฅผ ํ•˜๋‚˜๋กœ ํ•ฉ์น˜๋ฉด ์˜คํžˆ๋ ค ๋ณต์žกํ•ด์งˆ ๊ฒƒ์ด๋‹ค. ํ•˜์—ฌํŠผ ์•ž์œผ๋กœ Albums ํด๋ž˜์Šค๋Š” ์ดํ›„๋กœ AlbumsItem์„ ํ•˜๋‚˜ํ•˜๋‚˜ ๋‹ด๋Š” ๊ทธ๋ฆ‡์œผ๋กœ ๊ธฐ๋Šฅํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.
 

#4-3 (์—ฌ๋‹ด) kapt ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—†์ด ์–ด๋…ธํ…Œ์ด์…˜(@)์ด ์กด์žฌํ•˜๋Š” ์ด์œ 

๋”๋ณด๊ธฐ

์–ด๋…ธํ…Œ์ด์…˜(@)์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ kapt๋ฅผ build.gradle์˜ dependencies { ... }์— ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์•˜์Œ์—๋„ #4-1์˜ ์ฝ”๋“œ๊ฐ€ ์—๋Ÿฌ์—†์ด ์ปดํŒŒ์ผ์ด ๋˜๋Š” ์ด์œ ๊ฐ€ ๋ญ˜๊นŒ?

 

kapt๋Š” ์–ด๋…ธํ…Œ์ด์…˜์„ ๊ทธ์ € '์ฝ๊ฒŒ ํ•ด์ฃผ๋Š”' ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. kapt ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๊ฐœ์ž…์—†์ด ์†Œ์Šค ์ฝ”๋“œ์— ์–ด๋…ธํ…Œ์ด์…˜(@)์ด ์žˆ๋‹ค๊ณ  ์ปดํŒŒ์ผ์ด ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค. kapt์˜ ์ง„์งœ ์šฉ๋„๋Š”, ์ปดํŒŒ์ผ ํƒ€์ž„์— ํŠน์ • ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ๊ฒ€์ฆํ•˜๋Š” ๋ฐ์— ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, Room์—์„œ ์“ฐ์ด๋Š” ์–ด๋…ธํ…Œ์ด์…˜๋“ค์€, ์ปดํŒŒ์ผ ๋•Œ์— Sqlite ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๊ด€๋ จ๋œ ์ฝ”๋“œ๋ฅผ ์•”์‹œ์ ์œผ๋กœ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ Room์˜ ๊ตฌ์กฐ๊ฐ€ ์ œ๋Œ€๋กœ ์ง€์ผœ์ง€๋Š” ์ง€ ํ™•์ธํ•˜๋Š” ์šฉ๋„๋กœ ์‚ฌ์šฉ๋œ๋‹ค. ์ด ๋•Œ kapt๊ฐ€ ๊ทธ ๊ณผ์ •์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๋ฐ˜๋ฉด, ์œ„ ์ฝ”๋“œ์˜ ์–ด๋…ธํ…Œ์ด์…˜์ธ @SerializedName()์€ ์ปดํŒŒ์ผ ๋•Œ ๋ญ”๊ฐˆ ํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋Œ€์‹  ๋Ÿฐํƒ€์ž„ ์‹œ์ ์—, @SerializedName()์˜ ์ •๋ณด๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ JSON์„ ํŒŒ์‹ฑ์— ํ™œ์šฉํ•œ๋‹ค.

 

#5 Service Interface ๋งŒ๋“ค๊ธฐ

// package com.example.retrofitbasics

import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Query


interface AlbumService {

    @GET("/albums")
    suspend fun getAlbums(): Response<Albums>

    @GET("/albums")
    suspend fun getSortedAlbums(@Query("userId") userId: Int): Response<Albums>
}

HTTP ๋ฉ”์†Œ๋“œ์™€ ํ•จ๊ป˜ ๋‹ค๋ฃฐ ์ž์›์˜ ์œ„์น˜(์ด ๊ฒŒ์‹œ๊ธ€์˜ #2-2 ์ฐธ์กฐ)๋ฅผ ๋ฉ”์†Œ๋“œ์˜ ํ˜•ํƒœ๋กœ ํ•˜๋‚˜์”ฉ ๊ธฐ์ˆ ํ•œ๋‹ค. ์ด ํ•จ์ˆ˜๋ฅผ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰์‹œํ‚ฌ ๊ฒƒ์ด๋ฏ€๋กœ suspend ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์ธ๋‹ค. ๋ฐ˜ํ™˜ํ˜•์€ Response<>๋กœ, Retrofit์€ ํ•ญ์ƒ Response<>์˜ ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. Query Parameter๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ getSortedAlbums()์™€ ๊ฐ™์€ ํ˜•์‹์œผ๋กœ ๋ฉ”์†Œ๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.
 

#6 Retrofit Instance ๋งŒ๋“ค๊ธฐ

// package com.example.retrofitbasics

import com.google.gson.GsonBuilder
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

class RetrofitInstance {
    companion object {
        val BASE_URL = "https://jsonplaceholder.typicode.com/"
        fun getRetrofitInstance(): Retrofit {
            return Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(GsonBuilder().create()))
                .build()
        }

    }
}

Retrofit์˜ ์ธ์Šคํ„ด์Šค๋Š” Retrofit.Builder()๋ผ๋Š” ๋นŒ๋” ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด ์ƒ์„ฑ๋œ๋‹ค. Service Interface์—์„œ ๊ธฐ์ˆ ํ–ˆ๋˜ '๋‹ค๋ฃฐ ์ž์›์˜ ์œ„์น˜'์— ๋Œ€ํ•ด ๊ทธ ๊ธฐ๋ฐ˜์ด ๋˜๋Š” ๊ธฐ๋ณธ URL๊ณผ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ JSON ๋“ฑ์˜ ํŒŒ์ผ ํ˜•์‹์„ ์ฝ”ํ‹€๋ฆฐ ๊ฐ์ฒด๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” Converter๋ฅผ Retrofit.Builder()์— ๋‹ฌ์•„์ค€ ๋‹ค์Œ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
 

#7 Service Class ๋งŒ๋“ค๊ธฐ

// package com.example.retrofitbasics

...

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        ...

        val retrofitService = RetrofitInstance.getRetrofitInstance().create(AlbumService::class.java)
    }
}

#6์—์„œ ์ƒ์„ฑ๋œ Retrofit์˜ ์ธ์Šคํ„ด์Šค์—์„œ Service Interface๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›๋Š” Retrofit.create() ๋ฉ”์†Œ๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด Service Interface์˜ ๊ตฌํ˜„์ฒด(Service Class)๋ฅผ ๋งŒ๋“ ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด ๊ตฌํ˜„์ฒด์˜ ๋ฉ”์†Œ๋“œ๋“ค(= Service Interface์—์„œ ์ •์˜ํ–ˆ๋˜ ๋ฉ”์†Œ๋“œ๋“ค)๋กœ ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•  ๊ฒƒ์ด๋‹ค.
 

#8 ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์•„์˜จ ๋ฐ์ดํ„ฐ ํ™”๋ฉด์— ํ‘œ์‹œํ•˜๊ธฐ

#8-1 activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="1.0">

        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text=""
            android:textSize="30dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </ScrollView>

</androidx.constraintlayout.widget.ConstraintLayout>

๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌ์„ฑํ•œ๋‹ค. ScrollView ํ•˜๋‚˜ ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์•ˆ์— TextView ํ•˜๋‚˜๋ฅผ ๋ฐฐ์น˜ํ•œ๋‹ค.
 

#8-2 MainAcitivity.kt

...

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val retrofitService =
            RetrofitInstance.getRetrofitInstance().create(AlbumService::class.java)

        val textView = findViewById<TextView>(R.id.textView)

        val responseLiveData: LiveData<Response<Albums>> = liveData {
            val response1 = retrofitService.getAlbums()
            val response2 = retrofitService.getSortedAlbums(7)
            emit(response1)
        }

        responseLiveData.observe(this, Observer {
            appendListOnTextView(textView, it)
        })
    }

    private fun appendListOnTextView(textView: TextView, list: Response<Albums>) {
        val albumsList = list.body()?.listIterator()
        if (albumsList != null) {

            while (albumsList.hasNext()) {
                val albumsItem = albumsList.next()
                val result =
                    "User id : ${albumsItem.userId}" + "\n" +
                    "Album id : ${albumsItem.id}" + "\n" +
                    "Album Title : ${albumsItem.title}" + "\n\n\n"

                textView.append(result)
            }
        }
    }
}

์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ๋ฐ์ดํ„ฐ Response<Albums>์„ LiveData๋กœ ์„ ์–ธํ•œ๋‹ค. LiveData Builder๋„ ์‚ฌ์šฉํ–ˆ๋‹ค. ํ•ด๋‹น LiveData์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด๊ฐ€๊ฑฐ๋‚˜ ๋ณ€ํ™”ํ•  ๋•Œ๋งˆ๋‹ค ๋ฐœ์ƒํ•˜๋Š” ์ž‘์—…์„ ๊ธฐ์ˆ ํ•˜๊ธฐ ์œ„ํ•œ LiveData.observe() ๋ฉ”์†Œ๋“œ๋„ ์ •์˜ํ•œ๋‹ค. response1์€ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ, response2๋Š” userId๊ฐ€ 7์ธ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ์ด๋ ‡๊ฒŒ userId๋ฅผ ํ•˜๋“œ ์ฝ”๋”ฉํ–ˆ์ง€๋งŒ, ์ด์–ด์ง€๋Š” ๊ธ€(#12 ์ฐธ์กฐ)์—์„œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์›ํ•˜๋Š” userId๋ฅผ ์š”์ฒญํ•˜๊ณ  ๊ทธ์— ์‘๋‹ตํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค์–ด๋ณธ๋‹ค.
 

#9 ์ž‘๋™ ํ™•์ธ

 

#10 ์š”์•ฝ

Retrofit์€ ํด๋ผ์ด์–ธํŠธ-์„œ๋ฒ„ ๊ฐ„ ํ†ต์‹ ์„ ๊ฐ„ํŽธํ•˜๋ฉฐ ์œ ์—ฐํžˆ ๊ตฌํ˜„ํ•˜๋Š” ๋„๊ตฌ๋‹ค.
 

#11 ์™„์„ฑ๋œ ์•ฑ

 

android-practice/retrofit/RetrofitBasics at master ยท Kanmanemone/android-practice

Contribute to Kanmanemone/android-practice development by creating an account on GitHub.

github.com

 

#12 ์ด์–ด์ง€๋Š” ๊ธ€

#12-1 userId ์†Œํ”„ํŠธ ์ฝ”๋”ฉ ๋ฐ ํ”„๋กœ์ ํŠธ๋ฅผ MVVM ๊ตฌ์กฐ๋กœ ๊ตฌํ˜„

 

[Android] Retrofit - MVVM ๊ตฌ์กฐ

#1 ์ด์ „ ๊ธ€ [Android] Retrofit - ๊ธฐ์ดˆ#1 ์ด์ „ ๊ธ€ [Android] Retrofit - ๋ฐฐ๊ฒฝ๊ณผ ๊ตฌ์กฐ#1 Restrofit์˜ ๋ฐฐ๊ฒฝ#1-1 REST API REST API (REpresentational State Transfer Application Programming Interface)#1 ๋ฌด์—‡(What)์— ๋Œ€ํ•œ API์ธ๊ฐ€?#1-1 ๊ฐœ์š”REST(

kenel.tistory.com

์ด์–ด์ง€๋Š” ๊ธ€์—์„œ userId๋ฅผ ํ•˜๋“œ ์ฝ”๋”ฉํ•˜๋Š” ๋Œ€์‹ , ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์— ๋”ฐ๋ผ ๋ณ€ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ ๋‹ค. ๋˜, ํ•˜๋Š” ๊น€์— MVVM์ ์ธ ๊ตฌ์กฐ๋กœ ๋งŒ๋“ค์–ด๋ณธ๋‹ค.

 

#12-2 Logging๊ณผ Timeout ์„ค์ •

 

[Android] Retrofit - Logging, Timeout ๊ด€๋ฆฌ (Interceptor)

#1 ์ด์ „ ๊ธ€ [Android] Retrofit - ๊ธฐ์ดˆ#1 ์ด์ „ ๊ธ€ [Android] Retrofit - ๋ฐฐ๊ฒฝ๊ณผ ๊ตฌ์กฐ#1 Restrofit์˜ ๋ฐฐ๊ฒฝ#1-1 REST API REST API (REpresentational State Transfer Application Programming Interface)#1 ๋ฌด์—‡(What)์— ๋Œ€ํ•œ API์ธ๊ฐ€?#1-1 ๊ฐœ์š”RE

kenel.tistory.com

Retrofit Instance๊ฐ€ ํ†ต์‹  ๊ธฐ๋ก(Log)์„ ๋‚จ๊ธฐ๊ฒŒ ๋งŒ๋“ ๋‹ค. ๋˜, Retrofit Instance๊ฐ€ ์„œ๋ฒ„-ํด๋ผ์ด์–ธํŠธ ๊ฐ„ ํ†ต์‹ ์„ ์„ฑ๊ณต ๋˜๋Š” ์‹คํŒจ(Timeout)๋กœ ํŒ๋‹จํ•˜๋Š” ๊ทœ์น™์„ ๋ฐ”๊ฟ”๋ณธ๋‹ค.

 

#12-3 Post ์š”์ฒญ ๊ตฌํ˜„

 

[Android] Retrofit - Post

#1 ์ด์ „ ๊ธ€ [Android] Retrofit - ๊ธฐ์ดˆ#1 ์ด์ „ ๊ธ€ [Android] Retrofit - ๋ฐฐ๊ฒฝ๊ณผ ๊ตฌ์กฐ#1 Restrofit์˜ ๋ฐฐ๊ฒฝ#1-1 REST API REST API (REpresentational State Transfer Application Programming Interface)#1 ๋ฌด์—‡(What)์— ๋Œ€ํ•œ API์ธ๊ฐ€?#1-1 ๊ฐœ์š”RE

kenel.tistory.com

์„œ๋ฒ„์— Post ์š”์ฒญ์„ ํ•ด๋ณธ๋‹ค. (์ฐธ์กฐ: REST API)