CodeGym /행동 /SQL SELF /함수와 프로시저 간의 상호작용

함수와 프로시저 간의 상호작용

SQL SELF
레벨 55 , 레슨 1
사용 가능

몇 단계 전에 이미 PostgreSQL에서 프로시저와 함수에 대해 얘기했었지. 이제 좀 더 깊게 파보자.

함수랑 프로시저는 따로따로 쓸 수도 있지만, 보통은 둘의 상호작용이 시스템 전체의 성공을 좌우해. 제일 편한 점은, 함수 안에서 다른 함수를 호출할 수 있고, 데이터를 넘기거나 결과값도 받을 수 있다는 거야.

함수 vs 프로시저: 뭐가 다를까?

PostgreSQL에서 함수와 프로시저가 어떻게 다른지 다시 한 번 정리해보자:

  • 함수 (FUNCTION):

    • 값을 반환해.
    • SELECT에서 쓸 수 있어.
    • 주로 계산이나 데이터 변환에 자주 써.
  • 프로시저 (PROCEDURE):

    • 직접적으로 값을 반환하지 않아.
    • 데이터 삽입, 수정, 삭제 같은 작업에 써.
    • CALL 명령어로 호출해.

함수 간 데이터 전달

실전으로 들어가서, 함수와 프로시저 사이에서 데이터를 전달하는 기본 예제를 보자. 사실 함수 간 데이터 전달은 파라미터랑 반환값을 통해 이루어져.

아래는 함수 안에서 다른 함수를 호출하는 예시야:

CREATE OR REPLACE FUNCTION get_student_name(student_id INT)
RETURNS TEXT AS $$
DECLARE
    student_name TEXT;
BEGIN
    -- student_id로 학생 이름 가져오기
    SELECT name INTO student_name FROM students WHERE id = student_id;

    -- 이름 반환
    RETURN student_name;
END;
$$ LANGUAGE plpgsql;

이 함수는 다른 함수에서 이렇게 호출할 수 있어:

CREATE OR REPLACE FUNCTION welcome_student(student_id INT)
RETURNS TEXT AS $$
DECLARE
    message TEXT;
BEGIN
    -- 다른 함수로 학생 이름 받아오기
    message := 'Welcome, ' || get_student_name(student_id) || '!';

    -- 환영 메시지 반환
    RETURN message;
END;
$$ LANGUAGE plpgsql;
  1. get_student_name 함수는 student_id로 학생 이름을 반환해.
  2. 다른 함수인 welcome_student에서는 이 이름을 받아서 환영 메시지를 만들어.

참고: SELECT INTO로 데이터를 뽑으면 PL/pgSQL 변수에 결과가 저장돼.

함수에서 프로시저 호출 예시

이번엔 함수에서 프로시저를 호출하는 방법을 보자. 예를 들어, 학생이 시스템에 로그인한 시간을 기록하는 프로시저가 있다고 해보자:

CREATE OR REPLACE PROCEDURE log_student_entry(student_id INT)
LANGUAGE plpgsql
AS $$
BEGIN
    INSERT INTO log_entries(student_id, entry_time)
    VALUES (student_id, NOW());
END;
$$;

이제 이 프로시저를 함수에서 호출해서, 로그인 기록을 남기고 메시지를 반환해보자:

CREATE OR REPLACE FUNCTION student_login(student_id INT)
RETURNS TEXT AS $$
BEGIN
    -- 로그 기록용 프로시저 호출
    CALL log_student_entry(student_id);

    -- 메시지 반환
    RETURN '학생 로그인 기록 완료.';
END;
$$ LANGUAGE plpgsql;

실전 상호작용 예제

예제 1: 주문 총액 계산과 주문 로그 기록

온라인 주문 시스템을 만든다고 해보자. 주문의 총액을 계산하는 함수가 있어:

CREATE OR REPLACE FUNCTION calculate_order_total(order_id INT)
RETURNS NUMERIC AS $$
DECLARE
    total NUMERIC;
BEGIN
    -- 주문 항목 모두 합산
    SELECT SUM(price * quantity) INTO total
    FROM order_items
    WHERE order_id = order_id;

    RETURN total;
END;
$$ LANGUAGE plpgsql;

주문 총액을 저장하는 프로시저는 이렇게 만들어:

CREATE OR REPLACE PROCEDURE log_order_total(order_id INT, total NUMERIC)
LANGUAGE plpgsql
AS $$
BEGIN
    INSERT INTO order_totals(order_id, total)
    VALUES (order_id, total);
END;
$$;

이제 둘을 연결해보자:

CREATE OR REPLACE FUNCTION process_order(order_id INT)
RETURNS TEXT AS $$
DECLARE
    total NUMERIC;
BEGIN
    -- 총액 계산 함수 호출
    total := calculate_order_total(order_id);

    -- 프로시저로 총액 기록
    CALL log_order_total(order_id, total);

    RETURN '주문 처리 완료.';
END;
$$ LANGUAGE plpgsql;

예제 2: 학생 최고 점수 가져오기와 프로필 업데이트

최고 점수를 가져오는 함수:

CREATE OR REPLACE FUNCTION get_highest_rating(student_id INT)
RETURNS INT AS $$
DECLARE
    max_rating INT;
BEGIN
    -- 학생의 최고 점수 찾기
    SELECT MAX(rating) INTO max_rating
    FROM ratings
    WHERE student_id = student_id;

    RETURN max_rating;
END;
$$ LANGUAGE plpgsql;

학생 프로필을 업데이트하는 프로시저:

CREATE OR REPLACE PROCEDURE update_student_profile(student_id INT, max_rating INT)
LANGUAGE plpgsql
AS $$
BEGIN
    UPDATE students
    SET highest_rating = max_rating
    WHERE id = student_id;
END;
$$;

이 둘을 호출하는 함수:

CREATE OR REPLACE FUNCTION refresh_student_profile(student_id INT)
RETURNS TEXT AS $$
DECLARE
    max_rating INT;
BEGIN
    -- 최고 점수 받아오기
    max_rating := get_highest_rating(student_id);

    -- 학생 프로필 업데이트
    CALL update_student_profile(student_id, max_rating);

    RETURN '프로필 업데이트 완료.';
END;
$$ LANGUAGE plpgsql;

상호작용에서 흔한 실수

가장 흔한 실수 중 하나는 함수와 프로시저 사이의 데이터 타입이 안 맞는 거야. 예를 들어, 프로시저가 NUMERIC 타입을 기대하는데 INTEGER를 넘기면 PostgreSQL이 타입 불일치 에러를 내. 항상 데이터 타입이 맞는지 확인하자.

또 다른 실수는 함수 A가 함수 B를 호출하고, B가 다시 A를 호출하는 식의 순환 호출이야. 이러면 무한 루프가 돌면서 시스템이 뻗어버려.

실전에서 왜 중요할까?

왜 이런 상호작용이 필요할까? 실제로 함수와 프로시저는 복잡한 시스템의 "블록"처럼 동작해. 코드를 독립적인 부분으로 나눌 수 있어서 디버깅, 재사용, 테스트가 훨씬 쉬워져. 예를 들어:

  • 면접에서 복잡한 작업을 위해 프로시저를 호출하는 함수를 짜보라고 할 수도 있어. 이런 상호작용을 잘 보여주면 점수 따기 좋아.
  • 실제 앱(쇼핑몰, 로그 시스템, CRM 등) 개발할 때 함수와 프로시저를 잘 나눠서 쓰면 코드가 훨씬 깔끔해져.

함수와 프로시저의 상호작용을 더 공부하고 싶으면 PL/pgSQL 공식 문서를 참고해봐.

코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION