일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- gcm 푸시 번역
- GCM
- Java
- Design Pattern
- nginx
- 성능
- 카프카
- JPA
- 페이스북 번역
- 자바스크립트
- Push
- notification
- 도메인 주도 개발
- 푸시 번역
- nginx설정
- 푸시
- GCM 번역
- nginx설치
- 웹사이트 성능
- git
- kafka
- 디자인패턴
- ddd
- graphql
- 카프카 트랜잭션
- 웹사이트최적화기법
- 웹사이트성능
- php
- APNS
- Today
- Total
간단한 개발관련 내용
[요약] 웹 앱 API 개발을 위한 GraphQL 본문
1장 GraphQL에 오신 것을 환영합니다.
1.1 GraphQL 이란?
GraphQL은 API를 만들 때 사용할 수 있는 쿼리언어입니다. 쿼리에 대한 데이터를 받을 수 있는 런타임이기도 합니다. GraphQL은 선언형(declarative)데이터 페칭(fetching) 언어라고 흔히 일컬어집니다. 그러므로 개발자는 무슨 데이터가 필요한지에 대한 요구사항만 작성하면 되고 어떻게 가져올지는 신경쓰지 않아도 됩니다.?..
1.1.1 GraphQL 명세
GraphQL은 클라이언트와 서버 간의 통신 명세(스펙)입니다.
1.1.2 GraphQL의 설계 원칙
GraphQL API 작성법에 제한은 없으나 GraphQL 서비스를 만들 때 고려해야 할 지침이 몇 가지 있습니다.
- 위계적
- GraphQL 쿼리는 위계성을 띠고 있습니다. 필드 안에 다른 필드가 중첩될 수 있으며, 쿼리와 그에 대한 반환 데이터는 형태가 서로 같습니다.
- 제품 중심적
- 엄격한 타입 제한
- 클라이언트 맞춤 쿼리
- 인트로스펙티브
1.2 GraphQL의 탄생
GraphQL은 페이스북의 클라이언트의 서버 및 애플리케이션 데이터 모델 요구사항과 기능을 정립하기 위한 쿼리 언어였습니다. 2015년 7월, GraphQL 초벌 명세와 graphql.js라는 자바스크립트 GraphQL 레퍼런스 서버를 공개했습니다.
1.3 데이터 전송의 역사
1.3.1 RPC
1.3.2 SOAP
1.3.3 REST
1.4 REST의 단점
1.4.1 오버페칭
특정 데이터를 조회하기 위해 불필요한 데이터를 너무 많이 받아오게된다.
1.4.2 언더페칭
기존API에 추가 데이터를 또 요청하게 되는 상황을 언더페치(underfetch)라고 합니다.
GraphQL을 사용하면 쿼리를 중첩으로 정의해, 페치 한 번에 필요한 모든 데이터를 요청하여 이런 언더페칭 문제를 해결할 수 있습니다.
1.4.3 REST 엔드포인트 관리
REST API에 대한 흔한 불만 하나는 유연성이 부족하다는 것입니다. (한 번 배포되면 고치기 힘들다)
1.5 실생활에서의 GraphQL
1.5.1 GraphQL 클라이언트
GraphQL은 그냥 명세에 불과합니다. GraphQL은 여러 개발환경(React, Vue, 자바스크립트, 브라우저)에 독립적입니다. GraphQL 클라이언트의 목적은 개발자가 빠르게 작업할 수 있는 환경을 만들어주고 애플리케이션의 성능과 효율성을 끌어올리는 것입니다. 네트워크 요청, 데이터 캐싱, 사용자 화면에 데이터 주입 등의 일을 담당합니다. 그 종류가 많으나 Relay와 Apollo가 대표적입니다.
2장 그래프 이론
2.1 그래프 이론 어휘
그래프는 상호 연관 관계에 놓여 있는 객체 집합을 표현할 때 널리 사용합니다. 데이터 포인트(data point) 객체와 이들 사이의 관계가 그래프라 생각하면 됩니다.
- 데이터 포인트
- 데이터 집합이 주어졌을 때, 개별적인 요소로 구분 지을 수 있는 것
- 노드(node), 정점(vertex), 엣지(edge)
- 무방향 그래프(undirected graph)
- 비정렬 쌍(unordered pairs)
- 방향 그래프(directed graph, graph)
2.2 그래프 이론 역사
- 쾨니히스베르크 마을
- 오일러 경로(Eulerian path)
2.3 트리는 그래프다
2.4 실생활에서의 그래프
- 페이스북
- 트위터
3장 GraphQL 쿼리어
GraphQL을 설명하기에 앞서 SQL의 역사(Structured Query Language, SEQEUL) 그리고 REST에 영향을 준 SQL의 철학에 대한 설명으로 연관성 및 유사성에 대해 설명 및 요약한 내용.
GraphQL과 SQL은 둘 다 쿼리 언어이기는 하나, 사용 환경이 완전히 다릅니다. SQL 쿼리는 데이터베이스로 보내는 반면, GraphQL쿼리는 API로 보냅니다.
- SELECT / INSERT, UPDATE, DELETE
- query / mutation, subscription
3.1 GraphQL API 툴
3.1.1 GraphiQL
3.1.2 GraphQL 플레이그라운드
3.1.3 공용 GraphQL API
3.2 GraphQL 쿼리
쿼리 작업으로 API에 데이터를 요청할 수 있습니다. 쿼리안에는 GraphQL 서버에서 받고 싶은 데이터를 써 넣습니다. 쿼리를 보낼 때는 요청 데이터를 필드로 적어 넣습니다. 여기서 필드는 서버에서 받아오는 JSON 응답 데이터의 필드와 일치합니다.
- Query는 GraphQL 타입으로 루트타입이다.
- 쿼리를 작성할 때 필요한 필드들을 중괄호로 감싸는데 이 묶인 블록을 Selection-Set 라고 부릅니다.
- GraphQL 쿼리 결과에 대한 필터링 작업을 하고 싶다면 Query-Arguments를 넘기면 됩니다.
3.2.1 엣지와 연결
GraphQL 쿼리어에서 필드는 Scalar타입과 Object타입 둘 중 하나에 속하게 됩니다.
- Scalar : Int, Float, String, Boolean, ID
- 정수와 실수 타입은 JSON 숫자 타입 데이터를 돌려주고 문자열과 ID 타입은 JSON 문자열 데이터를 돌려줍니다.
- Object: 객체타입은 스키마에 정의한 필드를 그룹으로 묶어 둔 것 입니다.
3.2.2 Fragment
프래그먼트는 셀렉션세트의 일종이며, 여러번 재사용할 수 있습니다.
한 쿼리에 2개 이상의 selection-set에서 중복이 발생할 경우 fragment 식별자를 사용해서 만들면 됩니다.
유니언타입
객체 리스트를 반환하는 방법은 이미 봤는데, 이들은 모두 한 가지 타입만 리스트로 반환합니다. 타입 여러 개를 한 번에 리스트에 담아 반환하고 싶다면 유니언 타입(union type)을 만들면 됩니다. 두 가지 타입을 하나의 집합으로 묶는 것입니다.
인터페이스
인터페이스는 필드 하나로 객체 타입을 여러 개 반환할 때 사용합니다. 추상적인 타입이며, 유사한 객체 타입을 만들 때 구현해야 하는 필드 리스트를 모아둔 것입니다.
3.3 Mutation
3.3.1 쿼리 변수 적용하기
3.4 Subscription
3.5 Introspection
3.6 추상 구문 트리(Abstract Syntax Tree)
4장 스키마 설계하기
GraphQL을 사용하면 API가 REST 엔드포인트의 집합이 아니라 타입 집합으로 보이게 됩니다. API에서 반환할데이터 타입에 대해 생각해 보고, 같이 이야기를 나누어 보고, 이를 제대로 정의해 두는 일입니다. 이러한 데이터 타입의 집합을 스키마라고 부릅니다.
4.1 타입 정의하기
4.1.1 타입
GraphQL에서 타입은 커스텀 객체이며 이를 보고 애플리케이션의 핵심 기능을 알 수 있습니다.
4.1.2 스칼라 타입
4.1.3 열거 타입
4.2 연결과 리스트
- 리스트 null 적용 규칙
- [Int] 리스트 안에 담긴 정수 값은 null이 될 수 있다.
- [Int!] 리스트 안에 담긴 정수 값은 null이 될 수 없다.
- [Int]! 리스트 안의 정수 값은 null이 될 수 있으나, 리스트 자체는 null이 될 수 없다.
- [Int!]! 리스트 안의 정수 값은 null이 될 수 없고, 리스트 자체도 null이 될 수 없다.
4.2.1 일대일 연결
4.2.2 일대다 연결
4.2.3 다대다 연결
- 통과 타입(through type)
- User : friends: [User!]! (X)
- User: friends: [Friendship!]! (O)
4.2.4 여러 타입을 담는 리스트
- 유니언 타입
- 여러 타입들 가운데 하나를 반환할 수 있다.
- union AgendaItem = StudyGroup | Workout
- 인터페이스
- 객체 타입 용도로 만드는 추상타입이며, 스키마 코드의 구조를 조작할 때 좋은 방법입니다.
- interface implement
4.3 인자
4.3.1 데이터 필터링
- 데이터 페이징
- 정렬
4.4 뮤테이션
뮤테이션은 반드시 스키마 안에 정의해 두어야 합니다. 쿼리를 정의할 때처럼 커스텀 타입으로 정의한 다음에 스키마에 추가합니다. 애플리케이션 상태를 바꿀 액션이나 이벤트가 있을 때만 뮤테이션을 작성해야 합니다. 뮤테이션은 애플리케이션의 동사 역할을 해야 합니다. 사용자가 GraphQL 서비스를 가지고 할 수 있는 일을 정의해야 합니다.
4.5 인풋 타입
인풋 타입(input type)을 사용하면 인자 관리를 조금 더 체계적으로 할 수 있습니다. 인풋 타입은 GraphQL 객체 타입과 비슷하나, 인풋 타입은 인자에서만 쓰입니다.
4.6 리턴 타입
페이로드 데이터 말고도 쿼리나 뮤테이션에 대한 메타 정보를 함께 받아야할 때가 있습니다. 단순한 페이로드 데이터 외에 추가적으로 데이터가 더 필요할 때는 필드에 커스텀 객체 타입을 사용합니다.
4.7 Subscription
Subscription 타입은 GraphQL 서비스를 만들 때 실시간 데이터 전송과 더불어 PubSub 디자인 패턴을 사용해야 하는 경우에 유용하게 사용할 수 있습니다.
4.8 스키마 문서화
코멘트를 통한 부가 정보 제공
5장 GraphQL API 만들기
5.1 프로젝트 세팅
5.2 리졸버
5.2.1 루트 리졸버
5.2.2 타입 리졸버
5.2.3 인풋 & 열거 타입 사용하기
5.2.4 엣지와 연결
GraphQL의 진정한 힘은 데이터 포인트 사이를 잇는 연결 고리인 엣지에서 나옵니다. GraphQL 서버 관점에서 보면 보통 타입은 모델에 해당합니다. 타입이 데이터처럼 테이블에 저장된다고 생각해 보세요. 그리고 타입을 서로 연결해 봅시다.
일대일, 일대다, 다대다
5.2.5 커스텀 스칼라
ex) DateTime
5.3 apollo-server-express
5.4 컨텍스트
컨텍스트에 전역으로 사용할 값을 저장해 두면, 리졸버 함수에서 이 값에 접근할 수 있습니다. 컨텍스트에는 인증 정보, 데이터베이스 세부 정보, 로컬 데이터 캐시, 그 외 GraphQL 리졸버 기능에 필요한 모든 정보를 넣어 둘 수 있습니다.
5.4.1 MongoDB 설치하기
5.4.2 컨텍스트에 데이터베이스 추가하기
5.5 깃허브 인증
5.5.1 깃허브 OAuth 설정
5.5.2 권한 부여 설정
5.5.3 githubAuth 뮤테이션
5.5.4 사용자 권한 인증
5.6 마치며
6장 GraphQL 클라이언트
GraphQL 클라이언트는 서버와 통신하는 애플리케이션에 불과합니다. 쿼리와 뮤테이션을 보낼 때 유일하게 신경써야 할 것은 HTTP 요청이 가능한지 여부입니다. 요청에 대한 응답으로 서비스에서 데이터를 보내면 어떤 클라이언트에서든 이를 받아 사용할 수 있습니다.
6.1 GraphQL API 사용하기
클라이언트에서 GraphQL을 사용하는 가장 쉬운 방법은 HTTP요청을 엔드포인트에 보내는 것입니다.
6.1.1 fetch 요청
fetch 패키지
6.1.2 graphql-request
graphql-request 패키지 : fetch 요청을 promise로 감싸, 이를 GraphQL서버에 요청 보낼 때 사용합니다.
6.2 아폴로 클라이언트
현재 사용되는 GraphQL 클라이언트 중 가장 유명한 것은 Relay와 아폴로 클라이언트입니다. Relay는 React와 Native만 지원하므로, React외의 기술에서 사용할 GraphQL 클라이언트가 탄생할 여지가 있었습니다.
Meteor 개발 그룹이 만든 아폴로 클라이언트는 커뮤너티 주도 프로젝트이며, 캐싱, OptimisticUI 업데이트 등의 목표를 달성하기 위한 GraphQL 클라이언트 솔루션입니다. React, Angular, Ember, Vue, iOS, Android 등과 함께 사용할 수 있도록 패키지가 제공됩니다.
6.3 React와 아폴로 클라이언트
6.3.1 프로젝트 설정
6.3.2 아폴로 클라이언트 설정
6.3.3 Query 컴포넌트
아폴로 클라이언트를 사용할 때는 데이터를 받아 와 ReactUI로 불러오는 쿼리를 다루어야 합니다. 데이터를 받아 로딩 상태를 관리하고 UI를 업데이트하는 일은 Query 컴포넌트에서 담당합니다.
6.3.4 Mutation 컴포넌트
GraphQL 서비스로 뮤테이션 요청을 보낼 때는 Mutation 컴포넌트를 사용하면 됩니다.
6.4 인증
6.4.1 사용자 권한 인증
6.4.2 사용자 식별
6.5 캐시 작업
6.5.1 fetch 방침
- cache-first
- cache-only
- cache-and-network
- network-only
- no-cache
6.5.2 캐시 유지
6.5.3 캐시 업데이트
7장 실제 제품을 위한 GraphQL
7.1 subscription
차세대 웹의 장점을 제대로 누리려면 HTTP 요청뿐 아니라 실시간 웹소켓 데이터 통신도 GraphQL을 통해 할 수 있어야 합니다.
7.1.1 subscription 작업
아폴로 서버에는 처음부터 subscription 기능이 들어있습니다. GraphQL 애플리케이션 웹소켓 npm 패키지를 설치해 사용하면 됩니다.
- graphql-subscription : Pub/Sub 패턴틀 실제 구현한 패키지
- subscriptions-transport-ws : 웹소켓 서버와 클라이언트를 제공하는 패키지
7.1.2 subscription 데이터 사용하기
7.2 파일업로드
- apollo-upload-client
- 브라우저에서 파일을 GraphQL과 함께 서버로 전송
- apollo-upload-server
- apollo-upload-client에서 받은 파일을 서버에서 다룰 때
7.2.1 서버 파일 업로드 기능 구현하기
아폴로 서버에는 apollo-upload-server가 내장되어 있으나 업로드한 파일을 받을 수 있게 GraphQL API를 수정해야 한다.
7.2.2 클라이언트 사진 게시 기능 구현하기
7.3 보안
7.3.1 요청 타임아웃
7.3.2 데이터 제한
7.3.3 쿼리 깊이 제한
- graphql-depth-limit 패키지
7.3.4 쿼리 복잡도 제한
- graphql-validatiaon-complexity
7.3.5 아폴로 엔진
GraphQL 서비스를 모니터링하여 많이 사용되는 쿼리를 찾아내고 성능 병복 현상이 발생하는 지점을 찾아낼 수 있다.
환경변수에 ENGINE_API_KEY를 추가하여 CLI를 통해 실행 및 연동 할 수 있다.
- apollo schema:publish —key=<> —endpoint=http://localhost:4000/graphql
7.4 다음 단계
7.4.1 점진적 마이그레이션
- 리졸버 함수에서 REST 데이터 패치
- GraphQL 요청 사용하기
- 한두 개의 컴포넌트만 GraphQL 적용해 보기
- REST 엔드포인트는 더 이상 사용하지 않기
- 사용 중인 REST 엔드포인트는 유지 보수하지 말기
7.4.2 스키마 주도 개발
7.4.2 GraphQL 행사 모음
7.4.4 커뮤너티