🤖

[Prisma] 기존 테이블에 AUTO_INCREMENT 컬럼 추가

Created
2024/11/07 23:38
Tags
안녕하세요. 뻔한 서버 개발자입니다.
계속해서 더 편리하고 새로운 기술들이 생겨나고 있지만, 멈춰버린 시간 속에 살고 있는 뻔한 개발자는 오늘도 뻔한 정보를 사용합니다.

[Prisma] 기존 테이블에 AUTO_INCREMENT 컬럼 추가

데이터베이스를 사용하다 보면 종종 테이블에 새로운 컬럼을 추가해야 하는 상황을 맞이하게 됩니다. 특히, 고유 식별을 위해 AUTO_INCREMENT 컬럼이 필요해지는 경우가 많습니다. 하지만 이미 데이터를 가진 테이블에 AUTO_INCREMENT 컬럼을 추가하려고 하면 문제에 부딪히게 됩니다.
이 글에서는 Prisma를 사용하여 MySQL 테이블에 AUTO_INCREMENT 컬럼을 안전하게 추가하는 과정을 단계별로 설명합니다. 이 과정을 통해 이미 데이터가 있는 상황에서도 문제없이 AUTO_INCREMENT 기능을 활성화할 수 있습니다.

 문제 상황: 기존 테이블에 AUTO_INCREMENT 컬럼 추가하기

