PERFORM는 PostgreSQL 세계에서 진짜 조용한 히어로야. 와서 할 일 딱 하고, 아무런 반환값도 남기지 않고 사라져. 이 명령어는 PL/pgSQL 함수 안에서 SQL 쿼리를 실행하고 싶지만, 결과값은 필요 없을 때 쓰는 거야. PERFORM의 주된 목적은 뭔가를 일어나게 만드는 거지, 예를 들면 데이터 수정이나 다른 함수 호출 같은 거. 결과값을 받으려고 쓰는 게 아니야.
PERFORM는 쿼리 결과가 필요 없을 때 쓰는 거야. 일반적인 SELECT는 결과를 뭔가 처리하길 기대하지만, PERFORM는 그냥 쿼리 실행하고 조용히 넘어가. 함수의 동작 자체가 목적일 때, 예를 들어 로그 남기기 같은 거 할 때 진짜 편해. 이런 방식은 코드를 더 심플하고 이해하기 쉽게 만들어줘. 쓸데없는 게 줄고, 의미만 남는 거지.
PERFORM 사용 예제
함수 호출
실제 예제로 한번 볼까. log_action이라는 함수가 있다고 해보자. 이 함수는 사용자의 행동을 로그에 남겨. 반환값은 없고, 그냥 실행만 되면 돼. PERFORM로 이렇게 쓸 수 있어:
CREATE OR REPLACE FUNCTION log_action(user_id INT, action TEXT) RETURNS VOID AS $$
BEGIN
INSERT INTO logs (user_id, action, log_time)
VALUES (user_id, action, NOW());
END;
$$ LANGUAGE plpgsql;
-- 이제 PERFORM으로 이 함수를 호출해보자:
PERFORM log_action(5, '사용자가 로그인함');
여기서 무슨 일이 일어나냐면, PERFORM가 log_action 함수를 호출해서 logs 테이블에 기록을 남겨. 함수 호출 결과는 무시돼. 오직 그 효과만 필요해서 쓰는 거야, 반환값은 신경 안 써.
데이터 업데이트
가끔 PERFORM는 데이터 변경 쿼리를 실행할 때도 좋아. 결과값엔 관심 없을 때 말이지. 예를 들어 orders 테이블에서 주문 상태를 바꿔보자.
CREATE OR REPLACE FUNCTION update_order_status(order_id INT, new_status TEXT) RETURNS VOID AS $$
BEGIN
UPDATE orders
SET status = new_status
WHERE id = order_id;
END;
$$ LANGUAGE plpgsql;
-- PERFORM으로 이 함수 호출:
PERFORM update_order_status(101, '배송됨');
여기서 update_order_status는 주문 번호 101의 상태를 바꿔줘. 함수 안의 SQL 쿼리 결과엔 관심 없으니까 PERFORM가 딱이야.
보조 작업 실행
가끔 함수 안에 "보조" 로직이 들어가서 복잡한 프로세스를 마무리하는 데 도움을 줘. 예를 들어, 테이블 업데이트 후 캐시를 비우고 싶을 때:
CREATE OR REPLACE FUNCTION clear_cache() RETURNS VOID AS $$
BEGIN
DELETE FROM cache_table;
END;
$$ LANGUAGE plpgsql;
-- 다른 함수에서 호출:
CREATE OR REPLACE FUNCTION update_product(product_id INT, new_price NUMERIC) RETURNS VOID AS $$
BEGIN
UPDATE products
SET price = new_price
WHERE id = product_id;
-- 데이터 변경 후 캐시 비우기:
PERFORM clear_cache();
END;
$$ LANGUAGE plpgsql;
이게 바로 마법이지: PERFORM로 결과값이 필요 없는 함수들을 연달아 실행할 수 있어.
실전 과제
PERFORM가 개발자 인생을 얼마나 편하게 해주는지 몇 가지 예제로 볼까.
예제 1: 프로시저 단계별 로그 남기기
복잡한 결제 처리 프로시저가 있다고 해보자. 각 단계를 로그로 남기고 싶어. log_stage라는 함수를 만들고, PERFORM로 호출하면 돼:
CREATE OR REPLACE FUNCTION log_stage(stage_name TEXT) RETURNS VOID AS $$
BEGIN
INSERT INTO process_logs(stage, log_time)
VALUES (stage_name, NOW());
END;
$$ LANGUAGE plpgsql;
-- 프로시저 예시:
CREATE OR REPLACE FUNCTION process_payment(payment_id INT) RETURNS VOID AS $$
BEGIN
-- 시작 로그
PERFORM log_stage('결제 처리 시작');
-- 첫 단계 실행
UPDATE payments
SET status = '처리중'
WHERE id = payment_id;
PERFORM log_stage('결제 상태 업데이트됨');
-- 마지막 단계 실행
UPDATE payments
SET status = '완료됨'
WHERE id = payment_id;
PERFORM log_stage('결제 완료');
END;
$$ LANGUAGE plpgsql;
여기서 log_stage는 PERFORM로 각 단계마다 실행 상태를 기록해. 디버깅할 때 코드가 훨씬 쉬워져.
예제 2: 알림 활성화
알림 시스템이 있다고 해보자. 중요한 작업마다 알림을 보내야 해. PERFORM로 알림 보내는 함수를 호출할 수 있어:
CREATE OR REPLACE FUNCTION send_notification(user_id INT, message TEXT) RETURNS VOID AS $$
BEGIN
INSERT INTO notifications (user_id, message, created_at)
VALUES (user_id, message, NOW());
END;
$$ LANGUAGE plpgsql;
-- 프로시저에서 사용:
CREATE OR REPLACE FUNCTION complete_task(task_id INT) RETURNS VOID AS $$
DECLARE
user_id INT;
BEGIN
-- 작업 담당자 가져오기
SELECT assigned_to INTO user_id
FROM tasks
WHERE id = task_id;
-- 작업 완료 처리
UPDATE tasks
SET status = '완료됨'
WHERE id = task_id;
-- 알림 보내기
PERFORM send_notification(user_id, '네 작업이 완료됐어');
END;
$$ LANGUAGE plpgsql;
여기서 PERFORM는 오직 부수 효과(알림 보내기)에만 집중하게 해주고, 함수 결과는 무시해.
꿀팁 & 흔한 실수
PERFORM를 쓸 때 몇 가지 주의할 점이 있어. 예를 들어, PERFORM는 쿼리가 데이터를 반환했는지 확인하지 않아. 즉, 함수나 SQL 쿼리 결과가 로직상 중요하다면 SELECT INTO를 써야 해. 예시로 볼게:
-- 잠재적 실수
PERFORM 반드시_값을_반환해야하는_함수();
-- 올바른 방법
SELECT 반드시_값을_반환해야하는_함수() INTO some_variable;
또 하나 흔한 실수는, 쿼리 결과가 필요한데 PERFORM를 쓰는 거야. 예를 들어 데이터 검증 같은 경우엔 결과를 받아서 체크해야 해.
실제 프로젝트에서 PERFORM는 함수와 프로시저를 더 심플하고 읽기 쉽고 디버깅하기 쉽게 만들어줘. RAISE NOTICE 같은 로깅, PostgreSQL 내장 진단 함수(current_query())랑 같이 쓰면, 신뢰성 있고 관리하기 쉬운 시스템 만드는 데 진짜 유용한 도구야.
GO TO FULL VERSION