본문 바로가기
오늘은 뭘 배울까?/Android

Retrofit이란? (사용하기 전에 알아야 할 것들)

by Kim Juhwan 2021. 4. 2.

1. Retrofit
   1-1. Retrofit 이란?
   1-2. TMI
2. 기본 개념
   2-1. Request URL
   2-2. JSON과 HTML
   2-3. GET과 POST
   2-4. parameter
3. 사용 전 세팅
   3-1. gradle
   3-2. AndroidManifest.xml
   3-3. data class 생성

 

 


 

1. Retrofit

1-1. Retrofit 이란?

Retrofit는 서버와 클라이언트 간 http 통신을 위한 라이브러리이다.

더 쉽게 말하자면 안드로이드에서 http 통신을 할 수 있도록 도와주는 놈이다.

 

 

https://ceo.baemin.com/notice

 

예를 들어, retrofit 라이브러리를 사용하면 위 사이트의 공지사항들을 불러올 수 있다.

이를 이용하면 최저가 상품을 모아서 보여준다던가, 쇼핑몰 옷 사진들을 모아서 보여준다던가 등의 구현이 가능한 것이다.

 

사이트의 정보를 무작정 가져오는 것은 윤리적으로 금지된 행위이다.
자세한 내용은 이 게시물의 [목차 6]에서 다루었다.
배달의 민족 사이트는 허용하고 있어 예제로 사용했다.

 

1-2. TMI

예전에도 통신을 편하게 할 수 있도록 도와주는 라이브러리가 있었다.

HttpClient, Volley, OKhttp... 하지만 앞서 말한 2개는 Deprecated 되어 역사 속으로 사라졌고, OKhttp를 이용해서 더 편하고 사용하기 쉽게 만든 것이 Retrofit이다. 그래서 요즘은 전부 Retrofit을 사용하는 추세인 것 같다.

 

OKhttp를 기반으로 Retrofit을 만들었기 때문에 Retrofit 라이브러리를 추가하면 OKhttp의 메서드도 사용할 수 있다.

 

2. 기본 개념

  • 어떤 주소로 요청을 보내야 하는가?
  • 어떤 형태로 응답을 받는가?
  • 어떤 형태로 요청을 해야 하는가?
  • 어떤 파라미터를 가지고 요청해야 하는가?

Retrofit을 사용하기 전에 알아두어야 할 개념들이 있다. 만약 위 항목에 대해 답할 수 있다면 [목차 3]으로 넘어가면 된다. 아니라면 [목차 2]를 계속 읽어 나가면 된다.

 

2-1. Request URL

개발자 도구(F12) - Network - All

통신할 사이트에 들어가서 F12를 누르면 위와 같은 창이 뜬다.

해당 경로로 들어가 Ctrl + R을 눌러주자.

 

페이지를 구성하는 파일들

그러면 이렇게 알 수 없는 파일들이 쪼라ㅏ라라락 생기는데 이 파일들이 화면을 구성한다고 생각하면 될 것 같다.

이 중 우리가 필요한 파일을 찾아내야 하는데 공지사항처럼 1페이지, 2페이지가 있는 페이지라면 비교적 찾기가 쉽다.

개발자 도구 창을 그대로 둔 상태에서 2페이지로 넘어가 보자.

 

 

시간의 흐름에 따른 변화 그래프

사이트에 접속 후 몇 초정도 있다가 2페이지로 넘어갔더니 이전 작업 내용들은 저렇게 작아지고 새로운 작업 내용이 생겼다. 저 파란색 부분을 클릭해보자. (드래그하면 넓게 선택됨)

 

그러면 이렇게 저 시간 때에 바뀐 내용들을 볼 수 있다. 1페이지 -> 2페이지로 넘어갔다면 아마 사이트의 다른 부분들 예를 들어 로고나... 카테고리 이름이라던가... 로그인 버튼 등은 바뀔 필요가 없으니 변경사항이 없을 거고 게시물 목록이 바뀌었을 테니 저 목록 중 게시물 목록을 담당하는 놈을 찾아주면 된다.

 

