오라클과 MS SQL 작성 시 꼭 지킬 실무 원칙

오라클과 MS SQL 작성 시 꼭 지킬 실무 원칙 관련 이미지
Photo by Pexels via Pixabay

오라클과 Microsoft SQL Server는 기업 업무에서 널리 쓰이는 관계형 데이터베이스입니다. 두 제품 모두 SQL을 사용하지만 페이징, 날짜 처리, 문자열 결합, 자동 증가 값, 잠금 방식에 차이가 있습니다. 한 데이터베이스에서 실행된 문장을 이름만 바꿔 다른 곳에 적용하면 오류가 나거나 더 위험하게는 결과가 조용히 달라질 수 있습니다. 실무 SQL의 목표는 단순히 실행되는 문장이 아니라 정확한 결과를 예측 가능한 성능으로 반환하고 동시 요청에서도 데이터 무결성을 지키는 것입니다.

SELECT 별표보다 필요한 열을 명시하기

SELECT *는 빠르게 확인할 때 편하지만 운영 코드에서는 스키마 변경에 취약하고 필요하지 않은 대용량 열까지 전송할 수 있습니다. 필요한 열과 별칭을 명시하면 응답 구조가 분명해지고 네트워크와 메모리 사용량도 줄일 수 있습니다. 조인할 때는 모든 열에 테이블 별칭을 붙여 같은 이름의 열이 추가돼도 모호해지지 않게 합니다.

NULL은 빈 문자열이나 0이 아니다

NULL은 값이 없거나 알 수 없음을 나타내므로 = NULL로 비교할 수 없습니다. IS NULLIS NOT NULL을 사용해야 합니다. 오라클은 일반적인 문자 열에서 빈 문자열을 NULL처럼 다루는 반면 SQL Server는 빈 문자열과 NULL을 구분합니다. 두 제품을 함께 지원한다면 애플리케이션 입력 단계에서 빈 값 정책을 명확히 하고 데이터베이스별 암묵적 동작에 기대지 않아야 합니다.

오라클의 NVL과 SQL Server의 ISNULL은 비슷해 보이지만 반환 자료형 결정 규칙이 다를 수 있습니다. 이식성을 높이려면 표준 SQL의 COALESCE를 우선 고려하되, 서로 다른 자료형을 섞을 때는 명시적인 CAST로 결과형을 고정합니다.

날짜와 시간은 범위 조건으로 조회하기

날짜 열에 문자열을 직접 비교하면 세션의 날짜 형식 설정에 따라 결과가 달라질 수 있습니다. 오라클은 TO_DATE 또는 날짜 리터럴을, SQL Server는 명확한 ISO 형식이나 CONVERT를 사용합니다. 특정 하루를 조회할 때 열을 함수로 감싸기보다 시작 시각 이상, 다음 날 시작 시각 미만의 반열린 구간을 사용하면 인덱스를 활용하기 쉽습니다.

안전한 날짜 조회 원칙

  • 애플리케이션에서는 문자열 대신 날짜 자료형의 바인드 변수를 전달합니다.
  • 저장 시간대와 화면 표시 시간대를 분리합니다.
  • 밀리초와 더 높은 정밀도를 포함할 가능성을 고려합니다.
  • 열에 함수 적용이 필요하면 함수 기반 인덱스나 계산 열을 검토합니다.

바인드 변수로 보안과 성능을 함께 지키기

사용자 입력을 SQL 문자열에 이어 붙이면 SQL 인젝션 위험이 생깁니다. 값은 반드시 드라이버가 제공하는 매개변수 바인딩으로 전달합니다. 오라클과 SQL Server 드라이버는 자리표시자 문법이 다를 수 있으므로 프레임워크의 매개변수 API를 따라야 합니다. 테이블명과 정렬 열처럼 바인딩할 수 없는 식별자는 허용 목록에서만 선택합니다.

