본문 바로가기
Development/Front-end

GraphQL 파헤치기(1)

by 알 수 없는 사용자 2020. 2. 7.

 휴몬랩 개발자 진(JIN)입니다. 휴몬랩의 FlowCoding beta버전은 GraphQL을 도입해서 사용하고 있습니다. GraphQL을 도입하면서 어려웠던 개념들을 풀어서 정리해보려고 합니다.

 

 GraphQL은 페이스북에서 개발한 REST보다 효율적이고 강력하고 유연한 대안을 제공하는 새로운 API 표준입니다. GraphQL은 클라이언트가 API에 필요한 데이터를 정확하게 지정해서 요구해서 필요한 데이터만 받을 수 있습니다. 

따라서 GraphQL은 질의어(Query Language)로 서버 - 클라이언트 간의 통신 스펙. 즉 '명세서'라는 것입니다.

 

 우리가 DB에 SQL로 쿼리를 날려 필요한 데이터를 가져오거나 DB를 수정, 삭제하는 등 업데이트를 하는 것을 생각하는 것처럼 GraphQL도 마찬가지로 가져오거나 업데이트할 쿼리를 날리는데 DB가 아닌 API에 요청하는 것입니다.

 

SQL : 데이터베이스로 보냄 - 데이터베이스 쿼리 언어

GraphQL : API로 보냄  - 인터넷용 쿼리 언어

 

SQL은 데이터 테이블에 저장되지만 GraphQL은 저장 환경을 가리지 않습니다! 단일 DB / 여러 DB / 파일 시스템 / 기존 REST API / 또 다른 GraphQL API에서도 데이터를 받아올 수 있습니다.


REST API vs GraphQL

데이터는 읽고 / 쓰고 / 갱신하고 / 삭제할 수 있다는 SQL의 철학은 REST에 영향을 주긴 했습니다.

HTTP를 이용해 이런 CRUD작업을 GET, POST, PUT, DELETE 같은 HTTP메서드를 사용했습니다. 하지만, REST에서 데이터를 읽거나 변경하려면 각각의 수 많은 엔드포인트 URL을 사용해야 했고, 실제 쿼리 언어를 사용할 수는 없었습니다! 

 

GraphQL은 앞서 말한 것처럼 Query언어가 DB용이었다면 인터넷용으로 만들어진 쿼리 언어입니다. SQL처럼 GraphQL 쿼리도 데이터를 한데 모아 받아옵니다.

 

 

REST API의 아쉬웠던 점

 

1. 수 많은 엔드포인트

REST API의 엔드포인트들...

[출처]https://www.howtographql.com/basics/2-core-concepts/

 

REST API는 위의 그림처럼 단순히

/users/id?=JIN 으로 사용자 요청으로 서버에서 데이터를 불러와 사용자에게 필요한 정보들을 받습니다.

/users/id?=JIN/posts 로 그 JIN의 포스트 내용을 받습니다.

/users/id?=JIN/followers로 JIN의 팔로워 정보를 요청해서 get으로 데이터를 받습니다.

 

벌써 엔드포인트가 3개가 생겼고, 실제 프로젝트가 커지면 애플리케이션에서 처리해야할 엔드포인트는 엄청나게 많아질 수 있습니다. 프론트엔드 , 백엔드 개발자 간의 협업 시 이런 엔드포인트에 대한 설계와 커뮤니케이션에 많은 시간을 소모해야 했습니다.

 

GraphQL은 단일 엔드포인트!

[출처]https://www.howtographql.com/basics/2-core-concepts/

 

GraphQL은 하나의 엔드포인트만 만들어 소모적인 협업 시간을 줄일 수 있습니다.(물론, 명세를 작성한 schema에 따른 협업은 존재합니다!) 

 

2. 오버 페칭(over-fetching) 

 REST API에서는 내가 요청한 정보보다 더 많은 정보를 서버에서 받는 것을 '오버 페칭'이라고 합니다.

 

ex) https://kpopApi/bts/1 이라는 가상의 api로 요청을 했을 때 이름과 역할만 원하는데 5개의 키가 담긴 정보가 들어와 오버 페칭되었습니다.

