ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Android] Retrofit 알아보기 (REST API/ JSON/ GSON)
    안드로이드 2024. 5. 1. 14:57

    ✏️ TIL(Today I Learned)

    1. REST API

    • REST는 Representational State Transfer의 약자이다.
    • 웹의 장점을 최대한 활용할 수 있는 아키텍처 스타일을 의미한다.
    • 월드 와이드 웹 (WWW) 자체가 REST 아키텍처를 기반으로 구성되어 있다. 자원(리소스)의 식별: 각 리소스는 고유한 URI로 식별됩니다.

     

    1.1 REST의 핵심 원칙

    • 메시지의 상태를 통한 표현: 리소스는 JSON, XML 등의 형식으로 표현된다.
    • 상태가 없는(stateless) 통신: 각 요청은 서버에서 필요한 모든 정보를 포함하고 있어야 한다.
                                                     이를 통해 서버는 각 요청을 개별적으로 처리할 수 있다.
    • 클라이언트-서버 구조: 사용자 인터페이스와 데이터 저장소의 관심사가 분리되어 각각의 독립성이 높다.
    • 캐시 처리 가능: 응답 데이터에 캐싱이 가능한지 여부를 명시하여 성능을 향상할 수 있다.
    • 계층화된 시스템: 서버와 클라이언트 사이에 다양한 계층(보안, 로드 밸런싱 등)이 존재할 수 있다.

     

    1.2 REST와 HTTP

    • REST는 HTTP 프로토콜 위에서 구현되는 경우가 많다.
    • 주요 HTTP 메서드:
      • GET: 리소스 조회
      • POST: 리소스 생성
      • PUT: 리소스 수정
      • DELETE: 리소스 삭제

     

    1.3 RESTful API?

    • RESTful API는 REST 원칙을 지킨 API를 말한다.

     

    2. JSON

    • JavaScript Object Notation의 축약어로 데이터를 저장하거나 전송할 때 많이 사용되는 경량의 DATA 교환 형식이다.
    • JSON데이터는 하나의 NAME과 VALUE로 이루어져있다.
    • NAME (데이터이름): String타입
    • VALUE (값):
      • 문자열 (String): 텍스트 데이터, 큰따옴표로 감싸진 유니코드 문자들의 집합
      • 숫자 (Number): 정수 또는 부동 소수점
      • 객체 (Object): 이름과 값의 쌍의 집합, 중괄호 {}
      • 배열 (Array): 값의 순서 있는 리스트, 대괄호 []
      • 불리언 (Boolean): true 또는 false
      • null: 값이 없음을 나타내는 null

     

    2.1 JSON 배열

    • JSON배열은 중괄호{}가 아닌 대괄호[]로 둘러쌓아 표현한다.
    • JSON배열은 , (쉼표)를 사용하여 여러 JSON 데이터를 포함할 수 있다.
    • 예시:
      {
        "name": "John Doe",
        "age": 30,
        "isStudent": false,
        "addresses": [
          {
            "type": "home",
            "street": "123 Main St",
            "city": "Anytown",
            "country": "Anycountry"
          },
          {
            "type": "work",
            "street": "456 Office Blvd",
            "city": "Worktown",
            "country": "Workcountry"
          }
        ],
        "phoneNumber": null
      }​

     

     

    3. GSON

    Gson은 Google에서 제공하는 오픈소스 라이브러리로, Java와 Kotlin에서 주로 사용된다.

    JSON 데이터를 우리가 사용하는 프로그래밍 언어의 객체로 변환해야 할 때가 있다. 반대로, 객체를 JSON 형태로 변환해야 할 때도 있다. 이러한 작업을 직렬화(Serialization)와 역직렬화(Deserialization)라고 한다.

    Gson 라이브러리는 이러한 작업을 매우 간단하게 해 준다.

     

    3.1 Gson을 사용하는 이유

    • 코드의 간결성:
      일반적으로 JSON을 객체로, 또는 객체를 JSON으로 변환하는 작업은 복잡할 수 있다. 그러나 Gson을 사용하면 한 줄의 코드만으로 이러한 변환 작업을 수행할 수 있다.
    • 성능 효율성:
      Gson은 내부적으로 최적화된 알고리즘을 사용하여 직렬화 및 역직렬화 작업을 빠르게 수행한다. 그렇기 때문에 대규모의 데이터나 복잡한 구조의 객체도 효과적으로 처리할 수 있다.
    • 광범위한 커뮤니티 지원 및 잘 정리된 문서:
      Gson은 Google에서 개발되어 오랜 시간 동안 많은 개발자들에게 사용되어 왔다. 따라서 문제 해결 또는 활용 방안에 관한 다양한 정보와 예제가 인터넷상에 많다. 또한 공식 문서도 매우 잘 정리되어 있어, 필요한 정보를 쉽게 찾아볼 수 있다.

     

    3.2 기본 사용법

    • Kotlin 객체를 JSON으로 변환
      val gson = Gson()
      val jsonString = gson.toJson(someObject)
    • JSON을 Kotlin 객체로 변환
      val myClassInstance: MyClass = gson.fromJson(jsonString, MyClass::class.java)​

    3.3 고급 사용법

    • Custom Serializer/Deserializer: 특정 타입에 대해 사용자 지정 직렬화 및 역직렬화 로직을 정의
    • @SerializedName 어노테이션: Kotlin 필드와 JSON 키 이름이 다를 경우 매핑
      data class Person(
          @SerializedName("person_name")
          val name: String
      )​

     

     

    4. Retrofit

    • Retrofit은 Square Inc. 에서 개발한 안드로이드 및 자바를 위한 타입-세이프한 HTTP 클라이언트 라이브러리이다.
    • REST API의 HTTP 요청을 자바 인터페이스로 변환하는 것을 주목적으로 한다.

    4.1 Retrofit의 장점

    • 코드의 간결성
      • 복잡한 HTTP API 요청을 쉽고 간결하게 만들 수 있다.
      • 간단한 어노테이션을 통해 요청 메서드와 URL을 정의할 수 있다.
    • 안정성과 확장성
      • 내부적으로 OkHttp 라이브러리를 사용하여 통신, 이를 통해 안정적인 통신이 가능하다.
      • 인터셉터를 사용하여 요청/응답 프로세스를 확장하거나 수정할 수 있다.
    • 다양한 플러그인과 컨버터 지원
      • 다양한 데이터 형식(JSON, XML 등)에 대해 데이터 변환 컨버터를 제공한다.
      • RxJava, Coroutines와 같은 비동기 프로그래밍 라이브러리와 연동 가능하다.

     

    4.2  Retrofit 시작하기

    1. Gradle에 Retrofit 라이브러리 추가
      // build.gradle (Module: app)
      dependencies {
          implementation 'com.squareup.retrofit2:retrofit:2.x.x'
          implementation 'com.squareup.retrofit2:converter-gson:2.x.x' // Gson 컨버터 추가
      }​
    2. API 인터페이스 정의
      interface ApiService {
          @GET("users/{id}")
          fun getUser(@Path("id") id: Int): Call<User> // User는 서버 응답으로 받아올 데이터 모델 클래스
      }
    3. Retrofit 인스턴스 생성
      val retrofit = Retrofit.Builder()
          .baseUrl("https://api.example.com/")
          .addConverterFactory(GsonConverterFactory.create())
          .build()
      
      val apiService = retrofit.create(ApiService::class.java) // apiService 객체를 통해 정의된 API 요청 가능

     

    4.3 응답 처리하기

    • 동기식 vs 비동기식 요청
      • 동기식 요청: 현재 스레드에서 실행되며, 응답이 올 때까지 다음 코드의 실행이 중단
        val response: Response<User> = apiService.getUser(id).execute()
      • 비동기식 요청: 콜백을 사용하여 백그라운드에서 실행되며, 응답이 오면 해당 콜백이 호출
        apiService.getUser(id).enqueue(object: Callback<User> {
            override fun onResponse(call: Call<User>, response: Response<User>) {
                // 처리
            }
        
            override fun onFailure(call: Call<User>, t: Throwable) {
                // 오류 처리
            }
        })
    • 응답 객체 사용: Response 객체를 통해 HTTP 응답의 여러 정보에 접근할 수 있다.
      if (response.isSuccessful) {
          val user: User? = response.body()
      } else {
          // 오류 메시지 처리
          val error: String = response.errorBody()?.string() ?: "Unknown error"
      }
    • 오류 처리: Retrofit의 onFailure 콜백은 네트워크 오류나 데이터 변환 오류 등에서 호출된다.
      override fun onFailure(call: Call<User>, t: Throwable) {
          // 오류 메시지 표시
          Log.e("API_ERROR", t.message ?: "Unknown error")
      }

     

Designed by Tistory.