데이터베이스와의 상호작용은 현대 소프트웨어 애플리케이션의 핵심 요소입니다. Oracle의 Pro*C는 C/C++와 SQL을 조합하여 관계형 데이터베이스의 데이터를 쉽게 처리할 수 있도록 돕는 강력한 도구입니다. 이 글에서는 Pro*C를 사용하여 DLL(동적 링크 라이브러리)을 생성하고, C#에서 P/Invoke를 통해 Pro*C로 작성된 함수를 호출하여 데이터 접근 계층을 구축하는 방법에 대해 자세히 설명하겠습니다.
1. Pro*C 소개
Pro*C는 C 또는 C++ 프로그램 내에서 SQL을 사용할 수 있도록 설계된 Oracle의 전처리기입니다. SQL 문장을 C 코드에 임베드하여 데이터베이스와 상호작용할 수 있도록 해 주며, SQL 명령의 결과를 쉽게 처리할 수 있는 수단을 제공합니다.
1.1 Pro*C의 특징
- 강력한 SQL 기능: Pro*C는 SQL 문을 직접 C 코드에 통합할 수 있어 데이터베이스와의 통신을 원활하게 만듭니다.
- 효율성: C 언어의 성능을 활용하여 데이터베이스 접근을 빠르게 수행할 수 있습니다.
- 이식성: Oracle 데이터베이스에 대한 통합 API를 제공합니다.
2. C#과 P/Invoke
C#은 .NET 프레임워크의 주요 언어로, 강력한 데이터 접근 기능을 제공하지만, 경우에 따라 네이티브 성능을 요구하기도 합니다. 이 때 P/Invoke(Platform Invocation Services)를 사용하여 C에서 작성된 DLL을 호출할 수 있습니다.
2.1 P/Invoke의 개념
P/Invoke는 C# 코드와 C/C++ DLL 간에 메서드를 호출할 수 있도록 해주는 기술입니다. 이를 통해 C에서는 제공하지 않는 기능이나 성능을 C# 애플리케이션에서 사용할 수 있습니다.
3. Pro*C로 DLL 생성하기
3.1 Pro*C 환경 설정
DLL을 생성하기 위해 Pro*C 환경을 설정해야 합니다. 이는 Oracle 데이터베이스와 연결하고 SQL 명령을 사용할 수 있는 C 환경을 마련하는 것을 포함합니다. Pro*C를 사용하기 위해 Oracle Client와 Pro*C의 설치가 필요합니다.
3.2 Pro*C 코드 작성
다음은 간단한 Pro*C 프로그램의 예입니다. 이 프로그램은 Oracle 데이터베이스에서 사용자의 정보를 조회하는 기능을 제공합니다.
#include <stdio.h>
#include <stdlib.h>
#include <sqlca.h>
exec sql begin declare section;
char username[50];
char useremail[100];
int userId;
exec sql end declare section;
void getUserInfo(int id) {
userId = id;
exec sql select name, email into :username, :useremail
from users where id = :userId;
printf("Name: %s\n", username);
printf("Email: %s\n", useremail);
}
3.3 컴파일 및 DLL 생성
위 코드를 DLL로 컴파일하기 위해, Pro*C 컴파일러와 C 컴파일러를 사용해야 합니다. Oracle SQL*Plus, Pro*C 컴파일러, 그리고 gcc 또는 Visual Studio를 사용할 수 있습니다. 먼저 Pro*C 소스 파일을 SQL 명령을 포함한 C 파일로 변환한 후, C 컴파일러를 사용해 DLL을 생성합니다.
proc in_code.pco
gcc -shared -o mylib.dll in_code.c -L"path/to/oracle/lib" -lclntsh
4. C#에서 DLL 호출하기
4.1 C# 프로그램 작성
이제 C#에서 우리가 생성한 DLL을 호출할 준비가 되었습니다. 아래는 P/Invoke를 사용하여 Pro*C로 작성된 DLL의 함수를 호출하는 예제입니다.
using System;
using System.Runtime.InteropServices;
class Program {
[DllImport("mylib.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void getUserInfo(int id);
static void Main() {
Console.WriteLine("Enter User ID:");
int userId = Convert.ToInt32(Console.ReadLine());
getUserInfo(userId);
}
}
4.2 컴파일 및 실행
C# 코드를 컴파일하기 위해, Visual Studio 또는 .NET CLI를 사용할 수 있습니다. 사용자가 입력한 ID를 전달받아, Pro*C DLL로부터 사용자의 정보를 가져올 수 있습니다.
dotnet build
dotnet run
5. 데이터 교환 방식
P/Invoke를 통해 C#과 Pro*C 간의 데이터 교환은 일반적으로 값 전달 방식을 사용합니다. Pro*C가 C에서 SQL 쿼리를 실행하고 반환된 결과는 C의 변수를 통해 이루어집니다. 이러한 방법은 프로세스 간의 데이터 전송을 단순화할 수 있음을 의미합니다.
5.1 값 전달 예시
위의 예에서 Pro*C에서 반환된 데이터는 C의 변수에 저장되어 있습니다. 이 값들은 C#에서 호출될 때 변수의 내용을 통해 C#으로 전달됩니다. 이렇게 함으로써, 두 환경 간의 데이터 형식이 호환되도록 신경 써야 합니다.
6. 정리
이 글에서는 Oracle의 Pro*C와 C#을 이용하여 데이터 접근 계층을 구축하는 방법을 다루었습니다. Pro*C를 사용한 DLL 생성 및 C# 애플리케이션에서의 P/Invoke 호출 예제를 통해, 두 기술의 강력한 결합이 가능한 점을 알 수 있었습니다. 데이터베이스와의 상호작용을 효율적으로 처리하기 위해, 이러한 접근 방식을 활용해 보시기를 권장합니다.