파괴적 변경의 위험성: 데이터가 날아가는 아찔한 순간
컬럼 삭제나 타입 변경 같은 파괴적인 쿼리가 운영 서비스에 미치는 치명적 영향과 이를 피해야 하는 이유를 알아봅니다.
운영 중인 데이터베이스에 스키마를 변경할 때 가장 두려운 순간은 언제일까요? 바로 기존 데이터가 유실되거나, 변경 작업 도중 서비스가 멈춰버리는 상황입니다. 특히 컬럼을 삭제(DROP)하거나 데이터 타입을 변경(ALTER)하는 '파괴적 변경'은 돌이킬 수 없는 결과를 낳기도 합니다. 이번 시간에는 왜 파괴적인 변경을 피해야 하며, 그 대안은 무엇인지 알아보겠습니다.
파괴적 변경이란 무엇인가?
데이터베이스에서 파괴적 변경(Destructive Change)이란 기존에 존재하는 데이터를 지우거나, 구조를 변경하여 이전 상태로 완벽하게 되돌리기 어려운 작업을 의미합니다.
대표적인 파괴적 변경 쿼리는 다음과 같습니다.
- `DROP TABLE`: 테이블 자체를 삭제하는 작업
- `DROP COLUMN`: 특정 컬럼과 그 안의 데이터를 모두 삭제하는 작업
- `ALTER COLUMN TYPE`: 컬럼의 데이터 타입을 변경하는 작업 (예: 문자열을 정수형으로 변경)
- `RENAME COLUMN`: 컬럼의 이름을 변경하는 작업 (데이터는 유지되지만 앱에서 참조 오류 발생)
이러한 명령을 개발 환경이나 로컬 환경에서는 아무렇지 않게 사용할 수 있습니다. 하지만 사용자 요청이 쏟아지는 운영 환경(Production)에서 파괴적인 쿼리를 실행하는 것은 시한폭탄의 스위치를 누르는 것과 같습니다.
왜 운영 환경에서 치명적일까?
가장 큰 이유는 데이터 유실과 복구의 어려움입니다. 만약 실수로 중요한 사용자 정보가 담긴 컬럼을 `DROP` 해버렸다면, 백업본을 찾아 복구하기 전까지 해당 데이터는 영원히 사라지게 됩니다.
또한, 파괴적 변경은 다운타임(Downtime), 즉 서비스 중단을 유발합니다. 예를 들어, 수백만 건의 데이터가 있는 테이블의 컬럼 타입을 변경(`ALTER COLUMN TYPE`)하려고 하면, 데이터베이스는 변경 작업이 끝날 때까지 해당 테이블 전체나 일부에 락(Lock)을 겁니다. 이 동안에는 사용자가 앱을 통해 새로운 글을 쓰거나 읽을 수 없게 되어 장애로 이어집니다.
파괴적 변경에 대한 흔한 착각
오해 또는 실수
안 쓰는 컬럼이니까 바로 삭제해도 문제없을 거야.
바로잡기
구버전 앱이나 예상치 못한 배치 잡(Batch Job)에서 아직 참조하고 있을 수 있습니다.
오해 또는 실수
데이터 타입 변경 쿼리 하나니까 1초면 끝나겠지?
바로잡기
데이터가 많을수록 테이블 전체를 재구성하느라 수십 분이 걸릴 수 있습니다.
오해 또는 실수
이름만 바꾸는 건 데이터가 안 날아가니까 안전해.
바로잡기
앱의 코드는 여전히 옛날 이름을 찾고 있어서 즉시 에러가 발생합니다.
데이터 보존의 원칙과 대안
그렇다면 더 이상 필요 없어진 컬럼이나, 잘못 만든 테이블은 어떻게 처리해야 할까요? 핵심은 "즉시 파괴하지 않고, 안전하게 우회하는 것"입니다.
1. 컬럼 삭제 대신 '사용 안 함' 표시하기
컬럼을 물리적으로 `DROP`하기보다는, 먼저 애플리케이션 코드 수준에서 해당 컬럼을 더 이상 읽고 쓰지 않도록 변경하고 배포해야 합니다.
그리고 일정 기간 동안 모니터링을 거쳐 정말 아무곳에서도 해당 컬럼을 참조하지 않는 것이 확실해졌을 때, 비로소 마이그레이션을 통해 컬럼을 삭제하는 것이 안전합니다.
컬럼을 없애고 싶을 때의 올바른 선택
| 상황 | 선택 | 이유 |
|---|---|---|
| 사용 중인 상태 | DROP COLUMN 쿼리 즉시 실행 | 서비스 전체 장애 및 데이터 유실 발생 |
| 사용 안 한 지 1시간 됨 | DROP COLUMN 쿼리 실행 | 아직 트래픽을 받는 구버전 앱이 있을 수 있어 위험 |
| 코드에서 제거 후 1주일 경과 | DROP COLUMN 쿼리 실행 | 아무도 참조하지 않음을 확인했으므로 안전함 |
2. 타입 변경 대신 '새로운 컬럼' 추가하기
컬럼의 타입을 바꾸는 가장 안전한 방법은 기존 컬럼을 `ALTER`하는 것이 아닙니다. 대신 원하는 타입을 가진 새로운 컬럼을 추가(`ADD`)하는 것입니다.
- 새로운 컬럼 생성 (예: `price_new` INT)
- 기존 컬럼의 데이터를 새로운 컬럼으로 복사 (예: `price` 문자열을 숫자로 변환하여 `price_new`에 저장)
- 애플리케이션이 두 컬럼을 모두 사용하거나, 새로운 컬럼만 사용하도록 변경 배포
- 문제가 없다면 나중에 예전 컬럼(`price`) 삭제 및 이름 변경
이 방법은 다소 번거로워 보일 수 있지만, 기존 데이터를 털끝 하나 건드리지 않기 때문에 언제든지 이전 상태로 롤백(Rollback)할 수 있다는 엄청난 장점이 있습니다.
안전한 마이그레이션의 마음가짐
파괴적인 변경을 할 때는 방어 운전을 하듯 보수적으로 접근해야 합니다. "이 쿼리를 실행했을 때 최악의 상황이 발생한다면 어떻게 복구할 것인가?"를 스스로에게 물어보는 습관이 대형 장애를 막습니다.
개념 퀴즈
퀴즈 답을 맞춰야 학습 완료가 됩니다.운영 데이터베이스에서 파괴적 변경(Destructive Change)을 피해야 하는 가장 큰 이유로 적절한 것은 무엇인가요?
3줄 요약
- 1운영 DB에서 DROP이나 ALTER 같은 파괴적 변경 쿼리는 매우 위험합니다.
- 2데이터 유실뿐만 아니라 테이블 락(Lock)으로 인한 서비스 중단이 발생할 수 있습니다.
- 3즉시 삭제하거나 변경하는 대신, 새 컬럼을 추가하고 데이터를 복사하는 우회로를 써야 안전합니다.