현재 사용 중인 테이블은 아래와 같습니다:
model User { id Int @id username String }
SQL
복사
여기에 새로운 systemCode 컬럼을 AUTO_INCREMENT로 추가하여, 기존 id와는 별도의 고유 식별자를 부여하려고 합니다. 하지만 Prisma에서 아래와 같이 바로 설정할 경우 기존 레코드에는 systemCode 값이 없기 때문에 NOT NULL 제약 조건에 위배됩니다.
model User { id Int @id systemCode Int @unique @default(autoincrement()) // 새로운 컬럼 추가 username String }
GraphQL
복사
그렇다면 기존 데이터를 보존하면서 systemCode를 추가하려면 어떤 과정이 필요할까요?

 해결 방법: Prisma와 MySQL을 활용한 단계별 가이드

이제 systemCode 컬럼을 안전하게 추가하기 위한 단계별 해결 방법을 소개합니다.

 1. 새로운 nullable systemCode 컬럼 추가

먼저, NULL을 허용하는 systemCode 컬럼을 추가합니다.
이렇게 하면 기존 데이터에 영향을 주지 않고 systemCode 컬럼을 생성할 수 있습니다.
model User { id Int @id systemCode Int? // nullable로 추가한 컬럼 username String }
GraphQL
복사
이 작업을 통해 Prisma 마이그레이션을 실행할 때 기존 레코드에는 NULL 값이 할당됩니다.

 2. 기존 레코드에 systemCode 값 할당하기

이제 기존 레코드의 systemCode 값에 대해 순차적으로 ID 값을 채워 넣습니다. 다음 SQL 쿼리를 사용하여 기존 레코드에 값을 설정합니다.
SET @count = 0; UPDATE User SET systemCode = @count:= @count + 1;
GraphQL
복사
이 작업을 통해 기존 레코드도 systemCode 값을 가지게 됩니다.

 3. AUTO_INCREMENT 및 NOT NULL 속성 추가

이제 systemCode 컬럼에 AUTO_INCREMENTNOT NULL 속성을 추가할 수 있습니다. Prisma 스키마를 다음과 같이 업데이트하고, 마이그레이션을 실행합니다.
model User { id Int @id systemCode Int @unique @default(autoincrement()) username String }
GraphQL
복사
이렇게 하면 이후 추가되는 레코드에는 systemCode 값이 자동으로 증가하게 됩니다.

 4. 결론

기존 데이터에 영향을 주지 않고 AUTO_INCREMENT 컬럼을 추가하는 방법을 알아보았습니다.
이를 통해 id 컬럼과 별도로 고유한 systemCode를 사용하는 상황에서도 Prisma와 MySQL을 안전하게 사용할 수 있습니다.
 여기까지 ChatGPT의 글이였습니다.
이제 막강한 AI 도구가 우리와 함께하며 프로그래밍 문제를 해결하는 데 실질적인 도움을 주는 시대가 되었습니다. ChatGPT는 복잡한 데이터베이스 마이그레이션 문제부터 코드 최적화, 리팩토링에 이르기까지 다양한 상황에서 개발자들의 아이디어와 해결책을 제시할 수 있습니다.
앞으로 여러분의 개발 여정에서도 ChatGPT를 가벼운 조언자로 활용해 보세요. 생각보다 더 유용하고 재미있는 동반자가 될 것입니다!
 ChatGPT의 글이였다는 글도 ChatGPT의 글이였습니다.
마지막으로 GhatGPT가 알려준 뻔한 방법 말고 제가 실제 적용한 부분을 안내드리도록 하겠습니다.
수동으로 마이그레이션을 할 경우 실수가 있을 수 도 있고 동료들에게 전달해아하는 번거로움이 있습니다.
그래서 자동으로 해결하는 방법을 소개해 드립니다.

 자동으로 해결 방법1

  1. 새로운 nonNull 컬럼 추가 마이그레이션 생성

우선, Prisma에서 systemCode 컬럼을 nonNull로 추가하고 마이그레이션 파일을 --create-only로 생성
AUTO_INCREMENT는 index혹은 unique가 필수, 여기서는 index설정
model User { id Int @id systemCode BIGINT @default(autoincrement()) @@index([systemCode]) }
GraphQL
복사
$ prisma migrate dev --create-only ⚠️ We found changes that cannot be executed: 블라블라 it is not possible to execute this step. // 오류가 출력되지만 무시하고 생성만 합니다.
Bash
복사

  2. 마이그레이션 파일 수정하기

생성된 마이그레이션 파일을 엽니다. 문제가 있는 마이그레이션이기 때문에 warnings가 있습니다.
/* Warnings: - Added the required column `systemCode` to the `User` table without a default value. This is not possible if the table is not empty. */ -- AlterTable ALTER TABLE `User` ADD COLUMN `systemCode` BIGINT NOT NULL AUTO_INCREMENT; -- CreateIndex CREATE INDEX `User_systemCode_idx` ON `User`(`systemCode`);
SQL
복사
위 파일 내용을 아래 파일 내용으로 수정합니다.
위쪽에 nullable한 코드 아래쪽에 nonNull을 배치하는 부분이 중요합니다.
-- AlterTable ALTER TABLE `User` ADD COLUMN `systemCode` BIGINT NULL; -- CreateIndex CREATE INDEX `User_systemCode_idx` ON `User`(`systemCode`); START TRANSACTION; -- 기존 레코드에 순차적으로 systemCode 값 할당 SET @count = 0; UPDATE `User` SET `systemCode` = @count:= @count + 1; -- systemCode에 AUTO_INCREMENT 및 NOT NULL 제약 조건 추가 ALTER TABLE `User` MODIFY COLUMN `systemCode` BIGINT NOT NULL AUTO_INCREMENT; COMMIT;
SQL
복사

 자동으로 해결 방법2

위 해결방법 1이 --create-only로 만들어준 마이그레이션 파일을 완전히 변경하기 때문에 과감한 수정이라고 생각될 경우 안전하게 마이그레이션 파일 2개로 진행합니다.

  1. 새로운 nullable 컬럼과 index를 추가해서 마이그레이션 생성

nullablesystemCode 컬럼과 index를 추가하고 마이그레이션 파일을 --create-only로 생성
AUTO_INCREMENTindex 혹은 unique가 필요, 여기서는 index를 설정
nullable을 추가하는데 미리 설정하는 이유는 아래에서 설명
model User { id Int @id systemCode BIGINT? @@index([systemCode]) }
GraphQL
복사
$ prisma migrate dev --create-only ✔ Enter a name for the new migration: … Prisma Migrate created the following migration without applying it 20241105070016_ // 오류없이 안전하게 생성됩니다.
Bash
복사
-- AlterTable ALTER TABLE `User` ADD COLUMN `systemCode` BIGINT NULL; -- CreateIndex CREATE INDEX `User_systemCode_idx` ON `User`(`systemCode`);
SQL
복사

  2. nonNull로 컬럼을 수정하고 마이그레이션 생성

systemCode 컬럼을 nonNull로 수정하고 @default(autoincrement()) 추가 후 마이그레이션 파일을 --create-only로 생성
model User { id Int @id systemCode BIGINT @default(autoincrement()) @@index([systemCode]) }
GraphQL
복사
$ prisma migrate dev --create-only ⚠️ We found changes that cannot be executed: 블라블라 it is not possible to execute this step. // 오류가 출력되지만 무시하고 생성만 합니다.
Bash
복사
/* Warnings: - Made the column `systemCode` on table `User` required. This step will fail if there are existing NULL values in that column. */ -- AlterTable ALTER TABLE `User` MODIFY `systemCode` BIGINT NOT NULL AUTO_INCREMENT;
SQL
복사
위 파일 내용을 아래 파일 내용으로 수정합니다.
여기서는 --create-only로 만들어진 부분을 수정하지 않고 위에 systemCode를 채워주는 부분만 추가
START TRANSACTION; -- 기존 레코드에 순차적으로 systemCode 값 할당 SET @count = 0; UPDATE `User` SET `systemCode` = @count:= @count + 1; COMMIT; /* Warnings: - Added the required column `systemCode` to the `User` table without a default value. This is not possible if the table is not empty. */ -- AlterTable ALTER TABLE `User` MODIFY `systemCode` BIGINT NOT NULL AUTO_INCREMENT;
SQL
복사
만약 index를 첫번째 마이그레이션 파일에 넣지 않았다면 deploy 할때 index가 없는 상태에서 AUTO_INCREMENT를 적용하려고 하면 오류가 나오기 때문에 첫번째 마이그레이션에 포함했음
Incorrect table definition; there can be only one auto column and it must be defined as a key
나에게 새로운 정보가 누군가에게 뻔한 정보 일지라도,
나에게 뻔한 정보가 누군가에게는 새로운 정보가 되기를 바라며