2026년 09월 11일 | DBMS Error 가이드
이 글에서 다루는 내용
42703 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
42703 undefined column 란?
PostgreSQL 에러 코드 42703은 undefined column, 즉 쿼리에서 참조한 컬럼이 해당 테이블 또는 쿼리 결과에 존재하지 않을 때 발생하는 에러입니다. 주로 컬럼명 오타, 잘못된 테이블 참조, 또는 실제로 존재하지 않는 컬럼을 SELECT나 WHERE 절에서 사용할 때 발생합니다. 이 에러는 SQL 파싱 단계에서 감지되므로, 실제 데이터를 읽기 전에 에러 메시지를 즉시 확인할 수 있습니다.
주요 발생 원인
1. 컬럼명 오타 또는 대소문자 불일치
가장 흔한 원인으로, 컬럼명을 잘못 입력하거나 대소문자를 혼용하는 경우입니다. PostgreSQL은 기본적으로 식별자를 소문자로 처리하지만, 큰따옴표(")로 감싼 경우에는 대소문자를 구분합니다. 예를 들어 테이블 생성 시 "UserName"으로 만들었다면, 이후 쿼리에서 반드시 "UserName"으로 참조해야 하며 username이나 UserName으로 쓰면 에러가 발생합니다.
2. 존재하지 않는 컬럼 참조 (스키마 변경 후 미반영)
테이블 스키마가 변경(컬럼 삭제 또는 이름 변경)된 이후, 기존 쿼리나 애플리케이션 코드가 업데이트되지 않은 경우에 발생합니다. 특히 운영 환경에서 ALTER TABLE ... DROP COLUMN 또는 ALTER TABLE ... RENAME COLUMN을 실행한 후 ORM 모델이나 저장 프로시저가 갱신되지 않으면 이 에러가 빈번하게 나타납니다. 이는 마이그레이션 관리의 중요성을 보여주는 대표적인 사례입니다.
3. 서브쿼리 또는 CTE에서의 컬럼 범위 오류
서브쿼리나 CTE(Common Table Expression)에서 정의된 컬럼을 외부 쿼리에서 잘못 참조하거나, 서브쿼리 내부에서 외부 스코프의 컬럼을 참조할 때 발생합니다. 특히 복잡한 다단계 CTE에서 각 단계의 컬럼 별칭(alias)이 다음 단계로 올바르게 전달되지 않으면 이 에러가 발생합니다. 쿼리의 컬럼 범위(scope)를 명확히 이해하지 못하면 디버깅이 매우 어려울 수 있습니다.
해결 방법
원인 1 해결: 컬럼명 확인 및 수정
먼저 information_schema 또는 \d 메타 커맨드를 통해 실제 컬럼명을 확인하세요.
-- 테이블의 실제 컬럼 목록 확인
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'users';
-- psql 메타커맨드로 확인
\d users
-- 잘못된 쿼리 예시 (에러 발생)
SELECT UserName FROM users;
-- ERROR: column "username" does not exist (실제로는 "user_name")
-- 올바른 쿼리
SELECT user_name FROM users;
-- 큰따옴표로 생성된 컬럼인 경우
-- 테이블 생성 시: CREATE TABLE users ("UserName" TEXT);
-- 올바른 참조 방법
SELECT "UserName" FROM users;
원인 2 해결: 스키마 변경 후 쿼리 업데이트
스키마 변경 이력을 추적하고, 관련된 모든 쿼리를 업데이트해야 합니다.
-- 컬럼 이름 변경 전 기존 컬럼 확인
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'orders'
AND column_name = 'order_amt';
-- 컬럼 이름이 변경된 경우 (order_amt -> order_amount)
-- 잘못된 쿼리 (에러 발생)
SELECT order_amt FROM orders;
-- ERROR: column "order_amt" does not exist
-- 올바른 쿼리
SELECT order_amount FROM orders;
-- 마이그레이션 실행 시 컬럼 존재 여부 먼저 확인
DO $$
BEGIN
IF EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'orders'
AND column_name = 'order_amt'
) THEN
ALTER TABLE orders RENAME COLUMN order_amt TO order_amount;
END IF;
END $$;
-- 뷰(View)에서 삭제된 컬럼 참조 시 뷰 재생성
DROP VIEW IF EXISTS orders_summary;
CREATE VIEW orders_summary AS
SELECT id, order_amount, status
FROM orders;
원인 3 해결: 서브쿼리 및 CTE 컬럼 범위 수정
-- 잘못된 CTE 예시 (에러 발생)
WITH sales AS (
SELECT product_id, SUM(quantity) AS total_qty
FROM order_items
GROUP BY product_id
)
-- CTE에 정의되지 않은 컬럼(unit_price) 참조 시 에러
SELECT product_id, total_qty, unit_price
FROM sales;
-- ERROR: column "unit_price" does not exist
-- 올바른 CTE - 필요한 컬럼을 CTE에 포함
WITH sales AS (
SELECT
oi.product_id,
SUM(oi.quantity) AS total_qty,
p.unit_price -- 필요한 컬럼을 JOIN으로 포함
FROM order_items oi
JOIN products p ON oi.product_id = p.id
GROUP BY oi.product_id, p.unit_price
)
SELECT product_id, total_qty, unit_price
FROM sales;
-- 서브쿼리 컬럼 범위 오류 예시 및 수정
-- 잘못된 쿼리
SELECT *
FROM (
SELECT id, name FROM customers
) AS cust
WHERE email = 'test@example.com'; -- 서브쿼리에 email 컬럼 없음
-- ERROR: column "email" does not exist
-- 올바른 쿼리
SELECT *
FROM (
SELECT id, name, email FROM customers -- email 포함
) AS cust
WHERE email = 'test@example.com';
예방 방법
1. 명시적 컬럼 목록 사용 및 코딩 컨벤션 통일
SELECT * 대신 항상 명시적으로 컬럼명을 나열하는 습관을 들이세요. 이렇게 하면 스키마 변경 시 영향을 받는 쿼리를 즉시 파악할 수 있으며, 불필요한 데이터 전송도 줄일 수 있습니다. 또한 팀 내에서 컬럼 명명 규칙(예: 모두 소문자 snake_case)을 통일하고, 큰따옴표로 식별자를 감싸는 방식은 꼭 필요한 경우에만 사용하도록 컨벤션을 정립하세요.
-- 권장하지 않음
SELECT * FROM users;
-- 권장
SELECT id, user_name, email, created_at FROM users;
2. 마이그레이션 도구 활용 및 변경 전 영향도 분석
Flyway, Liquibase, Alembic 등의 마이그레이션 도구를 사용하여 스키마 변경 이력을 체계적으로 관리하세요. 컬럼을 삭제하거나 이름을 변경하기 전에, 해당 컬럼을 참조하는 뷰, 함수, 저장 프로시저, 트리거를 반드시 사전에 조회하여 영향도를 분석하고 함께 업데이트해야 합니다.
-- 특정 컬럼을 참조하는 뷰 및 함수 사전 확인
SELECT DISTINCT
dependent_ns.nspname AS dependent_schema,
dependent_view.relname AS dependent_view
FROM pg_depend
JOIN pg_rewrite ON pg_depend.objid = pg_rewrite.oid
JOIN pg_class AS dependent_view ON pg_rewrite.ev_class = dependent_view.oid
JOIN pg_class AS source_table ON pg_depend.refobjid = source_table.oid
JOIN pg_namespace dependent_ns ON dependent_ns.oid = dependent_view.relnamespace
JOIN pg_namespace source_ns ON source_ns.oid = source_table.relnamespace
WHERE source_table.relname = 'users'
AND source_ns.nspname = 'public';
관련 에러
- 42P01 (undefined_table): 참조한 테이블 자체가 존재하지 않을 때 발생합니다. 42703과 유사하지만 테이블 수준의 문제입니다.
- 42702 (ambiguous_column): 동일한 이름의 컬럼이 여러 테이블에 존재하여 어느 테이블의 컬럼인지 모호할 때 발생합니다. JOIN 쿼리에서 테이블 별칭 없이 컬럼을 참조할 때 자주 나타납니다.
- 42601 (syntax_error): SQL 문법 오류로, 잘못된 컬럼명 기재와 함께 발생하는 경우가 있습니다.
- 42883 (undefined_function): 존재하지 않는 함수를 호출할 때 발생하는 에러로, 42703과 마찬가지로 식별자 오류의 일종입니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.