728x90

데이터베이스

 : 데이터베이스(이하 DB)에는 크게 2가지 종류가 존재한다.

  SQL과 Nosql 이다. 실제로 sql과 nosql에 대한 비교와 사용이유에 대해서는 매우 중요하며 이는 이후에 자세하게 정리해보고자한다.

 

 - SQL

    : 변경 여지가 적은 경우, mysql 과 같은 관계형 데이터베이스 사용

      가장 정보가 많고, 수십년간 사용되었기 때문에 보안, 안정적임

      -> SQL을 사용하는 이유는 위에서 언급된 관계형 데이터베이스이기 때문이다. 데이터베이스에 대해 공부하다보면 

      데이터간의 관계성, 외래키(foreign key)에 대해서 많이 들어볼 것이다. 즉 데이터가 모여있는 테이블 간이 유동적으로

    연결된 데이터라면, SQL을 사용하는 것을 추천!

 

 - Nosql

   : 변경 여지가 큰 웹서비스 로깅(logging)을 위해서는 NoSQL 을 사용

     DB의 scale up 즉 규모가 커질 가능성이 큰 데이터를 저장하는 경우 Nosql 사용을 추천하는 편이다

 

  => 위의 두가지 특성으로인해, 실제로 두 DB를 혼용해서 사용하는 경우도있다.

  우리는 우선 DB 규모가 커질 가능성도 거의 없을 뿐더러(왜냐면 포폴용 프로젝트이므로),

   데이터간의 관계성이 매우 중요해서 SQL을 쓰기로했다.

 

 

SQLAlchemy VS Pymysql

-> SQL에서 가장 대표적인 DB인 mysql을 사용하기로 한 이후에는, 이 DB를 다룰 방식에 대해서 결정해야한다.

 

- pymysql

  : sql 쿼리문을 통해 서버와 데이터베이스가 통신하는 것이다.

    객체 형식의 서버코드에서 뜬금없이 SQL언어를 써야 하지만, 그만큼 직접적으로 데이터베이스에 접근하기 때문에 속도가 매우 뛰어나고,

   데이터간 JOIN을 구현해야 하는 경우 아주 용이하다.

 

그럼에도 불구하고, 우리는 ORM 즉, 서버에서는 서버 방식대로 객체지향적으로 코드를 구성하고 이를 통해 sql에 접근하는,

어떻게 보면 한단계 더 추가해서 데이터베이스에 접근하는 방식을 선정했다.

 

자바스크립트에는 sequelize가 있다면, 파이썬에는 sqlAlchemy가 있다. 

그렇다면 sql 쿼리문이 아니라 ORM 방식을 사용한 이유는 무엇일까?

 

 -ORM 방식의 특징

 1) 장점

   -  개발자는 DBMS에 대한 큰 고민없이, ORM에 대한 이해만으로 웬만한 CRUD를 다룰 수 있기 때문에,

       비즈로직에 집중할 수 있으므로 개발 생산성을 증가시킬 수 있다.

   - 객체를 통하여 대부분의 데이터를 접근 및 수정을 진행하므로, 코드 가독성이 좋다.

   -  데이터 구조 변경시, 객체에 대한 변경만 이루어지면 되므로, 유지보수성이 좋다.

 

2) 단점: 

 - 복잡한 쿼리 작성시, ORM 사용에 대한 난이도가 급격히 증가한다.

 - 호출 방식에 따라, 성능이 천차만별이다.

 -  DBMS 고유의 기능을 전부 사용하지는 못한다.

 

즉, 프로덕 단계를 고려하면 결국 sql 쿼리문 작성을 활용할 수 밖에 없지만, 초기 디벨롭 단계에서, DB에 대한 집중보다는 비즈니스로직에 집중해야 하는 경우. 이런 경우에는 ORM을 사용하는 것이 좋다고 볼 수 있다.

 -> 그러나 결국 프로덕 단계까지 고려한다면 초반의 불편함을 감수하고 sql쿼리문으로 진행해야 하는 것이다.

 

SQLAlchemy 사용하기

 

1. SQLAlchemy 라이브러리 설치하기

  pip install flask_sqlalchemy

 

