[GraphQL] GraphQL로 API 구현 예제 with python - 조회
BackEnd

[GraphQL] GraphQL로 API 구현 예제 with python - 조회

728x90

GraphQL 라이브러리

GraphQL 자체는 쿼리 언어이기 떄문에 구체화할 수있는 언어와 라이브러리가 필요

GraphQL의 라이브러리는 아래 링크를 참고하면 된다.

https://graphql.org/code/

 

GraphQL Code Libraries, Tools and Services

Typetta is an open-source ORM written in TypeScript that aims to allow seamless access to data in a typed fashion to all main SQL databases (MySQL, PostgreSQL, Microsoft SQL Server, SQLLite3, CockroachDB, MariaDB, Oracle & Amazon Redshift) and also to the

graphql.org

GraphQL 개발 언어로 JavaScript를 많이 사용하지만 이 글은 python을 사용해서 개발했습니다.

Python라이브러리로 "Ariadne"사용

GraphQL 예시 - 조회기능

  • REST API로 구현된 모델 조회기능(model, model_vsn)을 GraphQL로 구현한다.
  • DB가 준비되어있어야 한다
    • 이 글은 Postgresql의 Alertsys 로컬 DB사용

출처 - https://velog.io/@jeon_131/GraphQL%EA%B3%BC-REST

Flask 기본 설정 및 설치

  • GET > /model/model_id
  • GET > /model/model_id/version

1. 설치

pip install flask ariadne flask-sqlalchemy flask-cors

2. Flask app 생성 및 디렉토리 설계

아래 그림처럼 디렉토리 구조를 만들었습니다.

▷ api/init.py

from flask import Flask
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy
import psycopg2

app = Flask(__name__)
CORS(app)

app.config["SQLALCHEMY_DATABASE_URI"] = "postgresql+psycopg2://[DB_NAME]:[DB_USER]@[호스트주소]:[포트번호]/[DB_PASS]"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)

DB연결과 데이터가져오는 방법으로 SQLAlchemy라이브러리를 사용했다.

본인의 DB정보에 맞게 연결하기

▷ app.py

from api import app, db
from ariadne import load_schema_from_path, make_executable_schema, \
    graphql_sync, snake_case_fallback_resolvers, ObjectType
from ariadne.constants import PLAYGROUND_HTML
from flask import request, jsonify

@app.route("/graphql", methods=["GET"])
def graphql_playground():
    return PLAYGROUND_HTML, 200
flask run

Flask run코드로 앱 실행

 

http://127.0.0.1:5000/graphql

 

위 주소로 입력했을때 아래 그림처럼 나오면 Flask 정상 작동

위 GET요청의 Return페이지(PLAYGROUND_HTML)는 Ariadne 라이브러리에서 제공하는 쿼리실행 페이지

해당 페이지에서 쿼리를 통해 데이터를 확인할 수 있다.

Model 조회 코드 작성

1. GraphQL 스키마 코드 작성

▷ schema.graphql

schema {
    query: Query
}

type Model {
    model_id: String!
    model_nm: String!
    model_type: String
    model_cmmt: String
    rgst_dt: String
    rgst_time: String
    rgstr_nm: String
    del_yn: Boolean
}

type ModelResult {
    success: Boolean!
    errors: [String]
    model: Model
}

type Query {
    getModel(model_id: String!): ModelResult!
}

2. 모델 만들기

▷ api/models.py

from app import db

class Model(db.Model):
    model_id = db.Column(db.Integer, primary_key=True)
    model_nm = db.Column(db.String)
    model_type = db.Column(db.String)
    model_cmmt = db.Column(db.String)
    rgst_dt = db.Column(db.String)
    rgst_time = db.Column(db.String)
    rgstr_nm = db.Column(db.String)
    del_yn = db.Column(db.Boolean)

    def to_dict(self):
        return {
            "model_id": self.model_id,
            "model_nm": self.model_nm,
            "model_type": self.model_type,
            "model_cmmt": self.model_cmmt,
            "rgst_dt": str(self.rgst_dt),
            "rgst_time": str(self.rgst_time),
            "rgstr_nm": self.rgstr_nm,
            "del_yn": self.del_yn,
        }

DB에 있는 Model테이블 정보를 가져오는 코드 작성

3. Resolver 구현

▷ api/queries.py

from .models import Model

def getModel_resolver(obj, info, model_id):
    try:
        model = Model.query.get(model_id)
        payload = {
            "success": True,
            "model": model.to_dict(),
        }
    except AttributeError:  # todo not found
        payload = {
            "success": False,
            "errors": ["Post item matching {model_id} not found"]
        }
    return payload

getmodel 리졸버는 "model_id"값을 입력하면 해당 id값 데이터를 조회하는 기능

