본문 바로가기
IT/Android

Android Retrofit2를 활용한 공공데이터 API 사용하기

by TechTonic 2022. 9. 28.
반응형

우선 HTTP 통신을 위한 많은 라이브러리들이 있지만 Retrofit을 사용하는 이유와 장점에 대해 간략히 설명하고

사용 방법에 대해 알아보도록 합시다.

 

Retrofit란?

앱을 만들다보면 통신(HTTP) 이 필요한 기능이 대다수 필요하며 통신 기능을 쉽고 간결하게 구현가능하게 해주는 라이브러리입니다.

1. 장점

 - 간결한 코드로 통신 기능 지원

 - okhttp를 기반으로 사용하여 빠른 속도 지원

 - 어노테이션으로 메서드를 정의함으로써 직관적인 코드 구현과 유지보수에 용이

 - 통신 시 스레드 구현 필요 X (asyncTask 등..)

 

2. 단점

 - asyncTask, volley 보다 자유도가 낮음

 

Retrofit 사용방법

1. 라이브러리 사용을 위한 종속성 추가

build.gradle (Module)

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

 

2. 인터넷 사용을 위한 권한 설정

AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" />

 

3. http 접속 허용을 위한 권한 설정

AndroidManafest.xml (application) 태그 안

<application
	android:icon="@mipmap/ic_launcher"
    android:allowBackup="true"
    android:usesCleartextTraffic="true"   <-- 이것
    ..

 

4. 데이터를 담기 위한 model class 생성

 - 서버에서 JSON 형태로 받는 데이터가 아래와 같으므로 해당 내용으로 model 생성

공공데이터포탈의 api model

"data": [
    {
      "서비스ID": "string",
      "지원유형": "string",
      "서비스명": "string",
      "서비스목적": "string",
      "지원대상": "string",
      "선정기준": "string",
      "지원내용": "string",
      "신청방법": "string",
      "신청기한": "string",
      "상세조회URL": "string",
      "소관기관코드": "string",
      "소관기관명": "string",
      "부서명": "string",
      "조회수": 0
    }
  ]

ServiceModel.java (코드가 길어 접이식 글로 대체)

