😎 첫 임무
임무라고 할까. 회사에서 처음으로 데이터팀다운 일(?)을 했다. 바로 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로 따로 파일을 만들어서 하는 것은 더 공부해야 하지만, 우선적으로 나 같은 초보를 위해 글을 적어둔다.