API 연동

jiyoon·2023년 5월 21일
0

밀메이트

목록 보기
2/3

먼저, 외부 API로부터 받아온 응답 데이터를 객체로 변환해주는 라이브러리들을 알아보았습니다.

외부 api 연동 관련 라이브러리

프로젝트의 요구사항에 가장 적합한 라이브러리를 선택하면 됩니다. 예를 들어, 성능이 중요한 요소라면 Jackson이 좋은 선택이 될 수 있습니다. 간결하고 직관적인 API를 선호한다면 Gson이나 Moshi를 고려해볼 수 있습니다. 그리고 대부분의 경우, Retrofit은 API 호출을 처리하기 위해 널리 사용되는 선택입니다.


Gson

  • Google에서 개발하였으며 안드로이드 개발자들에게 매우 인기있습니다.
  • 사용하기 쉽고, 문서화가 잘 되어 있습니다.
  • API는 직관적이며, 복잡한 타입의 객체도 잘 처리합니다.
  • 단점 중 하나는 성능이며, Gson은 일부 상황에서 느릴 수 있습니다.

Jackson

  • 성능 면에서는 Gson보다 뛰어나며, 대부분의 경우에서 가장 빠른 라이브러리 중 하나입니다.
  • 스트리밍 API를 제공하며, 이를 통해 대용량 JSON을 처리할 수 있습니다.
  • 복잡한 데이터 타입에 대해서는 Gson보다 사용하기가 다소 어려울 수 있습니다.

Moshi

  • Gson의 개발자 중 일부가 만든 라이브러리입니다.
  • Gson의 성능 문제와 일부 디자인 결정을 개선하기 위해 개발되었습니다.
  • API는 간결하며 사용하기 쉽습니다.
  • 아직은 Gson이나 Jackson만큼 널리 사용되지는 않지만, 점점 더 인기를 얻고 있습니다.

Retrofit

  • HTTP API를 Java 인터페이스로 변환하는 데 사용됩니다.
  • Retrofit 자체는 JSON 또는 XML을 파싱하지 않지만, Gson, Jackson, Moshi와 같은 라이브러리를 이용해 응답을 Java 객체로 자동 변환할 수 있습니다.
  • 대부분의 안드로이드 개발자들이 Retrofit을 사용하여 네트워크 호출을 처리합니다.

결론

나는 비교적 간단한 프로젝트라서 사용하기 편리한 Gson과 Retrofit을 활용하기로 하였다.


Gson과 Retrofit을 사용한 api 호출

Retrofit을 사용하면 API를 호출하는 코드가 상당히 간결해집니다. 먼저, 호출하려는 API를 정의한 인터페이스를 만들고, 이 인터페이스를 사용해서 Retrofit 객체를 생성합니다. 그리고 이 객체를 사용해서 API를 호출하고 결과를 받습니다.
Retrofit은 별도의 스레드에서 네트워크 작업을 수행하고 결과를 메인 스레드로 전달해주는 기능을 자체적으로 지원합니다.
작업 플로우

  • 사용자가 앱에서 음식 이름을 입력하고, '요청' 버튼을 클릭합니다.
  • buttonRequest의 클릭 리스너가 requestApi 메소드를 호출합니다. 이 메소드는 사용자가 입력한 음식 이름을 매개변수로 받습니다.
  • requestApi 메소드에서는 먼저 ApiService 인터페이스의 구현체를 생성합니다. 이 구현체는 Retrofit이 자동으로 생성해줍니다.
  • 그 다음, getFoodNtrItdntList 메소드를 호출하여 API 요청을 시작합니다. 이 메소드는 Call 객체를 반환합니다. 이 객체를 사용하여 API 요청을 비동기적으로 수행할 수 있습니다.
  • Call 객체의 enqueue 메소드를 호출하여 API 요청을 비동기적으로 수행하도록 요청합니다. 이 메소드는 콜백을 매개변수로 받습니다. 이 콜백은 API 요청이 완료되었을 때 호출됩니다.
  • 콜백의 onResponse 메소드는 API 요청이 성공적으로 완료되었을 때 호출됩니다. 이 메소드에서는 API 응답을 처리합니다.
  • 콜백의 onFailure 메소드는 네트워크 오류 등으로 API 요청이 실패하였을 때 호출됩니다. 이 메소드에서는 오류를 처리합니다.


