현재 필자는 GraphQL 백엔드를 기반으로 한 프로젝트의 앱을 개발해보고 있다. 아직 Apollo-Client 를 사용하는 안드로이드 관련 자료가 국내에 많이 없다보니, 관련 자료나 팁을 자주 포스팅 해보려 한다. 이번 포스팅에선 Android 앱 개발 시 Apollo-Client 를 사용하여 편리하게 GraphQL 서버와 통신하는 기본적인 방법을 알아보려 한다.
GraphQL 을 클라이언트 단에서 보다 편리하게 사용할 수 있도록 해주는 라이브러리이다.
🙏 편의상 Mac OS 기준으로 설명하는 점 양해 바랍니다.
바~로 Terminal 혹은 iTerm2 켜준 뒤 아래 명령을 입력해준다.
project
단위의 build.gradle
로 이동해준 뒤, dependencies
스코프에 아래 코드를 추가한다.classpath "com.apollographql.apollo:apollo-gradle-plugin:2.5.2"
app
단위의 build.gradle
에서 plugins
에 아래 코드를 추가한다.id 'com.apollographql.apollo'
android
스코프가 보일텐데, 이 안에 아래 코드를 추가해주자.apollo {
generateKotlinModels = true
}
dependencies
에 라이브러리를 추가해주면 된다.
Rx3-support
는 선택이지만,RxJava3
기반의 Call Adapter 를 지정할 수 있어 유용하다! 또한, 코루틴 기반의 호출도 자체적으로 지원해준다.
implementation "com.apollographql.apollo:apollo-runtime:2.5.2"
implementation "com.apollographql.apollo:apollo-android-support:2.5.2"
implementation 'com.apollographql.apollo:apollo-rx3-support:2.5.2'
살짝 불편하긴 한데, 이 작업을 위해선 디렉토리 표시 방식을 기본값인 Android
에서, Project
로 바꿔야 한다. 왜냐하면 main
아래에 패키지를 직접 만들어 줘야 하기 때문이다. 개선 됐으면 좋겠다..
아래 사진처럼 graphql
패키지를 만든 뒤, 프로젝트의 패키지명처럼 하위 패키지들을 만들어 주면 된다.
예시는 com.team_gdb.graphql_test
라는 프로젝트이므로 이렇게 패키지를 만들어줬다.
GraphQL API 를 사용하기 위해선, Query 및 Mutation, 커스텀 스칼라타입 등의 정보가 담겨있는 schema.json
이라는 파일이 필요하다. 여기서부턴 실제 통신이 가능한 GraphQL 서버가 필요한데, 이번 포스팅에선 연습삼아 https://rickandmortyapi.com/graphql 라는 테스트 서버를 이용해보자.
Android Studio 의 터미널에서 아래 명령어를 입력하자.
apollo schema:download --endpoint=https://rickandmortyapi.com/graphql schema.json
정상적으로 실행됐다면, 아까 만든 GraphQL 패키지에 schema.json
이라는 파일이 생성된다.
🤚🏻 엥 잠시만요! 생성이 안되는데요?
서버 문제가 아닌 이상 파일 생성이 안 되는 것은 아닐거고, 가끔 알 수 없는 (?) 이유로 프로젝트 최상위 경로에 생성되는 경우가 간혹 있다. 당황하지 않고 아까 만든 패키지에 드래그 앤 드롭 해주면 된다.
GraphQL 에는 Query
와 Mutation
라는 개념이 존재한다. 단 하나의 End-point 에 여러 개의 Query 및 Mutation 을 중첩하여 호출해서 원하는 정보들을 한 번에 얻을 수 있는 장점이 있다. Query
와 Mutation
은 동일하게 서버 통신 동작을 하지만, Query
는 서버 및 데이터베이스의 상태가 변하지 않는 동작 (ID 유효성 검사, 이미지 다운로드 등) 을 의미하고 Mutation
은 서버 및 데이터베이스의 상태가 변하는 동작 (회원가입, 파일 업로드 등) 을 의미한다고 한다. 이 포스팅에선 자세한 이야기는 다루지 않는다.
아무튼, 이러한 Query
나 Mutation
자체를 작성하는 파일이 필요할 건데, 아래와 같이 생성해주면 된다. 아까 만든 패키지의 최하위 경로에서 마우스 우클릭을 하고, GraphQL File
을 눌러준다. 이름은 자유!
그럼 이제, 예시 쿼리를 작성해보자.
아까 만든 GraphQL File
안에 쿼리를 작성하면 된다. 원하는 정보만 쏙쏙 골라 필드로 담아서 보내면, 이에 대한 결과만 받아볼 수 있다. 쿼리 이름도 반드시 명시해주도록 하자. 필자의 경우 GetCharactersQuery
라고 하겠다.
query GetCharactersQuery {
characters {
results {
name
status
species
gender
image
}
}
}
👮🏻♀️ 여기서 조심해야 할 포인트!
Query, Mutation 파일이 변경될 때마다 Project Rebuild 를 해주어야 한다. 그래야 우리가 작성한 쿼리 및 뮤테이션을 인식한다.
자, 테스트용 쿼리를 작성해보았으니 실제로 호출해보자. 그 전에 GraphQL 은 Playground 를 매우 활발하게 지원해주는 편이므로, https://rickandmortyapi.com/graphql 에서 직접 쿼리를 자유자재로 테스트해볼 수 있다.
위에서 작성한 쿼리를 플레이그라운드에서 호출해보면..!
뭔지는 자세히 모르겠지만 JSON 형식이 갖춰진 응답 데이터가 오게 된다. data
필드 안에 characters
필드가 있고, 이 안에 result
라는 리스트 형식의 필드가 존재한다. 이를 안드로이드에서 받아와보자.
안드로이드에선 아래 예시 코드와 같이 호출부를 구현할 수 있고, 자동으로 콜백 메소드의 파라미터인 Response<GetCharactersQuery.Data>
에 응답 데이터가 담기게 된다. 놀라운 사실은, Apollo-Client
가 모든 응답에 대해 파싱된 객체까지 알아서 자동으로 생성해준 다는 것이다. 따라서 클라이언트 개발자는 매우 편리하게 호출을 할 수 있다. 기존 REST API 호출 시에는 Gson
으로 어쩌구 저쩌구 해서 데이터 클래스에 응답을 하나하나 담아주고 했는데 말이다. 🤦🏻♂️
아 참, 아래 호출부는 실제 사용시에는
Retrofit2
와 마찬가지로 싱글톤 패턴으로 구현한 뒤 사용하면 프로젝트 전역에서 이용할 수 있어 편리하다. 아래는 단지 예제일 뿐이다.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val apolloClient = ApolloClient.builder()
.serverUrl("https://rickandmortyapi.com/graphql/")
.build()
apolloClient.query(GetCharactersQuery())
.enqueue(object : ApolloCall.Callback<GetCharactersQuery.Data>() {
override fun onResponse(response: Response<GetCharactersQuery.Data>) {
// 결과 데이터
response.data?.characters?.results?.forEach {
Log.d("GraphQL", it.toString())
}
}
override fun onFailure(e: ApolloException) {
// 에러 처리
}
})
}
}
정말 놀랍게도 Response<GetCharactersQuery.Data>
타입의 response
라는 녀석 안에 플레이그라운드에서 확인했던 응답 데이터의 JSON 구조 (모양) 그대로 파싱된 클래스가 생성되어 있는데, 이를 활용하여 알맞게 응답 데이터를 핸들링할 수 있다. results
리스트 안에 있는 데이터들을 forEach
를 통해 하나씩 로그캣으로 찍어보자.
그리고 실행을 하게 되면, 로그캣에 이러한 로그가 출력될 것이다.
놀랍지않은가? Apollo-Client
라이브러리가 응답 전용 클래스까지 알아서 척척 만들어준다.
이러한 응답에서 필요한 필드만 골라서 적절히 데이터를 가공하여 사용하면 된다.
이래서 아폴로 아폴로 하는 것이다. 게다가 GraphQL 자체도 매우 편리하고 동작 자체가 효율적이다.
이번 포스팅에선 간단히 Android 에서의 Apollo-Client 사용법에 대해 알아보았다. 앞으로 커스텀 타입 정의, 파일 업로드 등의 내용에 대해 다뤄보려고 한다.