Retrofit
retrofit이란
android에서 REST API와 통신하기 위한 네트워크 라이브러리.
HTTP 요청을 더 쉽게 만들며, 응답을 model 객체로 변환할 수 있다.
Jetpack Compose는 UI Framework이므로, 네트워크 라이브러리인 Retrofit을 사용할 수 있는데
이 과정에서 ViewModel과 함께 사용하면 API 데이터를 UI에 반영할 수 있다.
코드가 간결하고, 유지보수가 쉬워 REST API 호출 시 가장 많이 쓰인다.
장단점
ㅇ 장점
1. 간결하고 직관적인 코드 : 인터페이스로 API를 정의하고, annotation을 사용해 간편한 API 요청 가능.
(OkHttp에 비해 코드가 깔끔)
2. Coroutine/Callback 등의 비동기 처리 지원
- Coroutine 기반 비동기 처리 : suspend fun 사용
- 콜백 방식 : enqueue()
- RxJava 지원
3. 자동 JSON 변환 : JSON 응답을 자동으로 데이터 클래스에 매핑 -> 파싱 편리
(Gson, Moshi, Kotlinx Serialization 등 사용 가능)
4. 동적 URL, query parameter 지원
- {}를 사용한 동적 엔드포인트 설정
- @Query로 query parameter 추가 가능
5. OkHttp와 조합 가능 : 네트워크 로깅, header 조작, 캐싱 등 기능 추가 가능
ㅇ 단점
1. GraphQL 지원 부족
- REST API에는 최적화, 그러나 GraphQL 같은 API에는 맞지x
- Apollo GraphQL 등의 라이브러리 사용 필요
2. 대용량 데이터 처리 overhead
- JSON 자동 변환 시 메모리 사용량 증가
- 대량의 데이터 처리를 위해 streaming 방식 필요
3. 복잡한 API 요청 구성 시 복잡도 증가
- 파일 업로드 / 멀티파트 요청 등은 코드가 복잡해짐 -> OkHttp 사용
* retrofit2?
Square에서 개발한 REST API 통신 라이브러리.
Retrofit1을 개선한 버전. OkHttp 기반으로 동작함.
성능과 유연성이 더 좋아짐.
Retrofit1 | Retrofit2 | |
기반 | HttpURLConnection | OkHttp |
비동기 방식 | 내부적으로 AsyncTask 사용 | Call.enqueue(), Coroutine, RxJava 지원 |
에러 처리 | 예외 발생 | Response<T>로 성공/실패 구분 가능 |
JSON 변환 | GsonConverter만 지원 | Gson뿐만 아니라 Moshi, Kotlinx Serialization 등 다양한 컨버터 지원 |
CallBack 인터페이스 | 전역 설정 가능 | 개별 요청마다 Call 객체 사용 |
사용법 (with. jetpack compose)
1. retrofit 라이브러리 추가
- app 모듈의 build.gradle.kts : dependency 추가
dependencies {
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0") // JSON 변환기
}
* gson 변환기?
API 응답을 자동으로 JSON에서 데이터 클래스로 변환해주는 역할
2. API 인터페이스 정의 : HTTP 요청 (GET, POST 등)
여기서는 제일 단순한 GET 요청을 기준으로 작성하였다.(POST method와 posts는 관련 없음)
import retrofit2.http.GET
interface ApiService {
@GET("posts") // API 엔드포인트 posts - HTTP GET 요청
suspend fun getPosts(): List<Post> // suspend fun : coroutine을 사용한 비동기 처리
}
3. 데이터 모델 생성 : API 응답을 받아올 데이터 클래스
import com.google.gson.annotations.SerializedName
data class Post(
val id: Int,
val title: String,
@SerializedName("body") val content: String // @SerializedName() : JSON 필드명과 변수명 매칭
)
4. Retrofit 객체 생성 : API 기본 설정
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object RetrofitInstance {
private const val BASE_URL = "https://jsonplaceholder.typicode.com/"
val api: ApiService by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create()) // JSON 자동 변환
.build()
.create(ApiService::class.java)
}
}
5. ViewModel에서 API 호출 - StateFlow 활용
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
class PostViewModel : ViewModel() {
// Compose에서 UI 업데이트를 쉽게 하기 위해 MutableStateFlow 사용
private val _posts = MutableStateFlow<List<Post>>(emptyList())
val posts: StateFlow<List<Post>> = _posts
init {
fetchPosts()
}
private fun fetchPosts() {
viewModelScope.launch { // ViewModel에서 비동기 네트워크 호출을 실행하기 위해
try {
_posts.value = RetrofitInstance.api.getPosts()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
6. jetpack compose UI에서 데이터 표시 - Flow data binding
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.*
import androidx.compose.material3.*
import androidx.lifecycle.viewmodel.compose.viewModel
@Composable
fun PostScreen(viewModel: PostViewModel = viewModel()) {
val posts by viewModel.posts.collectAsState() // Flow 데이터를 관찰해 UI를 업데이트 함
LazyColumn { // 리스트 형태로 API 데이터 출력
items(posts) { post ->
Card(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(text = post.title, style = MaterialTheme.typography.titleLarge)
Text(text = post.content, style = MaterialTheme.typography.bodyMedium)
}
}
}
}
}
출처 : Retrofit