[Flask]SQLAlchemy 도전

포동동·2022년 12월 13일
2

😎 첫 임무

임무라고 할까. 회사에서 처음으로 데이터팀다운 일(?)을 했다. 바로 FLASK로 DB 서버 구축하기.
이유는 모르겠지만(아마 MSA...?), 회사에서는 백엔드 서버, DB 서버, AI팀 서버를 따로 구축한다고 한다. 그래서 데이터팀에서 그나마 DB랑 웹을 만져본 내가 담당하기로 했다.



🙄 왜 굳이 FLASK..?

라는 생각이 들어 물어보니, 나중에 데이터 서버를 비개발직군이 쓸 수도 있으니 API로 설계하라는 지시였다. 본사가 멀어 구체적인 답변을 못 들은 것이 조금 아쉬웠지만, DB만 따로 구축하는 건 쉽기도 하고 개인 프로젝트에서 하고 있으니 일단 FLASK 복습도 할 겸 도전해보았다.



😵 FLASK 쉽지 않았나...? 이왜어렵?

6월이었나. FLASK를 처음 쓴 게. 처음쓸 때는 blueprint도 어려웠지만 그래도 잘만 복사해서 쓰니 그렇게 어렵지 않아서 내 안의 이미지는 FLASK=쉬운거, Django=어려운거 라는 이미지가 있었다. 그런데 플라스크는 확실히 라이브러리에 가깝다는 느낌을 강하게 받았다.

다 짜주는 프레임워크보다 스스로 짜야하는 라이브러리의 특성상 하고자 한다면 할 수 있는게 많다.
그래서 이번에 만난 기능은 바로 SQLAlchemy이다.

(SQLAlchemy란? 관계형 데이터베이스의 테이블과 컬럼들을 ORM(Object Relational Mapper)로 엮어서 python의 class로 표현할 수 있게 해주므로 데이터베이스의 테이블에 데이터 조회, 입력, 수정,삭제 등의 처리를 편리하게 도와준다.)

회사 규정상 컬럼을 공개할 순 없기 때문에 여기엔 실습 삼아 해 본 나의 테스트 flask app을 기록해두려 한다.




개발 환경

아래의 패키지들을 설치한다.

pip install Flask==2.2.2
pip install SQLAlchemy==3.0.2
pip install python-dotenv # 내 변수들은 소중하니까

파일 구조는 간단하다.

여기에 함수 많이 넣을거면 `views`폴더를 만들면 되고, 페이지 많이 만들거면 `templates`에 html 페이지 잔뜩 만들고 `render_template`로 연결만 해주면 된다. `static`은 알아서😎

db는 postgres를 사용했고, 사전에 dbeaver나 sql shell로 db랑 table을 만들고 row들도 넣어놨다.

다음으로는 flask의 메인인 app.py 파일을 열고 아래와 같이 써준다.

from flask import Flask, render_template
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
import psycopg2
import psycopg2.extras
from dotenv import load_dotenv
import os 

load_dotenv()

app = Flask(__name__)

# 변수들 가져오기
DB_HOST = os.environ.get('DB_HOST')
DB_NAME = os.environ.get('DB_NAME')
DB_USER = os.environ.get('DB_USER')
DB_PASSWORD = os.environ.get('DB_PASSWORD')

# SQLAlchemy의 핵심. 이 uri를 잘 써줘야 DB랑 연동이 된다.
app.config['SQLALCHEMY_DATABASE_URI'] = f'postgresql+psycopg2://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:5432/{DB_NAME}'

# 여기서 DB객체를 하나 만들어준다. 
db = SQLAlchemy(app)

# 이제 아래의 class를 통해 여러개의 row들을 만들어낼 수 있다. 
class User(db.Model):
    __tablename__="users" # 본인 DB의 table명. __table__로 안 쓰도록 주의!!
    name=db.Column(db.String(10), primary_key=True) # 컬럼들의 객체를 생성한다. 단, primary_key가 꼭 있어야한다. 
    gender=db.Column(db.String(10))
    phone=db.Column(db.String(50))

    def __init__(self, name, gender, phone) :
        self.name = name
        self.gender = gender
        self.phone = phone

# 하지만, 여기선 그냥 테이블 전체 내용을 조회하는 것만 기록할 것. 
@app.route('/')
def index():  # 사실상 여기만 보면 된다. 
    return render_template('index.html', data=db.session.query(User).all())

# flask run을 shell에 치면 여기가 작동한다. 
if __name__ == "__main__":
    app.run(debug=True)

나는 실습에서 DB에 새롭게 row를 넣는 것은 하지 않았지만, 만약 하고 싶다면 여기서 생성한 User 객체를 통해서 손쉽게 할 수 있다. 이것이 ORM...? 😮

나는 def index()에서 return값으로 db 세션에 query.all()을 날려 전체 row들을 다 반환하도록 작성했다.


그렇다면 이제 index.html에 가서 아래와 같이 작성한다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div>
      <table border="1">
        <thead>
          <tr>
            <td>name</td>
            <td>gender</td>
            <td>phone</td>
          </tr>
        </thead>
        <tbody>
          {% for row in data %}
          <tr>
            <td>{{row.name}}</td>
            <td>{{row.gender}}</td>
            <td>{{row.phone}}</td>
          </tr>
          {% endfor %}
        </tbody>
      </table>
    </div>
  </body>
</html>

간단한 표를 만들어서 표현해줬고, 아까 app.py에서 return 받은 data를 for문으로 row로 쪼갠다음 각 열마다 원하는 속성을 적어주면 아래와 같이 예쁘게 출력된다.




간단한 실습이지만

간단한 실습이지만, 새로운 라이브러리를 접하는 일은 언제나 설레이면서 머리가 아픈 일이다. 게다가 나 같은 초보가 원하는 것은 insert, delete, where절 이런 게 아니라 간단하게 모든 row들을 조회해보는 것인데 그것들에 대한 튜토리얼이 없어서 조금 서러웠다.

SQLAlchemy는 공부할 게 많고, 아직 engine이나 model.py로 따로 파일을 만들어서 하는 것은 더 공부해야 하지만, 우선적으로 나 같은 초보를 위해 글을 적어둔다.

참고1

참고2

그냥 psycopg2 쓰는 게 마음 편하다면

profile
완료주의

0개의 댓글