코드는 변해도 이름은 남는다: 성장과 파괴를 구분하는 데이터의 윤리
Hatched by Jaeyeol Lee
Apr 24, 2026
6 min read
6 views
87%
우리는 왜 시스템을 망가뜨리는가
가장 위험한 변경은 보통 가장 사소해 보인다. 컬럼 하나 이름을 바꾸고, 필드 하나를 지우고, 의미를 조금만 수정했을 뿐인데 어느 날부터 결제 배치가 깨지고, 리포트 숫자가 맞지 않고, 오래된 클라이언트가 조용히 오동작한다. 문제는 단지 변경이 아니라, 성장과 파괴를 같은 것으로 취급한 태도다.
흥미로운 질문은 이것이다. 데이터 모델은 왜 코드보다 더 엄격하게 다뤄져야 할까? 코드도 버전이 바뀌고 리팩토링되는데, 왜 스키마는 더 보수적으로 취급해야 할까? 답은 간단하다. 코드 한 벌이 아니라, 이미 존재하는 여러 코드베이스가 그 데이터를 믿고 있기 때문이다. 개발 환경에서는 혼자 실험하지만, 운영 환경에서는 당신의 데이터가 곧 여러 시스템의 공용 언어가 된다.
여기서 진짜 긴장은 명확해진다. 우리는 흔히 스키마를 “설계도”처럼 생각하지만, 실제로 스키마는 관계의 계약서다. 그리고 계약서는 고치기 쉬워 보여도, 한 번 의미가 바뀌면 과거의 합의가 무너진다. 그래서 데이터 모델링의 핵심은 더 아름다운 구조를 만드는 일이 아니라, 변화가 누적되는 동안 의미를 지키는 일이다.
개발에서의 실험과 운영에서의 책임은 같은 일이 아니다
개발 머신에서는 모든 변경이 가볍게 느껴진다. 데이터도 얼마 없고, 사용자도 없고, 실패해도 손실이 적다. 그래서 우리는 자연스럽게 “안 되면 지우면 되지”라는 감각을 갖게 된다. 하지만 운영은 다르다. 운영에서는 한 번 지운 이름이, 한 번 바꾼 의미가, 이미 누군가의 코드에 박혀 있을 수 있다.
이 차이를 무시하면 가장 흔한 오류가 발생한다. 즉, 성장을 파괴처럼 다루거나 파괴를 성장처럼 다루는 것이다. 새로운 필드를 추가하는 것은 성장이다. 기존 필드를 삭제하거나 의미를 바꾸는 것은 파괴다. 둘 다 “변경”이라는 점에서는 같지만, 시스템이 받는 충격은 전혀 다르다.
예를 들어 보자. user.name 필드를 user.full_name으로 바꾸고 싶다고 하자. 개발자 입장에서는 더 명확해 보일 수 있다. 하지만 운영에서는 단순한 개명처럼 보이는 이 행동이, 기존 보고서, 검색 인덱스, API 클라이언트, 데이터 웨어하우스 파이프라인에 연쇄적인 비용을 만든다. 더 나쁜 것은 그 비용이 즉시 보이지 않는다는 점이다. 부서진 시스템은 대개 조용히 부서진다.
운영에서의 스키마는 단지 구조가 아니다. 그것은 과거와 현재의 프로그램들이 동시에 읽는 장기 기억이다.
이 관점이 중요하다. 스키마를 설계하는 일은 미래의 아름다움을 추구하는 일이 아니라, 과거의 의미를 보존하면서 미래의 가능성을 여는 일이다. 이 두 목표는 자주 충돌하지만, 좋은 데이터 설계는 이 충돌을 정면으로 다룬다.
이름은 단순한 표식이 아니라 의미의 그릇이다
많은 팀이 스키마 변경을 기술 문제로만 본다. 하지만 실제로는 언어 문제에 더 가깝다. 어떤 이름이 무엇을 뜻하는지, 그 이름이 어떤 맥락에서 사용되는지, 누가 그 의미를 신뢰하고 있는지가 핵심이다. 이름을 바꾸는 것은 표지를 교체하는 것이 아니라, 도시의 약속을 다시 쓰는 일이다.
여기서 가장 강력한 원칙은 의외로 단순하다. 이름은 제거하지 말라. 더 정확히 말하면, 이미 배포된 이름의 의미를 뒤집지 말라. 어떤 이름이 잘못 붙었다고 느껴질 수 있다. 하지만 그 이름을 새 의미로 재사용하는 순간, 당신은 이름을 고친 것이 아니라 의미를 배신한 것이다.
이 원칙은 리팩토링의 본질과도 연결된다. 리팩토링의 목적 중 하나는 더 나은 이름을 채택하는 것이다. 그러나 그 과정에서 진짜 중요한 것은 과거의 이름을 지우는 것이 아니라, 새 이름을 추가하고 오래된 이름을 점진적으로 퇴장시키는 것이다. 그래서 deprecated 표시는 단순한 메모가 아니다. 그것은 시스템이 자신의 기억을 관리하는 방법이다.
가령 status라는 필드가 처음에는 “활성, 비활성”만 뜻했는데, 나중에는 “활성, 비활성, 보류, 삭제 예약”을 담게 되었다고 해 보자. 이때 기존 status를 새 의미로 억지로 확장하면, 오래된 코드와 새 코드가 같은 단어를 두고 서로 다른 세계를 살게 된다. 반대로 status_v2나 새로운 네임스페이스를 도입하면, 두 의미는 공존할 수 있다. 혼란을 줄이는 방법은 더 적은 이름이 아니라 더 명확한 경계다.
이 지점에서 네임스페이스의 가치가 드러난다. 같은 로컬 이름도 서로 다른 네임스페이스에서 안전하게 공존할 수 있다. 즉, 이름 충돌을 줄이는 것은 단순한 문법 편의가 아니라, 의미 충돌을 흡수하는 방화벽을 세우는 일이다. 규모가 커질수록 이것은 선택이 아니라 생존 전략이 된다.
데이터베이스를 진짜 저장소로 대할 때 생기는 일
많은 시스템에서 스키마는 코드 저장소에 텍스트 파일로 남아 있다. 편리해 보인다. 리뷰도 쉽고, diff도 보인다. 하지만 이 방식은 중요한 사실을 숨긴다. 스키마의 실제 집은 데이터베이스라는 점이다. 데이터베이스는 단지 데이터를 담는 통이 아니라, 검증, 구조, 질의, 트랜잭션, 이력까지 함께 제공하는 살아 있는 환경이다.
이 차이는 실무에서 엄청나다. 텍스트 파일에 적힌 스키마는 선언일 뿐이지만, 데이터베이스 안의 스키마는 실행 가능한 기억이다. 즉, 무엇이 유효한지, 언제 바뀌었는지, 어떤 트랜잭션으로 들어왔는지를 실제로 추적할 수 있다. 재현 가능성과 감사 가능성이 단순히 편의가 아니라 기본값이 되는 이유가 여기에 있다.
이것을 건축에 비유하면 이해가 쉽다. 설계도는 중요한 문서지만, 건물의 실제 구조는 현장에 있다. 벽을 어디에 세웠는지, 하중이 어떻게 분산되는지, 배선이 어디를 지나가는지는 현장에서만 진짜 의미를 가진다. 스키마도 마찬가지다. 파일에 적힌 선언만으로는 충분하지 않고, 실제 운영 환경에서 검증되고 축적되는 구조여야 한다.
이 관점에서 데이터베이스는 단순한 저장소가 아니라, 진실의 운영 체제에 가깝다. 어떤 필드가 언제 생겼고, 어떤 제약이 붙었고, 어떤 값들이 승인되었는지, 그것은 버전 관리 시스템보다 데이터베이스가 더 잘 말해줄 수 있다. 그래서 스키마 성장은 “소스 코드 관리”보다 “의미의 거주지 관리”로 이해하는 편이 정확하다.
성장만 허용하는 시스템이 더 강하다
처음 들으면 비정상적으로 들릴 수 있다. 왜 삭제를 금지해야 할까? 왜 더 단순한 구조로 정리하지 못할까? 하지만 이 제약은 보수주의가 아니라, 복원력을 위한 설계다. 성장만 허용한다는 것은 기존 의미를 파괴하지 않고도 시스템을 진화시킬 수 있다는 뜻이다.
이때 핵심은 “변하지 말라”가 아니다. 오히려 반대다. 더 많이 바꿀 수 있으려면, 더 적게 부술 수 있어야 한다. 새 이름을 추가하고, 새 필드를 만들고, 새 네임스페이스를 열고, 기존 요소를 폐기 표기만 한 채 남겨 두는 방식은 변화의 속도를 늦추지 않는다. 다만 변화의 비용을 미래로 미루지 않고, 현재의 변경이 과거를 파괴하지 않게 만든다.
이것은 도시 계획과 비슷하다. 오래된 길을 당장 없애고 새 도로를 깔고 싶을 수 있다. 하지만 그 길을 매일 쓰는 사람들이 있다면, 현명한 도시는 새 도로를 먼저 만들고, 안내를 바꾸고, 오래된 길을 점진적으로 비중 있게 줄인다. 스키마도 같다. 새 경로를 추가한 뒤 오래된 경로를 천천히 닫는 것이, 결국 가장 빠른 길이다.
이 원리를 실천하는 팀은 코드 리뷰의 기준도 달라진다. 질문은 더 이상 “이걸 더 간결하게 줄일 수 있는가?”가 아니라, “이 변경이 기존 의미를 얼마나 보존하는가?”가 된다. 간결함은 목적이 아니고, 의미의 연속성이 목적이 된다. 이 전환이 이루어지면 데이터 모델링의 미학 자체가 바뀐다.
스키마 성장의 세 가지 렌즈: 이름, 경계, 시간
스키마를 잘 다루는 팀은 사실 세 가지 렌즈를 함께 쓴다. 첫째는 이름이다. 무엇을 무엇이라 부르는가. 둘째는 경계다. 같은 이름이 어느 맥락에서 같은 의미를 유지하는가. 셋째는 시간이다. 과거의 의미가 어떻게 현재와 공존하는가.
이 세 렌즈를 함께 보면, 스키마 진화는 단순한 구조 변경이 아니라 의미의 기하학이 된다. 이름이 같아도 경계가 다르면 안전할 수 있고, 경계가 같아도 시간이 바뀌면 위험해질 수 있다. 예를 들어 price라는 필드는 현재는 원화 금액을 뜻하지만, 과거엔 세전 금액이었을 수 있다. 이름은 같아도 시간에 따라 의미가 다르다. 이럴 때 필요한 것은 이름을 바꾸는 것만이 아니라, 의미의 버전 관리다.
이 모델은 실무에서 강력한 질문을 던지게 한다.
- 이 변경은 새 의미를 추가하는가, 기존 의미를 대체하는가?
- 기존 코드가 여전히 읽고 있는 이름은 무엇인가?
- 시간이 지나도 해석이 흔들리지 않도록 무엇을 남겨야 하는가?
이 질문들은 결국 한 가지를 향한다. 데이터는 저장된 사실이 아니라, 합의된 의미의 기록이라는 점이다. 합의를 바꾸려면 기술적으로만이 아니라 언어적으로, 조직적으로, 시간적으로도 설계해야 한다.
Key Takeaways
- 성장과 파괴를 분리하라. 새 필드와 새 이름을 추가하는 일은 기존 의미를 바꾸는 일과 완전히 다르다.
- 이름을 삭제하지 말고, 폐기 상태로 남겨라. 오래된 이름은 기술 부채가 아니라 시스템의 역사다.
- 네임스페이스를 적극적으로 사용하라. 같은 로컬 이름이 다른 맥락에서 안전하게 공존할 수 있어야 한다.
- 스키마를 파일이 아니라 데이터베이스의 실제 구조로 생각하라. 검증, 이력, 재현 가능성은 운영 환경에서 더 강력해진다.
- 변경의 기준을 간결함이 아니라 의미의 연속성으로 바꿔라. 더 적게 부수는 시스템이 더 많이 진화한다.
결론: 좋은 시스템은 기억을 지우지 않는다
우리는 종종 더 나은 시스템이란 더 깔끔한 시스템이라고 믿는다. 하지만 운영에서 진짜 좋은 시스템은 깔끔함보다 기억력이 좋다. 무엇이 언제 왜 추가되었는지 기억하고, 오래된 의미를 함부로 지우지 않으며, 새로운 의미를 안전하게 덧붙일 줄 안다.
결국 스키마 설계는 구조를 만드는 일이 아니라 의미를 오래 살게 하는 일이다. 이름을 고치는 것보다 중요한 것은, 그 이름을 믿고 살아온 모든 코드와 사람에게 배신하지 않는 것이다. 그래서 가장 강한 데이터베이스는 가장 많은 것을 지우는 데이터베이스가 아니라, 가장 적게 파괴하면서 가장 많이 성장하는 데이터베이스다.
다음에 스키마를 바꾸고 싶을 때 이렇게 물어보자. “무엇을 더 좋게 만들 수 있을까?”가 아니라, “무엇을 남겨야 이 시스템의 과거와 미래가 동시에 살아남을까?” 그 질문을 던지는 순간, 당신은 단순한 변경 관리자가 아니라, 의미의 보존자가 된다.
Sources
Hatch New Ideas with Glasp AI 🐣
Glasp AI allows you to hatch new ideas based on your curated content. Let's curate and create with Glasp AI :)
Start Hatching 🐣