게으른 개발자의 끄적거림

프로시저란?

끄적잉 2024. 8. 21. 22:56
728x90

프로시저(Procedure)는 데이터베이스 시스템에서 매우 중요한 개념으로, 특히 관계형 데이터베이스(RDBMS)에서 빈번하게 사용됩니다. 프로시저는 특정 작업을 수행하기 위해 작성된 일련의 SQL 문(statement)들을 말하며, 하나의 함수나 메소드처럼 동작합니다. 사용자는 이 프로시저를 호출함으로써 복잡한 작업을 간단히 실행할 수 있습니다.

 


### 1. 프로시저의 개념과 역할

프로시저는 데이터베이스 내에서 반복적으로 수행해야 하는 작업을 자동화하고, 코드의 재사용성을 높이며, 복잡한 데이터 처리 작업을 단순화하는 데 중요한 역할을 합니다. 특히, 다음과 같은 이유로 프로시저가 사용됩니다:

- **반복 작업의 자동화**: 매번 동일한 SQL 문을 여러 번 실행해야 할 때, 프로시저를 사용하면 한 번의 호출로 그 작업을 수행할 수 있습니다. 예를 들어, 매달 월말 정산을 위한 데이터 업데이트 작업을 자동화하는 프로시저를 작성할 수 있습니다.
- **코드의 재사용성**: 동일한 SQL 코드를 여러 곳에서 사용해야 할 때, 그 코드를 프로시저로 묶어 놓으면 재사용이 매우 용이합니다. 이렇게 하면 코드 중복을 피할 수 있고, 코드의 유지보수가 쉬워집니다.
- **복잡한 로직의 단순화**: 복잡한 비즈니스 로직이나 데이터 처리 로직을 SQL 문으로만 작성하려고 하면 코드가 매우 길고 복잡해질 수 있습니다. 프로시저를 사용하면 이러한 로직을 단계별로 쪼개어 보다 이해하기 쉬운 코드로 구성할 수 있습니다.

 

728x90


### 2. 프로시저의 구조

일반적으로 프로시저는 다음과 같은 구조로 구성됩니다:

1. **프로시저 헤더**: 프로시저의 이름과 입력 파라미터를 정의하는 부분입니다. 이 부분에서는 프로시저의 입력 파라미터의 타입과 이름을 지정하며, 필요에 따라 출력 파라미터도 정의할 수 있습니다.

   ```sql
   CREATE PROCEDURE 프로시저명 (입력파라미터1 타입, 입력파라미터2 타입, ...)
   ```

 


2. **프로시저 바디**: 프로시저가 실제로 수행하는 작업을 정의하는 부분입니다. 여기에는 변수 선언, 제어문(조건문, 반복문 등), SQL 문 등 다양한 코드가 포함될 수 있습니다.

   ```sql
   BEGIN
       -- 변수 선언
       -- SQL 문 실행
       -- 제어문 사용
   END;
   ```

 


3. **예외 처리**: 프로시저가 실행되는 동안 발생할 수 있는 오류를 처리하는 부분입니다. SQL에서는 `EXCEPTION` 블록을 사용하여 예외 상황에 대응할 수 있습니다.

   ```sql
   EXCEPTION
       WHEN 예외상황1 THEN
           -- 예외 처리 로직
       WHEN 예외상황2 THEN
           -- 예외 처리 로직
   END;
   ```

 


### 3. 프로시저의 장단점

#### 장점:

1. **성능 향상**: 프로시저는 데이터베이스 서버에서 직접 실행되기 때문에, 클라이언트-서버 간의 통신 비용을 줄이고 성능을 향상시킬 수 있습니다. 특히, 여러 개의 SQL 문이 포함된 작업을 하나의 프로시저로 묶어 실행하면 그만큼 네트워크 통신이 줄어들어 속도가 빨라집니다.

2. **보안 강화**: 프로시저는 데이터베이스 객체에 대한 접근을 제한하는 데 사용할 수 있습니다. 예를 들어, 특정 사용자가 테이블에 직접 접근하지 않고, 프로시저를 통해서만 데이터를 조작할 수 있도록 권한을 설정할 수 있습니다.

3. **유지보수성**: 비즈니스 로직을 데이터베이스 레벨에서 처리하게 되면, 응용 프로그램의 코드베이스에서 중복되는 SQL 문이 줄어들어 유지보수가 용이해집니다.

4. **트랜잭션 관리**: 프로시저는 하나의 트랜잭션으로 간주될 수 있어, 여러 SQL 문이 실행되는 동안 발생하는 오류를 쉽게 처리할 수 있습니다. 즉, 하나의 프로시저 내에서 여러 작업을 수행하다가 오류가 발생하면, 전체 작업을 롤백하여 데이터 일관성을 유지할 수 있습니다.

 

#### 단점:

1. **이식성 문제**: 프로시저는 특정 데이터베이스 시스템에 종속적일 수 있습니다. 예를 들어, Oracle에서 작성된 프로시저는 MySQL이나 SQL Server에서 동작하지 않을 수 있습니다. 이는 서로 다른 DBMS의 SQL 문법과 기능이 다르기 때문입니다.

