출처 : https://12bme.tistory.com/247

   http://kikook.tistory.com/499


일단 pro-c 를 사용하는 이유에 대해 알아봅시다.


현업자들의 Comment


Comment (1) : DB처리가 가장 빠른 건 PL/SQL입니다. 그다음이 pro*c고요
속도만이 문제였다면 아마 PL/SQL을 쓰겠죠. 
pro*c를 쓰는 이유는 PL/SQL이 단점을 가지고 있기 때문입니다. 부하분산이 어렵다는..
보통 pro*c를 쓸땐 TP-모니터를 같이 씁니다. 턱시도같은...
AP서버 여러대를 써서 부하분산을 합니다. 일반적인 쓰리티어 구조죠.

Comment (2) : 사실 자바시스템도 마찬가지긴 합니다. WAS가 트랜잭션처리와 UI처리를 같이 해주는 거 뿐이죠. DB처리 속도도 JDBC가 꾸준히 업그레이드되면서 많이 좋아졌습니다. 다만 미션크리티컬한 사이트에서는 자바의 트랜잭션 처리에 의구심이 강합니다. 은행같은 금융이 그렇죠. 자바초기에 사건이 많았었기 때문에.. ^^ WAS는 UI구성만 맡기고 졸트로 TP-모니터에 연결해 트랜잭션 처리는 pro*c에 맡깁니다. 비용은 많이 들겠지만 더 신뢰할 수 있는 시스템을 원한다면 그렇게 해야겠죠.


Comment (3) : pro*c를 쓰는 가장 큰 이유는 가장 안정적이기 때문입니다. 또한 배치 프로그램도 java 처럼 힙메모리 제한이 없어 대용량 데이터 처리에 안정적이고 알맞기 때문에 pro*c로 개발합니다. pro*c로 개발했다고 해서 java보다 DB처리 속도에 대한 이득은 없습니다.



pro-c 개요



Pro-c란 Oracle rdbms에 준비된 pro-c 툴은, sql문을 포함한 c 프로그램을 oracle 데이터베이스내에 있는 데이터에 접근과 조작을 할 수 있는 c 프로그램으로 변환하기 위한 것이다.

pro-c는 프리컴파일러이기 때문에 입력 파일 내에 있는 exec sql 문을 적당한 oracle 콜로 변환해서 출력 파일을 작성한다. 그 다음 이 출력 파일을 c프로그램에 대한 통상의 방법으로 컴파일하고 링크해서 실행모듈을 작성한다. 


SQL 문은 절차형 언어가 아닙니다. 그래서 오라클을 포함한 많은 데이터베이스는 PL/SQL이라는 절차형 언어를 제공합니다. PL/SQL은 오라클 내부에서 실행되는 프로그램으로서 오라클 내부라는 한정된 공간에서 실행되는 도구입니다.


DBMS의 버전이 높아지면서 이전관 다르게 PL/SQL에도 다양한 기능이 추가 되었습니다. 예를 들면, TCP/IP, HTTP, FILE I/O 등과 같은 기능이 추가되어 다양한 방식의 프로그래밍이 가능해졌습니다. 하지만 오라클 외부 프로그램과의 연동 등에 있어서는 많은 제약이 있습니다. 예를 들어, TCP/IP 통신을 하는 PL/SQL 문장을 작성하여 수행하는 중에 메모리 할당 등 예기치 않은 오류로 프로그램이 종료되는 상황이 발생할 수 있습니다. 프로그램이 오류로 인해 종료되는 부분은 프로그램을 수정하여 해결이 가능합니다. 하지만 이로 인해 오라클 엔진에 부하가 가해진다면 이는 돌이킬 수 없는 장애로 이어질 수 있습니다. 이렇듯 내부 PL/SQL을 통한 프로그램의 경우 오라클이라는 내부 울타리에서만 수행되는 특징이 큰 제약으로 작용합니다.


이런 고민을 해결하기 위해서 대부분의 DBMS 벤더는 외부 C 프로그램과 결합할 수 있는 선행 컴파일러를 제공하고 있으며 오라클에서는 이를 Pro*C라고 합니다. Pro*C는 PL/SQL과 같이 절차적 프로그래밍이 가능한 프로그램 도구로서 PL/SQL처럼 오라클 내부에서 수행되는 프로그램이 아니라 실행 가능한 외부 프로그램으로 작성이 되어 관련 작업을 수행할 수 있게 해 주는 도구입니다.


