SlideShare a Scribd company logo
1 of 53
Download to read offline
GraphQL 적용기
전창완, 데이터블
RESTFul API
RESTFul API
Method Path Body 동작
GET /users 회원 목록 읽기
GET /users/:id 회원 정보 읽기
POST /users {"email": "hi@wani.kr", .. } 회원 정보 저장
PUT/PATCH /users/:id {"email": "hi@wani.kr", .. } 회원 정보 수정
DELETE /users/:id 회원 정보 삭제
RESTFul API
대부분의 프레임워크가 지원, 누구나 쉽게 도입 가능
RESTFul에서 모든 모델은 CRUD로 표현
OAS(Open Api Specification) 표준 존재
RESTFul API 예시 - Github API
Method Path 동작
GET /user 회원 정보 읽기
GET /user/repos 사용자의 저장소 조회
POST /user/repos 저장소 만들기
DELETE /repos/:owner/:repo 저장소 삭제하기
POST /repos/:owner/:repo/transfer 저장소 이동하기
developer.github.com/v3
developers.facebook.com/docs/graph-api
🤔
RESTFul API
데이터 유효성 검사
JSON Schema, JOI, Safen ...
const validator = sfl`{
username: (string & email & length_between(12, 100)) | null,
password?: string & length_between(8, 20),
areas: {
lat: number & between(-90, 90),
lng: number & between(-180, 180),
}[1:] | null,
env: {
referer: url,
ip: ip("v4"),
os: {
name: in("window", "osx", "android", "iphone"),
version: string,
},
},
}`
validator.assert({
username: "wan2land@gmail.com",
areas: [
{lat: 0, lng: 0},
],
env: {
referer: "http://wan2land.github.io",
ip: "127.0.0.1",
os: {
name: "osx",
version: "10.13.1",
},
},
}) // ok
RESTFul API
테스트 + 문서화 도구
Postman
RESTFul API
문서화(코드활용)
Swagger, APIDoc
GraphQL
“GraphQL is a query language
for APIs and a runtime for fulfilling those
queries with your existing data.”
graphql.org
지원언어
graphql.org/code
주요 라이브러리
서버
Apollo, GraphQL Yoga, Type GraphQL, Graphity
웹 클라이언트
apollo-client (react, vue, svelte!)
앱 클라이언트
apollo-ios, apollo-android (flutter는 공식라이브러리가 없는 듯..)
GraphQL 구조
Schema
데이터 구조를 정의, 서버에서 구현
Query
데이터를 읽고 쓰는 명령어, 주로 클라이언트에서 구현
type Query {
user(id: ID!): User
userPagination(take: Int, offset: Int): ListOfUser
}
type Mutation {
createUser(input: InputCreateUser!): User
updateUser(id: ID!, input: InputUpdateUser!): User
deleteUser(id: ID!): User
}
type ListOfUser {
count: Int
nodes: [User!]!
}
Schema
type User {
id: ID!
email: String!
friends: [User!]!
}
input InputCreateUser {
email: String!
}
input InputUpdateUser {
email: String!
}
type Query {
user(id: ID!): User
userPagination(take: Int, offset: Int): ListOfUser
}
type Mutation {
createUser(input: InputCreateUser!): User
updateUser(id: ID!, input: InputUpdateUser!): User
deleteUser(id: ID!): User
}
type ListOfUser {
count: Int
nodes: [User!]!
}
Schema
Name Arguments (생략가능) Return
Name Return
type User {
id: ID!
email: String!
friends: [User!]!
}
input InputCreateUser {
email: String!
}
input InputUpdateUser {
email: String!
}
type Query {
user(id: ID!): User
userPagination(take: Int, offset: Int): ListOfUser
}
type Mutation {
createUser(input: InputCreateUser!): User
updateUser(id: ID!, input: InputUpdateUser!): User
deleteUser(id: ID!): User
}
type ListOfUser {
count: Int
nodes: [User!]!
}
Schema
Entry Point
type User {
id: ID!
email: String!
friends: [User!]!
}
input InputCreateUser {
email: String!
}
input InputUpdateUser {
email: String!
}
GraphQL Types
Scalars
ID, String, Int, Float, Boolean
그외(?)
Object Type, Input Type, Enum, List, Non-Null
type Query {
user(id: ID!): User
userPagination(take: Int, offset: Int): ListOfUser
}
type Mutation {
createUser(input: InputCreateUser!): User
updateUser(id: ID!, input: InputUpdateUser!): User
deleteUser(id: ID!): User
}
type ListOfUser {
count: Int
nodes: [User!]!
}
Schema
type User {
id: ID!
email: String!
friends: [User!]!
}
input InputCreateUser {
email: String!
}
input InputUpdateUser {
email: String!
}
NonNull(List(NonNull(ObjectType)))
Object Type
Input Type
type Query {
user(id: ID!): User
userPagination(take: Int, offset: Int): ListOfUser
}
type Mutation {
createUser(input: InputCreateUser!): User
updateUser(id: ID!, input: InputUpdateUser!): User
deleteUser(id: ID!): User
}
type ListOfUser {
count: Int
nodes: [User!]!
}
Schema
type User {
id: ID!
email: String!
friends: [User!]!
}
input InputCreateUser {
email: String!
}
input InputUpdateUser {
email: String!
}
Arguments에는 Input Type + Scalar
Object Type
Return에는 Object Type + Scalar
Query
query GetUser($id: ID!) {
user(id: $id) {
id
email
friends {
id
email
}
}
}
mutation CreateUser($input: InputCreateUser!) {
user: createUser(input: $input) {
id
email
}
}
query GetUser($id: ID!) {
user(id: $id) {
id
email
friends {
id
email
}
}
}
Query
mutation CreateUser($input: InputCreateUser!) {
user: createUser(input: $input) {
id
email
}
}
Name (생략가능) Arguments
Fields
query GetUser($id: ID!) {
user(id: $id) {
id
email
}
}
Query
{
"data": {
"user": {
"id": "30",
"email": "wan2land@gmail.com"
}
}
}
query GetUser($id: ID!) {
user(id: $id) {
id
email
friends {
id
email
}
}
}
Query {
"data": {
"user": {
"id": "30",
"email": "wan2land@gmail.com",
"friends": [
{
"id": "31",
"email": "wan3land@gmail.com"
},
{
"id": "32",
"email": "wan4land@gmail.com"
}
]
}
}
}
GraphQL Custom Scalars
input InputCreateUser {
email: String!
name: String
}
GraphQL Custom Scalars
input InputCreateUser {
email: String!
name: String
}
"hi@wani.kr" O
"wan2land" O (!?)
GraphQL Custom Scalars
scalar Email
input InputCreateUser {
email: Email!
name: String
}
"hi@wani.kr" O
"wan2land" X
github.com/Urigo/graphql-scalars
GraphQL Custom Scalars
scalar DateTime
scalar EmailAddress
scalar NegativeFloat
scalar NegativeInt
scalar NonNegativeFloat
scalar NonNegativeInt
scalar NonPositiveFloat
scalar NonPositiveInt
scalar PhoneNumber
scalar PositiveFloat
scalar PositiveInt
scalar PostalCode
scalar UnsignedFloat
scalar UnsignedInt
scalar URL
scalar BigInt
scalar Long
scalar GUID
scalar HexColorCode
scalar HSL
scalar HSLA
scalar IPv4
scalar IPv6
scalar ISBN
scalar MAC
scalar Port
GraphQL Description
type Query {
user(id: ID!): User
"""
ex.
userPagination(take: 20, offset: 0) - 1
userPagination(take: 20, offset: 20) - 2
userPagination(take: 20, offset: 40) - 3
"""
userPagination(take: Int, offset: Int): ListOfUser
something(id: ID!): User @deprecated(reason: "use 'user' query")
}
GraphQL Description
type Query {
user(id: ID!): User
"""
ex.
userPagination(take: 20, offset: 0) - 1
userPagination(take: 20, offset: 20) - 2
userPagination(take: 20, offset: 40) - 3
"""
userPagination(take: Int, offset: Int): ListOfUser
something(id: ID!): User @deprecated(reason: "use 'user' query")
}
GraphQL Playground
Swagger + JSON Schema + Postman
iOS와 Android에서도
쉽게 사용할 수 있어요!
여긴 GDG니까 앱 개발자가 많을거야! 😤😤😤
(지인 앱개발자 ⽈)
RESTFul API인 경우, JSON객체를 가져와서 Kotlin/Swift 클래스에 일일이 대입하는 노가다 필요
GraphQL + Application
GraphQL + Application
Apollo iOS / Apollo Android
1. GraphQL Schema 불러오기
2. GraphQL 쿼리 작성
3. codegen
4. 클래스가 자동생성!
GraphQL + Application
남은 문제들
(키워드만 후다닥..)
GraphQL - N + 1
SELECT * FROM `users`
SELECT * FROM `users` WHERE `friend_id` = ?
SELECT * FROM `users` WHERE `friend_id` = ?
SELECT * FROM `users` WHERE `friend_id` = ?
SELECT * FROM `users` WHERE `friend_id` = ?
SELECT * FROM `users` WHERE `friend_id` = ?
...
query GetUser($id: ID!) {
userPagination {
id
friends {
id
}
}
}
목록조회 1번 + 친구조회 20번 = 21번
GraphQL - N + 1
SELECT * FROM `users`
SELECT * FROM `users` WHERE `friend_id` = ?
SELECT * FROM `users` WHERE `friend_id` = ?
SELECT * FROM `users` WHERE `friend_id` = ?
...
SELECT * FROM `users` WHERE `friend_id` = ?
SELECT * FROM `users` WHERE `friend_id` = ?
SELECT * FROM `users` WHERE `friend_id` = ?
...
SELECT * FROM `users` WHERE `friend_id` = ?
SELECT * FROM `users` WHERE `friend_id` = ?
SELECT * FROM `users` WHERE `friend_id` = ?
...
query GetUser($id: ID!) {
userPagination {
id
friends {
id
friends {
id
}
}
}
}
1 + 20 + 20 x 20 = 421번
GraphQL - N + 1
query GetUser($id: ID!) {
userPagination {
id
friends {
id
friends {
id
friends {
id
}
}
}
}
}
????!
GraphQL - N + 1
SELECT * FROM `users`
SELECT * FROM `users` WHERE `friend_id` IN (?, .. )
SELECT * FROM `users` WHERE `friend_id` IN (?, .. )
SELECT * FROM `users` WHERE `friend_id` IN (?, .. )
query GetUser($id: ID!) {
userPagination {
id
friends {
id
friends {
id
friends {
id
}
}
}
}
}
github.com/graphql/dataloader
GraphQL - N + 1
GraphQL - File Upload
scalar Upload
type Mutation {
uploadAttachment(file: Upload): Attachment
}
multipart/form-data 사용
github.com/jaydenseric/graphql-upload
GraphQL - File Upload
blog.apollographql.com/tutorial-graphql-subscriptions-server-side-e51c32dc2951
GraphQL - Subscription
GraphQL - Subscription
type Query {
user(id: ID!): User
userPagination(take: Int, offset: Int): ListOfUser
}
type Mutation {
createUser(input: InputCreateUser!): User
updateUser(id: ID!, input: InputUpdateUser!): User
deleteUser(id: ID!): User
}
type Subscription {
onUserCreated: User
onUserUpdated(id: ID!): User
onDeleteUser(id: ID!): User
}
Event 발생시, 구독가능
GraphQL - Image Response
corgi.photos/300/200
Response는 application/json 로 고정, 위와 같은 image/png는 처리할 수 없음.
(비슷한 예로 엑셀 다운로드)
query {
user(id: 566) {
profile {
id
resize(width: 100, height: 100)
}
}
}
{
"data": {
"user": {
"profile": {
"id": "1324",
"resize": "https://
something.s3.ap-
northeast-2.amazonaws.com/
6c326d50-
c1b8-45d8-80c7-7cd9d472b84f-
w100-h100.jpg"
}
}
}
}
GraphQL - Image Response
요약
GraphQL은 RESTFul API의 대체제로 충분하다.
GraphQL Custom Scalar를 활용하면 추가적인 데이터 유효성검사 라이브러리가 필요없다.
Apollo iOS / Android를 사용하면 앱에서 GraphQL을 훨씬 쉽게 사용할 수 있다.
1+N 문제는 생각보다 쉽게 해결가능하다.
GraphQL에서 파일업로드가 가능하다.
Subscription 활용을 활용하면 채팅 같은 서비스를 만들 수 있다.
이미지 Response는 URL로 사용하자.
Q & A
🙋