2. **디버깅의 어려움**: 프로시저는 데이터베이스 서버에서 실행되므로, 클라이언트 측에서 디버깅이 어렵습니다. 디버깅 도구가 지원되기도 하지만, 대부분의 경우 프로시저 내부에서 발생한 오류를 추적하는 데 어려움을 겪을 수 있습니다.

3. **복잡성 증가**: 비즈니스 로직이 복잡해지면 프로시저도 복잡해질 수 있습니다. 프로시저가 지나치게 복잡해지면 오히려 코드의 유지보수와 이해가 어려워질 수 있습니다.

 


### 4. 프로시저 작성 예제

아래는 Oracle DBMS를 예로 든 간단한 프로시저 작성 예제입니다. 이 프로시저는 특정 사원의 급여를 인상하는 작업을 수행합니다.

```sql
CREATE OR REPLACE PROCEDURE INCREASE_SALARY (
   p_employee_id IN EMPLOYEES.EMPLOYEE_ID%TYPE,
   p_increment IN NUMBER
)
IS
   v_current_salary EMPLOYEES.SALARY%TYPE;
BEGIN
   -- 현재 급여를 조회
   SELECT SALARY INTO v_current_salary
   FROM EMPLOYEES
   WHERE EMPLOYEE_ID = p_employee_id;

   -- 급여 인상
   UPDATE EMPLOYEES
   SET SALARY = v_current_salary + p_increment
   WHERE EMPLOYEE_ID = p_employee_id;

   -- 변경 사항을 커밋
   COMMIT;
EXCEPTION
   WHEN NO_DATA_FOUND THEN
       DBMS_OUTPUT.PUT_LINE('사원 ID가 잘못되었습니다.');
   WHEN OTHERS THEN
       DBMS_OUTPUT.PUT_LINE('알 수 없는 오류가 발생했습니다.');
END;
```

이 예제에서 `INCREASE_SALARY` 프로시저는 두 개의 파라미터를 받습니다: `p_employee_id`와 `p_increment`. `p_employee_id`는 급여를 인상할 사원의 ID이고, `p_increment`는 인상할 급여의 양입니다. 프로시저는 먼저 해당 사원의 현재 급여를 조회한 후, 급여를 인상하고, 마지막으로 트랜잭션을 커밋합니다. 예외 상황에서 적절한 메시지를 출력하도록 `EXCEPTION` 블록을 포함하고 있습니다.

### 5. 프로시저의 실행과 관리

프로시저는 데이터베이스 관리자나 개발자가 작성하며, SQL 문을 통해 호출됩니다. 다음은 Oracle DBMS에서 프로시저를 실행하는 방법입니다:

```sql
BEGIN
   INCREASE_SALARY(1001, 500);
END;
```

위의 SQL 문은 사원 ID가 1001인 사원의 급여를 500만큼 인상하는 프로시저를 호출하는 예입니다.

프로시저는 데이터베이스에 저장되며, 필요할 때마다 호출할 수 있습니다. 이를 통해 동일한 작업을 여러 번 반복할 필요 없이 한 번의 호출로 작업을 수행할 수 있습니다.

### 6. 프로시저와 함수의 차이점

프로시저와 함수는 매우 유사한 개념이지만, 중요한 차이점이 있습니다. 함수는 값을 반환해야 하는 반면, 프로시저는 그렇지 않을 수도 있습니다. 다음은 그 차이점을 요약한 것입니다:

- **반환값**: 함수는 항상 단일 값을 반환합니다. 반면, 프로시저는 값을 반환하지 않거나, 출력 파라미터를 통해 여러 개의 값을 반환할 수 있습니다.
- **용도**: 함수는 주로 계산 작업을 수행하여 값을 반환하는 데 사용됩니다. 프로시저는 보다 복잡한 작업을 수행하고, 그 결과를 데이터베이스에 반영하는 데 사용됩니다.
- **호출**: 함수는 SQL 문의 일부로 호출될 수 있지만, 프로시저는 독립적으로 호출되어야 합니다.

예를 들어, 다음은 동일한 작업을 수행하지만, 하나는 함수이고, 다른 하나는 프로시저입니다:

```sql
-- 함수
CREATE FUNCTION GET_TOTAL_SALARY (
   p_department_id IN EMPLOYEES.DEPARTMENT_ID%TYPE
) RETURN NUMBER
IS
   v_total_salary NUMBER;
BEGIN
   SELECT SUM(SALARY) INTO v_total_salary
   FROM EMPLOYEES
   WHERE DEPARTMENT_ID = p_department_id;
   
   RETURN v_total_salary;
END;

-- 프로시저
CREATE PROCEDURE PRINT_TOTAL_SALARY (
   p_department_id IN EMPLOYEES.DEPARTMENT_ID%TYPE
)
IS
   v_total_salary NUMBER;
BEGIN
   SELECT SUM

728x90