Skip to main content
DB를 사용하는 패키지를 지속적으로 유지보수하려면 최초 설치뿐 아니라, 이미 테이블이 존재하는 사용자에게 변경 사항을 전달하는 절차가 필요합니다. 마이그레이션의 배포, 실행, 실행 이력은 각각 별개의 처리로 설계하세요. 이 페이지에서는 Laravel 패키지 개발을 전제로 Laravel 13의 ServiceProvider, VendorPublishCommand, Migrator를 읽어 나갑니다. 프레임워크 구현은 v13.34.0을 참조합니다.

복사해서 넘길 것인가, 패키지에서 로드할 것인가

publishesMigrations()는 복사 원본과 복사 대상을 배포 대상으로 등록할 뿐입니다. 프로바이더가 부팅되어도 파일 복사나 SQL 실행은 하지 않습니다. 반면 loadMigrationsFrom()은 Migrator에 검색 경로를 등록합니다. 일반 migrate에서 해당 경로의 파일도 대상이 되지만, 프로바이더가 부팅되는 것만으로는 실행되지 않습니다. 사용자가 실행 전에 테이블명이나 컬럼을 조정하는 설계라면 배포 방식이 후보가 됩니다. 패키지가 스키마를 관리하고 사용자의 파일 편집을 전제로 하지 않는다면 직접 로드 방식도 검토할 수 있습니다. 아래 두 가지 프로바이더 예시는 서로 대체하는 방안입니다.
같은 마이그레이션을 배포하면서 동시에 직접 로드하는 설계는 피하세요. 배포 시 타임스탬프가 바뀌면 복사 원본과 복사 대상은 별개의 실행 이력으로 취급되어, 같은 테이블 생성 처리가 두 번 실행될 우려가 있습니다.

배포 방식 구현하기

패키지 고유의 태그를 붙여, 사용자가 다른 리소스와 구분하여 배포할 수 있도록 합니다.
최초 설치 시에는 대상 프로바이더와 태그를 지정해 복사하고, 내용을 확인한 뒤 실행합니다. 둘 다 지정하면 Laravel은 해당 프로바이더에 속한, 해당 태그의 배포 대상을 선택합니다.

타임스탬프 변경에는 설정이 관여한다

공식 문서는 배포 시 마이그레이션의 타임스탬프를 현재 일시로 업데이트하는 동작을 설명합니다. 다만 ServiceProvider::publishesMigrations()의 구현에서는 database.migrations.update_date_on_publish가 활성화된 경우에만 복사 원본을 타임스탬프 업데이트 대상에 추가합니다. 이 설정을 가져올 때의 폴백 값은 false입니다. Laravel 13 표준 애플리케이션의 config/database.php에는 다음 설정이 있습니다. 이전 구성을 이어받은 애플리케이션에서는 이 설정이 존재하는지도 확인하세요.
또한 VendorPublishCommand는 등록된 복사 원본의 실제 경로와 일치하고, 복사 대상 이름에 YYYY_MM_DD_HHMMSS_ 형식이 있는 경우에 일시를 다시 씁니다. 명령 시작 시각을 기준으로 대상 파일마다 1초씩 더합니다. 이름에 이 형식이 없으면 이 처리에서 일시를 덧붙이지 않습니다.
위 배포 후의 일시는 설명용입니다. 실제 파일명은 배포한 시각에 따라 달라집니다.
타임스탬프 업데이트는 패키지 측의 등록과 사용 애플리케이션의 설정 양쪽에 의존합니다. 패키지의 프로바이더에서 이 설정을 일괄 변경하지 말고, 설치 절차에 전제 조건을 기재하세요. 설정 캐시를 사용하는 경우에는 설정 변경 후 재구성도 필요합니다.

재배포는 “미실행된 것만 추가”가 아니다

vendor:publish는 DB의 실행 이력을 확인하지 않습니다. 또한 v13.34.0의 복사 처리에서는 기존 파일 확인을 타임스탬프 변경 전의 복사 대상에 대해 수행합니다. 디렉터리 배포에서도 먼저 복사 원본과 같은 상대 경로가 복사 대상에 있는지 확인하고, 그 다음에 일시를 다시 씁니다. 따라서 최초 배포에서 일시가 바뀌었고 복사 원본과 같은 이름의 파일이 애플리케이션 측에 없다면, 같은 태그를 다시 배포했을 때 다른 일시의 파일이 추가될 수 있습니다. --force를 붙이지 않으면 항상 중복을 막을 수 있다고 생각하지 마세요.

실행 여부는 파일명으로 판단한다

