본문으로 건너뛰기

Oracle 26ai에서 19c로, 요구사항 변경에 따른 전환 검토와 실험 설계

· 약 8분
김성연
AI Research Engineer, Braincrew

Deep Connector를 구축하던 중 고객의 데이터베이스 버전 요구사항이 Oracle 26ai에서 19c로 바뀌었다. 기존 구현이 26ai의 네이티브 JSON을 사용하고 있었으므로, 변경 요청을 받았다고 접속 대상만 바꿀 수는 없었다. DDL, 저장과 조회 코드, 검색 인덱스, 이관 절차를 함께 검토해야 했다.

이 글은 전환 영향검토서와 성능 비교 쿼리 샘플을 함께 읽고 재구성한 기록이다. 자료에 남은 파일 규모 계측과 정적 검토, 용량 추정, 비교 시험 계획을 구분했다. Oracle 26ai와 19c의 비교 부하 시험 결과나 최종 운영 전환 승인을 보고하는 글은 아니다. 고객사, 실제 계정과 스키마 식별자, 내부 작업 날짜 및 배포 정보는 제외했다.

버전 선택과 전환 승인의 분리​

영향검토서는 외부 요구가 없다면 26ai를 유지하는 편이 변경 위험이 작다고 판단했다. 이미 26ai를 기준으로 구현한 시스템을 바꿀 때의 회귀 위험을 평가한 것이지, Oracle 19c 자체가 불안정하다는 결론은 아니었다. 고객의 요구사항이 바뀌면 검토의 초점도 달라진다. 19c에서 필요한 기능을 유지하려면 무엇을 고쳐야 하는지, 어떤 시험을 통과해야 운영에 사용할 수 있는지를 정해야 한다.

기존 26ai DDL에는 빈 스키마 적용과 내부 일관성 검증을 통과한 기록이 있었다. 그 기록은 19c 호환성이나 실제 부하에서의 응답시간을 보장하지 않는다. 요구사항으로 목표 버전이 정해지는 것과 시험 결과로 전환을 승인하는 것은 별도 판단이다.

계측한 파일 크기와 아직 모르는 DB 성능​

두 자료를 읽을 때 먼저 구분해야 할 것은 숫자의 출처였다.

구분자료에 남은 근거해석 가능한 범위
파일 기반 계측원본 행과 고유 코드 수, JSON 직렬화 크기와 분포입력 데이터의 구조와 논리적 크기
용량 추정같은 상품 구성과 문서 재사용률, unit별 metadata 복제를 가정한 환산가정이 유지될 때의 행 수와 JSON 원문량
정적 검토DDL, 애플리케이션 저장 경로, 비교 SQL의 대조시험 대상과 구현의 일치 여부
비교 시험 계획조회, 저장, 검색, LOB fetch별 SQL과 측정 절차앞으로 검증할 조건과 지표

파일 계측에서는 고유 상품 하나가 매핑 한 행과 같지 않다는 점이 드러났다. 문서가 검색용 unit으로 나뉘고 metadata가 unit마다 복제된다면 DB의 물리 행 수는 그만큼 늘어난다. 따라서 원본 건수만으로 용량이나 응답시간을 판단할 수 없다.

용량 추정에는 상품 구성과 문서 재사용률이 유지된다는 가정이 들어갔다. unit별 복제 시나리오도 전체 metadata를 각 unit에 저장한다는 보수적 가정이었다. 이 글에서는 고객 데이터의 정확한 건수와 용량을 공개하지 않으며, 다른 숫자로 바꿔 실측 예시처럼 제시하지도 않는다.

UTF-8 JSON 원문 크기를 UTF-16LE로 환산한 값 역시 실제 Oracle CLOB segment 크기는 아니다. 본문 CLOB, 리비전, 인덱스, 로그와 블록 여유 공간은 별도로 고려해야 한다. 자료에 따르면 파일을 직렬화해 크기를 재는 실험은 수행됐지만, 그 결과가 버전별 쿼리 속도를 뜻하지는 않는다.

JSON 저장 타입 변경과 애플리케이션 호환성​

이번 비교 대상은 Oracle RDB의 JSON 저장과 CLOB 본문 검색이다. 이 구성에서 임베딩 저장과 벡터 검색은 Qdrant가 담당하므로 Oracle 벡터 기능의 버전 비교는 범위에서 제외했다.