더보기
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class ServiceModel {

    @SerializedName("서비스ID")
    @Expose
    private String serviceId;

    @SerializedName("지원유형")
    @Expose
    private String supportType;

    @SerializedName("서비스명")
    @Expose
    private String serviceName;

    @SerializedName("서비스목적")
    @Expose
    private String servicePurpose;

    @SerializedName("지원대상")
    @Expose
    private String supportTarget;

    @SerializedName("선정기준")
    @Expose
    private String selectionCriteria;

    @SerializedName("지원내용")
    @Expose
    private String supportContents;

    @SerializedName("신청방법")
    @Expose
    private String applyHow;

    @SerializedName("신청기한")
    @Expose
    private String applyDeadline;

    @SerializedName("상세조회URL")
    @Expose
    private String detailedUrl;

    @SerializedName("소관기관코드")
    @Expose
    private String agencyCode;

    @SerializedName("소관기관명")
    @Expose
    private String agencyName;

    @SerializedName("부서명")
    @Expose
    private String departmentName;

    @SerializedName("조회수")
    @Expose
    private int views;


    public String getServiceId() {
        return serviceId;
    }

    public void setServiceId(String serviceId) {
        this.serviceId = serviceId;
    }

    public String getSupportType() {
        return supportType;
    }

    public void setSupportType(String supportType) {
        this.supportType = supportType;
    }

    public String getServiceName() {
        return serviceName;
    }

    public void setServiceName(String serviceName) {
        this.serviceName = serviceName;
    }

    public String getServicePurpose() {
        return servicePurpose;
    }

    public void setServicePurpose(String servicePurpose) {
        this.servicePurpose = servicePurpose;
    }

    public String getSupportTarget() {
        return supportTarget;
    }

    public void setSupportTarget(String supportTarget) {
        this.supportTarget = supportTarget;
    }

    public String getSelectionCriteria() {
        return selectionCriteria;
    }

    public void setSelectionCriteria(String selectionCriteria) {
        this.selectionCriteria = selectionCriteria;
    }

    public String getSupportContents() {
        return supportContents;
    }

    public void setSupportContents(String supportContents) {
        this.supportContents = supportContents;
    }

    public String getApplyHow() {
        return applyHow;
    }

    public void setApplyHow(String applyHow) {
        this.applyHow = applyHow;
    }

    public String getApplyDeadline() {
        return applyDeadline;
    }

    public void setApplyDeadline(String applyDeadline) {
        this.applyDeadline = applyDeadline;
    }

    public String getDetailedUrl() {
        return detailedUrl;
    }

    public void setDetailedUrl(String detailedUrl) {
        this.detailedUrl = detailedUrl;
    }

    public String getAgencyCode() {
        return agencyCode;
    }

    public void setAgencyCode(String agencyCode) {
        this.agencyCode = agencyCode;
    }

    public String getAgencyName() {
        return agencyName;
    }

    public void setAgencyName(String agencyName) {
        this.agencyName = agencyName;
    }

    public String getDepartmentName() {
        return departmentName;
    }

    public void setDepartmentName(String departmentName) {
        this.departmentName = departmentName;
    }

    public int getViews() {
        return views;
    }

    public void setViews(int views) {
        this.views = views;
    }

    @Override
    public String toString() {
        return "ServiceModel{" +
                "serviceId='" + serviceId + '\'' +
                ", supportType='" + supportType + '\'' +
                ", serviceName='" + serviceName + '\'' +
                ", servicePurpose='" + servicePurpose + '\'' +
                ", supportTarget='" + supportTarget + '\'' +
                ", selectionCriteria='" + selectionCriteria + '\'' +
                ", supportContents='" + supportContents + '\'' +
                ", applyHow='" + applyHow + '\'' +
                ", applyDeadline='" + applyDeadline + '\'' +
                ", detailedUrl='" + detailedUrl + '\'' +
                ", agencyCode='" + agencyCode + '\'' +
                ", agencyName='" + agencyName + '\'' +
                ", departmentName='" + departmentName + '\'' +
                ", views=" + views +
                '}';
    }
}

 

위 작성한 ServiceModel의 상위 Model class 생성 

  • 객체 값에 위에 작성한 serviceModel 이 포함됨을 알 수 있습니다.

API Call 시 받는 response 값

코드가 길어 접이식 글로 대체.

더보기
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

import java.util.ArrayList;

public class ServiceApiModel {

    @SerializedName("page")
    @Expose
    private int page;

    @SerializedName("perPage")
    @Expose
    private int perPage;

    @SerializedName("totalCount")
    @Expose
    private int totalCount;

    @SerializedName("currentCount")
    @Expose
    private int currentCount;

    @SerializedName("matchCount")
    @Expose
    private int matchCount;

    @SerializedName("data")
    @Expose
    private ArrayList<ServiceModel> data;

    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public int getPerPage() {
        return perPage;
    }

    public void setPerPage(int perPage) {
        this.perPage = perPage;
    }

    public int getTotalCount() {
        return totalCount;
    }

    public void setTotalCount(int totalCount) {
        this.totalCount = totalCount;
    }

    public int getCurrentCount() {
        return currentCount;
    }

    public void setCurrentCount(int currentCount) {
        this.currentCount = currentCount;
    }

    public int getMatchCount() {
        return matchCount;
    }

    public void setMatchCount(int matchCount) {
        this.matchCount = matchCount;
    }

    public ArrayList<ServiceModel> getData() {
        return data;
    }

    public void setData(ArrayList<ServiceModel> data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "ServiceApiModel{" +
                "page=" + page +
                ", perPage=" + perPage +
                ", totalCount=" + totalCount +
                ", currentCount=" + currentCount +
                ", matchCount=" + matchCount +
                ", data=" + data +
                '}';
    }
}

 

5. Retrofit Interface 생성

