본문 바로가기

TIL

[TIL] #16. ORM

ORM이란?

ORM은 Object-Relation Mapping의 약자로 객체(Object)와 관계형 데이터베이스(Relational Database)를 매핑(Mapping)해주는 것을 말한다. 직접 SQL문을 작성하여 데이터베이스를 핸들링 하지 않고 Class로 정의된 객체간의 관계를 기반으로 SQL문을 자동으로 생성하여 데이터베이스를 핸들링할 수 있게 해준다. django의 경우, 프로젝트 폴더 내에 models.py 파일이 ORM과 관련된 파일이다. 이 파일에 클래스를 작성함으로써 관계형 데이터베이스를 설계할 수 있다.

img



ORM의 장단점

Pros

  1. 객체지향적인 코드로 인해 직관적인 코드 작성이 가능하다
    • SQL이 아닌 클래스의 메소드로 DB를 핸들링하므로 개발자가 객체 모델만 이용하여 로직을 구현하는 일에 집중할 수 있다.
    • 선언문, 할당, 종료같은 부수적인 코드가 없거나 줄어든다.
  2. 재사용 및 유지보수의 편리성이 증가한다.
    • ORM은 독립적으로 작성되어있기 때문에 해당 객체들을 재활용할 수 있다.
    • ERD를 보는 것에 대한 의존도를 낮출 수 있다.
  3. DBMS에 대한 종속성이 줄어든다
    • 대부분의 ORM솔루션은 DB에 종속적이지 않다.

Cons

  1. 모든 것을 ORM만으로 구현하기는 어렵다.
    • 프로젝트가 복잡하면 구현 난이도가 상승한다.
    • 대용량의 데이터를 처리할 때는 SQL쿼리를 직접 튜닝해서 사용하는 경우가 있다.
    • 잘못 구현되면 속도 저하, 일관성 문제가 발생할 수 있다.
  2. 프로시저가 많은 시스템에선 ORM의 객체지향적인 장점을 활용하기 어렵다.
    • 프로시저는 SQL로 만들어져 있는 대형 쿼리인데 이것을 일일이 다시 객체로 바꾸는 작업 자체가 생산성이 좋지 못하다.

SQL문을 직접 작성하지 않고도 RDB를 다룰 수 있게 해주는 기술이기 때문에 자칫 오해할 수 있지만, ORM은 개발자를 RDB로부터 분리시키기 위한 기술이 아니라 오히려 개발자에게 높은 RDB 지식을 요구한다는 점을 잊지 말아야 한다. 클래스 구조를 설계할 때에도 DB의 스키마를 고려해야하기 때문이다.



Django에서의 ORM

django프로젝트 앱 안에 있는 models.py 에 다음과 같이 클래스를 작성한다.

models.py

from django.db import models

class Owner(models.Model):
    name = models.CharField(default='', max_length=45, null=True)
    email = models.CharField(default='', max_length=300, null=True)
    age = models.IntegerField(default=0, null=True)

    class Meta:
        db_table = 'owners'

class Dog(models.Model):
    owner = models.ForeignKey(Owner, on_delete=models.CASCADE)
    name = models.CharField(default='', max_length=45, null=True)
    age = models.IntegerField(default=0, null=True)

    class Meta:
        db_table = 'dogs'

Owner와 Dog이라는 클래스는 RDB에서 각각의 테이블로 생성된다. 테이블의 이름은 Meta 클래스의 db_table에서 정해준 이름으로 생성된다. 앱에 대한 models.py 작성이 끝나면 makemigration을 통해 migrations파일을 생성한다.


migrations 파일

from django.db import migrations, models
import django.db.models.deletion

class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Owner',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(default='', max_length=45, null=True)),
                ('email', models.CharField(default='', max_length=300, null=True)),
                ('age', models.IntegerField(default=0, null=True)),
            ],
            options={
                'db_table': 'owners',
            },
        ),
        migrations.CreateModel(
            name='Dog',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(default='', max_length=45, null=True)),
                ('age', models.IntegerField(default=0, null=True)),
                ('owner_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='members.owner')),
            ],
            options={
                'db_table': 'dogs',
            },
        ),
    ]

migrate를 실행하면 위 파일의 내용을 기반으로 RDB에 테이블이 생성된다. migrate을 실행하면 django ORM이 migrations파일의 내용을 실제 RDB에서 수행되는 SQL쿼리문으로 변환하여 RDB에 테이블이 생성된다. 이 때 실행되는 쿼리문은 sqlmigrate 명령어를 통해 볼 수 있다.

Screen Shot 2021-04-08 at 21.32.51


RDB에서 생성된 테이블을 확인할 수 있다. 👍

References

'TIL' 카테고리의 다른 글

[TIL] #17. self에 대하여  (0) 2021.04.11
[Project] Westagram #1  (0) 2021.04.07
[TIL] #15. Django-Introduction  (0) 2021.03.30
[TIL] #14. Framework vs Library  (0) 2021.03.28
[TIL] #13. __init__.py  (0) 2021.03.23