2. 설치한 라이브러리를 임포트 해온 후, 기본 환경설정 값들을 기재해준다.

  - 환경설정 값들

  먼저 어플리케이션의 시크릿 키를 추가.  다음으로는 `SQLAlchemy`에서 사용할 데이터베이스의 위치를 알려줘야 한다. 

  이 데이버베이스 URI의 형태는 아래와 같다. 

  app.config\[‘SQLALCHEMY_DATABASE_URI’] = ‘mysql://<id>:<password>@<server url host>:<server url port>/<db name>’

  마지막으로 `SQLALCHEMY_TRACK_MODIFICATIONS`의 경우에는 추가적인 메모리를 필요로 하므로 false로 설정해서 꺼두어야 한다.    설정을 완료했으면 `SQLAlchemy` 객체를 하나 만든다.

1
2
3
4
5
from flask_sqlalchemy import SQLAlchemy
 
app.config['SECRET_KEY'= 'this is secret'
app.config['SQLALCHEMY_DATABASE_URI'= 'mysql+pymysql://root:Grace1234@localhost/medi?charset=utf8'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'= False
cs

 

3. 데이터 모델 생성

 

위와 같은 모델을 예로 한번 만들어 보고자 한다.

먼저 내가 만들 데이터 모델(User)을 나타내는 객체를 하나 선언 한다. 그리고 SQLAlchemy의 기능을 사용하기 위해 db.Model을 상속 받는다. 기본적으로 데이터베이스 테이블 이름(user)은 자동으로 정의되지만 __table_name__을 이용해 명시적으로 정할 수 있다.

 

필드 정의는 db.Column()을 사용하며 필드명 = db.Column(필드와 관련된 제약사항(데이터 타입, 키 설정 등..)) 이런 형식으로 작성한다.

현정님의 블로그에서 잘 정리해주신 부분이 있어서 그 글을 가지고 오게 되었다.

`id` 필드는 대부분의 모델에서 기본 키로 사용합니다.(primary_key=True)
`username`, `email`, `password`, `profile_image` 필드는 문자열로 정의를 하고, 최대 길이를 명시하여 공간을 절약할 수 있도록 합니다. 또한 `username`과 `email` 필드는 서로 중복되지 않아야 하고(unique=True), 비어있지 않아야 합니다.(nullable=False) `password` 필드의 경우에는 중복되는 것은 괜찮지만 비어있지 않아야 합니다. 그리고 보안을 위해 평문으로 저장하는 것이 아니라 암호화를 해서 저장을 해야 합니다. `profile_image` 필드는 이미지 데이터를 DB에 직접 저장하는 것이 아니라 파일 시스템에 저장한 다음 그 파일 이름만 저장할 예정입니다. 그리고 프로필 이미지는 모든 사람이 처음부터 넣는 것은 아니기 때문에 기본 이미지 파일을 가리킬 필요가 있습니다. 기본 이미지 파`default.png`로 설정하도록 하겠습니다.(default='default.png')

 

그리고 비밀번호는 암호화하여 저장해야 한다.

 

위의 정보들을 토대로 모델을 정의 하면 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class User(db.Model):
  __table_name__ = 'user' 
#모델이름을 설정
 
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(100), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    password = db.Column(db.String(100), nullable=False)
    profile_image = db.Column(db.String(100), default='default.png')
#모델 기본 칼럼 설정
 
  def __init__(self, username, email, password, **kwargs):
      self.username = username
      self.email = email
 
      self.set_password(password)
 
  def __repr__(self):
        return f"<User('{self.id}', '{self.username}', '{self.email}')>"
 
  def set_password(self, password):
    self.password = generate_password_hash(password)
#비밀번호 암호화
 
  def check_password(self, password):
    return check_password_hash(self.password, password)
#암호화 
cs

 

4. 관계성 정의

-> user와 post가 1:N인 관계인 테이블의 관계를 정의해보고자 했다.

 

- post table

post테이블의 user_id에 db_ForeignKey(참조할 테이블 명.필드명)를 사용하여 외래키로 선언해준다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
class Post(db.Model):
    __table_name__ = 'post'
 
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(120), unique=True, nullable=False)
    content = db.Column(db.Text)
    date_posted = db.Colunm(db.DateTime, default=datetime.utcnow())#게시일의 경우에는 기본값을 `datetime.utcnow()`를 사용함으로써 명시적으로 게시일을 나타내지 않은 경우 현재 시간을 게시일
 
    #user데이블의 id를 외래키로 하는 user_id
    user_id = db.Column(db.Integer, db.ForeignKey('user.id')) #테이블명.필드명 이다!! class명 아님!
 
    def __repr__(self):
        return f"<Post('{self.id}', '{self.title}')>"
cs

-user table

user테이블에도 해당 관계를 명시해주어야한다. 이때는 db.relationship(연결된 객체명, backref=가상 필드명, loding relationship) 형태를 사용. 위에서 정의한 user table 아래에, 해당 코드를 추가하면 된다.

1
posts = db.relationship('Post', backref='author', lazy=True)
cs

 

 

데이터베이스 실제로 사용하기

 

1. 데이터 베이스 초기화

user모델과 post모델을 다 만들어주었으니 Python 터미널 상에서 우리의 Flask 어플리케이션과 데이터베이스, user 모델, post 모델을 불러와서 그 다음 db.create_all()을 이용해 데이터베이스를 초기화 한다.

 

코드 맨 아래에 db.create_all()이라고 작성하여도 되고,

터미널 창에서 python을 실행시킨 후 db.create_all()을 입력해줘도 된다,

 

그러면 SQLALCHEMY_DATABASE_URI에서 지정해주었던 DB인 medi에 user, post 테이블이 잘 생성되었음을 알 수 있다.

 

2. 데이터 실제로 추가하기

user 변수에 User 데이터 모델 class에 대한 인스턴스를 만들어 저장

1
user = User(username='user', email='user@blog.com', password='password')
cs

db.session.add를 통해 변경사항(새로운 내용)을 데이터베이스에 올릴 준비를 한다.

1
db.session.add(user)
cs

db.session.commit()을 이용해서 데이터베이스에 새로운 내용을 반영하거나 db.session.rollback()으로 변경 사항을 취소할 수도 있다.

db.session.add로 데이터베이스에 객체를 추가했더라도 실제 데이터가 저장되는 시점은 db.session.commit()을 수행한 다음이다

 

3. 데이터 가져오기

select * from user의 결과처럼 전체 사용자의 데이터를 가지고 오려면 query.all()

 

 

 

daimhada.tistory.com/134

 

Python Flask 프레임워크 프로젝트에 ORM 적용하기 (Flask SQLAlchemy, ORM이란, ORM의 장점과 단점)

이 포스팅을 쓰는 이유 현재 Python의 Micro Framework인 Flask를 사용한 Studi 프로젝트를 진행하고 있다. Studi에서는 DBMS로 관계형 데이터베이스인 SQLite(에스큐엘라이트, 시퀄라이트)를 사용한다. 나는 F

daimhada.tistory.com

 

developer-stories.tistory.com/10

 

ORM(SQLAlchemy) 장단점 및 Flask 적용기

ORM 이란? - 객체 관계 매핑(Object-relational mapping; ORM)의 약자로 간단히 말해서, 데이터베이스 내의 리소스(테이블)들을 객체화하여, 각 DBMS(MySQL, MSSQL 등)들에 대해서 CRUD 등을 공통된 접근기법으로..

developer-stories.tistory.com

libertegrace.tistory.com/452

 

45. Python ORM - Flask-SQLAlchemy

지금까지 JavaScript로 Server를 구현하는 것을 배우면서 ORM으로 Sequelize를 사용해왔다. 그리고 그에 대한 정리는 libertegrace.tistory.com/entry/33-ORM-Sequelize와 [Server]Seuelize DB 세팅에 해 두었었다..

libertegrace.tistory.com

opentutorials.org/module/3669/22070

 

데이터베이스 - Flask로 만드는 블로그

이전 시간에 우리는 부트스트랩을 이용해서 어플리케이션의 디자인을 조금 세련되게 변경했습니다. 이번에는 사용자와 게시물에 대한 정보를 저장하기 위한 데이터베이스를 만들어보도록 하

opentutorials.org

flask-sqlalchemy.palletsprojects.com/en/2.x/config/#configuration

 

Configuration — Flask-SQLAlchemy Documentation (2.x)

Configuration The following configuration values exist for Flask-SQLAlchemy. Flask-SQLAlchemy loads these values from your main Flask config which can be populated in various ways. Note that some of those cannot be modified after the engine was created so

flask-sqlalchemy.palletsprojects.com

 

728x90

+ Recent posts