RetrofitInterface.java

import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
import retrofit2.http.Query;

public interface RetrofitInterface {

    @GET("{path}")
    Call<ServiceModel> getServiceList(
            @Path ("path") String path,
            @Query("page") String page,
            @Query("perPage") String perPage,
            @Query("serviceKey") String serviceKey
    );

    @GET("{path}")
    Call<ServiceModel> getTest(
            @Path ("path") String path,
            @Query("serviceKey") String serviceKey
    );

}
Call<ServiceModel> 앞서 작성한 model class 이름
@GET HTTP 통신 시 GET 방식을 사용할 것이고, http://BASE_URL/{path} 의 뒤에 end point url 을 명시해주기 위해 작성. (end point url 은 아래 MainActivity 에서 추가 설명
@Path 위 GET 에 들어가 String 문자
@Query http://BASE_URL/aaa?page=1 과 같이 URL 뒤 파라미터명 및 string 값
MainActivity에서 값 세팅해서 넘겨줌.

 

6. 통신 호출 (MainActivity에서 테스트)

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private static final String BASE_URL = "사용할 BASE_URL";
    private static final String SERVICE_KEY = "발급 받은 키값";

    public static String TAG = "retrofit_test";
    private static String buf = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        TextView tv = (TextView) findViewById(R.id.text1);

        retrofit2.Retrofit retrofit = new retrofit2.Retrofit.Builder()
                .baseUrl(BASE_URL)    // baseUrl 등록
                .addConverterFactory(GsonConverterFactory.create())  // Gson 변환기 등록
                .build();

        RetrofitInterface service = retrofit.create(RetrofitInterface.class);   // 레트로핏 인터페이스 객체 구현

        Call<ServiceApiModel> call = service.getServiceList("API end point url", "1", "10", SERVICE_KEY);

        call.enqueue(new Callback<ServiceApiModel>() {
            @Override
            public void onResponse(Call<ServiceApiModel> call, Response<ServiceApiModel> response) {
                if(response.isSuccessful()){
                    Log.d(TAG, "연결 주소 확인 : " + response.raw().request().url().url());
                    Log.d(TAG, "통신여부 코드 : " + response.code());
                    ServiceApiModel sm = response.body();
                    ArrayList<ServiceModel> arr = sm.getData();
                    Log.d(TAG, "데이터 정보: " + sm.toString());
                    for(ServiceModel serviceModel : arr){
                        buf = buf + serviceModel.getServiceName() + "\n";
                    }
                    tv.setText(buf);

                }
                else{
                    // 실패
                    Log.e(TAG, "실패 코드 확인 : " + response.code());
                    Log.e(TAG, "연결 주소 확인 : " + response.raw().request().url().url());
                }
            }

            @Override
            public void onFailure(Call<ServiceApiModel> call, Throwable t) {
                // 통신 실패
                Log.e(TAG, "onFailure: " + t.getMessage());
            }
        });

    }
}

 

MainActivity의 내용은 주석 및 로그 내용을 확인해 보면 통신에 대한 내용들을 파악할 수 있습니다.

 

Retrofit을 통한 공공데이터 정보

이로써 중요 코드 작업은 끝났고 해당 앱을 실행시키면 아래와 같이 공공데이터의 정보를 가져올 수 있습니다.

 

api를 사용한 공공데이터 정보

 

다음 과정으로는 해당 정보를 가지고 Recyclerview를 통해 리스트로 출력하는 방법은 아래 내용을 참고하세요.

 

2022.09.29 - [IT/Android] - Android Retrofit2 데이터 RecyclerView 적용하기

 

Android Retrofit2 데이터 RecyclerView 적용하기

개요 지난 발행글에서 Retrofit2 를 사용하여 공공데이터포탈의 API를 사용하여 데이터 가져오기를 해보았다. 이번글에서는 해당 데이터를 기반으로 RecyclerView를 활용하여 리스트뷰를 만드는 작업

soir1984.tistory.com

 

반응형

댓글