다만 일반 프로그램 언어들과 다른 점이 있다면, Pro*C만으로는 실행 파일을 만들어 낼 수 없다는 것입니다. 그래서 Pro*C를 Pre Compiler(설행 컴파일러)라고 합니다. Pro*C는 선행 컴파일러이기 때문에 선행 컴파일을 통해서 실행 파일이 아닌 C 컴파일러가 인식할 수 있는 출력 파일(xxx.c)을 생성합니다. 선행 컴파일러를 통해 생성된 C 프로그램은 C 프로그램의 통상적인 방법으로 컴파일되고, 오라클 라이브러리와 결합(링크)되어 실행 모듈이 만들어집니다.


Pro*C 프로그래밍을 위해서는 Pro*C 고유의 문법을 숙지하고 있어야 하지만 C 프로그래밍에 대한 기본 지식도 있어야 합니다. 특히 메모리와 관련된 부분이나 포인터 등과 같은 C의 고급 기능을 사용하기 위해서는 C 프로그래밍에 대한 지식을 갖추고 있어야 합니다. 그리고 C 프로그램은 기본적으로 OS의 특성에도 많은 영향을 받으므로 OS의 고유한 특성도 공부해야 합니다.


Pro*C를 처음 접하는 처음 접하는 분들에게 너무 많은 부담감을 드린 듯하지만 대부분의 개발자가 작성하는 일반적인 배치 프로그램이나 미들웨어 연동 프로그램의 경우에는 C에 대해 많이 알고 있지 않아도 정상적인 개발과 운영이 가능합니다. 물론 조금 더 심도 있는 프로그래밍을 위해서는 C의 고급 기능이나 OS의 고유한 특성을 자세히 알고 있어야 합니다.


그러나 이 책을 공부함에 있어서 C에 대해 많이 알고 있지 않아도 무방합니다. 기초 단계를 넘어 고급 단계로 가기 위해서 무엇이 필요한지 미리 알아본 것이므로 크게 부담감을 갖지 않아도 됩니다.


 프로그램 작성 방식


4GL 프로그램으로 DB 핸들링 프로그램을 작성하기 위해서 가장 먼저 할 일은 DB 접속 방식을 선택하는 것입니다. ODBC 방식으로 할 것인지, OLE-DB 방식으로 진행할 것인지를 선택한 후에 그에 맞는 프로그램 방식을 결정해야 합니다.


Pro*C 역시 다르지 않습니다. GUI 방식의 4GL 프로그램처럼 마우스 클릭을 통해 설정할 수 있는 것이 아니라 코딩 시점에 Header 파일 선정, 프로그램 방식의 선정, 컴파일 옵션의 변경을 통해 작성 방식을 선택하여 사용할 수 있습니다. Pro*C에서 프로그램 작성 방식은 두 가지로 나누어지며, 하나는 내장 SQL 방식이고, 다른 하나는 OCI(Oracle Call Interface) 방식입니다.



(1) 내장 SQL 방식

내장 SQL 방식이란 C 프로그램 내부에서 'EXEC SQL'이라는 접두사 뒤에 SQL 문장을 직접 기술하는 방식입니다. 내장 SQL 방식은 통상적으로 가장 많이 사용됩니다. 우리에게 익숙한 윈도우 환경의 개발툴과 비교해 본다면, OLE나 ODBC를 통해 데이터베이스와 연결하여 작업하는 방식의 프로그램과 비슷하다고 할 수 있습니다. 


이 책에서도 가장 대중적인 방식인 내장 SQL 방식을 기준으로 실습 예제를 만들고 설명할 것입니다. 내장 SQL 문장에는 일반 SQL 문장뿐만 아니라 오라클을 이용한 다양한 형식의 내부 문장을 사용할 수 있으며, 미리 생성되어 있는 Stored Procedure, Package 또는 개발자가 임의로 작성한 PL/SQL도 사용할 수 있습니다. 즉, 오라클 데이터베이스에서 사용하는 모든 문장, 즉 DML, DDL, DCL, PL/SQL, 일반 SQL 문장을 내장 SQL 문장에 사용할 수 있습니다.


