Retrofit2 / Android + Kotlin (KakaoAPI)

Lee Jung-hwan·2023년 7월 12일
1

Android

목록 보기
1/4

주의! 이글은 개인 공부 목적으로 작성된 포스팅입니다.
잘못된 내용이 있을 수 있음을 주의해주세요.

⭐️ 그게 뭐야?

오늘은 Android 주요 라이브러리 중 하나인 Retrofit에 대해 배워볼까 한다.
Retrofit은 비동기 API 통신을 보다 쉽게 구현할 수 있게 해주는 라이브러리이다.

기존에 우리가 사용하는 OkHttp 보다 성능이 월등히 빠르다.
물론 Retrofit2는 기본적으로 OkHttp에 의존하고 있지만 3배 ~ 10배 까지의 성능 차이가 난다고 한다.


🏖️ 그래서 사용 방법은?

사용방법을 알기 전에 우리는 간단한 HTTP method 개념을 알아야 한다.
HTTP method는 기본적으로 HTTP 통신에 사용되는 일종의 서버에 전달하는 명령어이다.

주로 사용하는 대표적인 4개의 HTTP 메소드를 알아보자.

종류설명
GET서버로 부터 데이터를 요청해 받는 메소드
POST서버에 데이터 추가와 같은 데이터를 처리 요청 메소드
PUT서버에 데이터를 전송하여 새로운 리소스를 생성하거나 기존 리소스를 업데이트 하는 메소드
DELETE서버의 특정 데이터를 삭제하는 메소드

⚒️ 사용 전 구조를 파악하자!

구현을 시작하기 전에 기본적으로 Retrofit2를 사용하기 위한 구조를 알아야 한다.

  • DTO?
    Data Trasnfer Object를 뜻하는 용어로 계층 간 데이터 교환을 위해 사용되는 객체이다.
    우리가 데이터를 서버에서 받아오면 여기에 차곡차곡 들어온다.

  • Interface?
    인터페이스라는 단어를 보면 거부감부터 들 수도 있지만 쉽게 말해
    서버 통신에 필요한 내용을 정의해놓는 부분이다.

  • Client?
    DTO를 구현하고 Interface를 구현했다면 해당 내용을 사용할 클라이언트가 필요하다.
    Client는 쉽게 말해 위의 내용을 사용하기 위한 수단이라고 생각하면 이해하기가 쉽다.


🏗️ 만들어 보자!

위 내용을 읽고 어느 정도 감이 잡혔다면 이제는 직접 구현해보자.
제일 먼저 Retrofit2를 사용하기 위해 App Module 단위 build.gradle에 Dependencies를 추가해주자.

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

여기서 위의 종속성을 추가하는 코드를 보고 아래와 같은 생각을 할 수 있다.

  • 우리는 Retrofit2를 추가하는데 왜 converter-gson이 필요할까?
    Retrofit2를 사용해 데이터를 받아오면 Json 형식으로 받아오게 된다.
    이를 converter-gson을 사용해 객체화 시켜주는 것이다.

추가적으로 인터넷을 사용해 통신할 예정이기 때문에 AndroidManifest.xml에
아래 코드를 추가해주자.

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

Dependencies 추가가 끝났으면 아래 목표를 진행해보자.

Kakao 검색 API를 사용해 EditText 박스에 검색어를 입력해 버튼을 누르면
받아온 정보를 TextView에 기록해보자!

위에서 언급한 구조를 순서대로 구현해보자.

1. DTO 구현하기

DTO를 구현하기 위해선 방법이 2가지가 있다.

  1. 우리가 직접 Kakao에서 제공하는 응답 예제를 보고 data class를 사용해 직접 구현하는 방법

  2. 안드로이드 스튜디오에서 사용할 수 있는 "Kotlin data class from json" 사용

우리는 편리함을 위해 2번 방법을 사용할 예정이다.

하지만 위 플러그인을 사용한다고 무조건 잘 작성해주는 건 아니다.
해당 내용을 참고해서 잘못된 부분을 찾아 수정할 수 있는 능력은 꼭 필요하다.

위와 같이 Android Studio에서 플러그인을 설치했으면 다시 DTO 생성 부분으로 넘어가자.

제일 먼저 깔끔한 프로젝트 구성을 위해 패키지를 생성해 DTO를 분리해주자.
나는 가독성을 위해 아래와 같이 구성했지만 보통 패키지 명은 소문자로 하는 걸 추천한다.

이제 DTO 패키지 위에 마우스 오른쪽 버튼을 눌러 New -> Kotlin data class File From Json을 눌러주자.

이제 해당 입력 칸 안에 Kakao 웹 검색 API 문서에서 제공하고 있는 응답 예제를 가져와 입력해보자.

결과를 보면 DTO 패키지 아래에 3개의 파일이 생성된 걸 확인할 수 있다.
해당 파일의 내용을 보면 data class로 구성된 내용을 확인할 수 있다.

이걸로 우리는 통신에 사용할 DTO 구현이 끝났다.
파일이 생성됐다고 넘어가지 말고 코드를 살펴보고 이해해 보는 걸 적극 추천한다.

2. Interface 구현하기