Oracle 26ai의 네이티브 JSON 타입은 OSON 바이너리 형식을 사용해 텍스트 JSON의 반복 파싱을 피한다. 19c 전환 기준안은 JSON을 CLOB에 저장하고 IS JSON 제약을 적용하는 방식이었다. Oracle 공식 문서는 LOB JSON 저장에 BLOB을 권장하지만, 영향검토서는 기존 CLOB 처리 코드의 재사용을 고려해 CLOB을 초기 후보로 두고 BLOB은 후속 비교 대상으로 남겼다. CLOB이 가장 빠르다고 확인해서 선택한 안은 아니었다.

변경 범위를 셀 때도 기준을 구분해야 했다. 검토 대상 DDL에는 JSON 컬럼이 29개였고, 이후 애플리케이션 코드에서 확인한 범위는 18개 테이블의 32개 컬럼이었다. 두 숫자는 서로 다른 기준의 목록이며, 변경 명세와 회귀 시험 대상은 실제 전환할 코드에 맞춰 다시 대조해야 한다.

DDL만 바꾸면 ORM의 타입 매핑이나 기동 시 보정 DDL에서 네이티브 JSON 정의가 다시 사용될 수 있다. 쓰기 직렬화, 읽기 역직렬화, 빈 객체와 빈 배열의 기본값, SQL NULL과 JSON null의 의미를 함께 확인해야 한다. 특히 RETURNING ... INTO로 CLOB을 돌려받는 경로는 자료에서도 별도 실측이 필요한 항목이었다. 쿼리 샘플은 이 호환성 확인용 INSERT를 일반 저장 경로와 구분해 제시했다.

grep 검색에서 나눠 볼 비용​

문서 grep은 metadata의 JSON 조건과 본문 CLOB의 정규식 검색을 함께 사용한다. 본문은 두 버전 모두 CLOB이고, 비교에서 주의할 변화는 metadata 저장 형식과 JSON 조건의 처리 비용이다. 반환 행 수가 적어도 조건을 평가한 후보 행 수까지 적다는 뜻은 아니다.

JSON 필터와 정규식의 비용을 고정된 배수로 곱해 응답시간을 예측해서는 안 된다. 실제 비용은 후보 행 수, 필터 선택도, 선택된 인덱스와 실행계획에 따라 확인해야 한다. 영향검토서가 인용한 벤더 벤치마크의 배수도 이 시스템의 26ai 대비 19c 성능 저하율로 옮겨 쓸 수 없다.

쿼리 샘플에는 JSON 조건이 없는 grep 대조군도 포함됐다. 다만 제시된 SQL끼리는 조인과 반환 컬럼에도 차이가 있어, 시간 차이를 전부 JSON 파싱 비용으로 해석하기 어렵다. 파싱 영향을 더 좁혀 비교하려면 조인, 반환 컬럼, 정렬과 바인드 조건을 맞추고 실제 스캔 행 수도 함께 기록해야 한다. 이는 샘플을 실행하기 전에 보완할 실험 조건이지, 파싱 병목을 확인한 결과가 아니다.

실제 저장 경로를 닮은 비교 시험​

성능 비교 쿼리 샘플에서 중요한 수정은 부분 갱신 SQL을 실제 저장 방식에 맞춘 것이었다. 애플리케이션은 최종 metadata 객체를 만든 뒤 전체 값을 다시 저장했으므로, JSON_MERGEPATCH만 비교하면 다른 동작을 시험하게 된다. 샘플은 이 부분 갱신을 제외하고 metadata 전체 저장과 본문을 함께 갱신하는 경로를 구분했다.

시험 축비교 조건확인할 차이
조회 범위특정 문서와 컬렉션 내 문서 미특정후보 행 수와 접근 경로
반환량한 행과 Bulk 조회정렬, 전송량과 LOB 읽기
검색 조건JSON 조건 유무, 고정 경로와 사용자 지정 키JSON 평가와 인덱스 사용
저장단건과 500행 단위 배치bind, 쓰기량과 왕복 비용
커밋배치마다 커밋과 전체 배치 후 커밋execute 시간과 commit 시간
응답 처리경량 컬럼과 본문 및 metadata 포함DB 실행 이후 fetch와 역직렬화

문서를 특정하지 않는 조회도 컬렉션 조건은 유지하도록 설계했다. 실제 API와 다른 전체 테이블 조회로 부하를 키우지 않기 위해서다. 컬렉션 범위 Bulk UPDATE는 실제 서비스 경로가 아닌 비교 전용 SQL이며, 성능시험 전용 DB에서 실행하고 매회 롤백하는 조건이다. 커밋 비용을 재는 시험은 운영 데이터가 없는 별도 시험 스키마에서 수행해야 한다.