내장 SQL 문장에 사용할 수 있는 명려어는 아래 표(내장 SQL 문장 구문 방식의 프로그램 구문)와 같습니다.


 명령어

 설명

 ARRAYLEN

 PL/SQL에서 호스트 array를 사용한다.

 BEGIN DECLARE SECTION

 END DECLARE SECTION

 ANSI 모드에서 호스트 변수를 사용한다.

 DECLARE

 내부 오브젝트를 선언한다.

 INCLUDE

 외부 *.h를 참조한다.

 TYPE

 임의 데이터 타입을 설정한다.

 VAR

 변수의 동일화

 WHENEVER

 runtime 에러 핸들링 문장

 ALLOCATE

 CURSOR 변수에 영역을 할당한다

 ALTER

 오라클의 정의

 ANALYZE
 AUDIT
 COMMENT
 CONNECT
 CREATE
 DROP
 GRANT
 NOAUDIT
 RENAMERE
 VOKE
 TRUNCATE
 CLOSE

 오라클에 접속 제어 오브젝트 변경 문장

 DELETE
 FETCH
 INSERT
 LOCK TABLE
 OPEN
 SELECT
 UPDATE
 EXPLAIN PLAN

 데이터 조작 및 데이터 추출문

 COMMIT
 ROLLBACK
 SAVEPOINT
 SET TRANSACTION

 트랜잭션 제어 문

 DESCRIBE
 EXECUTEPREPARE

 Dynamic SQL 사용을 위한 문

 ALTER SESSION
 SET ROLE

 세션 제어 문



(2) OCI 방식

OCI(Oracle Call Interface) 방식이란 OCI 라이브러리를 통해서 오라클 SQL 문장을 직접 호출하여 사용하는 방식입니다. 내장 SQL 방식에 비해서 조금 더 하위 레벨에 해당하는 프로그래밍 방식으로서 OCI를 통해서 DB 핸들링 작업을 실행하기 때문에 데이터베이스 서버의 자원을 효율적으로 관리하고 SQL 문장 수행의 각 단계를 직접 제어할 수 있다는 장점이 있습니다.


그러나 프로그래밍 방법에 있어 내장 SQL 프로그램에 비해 복잡하기 때문에 개발자의 숙련도가 요구된다는 단점이 있습니다. Unix 환경의 C 프로그램을 대부분의 개발자들은 쉽게 생각하기보다는 어렵게 생각하고 있습니다. 이는 대부분의 제어를 개발자가 직접 기술해야 하기 때문입니다. 반면에 GUI 프로그램은 마우스 클릭 몇번만으로 대부분의 설정이 가능해집니다. 이렇듯 OCI 프로그램에서는 모든 부분의 직접 제어나 기술이 내장 SQL 프로그램에 비해서 어렵게 여겨지는 것입니다. 물론 대부분의 프로그램에는 특정한 패턴이 있으므로 그 패턴을 익히기만 하면 어떤 프로그램 방식이 더 쉽다, 혹은 더 어렵다고 단정지을 수는 없습니다.


대부분의 경우라고 할 수는 없지만 적지 않은 개발자들이 내장 SQL 문장 방식을 사용하고 있습니다. 이 책에서도 내장 SQL 문장 방식을 사용하며, OCI 방식 프로그램에 대해서는 다루지 않습니다. OCI 방식의 프로그램 방법을 더 자세히 알고 싶으면 오라클 사이트에 관련 예제를 어렵지 않게 구할 수 있으므로 이를 참고하면 됩니다.


 내장 SQL 방식

OCI 방식

 SQL 연산을 쉽고 명료하게 처리하기 위해 3GL 어플리케이션 개발

 데이터베이스를 최대한 제어하면서 3GL 어플리케이션 개발

 간결한 코드 작성

 길고 복잡한 코드 작성

 컴파일 전에 소스 코드 선행 컴파일

 선행 컴파일 단계 없이 코드 컴파일

 선행 컴파일러를 별도로 구매

 오라클 데이터베이스와 함께 OCI 라이브러리 획득

 ANSI 표준 준수(X3.168-1992)

 독점 비 표준 절차적 호출 인터페이스 사용

 다중 행 질의만을 위해 명시적 커서 선언

 모든 데이터베이스 연산을 처리하기 위한 명시적 커서 선언

 선행 컴파일 시에 SQL 구문 확인 

 실행 시간에 SQL 구문 확인




1-4. Pro*C의 데이터 형