{
    "name": "Jimin",
    "height": "178",
    "weight": "68",
    "role": ["vocal", "dance"]
    "album": [
    	"https://kpopApi/bts/albums/1"
        "https://kpopApi/bts/albums/2"
        "https://kpopApi/bts/albums/3"
        "https://kpopApi/bts/albums/4"
        "https://kpopApi/bts/albums/5"
    ]
}

 

3. 언더 페칭(under-fetching)

사용자가 요청한 URL에서 추가적인 데이터를 요청할 상황이 생기는 데 이를 '언더 페칭'이라고 합니다.

 

ex) 이번엔 페이지에 지민의 정보와 bts의 앨범 제목들을 뿌리고 싶습니다.

그렇다면 위에서 album키의 배열의 각 앨범에 대한 요청을 5번 더 보내야 합니다.

그런데 그 각 요청에서 필요한 데이터는 오직 앨범 제목입니다.

받은 객체의 데이터에서 나머지 데이터는 사용하지 않을 거지만 같이 받아야 합니다. 과도한 데이터를 받는 것입니다. 

이런 과도한 데이터는 네트워크나 기기의 속도가 현저히 낮을 경우 컨텐츠를 못 보게 될 가능성도 생기게 됩니다!

 

GraphQL 쿼리어

Query(질의)

SELECT의 읽기 기능을 요청할 수 있습니다.

/* Query */
query lifts{
 bts{
   name
   statue
 }
}

query trails{
 allTrails{
   name
   difficulty
  }
}

/* 한 번에 받아오고 싶다면 */
query liftsAndtrails{
  liftCount(status: OPEN)
  
  allLifts{
	  name
      statue
    }
    
  allTrails{
      name
      difficulty
   }
}

GraphQL의 장점은 쿼리 한 번에 여러 종류의 data를 모두 받을 수 있습니다.

liftCount / allLifts / allTrails라는 3개의 필트를 루트 쿼리(liftsAndTrails) 안에 감싸주었습니다. 

 

Mutation(변형)

UPDATE / INSERT / DELETE의 기능을 합니다.

이라는 데이터 타입으로 데이터를 조작할 수 있습니다. Query가 단순한 읽기였다면 Mutation이란 말처럼 쿼리를 통해서 백엔드의 데이터를 변형할 수 있습니다.

 

/* Mutation */
mutation{
  addAlbum(album:"LOVE YOURSELF", release :'2018' ,title:'boy with love'){
  	id
    release,
    title
  }
}

mutation{
   deleteAlbum(id:3)
}

 

Subscription(구독)

소켓 연결로 전달되는 데이터 변경 사항을 감지합니다. 서버에서 실시간 데이터를 받을 때 사용하고, 페이스북의 '실시간 좋아요' 서비스에 적용되고 있습니다. HTTP가 정적인 프로토콜이라 이러한 소켓통신을 통해서 사용자가 새 로고 침 없이 실시간으로 데이터를 받아올 수 있습니다.

 

GraphQL은 데이터의 정보를 담은 '명세서'일뿐이고 언어에 상관없이( JAVA / JavaScript / C# / python / etc ) 쿼리문은 똑같은 구문을 사용한 문자열로, POST request본문에 담겨 GraphQL의 단일 엔드포인트로 전송됩니다.

(모든 Query든 Mutation이든 서버에서 받기 때문에 POST 전송을 해야합니다)

 

정리

GraphQL과 REST API와 GraphQL의 차이점을 알아봤습니다. 정리하면 GraphQL은 쿼리란 명세서에 data가 어떻게 보일 지 정의하고 Query(질의)를 resolve(해결)하는 함수를 만드는 것으로 생각하면 좋을 것 같습니다. GraphQL이란 개념은 들어만 보다가 실제 적용해보니 단일 엔드포인트로 클라이언트-백엔드 개발자 간의 협업 방식만 잘 맞추면 효율적으로 데이터를 요청하고 받을 수 있을 것 같다는 생각이 들었습니다:) 앞으로 GraphQL에 대한 포스팅을 더 정리해서 올리도록 해볼 예정입니다. 감사합니다.

 

 

[References]

웹 앱 API 개발을 위한 GraphQL / 프로그래밍 인사이트 / 이브 포셀로, 뱅크스 / 배영 옮김

댓글