해당 부분은 차후에 서비스라는 변수에 내용을 저장해 사용할 예정이다.
쉽게 말하면 데이터 통신을 위해 정의하는 일종의 규격 정도로 생각하자.

KaKao Web 검색을 위해 사용할 Interface인 KaKaoService 인터페이스를 생성하자.
이제 Interface안에 내용을 채워 넣어보자.

작성을 위해서는 공식 API 문서의 내용을 확인 해야 한다.

https://developers.kakao.com/docs/latest/ko/daum-search/dev-guide

공식 문서를 참고해 검색 요청을 하는 인터페이스 내용은 위와 같다.
코드를 분석해보자.

  1. GET("search/web")
    해당 부분은 https://dapi.kakao.com/v2/search/web에서 v2/ 뒤의 내용으로
    뒤에 나올 End-Point 다음으로 입력되는 요청 주소이다.

  2. @Header("Authorization") auth : String
    해당 부분은 공식 문서에 Header 부분에 Authorization이라는 이름으로 REST API 키를 첨부해 요청해달라고 했다. 이를 위해 해당 이름으로 생성한 헤더 부분이다.

  3. @Query("query") query : String
    해당 부분은 공식 문서에 "쿼리 파라미터"라고 되어있는 부분에
    필수 요소인 query를 지정해준 것이다. 매개변수 명은 달라도 된다.

  4. Call<클래스이름>
    해당 부분은 retrofit2에서 제공하고 있는 함수로 해당 함수의 요청이 끝나면 KaKaoDTO로 데이터를 넘겨주는 역할을 한다.

⚙️ 3. 클라이언트 만들기

DTO와 Interface까지 만들었으면 사실상 다 만든 거다.
MainActivity에서 예제를 실행해보자.

사실 LiveData와 ViewModel + 옵저버를 사용하면 더욱 깔끔하게 구성할 수 있지만 오늘 글의 목적은 Retrofit2가 어렵지 않고, 구현을 위한 코드만 보여주는 걸 목표로 하고 있기에 해당 내용은 생략하겠다.

  1. retrofit 클라이언트 만들기 - 껍데기
val retrofit = Retrofit
            .Builder()
            .baseUrl("https://dapi.kakao.com/v2/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()

제일 먼저 baseUrl을 API 문서에서 제공한 "https://dapi.kakao.com/v2/" 로 설정한다.
여기서 앞에서 말한 End-Point가 나오는데 v2 옆에 "/"까지가 End-Point이다.

만약, "/"를 생략하면 AndroidStudio로그에 End-Point 에러가 출력되고 앱이 강제 종료된다.

  1. Servcie를 지정한다.
val service = retrofit.create(KaKaoService::class.java)

위와 같이 인터페이스를 지정해 방금 생성한 retrofit 변수에 service를 지정해준다.

위의 과정이 끝나면 레트로핏2 클라이언트에 서비스가 장착된 통신을 위한
완전한 클라이언트가 만들어진 것이다.

  1. 통신 시작
binding.searchButton.setOnClickListener {
            service.SearchRequest("KakaoAK ~~~~",binding.inputBox.text.toString()).enqueue(object : Callback<KakaoDTO> {
                override fun onResponse(call: Call<KakaoDTO>, response: Response<KakaoDTO>) {
                    if(response.isSuccessful){
                        val result = response.body()

                        binding.resultView.text = HtmlCompat.fromHtml(
                            result?.documents?.get(0)!!.title +
                            "<br><br>"+result?.documents?.get(0)!!.contents,
                            HtmlCompat.FROM_HTML_MODE_LEGACY
                        )

                    }else{
                        binding.resultView.text = response.toString()
                    }
                }

                override fun onFailure(call: Call<KakaoDTO>, t: Throwable) {
                    Toast.makeText(applicationContext,"통신 실패 ${t.message}", Toast.LENGTH_SHORT).show()
                }

            })
        }

코드가 길어 당황스럽겠지만 어렵지 않다.
천천히 분석해보자.

  • SearchRequest("KakaoAK API Key", "검색어")
    위 함수는 아까 인터페이스에 만든 것과 같이 API 키와 검색어를 인자값으로 받아 처리한다.

  • enqueue 해당 메서드는 object : Calback<카카오DTO>를 사용해 통신이 끝나고 해당 결괏값을 처리하는 메서드로 onResponse()와 onFailure()를 오버라이드해서 사용한다.

  • HtmlCompat.fromHTML(Text, MODE)
    해당 함수는 결괏값이 HTML 형식으로 날아오는데 해당 부분을 HTML 형식에 맞게 지정해 주는 함수이다. 만약 이 함수를 사용하지 않으면 <태그>타이틀</태그>와 같이 출력된다.


😆 결과

해당 결과는 결과로 받아온 타이틀과 본문 내용을 출력해주는 코드이다.
documents?.get(0)부분에서 get의 숫자를 변경하면 다른 페이지의 내용도 가져올 수 있지만

해당 부분은 DTO를 이해하면 쉽게 생각할 수 있는 부분이기에 이번 글에서 설명을 생략했다.


긴 글 읽어주셔 감사하고 피드백은 언제나 환영입니다.
감사합니다.

profile
안녕하세요😁 안드로이드 개발자 이정환 입니다~⭐️

0개의 댓글