Pro*C에서 사용하는 데이터 형은 C 프로그램에서 사용하는 일반적인 데이터 형과 Pro*C에서만 사용할 수 있는 고유한 형태의 데이터 형으로 구성되어 있습니다. 아래의 내용은 Pro*C 프로그램에서 사용하는 데이터 형을 설명한 것입니다.


  • 기본적인 데이터 형의 일차원 배열
  • CHAR 데이터 형과 VARCHAR 데이터 형의 이차원 배열
  • 출력 호스트 변수로 VARCHAR 변수를 사용할 때 오라클은 구조체의 멤버 길이를 설정하지만 배열을 NULL-terminate(\0)시키지는 않습니다. 그러므로 출력하기 전에 출력 호스트 변수를 NULL-terminate 시키십시오. CHAR은 자동 NULL-terminate입니다.
  • 기본적인 데이터 형에 대한 포인터
  • 사용자 정의의 typedef
  • 구조체
  • 배열의 구조체
  • 구조체에 대한 포인터
  • 구조체 배열


아래의 [표 1-3]에서는 C 프로그램에서 일반적으로 사용할 수 있는 데이터 형의 종류와 각 데이터 형의 세부 내용을 설명하였습니다. Pro*C 역시 C 프로그램이기 때문에 C의 일반적인 데이터 형을 사용할 수 있습니다.


 C의 데이터 형

 설명

 char

 단일 문자

 char[n]

 n 바이트의 문자 배열

 int

 정수

 short
 short int

 작은 정수 (지시자 변수에 대한 데이터 형)

 long
 long int

 긴 정수

 floatlong
 float

 부동 소수점, 단정도

 double

 부동 소수점, 배정도

 VARCHAR

 가변 길이 문자



오라클 데이터베이스의 데이터 형과 C 프로그램의 데이터 형은 호환됩니다. 그 내용을 아래 표와 같이 정리할 수 있습니다.


 오라클 DB의 데이터 형

 C의 데이터 형

 설명

 VARCHAR2(Y)
 (Y: 1~2000)

 char

 단일 문자

 CHAR(X)(X:1~255)

 char[n]

 VARCHAR[n]

 int

 short

 float

 n 바이트의 문자 배열
 n 바이트의 가변 문자 배열
 정수

 작은 정수

 부동 소수점

 NUMBER

 NUMBER(P, S)

 int

 short

 long

 float

 double
 char

 char[n]

 VARCHAR[n]

 정수

 작은 정수

 긴 정수

 부동 소수점

 배정도 부동 소수점

 단일 문자

 n 바이트의 문자 배열

 n 바이트의 가변 문자 배열

 DATE

 char[n]

 VARCHAR[n]

 n 바이트의 문자 배열
 n 바이트의 가변 문자 배열

 LONG

 char[n]

 VARCHAR[n]

 n 바이트의 문자 배열
 n 바이트의 가변 문자 배열

 RAW(X)

 unsigned char[n]
 VARCHAR[n]

 n 바이트의 문자 배열

 n 바이트의 가변 문자 배열

 LONG LAW

 unsigned char[n]
 VARCHAR[n]

 n 바이트의 문자 배열
 n 바이트의 가변 문자 배열

 ROWID

 unsigned char[n]
 VARCHAR[n]

 n 바이트의 문자 배열
 n 바이트의 가변 문자 배열

 MLSLABEL

 unsigned char[n]

 VARCHAR[n]

 n 바이트의 문자 배열
 n 바이트의 가변 문자 배열

 주의:  X : 1~255 사이의 값, 디폴트는 1

         Y : 1~2000 사이의 값

         P : 2~38, S: -84~127 사이의 값


오라클의 char을 C 프로그램의 char로 치환하고, number을 in, long, short로 치환해서 사용할 수 있습니다. 그러므로 오라클 데이터베이스와 연결해서 프로그래밍을 함에 있어서 큰 제약이 없습니다.


VARCHAR 형의 경우에는 데이터 형의 특성상 C 프로그램의 char 데이터 형과는 다른 특이한 형태를 가지고 있습니다. Pro*C 프로그램에서 VARCHAR uid[20];로 선언하면 실제로는 아래와 같은 형태로 생성됩니다.


1
2
3
4
struct {
  unsigned short int len;
  unsigned char arr[20];
} uid;


오라클 데이터베이스에서 VARCHAR2 데이터 형의 선언은 가변 길이 문자열로, 데이터형 선언시 정의된 데이터 길이 내에서 다양한 길이의 데이터를 가질 수 있다는 것입니다. 좀더 쉽게 설명하자면 'VARCHAR2 CODE[40]'로 선언하고 '1'이라는 데이터를 할당하면 전체 40바이트의 길이 중 1바이트만 사용이 되고 나머지 39바이트는 빈 공간으로 남게되어 공간의 효율적 활용이 가능해지며 이러한 것을 가변 길이 문자열이라고 하는 것입니다. 


