개발/백엔드

Server - 서버 테스트 환경 만들기, Http Method (get,post,put,delete)

웅'jk 2023. 1. 4. 16:20

서버를 만들고 테스트하기 위한 환경을 만들어봅시다.

 

1. mysql 에서 서버를 하나 만듭니다.

CREATE SCHEMA '서버명' ;

2. 이 서버에 접속할 유저를 생성합니다.

use mysql;

create user '유저명'@'%'identified by '비밀번호';

# 접속 허락을 위한 dcl
grant all on 서버명.* to '유저명'@'%'

3. 테이블을 만듭니다.

CREATE TABLE `db명`.`table명` (
	데이터 설정
)

 

4. 파이썬에 mysql 라이브러리를 설치한다

pip install mysql-connector-python

 

5. vc 에서 소스 작성한다.

# app.py

from flask import Flask
from flask_restful import Api
from config import Config

# Flask 기본 시작방법.
app = Flask(__name__)
# 환경변수셋팅
app.config.from_object(Config)
api = Api(app)

if __name__ == '__main__' : 
    app.run()
# config.py


class Config :
    HOST = 여러분의 서버 주소
    DATABASE = DB 이름
    DB_USER = DB 유저 명
    DB_PASSWORD = DB 패스워드

 

6. mysql 과 연동하기 위한 소스 작성

# mysql_connection.py
import mysql.connector

from config import Config

def get_connection() :
    connection = mysql.connector.connect(
        host = Config.HOST ,
        database = Config.DATABASE,
        user = Config.DB_USER,
        password = Config.DB_PASSWORD
    )
    return connection

 만들어진 get_connection 을 통해 mysql 과 연동하게 됩니다.

 

7. HTTP Method 에 따른 API 설정하기

 

 - 경로를 생성합니다.

# app.py 에서

api.add_resource(RecipeListResource, '/recipes')
api.add_resource(RecipeResource,'/recipes/<int:recipe_id>')

 - RecipeListResource , RecipeResource  는 각자 클래스를 의미하며

제가 직접 정의한 클래스 입니다.

 

여기서 <int:recipe_id> 이 부분은 클라이언트가 보내는 숫자값을 recipe_id 에 저장하겠다는 뜻으로 클라이언트가 1을 보낸다면 path 는 /recipes/1 이 되고 2면 /recipes/2가 된다.

 

 - 클래스 정의하기

# recipe.py

from flask import request
from flask_restful import Resource
from mysql.connector.errors import Error
from mysql_connection import get_connection

# API를 만들기 위한 클래스 작성.
# class 란? 변수와 함수로 구성된 묶음
# 클래스는 상속이 가능하다.
# API를 만들기 위해서는, flask_restful 라이브러리에
# Resource 클래스를 상속해서 만든다.

class RecipeListResource(Resource) :
    pass
class RecipeResource(Resource) :
    pass

 

- 각 클래스의 http method 를 추가합니다.

#RecipeListResource class

# API 를 처리하는 함수 개발
    # HTTP Method 를 보고! 똑같이 만들어준다.
    def post(self) :
        # 1. client 가 보내준 데이터가 있으면
        #    그 데이터를 받아준다.
        data = request.get_json()        
        # 2. 이 레시피 정보를 DB에 저장해야한다.
        ### 1 . DB에 연결
        try :
            ### 1. DB에 연결 
            connection = get_connection()
            ### 2. 쿼리문 만들기
            query = '''insert into recipe(name,description, num_of_servings,cook_time,directions)
                        values(%s, %s ,%s ,%s , %s);'''
            ### 3. 쿼리에 저장되는 변수 처리 해준다.
            record = (data['name'] , 
                      data['description'],
                      data['num_of_servings'],
                      data['cook_time'],
                      data['directions'] )
            ### 4. 커서를 가져온다
            cursor = connection.cursor()
            ### 5. 쿼리문을 커서로 실행한다.
            cursor.execute(query , record)
            ### 6. 커밋 해줘야 DB에 완전히 반영된다.
            connection.commit()
            ### 7. 자원 해제
            cursor.close()
            connection.close()
        except Error as e:
            print('Error : ' + e)
            cursor.close()
            connection.close()
            return {'result' : 'Fail' , 'Error' : str(e)}, 500
        # API 를 끝낼때는 
        # client 에게 보내줄 정보(jsom)와 http 상태코드를 보낸다
        return {"result" : "success"} , 200
    
    # get 메소드를 처리하는 함수를 만든다.
    def get(self) :
        try :
       		connection = get_connection()
            query = '''select * from recipe;'''
        # select 문은 cursor를 가져올때, dictionary = True 해줘야 한다.  
            cursor = connection.cursor(dictionary = True)   
            cursor.execute(query)
            result_list = cursor.fetchall()
            print(result_list)
        # select 할때 datetime 이 있다면 변경해줘야한다.
            i = 0
            for row in result_list : 
                result_list[i]['created_at'] = row['created_at'].isoformat()
                result_list[i]['updated_at'] = row['updated_at'].isoformat()
                i = i + 1
            
            cursor.close()
            connection.close()

        except Error as e:
            print('Error : ' + e)
            cursor.close()
            connection.close()
            return {'result':'fail','Error':str(e) } , 500
        return {"result" : "success" , 
                'items':result_list , 
                'count':len(result_list)} , 200

이 코드에서 중요한 부분은 get 같은 경우는 cursor 를 설정할때 dictionary = True 항목을 설정해야 한다.

    # RecipeResource class
    def get(self,recipe_id) :
       ...
    def put(self,recipe_id) :
        data = request.get_json()

        try :
            connection = get_connection()

            query = ''' update recipe
                    set
                    name= %s,
                    description= %s,
                    num_of_servings= %s,
                    cook_time= %s,
                    directions= %s
                    where id = %s; '''

            record = (data['name'], data['description'], data['num_of_servings'], data['cook_time'], data['directions'], recipe_id)

            cursor = connection.cursor()

            cursor.execute(query, record)

            connection.commit()

            cursor.close()
            connection.close()

        except Error as e :
            print(e)
            cursor.close()
            connection.close()
            return {"result" : "fail", "error" : str(e)}, 500

        return {"result" : "success"}, 200
    def delete(self,recipe_id) : 
        try : 
            connection = get_connection()
            query = '''delete from recipe 
                        where id = %s;'''
            record = (recipe_id,)
            cursor = connection.cursor()
            cursor.execute(query,record)
            connection.commit()

            cursor.close()
            connection.close()
        except Error as e :
            cursor.close()
            connection.close()
            return {'result' : 'fail' ,'error':e},500

 

클라이언트에서는 주의할 점이 get , delete 는 바디항목이 존재해서는 안됩니다.

여기서 body 란 특정 값이 담기는 공간이라고 생각하시면 됩니다.