Preview 탭

항목을 클릭하고 Preview 탭에 들어가면 내용을 확인할 수 있다.

내용을 보아하니 이놈이 내가 찾던 놈이구만?

 

Header 탭

Header에 들어가면 그렇게 찾아 헤매던 Request URL을 알아낼 수 있다.

안드로이드에서 HTTP 통신을 할 때 우리가 흔히 사용하는 url 주소를 사용하는 게 아니라 이걸 사용해야 한다.

크롬 주소창에 있는 그 주소는 사용하기 편하라고 간편하게 줄여놓은 거고 이게 진짜 request를 하기 위한 주소이다.

 

1-2. JSON과 HTML

HTML은 Preview로 봤을 때 위 사진처럼 보인다.

request를 했을 때 사이트에서 응답해주는 값이 json형태 일수도 있고 html형태일 수도 있다.

앞서 보여주었던 배달의 민족 사이트가 json 그리고 지금 위에 보이는 사진이 html 형태이다.

(딱 봐도 느낌 오시쥬? 😉)

차이점을 설명하기엔 오늘 게시물이 너무 길어질 것 같으므로 내가 요청을 보내고자 하는 사이트가 어떤 형태로 응답을 하는지 알아두기만 하고 넘어가자. 형태에 따라 뒤에서 해야 할 것이 달라지므로...

 

1-3. GET과 POST

Request Method

앞서 말했듯이 응답을 받는 형태도 여러 종류가 있지만 보내는 요청의 형태도 여러 가지가 있다.

GET, POST, PUT, DELETE 총 4가지가 있으나 이 게시물에서는 크롤링을 목적으로 Retrofit을 사용할 것이기 때문에 GET과 POST만 확인하면 된다.

 

만약 Request Method가

GET으로 되어있다면 우리는 GET 요청을 해야만 응답을 받을 수 있고

POST로 되어있다면 POST 요청을 해야만 응답을 받을 수 있다.

즉 사이트에서 정해놓은 방법대로 요청을 해야 한다는 것이다.

 

보통은 GET 요청으로 게시물을 조회할 수 있도록 만들어두는 것이 권장되는 방법이지만
POST를 이용하도록 만든 사이트들도 있다. (우리 학교 사이트가 이랬음...)
GET과 POST에 대한 자세한 내용은 따로 글을 올려야 할 것 같다.

 

1-4. parameter

parameter

파라미터 없이 요청만 하면 결과를 내놓는 사이트도 있고

파라미터가 있어야 결과를 내놓는 사이트도 있다.

 

일단, 파라미터 목록은 Header 탭에 같이 적혀있다. 단 저기에 있는 게 전부 필요한 건 아니고 필수 파라미터를 골라내야 한다. 예를 들어 몇 페이지를 요청할 건지는 꼭 알려줘야 하기 때문에 page는 필수 파라미터인 걸 알 수 있다. 문제는 이렇게 때려 맞춰서 어떤 게 필수 파라미터인지 찾아내는 건 불확실하다는 거 (필수 여부는 정하는 사람 마음이라.. 😔)

 

https://www.postman.com/downloads/

이때 postman을 이용하면 편하다. api를 테스트하는 프로그램이다. request URL을 붙여 넣고 parameter를 하나씩 빼보면서 요청을 보내보면 응답 결과로 필수 파라미터를 구분할 수 있다.

파라미터를 뺐는데 결과가 잘 나온다? -> 필수 파라미터 아님

파라미터를 뺐는데 결과가 안 나온다? -> 필수 파라미터

 

아무튼 이렇게 꼭 필요한 기본 개념이 끝났다. 드럽게 기네... 읽다가 도망가시면 안 돼요 저 힘들게 썼어요 ㅠㅠ

 

2. 사용 전

2-1. gradle 추가

최신 버전은 Retrofit GitHub에서 확인할 수 있다.
    // Retrofit
    implementation 'com.squareup.retrofit2:retrofit:2.6.2'
    implementation 'com.squareup.retrofit2:converter-gson:2.6.0'

retrofit을 사용하려면 gradle을 추가해야 한다.

