Django는 파이썬 웹 프레임워크로써 웹 개발을 편리하게 하기 위한 종합적인 환경을 제공한다. 편리한 웹 개발을 위해 제공되는 것들 가운데에는 객체관계매핑, 유연한 웹 템플릿 활용 등 다양한 것들이 있지만, 가장 중요한 특징은 바로 객체관계매핑이다. 본 포스팅은 초보 웹개발자를 위해 Django 에서는 어떻게 데이터베이스를 사용하고, 이를 객체로 연결하여 활용하는 가를 설명한다.

Database --> SQL in source code

일 반적인 테이터베이스 어플리케이션은 보통 위 다이어그램 처럼 직접 데이터베이스 질의언어(SQL)을 어플리케이션 소스코드에서 직접 조작하는 방식으로 구성된다. 데이터베이스의 특정 테이블의 내용을 추출하기 위해서는 SQL "select" 구문을 직접 문자열로 조작하여 데이터베이스 연결 커서에 질의를 수행한다. 잘 알고 있는 내용이지만, 새로운 레코드를 삽입할 경우에는 "insert", 기존 레코드를 수정할 경우에는 "update", 삭제할 경우에는 "delete" 구문을 사용한다. 이들 역시 SQL 구문을 문자열로 조작하여 데이터베이스를 조작하게 된다.

Database --> Django ORM --> Object in source code

Django 는 위 다이어그램 처럼 데이터베이스의 내용을 객체로 변환하는 ORM(Object Relation Mapper)를 중간에 갖고 있어서, 어플리케이션 소스코드에서 직접 객체를 조작할 수 있도록 구성되어 있다. 개발자는 데이터베이스를 조작하는데 SQL을 사용하지 않고 직접 객체를 사용할 수 있다.

Django에서 데이터베이스의 관계(Relation)를 객체(Object)로 바꿀 때의 수준 및 용어는 다음과 같다.

Relation

Object

비고

Database

Project (Application)

하나의 프로젝트는 여러개의 App로 구성된다. 이들은 모두 하나의 database 를 사용한다.

Table

Model

클래스 개념

Record

Object

객체 개념

Column

Attribute

.

이러한 방식으로 각각의 SQL 구문은 다음처럼 객체지향 프로그래밍이 가능한다.

1. SELECT --> Est.objects.all()
--> Est.objects.filter(id__contains='1')
--> exclude, get, count,...
1. INSERT --> Est.objects.create(name='a',...)
1. UPDATE --> est = Est.objects.get(id=1)
est.name = b; est.save()
1. DELETE --> est.delete()

기 존의 어플리케이션 작성시 반복적으로 나타나는 SQL 구문의 패턴을 수정하는 일은 많은 중복과 함께 관리가 귀찮은 면이 있으나, 객체로 활용하면 보다 직관적이고 관리가 용이한 형태의 개발이 가능하다. 이밖에도 다음과 같은 장점이 있다.

  1. RDBMS independant (Oracle, MySQL, PostgreSQL, Sqlite) : Django 에 구현된 각 RDBMS 별 wrapper 를 통해 RDBMS 의 종류가 어떤것인가에 상관없이 만들 수 있다. 개발 용 PC에서는 가벼운 sqlite 를 사용하고, 실제 서비스에서는 Oracle 로 사용하는데 소스코드의 수정이 거의 필요없다. (물론 테스트를 통해 검토해 볼 필요는 있음)
  2. 직관적인 객체지향 프로그래밍 : 다양한 웹 프레임워크 및 웹 관련 라이브러리에서 객체관계매핑이 구현되어 있으나, Django 는 가장 직관적이고 활용이 용이한 방식을 제공한다.
  3. 기존의 DB 기반 구성을 객체 기반 구성으로 확장하여, 컴포넌트를 조합하는 방식의 개발이 가능하다.

대 신 단점도 있다. 복잡한 SQL 질의인 경우, ORM에서는 성능이 낮을 수 있다. : ORM 에서는 SQL 구문의 생성을 추상화하여 구현하였으므로, 복잡한 쿼리의 경우 비 효율적으로 SQL 구문이 생성될 수 있다. 또한 불필요한 질의를 자주 수행함으로써 성능이 낮아질 수 있다. 하지만 Django에서는 이러한 경우를 위해 사용자가 직접 SQL문을 만들 수 있는 기능을 제공하고 있으며, 오픈소스 커뮤니티를 통해 지속적으로 성능이 개선되고 있으므로 그다지 문제가 되지 않는다.

여 러개의 RDBMS를 지원함으로써, RDBMS 간의 마이그레이션이 용이하다는 장점도 있다. Django 에서 현재 데이터베이스의 내용을 덤프받고, 새로운 설정에서 로드하기만 하면된다. 아래 소스코드는 이전 대상 모델들의 데이터를 JSON 형식으로 덤프받고 새 환경에서 로드하는 내용을 보여준다.

from django.core.serializers import serialize
result = []
models = (User, ...) # 이전대상 모델들
for model in models:
result.extend(model.objects.all())
print serialize('json', result)

뒤 코드를 backup.py 로 저장한뒤,

./backup.py > ../fixtures/initial_data.json

로 덤프받고, 새로운 환경에서

./manage.py syncdb

만 수행하면 마이그레이션이 완료된다.

Django 데이터 객체를 이용하여 데이터베이스를 검색하는 방법은 다음과 같다. 만일 Est 라는 모델이 있고, 속성이 name, identifier, sequence, data 가 있다면,

Est.objects.all() # 모든 EST 객체
Est.objects.filter(sequence__startswith='ATG') # sequence 속성이 ATG 로 시작하는 객체
Est.objects.filter( # 필터를 체인으로 연결
name__endswith='Etc.',
).exclude(
date__gte=datatime(2005,1,1),
).filter(
sequence__icontains('AGAGAG'),
)

q = Est.objects.filter(sequence__startswith='ATG')[:10] # queryset are lazy
print q
Est.objects.filter(amodel__bmodel__cmodel__name__startswith='abc') # field lookups related models

마지막 예제에서 처럼 1:다 혹은 다:1, 다:다 로 연결된 모델의 속성에 ''로 연결하여 연결(join) 검색을 수행할 수 있다는 점은 복잡한 관계에서의 편리한 데이터 검색을 가능하게 한다.

이 와 같은 연결된 모델 검색의 경우 다음의 경우가 다르다는 점을 주의해야 한다. 예를 들어 네이버같은 곳에서 여러개의 블로그를 운영하고 각 블로그에 여러 엔트리(글)이 있다고 가정한 뒤(블로그:엔트리 1:다), 특정 글을 갖고 있는 블로그를 두가지 조건으로 검색하는 방법은 다음의 두가지가 있다.

1. Blog.objects.filter(entry__headline__contains='Lennon',
entry__pub_data__year=2009)
2. Blog.objects.filter(entry__headline__contains='Lennon').filter(
entry__pub_data__year=2009)

1번의 방법은 두 조건을 동시에 만족하는 엔트리를 갖는 블로그를 찾지만, 2번의 방법은 첫번째 조건을 만족하는 엔트리를 갖는 블로그 목록에서 다시 두번째 조건을 찾는다.

위 기능들 이외에도, 버전 1.1 이후부터, 효과적인 검색을 위한 다음의 기능을 지원한다.

  1. F() object
  2. annotate()
  3. aggregate()

다음시간에 이 이상의 기능들에 대해 알아본다.

Posted by 人Co

2010/01/15 11:19 2010/01/15 11:19
, ,
Response
No Trackback , 1 Comment
RSS :
https://post-blog.insilicogen.com/blog/rss/response/33