이와 같이 Pro*C의 VARCHAR 형도 오라클 데이터베이스의 VARCHAR2와 동일하게 가변 길이로 할당이 되어 사용된다는 것입니다. 다만 Pro*C만의 특징이 있다면, Pro*C에서 VARCHAR로 선언하는 것은, 내부적으로는 가변적 데이터 할당이 가능한 문자형 구조체로 선언하는 것과 같습니다.


구조체로 선언하지 않더라도 구조체의 특성을 가지므로 변수에 값을 할당하는 방법도 일반 char 변수와 다르게 이루어집니다. 뿐만 아니라 명시적으로 포인터로 선언하지 않더라도 VARCHAR 형은 데이터를 포인터로만 전달할 수 있기 때문에 데이터 할당과 출력에 있어 일반 데이터 형과 같은 형태가 아닌 포인터의 처리 프로세스를 따릅니다. 


char 형으로 선언하고 할당하려면 아래와 같이 진행하면 됩니다. 이 형식은 C 프로그램과 동일하며, 사용법에 있어서도 전혀 차이가 없음을 알 수 있습니다.


1
2
char uid[20];
strcpy(uid, "userid");


char 형과 달리 VARCHAR형의 경우에는 다음과 같이 선언하고 할당 합니다.

1
2
3
VARCHAR uid[20];
strcpy((char*)uid.arr, "userid");
uid.len = (short)strlen((char *)uid.arr);

VARCHAR 형은 선언과 동시에 len과 arr이라는 멤버를 갖는 구조체로 선언됩니다. 구조체이지기 때문에 앞서 확인한 char 형의 변수 데이터 할당 방법과 동일하게 사용할 수 ㅇ벗습니다.


구조체 변수에 대한 데이터 할당을 위해서는 구조체를 이루고 있는 각 멤버에 데이터를 할당해야 합니다. 물론 경우에 따라서는 구조체에 대한 할당만으로도 각 멤버에 대한 데이터 할당이 가능하기도 합니다. 이는 내부적으로 볼 때 자동적으로 각 멤버에 대한 할당이 이루어지는 것입니다. 대표적으로 Pro*C에서 데이터 추출 시 사용하는 FETCH 구문이 이에 해당됩니다.


VARCHAR 형도 구조체입니다. 그렇기 때문에 데이터를 할당하기 위해서는 구조체를 이루고 있는 각 멤버에 데이터를 할당해야만 합니다. 뿐만 아니라 데이터 전달이 포인터로만 가능하기 때문에 데이터 형에 대한 포인터로의 형 변환(Type Cast)도 필요합니다.


Pro*C의 VARCHAR형과 char 형은 사용 방법에서만 차이가 있는 것이 아닙니다. 저장 공간에 있어서도 차이가 있습니다. char 형은 Fixed Data Type으로 데이터 형의 길이만큼 저장 공간을 차지하고, VARCHAR 형은 데이터의 길이와 상관없이 할당받은 데이터 길이만큼의 저장 공간을 갖습니다. 사용의 편이성만 놓고 보자면 구조체로의 형변환도 안되고, 포인터로의 형번화도 필요없는 char형이 더 좋아보이지만 저장 공간, 즉 메모리 공간의 효율적 사용이라는 측면에서 본다면 VARCHAR 형은 char 형과 견주어 절대 뒤지지 않는 훌륭한 데이터형입니다.


이러한 장점이 작은 규모의 프로그래멩서는 큰 차이를 갖지 않지만, 사용자의 요청이 많은 프로그램이나 핸들링 해야 할 데이터가 많은 프로그램의 경우에는 성능 차이가 점점 크게 벌어지므로 각자 처한 상황에 맞게 충분히 고려한 후에 적절한 데이터 형을 사용해야 합니다.


Pro*C 프로그램에서 저장 공간과 처리 방법에 있어서 차이를 보이는 데이터 형은 char 형과 VARCHAR 형 두 개 밖에 없습니다. 다른 데이터 형은 C 프로그램에서 사용되는 일반 데이터 형과 동일합니다. 그러므로 두 데이터 형을 사용할 때는 주의하기 바랍니다.



+ Recent posts