Table of Content
SpringBoot Retrofit 연동하기
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
의존성 추가
retrofit2 버전은 2.7.X 로 합니다.
상위 버전을 이용하려면, JDK 를 8로 내리거나, 14로 올려야 합니다.
dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.7.2'
implementation 'com.squareup.retrofit2:converter-jackson:2.7.2'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
implementation 'com.squareup.okhttp3:logging-interceptor'
}
소스코드 추가
public class ApiClient {
private static final String BASE_URL = "https://dapi.kakao.com/";
private static Retrofit retrofit;
public static Retrofit getApiClient() {
// HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
// interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
// OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
ObjectMapper mapper = Jackson2ObjectMapperBuilder.json()
.featuresToDisable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
.modules(new JavaTimeModule())
.build();
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
// .client(client)
.addConverterFactory(JacksonConverterFactory.create(mapper))
.build();
}
return retrofit;
}
}
public interface ApiInterface {
// 장소이름으로 검색
@GET("v2/local/search/keyword.json")
Call<CategoryResult> getSearchLocation(
@Header("Authorization") String token,
@Query("query") String query,
@Query("category_group_code") String categoryGroupCode,
@Query("size") int size, // 1 ~ 15
@Query("page") int page, // 1 ~ 45
@Query("sort") String sort, // distance 또는 accuracy (기본값: accuracy)
@Query("x") String x,
@Query("y") String y
);
}
@Getter
public class CategoryResult {
// private Meta meta;
private List<Document> documents = null;
}
@Getter
@Setter
@NoArgsConstructor
public class Document {
@JsonProperty("place_name")
private String placeName;
}
테스트 코드 추가
@SpringBootTest
@SpringBootConfiguration
public class ApiClientTest {
@Value("${kakao.restapi.key}")
private String restApiKey;
@BeforeEach
public void setUp() throws Exception {
}
@Test
public void getApiClient() {
// given
// when
ApiInterface apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
Call<CategoryResult> call = apiInterface.getSearchLocation(
restApiKey,
"김치찌개",
"FD6", // 음식점
15,
1,
"accuracy", // distance
"0",
"0";
// then
try {
Response<CategoryResult> response = call.execute();
assertTrue(response.isSuccessful());
CategoryResult result = response.body();
assert result != null;
List<Document> documents = result.getDocuments();
assertTrue(documents.size() > 0);
Document document = documents.get(0);
System.out.println(document.getPlaceName());
} catch (Exception e) {
System.out.println(e);
}
}
}
비동기 호출
API 서버쪽은 비동기 호출이 앞뒤가 안맞는 듯 하다.
클라이언트에서 비동기 호출하는것이 맞는 듯 하다.
@Test
public void getApiClientAsync() throws InterruptedException {
// given
Map<String, String> params = new HashMap<>();
params.put("p", "1");
params.put("s", "15");
params.put("q", "김치찌개");
KakaoSearchDto searchDto = new KakaoSearchDto(params);
// when
ApiInterface apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
Call<CategoryResult> call = apiInterface.getSearchLocation(
restApiKey,
searchDto.getQueryString(),
"FD6", // 음식점
searchDto.getPageSize(),
searchDto.getPageNo(),
"accuracy", // distance
searchDto.getLongitude().toString(),
searchDto.getLatitude().toString());
System.out.println("start async call : " + call.hashCode());
call.enqueue(new Callback<>() {
@Override
public void onResponse(Call<CategoryResult> call, Response<CategoryResult> response) {
System.out.println("onResponse called : " + call.hashCode());
if (response.isSuccessful()) {
try {
CategoryResult result = response.body();
assert result != null;
List<Document> documents = result.getDocuments();
assertTrue(documents.size() > 0);
Document document = documents.get(0);
System.out.println(document.getPlaceName());
System.out.println(document.getCategoryName());
} catch (Exception e) {
System.out.println(e);
}
} else {
System.out.println("Request Error :: " + response.errorBody());
}
}
@Override
public void onFailure(Call<CategoryResult> call, Throwable t) {
System.out.println("onFailure called");
System.out.println("Network Error :: " + t.getLocalizedMessage());
}
});
System.out.println("sleep 5 seconds");
Thread.sleep(5000);
System.out.println("end main thread");
// then
}