ORA-06550 PL/SQL compilation error — 컴파일 오류 원인·해결·예방 완전 정리
PL/SQL 익명 블록이나 동적 SQL을 던졌을 때 ORA-06550: line X, column Y: PLS-NNNNN: ... 형태로 떨어지는 에러는 사실상 모든 PL/SQL 개발자가 한 번쯤 본다. ORA-06550은 항상 PLS-xxxxx 컴파일러 메시지와 함께 묶여 나타나는 wrapper로, PL/SQL 코드가 컴파일 단계에서 실패했음을 알려 주는 신호다.
본 글은 ORA-06550의 정확한 의미와 ORA-06512·ORA-04063과의 구분, 자주 함께 나타나는 7가지 PLS 컴파일 에러, line·column 좌표를 활용한 진단, 동적 SQL 안전화와 빌드 단계의 정적 분석까지 정리한다.

이 글의 구성
01 에러 메시지와 ORA-06550의 의미
| 항목 | 내용 |
|---|---|
| 에러 코드 | ORA-06550 |
| 메시지 형식 | line X, column Y: PLS-NNNNN: <세부 메시지> |
| 시점 | PL/SQL 컴파일 단계(런타임 아님) |
| 실제 원인 | 함께 표시된 PLS-NNNNN 코드 |
| EXCEPTION 처리 | 불가 — 컴파일이 실패하므로 핸들러 자체가 동작하지 않음 |
| 발생 단위 | 익명 블록 · EXECUTE IMMEDIATE · DBMS_SQL · CREATE OR REPLACE |
전형적인 출력 예시
ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'PROC'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
진단의 출발점은 두 번째 줄의 PLS-NNNNN 코드다. ORA-06550은 "어디서 실패했는가"의 좌표만 알려 주고, 진짜 원인은 PLS 코드에 담겨 있다.
핵심 관찰 — EXCEPTION 블록으로 잡을 수 없다
ORA-06550은 코드가 실행되기 전, 컴파일 단계에서 실패하므로 PL/SQL의 EXCEPTION 핸들러로는 잡히지 않는다. 동적 SQL을 EXECUTE IMMEDIATE로 던졌을 때도 그 안에서 발생한 컴파일 에러는 호출 측 외부에서만 잡을 수 있다. ORA-06512(런타임 백트레이스)와의 결정적 차이가 여기에 있다.
02 발생 시점 — 어디서 컴파일이 일어나는가
PL/SQL 엔진은 다음 다섯 가지 경로에서 코드를 컴파일한다. ORA-06550은 이 다섯 시점 어디서든 발생할 수 있다.
- 익명 블록 실행 — SQL*Plus·SQL Developer에서
BEGIN ... END;를 던질 때 - EXECUTE IMMEDIATE — 동적으로 만든 PL/SQL 또는 DDL 문자열을 실행할 때
- DBMS_SQL.PARSE — 동적 SQL 패키지를 통한 파싱
- CREATE OR REPLACE — 저장 객체(프로시저·함수·패키지·트리거) DDL
- 클라이언트 호출 — JDBC·ODP.NET·python-oracledb 등이 PL/SQL 블록을 전송할 때
저장 객체 DDL의 경우 컴파일이 실패하면 객체는 데이터 사전에 INVALID 상태로 남는다. 이때 누군가 이 객체를 호출하면 ORA-04063이 발생하므로, ORA-06550이 처음 떨어진 시점에 바로 잡지 못하면 운영 트래픽에서 ORA-04063으로 재발견된다. 둘은 같은 컴파일 실패의 두 얼굴이다.
03 자주 함께 나타나는 PLS 코드 7가지
| 코드 | 의미 | 흔한 원인 |
|---|---|---|
| PLS-00103 | Encountered the symbol ... | 세미콜론 누락, BEGIN/END 짝 불일치 |
| PLS-00201 | identifier must be declared | 객체 미존재, 권한 없음, 오타 |
| PLS-00302 | component must be declared | 패키지 멤버·컬럼 이름 잘못 |
| PLS-00306 | wrong number or types of arguments | 함수·프로시저 시그니처 불일치 |
| PLS-00357 | table, view or sequence reference not allowed in this context | DML이 허용되지 않는 위치 |
| PLS-00428 | INTO clause is expected in this SELECT | PL/SQL의 SELECT가 INTO 없이 작성 |
| PLS-00049 | bad bind variable | 바인드 변수 이름 잘못 |
PLS-00103·00201·00306이 가장 빈도가 높다. 좌표(line·column)만 알면 어느 토큰에서 컴파일러가 멈춘 것인지 즉시 식별할 수 있고, 이 세 가지를 능숙하게 다루는 것만으로도 일상적 컴파일 오류의 80%는 자력으로 해결된다.
04 line·column 좌표와 진단 절차
SQL*Plus에서 직전 컴파일 객체의 에러 확인
-- 직전 컴파일된 객체의 에러 표시
SHOW ERRORS
-- 객체 지정해서 확인
SHOW ERRORS PROCEDURE my_proc
SHOW ERRORS PACKAGE BODY my_pkg
USER_ERRORS 뷰 — 저장 객체 컴파일 잔여 오류
SELECT name, type, line, position, text
FROM user_errors
WHERE name = 'MY_PKG'
AND type = 'PACKAGE BODY'
ORDER BY sequence;
저장 객체의 컴파일 시점 ORA-06550은 결과적으로 USER_ERRORS에 PLS 메시지로 남는다. 이 뷰를 CI 파이프라인에서 0건이 될 때까지 검증한 뒤에야 배포를 통과시키는 게이트로 쓰는 것이 표준이다.
EXECUTE IMMEDIATE 디버깅 — 문자열을 정적으로 검증
동적 PL/SQL의 컴파일 오류는 줄 번호가 동적 문자열 내부 기준이라 추적이 어렵다. 가장 빠른 방법은 동적으로 생성된 SQL 문자열을 로그로 그대로 받아 SQL Developer에 붙여 정적 컴파일로 검증하는 것이다.
DECLARE
v_sql VARCHAR2(4000);
BEGIN
v_sql := 'BEGIN pkg.do_it(:1); END;';
DBMS_OUTPUT.PUT_LINE(v_sql); -- 동적 문자열 로깅
EXECUTE IMMEDIATE v_sql USING 100;
END;
/
05 예방 전략과 동적 SQL 안전화
| 영역 | 권장 조치 |
|---|---|
| 작성 단계 | SQL Developer·SQLcl의 실시간 syntax check 활용 |
| 동적 SQL | DBMS_ASSERT로 식별자·값 검증, 바인드 변수 강제(SQL Injection 동시 차단) |
| 빌드 게이트 | CI 파이프라인에서 USER_ERRORS 0건 검증 후에만 다음 단계 진행 |
| 정적 분석 | PL/Scope·SonarQube PL/SQL 룰로 시그니처·미사용 변수·deprecated 호출 점검 |
| 단위 테스트 | utPLSQL로 정상·예외·경계값 시나리오 자동화 |
| 코드 리뷰 | 패키지 spec 변경 시 dependent body 재컴파일 동반 확인 |
DBMS_ASSERT로 동적 SQL 안전화
DECLARE
v_tab VARCHAR2(30) := 'EMP';
v_sql VARCHAR2(4000);
v_cnt NUMBER;
BEGIN
-- 식별자 검증으로 컴파일 실패와 인젝션을 동시에 막는다
v_sql := 'SELECT COUNT(*) FROM ' ||
SYS.DBMS_ASSERT.SIMPLE_SQL_NAME(v_tab);
EXECUTE IMMEDIATE v_sql INTO v_cnt;
END;
/
값은 무조건 바인드 변수(USING)로, 식별자는 DBMS_ASSERT로 검증하는 두 가지 룰이 동적 SQL의 표준이다. 이 두 가지만 지켜도 ORA-06550 빈도와 보안 사고를 동시에 줄일 수 있다.
CI 게이트가 가장 효과적인 안전망
개발자가 로컬에서 컴파일 확인을 빠뜨려도, 빌드 단계에서 USER_ERRORS·DBA_ERRORS를 조회해 0건이 아니면 빌드 실패로 처리하는 룰을 두면 ORA-06550이 운영으로 흘러가지 않는다. 패키지 spec 변경 후 body 재컴파일까지 자동화하면 ORA-04063과의 결합 장애도 같이 막을 수 있다.
06 ORA-06512·ORA-04063과의 차이
| 에러 코드 | 시점 | 의미와 차이 |
|---|---|---|
| ORA-06550 | 컴파일 | 지금 보낸 코드가 컴파일 실패(PLS-NNNNN 동반) |
| ORA-06512 | 런타임 | 이미 컴파일된 코드가 실행 중 예외(위치 표시) |
| ORA-04063 | 런타임 | 호출된 저장 객체가 INVALID 상태 |
| ORA-04088 | 런타임 | 트리거 실행 중 예외 wrapper |
| ORA-06502 | 런타임 | 값·자료형 변환 오류(컴파일은 통과) |
ORA-06550은 PLS-NNNNN과 함께 컴파일 단계에서 떨어지고, 저장 객체에서 같은 컴파일 실패가 일어났다면 데이터 사전에 INVALID 상태로 남아 이후 호출 시 ORA-04063으로 표면화된다. ORA-06512는 컴파일을 통과한 코드의 실행 중 예외 위치를, ORA-04088은 그것이 트리거 컨텍스트에서 발생했음을 알려 준다. 어느 코드를 만났는지에 따라 진단 시작점이 USER_ERRORS인지 USER_SOURCE인지 자연스럽게 갈린다.
07 자주 묻는 질문
Q1. ORA-06550을 EXCEPTION WHEN OTHERS로 잡을 수 있나요?
없다. 컴파일 단계에서 실패하면 PL/SQL 엔진은 코드 자체를 실행 가능 상태로 만들지 못하므로 EXCEPTION 블록이 동작할 기회가 없다. EXECUTE IMMEDIATE로 동적 PL/SQL을 실행한 호출자 측에서 일반 OTHERS로 잡을 수 있지만, 정적 PL/SQL 블록은 그 위 호출자나 클라이언트 단에서만 잡힌다.
Q2. PLS-00201이 떨어졌는데 SQL*Plus에서는 같은 테이블이 보입니다.
PL/SQL 컴파일은 role 권한을 인정하지 않는다. 권한이 role을 통해 부여됐다면 SELECT는 되지만 PL/SQL 내부 참조에서는 PLS-00201로 떨어진다. 해결은 직접 GRANT 또는 시노님 생성이다. 시노님 경로 자체가 끊어진 경우도 같은 증상을 보인다.
Q3. EXECUTE IMMEDIATE에서 ORA-06550의 라인 번호가 이상해요.
동적 SQL의 line 좌표는 그 문자열 내부 기준이다. 외부 PL/SQL 파일의 라인이 아니다. 디버깅 시 동적 문자열을 DBMS_OUTPUT으로 그대로 찍어 SQL Developer에 붙여 넣으면 라인 좌표가 일치한다.
Q4. PLS-00306 시그니처 불일치는 어떻게 빨리 잡나요?
USER_ARGUMENTS·ALL_ARGUMENTS 뷰에서 해당 패키지·프로시저의 파라미터 시퀀스를 확인한다. named notation(`p_name => value`)으로 호출하면 컴파일 시점에 실수를 빠르게 잡을 수 있고, 의도하지 않은 오버로드 호출도 방지된다.
Q5. 저장 객체를 CREATE OR REPLACE했더니 SUCCESS인데 호출 시 ORA-04063이 떨어집니다.
CREATE OR REPLACE는 컴파일 에러가 있어도 "Warning: ... created with compilation errors" 정도로 통과시키고 INVALID 객체를 만든다. SHOW ERRORS 또는 USER_ERRORS에 PLS-NNNNN이 남아 있고, 누군가 그 객체를 호출하는 순간 ORA-04063이 떨어진다. 배포 직후 반드시 USER_ERRORS 0건 검증이 필요한 이유다.
마무리
ORA-06550은 PL/SQL 학습 곡선의 가장 앞쪽에 놓인 에러다. 막상 처음 보면 막막하지만, 함께 출력되는 PLS-NNNNN 코드와 line·column 좌표만 읽을 줄 알면 대부분 5분 안에 해결된다.
진단의 정공법은 (1) PLS 코드로 원인 유형 식별, (2) 좌표로 위치 확인, (3) SHOW ERRORS / USER_ERRORS로 보강, 세 단계다.
운영 안정성 측면에서는 (1) 모든 동적 SQL에서 바인드 변수와 DBMS_ASSERT 적용, (2) CI 빌드 단계에 USER_ERRORS 0건 게이트, (3) 패키지 spec 변경 시 dependent 객체 일괄 재컴파일 자동화, (4) 단위 테스트로 호출 경로 커버, 네 가지가 ORA-06550·ORA-04063·ORA-06512 묶음을 한 번에 줄여 준다. 컴파일 실패를 운영 트래픽으로 흘려보내지 않는 것이 PL/SQL 운영의 첫 번째 원칙이다.
ORA-06550 트러블슈팅 체크리스트
본 글은 Oracle Database PL/SQL 컴파일 오류 ORA-06550의 일반적 원인과 해결 방법을 정리한 자료다. 운영 환경 적용 전 테스트 환경에서 충분히 검증한다.
#ORA06550 #PLSQLcompilationError #오라클에러 #PLS00103 #PLS00201 #PLS00306 #익명블록 #EXECUTE_IMMEDIATE #DBMS_SQL #DBMS_ASSERT #바인드변수 #USER_ERRORS #SHOW_ERRORS #PLScope #utPLSQL
'IT' 카테고리의 다른 글
| ORA-00918 column ambiguously defined — 조인 컬럼 모호 에러 원인·해결·예방 완전 정리 (0) | 2026.05.19 |
|---|---|
| 데이터 거버넌스가 뭐야 — DAMA-DMBOK·데이터 품질·소유권·Lineage·데이터 메시 완전 정리 (0) | 2026.05.19 |
| ORA-01843 not a valid month — 월 값 부적합 에러 원인·해결·예방 (1) | 2026.05.19 |
| Apache Iceberg가 뭐야 — 오픈 테이블 포맷·데이터 레이크하우스·스키마 진화·시간 여행 완전 정리 (0) | 2026.05.18 |
| ORA-06512 at line N — PL/SQL 스택 트레이스 에러 원인·해결·예방 완전 정리 (0) | 2026.05.18 |
댓글