build.gradle 의존성 추가

먼저, Retrofit 라이브러리를 사용하려면 build.gradle 파일에 Retrofit과 Gson converter를 추가해야 합니다.

dependencies {
    ...
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    ...
}


Retrofit 객체 생성

// Retrofit 객체 생성
        retrofit = new Retrofit.Builder()       // Builder 패턴을 사용하여 Retrofit 객체 생성
                .baseUrl(BASE_URL) // 요청을 보낼 base URL 설정
                .addConverterFactory(GsonConverterFactory.create()) // JSON 응답을 자동으로 변환할 GsonConverterFactory 추가 (JSON을 POJO로 변환)
                .build();

  1. Retrofit.Builder(): Retrofit 객체를 생성하기 위한 Builder 패턴. Builder 패턴을 사용하면 코드의 가독성을 높이고, 여러 설정을 한 번에 할 수 있습니다. (빌더 패턴 : https://velog.io/@jiyoon_sw524/Builder-%ED%8C%A8%ED%84%B4)

  2. .addConverterFactory(GsonConverterFactory.create()): Retrofit에 Gson ConverterFactory를 추가. 이는 API 응답을 자바 객체로 자동으로 변환할 때 사용됩니다. Retrofit은 응답을 자동으로 변환하기 위해 Converter Factory를 사용하며, Gson Converter Factory는 JSON 응답을 자바 객체로 변환하는데 사용됩니다.

    • Gson은 Google이 개발한 라이브러리로, JSON 문자열과 자바 객체를 상호 변환할 수 있습니다.
    • ConverterFactory는 이 변환 작업을 담당하는 인터페이스로, 여러 개의 Converter를 관리하고 적절한 Converter를 제공합니다.
    • Gson Converter Factory는 Gson 라이브러리를 사용하여 JSON 문자열과 자바 객체를 상호 변환하는 Converter Factory입니다.


버튼 클릭 리스너 설정

        buttonRequest.setOnClickListener(v -> requestApi(editTextFoodName.getText().toString()));    
        // 람다식을 사용하여 버튼이 클릭되었을 때 requestApi() 메소드 호출


Retrofit 라이브러리를 사용하여 API를 호출하고 응답 처리

private void requestApi(String foodName) {
        // Retrofit 서비스 생성
        ApiService apiService = retrofit.create(ApiService.class);  // ApiService 객체 생성 (실제 구현체는 Retrofit이 자동으로 생성)

        // HTTP GET 요청을 수행. getFoodNtrItdntList() 메소드를 호출하면서 필요한 매개변수들을 전달.
        Call<ResponseClass> call = apiService.getFoodNtrItdntList( SERVICE_KEY, foodName, null, null, null, null, "json" );

        // 비동기로 실행할 것을 요청하고 응답을 처리할 콜백을 등록.
        call.enqueue(new Callback<ResponseClass>() {    // Callback 인터페이스를 구현한 익명 클래스 정의. 응답을 받았을 때 호출되는 메소드를 정의.
            @Override
            public void onResponse(Call<ResponseClass> call, Response<ResponseClass> response) {
                if (response.isSuccessful()) {
                    // API 요청 성공: 응답을 처리합니다.
                    ResponseClass result = response.body(); // 응답 객체를 받아옴.

                    //test
                    List<ResponseClass.Body.Item> items = result.body.getItems(); // items 리스트를 받아옴.
                    StringBuilder stringBuilder = new StringBuilder();
                    for (ResponseClass.Body.Item item : items) {
                        stringBuilder.append("Food Name: ").append(item.getFood_name()).append("\n");
                        stringBuilder.append("Serving Weight: ").append(item.getFood_1serving()).append("\n");
                        stringBuilder.append("Calories: ").append(item.getFood_kcal()).append("\n");
                        stringBuilder.append("Carbohydrates: ").append(item.getFood_carbohydrates()).append("\n");
                        stringBuilder.append("Protein: ").append(item.getFood_protein()).append("\n");
                        stringBuilder.append("Fat: ").append(item.getFood_fat()).append("\n");
                        stringBuilder.append("Company: ").append(item.getFood_company()).append("\n");
                        stringBuilder.append("------------------------\n");
                    }
                    textViewResult.setText(stringBuilder.toString()); // 결과를 화면에 출력

                    /*textViewResult.setText(result.toString()); // 결과를 화면에 출력*/
                } else {
                    // API 요청 실패: 오류를 처리합니다.
                    Log.e("ApiExplorer", "API 요청 실패: " + response.message());
                }
            }

            @Override
            public void onFailure(Call<ResponseClass> call, Throwable t) {
                // 네트워크 오류: 오류를 처리합니다.
                Log.e("ApiExplorer", "네트워크 오류: " + t.getMessage());
            }
        });
    }

  1. ApiService apiService = retrofit.create(ApiService.class);
    retrofit.create() 메서드는 ApiService 인터페이스를 기반으로 한 프록시 객체를 생성합니다. 이 객체는 인터페이스에 정의된 각 메소드를 호출할 때마다 HTTP 요청을 실행합니다.

    • 프록시 객체 : 실제 객체를 대신하는 객체. 이 객체는 실제 객체에 대한 접근을 제어하거나, 추가적인 기능을 수행하기 위해 사용됩니다. Retrofit에서 create() 메소드를 통해 생성하는 ApiService 객체는 실제 구현체가 아니라 프록시 객체입니다. 이 객체를 통해 메소드를 호출하면 Retrofit이 내부적으로 HTTP 요청을 생성하고 실행합니다.
  2. Call<ResponseClass> call = apiService.getFoodNtrItdntList(...);
    apiService.getFoodNtrItdntList(...) 메서드를 호출하면, 이 메서드에 해당하는 HTTP 요청을 나타내는 Call 객체를 반환합니다. 이 객체는 아직 요청을 실행하지 않았지만, 준비 상태에 있습니다. 이 Call 객체를 사용하여 요청을 나중에 실행할 수 있습니다. ResponseClass는 API 응답의 JSON 데이터를 자동으로 변환할 클래스를 나타냅니다.
    - Call 객체 : HTTP 요청을 나타내는 객체. 이 객체에는 요청의 HTTP 메소드(GET, POST 등), 요청 URL, 헤더, 본문 등 요청에 관한 모든 정보가 포함되어 있습니다. 이 객체의 enqueue() 메소드를 호출하면 요청이 비동기적으로 실행되며, 결과는 Callback 객체에 전달됩니다.

  3. call.enqueue(new Callback<ResponseClass>() {...});
    enqueue() 메서드는 HTTP 요청을 비동기적으로 실행하는 메서드입니다. 이 메서드는 Callback 객체를 매개변수로 받아서, HTTP 요청이 성공적으로 완료되었을 때 onResponse() 메서드를 호출하고, 요청이 실패하면 onFailure() 메서드를 호출합니다.
    - 비동기적 실행 : 메소드 호출이 즉시 완료되지 않고 나중에 완료되는 것. call.enqueue() 메소드를 호출하면 HTTP 요청이 백그라운드에서 실행되며, 그 결과는 나중에 Callback 객체에 전달됩니다.
    - Callback 객체 : 익명 클래스의 인스턴스. 이 객체의 onResponse() 또는 onFailure() 메서드는 HTTP 요청의 결과에 따라 호출됩니다.
    - onResponse()와 onFailure() 메서드는 Retrofit에 의해 자동으로 호출

  4. public void onResponse(Call<ResponseClass> call, Response<ResponseClass> response) {...}
    onResponse() 메서드는 HTTP 요청이 성공적으로 완료되었을 때 호출되는 콜백 메서드입니다. Response 객체에는 HTTP 응답에 포함된 여러 정보가 담겨 있습니다. 특히, Response.body() 메서드를 호출하면 HTTP 응답 본문을 얻을 수 있습니다. 본문 데이터는 Gson 라이브러리에 의해 ResponseClass 객체로 자동 변환됩니다.

  5. public void onFailure(Call<ResponseClass> call, Throwable t) {...}
    onFailure() 메서드는 네트워크 오류 등으로 HTTP 요청이 실패했을 때 호출되는 콜백 메서드입니다. 이 메서드는 오류 처리 로직을 구현하는 곳입니다.

``

profile
주니어 개발자

0개의 댓글