바인드 변수는 실행 계획 재사용에도 도움이 되지만 모든 값 분포에서 같은 계획이 최적인 것은 아닙니다. 특정 값에 데이터가 몰린 열에서는 오라클의 바인드 피킹이나 SQL Server의 매개변수 스니핑으로 성능 편차가 생길 수 있습니다. 무조건 힌트를 추가하기 전에 통계 정보, 실제 실행 계획, 입력값별 행 수를 확인해야 합니다.

페이징에는 안정적인 정렬이 필요하다

오라클의 최신 버전과 SQL Server는 OFFSET과 FETCH를 지원하지만 정렬 기준이 고유하지 않으면 페이지 사이에서 행이 중복되거나 사라질 수 있습니다. 생성 시각으로 정렬한다면 기본키를 두 번째 정렬 조건으로 추가합니다. 뒤쪽 페이지로 갈수록 OFFSET 비용이 커지는 서비스에서는 마지막으로 본 정렬 키를 조건에 넣는 키셋 페이징을 고려합니다.

핵심 원칙: ORDER BY가 없는 결과의 순서는 보장되지 않으며, 화면에서 우연히 같은 순서로 보였다는 사실은 계약이 아닙니다.

조인과 인덱스는 실행 계획으로 검증하기

인덱스는 검색을 빠르게 만들지만 INSERT와 UPDATE 비용, 저장 공간을 늘립니다. WHERE, JOIN, ORDER BY에서 자주 함께 사용하는 열과 선택도를 기준으로 복합 인덱스를 설계합니다. 복합 인덱스는 열 순서가 중요하며 모든 단일 열에 인덱스를 만드는 방식은 좋지 않습니다. 오라클의 EXPLAIN PLAN과 실제 실행 통계, SQL Server의 Actual Execution Plan을 확인해 추정 행 수와 실제 행 수의 차이를 살펴봅니다.

함수로 열을 감싸거나 자료형이 다른 열을 비교하면 암묵적 변환 때문에 인덱스를 사용하지 못할 수 있습니다. 숫자 열과 문자 매개변수를 비교하지 말고 애플리케이션에서 정확한 자료형을 전달합니다. 실행 계획의 테이블 스캔 자체가 항상 나쁜 것은 아닙니다. 대부분의 행을 읽는다면 전체 스캔이 인덱스보다 효율적일 수 있습니다.

트랜잭션을 짧고 명확하게 유지하기

여러 행을 수정할 때는 업무 단위로 트랜잭션을 묶고, 예외가 발생하면 롤백해야 합니다. 사용자 입력을 기다리거나 외부 API를 호출하는 동안 데이터베이스 트랜잭션을 열어 두면 잠금이 길어집니다. 두 세션이 서로 다른 순서로 자원을 잠그면 교착 상태가 생길 수 있으므로 테이블과 행에 접근하는 순서를 통일하고 실패 시 제한적으로 재시도합니다.

DB 연동 테스트 체크리스트

  1. NULL, 빈 문자열, 0을 각각 입력해 결과를 확인합니다.
  2. 날짜 경계와 시간대 변환을 테스트합니다.
  3. 동일한 정렬값이 많은 데이터로 페이징을 검증합니다.
  4. 소량과 대량 데이터에서 실제 실행 계획을 비교합니다.
  5. 동시 수정과 교착 상태 처리 방식을 시험합니다.
  6. 매개변수 바인딩이 모든 입력 경로에 적용됐는지 확인합니다.
  7. 마이그레이션 전 두 DB의 함수와 자료형 차이를 목록화합니다.

오라클과 MS SQL의 차이는 함수 이름 이상의 문제입니다. NULL 의미, 자료형 변환, 실행 계획, 잠금과 드라이버 동작까지 함께 살펴야 합니다. 공통 SQL을 억지로 늘리기보다 핵심 업무 규칙을 테스트로 고정하고 데이터베이스별 구현 차이를 명시적으로 관리하는 편이 안전합니다.

한 줄 요약: 오라클과 MS SQL 실무에서는 바인드 변수, 명확한 자료형, 안정적인 정렬, 짧은 트랜잭션을 실행 계획과 테스트로 검증해야 합니다.