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

ORA-04068
2026년 08월 23일 | DBMS Error 가이드

이 글에서 다루는 내용

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

ORA-04068 existing state of packages has been discarded 는?

ORA-04068 에러는 Oracle 데이터베이스에서 패키지(Package)의 기존 상태(State)가 무효화(Invalidate)되었을 때 발생하는 에러입니다. 주로 패키지가 재컴파일되거나 DDL 변경이 발생한 후, 해당 패키지의 패키지 변수(Package Variable) 또는 커서(Cursor) 등의 상태를 유지하고 있던 세션이 다시 패키지를 호출할 때 발생합니다. 이 에러는 데이터 손실을 일으키지는 않지만, 운영 중인 애플리케이션에서 예상치 못한 예외를 발생시켜 트랜잭션 중단으로 이어질 수 있어 반드시 원인 파악과 대응이 필요합니다.


주요 발생 원인

  • 패키지 재컴파일(Recompile) 또는 DDL 변경

가장 흔한 원인으로, 운영 중에 패키지를 ALTER PACKAGE ... COMPILE 명령으로 재컴파일하거나, 패키지가 의존하는 테이블/뷰/시노님 등에 DDL 변경(ALTER TABLE, CREATE OR REPLACE VIEW 등)이 발생하면 해당 패키지가 INVALID 상태로 전환됩니다. 이 상태에서 기존 세션이 패키지를 다시 호출하면 Oracle은 자동으로 패키지를 재컴파일하고, 이전 세션이 보유하고 있던 패키지 상태(전역 변수 값, 열린 커서 등)를 폐기(Discard)하면서 ORA-04068이 발생합니다.

  • 패키지에 Stateful(상태 유지) 전역 변수 사용

패키지 스펙(Spec) 또는 바디(Body)에 전역 변수를 선언하고 세션 간 상태를 유지하도록 설계된 경우, 패키지가 무효화되면 해당 변수들의 값이 모두 초기화됩니다. 이 때 애플리케이션이 여전히 이전 상태 값을 기대하고 있다면 단순한 에러 재시도만으로는 해결되지 않을 수 있으며, 로직 상의 추가 처리가 필요합니다.

  • RAC(Real Application Clusters) 환경 또는 다중 세션 환경에서의 동시 패키지 재컴파일

RAC 환경에서는 한 노드에서 패키지가 재컴파일되면 다른 노드의 기존 세션들도 동일하게 영향을 받습니다. 특히 배포(Deployment) 작업 시 여러 패키지를 순차적으로 배포하는 도중 운영 세션들이 해당 패키지를 호출하면 다수의 ORA-04068이 동시에 발생할 수 있으며, 이는 서비스 장애로 이어질 수 있습니다.


해결 방법

원인 1: 패키지 재컴파일 후 발생 시 즉각적인 재시도

ORA-04068은 일반적으로 한 번 발생한 후 다음 호출에서는 정상 동작합니다. 패키지 상태가 폐기된 직후 Oracle이 패키지를 새로 초기화하기 때문입니다. 애플리케이션 레벨에서 예외 처리를 통해 재시도 로직을 구현하는 것이 가장 현실적인 해결책입니다.

-- 애플리케이션 또는 PL/SQL 블록에서 ORA-04068 처리 예시
DECLARE
  v_retry_count NUMBER := 0;
  v_max_retry   NUMBER := 3;
BEGIN
  LOOP
    BEGIN
      -- 패키지 프로시저 호출
      my_package.my_procedure();
      EXIT; -- 정상 처리 시 루프 탈출
    EXCEPTION
      WHEN OTHERS THEN
        IF SQLCODE = -4068 AND v_retry_count < v_max_retry THEN
          v_retry_count := v_retry_count + 1;
          DBMS_OUTPUT.PUT_LINE('ORA-04068 발생, 재시도 중... (' || v_retry_count || '/' || v_max_retry || ')');
        ELSE
          RAISE; -- 재시도 초과 또는 다른 에러는 상위로 전파
        END IF;
    END;
  END LOOP;
END;
/

원인 2: 패키지 전역 변수 상태 초기화 대응

패키지에 전역 변수가 있는 경우, 재컴파일 후 변수가 초기화될 수 있음을 고려하여 패키지 내에 초기화 루틴을 별도로 두는 것이 좋습니다.

-- 패키지 스펙 예시
CREATE OR REPLACE PACKAGE my_stateful_pkg AS
  g_session_id   VARCHAR2(100);
  g_is_initialized BOOLEAN := FALSE;

  PROCEDURE initialize(p_session_id VARCHAR2);
  PROCEDURE do_work;
END my_stateful_pkg;
/

-- 패키지 바디 예시
CREATE OR REPLACE PACKAGE BODY my_stateful_pkg AS

  PROCEDURE initialize(p_session_id VARCHAR2) IS
  BEGIN
    g_session_id     := p_session_id;
    g_is_initialized := TRUE;
    DBMS_OUTPUT.PUT_LINE('패키지 초기화 완료: ' || g_session_id);
  END initialize;

  PROCEDURE do_work IS
  BEGIN
    -- 초기화 여부 확인 후 작업 수행
    IF NOT g_is_initialized THEN
      RAISE_APPLICATION_ERROR(-20001, '패키지가 초기화되지 않았습니다. initialize()를 먼저 호출하세요.');
    END IF;
    DBMS_OUTPUT.PUT_LINE('작업 수행 중: ' || g_session_id);
  END do_work;

