현재 개발하고 있는 서비스는 익숙하게 개발하던 REST API가 아닌 GraphQL을 사용하고 있다.
서비스 기획하고 개발 스택을 정할 때, 계속 해왔던 방식 말고 새로운 기술을 사용해보자는 욕심들이 있었고,
그렇게 해서 선택하게 된 게 GraphQL이였다.
GraphQL을 사용하기 위해서는 백엔드만 사용하면 되는 것이 아니라 프론트에서도 같이 사용해야 했어서
선택해도 될까 걱정을 했었는데 프론트 파트도 새로운 기술을 사용하는 것에 흔쾌히 동의해서 사용할 수 있었다.
그렇게 선택해서 사용한지 벌써 6개월 정도 되었는데 이 시점에서 GraphQL에 대해서 글을 쓰는 이유는
지금 알고 있는 GraphQL 사용법(?)을 정리해보려는 이유도 있지만
사실은 GraphQL을 잘 사용하고 있는건지 스스로 의문이 들기 때문이다.
그리고 대부분 이런 의문이 들고 있을 땐 제대로 사용을 못하고 있는 상태인 것 같아서..
이미 프로젝트의 오픈 기간이 다가오고 있긴 하지만, 리팩토링도 진행해야 하기 때문에 그 때를 위해 확실하게 알고 넘어가보려고 한다.
GraphQL은 API를 위한 쿼리 언어이며 타입 시스템을 사용하여 쿼리를 실행하는 서버사이드 런타임이다.
API 설계 방식 중 하나로, REST API가 그렇듯 특정 언어에 종속되는 기술이 아니고 특정 데이터베이스에도 종속되어 있지 않다.
왜 쿼리 언어라고 할까?라고 한다면 그 이유는 GraphQL을 사용하여 클라이언트에서 서버로 데이터를 요청할 때
필요한 정보를 쿼리문으로 만들어 요청하기 때문이다.
같은 쿼리 언어인 SQL을 생각해보면 되는데, SQL은 데이터베이스에 저장된 데이터를 가져오는 것이 목적이라면
GraphQL은 클라이언트가 서버로부터 데이터를 가져오는 것이 목적이다.
// gql 예시
{
user(name: "yujuck") {
age
email
phone
}
}
EndPoint가 하나인 것이 GraphQL의 가장 큰 특징인 것 같다.
REST API와 비교를 많이 하게 되는데, REST API는 Method와 url로 API를 설계하여 다양한 EndPoint를 만드는 반면,
GraphQL은 단 하나의 Endpoint만 존재하고, 클라이언트가 보내는 쿼리문에 따라 정보를 전달해준다.
밑에서 말할 GraphQL을 사용해야하는 이유 또한 GraphQL의 특징이라고 말할 수 있다.
공식에서 이 블로그의 글을 통해 GraphQL을 사용해야하 하는 이유에 대해서 말하고 있다.
GraphQL은 스키마 정의로부터 시작이 된다.
GraphQL 스키마 작성에 사용되는 자체 형식 언어인 SDL(Schema Definition Language)을 사용하여 정의한다.
// 예시
type Query {
hero(episode: Episode): Character
droid(id: ID!): Droid
}
GraphQL 스키마는 모든 GraphQL API의 backbone이다. (backbone을 핵심구조라는 의미로 사용하는 것 같다)
위의 코드처럼 타입 정의를 통해 API에 대한 정의를 하는데,
타입으로 정의가 되기 때문에 개발하면서 API 호출 시 발생할 수 있는 오류를 확인할 수도 있고,
편집기에서 API 작업에 대한 자동 완성 기능을 사용할 수도 있다.
또 다른 이점으로는 개발자가 수동으로 API 문서를 작성할 필요가 없다는 것을 얘기하고 있다.
스키마 자체가 API를 정의하고 있기 때문에 따로 문서를 작성하지 않더라고 스키마만 보고 확인할 수 있다는 것이 장점이라는 얘기인데,
이 부분에 대해서는 처음에는 익숙하지 않았는데 지금은 꽤 좋다고 느끼고 있다.
처음에 익숙하지 않았던 이유는,
이전 프로젝트에서는 NestJS에서 제공하고 있는 Swagger 모듈을 사용하여 문서를 만들었는데,
그렇게 하면 API 명세를 한눈에 볼 수 있는 페이지를 제공할 수 있다.
근데 이번에 GraphQL을 사용하면서는 따로 문서 작성을 하지 않고 GraphQL Playground의 Docs를 확인하며 개발할 수 있도록 했다.
처음에는 뭔가 한눈에 정리되어 보이지는 않아서 좀 불편하다고 생각을 했는데,
지금 다시 생각해보면 Swagger는 그렇게 보여주기 위해 수고가 드는 반면
GraphQL의 Docs는 쿼리/뮤테이션에 대한 정의만으로 알아서 만들어지기 때문에 편하긴 한 것 같다.
이제는 Docs를 참고해서 보는 것 자체에도 익숙해져서 그런 것 같다.
오버페칭, 언더페칭은 GraphQL의 장점에 꼭 언급되는 내용이다.
REST API와 비교해보면 이해가 쉽다.
상품의 정보를 가져와야 하는 A, B 페이지가 있다고 하자.
A 페이지에서는 name, price 를 가져와야 하고
B 페이지에서는 name, price, seller, category를 가져와야 한다.
이런 경우 REST API에서는 상품의 정보를 조회할 수 있는 하나의 엔드포인트를 만들고 A, B 페이지에서 공통으로 사용할 수 있도록 모든 필드에 대한 정보를 리턴한다.
[GET] /product/:id
라는 API를 만들어 response로는 다음과 같이 전달할 것이다.
{
name: 'custom keyboard',
price: 1000,
seller: 'yujuck',
category: 'keyboard'
}
이렇게 하면 A 페이지에서는 필요없는 seller, category가 포함된 응답을 받게 되는데, 이를 오버페칭
이라고 한다.
오버페칭은 클라이언트가 가져오는 시점에 실제로 필요하지 않은 데이터를 가져오는 것을 의미한다.
GraphQL을 사용한다면 클라이언트에서 원하는 데이터만 골라서 쿼리를 만들 수 있기 때문에 오버페칭은 일어나지 않는다.
실제로 사용하면서도 좋은 점으로 느낀 부분인데, 위에 예시로 든 상황에서 REST API로도 다른 엔드포인트를 만든다면 오버페칭이 발생하지 않도록 할 수는 있다.
하지만 GraphQL은 다른 Query를 만들지 않더라도 가능하기 때문에 이러한 작업들은 없어도 되서 좋긴 한 것 같다.
언더페칭
은 오버페칭과 반대의 의미로, API 응답에 포함된 데이터가 충분하지 않음을 의미한다.
클라이언트는 원하는 데이터를 가져오기 위해 여러 API 요청이 필요하다는 것을 의미한다.
GraphQL은 하나의 endpoint로 한번의 네트워크 요청을 통해 필요한 데이터를 가져올 수 있기 때문에
언더페칭도 일어나지 않는다.
GraphQL의 단점으로 언급되는 내용이 몇개 있다.
HTTP 캐싱 활용이 어렵다는 점인데, GraphQL은 단일 엔드포인트를 가지고 있기 때문에
REST API처럼 엔드포인트에 따라 캐싱을 설정할 수 없어 HTTP 캐싱의 이점을 누리기 어렵다.
Apollo Client를 사용하면 캐시 옵션을 설정해 메모리 상에 캐싱 데이터를 저장하는 방식으로 캐싱 할 수 있다.
결국 서버 레벨에서의 캐시 컨트롤이 아닌 클라이언트 레벨에서 컨트롤된다.
GraphQL을 사용하며 느낀 점은..
위에서 말한 GraphQL을 사용해야하는 이유, 즉 GraphQL의 장점들에는 공감을 한다.
문서를 따로 만들지 않아도 되는 것은 실제로 편하기도 하고
같은 쿼리로 다른 데이터를 조회해야하는 페이지가 있을 때 하나의 쿼리에 각각의 페이지에 필요한 데이터를 응답으로 추가만 하면 되는 부분도 좋은 것 같긴 하다.
장점을 잘 못느끼고 있다고 생각했었는데 글을 쓰면서 다시 생각해보니까 편한 부분도 있긴 했던 것 같다.
근데 사실 그렇다고 아주 좋다고 느끼고 있지도 않긴 하다.
이게 아직 REST API를 사용해왔던 기간보다 짧아서 덜 익숙해서인지는 잘 모르겠지만
특출나게 GraphQL이 더 좋다고 말할 수 있는 부분이.. 있는지 잘 모르겠다.
오버페칭, 언더페칭도 백엔드 입장에서 큰 장점인지는 잘 모르겠고..(위에 말한거 빼고)
뭔가 프론트 입장에서 좋은 방식인 것 같다.
무엇보다 지금 프로젝트를 진행할 때 GraphQL를 사용해본 사람도 없는 상황에서
빠르게 API를 개발하면서 공부를 하다보니 API 설계가 약간 REST API를 사용하는 것처럼 되어버려서
이 부분은 굉장히 아쉽다..
이걸 깨닫고 난 다음에는 최대한 GraphQL의 성격에 맞게 만들고 있긴 한데..
리팩토링이 가능할까 싶은 ㅠㅠ
어쨌든 계속 사용을 해야하기 때문에 계속 찾아보면서 제대로 활용하지 못하고 있는 부분을 채워가고 싶다.
지금은 백엔드 파트에 2명 밖에 없어서 DB 스키마 설계하면서 바로 API 만들고 이런 식으로 진행하느라..
정신없이 API만 계속 만들고 있어서 굉장히 아쉽..
이 와중에 이제 1차 오픈을 해야해서 개발/운영 서버 설정도 해야해서 여러모로 정신이 없는 상태인데,
어느 정도 안정화 되면 코드를 좀 더 정리해야겠다는 생각이 든다.
참고