ํ์คํ ์น๐ ๊ฐ๋ฐ์ ์ง๋ง์ ๐ง๐ฝโ๐ป
โ ์ธ๊ณต์ง๋ฅ ๊ด์ฌ ๐ค
Categories
-
โฃ
โถ COMPUTER_SCIENCE
๐: 7 -
โฃ
โถ WEB
๐: 3 -
โฃ
โถ ETC
๐: 3-
โ
โฃ
ETCS
๐: 10 -
โ
โฃ
SUBBRAIN ๊ฐ๋ฐ๊ธฐ
๐: 5 -
โ
โ
YOS ๊ฐ๋ฐ๊ธฐ
๐: 1
-
โ
โฃ
-
โ
โถ AI
๐: 9-
โฃ
AITOOLS
๐: 3 -
โฃ
CV
๐: 2 -
โฃ
DEEP_LEARNING
๐: 1 -
โฃ
DATA_VIS
๐: 2 -
โฃ
GRAPH
๐: 1 -
โฃ
LIGHTWEIGHT
๐: 1 -
โฃ
MATH
๐: 1 -
โฃ
NLP
๐: 3 -
โ
STRUCTURED_DATA
๐: 2
-
โฃ
GraphQL with flask
https://dev.to/mesadhan/python-flask-graphql-with-graphene-nla (Md. Sadhan Sarker)์ ๊ธ์ ๋ฒ์ญ, ์ ๋ฆฌํ ๊ธ์ ๋๋ค.
GraphQL with flask
GraphQL์ API๋ฅผ ์ํ query language์ด๋ค. REST API์ ๋นํด ์ฌ๋ฌ ์ฅ์ ์ด ์์ผ๋ฉฐ ํนํ data fetching ๋ถ๋ถ์ด ํจ์จ์ ์ด๋ค. ๊ท๋ชจ๊ฐ ํฐ API์ผ์๋ก ๋์ฑ ํจ๊ณผ์ ์ด๊ณ ๊ฐ๋ ฅํ๋ฉฐ, facebook์์ open source๋ก ๋ฐฐํฌํ์ฌ ์ปค๋ค๋ ์ปค๋ฎค๋ํฐ๋ฅผ ์ด๋ฃจ์๋ค.
์์ฆ์ ์ ์ธํ ํ๋ก๊ทธ๋๋ฐ์ด ์ ์ ์ธ๊ธฐ๋ฅผ ์ป๊ณ ์๋๋ฐ, GraphQL ๋ํ, ์ฌ๋ฌ API ํธ์ถ์ ๋ถ๋ฌ์์ผํ๋ REST API์๋ ๋ฌ๋ฆฌ ์ ์ธํ ๋ฐ์ดํฐ fetching์ด์ฉํ๋ค. GraphQL ์๋ฒ๋ ์ค์ง ํ๋์ endpoint(root URL ๋ค์ ๋ถ๋ ์ถ๊ฐ ์ฃผ์)์ ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญํ ์ฌ๋ฌ response๋ก ์ด๋ฃจ์ด์ก๋ค. ์์ผ๋ก ์์๋ฅผ ์ดํด๋ณผ ๊ฒ์ด๋ค.
GraphQL vs REST
- GraphQL์ ์ฟผ๋ฆฌ๋ก ์ฐ๋ฆฌ๊ฐ ํ์ํ ๋ฐ์ดํฐ๋ง ๋ช ์ํ๊ฒ ํด์ฃผ๋ฉฐ, ํ๋ฒ์ ์์ฒญ์ผ๋ก ์ ํํ ๊ทธ ๋ฐ์ดํฐ๋ง ์๋ต์ ํฌํจ์์ผ์ค ๊ฒ์ด๋ค. ์ด์ ๋ฐํด REST API๋ ์ฌ๋ฌ ์๋ต๊ณผ ํธ์ถ์ ์๊ตฌํ๋ค.
GraphQL๊ณผ REST์ ์ฐจ์ด ์์
-
API์์ data๋ฅผ ๊ฐ์ ธ์ฌ ๋, ํฐ ์ฐจ์ด๋ฅผ ๋ณด์ฌ์ฃผ๋๋ฐ. ๋ธ๋ก๊ทธ์์ ์ด๋ค ์ ์ ์ ์์ฑ๊ธ๋ค์ ์ ๋ชฉ์ด ํ์ํ ๊ฒฝ์ฐ, ๋ํ ๊ฐ์ ํ์ด์ง์์ ๊ทธ ์ ์ ์ ์ต์ ํ๋ก์๋ค 3๋ช ์ ์ด๋ฆ์ ๊ฐ์ ธ์ค๋ ค ํ ๋, GraphQL๊ณผ REST API๋ ์ด๋ค ์ฐจ์ด๋ฅผ ๋ณด์ผ๊น?
REST API์ ๊ฒฝ์ฐ
-
REST API์์๋ ์ฌ๋ฌ endpoint์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์จ๋ค.
- ์๋ฅผ ๋ค์ด, /user/<id> endpoint์์ ๋จผ์ ์ ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋
- ๊ทธ ํ, /user/<id>/posts endpoint์์ ํด๋น ์ ์ ์ ๋ชจ๋ ๊ฒ์๊ธ๋ค์ ๊ฐ์ ธ์จ๋ค
- ๋ง์ง๋ง์ผ๋ก, /user/<id>/followers์์ ํด๋น ์ ์ ์ ๋ชจ๋ ํ๋ก์๋ค์ ๊ฐ์ ธ์จ๋ค
-
โ - ๊ทธ๋ฆผ ์ถ์ฒ : source :howtographql.com
- REST API๋ฅผ ์ฌ์ฉํ๋ฉด 3๋ฒ์ ๊ฐ์ ๋ค๋ฅธ ์ฃผ์๋ก 3๋ฒ์ ์์ฒญ์ ๋ณด๋ด์ผ ํ๋ฉฐ, ์ธ๋ฐ์๋ ์ถ๊ฐ ๋ฐ์ดํฐ๋ค์ ์ถ๊ฐ๋ก ๊ฐ์ ธ์จ๋ค๋ ๊ฒ์ ์ ์ ์๋ค.
-
-
์๋๋ฉด /users/posts/follwers/<id> ๋ผ๋ ์๋ก์ด endpoint๋ฅผ ๋ง๋ค๊ณ , ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๋ฐ์ดํฐ๋ง ๊ฐ์ ธ์ค๊ฒ ๋ง๋ค์ด๋ ๋๋ค. ํ์ง๋ง ๊ทธ๋ ๊ฒํ๋ฉด ๋์งํ ์์ฐ์ฑ๊ณผ ์ฌ์ฌ์ฉ์ฑ์ ๊ฐ์ ธ์ฌ ๊ฒ์ด๋ค. ์ถ๊ฐ๋ก ๋ ์ง์ ๋ฐ๋ผ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ค๋ฉด /users/posts/follwers/<id>/<date>๋ผ๋ endpoint๋ฅผ ๋ง๋ค์ด์ผํ๋ค.
GraphQL์ ๊ฒฝ์ฐ
- GraphQL์ ๋จ ํ๋์ query๋ฅผ ์๋ฒ์ ๋ณด๋ธ๋ค. ์๋ฒ๋ JSON ํ์์ respond๋ฅผ ๋๋ ค์ค๋ค.
- ๊ทธ๋ฆผ ์ถ์ฒ : source :howtographql.com
- GraphQL์์๋ ํด๋ผ์ด์ธํธ ์๋ฒ๊ฐ ํ์ํ ๋ฐ์ดํฐ๋ง ์ฟผ๋ฆฌ์ ํฌํจํ ์ ์๋ค. ๋ฐฑ์๋ ์๋ฒ์ ์๋ต ๋ํ ์ ํํ ์ฟผ๋ฆฌ์ ์ ์ํ ๊ตฌ์กฐ๋ฅผ ๋ฐ๋ฅธ๋ค
๋ฉ์ง์ง ์๋๊ฐ? ์ด๋ก ์ ์ถฉ๋ถํ๋ ์ด์ Python Graphne์ ์ด์ฉํด์ GraphQL ์๋ฒ๋ฅผ ๋ง๋ค์ด๋ณด์.
Python Graphene์ ์ด์ฉํ GraphQL ์๋ฒ ๊ตฌํ
- Graphene์ python์ผ๋ GraphQL ํด๋ผ์ด์ธํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค. ์ด๋ฅผ ์ด์ฉํด ์ฐ๋ฆฌ๋ง์ GraphQL ์๋ฒ๋ฅผ ๋ง๋ค ์ ์๋ค.
Setting up your poject - ๋จผ์ ํ๋ก์ ํธ ๊ฒฝ๋ก์ ํด๋๋ฅผ ์์ฑํ๋ค.
```bash
$ mkdir graphql-flask
$ cd graphql-flask
- ๊ฐ์ํ๊ฒฝ์ค์ ์ ํตํด global package๋ค๊ณผ์ ์ถฉ๋์ ํผํ๊ณ , ๊ฐ ํ๋ก์ ํธ ๋ณ๋ก ํจํค์ง ๋ฒ์ ๊ด๋ฆฌ๋ฅผ ์ฝ๊ฒ ํ ์ ์๋ค.
```bash
$ pip install virtualenv
$ virtualenv venv
$ source venv/bin/activate
์ฐธ๊ณ ๋ก
$ deactivate
๋ก ๊ฐ์ ํ๊ฒฝ์์ ๋๊ฐ ์ ์๋ค.
- ํ์ํ depndency๋ฅผ ๋ง์ถ๊ธฐ ์ํด ์๋์ ๊ฐ์ด ํฐ๋ฏธ๋์ ์ ๋ ฅํ๋ผ
$ pip install flask flask-graphql flask-migrate flask-sqlalchemy graphene graphene-sqlalchemy
- ์ดํ ์ฐ๋ฆฌ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์คํํด์ผ ํ๋ค. ์๋ seed.py๋ฅผ ๋ง๋ค์ด ๋ณด์.
from app import db, User, Post
db.create_all() # create tables from models
user1 = User(
name="Sadhan Sarker",
email='cse.sadhan@gmail.com'
)
post1 = Post()
post1.title = "Blog Post Title 1"
post1.body = "This is the first blog post 1"
post1.author = user1
db.session.add(post1)
db.session.add(user1)
db.session.commit()
print(User.query.all())
print(Post.query.all())
- ์ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๋ ค๋ฉด ์๋์ ๊ฐ์ด ์
๋ ฅํ๋ผ
```bash
python seed.py
- ์ข๋ค! ๊ฑฐ์ ๋ค๋ฌ๋ค! ๋ง์ง๋ง์ผ๋ก app.py ์คํฌ๋ฆฝํธ๋ฅผ ๋ง๋ค๊ณ ํ๋ก์ ํธ์ ์ถ๊ฐํ์
```python
import os
import graphene
from flask import Flask
from flask_graphql import GraphQLView
from flask_sqlalchemy import SQLAlchemy
from graphene_sqlalchemy import SQLAlchemyObjectType, SQLAlchemyConnectionField
app = Flask(__name__)
basedir = os.path.abspath(os.path.dirname(__file__))
# Database Configs [Check it base on other Database Configuration]
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'database.sqlite')
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
# Initialize Database
db = SQLAlchemy(app)
# ------------------ Database Models ------------------
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(256))
email = db.Column(db.String(256), index=True, unique=True) # index =&#62; should not be duplicate
posts = db.relationship('Post', backref='author')
def __repr__(self):
return '&#60;User %r&#62;' % self.email
class Post(db.Model):
__tablename__ = 'posts'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(256))
body = db.Column(db.Text)
author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
def __repr__(self):
return '&#60;Post %r&#62;' % self.title
# ------------------ Graphql Schemas ------------------
# Objects Schema
class PostObject(SQLAlchemyObjectType):
class Meta:
model = Post
interfaces = (graphene.relay.Node,)
class UserObject(SQLAlchemyObjectType):
class Meta:
model = User
interfaces = (graphene.relay.Node,)
class Query(graphene.ObjectType):
node = graphene.relay.Node.Field()
all_posts = SQLAlchemyConnectionField(PostObject)
all_users = SQLAlchemyConnectionField(UserObject)
# noinspection PyTypeChecker
schema_query = graphene.Schema(query=Query)
# Mutation Objects Schema
class CreatePost(graphene.Mutation):
class Arguments:
title = graphene.String(required=True)
body = graphene.String(required=True)
email = graphene.String(required=True)
post = graphene.Field(lambda: PostObject)
def mutate(self, info, title, body, email):
user = User.query.filter_by(email=email).first()
post = Post(title=title, body=body)
if user is not None:
post.author = user
db.session.add(post)
db.session.commit()
return CreatePost(post=post)
class Mutation(graphene.ObjectType):
save_post = CreatePost.Field()
# noinspection PyTypeChecker
schema_mutation = graphene.Schema(query=Query, mutation=Mutation)
# Flask Rest & Graphql Routes
@app.route('/')
def hello_world():
return 'Hello From Graphql Tutorial!'
# /graphql-query
app.add_url_rule('/graphql-query', view_func=GraphQLView.as_view(
'graphql-query',
schema=schema_query, graphiql=True
))
# /graphql-mutation
app.add_url_rule('/graphql-mutation', view_func=GraphQLView.as_view(
'graphql-mutation',
schema=schema_mutation, graphiql=True
))
if __name__ == '__main__':
app.run()
- ์ด์ ์ฐ๋ฆฌ๋ graphene์ผ๋ก graphql์ ๋ง๋ค์๋ค. ์คํํด๋ณด์.
```bash
$ python app.py
## GraphQL API ํ
์คํธ
- PostMan์ด๋ cRUL์ ์ด์ฉํด ์๋ฒ์ ํต์ ํด๋ณด์.
- GraphQL์ ์์น์ ์ผ๋ก POST์ GET ์์ฒญ๋ง ๋ฐ๋๋ค.
```postman
## 1. Rest API examples
GET http://127.0.0.1:5000/
### Graphql query-api example
POST http://127.0.0.1:5000/graphql-query
Content-Type: application/graphql
{
allPosts{
edges{
node{
title
author{
email
}
}
}
}
}
### 2. Graphql mutation-api example
POST http://127.0.0.1:5000/graphql-mutation
Content-Type: application/graphql
mutation {
savePost(email:"cse.sadhan@gmail.com", title:"Title 2", body:"Blog post 2") {
post{
title
body
author{
email
}
}
}
}
###
_articles/web/backend/GraphQL with flask.md