[Android]Retrofit으로 Rest API를 사용하기

Happy Jiwon·2023년 3월 18일
1

Android

목록 보기
4/13

Retrofit

Retrofit은 Android 및 Java에서 사용되는 안전한 HTTP 클라이언트로 안드로이드 앱에서 네트워크 요청을 보내는 과정을 간편하게 구현할 수 있게 해주는 오픈소스 라이브러리이다.

이번 블로그 포스팅에서는 Retrofit의 특징, 장점, 사용법에 대해 자세히 살펴보겠다.


우선, Retrofit이 무엇이며 왜 필요한지 알아보자.
Retrofit은 인터페이스로 RESTful API 를 정의할 수 있는 라이브러리이다. 네트워크 요청 및 응답 처리를 하면서 개발자가 사용하기 쉬운 인터페이스를 제공해준다.

다음은 Retrofit은 안드로이드 앱 개발에 매우 적합한 기능들이다.

  1. Type safety
    Retrofit은 API 엔드포인트를 정의하기 위해 주석을 사용한다. 이를 통해 타입 안전성을 보장할 수 있다. 즉, 개발자는 서버로부터 올바른 유형의 데이터를 보내고 받는지 확인할 수 있다.

  2. Simplified API
    Retrofit을 사용하면 API 호출을 간단한 자바 메서드로 정의할 수 있다. 이로 인해 안드로이드 개발에 처음 입문한 개발자들도 쉽게 사용하고 이해할 수 있다.

  3. Easy customization
    Retrofit을 사용하면 HTTP 클라이언트, 요청 헤더 및 응답 처리를 사용자 정의할 수 있다.

  4. Asynchronous support
    Retrofit은 비동기 네트워크 호출을 지원하므로 UI를 반응적으로 유지하고 ANR 오류를 피할 수 있다.

Retrofit 공식 문서 바로가기


주로 API Server에 원하는 RESTful API에 맞는 요청을 할 때 사용되며, 주된 기능으로 RDBMS에서 대표적으로 요청이 오면 처리하는 CRUD 기능 요청을 할 수 있게 제공해준다.

Retrofit은 RESTful API에서 많이 사용하는 Format인 JSON/XML을 사용하기 위한 라이브러리를 지원한다.

지원하는 라이브러리
Gson, Jackson, Moshi, Wire, Simple XML, Scalars


이제 Retrofit을 직접 사용하는 방법에 대해 소개해보겠다.

Retrofit 사용해보기

Android 권한 설정 및 Gradle 추가

implementation 'com.squareup.retrofit2:retrofit:2.9.0' // Retrofit 사용
implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // gson 변환
// 인터넷을 사용 권한 추가 (manifest 파일)
<uses-permission android:name="android.permission.INTERNET"/>

🖐🏻 주의할 점
예전에 작성한 ExoPlayer 블로그에서 설명한 내용이지만 다시 써보자!

주의할 점은 안드로이드에서는 기본적으로 Http 접근을 허용하지 않는다는 것이다.
Https 로 접근하면 문제가 없지만 우리가 접근하려는 사이트가 Https를 지원하지 않는 등의 이유로 Http 로 접근을 해야 한다면 예외처리를 해야 한다.

Android Developer의 Opt out of cleartest traffic를 보면 안드로이드 Pie(API28)부터 cleartext HTTP를 비활성화 한다고 한다.
따라서 API28 이후에서 Http에 접근하려면 cleartext HTTP를 활성화 시켜야 하기에 한 줄을 추가해주면 된다.

<application
        ...
        ...
        ...
        android:usesCleartextTraffic="true">

Retrofit의 최신 버전 및 업데이트 내역 확인

다양한 오픈소스 라이브러리 및 프로젝트의 정보를 제공하는 사이트


Interface 선언하기

두 번째로 interface를 만들어줘야 한다.
Retrofit은 interface에 우리가 요청할 동작(API들에 대한 명세)을 interface에 적어준다. interface에서 사용할 수 있는 API 어노테이션의 종류는 기본적으로 GET, POST, DELETE, PUT등이 있다.

반환 타입을 Call<객체타입>의 형태로 적을 수 있다.

아래 코드는 Retrofit 공식 문서 예제이다.

public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

위 코드를 살펴보면, @GET 괄호 안의 내용은 baseURL 뒷부분의 주소이다.
{user} 부분은 동적으로 바뀔 수 있는 값으로 계정 이름에 따라 가져올 데이터가 다르기 때문에 {user} 로 되어있다.

이렇게 동적으로 바뀔 수 있는 부분에 대해 매개변수를 작성할 때는 @Path("user(동적으로 변하는 부분의 URL 이름)") 라는 Retrofit 어노테이션을 변수 앞에 붙여 줘야 한다.

