상상해봐, 네가 학생의 평균 점수를 계산하는 함수를 짜고 있어. 만약 점수가 없어서 0으로 나누려고 하면 어떻게 될까? 그런 코드를 실제로 돌리면, 예상치 못한 에러가 바로 튀어나올 거야. PL/pgSQL은 이런 에러를 처리할 수 있는 강력한 도구를 제공해서, 네 코드를 더 견고하고 안전하게 만들어주고, 작업하기도 편하게 해줘.
PL/pgSQL에서 에러 처리를 하면 이런 걸 할 수 있어:
- 뭐가 잘못됐는지 설명하는 메시지를 만들어낼 수 있어.
- 치명적인 에러가 발생하면 코드 실행을 멈출 수 있어.
- 문제가 생기면 나중에 분석할 수 있게 로그로 남길 수 있어.
PL/pgSQL의 주요 메시지 레벨
PL/pgSQL은 여러 가지 메시지 레벨을 지원해서, 개발자가 문제를 더 쉽게 진단하고 해결할 수 있게 도와줘. 여기 있어:
- NOTICE: 정보성 메시지를 출력해. 디버깅할 때 써.
- WARNING: 프로그램 실행을 멈추진 않지만, 뭔가 문제가 있을 수 있다는 알림이야.
- EXCEPTION: 프로그램 실행을 중단시키는 심각한 에러야(그리고 호출한 코드로 제어가 넘어가).
PL/pgSQL의 메시지 레벨
| 메시지 레벨 | 설명 |
|---|---|
NOTICE |
정보나 디버깅 메시지. 실행에는 영향 없어 |
WARNING |
문제가 있을 수 있다는 경고. 힌트처럼 동작해 |
EXCEPTION |
프로그램 실행을 끝내는 심각한 에러 |
RAISE 명령어 문법
메시지를 만들거나 에러를 처리하려면 RAISE 명령어를 써. 기본 문법은 이래:
RAISE <메시지 레벨> '메시지 텍스트' [, 변수...];
<메시지 레벨>—NOTICE,WARNING,EXCEPTION.'메시지 텍스트'— 문제에 대한 설명.[변수...]— 메시지 텍스트에 넣을 수 있는 추가 값들.
예시 1: RAISE NOTICE 사용하기
가끔 함수 안에서 무슨 일이 일어나는지 알아야 할 때가 있어. 예를 들어, 루프 디버깅할 때:
DO $$
BEGIN
FOR i IN 1..5 LOOP
RAISE NOTICE '현재 i 값: %', i;
END LOOP;
END
$$;
결과: 콘솔에 현재 i 값: 1, 현재 i 값: 2 이런 식으로 5까지 출력돼.
예시 2: RAISE EXCEPTION 사용하기
이번엔, 특정 조건에서 에러를 내고 함수 실행을 끝내야 할 때를 상상해보자:
DO $$
BEGIN
IF 1 = 1 THEN
RAISE EXCEPTION '뭔가 잘못됐어!';
END IF;
END
$$;
결과: 실행이 중단되고, 에러 메시지가 콘솔에 출력돼.
RAISE에서 파라미터 사용하기
파라미터를 쓰면 메시지 텍스트를 더 개인화할 수 있어. 이때 % 플레이스홀더를 써:
예시 3: RAISE에 변수 넣기
DO $$
DECLARE
student_name TEXT := '이반';
average_score NUMERIC := NULL;
BEGIN
IF average_score IS NULL THEN
RAISE EXCEPTION '학생 %의 평균 점수가 없어!', student_name;
END IF;
END
$$;
결과: 메시지 학생 이반의 평균 점수가 없어!.
보다시피, %가 student_name 변수로 바뀌어서 메시지가 더 의미 있어져.
사용자 정의 에러 만들기
에러는 꼭 예기치 않은 상황에서만 나는 게 아니야! 때로는 잘못된 데이터를 막으려고 일부러 만들어야 할 때도 있어.
예시 4: 입력값 체크하기
숫자 입력값을 검사해서, 음수면 에러를 내는 함수를 만들어보자:
CREATE OR REPLACE FUNCTION check_positive(value NUMERIC)
RETURNS TEXT AS $$
BEGIN
IF value < 0 THEN
RAISE EXCEPTION '숫자 %는 음수야!', value;
END IF;
RETURN '숫자가 올바르다.';
END;
$$ LANGUAGE plpgsql;
이제 함수를 테스트해보자:
SELECT check_positive(-5);
결과: 에러 메시지 숫자 -5는 음수야!.
양수를 넣으면:
SELECT check_positive(10);
결과: 숫자가 올바르다.
컨텍스트에서 에러 처리하기
에러를 만들 줄 아는 것도 좋지만, 상황에 따라 다르게 처리할 수 있으면 더 좋아. 이럴 때 BEGIN ... EXCEPTION 블록을 써.
에러 처리 구조
BEGIN
-- 네 메인 코드
EXCEPTION
WHEN 에러_타입 THEN
-- 에러 발생 시 할 일
WHEN 다른_에러 THEN
-- 다른 에러일 때 할 일
WHEN OTHERS THEN
-- 나머지 모든 에러 처리
END;
구성 요소 설명:
EXCEPTION— 에러 처리 블록의 시작을 나타내는 키워드야.WHEN— 처리할 에러 타입을 지정할 수 있어. 예를 들어unique_violation이나division_by_zero같은 거.OTHERS—WHEN블록에 명시되지 않은 모든 에러를 처리할 때 써.
예시 5: 0으로 나누기 에러 처리
간단한 나눗셈 함수로 에러 처리 예시를 보여줄게:
CREATE OR REPLACE FUNCTION safe_divide(a NUMERIC, b NUMERIC)
RETURNS NUMERIC AS $$
BEGIN
-- 나눗셈 시도
RETURN a / b;
EXCEPTION
WHEN division_by_zero THEN
RAISE WARNING '0으로 나누려고 했어. NULL을 반환할게.';
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
함수 테스트:
SELECT safe_divide(10, 2); -- 기대 결과: 5
SELECT safe_divide(10, 0); -- 기대 결과: NULL, 그리고 콘솔에 경고
RAISE 쓸 때 자주 하는 실수
메시지 레벨 빼먹기. 레벨을 안 쓰면 PostgreSQL이 에러를 내.
잘못된 예:
RAISE '레벨 없는 메시지';
올바른 예:
RAISE NOTICE 'NOTICE 레벨 메시지';
잘못된 파라미터. %를 쓸 땐, 필요한 만큼 변수를 꼭 넘겨줘야 해.
잘못된 예:
RAISE NOTICE '파라미터 예시 %';
올바른 예:
RAISE NOTICE '파라미터 예시 %', '값';
남발하기. RAISE EXCEPTION을 너무 많이 쓰면 중요한 작업이 중단될 수 있어. 적당히 써.
꿀팁
WHEN OTHERS블록은 신중하게 써. 가능하면 구체적인 에러를 지정해서, 다른 방식으로 처리해야 할 에러까지 다 잡지 않게 해.RAISE를 디버깅에 활용해. 에러는 절대 무시하지 마.- 성능도 신경 써. 에러 처리는 특히 큰 프로시저에서 비용이 클 수 있어.
이걸 제대로 하면, 네 프로시저는 예상치 못한 장애도 잘 버틸 수 있을 거야. PM이 너를 엄청 자랑스러워할걸!
GO TO FULL VERSION