pnpm migrate 명령어는 데이터베이스 스키마 변경을 안전하게 관리합니다. Entity 정의를 기반으로 자동으로 마이그레이션을 생성하고, 여러 데이터베이스에 일관되게 적용할 수 있습니다.
기본 개념
마이그레이션은 데이터베이스 스키마 변경을 버전 관리하는 시스템입니다:
- Entity 기반: Entity 정의에서 자동으로 마이그레이션 생성
- 순차 실행: 생성 순서대로 마이그레이션 적용
- 롤백 지원: 실수를 되돌릴 수 있음
- 다중 DB 지원: 여러 데이터베이스를 동시에 관리
명령어
status - 상태 확인
현재 마이그레이션 상태를 확인합니다.
출력 예시:
Development Master: ✓ Up to date (v20240115_143022)
Testing: ⚠ 2 pending migrations
Production: ✓ Up to date (v20240115_143022)
Prepared migrations:
• 20240116_101530_add_user_profile
• 20240116_102045_create_posts_table
상태 종류:
✓ Up to date: 모든 마이그레이션 적용 완료
⚠ N pending: N개의 미적용 마이그레이션
❌ Error: 데이터베이스 연결 실패
run - 마이그레이션 실행
대기 중인 마이그레이션을 모두 적용합니다.
실행 과정:
Running migrations...
Development Master:
✓ 20240116_101530_add_user_profile (0.2s)
✓ 20240116_102045_create_posts_table (0.3s)
Testing:
✓ 20240116_101530_add_user_profile (0.2s)
✓ 20240116_102045_create_posts_table (0.3s)
All migrations completed successfully!
자동 생성 및 적용:
- Entity 변경사항을 감지
- 마이그레이션 코드 자동 생성
- 모든 대상 DB에 순차 적용
Sonamu는 Entity 정의를 분석하여 필요한 마이그레이션을 자동으로 생성합니다. 수동으로 마이그레이션 파일을 작성할 필요가 없습니다.
rollback - 롤백
마지막 배치의 마이그레이션을 되돌립니다.
실행 과정:
Rolling back last batch...
Development Master:
✓ Rollback 20240116_102045_create_posts_table
✓ Rollback 20240116_101530_add_user_profile
Rollback completed successfully!
롤백은 데이터 손실을 초래할 수 있습니다. 프로덕션에서는 매우 신중하게 사용하세요.
reset - 전체 초기화
모든 마이그레이션을 롤백합니다.
주의사항:
- 모든 테이블이 삭제됩니다
- 데이터가 모두 손실됩니다
- 개발 환경에서만 사용하세요
clear - 마이그레이션 기록 삭제
마이그레이션 기록만 삭제합니다 (테이블은 유지).
사용 시나리오:
- 마이그레이션 기록이 손상된 경우
- 수동으로 스키마를 수정한 경우
- 마이그레이션을 재정렬해야 하는 경우
마이그레이션 생성
자동 생성
Entity를 수정하면 Sonamu가 자동으로 마이그레이션을 생성합니다.
// Entity 정의 변경
const UserEntity = {
properties: [
{
name: "email",
type: "string",
length: 255,
},
// 새 필드 추가
{
name: "phone",
type: "string",
length: 20,
nullable: true,
},
],
};
# 상태 확인
pnpm migrate status
# 출력:
# Prepared migrations:
# • 20240116_103045_add_phone_to_users
# 적용
pnpm migrate run
마이그레이션 파일
생성된 마이그레이션 파일은 src/migrations/ 디렉토리에 저장됩니다.
src/migrations/20240116_103045_add_phone_to_users.ts
import type { Knex } from "knex";
export async function up(knex: Knex): Promise<void> {
await knex.schema.alterTable("users", (table) => {
table.string("phone", 20).nullable();
});
}
export async function down(knex: Knex): Promise<void> {
await knex.schema.alterTable("users", (table) => {
table.dropColumn("phone");
});
}
구조:
up(): 마이그레이션 적용 (테이블 생성, 컬럼 추가 등)
down(): 마이그레이션 롤백 (변경사항 되돌리기)
지원하는 변경사항
Sonamu가 자동으로 감지하고 마이그레이션을 생성하는 변경사항:
| 변경 타입 | 설명 | 예시 |
|---|
| 테이블 생성 | 새 Entity 추가 | PostEntity 생성 |
| 컬럼 추가 | 새 프로퍼티 추가 | phone 필드 추가 |
| 컬럼 수정 | 타입/길이 변경 | varchar(100) → varchar(255) |
| 컬럼 삭제 | 프로퍼티 제거 | deprecated_field 삭제 |
| 인덱스 추가 | 인덱스 정의 | @index 데코레이터 |
| 외래키 추가 | 관계 정의 | @belongsTo 관계 |
다중 데이터베이스 관리
Sonamu는 여러 데이터베이스를 동시에 관리할 수 있습니다.
데이터베이스 구성
export default {
database: {
// 개발 환경 - 마스터
development_master: {
client: "pg",
connection: {
host: "localhost",
database: "myapp_dev",
user: "postgres",
password: "password",
},
},
// 개발 환경 - 슬레이브 (읽기 전용)
development_slave: {
// 슬레이브는 자동으로 무시됨
},
// 테스트 환경
test: {
client: "pg",
connection: {
host: "localhost",
database: "myapp_test",
user: "postgres",
password: "password",
},
},
// 프로덕션 환경
production: {
client: "pg",
connection: {
host: "prod-db.example.com",
database: "myapp_prod",
user: "postgres",
password: process.env.DB_PASSWORD,
},
},
},
};
마이그레이션 대상:
_master로 끝나는 데이터베이스
_slave가 아닌 모든 데이터베이스
일괄 적용
# 모든 데이터베이스에 적용
pnpm migrate run
# 출력:
# Development Master: ✓ 2 migrations applied
# Testing: ✓ 2 migrations applied
# Production: ✓ 2 migrations applied
실전 워크플로우
1. Entity 변경
const UserEntity = {
properties: [
// 기존 필드...
{
name: "profile_image",
type: "string",
nullable: true,
},
],
};
2. 상태 확인
Prepared migrations:
• 20240116_110230_add_profile_image_to_users
3. 마이그레이션 적용
✓ All migrations applied successfully!
4. 코드 업데이트
class UserModelClass extends BaseModel {
async updateProfileImage(userId: number, imageUrl: string) {
await this.getPuri("w")
.update({ profile_image: imageUrl })
.where("id", userId);
}
}
문제 해결
마이그레이션 충돌
문제: 여러 개발자가 동시에 마이그레이션 생성
Error: Migration conflict detected
해결:
# 1. 최신 코드 가져오기
git pull
# 2. 마이그레이션 상태 확인
pnpm migrate status
# 3. 필요 시 마이그레이션 재생성
pnpm migrate run
데이터베이스 연결 실패
문제: DB 연결 실패
Error: connect ECONNREFUSED 127.0.0.1:5432
해결:
# 1. PostgreSQL 실행 확인
psql -U postgres -l
# 2. 연결 정보 확인
cat sonamu.config.ts
# 3. 데이터베이스 생성
createdb myapp_dev
마이그레이션 순서 오류
문제: 잘못된 순서로 적용됨
Error: Foreign key constraint violation
해결:
# 1. 롤백
pnpm migrate rollback
# 2. 마이그레이션 파일명 수정 (타임스탬프)
mv 20240116_110230_*.ts 20240116_110231_*.ts
# 3. 재적용
pnpm migrate run
베스트 프랙티스
1. 자주 적용하기
# 작은 단위로 자주 마이그레이션
pnpm migrate run # 매일
2. 프로덕션 전 테스트
# 테스트 DB에서 먼저 확인
pnpm migrate status
pnpm migrate run
# 문제없으면 프로덕션 적용
3. 백업 필수
# 프로덕션 마이그레이션 전 백업
pg_dump myapp_prod > backup_$(date +%Y%m%d).sql
# 마이그레이션 적용
pnpm migrate run
4. 롤백 가능성 고려
// ✅ 롤백 가능
export async function up(knex: Knex) {
await knex.schema.alterTable("users", (table) => {
table.string("phone").nullable();
});
}
export async function down(knex: Knex) {
await knex.schema.alterTable("users", (table) => {
table.dropColumn("phone");
});
}
다음 단계