자, 복잡한 함수나 프로시저를 만들었다고 상상해봐. 이미 DB가 멋지게 돌아가는 게 보이는데, 갑자기 — 빡! — 데이터가 이상하거나 쿼리가 느려지고, 팀장이 슬슬 불안해하기 시작하지. 이럴 때 등장하는 게 바로 디버깅이야.
PL/pgSQL에서 디버깅이 필요한 이유는:
- 로직 에러 찾기, 예를 들어 함수가 기대한 결과를 안 돌려줄 때.
- 입력 데이터가 이상할 때 파악하기. DB 사용자들이 가끔 데이터뿐만 아니라... 완전 알 수 없는 걸 넣기도 하거든!
- 성능 문제 해결하기. 급하게 짠 코드는 사막에서 Wi-Fi 찾는 거북이처럼 느릴 수도 있으니까.
진지하게 말하면, 디버깅은 단순히 버그를 찾고 고치는 게 아니야. 코드를 더 빠르고, 효율적이고, 읽기 쉽게 만드는 방법이기도 해.
PL/pgSQL 디버깅 기본 접근법
PL/pgSQL에서 디버깅은 여러 가지 방법으로 할 수 있어. 하나씩 살펴보자.
- PostgreSQL 내장 도구 사용하기
PostgreSQL은 진단을 위한 몇 가지 내장 기능을 제공해. 로깅 함수(RAISE NOTICE랑 RAISE EXCEPTION), 쿼리 실행 계획 분석(EXPLAIN ANALYZE) 같은 거지. 이런 도구들은 함수 내부에서 무슨 일이 일어나는지 이해하는 데 도움을 줘.
RAISE NOTICE로 로깅하기
RAISE NOTICE는 함수에서 어떤 데이터가 지나가는지, 어디서 뭔가 잘못됐는지, 변수 값이 뭔지 확인하고 싶을 때 완전 좋은 친구야. RAISE EXCEPTION이랑 다르게 함수 실행을 멈추지 않아. 예를 들어, 실행 단계마다 변수 값을 출력할 수 있지.
DO $$
DECLARE
counter INT := 0;
BEGIN
FOR counter IN 1..5 LOOP
RAISE NOTICE '현재 카운터 값: %', counter;
END LOOP;
END $$;
이 코드는 counter 값을 1부터 5까지 출력해. 단순하지만 디버깅할 때 진짜 유용해!
- 외부 툴 사용하기
PL/pgSQL 디버깅은 pgAdmin 같은 툴(GUI 인터페이스 있음)로도 할 수 있어. 브레이크포인트 걸고, 변수 값을 실시간으로 볼 수 있지. 시각적인 도구를 좋아한다면 pgAdmin이 진짜 좋은 동료가 될 거야.
디버깅 단계
함수나 프로시저 디버깅을 시작할 때는, 특정 순서를 따르는 게 중요해. 각 단계를 자세히 보자:
- 입력 데이터 분석
가장 먼저 확인해야 할 건 입력 데이터야. 함수가 받는 데이터에 에러나 예상치 못한 값이 없는지 꼭 체크해. 예를 들어, 모든 입력 파라미터를 RAISE NOTICE로 확인할 수 있어:
CREATE FUNCTION check_input(x INTEGER) RETURNS VOID AS $$
BEGIN
IF x IS NULL THEN
RAISE EXCEPTION '입력 값은 NULL이면 안 돼!';
END IF;
RAISE NOTICE '입력 값: %', x;
END;
$$ LANGUAGE plpgsql;
이 예제는 입력 데이터에 문제가 있을 때 사용자에게 경고하는 방법을 보여줘.
- 각 단계별 실행 확인
함수를 논리 블록으로 나누고, 중요한 지점마다 RAISE NOTICE를 추가해. 어디서 문제가 생기는지 파악하기 쉬워져.
CREATE FUNCTION calculate_discount(price NUMERIC, discount NUMERIC) RETURNS NUMERIC AS $$
BEGIN
RAISE NOTICE '함수 시작: 가격 %, 할인 %', price, discount;
IF price <= 0 THEN
RAISE EXCEPTION '가격은 0 이하일 수 없어!';
END IF;
IF discount < 0 OR discount > 100 THEN
RAISE EXCEPTION '할인은 0에서 100 사이여야 해!';
END IF;
RETURN price - (price * discount / 100);
END;
$$ LANGUAGE plpgsql;
여기서는 디버깅 단계마다 프로세스 상태에 대한 유용한 메시지를 출력해.
- 최적화 및 문제 해결
- 에러를 찾았으면, 고쳐야지. 성능 문제라면
EXPLAIN ANALYZE같은 분석 도구로 쿼리를 최적화해봐.
디버깅 스킬 실전 적용
실제 예제를 보자: 테이블에 레코드를 추가하고 생성된 id를 반환하는 함수가 있어. 논리적으로 간단해 보이지만, 가끔 함수가 에러로 끝나기도 해. 왜 그런지 알아내고 싶지?
원본 함수:
CREATE FUNCTION add_student(name TEXT, age INTEGER) RETURNS INTEGER AS $$
DECLARE
new_id INTEGER;
BEGIN
INSERT INTO students (name, age) VALUES (name, age) RETURNING id INTO new_id;
RETURN new_id;
END;
$$ LANGUAGE plpgsql;
이 함수를 잘못된 데이터로 호출하면, 예를 들어 age < 0일 때 에러가 나와. 디버깅 도구로 더 좋게 만들어보자.
로깅 추가한 개선 함수:
CREATE FUNCTION add_student(name TEXT, age INTEGER) RETURNS INTEGER AS $$
DECLARE
new_id INTEGER;
BEGIN
-- 입력 데이터 로깅
RAISE NOTICE '학생 추가: 이름 %, 나이 %', name, age;
-- 나이 유효성 체크
IF age < 0 THEN
RAISE EXCEPTION '나이는 음수일 수 없어!';
END IF;
-- 학생 추가하고 ID 반환
INSERT INTO students (name, age) VALUES (name, age) RETURNING id INTO new_id;
-- 성공적으로 처리됐다는 로그
RAISE NOTICE '학생이 ID %로 추가됨', new_id;
RETURN new_id;
END;
$$ LANGUAGE plpgsql;
이제 에러가 나면 RAISE NOTICE 메시지 덕분에 어디서 문제인지 바로 알 수 있어.
마지막으로 꿀팁!
- 실제 코드에서는 불필요한 로깅은 꼭 지워.
RAISE NOTICE는 디버깅할 때는 최고지만, 계속 남겨두면 운영 환경 로그가 너무 복잡해질 수 있어. - 코드를 작게 나눠서 작업해. 함수가 너무 복잡하면 여러 개로 쪼개. 디버깅이 훨씬 쉬워질 거야.
- 자주 연습해. 코드를 많이 짜고 디버깅할수록, 버그 찾고 고치는 속도가 점점 빨라질 거야.
디버깅은 탐정 놀이랑 비슷해. 돋보기 대신 SQL 쿼리랑 PL/pgSQL 논리를 쓰는 거지. 경험이 쌓일수록 실력이 늘고, 버그 하나 고칠 때마다 한 단계 성장하는 거야!
GO TO FULL VERSION