Oracle ORA-06512 오류 원인과 해결 방법 완벽 가이드

ORA-06512
2026년 08월 29일 | DBMS Error 가이드

이 글에서 다루는 내용

ORA-06512 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.

ORA-06512 at string line number 는?

ORA-06512는 Oracle PL/SQL 실행 중 런타임 오류가 발생했을 때, 해당 오류가 어느 위치(프로그램 단위 및 줄 번호)에서 발생했는지를 추적(traceback)하기 위해 Oracle이 자동으로 스택에 추가하는 보조 메시지입니다. 즉, ORA-06512 자체가 독립적인 오류를 나타내는 것이 아니라, 오류의 근본 원인이 된 다른 ORA 에러(예: ORA-01403, ORA-20001 등)와 함께 콜 스택 정보를 제공하는 역할을 합니다. 실무에서는 대부분 RAISE 문이나 RAISE_APPLICATION_ERROR, 혹은 예외 처리 미흡으로 인해 상위 블록으로 예외가 전파될 때 이 메시지가 동반됩니다.


주요 발생 원인

1. RAISE_APPLICATION_ERROR 또는 RAISE를 통한 사용자 정의 예외 발생

개발자가 비즈니스 로직 검증을 위해 RAISE_APPLICATION_ERROR(-20001, '메시지') 또는 RAISE를 명시적으로 호출할 때, Oracle은 ORA-06512와 함께 해당 줄 번호를 스택에 쌓습니다. 프로시저 → 함수 → 패키지 등 여러 단계의 호출 체인이 있을 경우 각 레이어마다 ORA-06512가 반복 출력되어 오류 추적이 복잡해 보일 수 있습니다.

2. 처리되지 않은 런타임 예외(Unhandled Runtime Exception)

NO_DATA_FOUND, TOO_MANY_ROWS, ZERO_DIVIDE 등 Oracle 내장 예외가 발생했음에도 불구하고 해당 블록에 적절한 EXCEPTION 핸들러가 없을 때, 예외는 상위 호출자로 전파되면서 각 전파 단계에서 ORA-06512 메시지가 누적됩니다. 특히 중첩 프로시저 구조에서 예외 핸들러를 가장 내부 블록에만 배치하거나, 아예 생략한 경우 실무에서 빈번하게 발생합니다.

3. 잘못된 데이터 타입 변환 또는 제약 조건 위반

PL/SQL 내부에서 DML(INSERT, UPDATE 등)을 수행할 때 NOT NULL 제약, UNIQUE 제약, CHECK 제약 등을 위반하거나, 숫자형 컬럼에 문자를 삽입하는 등의 묵시적 변환 오류가 발생하면 SQL 엔진이 ORA 에러를 던지고, PL/SQL 엔진은 이를 ORA-06512와 함께 호출 스택으로 전달합니다. 이 경우 근본 원인 에러(예: ORA-00001 unique constraint violated)를 함께 확인해야 합니다.


해결 방법

원인 1: 사용자 정의 예외 처리

오류 메시지의 스택을 위에서부터 순서대로 읽어 실제 발생 지점(가장 마지막 ORA-06512 줄)을 확인한 뒤, 해당 코드를 점검합니다.

-- 문제가 되는 코드 예시
CREATE OR REPLACE PROCEDURE check_salary(p_emp_id IN NUMBER) IS
  v_salary NUMBER;
BEGIN
  SELECT salary INTO v_salary FROM employees WHERE employee_id = p_emp_id;

  IF v_salary < 0 THEN
    -- 이 줄에서 ORA-06512 발생
    RAISE_APPLICATION_ERROR(-20001, '급여는 음수일 수 없습니다: ' || p_emp_id);
  END IF;
END;
/

-- 호출부에서 예외를 포착하는 올바른 처리 방법
BEGIN
  check_salary(100);
EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('오류 코드: ' || SQLCODE);
    DBMS_OUTPUT.PUT_LINE('오류 메시지: ' || SQLERRM);
    -- 필요 시 로그 테이블에 기록
    INSERT INTO error_log (err_code, err_msg, log_date)
    VALUES (SQLCODE, SQLERRM, SYSDATE);
    COMMIT;
END;
/

원인 2: 처리되지 않은 런타임 예외 처리

모든 PL/SQL 블록에 EXCEPTION 섹션을 추가하고, 예상 가능한 예외를 명시적으로 처리합니다.

CREATE OR REPLACE PROCEDURE get_employee_info(p_emp_id IN NUMBER) IS
  v_name    VARCHAR2(100);
  v_dept_id NUMBER;
BEGIN
  SELECT first_name || ' ' || last_name, department_id
    INTO v_name, v_dept_id
    FROM employees
   WHERE employee_id = p_emp_id;

  DBMS_OUTPUT.PUT_LINE('직원: ' || v_name || ', 부서: ' || v_dept_id);

EXCEPTION
  WHEN NO_DATA_FOUND THEN
    -- ORA-01403 방지: 데이터 없음을 명확히 처리
    DBMS_OUTPUT.PUT_LINE('사원번호 ' || p_emp_id || '에 해당하는 직원이 없습니다.');
  WHEN TOO_MANY_ROWS THEN
    -- ORA-01422 방지: 복수 행 반환 처리
    DBMS_OUTPUT.PUT_LINE('복수의 데이터가 반환되었습니다. 조건을 확인하세요.');
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('예상치 못한 오류: ' || SQLERRM);
    RAISE; -- 필요 시 상위로 재전파
