모든 글

어댑터·듀얼 라이트·플래그로 Oracle을 MySQL로 이관하기

호환 어댑터, 사전 배포, 듀얼 라이트, 검증된 스위치와 롤백으로 Oracle 레거시를 MySQL로 점진 이관합니다.

출처 및 AI 안내: 이 글은 제미니의 개발실무 유튜브를 기반으로 작성되었습니다. gpt-5.6-sol 모델을 사용해 생성·편집했습니다.

기억으로는 약 13년 된 Oracle DB와 IDC 장비를 빠르게 내려야 했다. 주변 코드는 오래된 MyBatis 쿼리가 많은 상태였고 API 서버는 이미 클라우드로 옮겨져 있었다. 데이터베이스 교체는 급했지만 서비스 전체를 같은 시점에 다시 설계할 이유는 없었다.

이관 중에는 프레임워크까지 현대화하지 않는다

비즈니스 서비스 로직과 리포지토리 시그니처는 그대로 두었다. 기존 계약 아래에 일대일로 대응하는 어댑터를 만들고 신규 MySQL 구현을 연결했다. 영속성 방식도 옛 코드와 가깝게 유지했다. MyBatis를 JPA로 바꾸는 일까지 묶으면 Oracle을 빨리 내리는 데 도움 없이 변경만 커지기 때문이다.

Oracle 전용 SQL은 바꿔야 했다. 함수 문법을 변환하고, 쿼리 안에 숨어 있던 시퀀스 동작은 MySQL용 별도 시퀀스 테이블을 포함한 명시적인 로직으로 풀었다. 차이는 신규 영속성 경로 안에 가둬 모든 서비스 호출부로 퍼지지 않게 했다.

첫 운영 배포는 동작을 바꾸지 않았다

어댑터와 신규 코드를 먼저 배포하되 플래그는 읽기와 쓰기가 계속 레거시 경로를 타게 두었다. 새 경로는 존재하지만 사용하지 않는 상태였으므로 라이브 서비스가 MySQL을 쓰지 않아도 며칠 안에 경계를 먼저 배포할 수 있었다.

그다음에는 플래그 조합을 단계적으로 시험했다. 읽기는 Oracle에 둔 채 두 저장소에 함께 쓸 수 있었다. 신규 데이터가 아직 조회에 쓰이지 않으므로 확인하고, 지우고, 다시 쌓아 테스트할 수 있었다. 레거시 읽기와 신규 쓰기의 의도한 상태를 테스트로 덮었고 부분 배포도 거의 매주 이어 갔다.

마지막 이관 PR에는 스위치만 남았다

과거 데이터 이동은 DB 담당자와 조율했다. 짧은 점검 시간을 쓸 수 있었지만, 필요한 코드는 점검 전에 이미 배포하고 검증한 상태였다. 마지막 PR은 마이그레이션 구현 전체가 아니라 좁은 true/false 설정만 바꿨다.

롤백도 같은 크기였다. 호환 경로가 이미 배포되어 있으므로 읽기 설정을 Oracle로 돌리면 됐다. 플래그 상태별 테스트, 단계적 전환과 되돌릴 수 있는 스위치가 마지막 변경을 작게 만들었다. 전환 뒤 작은 문제는 있었지만 롤백이 필요할 정도의 심각한 문제는 없었다.

MySQL이 안정된 뒤에는 레거시 DB 모듈, 미사용 리포지토리, 옛 분기와 이관 플래그를 지웠다. 기억으로는 어댑터가 남았고 나중에 제거할 수도 있다고 인수인계했다. 핵심은 배포의 순서다. 호환 경계를 만들고, 비활성 상태로 먼저 배포하고, 플래그 상태를 반복 검증한 뒤 전환을 작게 끝내고 필요 없어진 다리를 치운다.