Retrofit Singleton 패턴을 유지하면서 ApiService를 기능별로 분리하기
2025. 2. 17. 16:35ㆍAndroid/네트워킹
728x90
반응형
Retrofit을 이용하여 API 통신을 하려면 Retrofit 객체를 만들어야 한다.
이 때, 객체에 BaseURL을 주입해줘야 하는데 대부분의 프로젝트에서는 url이 하나로 통일되지는 않을 것이다.
게다가 앱 규모가 커질수록 API 호출 개수는 무수히 많아지는데
이걸 하나의 파일에서 관리하기는 불가능.
Retrofit 객체를 싱글톤으로 유지하면서 APIService를 기능별로 분리하려면 어떻게 해야할까?
1️⃣ API 인터페이스를 기능별로 분리
각 도메인(feature)별로 @Headers를 추가해서 Base URL을 구분하면 된다.
✅ AService
interface AService {
@GET("endpoint-a")
@Headers("Base-Url: API_A")
suspend fun getSomethingA(): Response<AResponse>
}
✅ BService
interface BService {
@GET("endpoint-b")
@Headers("Base-Url: API_B")
suspend fun getSomethingB(): Response<BResponse>
}
✅ CService
interface CService {
@GET("endpoint-c")
@Headers("Base-Url: API_C")
suspend fun getSomethingC(): Response<CResponse>
}
2️⃣ Retrofit을 싱글톤으로 유지하면서 각각의 Service 제공
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@Singleton
fun provideOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(BaseUrlInterceptor()) // Base URL 변경 Interceptor
.build()
}
@Provides
@Singleton
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl("<https://default-api.com/>") // 기본 Base URL (변경 가능)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
@Provides
fun provideAService(retrofit: Retrofit): AService {
return retrofit.create(AService::class.java)
}
@Provides
fun provideBService(retrofit: Retrofit): BService {
return retrofit.create(BService::class.java)
}
@Provides
fun provideCService(retrofit: Retrofit): CService {
return retrofit.create(CService::class.java)
}
}
3️⃣ Base URL을 변경하는 Interceptor
Retrofit은 기본적으로 하나의 Base URL을 가지지만, OkHttp의 Interceptor를 사용하면 동적으로 변경할 수 있다.
class BaseUrlInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()
val originalHttpUrl = originalRequest.url
// 헤더에서 특정 Base URL 키 가져오기 (예: "Base-Url")
val baseUrlHeader = originalRequest.header("Base-Url")
val newBaseUrl = when (baseUrlHeader) {
"API_A" -> "<https://api-a.com/>"
"API_B" -> "<https://api-b.com/>"
"API_C" -> "<https://api-c.com/>"
else -> originalHttpUrl.toString() // 기본값 유지
}
// 새로운 URL을 기반으로 요청 변경
val newHttpUrl = originalHttpUrl.newBuilder()
.scheme("https")
.host(newBaseUrl.removePrefix("https://").removeSuffix("/"))
.build()
val newRequest = originalRequest.newBuilder()
.url(newHttpUrl)
.build()
return chain.proceed(newRequest)
}
}
이렇게 작업을 하면 BaseURL 별로 Retrofit 객체를 생성하지 않으면서
기능별로 ApiService 파일을 구분해서 관리할 수 있게 된다.
728x90
반응형
'Android > 네트워킹' 카테고리의 다른 글
[Android] 특정 국가 차단하기 (SIM 정보 이용) (0) | 2025.03.27 |
---|---|
Android에서 OkHttp 통신 시 Memory를 최적화 하기 위한 체크 포인트 (0) | 2025.01.21 |
[Android/Java/Kotlin]ExecutorService (0) | 2023.05.29 |
[Android/Async]Process, Thread에 대한 기본개념 (0) | 2023.02.26 |