More Related Content

What's hot

A Fast Decision Rule Engine for Anomaly Detection
A Fast Decision Rule Engine for Anomaly DetectionA Fast Decision Rule Engine for Anomaly Detection
A Fast Decision Rule Engine for Anomaly DetectionDatabricks
 
GoldenGate and Stream Processing with Special Guest Rakuten
GoldenGate and Stream Processing with Special Guest RakutenGoldenGate and Stream Processing with Special Guest Rakuten
GoldenGate and Stream Processing with Special Guest RakutenJeffrey T. Pollock
 
Survey of High Performance NoSQL Systems
Survey of High Performance NoSQL SystemsSurvey of High Performance NoSQL Systems
Survey of High Performance NoSQL SystemsScyllaDB
 
AWS Summit Seoul 2023 | 롯데면세점이 고객에게 차별화된 경험을 제공하는 방법: AWS Native 서비스를 활용한 초개인...
AWS Summit Seoul 2023 | 롯데면세점이 고객에게 차별화된 경험을 제공하는 방법: AWS Native 서비스를 활용한 초개인...AWS Summit Seoul 2023 | 롯데면세점이 고객에게 차별화된 경험을 제공하는 방법: AWS Native 서비스를 활용한 초개인...
AWS Summit Seoul 2023 | 롯데면세점이 고객에게 차별화된 경험을 제공하는 방법: AWS Native 서비스를 활용한 초개인...Amazon Web Services Korea
 
