GraphQL 연재 1편으로 스키마를 정의하는 세 가지 방식을 비교한다. 클래스로 직접 만드는 방식, 스키마 정의 문자열에서 만드는 스키마 우선 방식, 코드에서 유도해 내는 코드 우선 방식이다. 카카오스타일은 한때 코드 우선을 전체에 적용했다가 스키마 우선으로 되돌아왔고 그 이유를 네 가지로 정리한다.
핵심 포인트- GraphQL 자체는 데이터 query 를 어떻게 할지만 정해둔 것이고, 개념이 간단하다고 구현까지 간단한 것은 아니다.
- 스키마는 GraphQLSchema 클래스의 인스턴스다. 클래스로 직접 정의할 수 있지만 간단한 스키마에도 노력이 많이 들고 틀리기 쉽다.
- 다만 내부적으로는 그 형태이므로 이해해두면 GraphQL 실행 최적화 때 도움이 된다.
- 스키마 우선은 스키마 정의 문자열에서 buildSchema 로 만드는 방식이다. graphql-java 와 DGS 도 이 방식을 지원하며 리졸버는 따로 붙인다.
- 코드 우선은 기본 라이브러리가 아닌 별도 도구가 필요하며, 리졸버 구현에 어차피 필요한 모델 클래스를 스키마 정의에 그대로 쓸 수 있다는 장점이 있다.
상세 정리- 설명은 참조 구현인 graphql-js 를 중심으로 하고, 대중적으로 쓰이는 Java 계열 라이브러리도 일부 포함한다. 언어와 구현체마다 세부는 달라도 개념은 크게 다르지 않다고 본다.
- 클래스 직접 정의 방식은 리졸버를 정의 시 함께 포함할 수 있다는 장점이 있어 도입 초기에 잠깐 썼지만 지금은 쓰지 않는다.
- 루트 타입 이름을 RootQueryType 에서 Query 로 바꾸면 더 익숙한 형태의 스키마가 나온다.
- gql 태그를 쓰는 방법도 있는데, parse 함수를 거쳐 GraphQLSchema 가 아닌 DocumentNode 를 만들기 때문에 별도로 스키마 객체로 변환해야 한다.
- gql 태그의 장점은 IDE 문법 강조였지만 지금은 태그 없이도 강조가 되고, 카카오스타일은 질의를 별도 파일로 분리해 강조를 받고 있어 이 방식을 쓰지 않는다.
- 코드 우선을 전면 도입했던 이유는 같은 모델을 데이터베이스 테이블 정의에도 쓸 수 있다는 점이 좋아 보였기 때문이다.
- 되돌린 이유 첫째는 GraphQL 타입과 데이터베이스 테이블이 미묘하게 달라 한 클래스로 양쪽을 지원하는 게 어색한 경우가 많았다는 것이다.
- 둘째는 다른 서비스가 이 API 를 쓸 때 제공되는 스키마 전체를 한눈에 보고 싶은데, 코드와 스키마가 섞여 있어 어렵다는 점이다.
- 셋째는 원하는 스키마를 만들기 위해 도구의 방식을 따로 배워야 한다는 점이다. TypeScript 타입을 옵션으로 지정하는 식이라 직관성이 떨어진다.
- 넷째는 도구로 안 되는 부분이 있었다는 것이다. 당시 enum 에 주석을 다는 게 불가능했고, 지금은 가능해졌지만 TypeScript 한계로 자연스럽지 않다.
- 그래서 현재는 스키마 우선을 쓴다. 스키마 타입과 코드 클래스를 각각 정의해야 하는 단점은 코드 생성기를 쓰면 어느 정도 해소된다.
왜 읽나GraphQL 을 도입하며 스키마를 어느 쪽에서 정의할지 고민 중인 팀에게, 코드 우선을 실제로 써보고 되돌린 팀의 구체적인 불만 목록을 보여주는 글.