{"id":4162,"date":"2021-12-18T13:11:49","date_gmt":"2021-12-18T04:11:49","guid":{"rendered":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=4162"},"modified":"2021-12-18T16:16:44","modified_gmt":"2021-12-18T07:16:44","slug":"springboot-retrofit-%ec%97%b0%eb%8f%99%ed%95%98%ea%b8%b0","status":"publish","type":"post","link":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=4162","title":{"rendered":"SpringBoot Retrofit \uc5f0\ub3d9\ud558\uae30"},"content":{"rendered":"<h1>SpringBoot Retrofit \uc5f0\ub3d9\ud558\uae30<\/h1>\n<p>. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .<br \/>\n. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .<br \/>\n. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .<\/p>\n<h2>\uc758\uc874\uc131 \ucd94\uac00<\/h2>\n<p>retrofit2 \ubc84\uc804\uc740 2.7.X \ub85c \ud569\ub2c8\ub2e4.<br \/>\n\uc0c1\uc704 \ubc84\uc804\uc744 \uc774\uc6a9\ud558\ub824\uba74, JDK \ub97c 8\ub85c \ub0b4\ub9ac\uac70\ub098, 14\ub85c \uc62c\ub824\uc57c \ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-gradle\">dependencies {\n    implementation &#039;com.squareup.retrofit2:retrofit:2.7.2&#039;\n    implementation &#039;com.squareup.retrofit2:converter-jackson:2.7.2&#039;\n    implementation &#039;com.fasterxml.jackson.datatype:jackson-datatype-jsr310&#039;\n    implementation &#039;com.squareup.okhttp3:logging-interceptor&#039;\n}<\/code><\/pre>\n<h2>\uc18c\uc2a4\ucf54\ub4dc \ucd94\uac00<\/h2>\n<pre><code class=\"language-java\">public class ApiClient {\n\n    private static final String BASE_URL = &quot;https:\/\/dapi.kakao.com\/&quot;;\n    private static Retrofit retrofit;\n\n    public static Retrofit getApiClient() {\n\n\/\/        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();\n\/\/        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);\n\/\/        OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();\n\n        ObjectMapper mapper = Jackson2ObjectMapperBuilder.json()\n                .featuresToDisable(SerializationFeature.FAIL_ON_EMPTY_BEANS)\n                .modules(new JavaTimeModule())\n                .build();\n\n        if (retrofit == null) {\n            retrofit = new Retrofit.Builder()\n                    .baseUrl(BASE_URL)\n                    \/\/ .client(client)\n                    .addConverterFactory(JacksonConverterFactory.create(mapper))\n                    .build();\n        }\n\n        return  retrofit;\n    }\n}<\/code><\/pre>\n<pre><code class=\"language-java\">public interface ApiInterface {\n\n    \/\/ \uc7a5\uc18c\uc774\ub984\uc73c\ub85c \uac80\uc0c9\n    @GET(&quot;v2\/local\/search\/keyword.json&quot;)\n    Call&lt;CategoryResult&gt; getSearchLocation(\n            @Header(&quot;Authorization&quot;) String token,\n            @Query(&quot;query&quot;) String query,\n            @Query(&quot;category_group_code&quot;) String categoryGroupCode,\n            @Query(&quot;size&quot;) int size,            \/\/ 1 ~ 15\n            @Query(&quot;page&quot;) int page,            \/\/ 1 ~ 45\n            @Query(&quot;sort&quot;) String sort,         \/\/ distance \ub610\ub294 accuracy (\uae30\ubcf8\uac12: accuracy)\n            @Query(&quot;x&quot;) String x,\n            @Query(&quot;y&quot;) String y\n    );\n}<\/code><\/pre>\n<pre><code class=\"language-java\">@Getter\npublic class CategoryResult {\n\n    \/\/ private Meta meta;\n    private List&lt;Document&gt; documents = null;\n}<\/code><\/pre>\n<pre><code class=\"language-java\">@Getter\n@Setter\n@NoArgsConstructor\npublic class Document {\n\n    @JsonProperty(&quot;place_name&quot;)\n    private String placeName;\n}<\/code><\/pre>\n<h2>\ud14c\uc2a4\ud2b8 \ucf54\ub4dc \ucd94\uac00<\/h2>\n<pre><code class=\"language-java\">@SpringBootTest\n@SpringBootConfiguration\npublic class ApiClientTest {\n\n    @Value(&quot;${kakao.restapi.key}&quot;)\n    private String restApiKey;\n\n    @BeforeEach\n    public void setUp() throws Exception {\n    }\n\n    @Test\n    public void getApiClient() {\n\n        \/\/ given\n\n        \/\/ when\n        ApiInterface apiInterface = ApiClient.getApiClient().create(ApiInterface.class);\n\n        Call&lt;CategoryResult&gt; call = apiInterface.getSearchLocation(\n                restApiKey,\n                &quot;\uae40\uce58\ucc0c\uac1c&quot;,\n                &quot;FD6&quot;,          \/\/ \uc74c\uc2dd\uc810\n                15,\n                1,\n                &quot;accuracy&quot;,                \/\/ distance\n                &quot;0&quot;,\n                &quot;0&quot;;\n\n        \/\/ then\n        try {\n            Response&lt;CategoryResult&gt; response = call.execute();\n            assertTrue(response.isSuccessful());\n\n            CategoryResult result = response.body();\n            assert result != null;\n\n            List&lt;Document&gt; documents = result.getDocuments();\n            assertTrue(documents.size() &gt; 0);\n\n            Document document = documents.get(0);\n\n            System.out.println(document.getPlaceName());\n        } catch (Exception e) {\n            System.out.println(e);\n        }\n    }\n}<\/code><\/pre>\n<h2>\ube44\ub3d9\uae30 \ud638\ucd9c<\/h2>\n<p>API \uc11c\ubc84\ucabd\uc740 \ube44\ub3d9\uae30 \ud638\ucd9c\uc774 \uc55e\ub4a4\uac00 \uc548\ub9de\ub294 \ub4ef \ud558\ub2e4.<br \/>\n\ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c \ube44\ub3d9\uae30 \ud638\ucd9c\ud558\ub294\uac83\uc774 \ub9de\ub294 \ub4ef \ud558\ub2e4.<\/p>\n<pre><code class=\"language-java\">    @Test\n    public void getApiClientAsync() throws InterruptedException {\n\n        \/\/ given\n        Map&lt;String, String&gt; params = new HashMap&lt;&gt;();\n        params.put(&quot;p&quot;, &quot;1&quot;);\n        params.put(&quot;s&quot;, &quot;15&quot;);\n        params.put(&quot;q&quot;, &quot;\uae40\uce58\ucc0c\uac1c&quot;);\n        KakaoSearchDto searchDto = new KakaoSearchDto(params);\n\n        \/\/ when\n        ApiInterface apiInterface = ApiClient.getApiClient().create(ApiInterface.class);\n\n        Call&lt;CategoryResult&gt; call = apiInterface.getSearchLocation(\n                restApiKey,\n                searchDto.getQueryString(),\n                &quot;FD6&quot;,          \/\/ \uc74c\uc2dd\uc810\n                searchDto.getPageSize(),\n                searchDto.getPageNo(),\n                &quot;accuracy&quot;,                \/\/ distance\n                searchDto.getLongitude().toString(),\n                searchDto.getLatitude().toString());\n\n        System.out.println(&quot;start async call : &quot; + call.hashCode());\n\n        call.enqueue(new Callback&lt;&gt;() {\n            @Override\n            public void onResponse(Call&lt;CategoryResult&gt; call, Response&lt;CategoryResult&gt; response) {\n\n                System.out.println(&quot;onResponse called : &quot; + call.hashCode());\n\n                if (response.isSuccessful()) {\n                    try {\n                        CategoryResult result = response.body();\n                        assert result != null;\n\n                        List&lt;Document&gt; documents = result.getDocuments();\n                        assertTrue(documents.size() &gt; 0);\n\n                        Document document = documents.get(0);\n\n                        System.out.println(document.getPlaceName());\n                        System.out.println(document.getCategoryName());\n                    } catch (Exception e) {\n                        System.out.println(e);\n                    }\n                } else {\n                    System.out.println(&quot;Request Error :: &quot; + response.errorBody());\n                }\n            }\n\n            @Override\n            public void onFailure(Call&lt;CategoryResult&gt; call, Throwable t) {\n                System.out.println(&quot;onFailure called&quot;);\n                System.out.println(&quot;Network Error :: &quot; + t.getLocalizedMessage());\n            }\n        });\n\n        System.out.println(&quot;sleep 5 seconds&quot;);\n\n        Thread.sleep(5000);\n\n        System.out.println(&quot;end main thread&quot;);\n\n        \/\/ then\n    }<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>SpringBoot Retrofit \uc5f0\ub3d9\ud558\uae30 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=4162\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[29],"tags":[],"class_list":["post-4162","post","type-post","status-publish","format-standard","hentry","category-spring-boot-2-5"],"_links":{"self":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/4162","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4162"}],"version-history":[{"count":5,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/4162\/revisions"}],"predecessor-version":[{"id":4167,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/4162\/revisions\/4167"}],"wp:attachment":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4162"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4162"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4162"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}