서비스 간 데이터 마이그레이션: 전략, 위험 및 trade-offs

발행: (2026년 1월 19일 오전 06:37 GMT+9)
14 min read
원문: Dev.to

Source: Dev.to

배경

최근에 나는 한 작업(task) 중에 두 서비스 간에 수십만 건의 감사 로그를 마이그레이션해야 했습니다! 데이터 마이그레이션을 처음 해보는 것이었고, 특히 이런 규모라 더 많은 것을 배웠기에 이 글에 모두 기록하기로 했습니다.

기본적으로 데이터 마이그레이션은 특정 데이터베이스, 스프레드시트 또는 다른 형식에 저장된 정보를 가져와서, 대상 서비스가 올바르게 사용할 수 있도록 모델과 규칙에 맞게 변환하는 작업을 말합니다.

Migração de Dados

마이그레이션 동기

  • 레거시 데이터가 새로운 서비스로 옮겨져야 할 때.
  • 서로 다른 시스템이 책임을 공유하게 되면서 일관된 데이터 교차점이 필요할 때.
  • 사전 계획을 통해 분석 및 실행 시간을 충분히 확보할 수 있을 때.
  • 고객 요청, 부서 요구 또는 예상치 못한 운영상의 필요와 같은 긴급한 요구가 있을 때.

마이그레이션 결정은 제품 팀이나 엔지니어링 팀 모두에서 나올 수 있습니다. 그럼에도 엔지니어링 팀이 기술적 타당성을 평가하고 최종 결정을 내리는 것이 책임입니다! 이 타당성은 우리가 보유한 데이터에 대한 분석에 직접적으로 달려 있습니다.

예를 들어, 요구가 제품 팀에서 왔을 때는 엔지니어링이 복잡성, 위험 및 비용을 조사할 여지가 더 큽니다. 하지만 “마이그레이션 할 수 있다, 내가 해결한다”는 식의 일방적인 답변으로는 충분하지 않습니다. 어떤 약속을 하기 전에 데이터의 볼륨, 구조 및 복잡성을 매우 자세히 분석하는 것이 중요합니다.

Análise de Viabilidade

명확한 예시: 15건의 레코드를 마이그레이션하기 위해 두 스프린트 동안 두 명의 개발자를 정지시키는 것이 가치가 있을까요? 대부분의 경우 아닙니다. 엔지니어링 비용이 제품에 미치는 영향에 비해 너무 클 수 있습니다.

물론 타당성은 숫자만으로 판단되지 않습니다. 제품의 상황도 중요합니다. 결정을 돕는 질문들:

  • 어떤 종류의 데이터를 마이그레이션하고 있나요?
  • 데이터가 단순한가, 아니면 재귀적인 구조를 가지고 있나요?
  • 레코드 간에 의존성이 있나요?
  • 중간 상태, 히스토리 또는 비즈니스 규칙이 해당 데이터에 결합되어 있나요?

이 모든 요소가 직접적으로 마이그레이션 여부에 영향을 미칩니다.

마이그레이션 단계

마이그레이션이 실행 가능하다고 판단될 때, 해결해야 할 문제들의 집합은 보통 세 가지 큰 단계로 나뉩니다:

  1. 추출 – 데이터를 어떻게 가져올 것인가?
  2. 변환 – 이 데이터를 기대하는 형식에 맞게 어떻게 조정할 것인가?
  3. 로드 – 변환된 데이터를 대상 서비스에 어떻게 전송할 것인가?

이러한 맥락에서 저는 ETL에 대해 배우게 되었는데, 이는 바로 이러한 프로세스를 조직하고 구조화하기 위해 고안된 접근 방식입니다 (축하합니다, 여러분도 ETL이 무엇인지 배웠네요! :))

ETL

그럼에도 불구하고 강조하고 싶은 점은 ETL이 만능 해결책은 아니라는 것입니다. 많은 경우에 마이그레이션 전용 애플리케이션을 만드는 것이 불필요한 복잡성을 초래할 수 있습니다. 구현에 앞서 마이그레이션의 실제 가능성을 검토하고, 원본 데이터 형식, 변환 작업의 난이도, 그리고 해당 솔루션을 유지하는 비용을 파악하는 것이 필수적입니다.

일반적으로 ETL은 마이그레이션을 여러 번 실행하거나 향후 재사용해야 할 때 의미가 있습니다. 일회성 마이그레이션의 경우, 보다 간단하고 안전한 솔루션이 충분히 적합할 수 있습니다.

Source:

전략

작은 마이그레이션

작은 마이그레이션을 다룰 때는 보통 간단한 솔루션을 선택합니다. 특히 Jupyter Notebook을 많이 사용하는데, 원본 데이터가 스프레드시트나 작은 데이터베이스에 있을 경우에 특히 유용합니다. 이런 상황에서는 일회성 작업을 수행하기 위해 전체 애플리케이션을 구축할 필요성을 크게 느끼지 못합니다.

노트북을 만드는 것은 비교적 간단합니다: .ipynb 확장자를 가진 파일 하나와 로컬에 설정된 커널만 있으면 됩니다. 상황에 따라 Kotlin, Python, Deno 등 다양한 옵션을 사용할 수 있습니다. 여기서 큰 장점은 데이터를 빠르게 탐색하고, 변환을 테스트하며, 큰 어려움 없이 반복 작업을 할 수 있다는 점입니다.

Jupyter Notebook

복잡한 마이그레이션

복잡한 마이그레이션의 경우에는 터미널에서 실행되는 로컬 애플리케이션—간단하지만 제어 가능한 CLI을 만드는 것을 선호합니다. 이러한 접근 방식은 다음과 같은 장점을 제공합니다:

  • 실행 예측 가능성 및 제어성 향상
  • 대용량 데이터 처리 용이
  • 버전 관리 및 자동화 가능 (예: CI/CD 스크립트)