END;
/

원인 3: 데이터 타입 및 제약 조건 위반 처리

DML 수행 전 데이터 유효성을 검증하고, 제약 조건 위반을 명시적으로 처리합니다.

CREATE OR REPLACE PROCEDURE insert_product(
  p_product_id   IN NUMBER,
  p_product_name IN VARCHAR2,
  p_price        IN NUMBER
) IS
BEGIN
  -- 사전 유효성 검사
  IF p_product_name IS NULL THEN
    RAISE_APPLICATION_ERROR(-20010, '상품명은 필수 입력 항목입니다.');
  END IF;

  IF p_price < 0 THEN
    RAISE_APPLICATION_ERROR(-20011, '가격은 0 이상이어야 합니다.');
  END IF;

  INSERT INTO products (product_id, product_name, price)
  VALUES (p_product_id, p_product_name, p_price);

  COMMIT;

EXCEPTION
  WHEN DUP_VAL_ON_INDEX THEN
    -- ORA-00001: unique constraint violated
    ROLLBACK;
    DBMS_OUTPUT.PUT_LINE('이미 존재하는 상품 ID입니다: ' || p_product_id);
  WHEN OTHERS THEN
    ROLLBACK;
    DBMS_OUTPUT.PUT_LINE('삽입 오류: ' || SQLCODE || ' - ' || SQLERRM);
    RAISE;
END;
/

ORA-06512 스택 추적 분석 방법

-- DBMS_UTILITY.FORMAT_ERROR_BACKTRACE를 활용한 정밀 스택 추적
CREATE OR REPLACE PROCEDURE outer_proc IS
BEGIN
  inner_proc; -- inner_proc에서 예외 발생 시
EXCEPTION
  WHEN OTHERS THEN
    -- FORMAT_ERROR_BACKTRACE는 ORA-06512 스택을 문자열로 반환
    DBMS_OUTPUT.PUT_LINE('=== 오류 발생 위치 추적 ===');
    DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
    DBMS_OUTPUT.PUT_LINE('=== 오류 메시지 ===');
    DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_STACK);
END;
/

예방 방법

1. DBMS_UTILITY.FORMAT_ERROR_BACKTRACE를 활용한 체계적 오류 로깅

모든 PL/SQL 프로그램의 최상위 EXCEPTION 핸들러에서 DBMS_UTILITY.FORMAT_ERROR_BACKTRACEDBMS_UTILITY.FORMAT_ERROR_STACK을 조합하여 오류 발생 위치와 전파 경로를 로그 테이블에 기록하는 공통 오류 처리 패키지를 구현하세요. 이를 통해 ORA-06512 스택이 길어지더라도 근본 원인을 신속하게 추적할 수 있으며, 운영 환경에서의 장애 대응 시간을 크게 단축할 수 있습니다.

-- 공통 오류 처리 패키지 예시
CREATE OR REPLACE PACKAGE error_handler AS
  PROCEDURE log_error(p_module IN VARCHAR2, p_action IN VARCHAR2);
END error_handler;
/

CREATE OR REPLACE PACKAGE BODY error_handler AS
  PROCEDURE log_error(p_module IN VARCHAR2, p_action IN VARCHAR2) IS
    PRAGMA AUTONOMOUS_TRANSACTION;
  BEGIN
    INSERT INTO app_error_log (
      log_id, module_name, action_name,
      error_code, error_message, backtrace, log_date
    ) VALUES (
      app_error_log_seq.NEXTVAL,
      p_module, p_action,
      SQLCODE, SQLERRM,
      DBMS_UTILITY.FORMAT_ERROR_BACKTRACE,
      SYSTIMESTAMP
    );
    COMMIT;
  END log_error;
END error_handler;
/

2. 표준화된 PL/SQL 코딩 가이드라인 수립 및 코드 리뷰 도입

팀 전체가 따르는 PL/SQL 예외 처리 표준(모든 프로시저/함수에 EXCEPTION 절 필수, WHEN OTHERS만 단독 사용 금지, RAISE 또는 로그 없이 예외 무시 금지 등)을 문서화하고 코드 리뷰 체크리스트에 포함시키세요. 또한 Oracle SQL Developer나 PL/SQL Developer의 정적 분석 기능, 또는 별도의 정적 분석 도구(예: Trivadis PL/SQL Cop)를 CI/CD 파이프라인에 통합하면 배포 전 단계에서 누락된 예외 처리를 자동으로 감지할 수 있습니다.


관련 에러

  • ORA-06511: PL/SQL: cursor already open — 커서 관련 예외가 전파될 때 ORA-06512와 함께 출력됩니다.
  • ORA-01403: no data found — SELECT INTO 구문에서 데이터가 없을 때 가장 흔히 ORA-06512를 동반하는 에러입니다.
  • ORA-01422: exact fetch returns more than requested number of rows — SELECT INTO에서 복수 행 반환 시 발생합니다.
  • ORA-00001: unique constraint violated — DML 실행 중 제약 위반으로 ORA-06512가 발생하는 대표적 케이스입니다.
  • ORA-06510: PL/SQL: unhandled user-defined exception — 사용자 정의 예외를 처리하지 않았을 때 ORA-06512와 함께 나타납니다.
  • ORA-20000 ~ ORA-20999: RAISE_APPLICATION_ERROR로 발생시키는 사용자 정의 에러 범위로, ORA-06512와 항상 쌍으로 등장합니다.
DBMS 에러 코드 시리즈

주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.

본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.

댓글 남기기