이 글은 Graphcool의 허락을 받아 한글로 번역했으며, 원문은 이곳에서 확인할 수 있습니다.
GraphQL vs Firebase
다양해진 서버 사이드 기술들로 인해, 새로운 앱을 개발할 때 사용할 수 있는 백엔드 서비스에 대한 선택폭이 넓어졌다. 이 글에서는 서버 사이드 기술 중 가장 인기 있는 Firebase와 GraphQL의 특성과 차이점에 대해 알아보도록 하겠다.
개요
세부적인 기술들을 살펴보기 전에, 이들의 탄생 배경과 간략한 특징들을 알아보겠다.
Firebase는 실시간 기능에 초점을 맞춘 백엔드 서비스(Backend-as-a-Service)로 출발했으며, 2014년에 구글에 인수된 이후에는 Analytics, 호스팅, 오류 보고 등의 기능들을 통합적으로 제공하는 모바일, 웹 플랫폼으로 발전했다.
GraphQL는 서버가 데이터를 노출하는 방법을 정의한 기술 표준이다. 몇 년간은 페이스북 내부에서만 사용하다가 2015년에 오픈 소스로 공개되었다. 페이스북은 일종의 명세서(specification)로 GraphQL을 출시했으며, GraphQL을 사용하고자 하는 개발자는 GraphQL 서버를 구축하든지, GraphQL API를 제공하는 Graphcool 같은 서비스를 이용하면 된다.
이것만 보아도 GraphQL과 Firebase가 매우 다르다는 것을 알 수 있을 것이다. GraphQL은 클라이언트가 API를 소비하는 방법만을 정의하며 누가 어떻게 API를 제공하든 상관없다. 이에 반해, Firebase는 그들이 제공하는 플랫폼과 클라이언트들이 매우 강하게 연결된 서비스다.
데이터 구성하기
Firebase, 관리하기는 쉽지만 변경하기는 어렵다
Firebase는 JSON을 이용해 스키마가 없는(schemaless) 형태로 데이터를 저장한다. 데이터베이스는 JSON 트리로 관리되며, 개발자는 자신이 선호하는 방식을 사용하여 기존 데이터를 업데이트할 수 있다. 트리를 수정하여 데이터를 추가, 업데이트, 삭제할 수 있으며 이때 Firebase는 이러한 요청에 대해 검증(validation)을 하지 않는다.
이 방식은 쉽게 이해할 수 있다는 장점이 있지만, 장기간 운영이 필요한 서비스의 경우 코드 관리가 어렵다는 단점이 있다. 개발자는 수동으로 데이터 구조를 관리해야 하며, 프로젝트에서 이들 데이터가 사용되고 있는지 지속해서 확인해야 한다. 이러한 접근 방식은 작은 규모의 프로젝트라면 잘 동작할 수도 있지만, 지속 가능한 애플리케이션 또는 복잡한 애플리케이션을 작성하기에는 적합한 방식이 아니다.
Firebase 문서는 "데이터베이스를 적절히 구조화하려면 철저한 사전 준비가 필요하다"고 설명하고 있다. 데이터 구조를 디자인할 때는 데이터 구조 권장사항을 참고하고, 성능 저하(performance traps)를 피하기 위해 가능한 데이터 트리를 최대한 평면화(flat)하는 것을 권장한다. 애플리케이션에서 필요한 조건들을 사전에 모두 아는 것은 불가능하므로, 개발에 들어가기 전에 적절한 데이터베이스를 설계하는 것은 매우 어려운 일이다. Firebase의 구조화 되지 않은 데이터 저장 방식은 데이터베이스 구조 변경이 필요한 상황이 발생했을 때 큰 문제가 될 것이다.
Firebase 방식으로 데이터를 구성했을 때 가장 큰 단점은 관계(relations) 개념이 없다는 것이다. 트위터를 예로 들면, tweets를 만드는 users 데이터 모델이 있는 경우, JSON 트리에 저장할 때 user와 tweet 객체간의 관계를 어떻게 관리해야 할까? 위에서 언급했듯이 JSON 트리는 가능한 플랫(flat)하게 유지해야 한다고 했다. 이 문제에 대한 가장 일반적인 해결책은 트리에서 ID를 이용해 다른 객체를 참고하는 것이다. 하지만 이 방식은 복잡한 데이터에 대한 쿼리를 처리할 때 문제가 발생할 수 있다. 또 다른 해결책은 데이터를 복제하는 것인데 복제한 데이터 관리 문제가 쟁점이 될 것이며, 데이터가 업데이트될 때 복제한 부분을 업데이트하는 것을 잊어버릴 수도 있으므로 에러가 발생할 가능성이 높다.
Firebase 환경에서는 개발자가 실제로 생각한 것과는 다른 형태(unnatural)로 데이터를 구조화하는 경우가 자주 발생한다. Firebase 보안 규칙을 고려하여 데이터를 설계할 경우, JSON 트리를 구성하는 데이터 노드의 이름을 admin
, userReadable
, userWritable
처럼 데이터 접근 규칙을 상징하는 이름으로 작성하게 되며, 이로 인해 데이터가 복잡해진다.
Graphql, 타입 시스템의 유연함과 안정성
이에 반해, GraphQL은 데이터베이스에 저장되는 데이터를 기술할 수 있는 강력한 타입 시스템을 기반으로 한다. 애플리케이션을 위한 데이터 모델(또는 스키마)은 간단하고 강력한 GraphQL SDL (schema definition language)(IDL) 문법으로 표현된다. 스키마에 기술된 타입은 API의 기본 요소다.
SDL로 트위터 애플리케이션 스키마 예제 코드를 간단히 작성하면 다음과 같다.
type User {
id: ID!
username: String!
followers: [User] @relation(name: "Following")
follows: [User] @relation(name: "Following")
tweets: [Tweet] @relation(name: "UserTweets")
}
type Tweet {
id: ID!
text: String!
author: User @relation(name: "UserTweets")
}
강력한 타입 시스템은 몇 가지 장점이 있다. 우선, 타입 체크와 데이터 검증이 컴파일 및 빌드 타임에 이루어지기 때문에, 개발과정에서 데이터 모델을 안전하게 확장하고 업데이트할 수 있다. 이로 인해, 앱을 수행하는 동안 발생하는 데이터 구조와 관련된 에러 대부분을 방지할 수 있다. 따라서, 강력한 타입 시스템을 따르는 애플리케이션은 유연하며 안전하다!
강력한 타입 시스템은 데이터 검증 이외에도 정적 분석과 같은 추가적인 이점도 제공한다. GraphQL의 경우, 요청하는 쿼리에 대한 정적 분석은 엄청난 성능 향상을 가져다준다.
GraphQL의 강력한 타입 속성으로 인해, Flow, Typescript, Swift, Java와 같은 다른 타입 언어들과 특히 잘 어울린다. 이러한 언어들을 사용해 GraphQL 애플리케이션을 만든다면, 스키마는 클라이언트와 서버 사이의 계약(contract)으로 이해할 수 있다. 이는 코드 생성 또는 클라이언트, 서버 사이드 mocking 데이터를 작성할 때 큰 장점으로 작용한다.
데이터 읽기
Firebase, 제한적인 데이터 검색
Firebase에서 데이터를 읽는 가장 기본적인 방법은 Firebase SDK를 사용하는 것이다. 어떤 플랫폼을 사용하든 Firebase 데이터베이스로부터 데이터를 검색하기 위해서는 일반적으로 아래 단계를 거쳐야 한다.
- Firebase 데이터베이스에 대한 지역(local) 인스턴스를 얻는다. (위에서 언급한 JSON 트리를 저장하고 있는 곳이다) Javascript SDK의 경우,
const db = firebase.database()
를 이용해 인스턴스를 얻을 수 있다. - JSON 트리에서 읽고 싶은 데이터에 대한 경로(path)를 전달한다. 예를 들면,
const tweets = db.ref('user/tweets')
과 같은 형태다. - 데이터 읽기 완료에 대해 반응할 콜백(callback)을 제공한다. 데이터 변경이 발생할 때마다 콜백을 호출할 때는
on
을 사용하고, 특정 시점의 데이터만 관심 있다면once
를 사용할 수 있다. 예를 들면,
tweets.once('value', snapshot => { console.log(snapshot.val()) })
과 같은 형태다.
이 방식은 간단한 데이터인 경우 데이터베이스에서 쉽게 검색할 수 있다는 장점이 있지만, 대부분 애플리케이션에서는 JSON 데이터가 서로 다른 브랜치에 중첩된 구조로 존재하기 때문에 이러한 접근 방식으로는 복잡한 데이터를 다루기가 쉽지 않고, 성능도 떨어진다.
Firebase는 많은 애플리케이션에서 사용되고 있는 페이지네이션(pagination)이나 검색과 같은 기능을 지원하지 않기 때문에 상당한 추가 작업이 필요하다. 또한, Firebase는 검색된 객체의 특정 속성을 기반으로 데이터를 필터링할 수 있는 기능(예를 들어, age
가 21세 이상인 사용자만 검색해야 하는 경우)을 서버 사이드에서 제공하지 않는다. 즉, 클라이언트에서 on
이나 once
를 호출할 때, 필터링 조건을 지정할 수 없다는 뜻이다. 클라이언트가 필터링 작업을 직접 수행해야 하므로 낮은 사양의 기기에서는 성능 저하 문제가 발생할 수 있다.
Firebase는 REST API를 통해 JSON 트리의 특정 경로에 접근할 수 있는 endpoint를 제공한다. 하지만, 데이터가 구조화되지 않은 형태로 저장되어 있으므로 API를 통해 전달받은 데이터에 대한 신뢰성이 떨어진다. 따라서, 특별한 경우에만 REST API를 사용해야 한다.
GraphQL, 강력한 쿼리 기능
GraphQL은 데이터베이스에서 데이터를 읽기 위해 쿼리(query) 라는 개념을 사용한다. 쿼리는 클라이언트의 데이터 요구 조건을 간단하게 그리고 직관적으로(intuitive) 서술한 것이다. 쿼리를 GraphQL 서버로 전송하면, 서버가 이것을 해석하여 JSON 객체와 같은 형태로 결과 데이터를 돌려준다.
위에서 살펴본 스키마를 기반으로 간단한 예제를 살펴보자.
query {
allTweets {
text
author {
username
}
}
}
위의 예제는 현재 데이터베이스에 저장된 모든 트윗들(allTweets)을 요청하는 쿼리다. 서버 응답에는 쿼리의 페이로드(payload)에 정의된 모든 정보가 포함될 것이다. 여기에는 트윗 author
의 username
뿐만 아니라 text
도 포함된다. 서버의 응답은 다음과 같은 모습일 것이다.
{
"data": {
"allTweets": [
{
"text": "GraphQL is awesome 🚀",
"author": {
"username": "johnny"
}
},
{
"text": "Firebase? Sounds dangerous!🔥😱",
"author": {
"username": "mike"
}
},
...
]
}
}
GraphQL 쿼리는 JSON 필드를 선택하는 것과 유사하다고 할 수 있다. 쿼리는 JSON 응답과 같은 모습(shape)을 갖추고 있으므로, 키(key)만 있고 값은 없는 JSON 객체로 볼 수도 있다.
이 쿼리만 보아도 중첩된 정보를 검색할 때 GraphQL 쿼리가 얼마나 강력한지 잘 알 수 있다. 위의 예제에서는 User
에서 Tweet
로 연결된 관계로 이동하려면 author
필드를 통해 딱 한 단계만 더 들어가면 된다. 쿼리를 확장하여 author
별로 최근 팔로워 3명만 요청할 수도 있다.
query {
allTweets {
text
author {
username
followers(last: 3) {
username
}
}
}
}
데이터 그래프의 구조를 따르기만 하면 중첩된 구조를 쿼리할 수 있는 기능 덕분에, GraphQL은 더욱 강력해졌고, 표현력도 훨씬 풍부해졌다.
GraphQL API는 관계(to-many-relation)에 대한 쿼리 요청 시 last
이외에도 first
, before
, after
, skip
등을 인자로 전달할 수 있다. 이러한 API 기능을 활용하면 목록 중 특정 범위에 해당하는 객체만 요청할 수 있으므로 클라이언트에서 페이지네이션을 구현하기가 매우 쉬워진다.
GraphQL 명세서(spec)가 유연하므로, 서버에서 해석할 수 있는 강력한 필터 기능을 클라이언트가 작성할 수 있다. 간단한 Graphcool API에서는 서버에서 반환되는 정보의 양을 제한하는 필터를 작성할 수 있다. 예제를 통해 한번 살펴보자.
이 쿼리는 text
에 "GraphQL"이라는 문자열을 포함하고 있는 모든 트윗들(allTweets)을 검색한다.
query {
allTweets(filter: {
text_contains: "GraphQL"
}) {
text
author {
username
}
}
}
또 다른 쿼리는 2016년 12월 24일 이후에 작성된 모든 트윗들을 검색한다.
{
allTweets(filter: {
createdAt_gt: "2016-12-24T00:00:00.000Z"
}) {
text
author {
username
}
}
}
AND
와 OR
연산자를 이용해 필터 조건을 조합할 수도 있다.
데이터 업데이트
Firebase, JSON 트리에 직접 쓰기
Firebase에서는 일반적으로 SDK를 이용해 데이터베이스를 변경한다. (REST API에서도 이 기능을 지원하고 있다) SDK는 데이터베이스에 데이터를 저장하기 위해 set
, update
, push
, transaction
등 4개의 메서드를 제공하고 있다. 상황에 따라 필요한 메서드를 사용하면 된다. 예를 들어 목록에 새로운 아이템을 추가할 때는 push
를 사용하고, set
과 update
는 기존 데이터를 업데이트할 때 사용한다. (set과 update의 차이는 이곳을 참조하라) 데이터 삭제할 때는 remove
를 호출한다. (set
또는 update
에 null
인자를 전달해도 동일한 효과를 얻을 수 있다)
JSON 트리에서 데이터를 읽을 때와 마찬가지로, 이들 메서드를 호출할 때는 쓰기 작업을 수행해야 하는 JSON 트리 경로를 함께 전달해야 한다.
아래와 같은 방법으로 Firebase에서 트윗을 생성할 수 있다.
const tweet = { ... }
const newTweetKey = firebase.database().ref('user/tweets').push().getKey()
const updates = { }
updates['user/tweets/' + newTweetKey] = tweet
firebase.database().ref().update(updates)
이런 방식에는 데이터 쿼리를 설명할 때 언급했던 Firebase의 제약사항들이 여전히 나타난다. 가장 큰 문제는 데이터베이스에 복잡한 쓰기 작업을 하기 힘들다는 점이다. 서버 사이드의 부족함을 만회하기 위해 클라이언트에서 여러 가지 작업을 수행해야 하기 때문이다.
GraphQL, Mutation을 이용한 데이터 저장 및 업데이트
GraphQL에서는 백앤드 변경사항을 mutation을 이용해 처리한다. Mutation의 문법은 쿼리의 구조를 따르며, 데이터베이스에 쓰는(writes) 역할을 한다. 새로운 트윗을 생성하는 mutation은 다음과 같이 작성할 수 있다.
mutation {
createTweet(text: "GraphQL is awesome!", authorId: "abcdefghijklmnopq") {
id
}
}
이 mutation은 ID가 abcdefghijklmnopq
인 사용자의 이름으로 새로운 트윗을 생성하고 새롭게 생성한 트윗의 id
를 반환한다. 쿼리처럼 mutation도 mutation을 수행한 후에 서버에서 반환하는 페이로드(payload)를 제공할 수 있다. 이로 인해, 서버에 추가적인 요청을 하지 않아도 새로운 데이터에 쉽게 액세스할 수 있다.
GraphQL mutation은 중첩 mutation이 가능하다. 즉 여러 개의 노드를 한 번에 생성할 수 있다. 아래 예제처럼 하나의 mutation만 사용해서 새로운 User
를 생성하는 동시에 첫 번째 Tweet
을 작성할 수 있다.
mutation {
createUser(username: "lee", tweets: [{ text: "This is my first Tweet 😎" }]) {
id
tweets {
id
}
}
}
실시간 기능
Firebase, 데이터베이스 실시간 연결
Firebase은 초기에 실시간 데이터베이스로 시작해서 현재는 좀 더 다양한 백엔드 솔루션을 제공하는 서비스로 발전했다. 이러한 탄생 배경으로 인해 실시간 기능은 Firebase의 핵심 기능이 되었다. Firebase SDK API 디자인은 처음부터 실시간 기능에 중점을 두고 개발되었기 때문에 그 밖의 기능들을 사용할 때 종종 부자연스럽고 직관적이지 못하다고 느낄 때가 많다.
Firebase에서는 콜백을 이용해 JSON 트리에서 특정 데이터를 구독하고 있다가(subscribing), 데이터에 변경사항이 발생하면 콜백에게 알려주는 용도로 실시간 기능을 사용할 수 있다. Javascript SDK를 이용한 아래 예제에서는 로컬 DB를 참조하는 on
메서드를 사용해 변경사항이 발생하면 콜백 함수가 실행되도록 만들었다.
var tweets = firebase.database().ref('user/tweets')
tweets.on('value', snapshot => { console.log(snapshot.val()) }
GraphQL, Subscription을 이용한 실시간 업데이트
GraphQL의 실시간 기능은 subscription을 이용해 구현할 수 있다. Subscription은 문법적으로는 쿼리나 mutation과 유사하며, 개발자가 선언적인(declarative) 방식으로 데이터 요구 조건을 작성할 수 있다.
subscription은 항상 백엔드에서 발생하는 특정 이벤트 타입과 연관되어 있다. 클라이언트가 해당 이벤트 타입을 구독하면 이 이벤트가 발생할 때마다 알림이 발생한다. 크게 세 종류의 이벤트 타입으로 나눌 수 있다.
- 특정 타입의 새로운 노드 생성하기(예를 들면, 사용자가 새로운
Tweet
을 생성하는 것) - 특정 타입의 기존 노드 업데이트하기(예를 들면, 사용자가 기존
Tweet
의 text를 변경하는 것) - 특정 타입의 기존 노드 삭제하기(예를 들면, 사용자가
Tweet
을 삭제하는 것)
이러한 mutation이 발생할 때마다 subscription이 반응(fire)하고 구독 중인 클라이언트는 업데이트된 데이터를 수신하게 된다.
Tweet
타입에 대해 위에서 언급한 모든 이벤트에 반응하는 간단한 subscription 예제를 작성해보자.
subscription {
Tweet {
mutation # CREATED, UPDATED 또는 DELETED
node {
id
text
}
}
}
subscription과 관련된 페이로드에서 두 가지 사실에 주목하라.
mutation
필드는 발생한 mutation 종류에 대한 정보를 전달한다. (CREATED
,UPDATED
또는DELETED
가 해당됨)node
필드를 이용해 신규 생성되었거나 업데이트된 트윗에 관한 정보에 접근할 수 있다.
filter
를 이용해 관심 있는 mutation 종류를 직접 지정할 수 있다. 아래의 예제는 업데이트된 트윗 정보만을 원하는 subscription을 보여주고 있다.
subscription {
Tweet(filter: {
mutation_in: [UPDATED]
}) {
node {
text
}
previousValues {
text
}
}
}
페이로드에 previousValues
를 추가하면 트윗의 text
(node
아래에 중첩된)에 대한 새로운 값뿐만 아니라 변경 전의 text
값도 검색할 수 있다. DELETE
mutation일 때도 적용 가능하다.
GraphQL에서 subscription의 동작 방식이 궁금하거나 React 애플리케이션에서 어떻게 사용할 수 있는지 알고 싶다면, 이 자습서를 참고하길 바란다.
인 증
Firebase, 제한적이며 에러 발생 가능성이 높은 JSON 기반의 접근 권한 설정
Firebase는 JSON 객체에 인증 규칙을 기술한 규칙 기반 권한 시스템(rule-based permission system)을 사용한다. 규칙을 기술하는 JSON 객체의 구조는 데이터베이스의 트리 구조 중 하나와 같아야 한다.
간단한 데이터베이스 규칙을 작성해보겠다. 아래 예제에서는 최근 10분 안에 작성된 트윗에 대해서만 읽기(read) 권한이 부여되며, 쓰기권한은 모두에게 부여된다.
{
"rules": {
"tweets": {
// only messages from the last ten minutes can be read
".read": "data.child('timestamp').val() > (now - 600000)",
// everyone is allowed to perform writes (create, update, delete)
".write": true
}
}
}
데이터에 대한 읽기와 쓰기 권한을 설정하는 규칙을 작성할 수는 있지만, 쓰기권한을 생성(creating), 업데이트(updating), 삭제(deleting)로 구별해서 규칙을 만드는 것은 불가능하다.
이런 방식으로는 특정 사용자에게 새로운 트윗을 생성하는 것만 허용하고, 다른 사용자는 트윗 생성과 삭제를 허용하는 간단한 상황도 표현하기 쉽지 않다. 물론, 앞에서 언급한 상황에 대한 권한 설정을 작성할 수는 있다. 하지만, Firebase 권한 설정 시스템에서 이러한 설정을 하기 위해서는 매우 복잡하고 길고 긴 규칙이 필요할 것이다.
Firebase 권한 시스템의 가장 큰 단점은 접근 권한 규칙이 JSON 객체로 표현되는 평문 문자열로 작성된다는 점이다. 이 방식은 에러가 발생할 확률이 매우 높고, 개발자가 규칙이 제대로 작성되었는지 검증하는 도구를 활용할 수 없다. 개발자가 접근 권한이 제대로 설정되었는지 확인하기 위해서는 실제로 규칙을 적용해서 배포하는 방법밖에 없다.
GraphQL 쿼리, 표현적인 접근 권한 방식
API에서 데이터를 노출하는 방법에 관한 명세서만 있으므로, GraphQL에서는 접근 권한 설정 방법에 대한 기본적인 방침이 존재하지 않는다. GraphQL에서 인증과 접근 권한을 처리하는 방법은 서버 사이드 구현에 의존적이다. 이어지는 다음 글에서는 GraphQL 쿼리를 이용해 Graphcool에서 어떻게 권한 관리를 구현하였는지에 대해 설명하고 있다.
Firebase와 유사하게, Graphcool에서도 화이트리스트(whitelist) 방식의 접근 권한 시스템을 따르고 있다. 따라서, 필요한 작업을 명확하게 명시해야 하며, 허가되지 않은 동작들은 수행할 수 없다. 하지만, 특정 타입의 데이터에 대한 읽기, 쓰기, 업데이트, 삭제 등을 수행할 때 실제 발생하는 동작을 기준으로 권한을 설정할 수 있다는 점에서 Firebase의 방식과 차이가 있다.
특정 필드에 대해 권한을 설정하는 것도 가능하다. name
, address
, relationshipStatus
을 가지고 있는 User
타입이 있다고 가정해보자. name
, address
은 누구나(everyone) 접근할 수 있게 만들고, relationshipStatus
는 특정 그룹(예를 들면 사용자의 친구들)에만 보이도록 설정하고 싶다면 어떻게 해야 할까? name
, address
필드는 누구나 읽을 수 있게 설정하고, relationshipStatus
에 대해서는 퍼미션 쿼리(permission query)를 이용해 접근을 제한하면 이 문제는 간단히 해결할 수 있다.
접근 권한 대상을 정할 때는 아래의 세 가지 방법 중 하나를 이용한다.
- 누구나 이용할 수 있는 연산(operation) 만들기
- 인가된 사용자만 이용할 수 있는 연산 만들기
- 접근 권한을 세밀하게 관리할 수 있는 퍼미션 쿼리 사용하기
이러한 접근법들을 조합하여 강력한 접근 권한 시스템을 개발할 수 있다. GraphQL에서는 사용자에게 인증을 요청하는 권한 설정을 할 수 있을 뿐만 아니라, 사용자 또는 관계(relationships)의 다른 특성들에 대해서도 접근 권한을 지정할 수 있다.
접근 권한 설정이 필요한 모든 상황을 GraphQL 쿼리 문법을 이용해 퍼미션 쿼리로 작성할 수 있다. 개발자들은 권한 설정 방법을 배우기 위해 추가적인 학습을 하지 않아도 되고, 익숙한 문법을 사용해 모든 상황을 표현할 수 있다.
트윗 작성자에게만 삭제를 허락하는 퍼미션 쿼리는 아래와 같은 모습일 것이다.
query ($user_id: ID!, $node_id: ID!) {
SomeTweetExists(
filter: {
id: $node_id,
author: {
id: $user_id
}
}
)
}
퍼미션 쿼리는 서버 사이드에 요청한 연산이 발생하기 전에 평가된다. 연산은 퍼미션 쿼리가 true
를 반환할 때만 수행될 것이다.
클라이언트 사이드 기술들
서버 사이드 기술의 가치는 클라이언트에서 그 기술을 얼마나 쉽게 사용할 수 있는가에 달려있다. 앞서 언급했듯이, Firebase에서는 백앤드 서비스를 이용하려면 자신들의 SDK를 사용하라고 권장한다. REST API를 사용하는 방법도 있지만 구조화되지 않은 JSON 데이터베이스 특성 때문에 REST 이용 시 결과를 예측할 수 없다.
Firebase는 안드로이드, iOS, 웹 등 거의 모든 개발 플랫폼에 대해 SDK를 제공하고 있다. 웹에 대해서는 React, Angular와 같은 UI 프레임워크와 바인딩할 수 있는 기능도 제공하고 있다. 다음번 프로젝트에 Firebase를 도입하면, 개발자는 구글이 제공하는 인프라에 철저히 의존하게 된다. 즉, 구글이 Firebase 서비스를 중단한다면, 애플리케이션의 모든 데이터 계층을 재작성해야 한다는 뜻이다.
이에 반해, GraphQL은 HTTP(또는 다른 transport 계층)를 통해 이용할 수 있다. 하지만, 주요 기능들을 구현한 클라이언트 사이드 프레임워크를 이용하는 것이 시간을 절약하는 방법이자, GraphQL을 쉽게 시작하는 방법이다. 현재 가장 인기있는 클라이언트 라이브러리는 Apollo와 Relay다.
- Apollo: 모든 기능을 갖춘 유연한 GraphQL 클라이언트다. 캐싱, 최적화된 UI, 페이지네이션, 서버 사이드 렌더링을 위한 헬퍼, 데이터 프리페칭(prefetching) 등의 간편 기능을 제공한다. 또한, Apollo는 React, Angular, Vue 등 대부분의 UI 프레임워크 뿐만 아니라 iOS, Android도 지원한다.
- Relay: 페이스북의 GraphQL 클라이언트이며 GraphQL과 함께 오픈소스로 공개되었다. 최근에 1.0 릴리즈가 공식 출시되었다.: Relay Modern. Relay는 매우 정교한 GraphQL 클라이언트지만 학습난이도가 꽤 높다는 단점이 있다. Relay는 Apollo만큼 쉽지는 않지만, 성능 최적화 기능을 제공하며, 많은 데이터를 처리해야 하는 복잡하고 큰 규모의 애플리케이션에 적합하다.
Relay와 Apollo에 대한 보다 자세한 비교는 이 글을 참고하고 이들에 대한 자습서는 Learn Apollo와 Learn Relay에서 확인할 수 있다.
기술 표준(standards)과 커뮤니티
Firebase 플랫폼에 대한 구글이 제공하는 기술 표준은 없다. 개발은 구글 내부에서 이루어지며, Firebase 이용을 돕기 위한 커뮤니티도 부족하다. (Firebase 웹 플랫폼에 대해서만 다루는 몇몇 Firebase 에반젤리스트는 고려하지 않았다)
GraphQL은 오픈 소스로 개발되었다. GraphQL을 어떻게 발전시킬 것인지 논의하는데 누구나 참여하고 공헌할 수 있다. 짧은 시간에도 불구하고, 멋진 커뮤니티들이 많이 탄생했다. 대기업들도 API를 GraphQL로 전환하고 있다. 페이스북은 물론, GitHub, Yelp, Shopify, Coursera와 같은 기업들도 이 대열에 참여하여 GraphQL의 멋진 기능들을 이용하고 있다.
GraphQL 커뮤니티들이 모이는 컨퍼런스로는 베를린과 샌프란시스코에서 열리는 GraphQL Europe, GraphQL Summit이 가장 유명하다.
GraphQL 시작하기
GraphQL을 시작하는 가장 빠른 방법은 Graphcool CLI를 이용하는 것이다. 아래 명령어를 통해 Graphcool에서 GraphQL 백앤드를 생성하고 샘플 데이터 모델을 사용해보자.
# Graphcool CLI 설치
npm install -g graphcool
# 리모트 스키마에 기반한 GraphQL API 생성
graphcool init --schema http://graphqlbin.com/twitter.graphql
위 명령어는 화면에 나타난 endpoint를 통해 접근할 수 있는 GraphQL API를 생성할 것이다. API를 경험하고 싶다면, 브라우저에 URL을 복사하고 쿼리와 mutation을 보내면 된다.
아래는 GraphQL을 시작하고 학습할 때 참고할만한 사이트들이다. 꼭 방문해보길 바란다.
- Quickstart 예제에서는 사용자가 선택한 클라이언트 기술을 이용해 풀 스택 앱을 설치하는 방법을 보여준다.
- 풀 스택 자습서 시리즈에서는 Intercom을 이용한 채팅 지원 환경을 구축하는 방법을 알려준다.
- Graphcool, Apollo 블로그에서는 유용한 자습서들과 GraphQL과 관련된 깊이있는 글들을 만나볼 수 있다.
- GraphQL Weekly는 GraphQL 커뮤니티에서 있었던 최신 소식을 알려주는 뉴스레터다.
요 약
Firebase는 진화된 백앤드 솔루션을 제공하는 현재까지도 여전히 실시간 데이터베이스 서비스를 기반으로 유지되고 있다. 때문에, 호스팅, 클라우드 저장소를 비롯해 많은 기능이 Firebase에 추가되었지만, 복잡한 쿼리 요청이나 보안 규칙 설정 등 대부분의 필수 API 기능들은 부자연스럽거나 어렵게 느껴질 때가 많다. 또한, 구조화되지 않은 상태로 저장된 JSON 데이터는 지속 가능한 코드를 작성하거나 유지 보수하기 어렵게 만든다.
GraphQL을 통해 개발자는 유연함과 안전성이라는 두 가지 장점을 모두 누릴 수 있다. 강력한 타입 시스템의 스키마는 다양한 방법으로 사용될 수 있으며, 클라이언트와 서버 사이에서 개발자의 작업 흐름을 최적화하고, 성능을 최적화하는데 특히 유용하다. Graphcool은 GraphQL을 시작하는 가장 쉬운 방법이며 웹과 모바일 앱 서비스에서 바로 활용할 수 있는 강력한 백앤드 솔루션을 제공한다.
I am Groot! :D
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Congratulations @dakeshi! You have completed some achievement on Steemit and have been rewarded with new badge(s) :
Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here
If you no longer want to receive notifications, reply to this comment with the word
STOP
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Congratulations @dakeshi! You have completed some achievement on Steemit and have been rewarded with new badge(s) :
Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here
If you no longer want to receive notifications, reply to this comment with the word
STOP
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
감사합니다. 많은 도움이 될것 같습니다!
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit