Heroku를 활용한 배포 - DB 연결편

Page content

읽기 전 공지

  • 본 글은 2022년 11월 28일까지만 유효합니다. 무료 버전이 사라지기 때문에, 앞으로 어떻게 될지는 현재 글 쓰는 시점에서는 모릅니다. 이 부분에 주의해서 참고 하시기를 바랍니다.

강의 홍보

개요

  • Windows 10에서 Heroku를 활용한 배포를 작업한다.
  • PostgreSQL DB 연결을 통해 로컬 데이터를 DB에 올려보도록 한다.
  • Flask를 활용한다.

사전준비

App 만들기

  • Create New App 버튼을 클릭한다.

Untitled

  • App name을 지정한다.
    • 이 때, App Name은 각 개인의 고유값으로 지정해야 한다.
    • 가급적 _ 대신에 - 으로 지정한다.

Untitled

Heroku Login

  • Heroku를 로그인한다.
$ heroku login
 »   Warning: heroku update available from 7.53.0 to 7.66.0.
heroku: Press any key to open up the browser to login or q to exit: a
Opening browser to https://cli-auth.heroku.com/auth/cli/browser/74049fd8-34d8-4125-980d-90650f72c541?requestor=SFMyNTY.g2gDbQAAAA01OC43Mi4xNTEuMTI2bgYACH1ZWoQBYgABUYA.lh-yG6rtbGZqCtIHiMMeDsQSJi-CCGQAB_72jJgSVkQ

Untitled

  • 로그인을 하고 나면 아래와 같이 완료가 된다.
$ heroku login
 »   Warning: heroku update available from 7.53.0 to 7.66.0.
heroku: Press any key to open up the browser to login or q to exit: a
Opening browser to https://cli-auth.heroku.com/auth/cli/browser/feac7503-9c5e-4a89-9782-eb92ddbc4d11?requestor=SFMyNTY.g2gDbQAAAA01OC43Mi4xNTEuMTI2bgYAqP1bWoQBYgABUYA.DvMXiQ3idJYttk03Sjsrl8z48g8_Bu8k9JgDmTqwiPw
heroku: Waiting for login...
Logging in... done
Logged in as j2hoon85@gmail.com

Github Repo

  • github repo를 생성 한다.
  • repo 이름은 heroku App name과 동일하게 하도록 한다.

Untitled

  • github를 다운로드 받는다. (예)
$ git clone https://github.com/your_name/your_repo.git
  • 해당 프로젝트 Root 경로로 가서 heroku와 연결을 시도한다.
$ heroku git:remote -a human-cal-evan
 »   Warning: heroku update available from 7.53.0 to 7.66.0.
set git remote heroku to https://git.heroku.com/human-cal-evan.git

첫번째 페이지 구축

  • Heroku를 통해 Hello World 서버를 구축한다.

(1) 주요 라이브러리 설치

  • Flask 파일을 활용하여 Hello World 배포를 진행한다.
$ virtualenv venv
created virtual environment CPython3.10.8.final.0-64 in 7072ms
  creator CPython3Windows(dest=C:\Users\h\Desktop\human-cal-evan\venv, clear=False, no_vcs_ignore=False, global=False)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=C:\Users\h\AppData\Local\pypa\virtualenv)
    added seed packages: pip==22.2.2, setuptools==65.4.1, wheel==0.37.1
  activators BashActivator,BatchActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator
  • 가상환경에 접속 후, flask를 설치한다.
$ source venv/Scripts/activate
(venv) $ pip install Flask gunicorn
Collecting Flask
  Downloading Flask-2.2.2-py3-none-any.whl (101 kB)
     -------------------------------------- 101.5/101.5 kB 6.1 MB/s eta 0:00:00
Collecting gunicorn
  Using cached gunicorn-20.1.0-py3-none-any.whl (79 kB)
Collecting itsdangerous>=2.0
  Using cached itsdangerous-2.1.2-py3-none-any.whl (15 kB)
Collecting click>=8.0
  Using cached click-8.1.3-py3-none-any.whl (96 kB)
Collecting Werkzeug>=2.2.2
  Using cached Werkzeug-2.2.2-py3-none-any.whl (232 kB)
Collecting Jinja2>=3.0
  Using cached Jinja2-3.1.2-py3-none-any.whl (133 kB)
Requirement already satisfied: setuptools>=3.0 in c:\users\h\desktop\human-cal-evan\venv\lib\site-packages (from gunicorn) (65.4.1)
Collecting colorama
  Downloading colorama-0.4.6-py2.py3-none-any.whl (25 kB)
Collecting MarkupSafe>=2.0
  Using cached MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl (17 kB)
Installing collected packages: MarkupSafe, itsdangerous, gunicorn, colorama, Werkzeug, Jinja2, click, Flask
Successfully installed Flask-2.2.2 Jinja2-3.1.2 MarkupSafe-2.1.1 Werkzeug-2.2.2 click-8.1.3 colorama-0.4.6 gunicorn-20.1.0 itsdangerous-2.1.2

[notice] A new release of pip available: 22.2.2 -> 22.3.1
[notice] To update, run: python.exe -m pip install --upgrade pip
  • 설치를 진행 후, requirements.txt 파일을 터미널에서 생성한다.
(venv) $ pip freeze > requirements.txt

(2) app.py 파일

  • VS Code를 연다.
  • 다음 코드를 작성한다.
# -*- coding: utf-8 -*-

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
    return "Hello World!"

(3) Procfile 파일

  • WSGI 서버의 양대산맥 Gunicorn 과 uwsgi 중 하나.
    • Web Server Gateway Interface
  • 대소문자에 주의하며, 확장명은 없다.
    • 첫번째 app은 파일명을 의미한다.
    • 두번째 app은 Flask 객체의 변수명이다.
  • wsgi.py를 사용하면, 이 부분은 또 달라진다.
web: gunicorn app:app

(4) runtime.txt 파일

  • 파이썬 버전을 명시한다.
python-3.9.12

(5) 배포

  • github와 Heroku에 배포를 동시에 진행하는 코드를 작성한다.
(venv) $ git add .
(venv) $ git commit -m "your_message"
(venv) $ git push && git push heroku main
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 8 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 679 bytes | 339.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/dschloe/human-cal-evan.git
   06b2fe6..1158e96  main -> main
Enumerating objects: 10, done.
Counting objects: 100% (10/10), done.
Delta compression using up to 8 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (10/10), 2.22 KiB | 1.11 MiB/s, done.
Total 10 (delta 0), reused 4 (delta 0), pack-reused 0
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-22 stack
remote: -----> Determining which buildpack to use for this app
remote: -----> Python app detected
remote: -----> Using Python version specified in runtime.txt
remote:  !
remote:  !     A Python security update is available! Upgrade as soon as possible to: python-3.9.15
remote:  !     See: https://devcenter.heroku.com/articles/python-runtimes
remote:  !
remote: -----> Installing python-3.9.12
remote: -----> Installing pip 22.3.1, setuptools 63.4.3 and wheel 0.37.1
remote: -----> Installing SQLite3
remote: -----> Installing requirements with pip
remote:        Collecting click==8.1.3
remote:          Downloading click-8.1.3-py3-none-any.whl (96 kB)
remote:        Collecting colorama==0.4.6
remote:          Downloading colorama-0.4.6-py2.py3-none-any.whl (25 kB)
remote:        Collecting Flask==2.2.2
remote:          Downloading Flask-2.2.2-py3-none-any.whl (101 kB)
remote:        Collecting gunicorn==20.1.0
remote:          Downloading gunicorn-20.1.0-py3-none-any.whl (79 kB)
remote:        Collecting itsdangerous==2.1.2
remote:          Downloading itsdangerous-2.1.2-py3-none-any.whl (15 kB)
remote:        Collecting Jinja2==3.1.2
remote:          Downloading Jinja2-3.1.2-py3-none-any.whl (133 kB)
remote:        Collecting MarkupSafe==2.1.1
remote:          Downloading MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (25 kB)
remote:        Collecting Werkzeug==2.2.2
remote:          Downloading Werkzeug-2.2.2-py3-none-any.whl (232 kB)
remote:        Collecting importlib-metadata>=3.6.0
remote:          Downloading importlib_metadata-5.0.0-py3-none-any.whl (21 kB)
remote:        Collecting zipp>=0.5
remote:          Downloading zipp-3.10.0-py3-none-any.whl (6.2 kB)
remote:        Installing collected packages: zipp, MarkupSafe, itsdangerous, gunicorn, colorama, click, Werkzeug, Jinja2, importlib-metadata, Flask
remote:        Successfully installed Flask-2.2.2 Jinja2-3.1.2 MarkupSafe-2.1.1 Werkzeug-2.2.2 click-8.1.3 colorama-0.4.6 gunicorn-20.1.0 importlib-metadata-5.0.0 itsdangerous-2.1.2 zipp-3.10.0
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote:
remote: -----> Compressing...
remote:        Done: 24.8M
remote: -----> Launching...
remote:        Released v3
remote:        https://human-cal-evan.herokuapp.com/ deployed to Heroku
remote:
remote: Starting November 28th, 2022, free Heroku Dynos, free Heroku Postgres, and free Heroku Data for Redis® will no longer be available.
remote:
remote: If you have apps using any of these resources, you must upgrade to paid plans by this date to ensure your apps continue to run and to retain your data. For students, we will announce a new program by the end of September. Learn more at https://blog.heroku.com/next-chapter
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/human-cal-evan.git
 * [new branch]      main -> main
  • 배포 실행 확인

Untitled

테이블 생성

  • PostgreSQL 테이블을 생성하는 코드를 작성한다.
  • Heroku에서 확인하도록 한다.

(1) PostgreSQL 설치

Untitled

  • 비밀번호는 1234로 지정한다.

Untitled

  • 그 외 나머지는 모두 Default 값으로 설정한다.
  • 환경변수 편집을 진행한다.
    • 경로 : C:\Program Files\PostgreSQL\13\bin

Untitled

Untitled

  • 설정 방법은 크게 2가지 있다. (Web UI / CLI)
    • 여기에서는 CLI 명령어를 통해 설치한다.
$ heroku addons:create heroku-postgresql:hobby-dev
 »   Warning: heroku update available from 7.53.0 to 7.66.0.
Creating heroku-postgresql:hobby-dev on ⬢ human-cal-evan... free
Database has been created and is available
 ! This database is empty. If upgrading, you can transfer
 ! data from another database with pg:copy
DEPRECATION NOTICE:
 Starting November 28th, 2022, ‘hobby-dev’ databases will no longer be available. To retain your data after this date, upgrade to ‘mini’ or another paid plan.
 Learn more in our blog (https://blog.heroku.com/new-low-cost-plans)
Created postgresql-concave-93710 as DATABASE_URL
Use heroku addons:docs heroku-postgresql to view documentation

Untitled

  • 위 리스트에서 application 이름이 human-cal-evan 과 연동된 것이 해당 postgresql DB가 된다.

Settings

  • 아래 화면에서 Settings 탭을 누른 후, View Credentials 를 클릭한다.

Untitled

데이터 불러오기 및 테이블 생성

  • Heroku DB에 iris.csv 데이터를 불러온 후, 해당 테이블에 추가하도록 한다.

(1) 라이브러리 설치

  • DB와 관련된 주요 라이브러리를 설치한다.
  • 설치 후, requirements.txt 파일을
(venv) $ pip install psycopg2 SQLAlchemy pandas
(venv) $ pip freeze > requirements.txt

(2) app.py 파일 수정 및 배포

# -*- coding: utf-8 -*-
from flask import Flask
import pandas as pd 
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String

## DB 연결 Local
def db_create():
	# Heroku
    engine = create_engine("postgresql://your_url", echo = False)

    engine.connect()
    engine.execute("""
        CREATE TABLE IF NOT EXISTS iris(
            sepal_length FLOAT NOT NULL,
            sepal_width FLOAT NOT NULL,
            pepal_length FLOAT NOT NULL,
            pepal_width FLOAT NOT NULL,
            species VARCHAR(100) NOT NULL
        );"""
    )
    data = pd.read_csv('data/iris.csv')
    print(data)
    data.to_sql(name='iris', con=engine, schema = 'public', if_exists='replace', index=False)

application = Flask(__name__)

@application.route("/")
def index():
    # db_create()
    return "DB Created Done!!!"

if __name__ == "__main__":
    db_create()
    application.run()
  • 코드 작성이 끝난 후, 배포를 재 진행한다.
(venv) $ git add .
(venv) $ git commit -m "your_message"
(venv) $ git push && git push heroku main
  • 정상적으로 배포가 되는지 확인한다.

Untitled

(3) DB확인

  • Heroku DB 플랫폼에서 실제 데이터가 들어갔는지 확인한다.

Untitled

  • 이제 기 설치 된, Local Postgresql에서 실제 DB가 저장이 되었는지 확인하도록 한다.
  • 먼저, pgAdmin4 프로그램을 실행한다.

Untitled

  • 첫 화면이 뜬다면, 1234 비밀번호를 입력한다.

Untitled

  • 마찬가지로 1234 비밀번호를 입력한다.

Untitled

  • Heroku DB에 접근하기 위해 새로운 서버를 만든다.

Untitled

  • DB 정보를 입력한다.

Untitled

  • 연결이 완료가 되면, 아래와 같이 많은 수의 DB 종류가 보일 것이다.
    • 각자 본인에게 맞는 DB명을 찾아야 한다.

Untitled

Untitled

  • Query Tool을 클릭 후, 간단하게 조회 쿼리를 작성해서 확인해본다.

Untitled

SELECT * FROM iris;

Untitled