Django์์ migration์ผ๋ก ํ ์ด๋ธ ๊ด๋ฆฌํ๊ธฐ
๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ฉฐ ๋ชจ๋ธ์ ๋ณ๊ฒฝํด์ผ ํ ์ผ์ด ์๊ฒผ๋ค. ํ ์ด๋ธ์ ์์ ํ๊ณ migration์ ์ ์ฉํ๋ฉด์ dependency ์ค๋ฅ๋ถํฐ relationExists ์ค๋ฅ๊น์ง ์์ฃผ ๋ํญ์ ๊ฒช์๋ค.
์ฌ์ค ํ ์ดํ๋ก์ ํธ์์๋ migration์ด ๊ผฌ์ด๋ฉด ๊ทธ๋ฅ ์ ๋ถ ๋ฐ์ด๋ฒ๋ฆฌ๊ณ ๋ค์ ์ ์ฉํ๋ฉด ๊ทธ๋ง์ด์๋ค. ํ์ง๋ง ์ค์ ๋ก ๋ฐฐํฌ๋๊ณ ๋ฐ์ดํฐ๊ฐ ๋ด๊ฒจ ์๋ DB์ ํ ์ด๋ธ์ ์์ ํ๋ ๊ฒฝ์ฐ์๋ ์ด๋ฐ 1์ฐจ์์ ์ธ ๋ฐฉ์์ผ๋ก ์ ๊ทผํ ์๋ ์์๋ค.
๋ค์ ๊ธด ์ฝ์ง์ ๊ณผ์ ์ ๊ฒฝํํ๋ฉฐ, ๋ด๊ฐ migration์ ๋ํ์ฌ ์ ํํ ์ดํด๋ฅผ ํ์ง ๋ชปํ๊ณ ์์์ ๊นจ๋ฌ์๋ค.
Migration์ด๋?
์ผ์ข
์ database version control log๋ผ๊ณ ์ดํดํ๋ฉด ๋ ๊ฒ ๊ฐ๋ค.
python manage.py makemigrations
๋ช
๋ น์ด๋ฅผ ์ํํ๋ฉด ๊ฐ app์ ๋ชจ๋ธ์ ๋ํ ๋ณ๊ฒฝ์ฌํญ์ ๊ธฐ๋กํ python script๊ฐ ์๋์ผ๋ก ์์ฑ๋๊ณ
$ python manage.py makemigrations [app_name]
Migrations for 'users':
apps/users/migrations/0002_user_auth_id_user_social_type.py
- Add field auth_id to users
- Add field social_type to users
python manage.py migrate
๋ช
๋ น์ด๋ฅผ ์ํํ๋ฉด db์ ๋ณ๊ฒฝ์ฌํญ์ ๋ฐ์ํ ์ ์๋ค.
์ด migration script๋ 000X_changelog_contents_whatever.py
ํ์์ผ๋ก ๋ค์ด๋ฐ๋๋ฉฐ,
๋ชจ๋ธ ๊ฐ์ ๊ด๊ณ(์์ฑ ์์, ์ฐธ์กฐ ๋ฐฉํฅ ๋ฑ)๋ฅผ ๊ณ ๋ คํ์ฌ ์์ฐจ์ ์ผ๋ก dependency๊ฐ ์กด์ฌํ๋ค.
์๋ฅผ ๋ค์ด, BookObject
ํ
์ด๋ธ์์ User
ํ
์ด๋ธ์ FK๋ก ์ฐธ์กฐํ๊ณ ์๋ ๊ฒฝ์ฐ๋ผ๋ฉด
๋ฐ๋์ User
ํ
์ด๋ธ์ ์์ฑ์ด ์ ํ๋์ด์ผ๋ง BookObject
ํ
์ด๋ธ์ ์ฐธ์กฐํ ์ ์๋ค.
class User(AbstractUser, TimeStampModel):
username = None
email = models.EmailField(
max_length=255,
verbose_name='์ด๋ฉ์ผ',
validators=[SpecificEmailDomainValidator(allowlist=domain_allowlist)]
)
class BookObject(TimeStampModel):
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='note',
verbose_name='์์ฑ์'
)
๋ฐ๋ผ์ BookObject
app์ migration์๋ ๋ค์๊ณผ ๊ฐ์ dependency(users.migrations.0001_initial.py
์ ์ ์ฉํ ํ์ ํด๋น migration์ ์ ์ฉํ ์ ์์)๊ฐ ๋ช
์๋์ด ์๋ค.
class Migration(migrations.Migration):
initial = True
dependencies = [
('users', '0001_initial'),
]
์ ์ฉ๋ migration ํ์ธํ๊ธฐ
migration ์ ์ฉ ๋ด์ญ์ django_migrations
ํ
์ด๋ธ์ ์ ์ฅ๋๋๋ฐ
์ด ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ migration ๋ด์ฉ์ ์ ์ฅ๋์ง ์๋๋ค. ์ ์ฉ ์์, script๋ช
, ์๊ฐ ์ ๋์ ๋ฐ์ดํฐ๋ง ํ์ธํ ์ ์๋ค.
๋ฐ๋ผ์ ์ด๋ฏธ ์ ์ฉ๋ migration script๋ฅผ ์์ ํ ๋ค ๋ค์ migrate๋ฅผ ์ํํ๋ค๊ณ ํด๋ django_migration
ํ
์ด๋ธ์ ๋ณ๊ฒฝ ๋ด์ฉ์ ์ ์ฅ๋์ง ์๋๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์ ๋ด์ฉ์ด ๋ฐ์๋์ง ์๊ณ ์ถฉ๋์ด ์ผ์ด๋ ์๋ ์๋ค.
python manage.py showmigrations
๋ฅผ ํตํด์๋ ํ๋์ migration ์ ์ฉ์ํ๋ฅผ ํ์ธํ ์ ์๋ค.
์ด๋ฏธ ์ ์ฉ๋ migration์ Revertํ๊ณ ์ถ์ ๊ฒฝ์ฐ?
์๋์ ๊ฐ์ด Revertํ๊ณ ์ ํ๋ app์ ์ด๋ฆ๊ณผ migration ๋ฒํธ๋ฅผ ๋ช ์ํ๋ฉด ๋๋ค.
$ python manage.py migrate [app_name] [number]
์๋ฅผ ๋ค์ด 0004๊น์ง migration์ด ์ ์ฉ๋์ด ์๋ User app์ด ์๋ค๊ณ ํ์.
python manage.py migrate users 0002
๋ผ๋ ๋ช
๋ น์ ์ํํ๋ฉด, 0003 ์ดํ์ migration์ unapply๋๊ณ 0002 migration ๊ธฐ์ค์ผ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๋์ํ๋ค
์ด ๋, ์ฃผ์ํ์ฌ์ผ ํ ์ ์ ๋๋๋ฆฌ๊ณ ์ ์์ ์ดํ์ ๋ํ migration script๋ฅผ ์ ๋ ์ญ์ ํด์๋ ์๋๋ค๋ ๊ฒ์ด๋ค! ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๋ช ๋ น์ ์กด์ฌํ์ง๋ ์๋ migration์ revertํ๋ ค๋ ๊ฒ์ผ๋ก ์ดํดํ ๊ฒ์ด๋ค. ์ญ์ ๋ migration์ ๋ณต๊ตฌํ ์ ์๋ ๊ฒฝ์ฐ๋ผ๋ฉด ์ง์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ ์ด๋ธ์ ์์ ํด์ผ ํ๋ค.
์ด๋ฏธ ์ ์ฉ๋ migration ๋ด์ฉ์ ์์ ํ๊ณ ์ถ์ ๊ฒฝ์ฐ?
n๋ฒ์งธ migration ์ ์ฉ ๋ด์ญ์ ์์ ํ๊ณ ์ถ๋ค๋ฉด ์ด๋ป๊ฒ ํ๋ฉด ๋ ๊น? n+1๋ฒ์งธ์ ์๋ก์ด migration script๋ฅผ ์์ฑํ๋ฉด ๋๋ค. ์์ ์ธ๊ธํ ๊ฒ์ฒ๋ผ ์ด๋ฏธ ์ ์ฉ๋ migration์ ์์ ํ๋ ๊ฒ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ถฉ๋์ ๋ถ๋ฌ์ฌ ์๋ ์๊ณ , ์ดํ์ ์ ์ฉํ migration์์ ์ถฉ๋์ด ๋ฐ์ํ ์๋ ์๋ค.
๊ทธ๋๋ n๋ฒ์งธ๋ก ์ ์ฉ๋ migration์ ์์ ํ๋ ๋ฐฉํฅ์ผ๋ก ๊ฐ๋ฐ์ ํ๊ณ ์ถ๋ค๋ฉด, ์ด์ n-1๋ฒ์งธ version์ผ๋ก revert๋ฅผ ์ํํ๋ค์ ์๋กญ๊ฒ n๋ฒ์งธ migration script๋ฅผ ์์ฑํ๊ณ ์ ์ฉํ๋ฉด ๋๋ค.
migration์ Squashํ์ฌ log๋ฅผ ๊ด๋ฆฌํ๊ณ ์ถ์ ๊ฒฝ์ฐ?
python manage.py squashmigrations
๋ฅผ ์ฌ์ฉํ์ฌ
์กด์ฌํ๋ ๋ง์ ์์ migration์ ํ ๊ฐ(๋๋ ๊ทธ ์ด์)์ migration์ผ๋ก ํฉ์ณ์ ๊ด๋ฆฌํ ์ ์๋ค.
์๋ฅผ ๋ค์ด CreateModel
๊ณผ DeleteModel
action์ ํฉ์น ์ ์๊ณ , AddField
action์ CreateModel
๋ด๋ถ๋ก roll ์ํฌ ์ ์์ ๊ฒ์ด๋ค.
squash๋ migration๊ณผ ์ด์ ๋ฒ์ ์ migration log๋ ๋์์ ์กด์ฌํ ์ ์๋ค. Django๋ migration์ด ์ ์ฉ๋๋ ์์ ์ ์๋์ผ๋ก ํ์ ํ์ฌ ์๋ก์ด version์์๋ squash๋ migration์ ์ ์ฉํ๊ณ ์ด์ ๋ฒ์ ์ migration์ skipํ๋ค.
--squashed-name
์ต์
์ ์ฌ์ฉํ์ฌ squashํ migration script์ ์ด๋ฆ์ ์ง์ ํ ์๋ ์๋ค.
$ python manage.py squashmigrations [app_name] [number] --squaushed_name [SQUASHED_NAME]
Will squash the following migrations:
- 0001_initial
- 0002_some_change
- 0003_another_change
- 0004_undo_something
Do you wish to proceed? [y/N] y
Optimizing...
Optimized from 12 operations to 7 operations.
Created new squashed migration /home/andrew/Programs/DjangoTest/test/migrations/0001_squashed_0004_undo_somthing.py
You should commit this migration but leave the old ones in place;
the new migration will be used for new installs. Once you are sure
all instances of the codebase have applied the migrations you squashed,
you can delete them.