마이그레이션
Migration
방법
이미 쌓인 데이터를 살려 둔 채 저장 구조나 값의 형태를 새 모양으로 옮기는 작업으로, 코드 배포와 짝을 지어 진행합니다.
등장 배경
코드는 새로 배포하면 옛것이 사라지지만 데이터는 그렇지 않습니다. 새 버전을 올리는 순간 예전 코드는 서버에서 내려가는데, 예전 구조로 저장된 백만 줄은 그대로 남아 있습니다. 이 비대칭이 데이터베이스를 손대는 모든 작업을 까다롭게 만듭니다.
예전에는 이 일을 사람이 직접 했습니다. 배포하는 날 담당자가 운영 데이터베이스에 접속해 칸을 더하는 명령을 손으로 실행했고, 그 명령은 어디에도 남지 않았습니다. 개발자 각자의 컴퓨터에 있는 데이터베이스는 저마다 다른 상태가 됐고, 새로 온 사람은 표가 몇 개고 칸이 무엇인지 알려면 누군가에게 물어보는 수밖에 없었습니다.
페이지덱에서도 같은 일이 있었습니다. 태오가 문서 표에 공유 범위를 적는 칸을 더하면서 운영에는 적용하고 스테이징에는 빠뜨렸습니다. 다음 주에 스테이징에서 테스트를 돌린 사람이 이틀 동안 코드에서 원인을 찾다가 구조가 다르다는 사실을 알았습니다.
마이그레이션은 이 변경을 손이 아니라 기록으로 만들려고 나온 방식입니다. 구조를 바꾸는 명령을 파일로 적어 코드와 같은 저장소에 넣고, 어느 환경에서든 그 파일을 순서대로 실행하면 같은 구조가 나오게 합니다. 데이터베이스의 모양이 기억이 아니라 저장소에 적히게 된 것입니다.
사용 절차
칸 하나를 더하는 일도 절차로 밟습니다. 쌓여 있는 데이터와 지금 돌고 있는 코드를 동시에 상대해야 하기 때문입니다. 순서는 여섯 단계입니다.
- 변경 파일을 만듭니다. 파일 하나가 변경 하나를 맡고 이름 앞에 시간이 붙습니다. 실행한 파일의 목록을 데이터베이스가 따로 기억하므로, 같은 파일이 두 번 실행되는 일은 일어나지 않습니다.
- 되돌리는 명령을 같은 파일에 함께 적습니다. 칸을 더하는 변경이면 그 칸을 지우는 명령이 짝입니다. 앞으로 가는 길만 적어 두면 문제가 생겼을 때 손으로 수습해야 합니다.
- 자기 컴퓨터와 스테이징에서 먼저 돌립니다. 여기서 보는 것은 명령이 실행되는지가 아니라 얼마나 걸리는지입니다. 줄 수가 적은 개발 데이터베이스에서 0.1초 걸린 명령이 운영의 이천만 줄에서는 몇 분을 잡아먹습니다.
- 새 구조를 더하되 옛 구조를 아직 지우지 않은 채로 운영에 적용합니다. 배포가 순식간에 끝나지 않아서입니다. 새 코드와 옛 코드가 몇 분 동안 같이 도는 구간이 있고, 그 사이 옛 코드가 사라진 칸을 찾으면 오류가 납니다.
- 이미 쌓인 줄의 값을 채웁니다. 새 칸은 비어 있는 채로 생기므로 과거 구간을 다시 처리해 채워 넣는 백필이 따라붙습니다. 백만 줄을 한 번에 고치면 표가 잠겨 서비스가 멈추니, 보통 만 줄씩 끊어 돌리고 사이에 틈을 둡니다.
- 새 코드만 남은 것을 확인한 뒤 옛 칸을 지웁니다. 4번과 6번 사이는 며칠이 걸리기도 합니다.
4번부터 6번까지를 나눠 밟는 것은 테이블 구조를 바꾸면서도 서비스를 세우지 않으려는 방법입니다. 한 번에 끝내면 배포와 구조 변경 사이의 몇 분이 그대로 장애 구간이 됩니다.
적합한 상황과 한계
이 절차가 맞는 자리는 구조가 바뀌는 변경입니다. 칸을 더하거나 이름을 바꾸거나 없애는 일, 표를 새로 만드는 일, 여러 작업을 한 덩어리로 묶어 전부 성공하거나 전부 취소되게 하는 트랜잭션의 범위를 바꾸는 일이 모두 여기 들어옵니다. 값만 고치는 일회성 작업은 따로 돌리는 스크립트가 낫습니다. 구조가 아니라 내용이고 한 번 돌리고 버리는 성격이기 때문입니다.
한계는 셋입니다.
- 큰 표에서는 명령 하나가 표를 잠급니다. 칸을 더하는 동안 그 표를 읽고 쓰는 요청이 전부 대기합니다. 그래서 사용량이 적은 시간대를 고르거나 잠그지 않고 조금씩 바꿔 주는 도구를 씁니다. 검색을 빠르게 하려고 만들어 두는 인덱스를 새로 거는 일도 같은 이유로 조심스럽습니다.
- 되돌리기가 코드만큼 간단하지 않습니다. 코드는 이전 버전으로 되돌리는 롤백이 몇 분이면 끝나지만, 칸을 지우는 변경은 되돌려도 구조만 돌아오고 안에 있던 값은 돌아오지 않습니다. 그래서 실무에서는 지우는 대신 한동안 쓰지 않는 상태로 두는 편을 고릅니다.
- 옛 코드가 새 구조에서도 동작해야 합니다. 이 조건을 하위 호환성이라고 부르는데, 마이그레이션에서는 칸 이름을 한 번에 바꾸지 않고 새 이름을 더한 뒤 양쪽에 함께 쓰는 기간을 두는 방식으로 지킵니다.
실무 용례
"이번 배포에 마이그레이션 있어요. 순서 주의해 주세요."
데이터베이스 변경이 끼어 있으니 코드와 구조 중 무엇을 먼저 올릴지 맞추자는 뜻입니다.
"이 마이그레이션 운영에서 얼마나 걸릴까요? 줄 수부터 봅시다."
개발에서 금방 끝난 명령이 운영에서는 표를 오래 잠글 수 있으니 미리 재 보자는 말입니다.
"칸은 더했는데 기존 줄이 비어 있어요. 백필 언제 돌리죠?"
구조는 바뀌었지만 과거 데이터가 아직 새 형태로 채워지지 않았다는 지적입니다.
페이지덱이 문서마다 공유 범위를 저장하기로 한 주에 이 말들이 한꺼번에 오갔습니다. 태오가 칸을 더하는 파일을 올리고, 스테이징에서 4초가 걸리는 것을 확인한 뒤, 운영의 줄 수로 환산해 3분쯤 잠긴다는 계산을 공유했습니다. 결국 새벽에 적용하기로 하고, 지현이 그 시간대에 쓰는 기업 고객이 있는지 확인했습니다.
흔한 오해
마이그레이션과 배포를 같은 일로 보는 오해가 가장 흔합니다. 한 번에 같이 일어나는 경우가 많으니 자연스러운 생각입니다. 하지만 둘은 되돌아가는 방식이 다릅니다. 코드는 이전 버전으로 바꿔 올리면 원래대로 돌아오지만, 이미 실행된 구조 변경은 그대로 남아 있습니다. 이 둘을 묶어 생각하면 장애가 났을 때 코드만 되돌려 놓고 복구가 끝났다고 판단하게 되고, 새 구조를 전제로 쓰인 데이터가 옛 코드에 걸려 두 번째 장애를 만듭니다.
마이그레이션 파일이 있으니 데이터가 안전하다고 여기는 것도 자주 보는 오해입니다. 이 파일은 구조를 어떻게 바꿨는지에 대한 기록이지 값의 사본이 아닙니다. 값을 지키는 것은 같은 데이터를 여러 서버에 복사해 두는 복제와 별도로 떠 두는 백업의 몫이고, 큰 변경 전에는 그 백업이 실제로 복구되는지 한 번 확인해 두는 편이 안전합니다.
같이 보면 좋은 페이지
마지막 업데이트 2026-09-16