IT 프로그래밍 관련/API server ( Flask )

API 서버 실제 구성 ( 데이터베이스 연결, API개발, 경로의 변수처리)

지나는행인 2021. 4. 8. 00:07
728x90

flask 기본적인 문법사항이나, 기본 사용법을 마치고,

 

실제로 API 서버 구성을 해보겠다.

위를 토대로 API 개발을 해본다.

 

일단 내가 하고 있지만 , 숙련되지 않고는 복잡하다.

 

먼저 데이터 베이스에서 테이블을 새롭게 만들었다. (recipe)

* recipe 테이블의 정보

현재 작성하고 있는 visual studio code에는 폴더를 여러개로 구성하여 , db, config 등 상황별에 맞춰 파일이 저장되어 있음을 참고한다.

 

먼저 이 데이터 베이스의 모든 정보를 가져오는(GET) API 를 만들어본다.

 

이 실제 API는 기문 문법에서 이용한 문법과는 다르게 , 클래스와 함수로 처리하는 부분이 많다.

 

먼저 데이터 베이스와 연결을 해주는 커넥터를 연결하기 위한 함수를 db 폴더의 db.py 파일에 작성하였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import mysql.connector            #mysql과 연결하기 위한 커넥터
from mysql.connector import Error    # 연결 에러시 처리하기 위한 라이브러리
from config.config import db_config  # 아래의 커넥터의 변수처리
 
def get_mysql_connection():
    
try :
 
        connection = mysql.connector.connect( **db_config )
 
        if connection.is_connected() :
            print('connection ok!')
            return connection
 
    except Error as e:
        print('Error while connecting to MySQL', e)
        return None        
cs

 

위는 커넥터를 연결까지만 하는 함수이다. 이후에 이 함수를 이용하여 ,  연결 후 작업을 처리한다.

 

** db_config 의 부분에는 원래

 

host = '데이터베이스 호스트',

database = '데이터베이스이름',

user = '사용자',

password = '비밀번호'    이렇게 들어가는데, 이것은 중요한 정보임으로, 밖으로 들어나지 않도록 하기 위하여,

 

config폴더의 config파일의 db_config 변수로 저장하여 사용하였다.

 

커넥터의 문법상 **db_config으로 받는다.

1
2
3
4
5
6
7
8
 
## mysql 접속 정보를, 딕셔너리 형태로 저장한다.
 
 
db_config = { 'host' :'데이터베이스호스트',
        'database' : '데이터베이스이름',
        'user' : '유저이름',
        'password' : '비밀번호'   }

class Config : 
DEBUG = True

cs

( config폴더의 config파일)

키의 값은 수정한 값으로 , 사용한 호스트 및 데이터베이스 이름등으로 들어가야한다.

 

 

 

이제 API 서버를 실행하는 py파일을 만든다. ( app.py )

기본적인 import를 해주고 코드를 써보겠다.

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
32
from flask import Flask
from flask_restful import Api   # API 설정위한 .
from db.db import get_mysql_connection # 작성한 커넥션 함수
from config.config import Config #config파일의 Config클래스
from resources.recipe import RecipeListResource
 
 
app = Flask(__name__)
 
# 1. 환경변수 설정
app.config.from_object(Config)   # 환경변수를 설정한다. 현재는 Config클래스 내용으로
                                 # DEBUG 뿐이 없지만, 앞으로 더 많은 내용이 들어갈 예정
 
 
# 2. api설정
api = Api(app)   #API설정을 한다. 괄호안에는 위에서 받은 플라스크변수
 
# 3. 경로(Path)와 리소스(Resource)를 연결한다. 
# /recipes 
 
api.add_resource(RecipeListResource, '/recipes'#API서버는 리소스라는 것을 추가해야한다.
                                          #괄호안에는 임의로 만든 클래스명, 임의로만든 경로이다.
                                        #클래스에는 recipe테이블의 모든 데이터를 가져오려고 하니.
                                          #GET메소드가 함수로 들어간다. 경로는 
                                       #앞서 나의 경로였던, localhost:5000/뒤에 recipes를 붙인다는
                                          #뜻이다. 
 
#RecipeListResource클래스는 별로로 다른 폴더에 만들어 두었으니, 위에 import를 한다.
 
 
if __name__ == '__main__':
    app.run()
cs

위에 화면에서 이야기했듯이 리소스 추가를 위해서는 클래스를 생성하여 그 클래스에 우리가 행할 코드를 생성해야한다.

** 주의 : 이 글의 젤 위의 API설계 화면에 보면, URL이 같으면 resource의 클래스명이 같다.

            같은 URL일때는 같은 클래스명 아래서 , 서로다른 함수를 만들어가면서 추가한다.(GET,POST등)

            (api.add_resource api설계 추가시 계속 추가됨. 

 

 

resources폴더의 recipe.py파일의 RecipeListResource 클래스 만든것을 보면

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from flask import request
from flask_restful import Resource   # 리소스 위한 .
from http import HTTPStatus  # HTTP 상태코드 전송위한.
from db.db import get_mysql_connection
 
 
# 이 파일에서 작성하는 클래스는, 플라스크 프레임워크에서, 
# 경로랑 연결시킬 크래스다. 따라서 클래스명 뒤에 상속한다는 
# Resource 클래스를 상속받아야한다.
# 플라스크 프레임워크의 레퍼런스에 나옴.
class RecipeListResource(Resource) :         # 괄호안에는 꼭 Resource로 상속받아야한다. 문법상!
    
    # get 메소드로 연결시킬 함수 작성
    def get(self) :          
        # recipe테이블에 저장되어 있는 모든 레시피 정보를 가져오는 함수
 
        # 1. DB 커넥션을 가져온다
        connection = get_mysql_connection()  # 작성한 함수 사용
 
        # 2. 커넥션에서 커서를 가져온다.
        cursor = connection.cursor(dictionary=True)
 
        # 3. 쿼리문을 가져온다.
 
        query = """select * from recipe;"""    # recipe테이블에서 모든 정보 가져옴.
 
        # 4. sql 실행
        cursor.execute(query)
 
        # 5. 데이터를 페치
        records = cursor.fetchall()
        print(records)
 
        ret = []
        for row in records :
            row['created_at'= row['created_at'].isoformat()   # 문자열로 바꾸기 iso포맷으로
            row['updated_at'= row['updated_at'].isoformat()   # date.date로 들어와서 
            ret.append(row)
 
        # 6. 커서와 커넥션을 닫아준다.    
        cursor.close()
        connection.close()
 
        # 7. 클라이언트에 리스펀스 한다.
        return {'count' : len(ret), 'ret' : ret}, HTTPStatus.OK
cs

이러한 코드 진행이 된다. 위의 클래스 코드 진행은 플라스크 문법상의 진행이다.

 

Resource로 상속 받는것은 무조건해야한다.

 

완성된 코드를 포스트맨으로 테스트해보면.

 

HTTP상태코드 포함하여 잘 출력된것을 알 수 있다.