두 번째 줄에 있는 converter-gson은 응답 결과가 JSON일 때 객체로 변환해주는 놈이다.

 

2-2. AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="_">

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

    <application
        android:allowBackup="false"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.SelfStudy_Kotlin"
        android:usesCleartextTraffic="true"> <----------- 2번
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

1번은 서버와 통신을 하기 위해 인터넷 권한을 얻는 거고

2번은 http로 시작하는 사이트에 접근하기 위해서 적어준다.

(안드로이드는 기본적으로 http 접근을 허용하지 않기 때문. 만약 https를 지원하는 사이트와 통신할 거면 안 적어줘도 된다)

 

2-3. data class 생성

 

 

배달의 민족 GET 요청 결과 (JSON)

사이트에서 받아온 값이 JSON이라면 그에 맞게 데이터 타입을 준비해두어야 한다.

일단 위 결과를 정리해보면 아래처럼 표현할 수 있다.

 

응답 결과
└ timestamp
└ statusCode
└ statusMessage
└ data
    └ content[0] // '{'가 아닌 '['로 시작했다는 건 배열이란 뜻이다.
        └ contentId
        └ contentSeq
        └ title
        └ content
               .
               .
               .

이걸 date class로 바꾸면 아래처럼 표현할 수 있다.

 

data class Baemin(val timestamp: Long, val statusCode: String, val statusMessage: String, val data: Data)

data class Data(val content: ArrayList<Content>)

data class Content(val contentId: Long, val contentSeq: Long, val title: String, val created: String)

Baemin은 임의로 정해준 이름이고, 나머지는 JSON에 정해져 있는 그대로 사용한 것이다.

content는 배열이기 때문에 ArrayList로 선언하였다.

 

data class Baemin(val data: Data)

data class Data(val content: ArrayList<Content>)

data class Content(val title: String, val created: String)

나는 title과 created만 필요하다! 나는 쓸데없이 다른 데이터까지 다 가져오고 싶지 않다! 하면 위와 같이 필요 없는 건 지워버리면 된다.

 

data class Baemin(val data: Data)

data class Data(val content: ArrayList<Content>)

data class Content(
    @SerializedName("title")
    val title: String,
    @SerializedName("created")
    val date: String
)

JSON에 정해져 있는 이름을 사용하다 보면 마음에 안 드는 변수명이 있을 수도 있다.

예를 들어 created라는 변수명 대신에 date를 사용하고 싶다 하면

위에 @SerializedName("")을 붙여 원래 변수명을 넣어주고 그 밑에 변수를 선언할 때는 원하는 변수명을 사용하면 된다.

 

@SerializedName은 Gson 라이브러리에서 제공하는 어노테이션인데

여기서 Serialize는 data class 객체를 JSON 형태로 변환하는 것을 말한다.

한국말로는 직렬화인데 영어나 한국말이나 드럽게 어렵네 😑

아무튼 그래서 @SerializedName을 이용하면 'date'의 직렬화된 이름은 'created'입니다.라는 뜻이 되는 것이다.

이렇게 표시해두면 GSON converter가 JSON을 받아와서 어노테이션을 보고 'created'값을 'date'에 매핑해준다.

 

분량 조절 실패로 Retrofit 사용 방법은 다음 게시물에서...

 


💡 느낀 점

  • 이 블로그를 처음 개설했을 때 Retrofit에 대해 게시글을 쓴 적이 있었다. 그땐 정리하면서도 감이 잘 안 왔는데 역시 실제로 사용해봐야 확실히 알게 되는 것 같다.
  • 예전에는 JSON 대신에 XML 형태를 많이 썼다는 듯하다.
  • JSON으로 통일해서 리턴해주면 편할 것 같은데 HTML로 리턴하는 사이트도 있어서 불편하다. HTML은 파싱 작업도 거쳐야 해서 비교적 코드가 더러워지고 시간도 더 걸리는 것 같아서 영... 어쩔 수 없는 웹 세상만의 사정이 있겠지? (나는야 웹알못)

📘 참고한 자료


반응형

댓글