또한 @GET 이라는 어노테이션은 서버 데이터를 조회하는 뜻으로 내부 값으로는 baseURL의 EndPoint 값이 들어가면 된다.

다음으로 Call 객체를 선언해서 HTTP 요청을 웹서버로 보내준다. 이때 <> 안의 자료형은 JSON 데이터를 받아올 자료형이다. 그렇기 때문에 Repo 클래스는 직접 구현해야 한다.


서론이 너무 길었으니 직접 구현을 해보자!

먼저 json 데이터는 이곳에서 사용할 예정이다.
https://jsonplaceholder.typicode.com/posts


들어가 보면 위의 사진처럼 데이터가 보인다.
위 사진에는 userId , id, title, body로 구성되어 있는것을 확인할 수 있다.

interface

public interface RetrofitApiService {

    String BASE_URL = "http://jsonplaceholder.typicode.com";

    @GET("/posts") // 전체 URL 에서 EndPoint URL
    Call<List<Post>> getData(@Query("userId") String id);
}
  • baseUrl : 가져올 데이터가 있는 홈페이지의 baseUrl을 적어준다.
  • @GET : /posts에 있는 데이터를 가져오겠다는 의미이다.
  • Call 내부에있는 Post클래스는 새로 구현해야 함

Post 클래스 내부 구현

public class Post {
    @SerializedName("userId")
    private int userId;
    @SerializedName("id")
    private int id;
    @SerializedName("title")
    private String title;
    @SerializedName("body")
    private String body;

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }
}

userId , id, title, body 를 각각 선언해주었고 @SerializedName 으로 JSON 객체와 해당 변수를 매칭 시켜 주었다.

💡@SerializedName 사용 이유
여기서 주의할 점으로, json의 key 이름이 class의 변수 이름과 동일하다는 것이다.
하지만, json의 key이름이 한글이라면 class의 변수 이름을 어떻게 정의해야 하는가?
이러한 경우를 대비해 gson이 @SerializedName 이라는 annotation을 제공해준다.

위와 같이 사용한다면 title로 선언한 변수는 @SerializedName("제목") key에 해당하는 변수로 사용이 된다.
참고 자료


MainActivity에서 Retrofit 선언하기

Retrofit 객체를 생성하고, BASE_URL을 설정

//Retrofit 객체 생성
Retrofit retrofit = new Retrofit.Builder()
	.baseUrl(RetrofitApiService.BASE_URL)
	.addConverterFactory(GsonConverterFactory.create())
	.build();
  • BASE_URL 은 RetrofitApiService에 선언한 URL을 가져와 설정하였다. (가져올 데이터가 있는 홈페이지의 baseUrl을 적으면 된다)
  • addconverterFactory 내부에 gson 변환기를 적어준다.
    (gson을 사용해 JSON을 변환할 것 이기 때문)
  • 마지막으로 build()

앞전에 만들었던 인터페이스를 사용하여 Retrofit 객체를 생성

RetrofitApiService retrofitApiService = retrofit.create(RetrofitApiService.class);

생성한 인터페이스 getData() 메서드를 호출하여 서버에 있는 정보를 가져올 수 있다.

retrofitApiService.getData("1").enqueue(new Callback<List<Post>>() {
	@Override
	public void onResponse(Call<List<Post>> call, Response<List<Post>> response) {
		if (response.isSuccessful()) {
			List<Post> data = (List<Post>) response.body();
				if (data != null) {
					Log.e("test", "isSuccesful~~!!");
					Log.e("test", data.get(0).getTitle());
				}
			}
		}

	@Override
	public void onFailure(Call<List<Post>> call, Throwable t) {
		Log.e("test", "실패~~!!");
		Log.e("test", t.toString());
	}
});

생성한 인터페이스인 getData()에 찾을 id 값인 '1'을 넣어준 후 enqueue 해주면 된다.
이때 enqueue()는 큐에 데이터를 입력하는 의미이다. enqueue에는 override 된 두 개의 메소드가 있는데, 결과가 성공적으로 응답했을 때 onResponse 내부가 실행되고, 실패했을 때 onFailure 가 실행된다.

가져오고 싶은 데이터는 response의 body 이므로 자료형을 맞춰서 데이터를 가져온 후 Log를 찍어서 응답이 잘 도착했는지 확인해보겠다.


실행

실행하면 위와 같은 로그가 찍히는 것을 확인할 수 있다.(로그 잘 보고싶어서 Log.e(error)로 찍은것..!)

profile
공부가 조은 안드로이드 개발자

0개의 댓글