마이그레이션 CLI의 전형적인 구조는 다음과 같습니다:

  1. 인자 파서 – 시작/종료 날짜, 필터, “dry‑run” 모드 등 파라미터를 받음
  2. 추출 레이어 – 데이터베이스, API 또는 파일에 대한 커넥터
  3. 변환 레이어 – 레코드를 받아 원하는 형식으로 반환하는 순수 함수들
  4. 로드 레이어 – 배치 삽입, 파일 쓰기, 대상 API 호출 등
  5. 로깅 및 메트릭 – 감사 및 진행 상황 모니터링을 위한 로깅 및 메트릭 수집

결론 (첫 번째)

  • 마이그레이션을 시작하기 전에 가능성을 평가하는 것이 필수적입니다 – 볼륨, 복잡성, 의존성 및 엔지니어링 비용을 고려하세요.
  • ETL은 강력한 도구이지만 재사용이나 반복 실행이 필요할 때만 채택해야 합니다.
  • 소규모 및 일회성 마이그레이션의 경우 Jupyter Notebook이나 ad‑hoc 스크립트가 더 민첩합니다.
  • 대규모 마이그레이션이나 세밀한 제어가 필요한 경우 CLI 또는 작은 전용 애플리케이션이 가장 안전한 선택입니다.
[![Imagem da migração](https://media2.dev.to/dynamic/image/width=800,height=,fit=scale-down,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8w59uslh300rzxxop5e.png)](https://media2.dev.to/dynamic/image/width=800,height=,fit=scale-down,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8w59uslh300rzxxop5e.png)

여기서 가장 중요한 고려사항은 롤백 전략을 갖는 것입니다. 마이그레이션이 처음부터 완벽하게 실행된다고 가정할 수 없습니다. 가능하면 staging 환경에서 테스트한 후 프로덕션에 적용하고, 롤아웃을 팀과 충분히 조율하는 것이 좋습니다.

데이터를 로드하는 방식도 차이를 만듭니다. 경우에 따라서는 데이터베이스에 직접 삽입하는 것으로 충분할 수 있습니다. 다른 경우에는 API를 사용하거나 큐에 이벤트를 게시하는 것이 더 안전합니다. 특히 대용량을 다루고 비동기적으로 처리하려는 경우에 그렇습니다.

결국 ETL의 형태보다는 최종 목표가 더 중요합니다. 노트북, CLI, 혹은 간단한 스크립트 등 어떤 형태든 안전하고 예측 가능한 방식으로 추출, 변환, 적재 요구를 충족한다면 괜찮습니다.

실용적인 도전 과제

누락되거나 일관성 없는 데이터

실제 마이그레이션에서는 불완전하거나 일관성이 없거나 삭제된 것으로 표시된 데이터(예: soft delete)를 많이 마주합니다. 이러한 시나리오는 레코드를 무시하거나 기본값을 채우거나 알 수 없는 데이터를 표시하는 등 명시적으로 처리해야 합니다.

데이터 보강

필요한 모든 정보가 한 곳에 있는 경우는 드뭅니다. 종종 다른 데이터베이스나 서비스/API에 “조회”하여 누락된 데이터를 찾아야 합니다. 이 점을 초기에 파악해 두는 것이 좋은데, 솔루션의 복잡성을 높이기 때문입니다.

기술적 트레이드오프

  • 속도 vs 정확성 – 마이그레이션이 긴급할 때, 전달을 손상시키지 않으면서 데이터 불일치를 어느 정도까지 허용할지 결정해야 합니다.
  • Jupyter Notebook vs CLI – 작은 마이그레이션의 경우, 노트북이 문제를 해결하고 크게 가속합니다! 하지만 노트북은 빠르게 커져 가독성과 유지보수가 어려워질 수 있습니다. 이런 경우에는 CLI를 채택하는 것이 더 가치 있습니다.
  • 전체 마이그레이션 vs 핵심만 마이그레이션 – 모든 데이터가 마이그레이션될 필요는 없습니다. 어떤 데이터를 보존하고 어떤 데이터를 의식적으로 폐기할지 제품 팀과 정렬하는 것이 중요합니다.
  • 한 번에 전체 처리 vs 배치 처리 – 레코드를 batches 단위로 처리하고 각 배치 후 결과를 검증할 것을 권장합니다. 이 접근법은 한 번에 전체를 처리하고 데이터 처리 중 작은 오류 때문에 전체를 다시 해야 하는 상황보다 훨씬 좋습니다.

결론 (두 번째)

아무도 데이터 마이그레이션이 프로덕션에서 이루어졌다는 것을 눈치채지 못했다면, 아마도 좋은 신호였을 것입니다. 결국 모든 것은 맥락, 균형 및 트레이드‑오프에 달려 있으며, 무엇을 제공할 수 있는지에 대해 팀을 정렬된 상태로 유지하는 것입니다.

Back to Blog

관련 글

더 보기 »

Node.js 및 Express.js를 활용한 API 설계 모범 사례

소개: 대부분의 API가 규모를 확장하기 전에 실패하는 이유 🚨 오늘 작동하는 API를 만들 수 있지만… 내일은 여전히 ​​깨진 시스템을 구축하고 있을 수 있습니다. 많은 API가 실패하는 이유는…

2015년처럼 API를 작성하지 마세요

우리는 2025년에 살고 있으며, 많은 코드베이스가 여전히 API를 단순히 “JSON을 반환하는 엔드포인트”로만 취급합니다. API 설계가 기본 CRUD 라우트를 넘어 발전하지 않았다면, 당신은 sacr…