3-3. NUGU Backend proxy server with Flask

투어하냥💜·2019년 12월 11일
0

SKT NUGU Project

목록 보기
6/10

앞선 3-1과 3-2에서 소개한 함수를 사용해 NUGU Play Builder와 통신하는 서버를 구축했다. 우리는 RESTful API 서버를 구축하는 데에 python flask를 사용했다.

먼저 3-1과 3-2에서 각각 생성한 관광 정보 API를 불러오는 함수와 DB에 접근하는 함수를 import해주었다.

from getEventList import content, action
from dbconnect import predicted_pop

1. Flask RESTful 서버 기본 코드

아래 코드는 flask 서버를 구축하기 위해 필요한 메인 요소들을 모아놓은 코드이다.

from flask_restful import Api, Resource
from flask import Flask, jsonify, request
import datetime

app = Flask(__name__)
api = Api(app)

class GetParams(Resource):
    def post(self):
        data = request.get_json()

        location = data['action']['parameters']['location']['value']
        ymonth = data['action']['parameters']['ymonth']['value']
        mday = data['action']['parameters']['mday']['value']

        api_date = makedate(ymonth, mday, has_dash = False)
        c = content(location, api_date, api_date)

        db_date = makedate(ymonth, mday, has_dash = True)
        val = translate_code(str(location))
        
        result_list = action(c)
        foot_traffic = predicted_pop(val, str(db_date))
        
        response = make_response(result_list, foot_traffic, one_item = False)
        print(response)

        return jsonify(response)


class GetParams1(Resource):
    def post(self):
        data = request.get_json()

        location = data['action']['parameters']['location']['value']
        ymonth = data['action']['parameters']['ymonth']['value']
        mday = data['action']['parameters']['mday']['value']

        api_date = makedate(ymonth, mday, has_dash = False)
        c = content(location, api_date, api_date)

        db_date = makedate(ymonth, mday, has_dash = True)
        val = translate_code(str(location))
        
        result_list = action(c)
        foot_traffic = predicted_pop(val, str(db_date))
        
        response = make_response(result_list, foot_traffic, one_item = True)
        print(response)

        return jsonify(response)


api.add_resource(GetParams, '/eventList', '/eventItem2', '/eventItem3',
                            '/2_1', '/2_2', '/3_1', '/3_2', '/3_3')

api.add_resource(GetParams1, '/eventItem1', '/yes')

if __name__ == '__main__':
    app.run(debug=True)

Module

* flask_restful: Flask를 사용해 REST API를 생성하기 위한 모듈
* flask: python으로 작성된 마이크로 웹프레임워크

Resource

실제로 request를 받아와 response를 만드는 main building block이다. 우리는 NUGU Play Builder에서 보내는 post request를 처리해야 하기 때문에 post 메소드만을 사용했다.
여기서 관광정보 api에서 가져온 값이 1개인 경우와, 2개 이상인 경우 처리해야 하는 방식이 달라지므로, 같은 기능을 하는 Resource Block을 두 개 생성했다.

class 내부의 코드를 살펴보면, 먼저 get_json()을 통해 NUGU Play Builder로부터 온 request 정보를 받고, 이 request 내의 값들에 접근해 사용자가 발화한 location, ymonth, mday 정보를 각각 저장한다.

ymonth, mday, has_dash 값을 makedate 함수에 넣으면, 행사 정보 및 유동인구 정보를 얻기 위한 date 값을 각각 생성해 주고, location 값을 translate_code 함수에 넣어 DB 접근을 할 때 필요한 구 코드로 변환한다.

각각 구한 변수들을 make_response 함수에 넣어 response 값을 얻고, 이를 jsonify를 이용해 json file로 변환한 후, return해 준다.

Endpoints

api.add_resource는 생성한 Resource Block을 URL에 따라 route해 준다. NUGU Play Builder에서 보내는/eventList1/yes URL은 행사 정보가 1개일 때 불러지므로, GetParams1로, 나머지 URL은 GetParams로 route해 주었다.


여기서부터는 우리가 직접 정의한 함수들을 설명하겠다.

2. 날짜 생성 함수

def makedate(ymonth, mday, has_dash):
    now = datetime.datetime.now()
    year = now.strftime('%Y')
    if len(ymonth) == 1:
        ymonth = '0' + ymonth
    if len(mday) == 1:
        mday = '0' + mday

    if has_dash:
        date = year +'-'+ ymonth +'-'+ mday
        return date
    else:
        date = year + ymonth + mday
        return date

NUGU Play Builder의 request로부터 가져온 ymonthmday 파라미터를 각 함수에 넣을 수 있는 형태로 바꿔주기 위한 makedate 함수를 정의하였다.

makedate 함수는 ymonth, mday, has_dash 값을 입력값으로 받고, datetime 모듈을 통해 현재 년도를 계산한다. 이 때, ymonth 값과 mday값이 한자리수일 경우, 앞에 0을 붙여 두자리 수로 만들어 주고, TourAPI에서는 날짜 중간에 대시(-)가 없는 형식을, MySQL에서는 대시(-)가 있는 형식을 요구하므로, has_dash에 따라 date값을 만들어 반환한다.

3. 구 코드 변환 함수

NUGU Play Builder에서는 사용자가 발화한 지역구에 따라 location entity의 값을 request에 넣어 보내주는데, 이 때 TourAPI에서의 지역구 코드와, 생활인구 데이터의 지역구 코드가 다르기 때문에, 이를 변환해주기 위한 함수를 생성했다.

def translate_code(val):
    return {
        '1': '11680', '2': '11740', '3': '11305', '4': '11500', '5': '11620',
        '6': '11215', '7': '11530', '8': '11545', '9': '11350', '10': '11320',
        '11': '11230', '12': '11590', '13': '11440', '14': '11410', '15': '11650',
        '16': '11200', '17': '11290', '18': '11710', '19': '11470', '20': '11560',
        '21': '11170', '22': '11380', '23': '11110', '24': '11140', '25': '11260'
    }.get(val)

4. response 생성 함수

make_response함수는 3-1, 3-2에 입력값을 넣고 처리한 결과를 NUGU Play Builder에 다시 보내기 위한 response(응답값)을 만들기 위한 함수이다. 기본적으로 필요한 response를 dictionary형태로 미리 정의한 뒤, 3-1, 3-2에서 정의한 함수에 날짜와 지역구를 넣어 얻은 결과를 output key에 추가한다.

def make_response(result_list, foot_traffic, one_item):
    response = {
        "version": "2.0",
        "resultCode": "OK",
        "output": {
            "list": "0"
        }
    }

    if len(result_list) == 0:
        return response
    
    elif len(result_list)>0:
        response["output"]["list"] = str(len(result_list))

        result_output = {}
        for index, result in enumerate(result_list, 1):
            for key, value in result.items():
                if key in ['title', 'place', 'cost', 'time']:
                        if one_item:
                            result_output[key + str(index)] = value[0]
                        else:
                            result_output[key + str(index)] = value



        response["output"] = dict(response["output"], **result_output)
        response["output"]["traffic"] = str(foot_traffic)
    return response
profile
TourHanyang

0개의 댓글