Migrator::getMigrationName()은 파일의 베이스 이름에서 .php를 제외한 문자열을 반환합니다. 미실행 판정에서는 이 이름과 실행 이력을 비교합니다. PHP 내용이나 테이블명이 같은지로 판정하는 것이 아닙니다.
이 두 개는 서로 다른 마이그레이션 이름입니다. 전자가 실행되었더라도 그 이력만으로 후자가 실행된 것으로 처리되지는 않습니다.
패키지를 업데이트할 때마다 최초 설치용 배포 명령을 무조건 다시 실행하거나, --force를 표준 절차로 삼지 마세요. 배포된 파일의 편집 내용을 덮어쓸 뿐만 아니라, 일시 변경으로 인해 중복된 처리를 추가할 가능성이 있습니다.

직접 로드 방식 구현하기

패키지 내의 마이그레이션을 그대로 실행 대상으로 삼고 싶다면 검색 경로를 등록합니다. 이 방식에서는 같은 파일을 배포하는 처리를 추가하지 않습니다.
loadMigrationsFrom()은 Migrator가 해결될 때 path()를 호출합니다. Migrator::path()는 검색 경로의 중복을 제거하고, getMigrationFiles()는 찾은 파일을 마이그레이션 이름을 키로 하여 그 이름 순으로 정렬합니다. 사용자가 패키지를 업데이트하면 새 파일은 다음 migrate의 대상이 됩니다. 기존 파일의 이름은 바꾸지 말고, 새로운 스키마 변경에는 새 파일을 추가합니다. 다른 패키지와의 충돌을 피하기 위해 create_courier_deliveries_table처럼 기능명도 포함하세요. 같은 이름의 파일은 같은 키가 되며, 두 파일이 각각 독립적으로 실행되는 것이 아닙니다.
배포 방식에서 직접 로드 방식으로의 변경은 단순히 프로바이더를 수정하는 일이 아닙니다. 사용자의 실행 이력이 배포 시의 이름으로 기록되어 있다면 패키지 측의 원래 이름과 일치하지 않습니다. 기존 사용자의 이력, 배포된 파일, 롤백을 포함한 이전 절차가 필요합니다.

스키마 변경을 기존 사용자에게 전달하기

예를 들어 배송 테이블에 추적 번호를 추가하는 경우, 이미 배포된 create_courier_deliveries_table을 편집하는 것이 아니라 변경용 새 파일을 추가합니다. 기존 생성 마이그레이션을 편집해도 이미 실행한 사용자에게는 그 변경이 실행되지 않습니다.
database/migrations/2026_10_02_000000_add_tracking_code_to_courier_deliveries_table.php
기존 행이 있는 테이블에 추가하는 예시이므로 여기서는 nullable로 했습니다. 필수화나 데이터 채우기가 필요하다면 그 절차와 실행 순서를 별도로 설계합니다. 배포 방식에서는 사용자의 배포된 파일과 대조하여 이번에 추가한 파일만 전달하는 업데이트 절차를 준비합니다. 신규 파일 전용 배포 태그를 두는 방법도 있지만, 일시 업데이트가 활성화되어 있다면 그 태그를 반복 실행할 때도 같은 주의가 필요합니다. 최초 설치용 태그를 다시 실행하기만 하는 업데이트 절차로 만들지 마세요. 직접 로드 방식에서는 업데이트된 코드에서 새 파일을 감지할 수 있습니다. 어느 방식이든 파일이 존재하는 것만으로는 DB가 바뀌지 않으므로, 릴리스 노트에 마이그레이션 실행이 필요하다는 점을 명시합니다.

릴리스 전에 확인할 사항

패키지의 DB 테스트에 더해, 사용 애플리케이션에서 배포와 업데이트 절차를 확인하세요. 테스트에서 마이그레이션을 직접 로드하는 것만으로는 파일명이 바뀌는 배포 방식을 검증한 것이 되지 않습니다.
  • 빈 DB에 최초 설치하여 필요한 테이블을 생성할 수 있다.
  • 이전 릴리스의 DB와 실행 이력에서 업데이트하여 새로운 변경만 적용된다.
  • 같은 배포 명령을 반복했을 때의 파일 목록을 확인하고, 업데이트 절차가 중복을 만들지 않는다.
  • 일시 업데이트의 활성화·비활성화와 배포된 파일의 편집을 고려한 절차로 되어 있다.
  • 신규 마이그레이션의 롤백과, 애플리케이션의 다른 마이그레이션과의 실행 순서를 확인한다.

관련 페이지

마이그레이션

스키마 정의, 실행 이력, 롤백의 기본을 확인합니다.

패키지 테스트

패키지의 서비스 프로바이더와 DB를 테스트합니다.

패키지 설정 병합과 캐시

사용자의 설정과 설정 캐시를 고려한 업데이트 절차를 확인합니다.

버전 호환성 관리

업데이트 절차와 호환성 변경을 릴리스 방침에 연결합니다.

참조한 1차 자료

마지막 수정일 2026년 10월 2일