플라스크로 나만의 웹 페이지 만들기-05

Intro


이 포스트는 플라스크로 나만의 웹 페이지 만들기 - 04 에 의존합니다. 이전 포스트를 먼저 보시는걸 추천합니다.



SQL 데이터베이스


데이터베이스는 구조적인 방법으로 애플리케이션 데이터를 저장한다. 애플리케이션은 필요한 특정 데이터를 추출하기 위해 쿼리(query)를 실행한다.

사실 SQL이라는 이름도 구조화된 쿼리 언어(Structured Query Language)이다.

또, 최근에는 문서기반(document-oriented)과 키-값(key-value) 데이터베이스를 사용하기 시작했는데 이러한 데이터베이스는 NoSQL 데이터베이스로 대중화되고 있다.


관계형 데이터베이스에는 테이블(Table)에 데이터를 저장하며 애플리키이션 도메인에 따라 다른 엔터티를 모델링한다. 예를들어 주문 관리 애플리케이션을 위한 데이터베이스는 customers, products, orders 같은 테이블을 갖게 되는식.

테이블은 고정된 수의 열(Column)과 변경 가능한 수의 행(Row)으로 구성된다. 기본 개념과 명령어는 생활코딩 동영상을 참고하자.



파이썬 데이터베이스 프레임워크


파이썬은 오픈 소스와 상용 데이터베이스에 대한 대부분의 데이터베이스 엔진을 위한 패키지를 갖고 있다. 이 말은 곧 사용자가 어떤 DB를 사용하든 제한이 없다는 이야기. 원한다면 MySQL, Postgre, SQLite, Redis, MongoDB, CouchDB등 편한것을 사용하면 된다.

선택하기 쉽지않다면 SQLAlchemyMongoEngine같은 데이터베이스 추상화 레이어를 사용해보자. 이건 쿼리언어같은 기본 데이터베이스 엔터티 대신 일반적인 파이썬 오브젝트보다 더 상위 레벨에서 동작 할 수 있도록 한다.

우리는 Flask-SQLAlchemy를 사용한다. 한글발음은 플라스크 에스큐엘 알케미…정도?

기존의 DB를 다루는 방법중에서 객체지향적 사고방식을 접목한 것으로 모델(class) 들의 개념과 관계형 데이터베이스에 속하는 MySQL의 관계(Relation)를 따로따로 보지 않고 연결해서 보는게 특징이다.


Flask-SQLAlchemy


대부분의 확장과 마찬가지로 pip를 사용하여 설치한다.

$ pip install flask-sqlalchemy

Flask-SQLAlchemy에서 데이터베이스는 URL을 사용하여 설정한다. 아래의 표는 가장 인기 있는 세 개의 데이터베이스 엔진을 위한 데이터베이스 URL 포맷 리스트다.

데이터베이스 엔진 URL
MySQL mysql://username:password@hostname/database
Postgre pstgresql://username:password@hostname/database
SQLite(리눅스) sqlite:////absolute/path/to/database
SQLite(윈도우) sqlite:///c:/absolute/path/to/database


이 URL에서 hostname은 MySQL 서비스를 호스트하는 서버를 참조하는데 로컬호스트(localhost)나 리모트 서버가 될 수 있다. 데이터베이스 서버는 여러 데이터베이스를 호스트하므로 database는 사용할 데이터베이스 이름을 가리킨다. 인증을 위해 데이터베이스에 usernamepassword를 데이터베이스 사용자 자격으로 사용한다. SQLite 데이터베이스는 서버를 갖고있지 않으므로 hostname과 username, password가 생략되고 database는 디스크 파일에 있는 파일 이름을 사용한다.


애플리케이션 데이터 베이스의 URL은 플라스크 설정 오브젝트에서 SQLALCHEMY_DATABASE_URI키로 설정되어야 한다. 다른 사용자 옵션은 설정키인 SQLALCHEMY_COMMIT_ON_TEARDOWN인데, 이 키는 True로 설정하면 각 리퀘스트의 끝에 데이터베이스 변경사항을 자동 커밋한다.

