잡(job)기술
TypeORM 마이그레이션 사용하기: 안전한 데이터베이스 관리를 위한 단계별 가이드
무니이구나
2025. 5. 30. 13:24
데이터베이스 스키마 변경을 관리하는 것은 까다로울 수 있다. 특히 개발 환경과 프로덕션 환경 간의 일관성을 유지해야 할 때 더욱 그렇다. TypeORM의 마이그레이션 기능은 통해 이러한 변경 사항을 체계적으로 추적하고 적용할 수 있다. 이 글에서는 TypeORM 마이그레이션 사용 과정을 단계별로 설명하고, 각 단계가 왜 중요한지, 흔히 발생하는 함정을 피하기 위한 사례를 정리하고자 한다.
왜 마이그레이션을 사용해야 할까?
마이그레이션을 위한 절차를 정리하기 전에, 마이그레이션이 왜 중요한지 이해하는 것이 필요하다.
- 데이터베이스 버전 관리: 마이그레이션은 코드 버전 관리처럼 스키마 변경을 시간 순으로 추적할 수 있게 해준다.
- 환경 간 일관성: 개발, 스테이징, 프로덕션 데이터베이스가 동기화된 상태를 유지하도록 보장한다.
- 안전한 롤백: 문제가 발생했을 때 변경 사항을 쉽게 되돌릴 수 있다.
- 팀 협업: 팀원들이 서로의 작업을 방해하지 않고 데이터베이스 변경 작업을 협업할 수 있게 한다.
이제 TypeORM 마이그레이션을 효과적으로 사용하는 단계별 과정을 살펴보자.
1단계: synchronize를 false로 설정하기
- 해야 할 일: TypeORM 설정에서 synchronize 옵션을 false로 설정한다.
TypeOrmModule.forRoot({ synchronize: false, });
- 이유:
- synchronize가 true일 경우, 애플리케이션이 시작될 때마다 TypeORM이 엔티티 정의를 기반으로 데이터베이스 스키마를 자동으로 업데이트한다. 이는 개발 환경에서 편리하지만, 프로덕션에서는 의도치 않은 데이터 손실이나 스키마 변경을 초래할 수 있다.
- synchronize: false로 설정하면 명시적인 마이그레이션을 통해서만 스키마 변경이 적용되므로, 특히 프로덕션에서 완전한 제어와 안전성을 보장한다.
2단계: 엔티티 수정하기
- 해야 할 일: 데이터베이스 스키마에 반영하고 싶은 변경 사항(예: 새 열 추가, 데이터 타입 변경)을 엔티티 파일에 업데이트한다.
- 이유:
- 엔티티는 데이터베이스 테이블의 구조를 정의한다. 애플리케이션의 데이터 요구사항이 변경되면 일반적으로 엔티티 수정부터 시작한다.
- 하지만 synchronize: false 설정에서는 이러한 변경이 데이터베이스에 자동으로 반영되지 않는다. 이는 의도치 않은 스키마 업데이트를 방지하지만, 마이그레이션을 통해 수동으로 변경을 적용해야 한다는 것을 의미한다.
중요 참고: 개발 환경에서 엔티티를 수정한 후 "no such column" 같은 오류가 발생할 수 있다. 이는 데이터베이스 스키마가 아직 업데이트되지 않았기 때문에 예상된 현상이며, 다음 단계에서 해결할 수 있다.
3단계: 마이그레이션 생성하기
- 해야 할 일: 다음 명령어를 실행해 마이그레이션 스크립트를 생성한다.
typeorm migration:generate -n MigrationName
- 이유:
- 이 명령어는 현재 엔티티 정의와 기존 데이터베이스 스키마를 비교하여 차이점(예: 새 열 추가)을 포착하는 마이그레이션 스크립트를 생성한다.
- 생성된 스크립트에는 up(변경 적용)과 down(변경 롤백) 메서드가 포함되어 있어 스키마 변경과 롤백을 쉽게 관리할 수 있다.
- 참고: 마이그레이션 이름을 구체적으로 지정하라(예: AddUserEmailColumn). 어떤 변경이 적용되는지 명확히 알 수 있다.
4단계: 마이그레이션 실행하기
- 해야 할 일: 마이그레이션을 실행하여 데이터베이스에 변경을 적용한다.
typeorm migration:run
- 이유:
- 이 명령어는 보류 중인 마이그레이션 스크립트의 up 메서드를 실행하여 데이터베이스 스키마를 엔티티와 일치하도록 업데이트한다.
- TypeORM은 migrations 테이블을 확인하여 새로운 마이그레이션만 적용되도록 하므로 중복 실행을 방지한다.
- 안전한 이유: 마이그레이션은 버전 관리되고 추적되므로, 순서대로 적용할 때 중복이나 충돌 걱정 없이 안심하고 사용할 수 있다.
5단계: 애플리케이션 재시작하기 (개발 환경 전용)
- 해야 할 일: 마이그레이션을 실행한 후 개발 환경에서 애플리케이션을 재시작한다.
- 이유:
- 개발 환경에서 앱을 재시작하면 업데이트된 스키마를 인식하게 되어 스키마-엔티티 불일치로 인한 오류(예: 열 누락)가 해결된다.
- 참고: 프로덕션에서는 일반적으로 배포 과정에서 마이그레이션이 실행되므로 애플리케이션이 업데이트된 스키마와 함께 자동으로 시작된다.
6단계: 프로덕션에서 마이그레이션 적용하기
- 해야 할 일: 마이그레이션 파일을 버전 관리 시스템에 포함시키고 배포 중에 마이그레이션을 실행한다.
typeorm migration:run
- 이유:
- 프로덕션 환경에서는 synchronize: true를 사용해서는 안 된다. 대신 마이그레이션을 통해 스키마 변경을 의도적이고 안전하게 적용해야 한다.
- 마이그레이션 파일을 리포지토리에 커밋하면 코드 변경처럼 스키마 변경을 추적하고 검토할 수 있다.
- 예시: CI/CD 파이프라인에서 마이그레이션 실행을 자동화하여 배포 시 일관성 있게 적용되도록 한다.
흔한 오해
- 프로덕션에서의 마이그레이션 생성: 프로덕션에서 migration:generate를 실행해서는 안 된다.. 이 명령어는 개발 환경에서 엔티티 변경을 기반으로 마이그레이션 스크립트를 생성하는 데 사용된다. 프로덕션에서는 미리 생성된 마이그레이션 스크립트를 migration:run으로 실행하기만 하면 된다.
- 롤백 가능성: 필요 시 migration:revert를 사용해 마지막 마이그레이션을 되돌릴 수 있다. 이는 down 메서드를 실행하여 변경을 취소하며, 문제가 생겼을 때 안전망 역할을 한다.
추가적으로 고려할 점
- 마이그레이션 먼저 테스트하기: 프로덕션에 적용하기 전에 스테이징 또는 테스트 데이터베이스에서 마이그레이션을 테스트한다. 문제를 조기에 발견할 수 있다.
- 마이그레이션 문서화: 마이그레이션 파일에 각 변경의 목적을 설명하는 주석을 추가한다. 팀 협업과 향후 유지보수에 도움이 된다.
- 데이터베이스 백업: 프로덕션에서 마이그레이션을 실행하기 전 데이터베이스를 백업한다. 문제가 발생했을 때 데이터를 복구할 수 있다.
- 마이그레이션 기록 모니터링: migrations 테이블을 정기적으로 확인하여 예상한 모든 마이그레이션이 적용되었는지 점검한다.
SELECT * FROM migrations;
결론
TypeORM 마이그레이션을 사용하면 데이터베이스 스키마 변경을 제어되고 예측 가능한 방식으로 관리할 수 있다. synchronize를 false로 설정하고, 엔티티를 수정하며, 마이그레이션을 생성하고 실행하고, 프로덕션 배포를 신중히 처리하는 이 단계를 따르면 데이터베이스가 애플리케이션과 함께 안전하게 관리될 수 있다.
데이터베이스 스키마를 애플리케이션 코드와 동일한 주의와 버전 관리 규율로 다루는 것이 성공적인 마이그레이션의 핵심이다.