END my_stateful_pkg;
/

-- 호출 예시: ORA-04068 발생 후 재초기화 처리
DECLARE
  v_retry NUMBER := 0;
BEGIN
  LOOP
    BEGIN
      IF NOT my_stateful_pkg.g_is_initialized THEN
        my_stateful_pkg.initialize('SESSION_001');
      END IF;
      my_stateful_pkg.do_work();
      EXIT;
    EXCEPTION
      WHEN OTHERS THEN
        IF SQLCODE = -4068 AND v_retry < 2 THEN
          v_retry := v_retry + 1;
          -- 다음 반복에서 재초기화 수행
        ELSE
          RAISE;
        END IF;
    END;
  END LOOP;
END;
/

원인 3: 무효화된 패키지 사전 확인 및 재컴파일

배포 전후 INVALID 상태의 객체를 확인하고, 배포 후 즉시 재컴파일하여 운영 세션이 최초 호출 시 자동 재컴파일로 인한 지연과 에러를 최소화합니다.

-- 현재 INVALID 상태의 패키지 목록 조회
SELECT owner,
       object_name,
       object_type,
       status,
       last_ddl_time
  FROM dba_objects
 WHERE status = 'INVALID'
   AND object_type IN ('PACKAGE', 'PACKAGE BODY', 'PROCEDURE', 'FUNCTION')
 ORDER BY last_ddl_time DESC;

-- 특정 패키지 수동 재컴파일
ALTER PACKAGE my_package COMPILE;
ALTER PACKAGE my_package COMPILE BODY;

-- 스키마 전체 INVALID 객체 일괄 재컴파일 (UTL_RECOMP 활용)
EXEC UTL_RECOMP.RECOMP_SERIAL('MY_SCHEMA');  -- 직렬 재컴파일
-- 또는
EXEC UTL_RECOMP.RECOMP_PARALLEL(4, 'MY_SCHEMA');  -- 병렬(4개 스레드) 재컴파일

-- 재컴파일 후 상태 재확인
SELECT object_name, object_type, status
  FROM dba_objects
 WHERE owner = 'MY_SCHEMA'
   AND status = 'INVALID';

예방 방법

  • 배포(Deployment) 절차에 서비스 점검 시간 확보 및 사전 재컴파일 포함

운영 환경에서 패키지를 배포할 때는 반드시 서비스 점검 시간(Maintenance Window)을 확보하거나, 최소 트래픽 시간대를 선택해야 합니다. 배포 스크립트 마지막에 UTL_RECOMP.RECOMP_SERIAL 또는 UTL_RECOMP.RECOMP_PARALLEL을 실행하여 모든 관련 객체를 사전에 VALID 상태로 만들어 두면, 운영 세션이 첫 호출 시 자동 재컴파일로 인해 ORA-04068을 마주치는 상황을 크게 줄일 수 있습니다. 또한 배포 전 의존성 체인을 분석하여 영향 받는 모든 객체를 파악하는 습관을 들이는 것이 중요합니다.

  • 패키지 설계 시 Stateless 구조 권장 및 예외 처리 표준화

가능하면 패키지 전역 변수에 세션 상태를 저장하는 Stateful 설계보다는, 필요한 정보를 매개변수로 전달하는 Stateless 설계를 권장합니다. 불가피하게 전역 변수를 사용해야 한다면, 패키지 초기화 섹션(BEGIN ... END in package body)에서 기본값을 명확히 설정하고, 애플리케이션 레이어에서 ORA-04068(-4068)에 대한 표준 예외 처리 및 재시도 로직을 공통 모듈로 구현하여 모든 패키지 호출에 일관되게 적용하는 것이 좋습니다.


관련 에러

  • ORA-04061: existing state of "" has been invalidated — ORA-04068 발생 직전에 함께 나타나는 에러로, 패키지나 함수/프로시저가 무효화되었음을 알립니다.
  • ORA-04065: not executed, altered or dropped "" — 패키지가 변경되거나 삭제되어 현재 세션에서 실행할 수 없음을 나타냅니다.
  • ORA-06508: PL/SQL: could not find program unit being called — 패키지가 DROP된 후 호출 시 발생하며, ORA-04068과 유사한 상황에서 나타날 수 있습니다.
  • ORA-00604: error occurred at recursive SQL level — ORA-04068과 함께 연쇄적으로 발생할 수 있는 재귀 SQL 에러입니다.
  • 이 에러들은 보통 스택 형태로 함께 출력되므로, Alert Log 또는 애플리케이션 로그에서 전체 에러 스택을 확인하여 근본 원인을 파악하는 것이 중요합니다.


    DBMS 에러 코드 시리즈

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

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

    댓글 남기기