Android Retrofit 설명
Retrofit은 Square에서 개발한 안드로이드 및 JVM 환경에서 사용되는 타입-세이프(type-safe) HTTP 클라이언트 라이브러리입니다.
REST API 기반의 네트워크 통신을 간편하고 효율적으로 처리할 수 있도록 도와줍니다.
Retrofit의 주요 특징:
- 타입 안정성: Retrofit은 인터페이스를 사용하여 API 엔드포인트를 정의하고, 어노테이션을 통해 HTTP 요청 메서드(GET, POST, PUT, DELETE 등)와 파라미터를 명시합니다.
- 이를 통해 컴파일 시점에 오류를 확인할 수 있어 안정적인 코드 작성이 가능합니다.
- 선언적인 API: Retrofit은 선언적인 방식으로 API 인터페이스를 정의하여 코드의 가독성을 높이고 유지보수를 용이하게 합니다.
- 비동기 처리: Retrofit은 기본적으로
OkHttp 라이브러리
를 사용하여 네트워크 요청을 비동기적으로 처리합니다.- 따라서 UI 스레드를 차단하지 않고 백그라운드 스레드에서 네트워크 작업 수행
- 확장성: Retrofit은 Converter, CallAdapter 등 다양한 확장 기능을 제공하여 JSON, XML 등 다양한 데이터 형식을 지원하고, RxJava, Coroutines 등 다양한 비동기 처리 방식을 사용할 수 있습니다.
Retrofit 구성 요소
1. 인터페이스 (Interface):
- REST API의 엔드포인트를 정의합니다.
- 각 엔드포인트는 HTTP 메서드(GET, POST, PUT, DELETE 등)와 URL 경로, 파라미터 등을 포함합니다.
- Retrofit은 이 인터페이스를 기반으로 동적인 프록시 객체를 생성하여 실제 네트워크 요청을 처리합니다.
|
|
2. 어노테이션 (Annotation):
- 인터페이스의 메서드에 사용되어 HTTP 요청 정보를 명시합니다.
@GET
,@POST
,@PUT
,@DELETE
,@PATCH
,@HEAD
등의 HTTP 메서드 어노테이션을 사용하여 요청 방식을 지정합니다.@Path
,@Query
,@Body
,@Header
등의 어노테이션을 사용하여 URL 경로, 쿼리 파라미터, 요청 본문, 헤더 등을 설정합니다.
|
|
3. Retrofit 객체:
- 인터페이스를 기반으로 동적인 프록시 객체를 생성합니다.
Retrofit.Builder
를 사용하여 Retrofit 객체를 생성하고, 베이스 URL, Converter, CallAdapter 등을 설정합니다.
|
|
4. Call 객체:
- 네트워크 요청(Request) 을 나타내는 객체입니다.
enqueue()
메서드를 호출하여 비동기 요청을 보내고,execute()
메서드를 호출하여 동기 요청을 보냅니다.- 콜백 메서드(
onResponse
,onFailure
)를 통해 요청 결과를 처리합니다.
|
|
5. Converter:
- 서버 응답 데이터(JSON)를 객체로 변환하는 역할을 합니다.
- Gson, Moshi, Jackson 등의 라이브러리를 Converter로 사용할 수 있습니다.
Retrofit.Builder
의addConverterFactory()
메서드를 사용하여 Converter를 추가합니다.
Android Retrofit 사용 시 주의 사항
1. 메인 스레드 네트워크 작업 금지:
- Retrofit은 기본적으로 OkHttp를 사용하여 네트워크 요청을 처리합니다.
- 안드로이드에서는 메인 스레드에서 네트워크 작업을 수행하면
NetworkOnMainThreadException
예외가 발생합니다. - 따라서, Coroutine, RxJava, 또는 Executor 등을 사용하여 네트워크 요청을 백그라운드 스레드에서 처리해야 합니다.
2. 에러 핸들링:
- 네트워크 요청은 항상 실패할 가능성이 있으므로, 예외 처리를 철저히 해야 합니다.
- Retrofit은
onFailure()
콜백 또는 RxJava의onError()
메서드를 통해 에러를 처리할 수 있습니다. - HTTP 상태 코드(404, 500 등)에 따른 적절한 에러 메시지를 사용자에게 표시해야 합니다.
3. 응답 데이터 처리:
- 서버에서 받은 응답 데이터는 JSON, XML 등 다양한 형식일 수 있습니다.
- Retrofit은 Gson, Moshi, Jackson 등의 Converter를 사용하여 응답 데이터를 자바 객체로 변환할 수 있습니다.
- 데이터 변환 과정에서 발생할 수 있는 예외를 처리해야 합니다.
Android Retrofit 에서 coroutine을 사용하면, 백그라운드 스레드에서 처리되는 이유
1. Main Thread 안전성 (Main Thread Safety):
안드로이드는 UI 업데이트와 사용자 입력 처리를 담당하는 메인 스레드(Main Thread) 를 가지고 있습니다.
메인 스레드에서 시간이 오래 걸리는 작업(예: 네트워크 요청)을 수행하면 UI가 멈추거나 응답하지 않는 현상이 발생할 수 있습니다.
- 이를 ANR(Application Not Responding) 이라고 합니다.
Coroutine은
suspend
함수를 통해 비동기 작업을 간편하게 처리할 수 있도록 도와주는 기능입니다.Retrofit과 Coroutine을 함께 사용하면
suspend
함수 내에서 네트워크 요청을 수행하고, 요청이 완료될 때까지 해당 Coroutine을 일시 중단(suspend)시킵니다.이때 Coroutine은 백그라운드 스레드로 전환되어 네트워크 요청을 처리 하고, 요청이 완료되면 다시 메인 스레드로 돌아와 결과를 처리 합니다.
이러한 방식으로 메인 스레드를 차단하지 않고 네트워크 요청을 처리하여 UI의 반응성을 유지할 수 있습니다.
2. Retrofit의 Main Safety 보장:
- Retrofit 2.6.0 버전부터는 Coroutine을 공식적으로 지원하며,
suspend
함수를 사용하여 네트워크 요청을 수행할 수 있습니다. - Retrofit은 내부적으로 OkHttp 라이브러리를 사용하여 네트워크 요청을 처리하는데, OkHttp는 기본적으로 백그라운드 스레드에서 네트워크 작업을 수행하도록 설계되어 있다.
- 따라서 Retrofit에서 Coroutine을 사용하더라도, 실제 네트워크 요청은 OkHttp에 의해 백그라운드 스레드에서 처리됩니다.
- 이는 Coroutine의 Main Safety 보장 기능과 함께 작동하여, 개발자가 명시적으로 백그라운드 스레드를 지정하지 않아도 안전하게 네트워크 요청을 처리할 수 있도록 합니다.
Android OkHttp 설명
OkHttp는 Square에서 개발한 강력하고 효율적인 HTTP 클라이언트 라이브러리입니다. 안드로이드 뿐만 아니라 자바 및 코틀린 환경에서도 사용할 수 있습니다.
OkHttp는 HTTP/2, WebSocket 등 최신 웹 기술을 지원하며, 안정성과 성능이 뛰어나다는 장점을 가지고 있습니다.
OkHttp 주요 특징:
- HTTP/2 지원: HTTP/2 프로토콜을 지원하여 다중화, 헤더 압축, 서버 푸시 등의 기능을 활용하여 네트워크 성능을 향상시킵니다.
- 연결 풀링: 연결 풀링을 통해 여러 요청을 효율적으로 처리하고, 연결 재사용을 통해 성능을 최적화합니다.
- 투명한 GZIP 압축: 응답 데이터를 자동으로 압축하여 네트워크 대역폭을 절약합니다.
- 응답 캐싱: 응답 데이터를 캐싱하여 동일한 요청을 반복할 때 네트워크 트래픽을 줄이고 응답 시간을 단축합니다.
- 요청 재시도: 네트워크 오류 발생 시 자동으로 요청을 재시도하여 안정성을 높입니다.
- Interceptor 지원: Interceptor를 사용하여 요청 및 응답을 가로채서 로깅, 헤더 추가, 인증 등 다양한 작업을 수행할 수 있습니다.
- WebSocket 지원: WebSocket 프로토콜을 지원하여 실시간 양방향 통신을 구현할 수 있습니다.
OkHttp와 Retrofit의 관계:
Retrofit은 OkHttp의 기능을 활용하면서, 더욱 간편하고 직관적인 API를 제공하여 REST API 통신을 쉽게 구현할 수 있도록 도와줍니다.
OkHttp: 저수준 HTTP 클라이언트, 강력하고 유연하지만 사용하기 복잡
Retrofit: OkHttp 기반 고수준 라이브러리, 간편하고 직관적인 API, 선언적 방식, 비동기 처리 지원
OkHttp 사용 방법:
OkHttpClient 생성:
OkHttpClient
객체를 생성하고 필요에 따라 설정을 변경합니다.1 2 3 4 5
val client = OkHttpClient.Builder() .addInterceptor(HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY }) .build()
Request 생성:
Request.Builder
를 사용하여 요청 객체를 생성하고 URL, 헤더, 요청 본문 등을 설정합니다.요청 실행:
OkHttpClient
객체의newCall()
메서드를 사용하여 요청을 실행하고enqueue()
메서드를 통해 비동기적으로 응답을 처리합니다.1 2 3 4 5 6 7 8 9
client.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { // 요청 실패 처리 } override fun onResponse(call: Call, response: Response) { // 응답 성공 처리 val body = response.body?.string() } })
OkHttp Interceptor 설명
OkHttp Interceptor는 네트워크 요청 및 응답을 가로채서 추가 작업을 수행하거나 수정할 수 있는 강력한 기능입니다.
로깅, 인증, 캐싱, 헤더 수정, 요청/응답 데이터 변환 등 다양한 목적으로 활용될 수 있습니다.
1. Application Interceptor:
역할: 애플리케이션 레벨에서 요청 및 응답을 가로챕니다. 실제 네트워크 연결이 이루어지기 전후에 동작하며, 캐시된 응답에도 적용됩니다.
주요 용도:
- 로깅 (Logging): 요청 및 응답 정보를 로그로 출력하여 디버깅을 돕습니다.
- 헤더 추가 (Header Modification): 모든 요청에 공통적으로 추가해야 하는 헤더(예: 인증 토큰, API 키)를 설정합니다.
- 인증 (Authentication): 요청에 인증 정보를 추가하거나, 응답을 기반으로 인증 토큰을 갱신합니다.
- 요청/응답 수정 (Request/Response Rewriting): 요청 URL, 파라미터, 응답 데이터 등을 수정합니다.
OkHttpClient.Builder
의addInterceptor()
메서드를 사용하여 추가합니다.
2. Network Interceptor:
- 역할: 네트워크 레벨에서 요청 및 응답을 가로챕니다. 실제 네트워크 연결이 이루어질 때만 동작하며, 캐시된 응답에는 적용되지 않습니다.
- 주요 용도:
- 캐싱 (Caching): 응답 데이터를 캐시에 저장하거나 캐시된 응답을 반환하여 네트워크 트래픽을 줄입니다.
- 압축 (Compression): 요청 및 응답 데이터를 압축하여 네트워크 대역폭을 절약합니다.
- 요청 재시도 (Retry): 네트워크 오류 발생 시 자동으로 요청을 재시도합니다.
- 네트워크 연결 변경 (Connection Modification): 특정 조건에 따라 다른 네트워크 연결을 사용하도록 변경합니다.
OkHttpClient.Builder
의addNetworkInterceptor()
메서드를 사용하여 추가합니다.
Interceptor 사용 예시:
|
|
- HttpLoggingInterceptor: 요청 및 응답 정보를 로그로 출력하는 Interceptor입니다. 디버깅에 유용합니다.
커스텀 Interceptor 생성:
|
|
위 예시는 요청 헤더에 인증 토큰을 추가하는 커스텀 Interceptor를 보여줍니다.
Interceptor 활용 팁:
- 여러 Interceptor를 사용할 때는 순서가 중요합니다. 요청(Request)은 추가된 순서대로 Interceptor를 거치고, 응답(Reply)은 역순으로 Interceptor를 거칩니다.
- Interceptor는 강력한 기능을 제공하지만, 과도하게 사용하면 성능 저하를 일으킬 수 있습니다.
- Interceptor를 사용하여 민감한 정보(예: API 키, 개인 정보)를 로깅하지 않도록 주의해야 합니다.