500행 배치는 애플리케이션이 ORM에 전달하는 저장 단위를 반영한다. 시험 도구의 array binding이나 executemany가 실제 ORM의 SQL 생성과 네트워크 왕복을 그대로 재현한다는 뜻은 아니다. DB 단위 시험 뒤에 실제 드라이버와 ORM을 거치는 요청도 측정해야 한다.

인덱스 기준선과 최적화안의 분리​

DDL에 JSON Search Index가 없다는 사실만으로 실제 DB에도 없다고 단정할 수 없었다. 애플리케이션의 기동 보정 로직이 인덱스 생성을 시도하고 실패하면 일반 JSON 조건 조회로 폴백했기 때문이다. 시험 전에 실제 인덱스의 존재와 상태를 확인해야 하는 이유다.

먼저 같은 인덱스 조건에서 버전별 기준선을 측정하고, 함수 기반 인덱스를 추가한 최적화안은 별도 결과로 기록하도록 설계했다. 한쪽에만 인덱스를 추가하고 버전 차이라고 보고하면 개선 원인을 구분할 수 없다. 고정 JSON 경로는 함수 기반 인덱스의 후보가 되지만, 임의 metadata 키 전체를 미리 같은 방식으로 인덱싱하기는 어렵다. Oracle 공식 문서도 인덱스 이름이 실제 실행계획에 나타나는지 확인하도록 안내한다.

검색 인덱스는 읽기 지연만으로 평가할 수 없다. 동기화 방식에 따른 쓰기와 커밋 비용, 갱신한 데이터가 검색에 반영되는 지연도 함께 비교해야 한다.

DB 실행시간 이후까지 이어지는 측정​

시험 계획은 동일 데이터 스냅샷과 하드웨어, 문자셋, 통계, 커넥션 풀 및 동시성을 맞추는 것을 전제로 했다. 쿼리 샘플은 각 케이스를 3~5회 warm-up한 뒤 최소 30회 측정하고 평균과 P50, P95, P99를 기록하도록 제안했다. 이 반복 횟수는 실행 기록이 아니라 계획이며, 특히 P99를 안정적으로 판단하려면 충분한 표본과 반복 부하를 추가로 확보해야 한다.

측정은 DB가 첫 결과를 돌려준 시점에서 끝나지 않는다. CLOB을 끝까지 읽고 JSON을 역직렬화한 뒤 응답을 만들 때까지의 시간과 커넥션 점유시간을 기록해야 한다. DB CPU와 읽기량, 반환 바이트, 애플리케이션 CPU와 메모리를 함께 보면 지연이 늘어난 구간을 좁힐 수 있다.

영향검토서에는 읽기 API P95 증가를 26ai 대비 20% 이내로 제한하고, 검색 API P99 증가는 30% 이내로 제한하는 초기 제안이 있었다. 업로드와 파싱 처리량은 26ai의 90% 이상을 제안했다. 이 수치는 고객과 합의한 SLA도, 시험을 통과한 결과도 아니다. 실제 승인에는 성능 기준 합의와 함께 기능 정합성, 검색 최신성, 삭제 시 잠금, 이관시간과 롤백 검증이 필요하다.

개발 완료 이후의 전환 판단​

영향검토서는 개발 공수를 9~15영업일로 산정했지만, 전체 성능 시험과 운영 전환 리허설, DBA 반입 및 컷오버 일정은 별도로 분리했다. 개발 범위에 일부 실측 확인이 포함돼 있어도 전체 전환 승인에 필요한 검증을 대신하지는 않는다.

이관 계획의 expdp VERSION=19도 실행 성공을 뜻하지 않는다. 자료는 네이티브 JSON 컬럼 처리 여부를 시험 이관으로 확인하고, 필요하면 별도 직렬화 경로를 검토하도록 남겼다. 롤백 역시 접속 대상을 원래 DB로 되돌리는 것으로 끝나지 않는다. 19c에서 새로 발생한 쓰기를 어떻게 원본에 반영할지 정하지 않으면 복귀 과정에서 데이터가 유실될 수 있다.

이번 검토에서 확보한 것은 전환 성공의 증명이 아니라, 바뀐 요구사항에 맞춰 확인할 변경 범위와 시험 조건이었다. 파일 계측은 데이터 구조를 설명하고, 용량 추정은 준비할 시험 규모를 정하는 데 쓰이며, 비교 쿼리는 아직 모르는 성능을 확인하는 수단이다. 19c 채택 요구를 실제 운영 승인으로 이어가려면 그 사이에 남은 호환성, 부하, 이관과 복구 시험 결과가 필요하다.

References​