Data Transformation Patterns in AWS - AWS Online Tech Talks
Data Transformation Patterns in AWS - AWS Online Tech TalksData Transformation Patterns in AWS - AWS Online Tech Talks
Data Transformation Patterns in AWS - AWS Online Tech TalksAmazon Web Services
 
ELK, a real case study
ELK,  a real case studyELK,  a real case study
ELK, a real case studyPaolo Tonin
 
Optimizing SaaS Productivity for CEOs, CFOs & CIOs with LeanIX's CEO
Optimizing SaaS Productivity for CEOs, CFOs & CIOs with LeanIX's CEOOptimizing SaaS Productivity for CEOs, CFOs & CIOs with LeanIX's CEO
Optimizing SaaS Productivity for CEOs, CFOs & CIOs with LeanIX's CEOsaastr
 
How AWS Minimizes the Blast Radius of Failures (ARC338) - AWS re:Invent 2018
How AWS Minimizes the Blast Radius of Failures (ARC338) - AWS re:Invent 2018How AWS Minimizes the Blast Radius of Failures (ARC338) - AWS re:Invent 2018
How AWS Minimizes the Blast Radius of Failures (ARC338) - AWS re:Invent 2018Amazon Web Services
 
Data and Analytics at Holland & Barrett: Building a '3-Michelin-star' Data Pl...
Data and Analytics at Holland & Barrett: Building a '3-Michelin-star' Data Pl...Data and Analytics at Holland & Barrett: Building a '3-Michelin-star' Data Pl...
Data and Analytics at Holland & Barrett: Building a '3-Michelin-star' Data Pl...Dobo Radichkov
 
Introduction to Graphs with Neo4j
Introduction to Graphs with Neo4jIntroduction to Graphs with Neo4j
Introduction to Graphs with Neo4jNeo4j
 
