MSSQL

[Procedure] Procedure 는 뭘까?

정희재 2022. 1. 24. 23:48

첫 취직을 하고 나서 처음 만나게된 아주 낯선 녀석이 있다.

Procedure 라는 것이다.

'프로시저' 라고 불리는 이 녀석, 뭐하는 녀석일까?

먼저 네이버 지식백과에서 정의하는 프로시저 에 대해 알아보면,

"어떤 일을 수행하기 위해 해야할 일들을 단계적으로 적어놓은 것." 이라고 한다.

그럼 프로그래밍에서의 프로시저란 대충 함수 같은 것일거라고 생각할 수 있다.

틀린 말은 아니다.

여러 명령을 하나의 집합으로 정의해서 사용한다는 점에서 함수라고 할 수 있다.

 

물론 함수와 프로시저에는 차이가 있다.

그 차이에 대해서는 크게 안중요하니까 다음에 알아보자. 

 

그럼 이 프로시저라는 것은 어디에서 쓰일까?

DB 쿼리를 실행하는데 사용된다.

DB 쿼리란 흔히들 생각하는 SELECT FROM , INSERT INTO 이런 것들이다.

프로시저는 여러 개의 쿼리문을 하나의 함수로 만들어서 어떤 동작을 일괄적으로 처리하는 용도로 사용된다.

 

대충 이렇다.

 

프로시저는 왜 쓰는 것일까?

"함수는 왜 쓰는가?" 라는 질문에 스스로 대답을 해보자.

그게 프로시저를 사용하는 대략적인 이유일 것이다.

 

대표적인 예시를 하나만 들어보자.

게임 상에서 아이템 구입을 구현한다고 생각해보자.

필요한 쿼리는 크게 4개 정도가 필요하다.

 

1. 유저가 가지고 있는 돈의 양을 조회한다. (SELECT)

2. 구매할 아이템의 가격을 조회한다. (SELECT)

3. 유저의 돈에서 구매할 아이템의 가격만큼을 뺀다. (UPDATE)

4. 유저의 아이템 창에 구매한 아이템을 추가한다. (UPDATE)

 

쿼리를 실행할 때마다 DB 서버에 연결을 시도할 것이다.

그럼 총 4번의 DB 연결을 시도한다.

누가봐도 맘에 안든다.

 

저 4개의 쿼리들을 하나의 프로시저 안에 정의해서 사용한다면 한 번의 DB 연결만으로 아이템 구매가 가능하다.

만약 DB서버와 통신이 잦은 서비스라면 프로시저의 장점이 발휘될 수 있다.

 

그 외에도 다양한 장점들이 있다.

프로시저는 한 번 만들어서 컴파일하고 나면 DB 캐시에 저장된다.

만약 여러 군데에서 하나의 프로시저를 자주 호출한다면 프로시저의 장점을 적극 활용한 것이라고 볼 수 있다.

 

프로시저도 함수처럼 Input과 Output을 지정해서 사용할 수 있다.

함수처럼 파라미터와 리턴값을 지정해준다고 이해하면 쉽다.

따라서 다양한 용도로 프로시저를 구현할 수 있다.

 

프로시저 내에서 if, while 등 우리가 흔히 알고 있는 제어문장을 사용할 수 있다.

그래서 데이터의 유효성 검증이 프로시저 내에서 가능하고 상황에 따라 트랜잭션을 롤백 함으로써 DB의 무결성을 유지할 수 있다.

 

프로시저마다 Lock TimeOut 이나 Isolation Level 등을 각각 설정해줄 수 있다.

필요에 따라 제약사항이나 격리 수준을 조정할 수 있다.

 

마지막으로 프로시저를 업데이트했을 때 DB 서버에만 적용하면 되기 때문에 웹 서버를 다시 껐다 켜줄 필요가 없다.

 

자, 그래서 이 프로시저라는 것은 대체 어떻게 생겨먹었는가?

MSSQL을 예시로 들면 이렇게 생겼다.

CREATE PROCEDURE [프로시저 이름]
    -- 인풋 정의
    @age     INT
   ,@city    NVARCHAR(100)
   
    -- 아웃풋 정의
   ,@result  INT           OUTPUT
   ,@count   INT           OUTPUT
   
-- 프로시저 정의
AS
BEGIN
    SET LOCK_TIMEOUT 5000
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

    SET @result = 0
    
    BEGIN TRY
        SELECT *
        FROM [테이블]
        WHERE age >= @age
        AND city = @city
    
        SET @count = @@ROWCOUNT
    END TRY
    BEGIN CATCH
        SET @result = ERROR_NUMBER()
    END CATCH
END
GO

대충 설명을 하면

프로시저의 Input과 Output을 정의하고,

실행하려는 쿼리를 적고,

TRY, CATCH를 이용해 예외처리를 할 수 있다.

@@ROWCOUNT는 쿼리 결과 조회된 ROW 개수를 반환해주는 내장 기능,

ERROR_NUMBER() 에러 발생시 에러 번호를 반환해주는 내장 기능이다.

 

이런식으로 작성해서 SQL Server에 저장해놓고

Flask, Django, Spring, Node.js, ASP.NET 등 뭐 다양한 프레임워크가 있을건데,

각 프레임워크의 방식에 맞게 프로시저를 호출하면 된다.

누군가의 블로그나 스택오버플로우를 참고하면 쉽게 따라할 수 있을 것이다.

 

프로시저와의 첫 만남은 이정도면 충분한 것 같다.

 

 

 

 

물론... 이러한 프로시저에도 단점은 있다.

단점에 대해 자세히 언급한다면 마음이 아프기 때문에 간략하게만 언급해보자.

1. 문자나 숫자 연산에 대해서 처리 성능이 낮다.

2. 디버깅이 어렵다.

3. DB 확장이 어렵다.

 

 

참고

[네이버 지식백과] https://terms.naver.com/entry.naver?docId=3612007&cid=58598&categoryId=59316 

[런코딩 블로그] https://runcoding.tistory.com/31

[siahn95 블로그] https://siahn95.tistory.com/entry/DBMSSQL-%EC%A0%80%EC%9E%A5-%ED%94%84%EB%A1%9C%EC%8B%9C%EC%A0%80Stored-Procedure%EB%9E%80