4. POST 요청 API코드

▷ app.py

from api import app, db
from ariadne import load_schema_from_path, make_executable_schema, \
    graphql_sync, snake_case_fallback_resolvers, ObjectType
from ariadne.constants import PLAYGROUND_HTML
from flask import request, jsonify
from api.queries import getModel_resolver

query = ObjectType("Query")
query.set_field("getModel", getModel_resolver)

type_defs = load_schema_from_path("schema.graphql")
schema = make_executable_schema(
    type_defs, query, snake_case_fallback_resolvers
)

@app.route("/graphql", methods=["GET"])
def graphql_playground():
    return PLAYGROUND_HTML, 200

@app.route("/graphql", methods=["POST"])
def graphql_server():
    data = request.get_json()
    success, result = graphql_sync(
        schema,
        data,
        context_value=request,
        debug=app.debug
    )
    status_code = 200 if success else 400
    return jsonify(result), status_code

기존 app.py코드에 위 코드로 변경

  • 실행
flask run
  • 확인

http://127.0.0.1:5000/graphql 로 접속해서 아래 쿼리로 정보 조회

query GetModel {
  getModel(model_id: "test1") {
    model {
      model_id
      model_nm
      model_type
      model_cmmt
      rgst_dt
      rgst_time
      rgstr_nm
      del_yn
    }
    success
    errors
  }
}

아래 이미지처럼 해당 model_id값에 대한 DB정보 가져올수 있다.

Model_Vsn 조회 코드 작성

위 코드에서 각자 .py에 ModelVsn코드 추가

▷ schema.graphql

type Model_vsn {
    model_id: String!
    model_vsn: String!
    rpstr_loc: String
    workflow_use_yn: Boolean
    del_yn: Boolean
    rgst_dt: String
    rgst_time: String
    rgstr_nm: String
}

type ModelvsnResult {
    success: Boolean!
    errors: [String]
    model_vsn : Model_vsn
}
type Query {
    getModel(model_id: String!): ModelResult!
    getModelVsn(model_id: String!, model_vsn: String!): ModelvsnResult!
}

▷ api/queries.py

def getModelVsn_resolver(obj, info, model_id, model_vsn):
    try:
        model_vsn1 = rnn_model_vsn.query.get({"model_id":model_id, "model_vsn": model_vsn})
        payload = {
            "success": True,
            "model_vsn" : model_vsn1.to_dict()
        }
    except AttributeError:  # todo not found
        payload = {
            "success": False,
            "errors": ["Post item matching {id} not found"]
        }
    return payload

▷ api/models.py

class rnn_model_vsn(db.Model):
    model_id = db.Column(db.Integer, primary_key=True)
    model_vsn = db.Column(db.String, primary_key=True)
    rpstr_loc = db.Column(db.String)
    workflow_use_yn = db.Column(db.Boolean)
    del_yn = db.Column(db.Boolean)
    rgst_dt = db.Column(db.String)
    rgst_time = db.Column(db.String)
    rgstr_nm = db.Column(db.String)

    def to_dict(self):
        return {
            "model_id": self.model_id,
            "model_vsn": self.model_vsn,
            "rpstr_loc": self.rpstr_loc,
            "workflow_use_yn": self.workflow_use_yn,
            "del_yn" : self.del_yn,
            "rgst_dt": str(self.rgst_dt),
            "rgst_time": str(self.rgst_time),
            "rgstr_nm": self.rgstr_nm,
        }

▷ app.py

from api.queries import getModel_resolver, getModelVsn_resolver

query.set_field("getModelVsn", getModelVsn_resolver)
  • 실행
flask run
  • 확인

http://127.0.0.1:5000/graphql 로 접속해서 아래 쿼리로 조회하는데 이 때 내가 원하는 정보만 fit하게 조회가 가능하다.

  • model_id
  • model_vsn
  • rpstr_loc
query {
  getModelVsn(model_id: "test1", model_vsn: "v1") {
      model_vsn {
          model_id
          model_vsn
          rpstr_loc
      }
  }
}

아래 이미지처럼 해당 model_id, model_vsn값에 대한 DB정보를 fit하게 가져올수 있다.


다음 포스팅으로는 생성하는 코드를 작성함

https://zeuskwon-ds.tistory.com/76?category=1033905

 

[GraphQL] GraphQL로 API 구현 예제 with python - 생성

* 혹시 오류가 나거나 질문이 있으면 아래에 댓글을 달아주세요(오류코드 포함) GraphQL로 조회하는 코드를 확인하려면 아래 링크를 클릭 https://zeuskwon-ds.tistory.com/75?category=1033905 [GraphQL] GraphQL..

zeuskwon-ds.tistory.com

728x90