[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기NAVER D2
 
How to go from zero to data lakes in days - ADB202 - New York AWS Summit
How to go from zero to data lakes in days - ADB202 - New York AWS SummitHow to go from zero to data lakes in days - ADB202 - New York AWS Summit
How to go from zero to data lakes in days - ADB202 - New York AWS SummitAmazon Web Services
 
ABD315_Serverless ETL with AWS Glue
ABD315_Serverless ETL with AWS GlueABD315_Serverless ETL with AWS Glue
ABD315_Serverless ETL with AWS GlueAmazon Web Services
 
Using ML with Amazon SageMaker & GuardDuty to identify anomalous traffic - SE...
Using ML with Amazon SageMaker & GuardDuty to identify anomalous traffic - SE...Using ML with Amazon SageMaker & GuardDuty to identify anomalous traffic - SE...
Using ML with Amazon SageMaker & GuardDuty to identify anomalous traffic - SE...Amazon Web Services
 
Culture Code - Growth Machine
Culture Code - Growth MachineCulture Code - Growth Machine
Culture Code - Growth MachineGrowth_Machine
 
All You Need to Know about AWS Elastic Load Balancer
All You Need to Know about AWS Elastic Load BalancerAll You Need to Know about AWS Elastic Load Balancer
All You Need to Know about AWS Elastic Load BalancerCloudlytics
 
글로벌 고객 사례를 통하여 소개하는 혁신적인 데이터 웨어하우스 - 김형일 (AWS 솔루션즈 아키텍트)
글로벌 고객 사례를 통하여 소개하는 혁신적인 데이터 웨어하우스 - 김형일 (AWS 솔루션즈 아키텍트)글로벌 고객 사례를 통하여 소개하는 혁신적인 데이터 웨어하우스 - 김형일 (AWS 솔루션즈 아키텍트)
글로벌 고객 사례를 통하여 소개하는 혁신적인 데이터 웨어하우스 - 김형일 (AWS 솔루션즈 아키텍트)Amazon Web Services Korea
 

What's hot (20)

A Fast Decision Rule Engine for Anomaly Detection
A Fast Decision Rule Engine for Anomaly DetectionA Fast Decision Rule Engine for Anomaly Detection
A Fast Decision Rule Engine for Anomaly Detection
 
GoldenGate and Stream Processing with Special Guest Rakuten
GoldenGate and Stream Processing with Special Guest RakutenGoldenGate and Stream Processing with Special Guest Rakuten
GoldenGate and Stream Processing with Special Guest Rakuten
 
Dwbi Project
Dwbi ProjectDwbi Project
Dwbi Project
 
Five API Styles
Five API StylesFive API Styles
Five API Styles
 
Survey of High Performance NoSQL Systems
Survey of High Performance NoSQL SystemsSurvey of High Performance NoSQL Systems
Survey of High Performance NoSQL Systems
 
AWS Summit Seoul 2023 | 롯데면세점이 고객에게 차별화된 경험을 제공하는 방법: AWS Native 서비스를 활용한 초개인...
AWS Summit Seoul 2023 | 롯데면세점이 고객에게 차별화된 경험을 제공하는 방법: AWS Native 서비스를 활용한 초개인...AWS Summit Seoul 2023 | 롯데면세점이 고객에게 차별화된 경험을 제공하는 방법: AWS Native 서비스를 활용한 초개인...
AWS Summit Seoul 2023 | 롯데면세점이 고객에게 차별화된 경험을 제공하는 방법: AWS Native 서비스를 활용한 초개인...
 
Data Transformation Patterns in AWS - AWS Online Tech Talks
Data Transformation Patterns in AWS - AWS Online Tech TalksData Transformation Patterns in AWS - AWS Online Tech Talks
Data Transformation Patterns in AWS - AWS Online Tech Talks
 
ELK, a real case study
ELK,  a real case studyELK,  a real case study
ELK, a real case study
 
Optimizing SaaS Productivity for CEOs, CFOs & CIOs with LeanIX's CEO
Optimizing SaaS Productivity for CEOs, CFOs & CIOs with LeanIX's CEOOptimizing SaaS Productivity for CEOs, CFOs & CIOs with LeanIX's CEO
Optimizing SaaS Productivity for CEOs, CFOs & CIOs with LeanIX's CEO
 
How AWS Minimizes the Blast Radius of Failures (ARC338) - AWS re:Invent 2018
How AWS Minimizes the Blast Radius of Failures (ARC338) - AWS re:Invent 2018How AWS Minimizes the Blast Radius of Failures (ARC338) - AWS re:Invent 2018
How AWS Minimizes the Blast Radius of Failures (ARC338) - AWS re:Invent 2018
 
Vue d'ensemble Dremio
Vue d'ensemble DremioVue d'ensemble Dremio
Vue d'ensemble Dremio
 
Data and Analytics at Holland & Barrett: Building a '3-Michelin-star' Data Pl...
Data and Analytics at Holland & Barrett: Building a '3-Michelin-star' Data Pl...Data and Analytics at Holland & Barrett: Building a '3-Michelin-star' Data Pl...
Data and Analytics at Holland & Barrett: Building a '3-Michelin-star' Data Pl...
 
Introduction to Graphs with Neo4j
Introduction to Graphs with Neo4jIntroduction to Graphs with Neo4j
Introduction to Graphs with Neo4j
 
[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기[245] presto 내부구조 파헤치기
[245] presto 내부구조 파헤치기
 
How to go from zero to data lakes in days - ADB202 - New York AWS Summit
How to go from zero to data lakes in days - ADB202 - New York AWS SummitHow to go from zero to data lakes in days - ADB202 - New York AWS Summit
How to go from zero to data lakes in days - ADB202 - New York AWS Summit
 
ABD315_Serverless ETL with AWS Glue
ABD315_Serverless ETL with AWS GlueABD315_Serverless ETL with AWS Glue
ABD315_Serverless ETL with AWS Glue
 
Using ML with Amazon SageMaker & GuardDuty to identify anomalous traffic - SE...
Using ML with Amazon SageMaker & GuardDuty to identify anomalous traffic - SE...Using ML with Amazon SageMaker & GuardDuty to identify anomalous traffic - SE...
Using ML with Amazon SageMaker & GuardDuty to identify anomalous traffic - SE...
 
Culture Code - Growth Machine
Culture Code - Growth MachineCulture Code - Growth Machine
Culture Code - Growth Machine
 
All You Need to Know about AWS Elastic Load Balancer
All You Need to Know about AWS Elastic Load BalancerAll You Need to Know about AWS Elastic Load Balancer
All You Need to Know about AWS Elastic Load Balancer
 
글로벌 고객 사례를 통하여 소개하는 혁신적인 데이터 웨어하우스 - 김형일 (AWS 솔루션즈 아키텍트)
글로벌 고객 사례를 통하여 소개하는 혁신적인 데이터 웨어하우스 - 김형일 (AWS 솔루션즈 아키텍트)글로벌 고객 사례를 통하여 소개하는 혁신적인 데이터 웨어하우스 - 김형일 (AWS 솔루션즈 아키텍트)
글로벌 고객 사례를 통하여 소개하는 혁신적인 데이터 웨어하우스 - 김형일 (AWS 솔루션즈 아키텍트)
 

Similar to GraphQL 적용기

Hello, GraphQL!
Hello, GraphQL!Hello, GraphQL!
Hello, GraphQL!민환 조
 
Ksug 세미나 (윤성준) (20121208)
Ksug 세미나 (윤성준) (20121208)Ksug 세미나 (윤성준) (20121208)
Ksug 세미나 (윤성준) (20121208)Sungjoon Yoon
 
overview of spring4
overview of spring4overview of spring4
overview of spring4Arawn Park
 
GraphQL overview #2
GraphQL overview #2GraphQL overview #2
GraphQL overview #2기동 이
 
Node.js + Express + MongoDB
Node.js + Express + MongoDBNode.js + Express + MongoDB
Node.js + Express + MongoDBVincent Park
 
Realm은 어떻게 효율적인 데이터베이스를 만들었나?
Realm은 어떻게 효율적인 데이터베이스를 만들었나?Realm은 어떻게 효율적인 데이터베이스를 만들었나?
Realm은 어떻게 효율적인 데이터베이스를 만들었나?Leonardo YongUk Kim
 
Partner Story(Megazone): 금융사 실전 프로젝트 DeepDive
Partner Story(Megazone): 금융사 실전 프로젝트 DeepDive Partner Story(Megazone): 금융사 실전 프로젝트 DeepDive
Partner Story(Megazone): 금융사 실전 프로젝트 DeepDive Elasticsearch
 
[Td 2015]java script에게 형(type)이 생겼어요. typescript(박용준)
[Td 2015]java script에게 형(type)이 생겼어요. typescript(박용준)[Td 2015]java script에게 형(type)이 생겼어요. typescript(박용준)
[Td 2015]java script에게 형(type)이 생겼어요. typescript(박용준)Sang Don Kim
 
KTH_Detail day_화성에서 온 개발자 금성에서 온 기획자 시리즈_5차_데이터분석_조범석_20120613
KTH_Detail day_화성에서 온 개발자 금성에서 온 기획자 시리즈_5차_데이터분석_조범석_20120613KTH_Detail day_화성에서 온 개발자 금성에서 온 기획자 시리즈_5차_데이터분석_조범석_20120613
KTH_Detail day_화성에서 온 개발자 금성에서 온 기획자 시리즈_5차_데이터분석_조범석_20120613KTH, 케이티하이텔
 
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GDG Korea
 
씹고 뜯고 맛보고 즐기는 스트림 API
씹고 뜯고 맛보고 즐기는 스트림 API씹고 뜯고 맛보고 즐기는 스트림 API
씹고 뜯고 맛보고 즐기는 스트림 APIArawn Park
 
GraphQL overview
GraphQL overviewGraphQL overview
GraphQL overview기동 이
 
Ksug2015 - JPA1, JPA 소개
Ksug2015 - JPA1, JPA 소개Ksug2015 - JPA1, JPA 소개
Ksug2015 - JPA1, JPA 소개Younghan Kim
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjsNodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjs기동 이
 
//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작
//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작
//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작Taeyoung Kim
 
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로Jaeseung Ha
 
Booting Spring Data REST
Booting Spring Data RESTBooting Spring Data REST
Booting Spring Data REST경원 이
 

Similar to GraphQL 적용기 (20)

Hello, GraphQL!
Hello, GraphQL!Hello, GraphQL!
Hello, GraphQL!
 
Ksug 세미나 (윤성준) (20121208)
Ksug 세미나 (윤성준) (20121208)Ksug 세미나 (윤성준) (20121208)
Ksug 세미나 (윤성준) (20121208)
 
overview of spring4
overview of spring4overview of spring4
overview of spring4
 
GraphQL overview #2
GraphQL overview #2GraphQL overview #2
GraphQL overview #2
 
Node.js + Express + MongoDB
Node.js + Express + MongoDBNode.js + Express + MongoDB
Node.js + Express + MongoDB
 
Realm은 어떻게 효율적인 데이터베이스를 만들었나?
Realm은 어떻게 효율적인 데이터베이스를 만들었나?Realm은 어떻게 효율적인 데이터베이스를 만들었나?
Realm은 어떻게 효율적인 데이터베이스를 만들었나?
 
Partner Story(Megazone): 금융사 실전 프로젝트 DeepDive
Partner Story(Megazone): 금융사 실전 프로젝트 DeepDive Partner Story(Megazone): 금융사 실전 프로젝트 DeepDive
Partner Story(Megazone): 금융사 실전 프로젝트 DeepDive
 
[Td 2015]java script에게 형(type)이 생겼어요. typescript(박용준)
[Td 2015]java script에게 형(type)이 생겼어요. typescript(박용준)[Td 2015]java script에게 형(type)이 생겼어요. typescript(박용준)
[Td 2015]java script에게 형(type)이 생겼어요. typescript(박용준)
 
Scala for play
Scala for playScala for play
Scala for play
 
KTH_Detail day_화성에서 온 개발자 금성에서 온 기획자 시리즈_5차_데이터분석_조범석_20120613
KTH_Detail day_화성에서 온 개발자 금성에서 온 기획자 시리즈_5차_데이터분석_조범석_20120613KTH_Detail day_화성에서 온 개발자 금성에서 온 기획자 시리즈_5차_데이터분석_조범석_20120613
KTH_Detail day_화성에서 온 개발자 금성에서 온 기획자 시리즈_5차_데이터분석_조범석_20120613
 
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
 
Mongo db 최범균
Mongo db 최범균Mongo db 최범균
Mongo db 최범균
 
강의자료3
강의자료3강의자료3
강의자료3
 
씹고 뜯고 맛보고 즐기는 스트림 API
씹고 뜯고 맛보고 즐기는 스트림 API씹고 뜯고 맛보고 즐기는 스트림 API
씹고 뜯고 맛보고 즐기는 스트림 API
 
GraphQL overview
GraphQL overviewGraphQL overview
GraphQL overview
 
Ksug2015 - JPA1, JPA 소개
Ksug2015 - JPA1, JPA 소개Ksug2015 - JPA1, JPA 소개
Ksug2015 - JPA1, JPA 소개
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjsNodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjs
 
//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작
//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작
//BUILD/ Seoul - .NET의 현재와 미래. 그 새로운 시작
 
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
 
Booting Spring Data REST
Booting Spring Data RESTBooting Spring Data REST
Booting Spring Data REST
 

More from Changwan Jun

Serverless 프레임워크로 Nuxt 앱 배포하기
Serverless 프레임워크로 Nuxt 앱 배포하기Serverless 프레임워크로 Nuxt 앱 배포하기
Serverless 프레임워크로 Nuxt 앱 배포하기Changwan Jun
 
Infrastructure as Code 삽질기
Infrastructure as Code 삽질기Infrastructure as Code 삽질기
Infrastructure as Code 삽질기Changwan Jun
 
Vue SSR vs Prerender
Vue SSR vs PrerenderVue SSR vs Prerender
Vue SSR vs PrerenderChangwan Jun
 
PHP로 Slack Bot 만들기
PHP로 Slack Bot 만들기PHP로 Slack Bot 만들기
PHP로 Slack Bot 만들기Changwan Jun
 
PHP에서 GCM 푸시 빠르게 보내기 (feat. Async / Generator)
PHP에서 GCM 푸시 빠르게 보내기 (feat. Async / Generator)PHP에서 GCM 푸시 빠르게 보내기 (feat. Async / Generator)
PHP에서 GCM 푸시 빠르게 보내기 (feat. Async / Generator)Changwan Jun
 

More from Changwan Jun (6)

Serverless 프레임워크로 Nuxt 앱 배포하기
Serverless 프레임워크로 Nuxt 앱 배포하기Serverless 프레임워크로 Nuxt 앱 배포하기
Serverless 프레임워크로 Nuxt 앱 배포하기
 
Infrastructure as Code 삽질기
Infrastructure as Code 삽질기Infrastructure as Code 삽질기
Infrastructure as Code 삽질기
 
Vue SSR vs Prerender
Vue SSR vs PrerenderVue SSR vs Prerender
Vue SSR vs Prerender
 
PHP로 Slack Bot 만들기
PHP로 Slack Bot 만들기PHP로 Slack Bot 만들기
PHP로 Slack Bot 만들기
 
Modern PHP
Modern PHPModern PHP
Modern PHP
 
PHP에서 GCM 푸시 빠르게 보내기 (feat. Async / Generator)
PHP에서 GCM 푸시 빠르게 보내기 (feat. Async / Generator)PHP에서 GCM 푸시 빠르게 보내기 (feat. Async / Generator)
PHP에서 GCM 푸시 빠르게 보내기 (feat. Async / Generator)
 

GraphQL 적용기

  • 3. RESTFul API Method Path Body 동작 GET /users 회원 목록 읽기 GET /users/:id 회원 정보 읽기 POST /users {"email": "hi@wani.kr", .. } 회원 정보 저장 PUT/PATCH /users/:id {"email": "hi@wani.kr", .. } 회원 정보 수정 DELETE /users/:id 회원 정보 삭제
  • 4. RESTFul API 대부분의 프레임워크가 지원, 누구나 쉽게 도입 가능 RESTFul에서 모든 모델은 CRUD로 표현 OAS(Open Api Specification) 표준 존재
  • 5. RESTFul API 예시 - Github API Method Path 동작 GET /user 회원 정보 읽기 GET /user/repos 사용자의 저장소 조회 POST /user/repos 저장소 만들기 DELETE /repos/:owner/:repo 저장소 삭제하기 POST /repos/:owner/:repo/transfer 저장소 이동하기 developer.github.com/v3
  • 7.
  • 9. RESTFul API 데이터 유효성 검사 JSON Schema, JOI, Safen ... const validator = sfl`{ username: (string & email & length_between(12, 100)) | null, password?: string & length_between(8, 20), areas: { lat: number & between(-90, 90), lng: number & between(-180, 180), }[1:] | null, env: { referer: url, ip: ip("v4"), os: { name: in("window", "osx", "android", "iphone"), version: string, }, }, }` validator.assert({ username: "wan2land@gmail.com", areas: [ {lat: 0, lng: 0}, ], env: { referer: "http://wan2land.github.io", ip: "127.0.0.1", os: { name: "osx", version: "10.13.1", }, }, }) // ok
  • 10. RESTFul API 테스트 + 문서화 도구 Postman
  • 13. “GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data.” graphql.org
  • 15. 주요 라이브러리 서버 Apollo, GraphQL Yoga, Type GraphQL, Graphity 웹 클라이언트 apollo-client (react, vue, svelte!) 앱 클라이언트 apollo-ios, apollo-android (flutter는 공식라이브러리가 없는 듯..)
  • 16. GraphQL 구조 Schema 데이터 구조를 정의, 서버에서 구현 Query 데이터를 읽고 쓰는 명령어, 주로 클라이언트에서 구현
  • 17. type Query { user(id: ID!): User userPagination(take: Int, offset: Int): ListOfUser } type Mutation { createUser(input: InputCreateUser!): User updateUser(id: ID!, input: InputUpdateUser!): User deleteUser(id: ID!): User } type ListOfUser { count: Int nodes: [User!]! } Schema type User { id: ID! email: String! friends: [User!]! } input InputCreateUser { email: String! } input InputUpdateUser { email: String! }
  • 18. type Query { user(id: ID!): User userPagination(take: Int, offset: Int): ListOfUser } type Mutation { createUser(input: InputCreateUser!): User updateUser(id: ID!, input: InputUpdateUser!): User deleteUser(id: ID!): User } type ListOfUser { count: Int nodes: [User!]! } Schema Name Arguments (생략가능) Return Name Return type User { id: ID! email: String! friends: [User!]! } input InputCreateUser { email: String! } input InputUpdateUser { email: String! }
  • 19. type Query { user(id: ID!): User userPagination(take: Int, offset: Int): ListOfUser } type Mutation { createUser(input: InputCreateUser!): User updateUser(id: ID!, input: InputUpdateUser!): User deleteUser(id: ID!): User } type ListOfUser { count: Int nodes: [User!]! } Schema Entry Point type User { id: ID! email: String! friends: [User!]! } input InputCreateUser { email: String! } input InputUpdateUser { email: String! }
  • 20. GraphQL Types Scalars ID, String, Int, Float, Boolean 그외(?) Object Type, Input Type, Enum, List, Non-Null
  • 21. type Query { user(id: ID!): User userPagination(take: Int, offset: Int): ListOfUser } type Mutation { createUser(input: InputCreateUser!): User updateUser(id: ID!, input: InputUpdateUser!): User deleteUser(id: ID!): User } type ListOfUser { count: Int nodes: [User!]! } Schema type User { id: ID! email: String! friends: [User!]! } input InputCreateUser { email: String! } input InputUpdateUser { email: String! } NonNull(List(NonNull(ObjectType))) Object Type Input Type
  • 22. type Query { user(id: ID!): User userPagination(take: Int, offset: Int): ListOfUser } type Mutation { createUser(input: InputCreateUser!): User updateUser(id: ID!, input: InputUpdateUser!): User deleteUser(id: ID!): User } type ListOfUser { count: Int nodes: [User!]! } Schema type User { id: ID! email: String! friends: [User!]! } input InputCreateUser { email: String! } input InputUpdateUser { email: String! } Arguments에는 Input Type + Scalar Object Type Return에는 Object Type + Scalar
  • 23. Query query GetUser($id: ID!) { user(id: $id) { id email friends { id email } } } mutation CreateUser($input: InputCreateUser!) { user: createUser(input: $input) { id email } }
  • 24. query GetUser($id: ID!) { user(id: $id) { id email friends { id email } } } Query mutation CreateUser($input: InputCreateUser!) { user: createUser(input: $input) { id email } } Name (생략가능) Arguments Fields
  • 25. query GetUser($id: ID!) { user(id: $id) { id email } } Query { "data": { "user": { "id": "30", "email": "wan2land@gmail.com" } } }
  • 26. query GetUser($id: ID!) { user(id: $id) { id email friends { id email } } } Query { "data": { "user": { "id": "30", "email": "wan2land@gmail.com", "friends": [ { "id": "31", "email": "wan3land@gmail.com" }, { "id": "32", "email": "wan4land@gmail.com" } ] } } }
  • 27. GraphQL Custom Scalars input InputCreateUser { email: String! name: String }
  • 28. GraphQL Custom Scalars input InputCreateUser { email: String! name: String } "hi@wani.kr" O "wan2land" O (!?)
  • 29. GraphQL Custom Scalars scalar Email input InputCreateUser { email: Email! name: String } "hi@wani.kr" O "wan2land" X
  • 30. github.com/Urigo/graphql-scalars GraphQL Custom Scalars scalar DateTime scalar EmailAddress scalar NegativeFloat scalar NegativeInt scalar NonNegativeFloat scalar NonNegativeInt scalar NonPositiveFloat scalar NonPositiveInt scalar PhoneNumber scalar PositiveFloat scalar PositiveInt scalar PostalCode scalar UnsignedFloat scalar UnsignedInt scalar URL scalar BigInt scalar Long scalar GUID scalar HexColorCode scalar HSL scalar HSLA scalar IPv4 scalar IPv6 scalar ISBN scalar MAC scalar Port
  • 31. GraphQL Description type Query { user(id: ID!): User """ ex. userPagination(take: 20, offset: 0) - 1 userPagination(take: 20, offset: 20) - 2 userPagination(take: 20, offset: 40) - 3 """ userPagination(take: Int, offset: Int): ListOfUser something(id: ID!): User @deprecated(reason: "use 'user' query") }
  • 32. GraphQL Description type Query { user(id: ID!): User """ ex. userPagination(take: 20, offset: 0) - 1 userPagination(take: 20, offset: 20) - 2 userPagination(take: 20, offset: 40) - 3 """ userPagination(take: Int, offset: Int): ListOfUser something(id: ID!): User @deprecated(reason: "use 'user' query") }
  • 34. Swagger + JSON Schema + Postman
  • 35. iOS와 Android에서도 쉽게 사용할 수 있어요! 여긴 GDG니까 앱 개발자가 많을거야! 😤😤😤
  • 36. (지인 앱개발자 ⽈) RESTFul API인 경우, JSON객체를 가져와서 Kotlin/Swift 클래스에 일일이 대입하는 노가다 필요 GraphQL + Application
  • 37. GraphQL + Application Apollo iOS / Apollo Android
  • 38. 1. GraphQL Schema 불러오기 2. GraphQL 쿼리 작성 3. codegen 4. 클래스가 자동생성! GraphQL + Application
  • 39.
  • 41. GraphQL - N + 1 SELECT * FROM `users` SELECT * FROM `users` WHERE `friend_id` = ? SELECT * FROM `users` WHERE `friend_id` = ? SELECT * FROM `users` WHERE `friend_id` = ? SELECT * FROM `users` WHERE `friend_id` = ? SELECT * FROM `users` WHERE `friend_id` = ? ... query GetUser($id: ID!) { userPagination { id friends { id } } } 목록조회 1번 + 친구조회 20번 = 21번
  • 42. GraphQL - N + 1 SELECT * FROM `users` SELECT * FROM `users` WHERE `friend_id` = ? SELECT * FROM `users` WHERE `friend_id` = ? SELECT * FROM `users` WHERE `friend_id` = ? ... SELECT * FROM `users` WHERE `friend_id` = ? SELECT * FROM `users` WHERE `friend_id` = ? SELECT * FROM `users` WHERE `friend_id` = ? ... SELECT * FROM `users` WHERE `friend_id` = ? SELECT * FROM `users` WHERE `friend_id` = ? SELECT * FROM `users` WHERE `friend_id` = ? ... query GetUser($id: ID!) { userPagination { id friends { id friends { id } } } } 1 + 20 + 20 x 20 = 421번
  • 43. GraphQL - N + 1 query GetUser($id: ID!) { userPagination { id friends { id friends { id friends { id } } } } } ????!
  • 44. GraphQL - N + 1 SELECT * FROM `users` SELECT * FROM `users` WHERE `friend_id` IN (?, .. ) SELECT * FROM `users` WHERE `friend_id` IN (?, .. ) SELECT * FROM `users` WHERE `friend_id` IN (?, .. ) query GetUser($id: ID!) { userPagination { id friends { id friends { id friends { id } } } } }
  • 46. GraphQL - File Upload scalar Upload type Mutation { uploadAttachment(file: Upload): Attachment } multipart/form-data 사용
  • 49. GraphQL - Subscription type Query { user(id: ID!): User userPagination(take: Int, offset: Int): ListOfUser } type Mutation { createUser(input: InputCreateUser!): User updateUser(id: ID!, input: InputUpdateUser!): User deleteUser(id: ID!): User } type Subscription { onUserCreated: User onUserUpdated(id: ID!): User onDeleteUser(id: ID!): User } Event 발생시, 구독가능
  • 50. GraphQL - Image Response corgi.photos/300/200 Response는 application/json 로 고정, 위와 같은 image/png는 처리할 수 없음. (비슷한 예로 엑셀 다운로드)
  • 51. query { user(id: 566) { profile { id resize(width: 100, height: 100) } } } { "data": { "user": { "profile": { "id": "1324", "resize": "https:// something.s3.ap- northeast-2.amazonaws.com/ 6c326d50- c1b8-45d8-80c7-7cd9d472b84f- w100-h100.jpg" } } } } GraphQL - Image Response
  • 52. 요약 GraphQL은 RESTFul API의 대체제로 충분하다. GraphQL Custom Scalar를 활용하면 추가적인 데이터 유효성검사 라이브러리가 필요없다. Apollo iOS / Android를 사용하면 앱에서 GraphQL을 훨씬 쉽게 사용할 수 있다. 1+N 문제는 생각보다 쉽게 해결가능하다. GraphQL에서 파일업로드가 가능하다. Subscription 활용을 활용하면 채팅 같은 서비스를 만들 수 있다. 이미지 Response는 URL로 사용하자.