Retrofit 란?
- Retrofit 은 Java 에서 REST Client 를 간편하게 구현할 수 있도록 기능을 제공하는 라이브러리이다.
- Spring Web 에서 제공하는 RestTemplate 도 이와 동일한 기능을 제공하지만, Retrofit 을 사용할 때가 코드 가독성과 편의성이 좀더 높다.
- Retrofit 은 Annotation 과 Interface 로 선언된 HTTP API 명세를 기반으로 HTTP API 구현체를 생성해준다.
- Retrofit 은 HTTP API 의 요청과 응답에서 타입을 강제하여 Type Safe 한 장점을 제공한다.
- 타입이 강제되기 때문에 개발 과정에서 요청과 응답에 대한 예측이 가능하다.
의존성 추가
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'
구현
HTTP API interface 선언
public interface RetrofitApiTest {
@GET("api/sr/retrofit-test")
Call<APIDataResponse<String>> test();
}
- HTTP Method - @GET, @POST, @PUT, @DELETE 를 제공한다.
- Request Body 를 표현하는 @Body 를 제공한다.
- Form-encoded 를 표현하는 @FormUrlEncoded 를 제공한다.
- MultiPart 를 표현하는 @Part 를 제공한다.
- Path Variable 을 표현하는 @Path 를 제공한다.
- Query Parameter 을 표현하는 @Query 를 제공한다.
- 요청 Header 를 표현하는 @Headers 또는 @Header 를 제공한다.
Builder 구현
public static Retrofit initRetrofit(String baseUrl) {
return new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(httpClient.build())
.build();
}
- HTTP 통신에 대한 baseUrl 과 converter 등을 설정한다.
- 선언된 HTTP API Interface 를 생성하는 Retrofit 객체를 생성한다.
- hrrtClient 선언 시 Connection Timeout, ReadTimeout 설정이 가능하고, HTTP 요청과 응답에 대한 로깅을 남기는 Interceptor 선언도 가능하다.
Retrofit.create()
@Bean
public RetrofitApiTest retrofitOrderApi() {
var retrofit = RetrofitUtils.initRetrofit(baseUrl);
return retrofit.create(RetrofitApiTest.class);
}
- Retrofit.create() 메소드를 활용하여 사전에 선언한 HTTP API Interface 의 실제 구현체를 생성하고 사용한다.
RetrofitUtils 전체 코드
public class RetrofitUtils {
private static final HttpLoggingInterceptor loggingInterceptor
= new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
private static final OkHttpClient.Builder httpClient = new OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.connectTimeout(3, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS);
private static final Gson gson = new GsonBuilder()
.setLenient()
.create();
public static Retrofit initRetrofit(String baseUrl) {
return new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(httpClient.build())
.build();
}
public <T extends APIDataResponse> Optional<T> responseSync(Call<T> call) {
try {
Response<T> execute = call.execute();
if (execute.isSuccessful()) {
return Optional.ofNullable(execute.body());
} else {
log.error("requestSync errorBody = {}", execute.errorBody());
throw new RuntimeException("retrofit execute response error");
}
} catch (IOException e) {
log.error("", e);
throw new RuntimeException("retrofit execute IOException");
}
}
public void responseVoid(Call<Void> call) {
try {
if (!call.execute().isSuccessful()) throw new RuntimeException();
} catch (IOException e) {
throw new RuntimeException();
}
}
}
- 위와 같이 로깅을 위한 인터셉터와 httpClient 설정을 해준다.
- responseSync 메소드의 결과 값으로 직접 커스텀한 APIDataResponse 를 넘겨준다.
- 실제로 responseSync 메소드가 호출 되는 시점에 REST Client 요청이 호출된다.
REFERENCES
- 이희창님의 Java/Spring 기반 서비스 개발