아래 예제로 SQLite 데이터베이스를 초기화하고 설정하는 방법을 보여준다.

from flask.ext.sqlalchemy import SQLAlchemy

basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] =\
    'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app. config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True

db = SQLAlchemy(app)

클래스 SQLAlchemy에서 인스턴스화된 db 오브젝트는 데이터베이스를 표현하고 Flask-SQLAlchemy에 대한 모든 기능을 액세스할 수 있도록 해준다.


모델


모델(model)이라는 용어는 애플리케이션에서 사용되는 영구적인 엔터티를 참조할때 사용한다. ORM의 컨텍스트 에서는 일반적으로 데이터베이스 테이블의 열과 매칭되는 속성을 갖는다.

다음 예제는 Role과 User모델을 정의한다.

class Role(db.Model):
  __tablename__ = 'roles'
  id = db.Column(db.Integer, primary_key=True)
  name = db.Column(db.String(64), unique=True)

  def __repr__(self):
    return '<Role %r>' % self.name

class User(db.Model):
  __tablename__ = 'users'
  id = db.Column(db.Integer, primary_key=True)
  username = db.Colum(db.String(64), unique=True, index=True)

  def __repr__(self):
    return '<User %r>' % self.username

__tablename__ 클래스 변수는 데이터베이스에 있는 테이블 이름을 정의하는데 만약 생략되었다면 디폴트 테이블 이름을 할당한다. 테이블 이름을 명확하게 설정하자.

db.Column 생성자에 넘겨진 첫 번째 인수는 데이터베이스 열의 타입이며 모델 속성이다. 일반적인 데이터베이스 타입을 넣을수 있다.

나머지 인수들은 각 속성의 설정 옵션이다. 이 또한 일반적인 데이터베이스 속성과 비슷하다.

항상 필요한 것은 아니지만 두 개의 모델은 __repr__() 메소드를 포함하는데 이 메소드는 디버깅이나 테스트용으로 사용하는 문자열 표현식을 전달한다.


관계


관계형 데이터베이스는 관계를 통해 서로 다른 테이블의 행들을 연결한다.

_post-17-11-03-01


위 그림은 사용자(user)와 규칙(roles) 사이의 간단한 관계를 보여준다. 이것은 규칙으로부터 사용자까지의 일대다(one-to-many) 관계를 보여주는데 하나의 규칙은 많은 사용자에게, 사용자는 오직 하나의 규칙을 갖는다.

class Role(db.Model):
  #....
  users = db.relationship('User', backref='role')

class User(db.Model):
  #...
  role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

위의 그림에서 본 것처럼, 관계는 외래키의 사용자를 통해 두 개의 행을 연결한다. User 모델에 추가된 role_id 열은 외래키로 정의되고 이것은 관계를 만든다.

rolse.id인수는 열이 roles 테이블에있는 행에서 id값을 갖는 것으로 해석된다.

db.relationship()의 첫 번째 인수는 관계의 다른 쪽에 어떤 모델이 있는지를 나타낸다. 이 모델은 클래스가 아직 정의되지 않았다면 문자열로 제공된다.

두번째 backref 인수는 User모델에 role 속성을 추가하여 관계의 반대 방향을 정의한다. 이 속성은 Role 모델이 외래키 대신 오브젝트에 접근하도록 role_id 대신에 사용된다.

관계에는 일대다 외에 다른 타입이 있다. 일대일 관계는 userlist 옶견을 사용하여 db.relationship() 정의에서 False로 설정하면된다. 다대일 관계는 테이블이 반대라면 일대다로 표현된다. 조금 복잡한 다대다의 경우는 관련 테이블(association table)이라고 하는 추가 테이블이 필요하다. 다대다 관계에 대해서는 나중에 다시 알아보자.


다음포스트 - 플라스크로 나만의 웹 페이지 만들기 - 06